Files
goodbuddy/src/shared/agent-installation-contracts.test.ts
T
mesalogo de64e9768a
Cross-platform packages / Validate source (push) Canceled after 0s
Cross-platform packages / Authorize desktop packaging (push) Canceled after 0s
Cross-platform packages / linux arm64 (push) Canceled after 0s
Cross-platform packages / macos arm64 (push) Canceled after 0s
Cross-platform packages / windows arm64 (push) Canceled after 0s
Cross-platform packages / linux x64 (push) Canceled after 0s
Cross-platform packages / macos x64 (push) Canceled after 0s
Cross-platform packages / windows x64 (push) Canceled after 0s
Cross-platform packages / Publish GitHub and OSS release (push) Canceled after 0s
GoodBuddy Agents / Validate Agent source (push) Canceled after 0s
GoodBuddy Agents / Build Linux arm64 Agent (push) Canceled after 0s
GoodBuddy Agents / Build Linux x64 Agent (push) Canceled after 0s
fix: make Agent updates reliable and visible
Valid Agent packages could be rejected when packaged trusted-key JSON used CRLF, and Settings could not show whether a newer compatible Agent existed. Registry formatting is now parsed independently of cryptographic trust, and Settings reads only the signed catalog to report local and latest versions.

New installations use a credential-free local Ollama-compatible profile. The v20 migration changes only untouched historical defaults, while explicit profiles and legacy environment aliases remain compatible. Magic Notes count badges no longer shift navigation rows.

Release note: 修复 Agent 下载兼容性并在设置中显示更新状态;新安装默认连接本地模型,保留显式用户配置;魔法笔记待办数字不再改变侧栏菜单高度。
2026-08-26 15:43:41 +08:00

189 lines
4.3 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import {
agentBundleManifestSchema,
agentReleaseKeyRegistrySchema,
agentRuntimeLockSchema
} from './agent-installation-contracts'
const digest = 'a'.repeat(64)
function manifest() {
return {
formatVersion: 1,
product: 'GoodBuddy',
agentVersion: '0.11.0',
platform: 'linux',
arch: 'x64',
protocol: { major: 1, minor: 0 },
signingKeyId: 'test-key',
entrypoint: {
path: 'goodbuddy-agent',
runtimePath: 'node',
scriptPath: 'lib/agent.cjs'
},
files: [
{
path: 'goodbuddy-agent',
size: 1,
sha256: digest,
mode: '0755'
},
{
path: 'node',
size: 1,
sha256: digest,
mode: '0755'
},
{
path: 'lib/agent.cjs',
size: 1,
sha256: digest,
mode: '0644'
},
{
path: 'licenses/license.txt',
size: 1,
sha256: digest,
mode: '0644'
}
],
licenses: [
{
package: 'fixture',
version: '1.0.0',
spdx: 'MIT',
path: 'licenses/license.txt'
}
]
} as const
}
describe('Agent installation contracts', () => {
it('accepts a complete strict manifest', () => {
expect(agentBundleManifestSchema.parse(manifest())).toMatchObject({
arch: 'x64'
})
expect(() =>
agentBundleManifestSchema.parse({
...manifest(),
agentVersion: 'release_10'
})
).toThrow()
})
it('rejects unsafe, duplicate, undeclared, and incorrectly-modeled files', () => {
expect(() =>
agentBundleManifestSchema.parse({
...manifest(),
files: [
...manifest().files,
{
path: '../outside',
size: 1,
sha256: digest,
mode: '0644'
}
]
})
).toThrow()
expect(() =>
agentBundleManifestSchema.parse({
...manifest(),
files: [...manifest().files, manifest().files[0]]
})
).toThrow()
expect(() =>
agentBundleManifestSchema.parse({
...manifest(),
licenses: [
{
package: 'fixture',
version: '1.0.0',
spdx: 'MIT',
path: 'licenses/missing.txt'
}
]
})
).toThrow()
expect(() =>
agentBundleManifestSchema.parse({
...manifest(),
files: manifest().files.map((file) =>
file.path === 'goodbuddy-agent'
? { ...file, mode: '0644' }
: file
)
})
).toThrow()
})
it('rejects duplicate keys and extra registry fields', () => {
const key = {
keyId: 'test-key',
publicKeySpkiBase64: 'AAAA',
environment: 'test'
}
expect(() =>
agentReleaseKeyRegistrySchema.parse({
formatVersion: 1,
keys: [key, key],
revocations: [],
unknown: true
})
).toThrow()
})
it('rejects Base64 encodings with non-zero padding bits', () => {
expect(() =>
agentReleaseKeyRegistrySchema.parse({
formatVersion: 1,
keys: [{
keyId: 'test-key',
publicKeySpkiBase64: 'ZE==',
environment: 'test'
}],
revocations: []
})
).toThrow('canonical Base64')
})
it('requires both locked Linux targets and the fixed Node patch', () => {
const target = {
archive: 'node.tar.gz',
sha256: digest,
binaryPath: 'node/bin/node',
licensePath: 'node/LICENSE'
}
expect(
agentRuntimeLockSchema.parse({
formatVersion: 1,
agentVersion: '0.11.0',
protocol: { major: 1, minor: 0 },
node: {
version: '24.19.0',
source: 'https://nodejs.org/dist/v24.19.0/',
targets: {
'linux-x64': target,
'linux-arm64': target
}
},
koffi: { version: '3.1.4' }
}).koffi.version
).toBe('3.1.4')
expect(() =>
agentRuntimeLockSchema.parse({
formatVersion: 1,
agentVersion: '0.11.0',
protocol: { major: 1, minor: 0 },
node: {
version: '24.18.0',
source: 'http://nodejs.org/',
targets: { 'linux-x64': target }
},
koffi: { version: '3.1.3' }
})
).toThrow()
})
})