GoodBuddy Agents / Validate Agent source (push) Canceled after 0s
GoodBuddy Agents / Build darwin arm64 Agent (push) Canceled after 0s
GoodBuddy Agents / Build linux arm64 Agent (push) Canceled after 0s
GoodBuddy Agents / Build linux x64 Agent (push) Canceled after 0s
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
Account for concurrent composer, conversation-order, desktop-notification, and Supervisor discussion changes in bilingual notes and feature matrices. Correct the removed entity-writeback description in the companion article. Align the configuration fixture with the default-on notification setting, scope note-source UI queries and wait for completed actions, and preserve all real Obsidian child-process checks with a 15-second scenario allowance. Validation: frozen complete tree passed 5371 Linux tests with 51 skipped; 19 focused Windows tests, typecheck, lint, and release-note validation passed. The older 5345-test Host result did not cover all concurrent branch changes and is not treated as validation of this complete candidate.
257 lines
7.6 KiB
TypeScript
257 lines
7.6 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import {
|
|
goodbuddyConfigApplyInputSchema,
|
|
goodbuddyConfigCapabilities,
|
|
goodbuddyConfigCapabilitiesOutputSchema,
|
|
goodbuddyConfigCommonExamples,
|
|
goodbuddyConfigGetOutputSchema,
|
|
goodbuddyConfigOperationNameSchema,
|
|
goodbuddyConfigOperationSchema,
|
|
goodbuddyConfigPlanInputSchema,
|
|
goodbuddyConfigPlanOutputSchema
|
|
} from './goodbuddy-config-contracts'
|
|
import {
|
|
goodbuddyConfigToolByName,
|
|
goodbuddyConfigTools
|
|
} from './goodbuddy-config-tools'
|
|
import { defaultLocalToolEnvironmentSettings } from './local-tool-environment-contracts'
|
|
import { defaultApplicationNavigation } from './application-settings-contracts'
|
|
|
|
describe('GoodBuddy configuration contracts', () => {
|
|
it('uses the authoritative full application order for configuration-tool writes', () => {
|
|
const operation = {
|
|
operation: 'application.update',
|
|
updates: { applicationNavigation: {
|
|
...defaultApplicationNavigation,
|
|
order: ['local-inference', 'heartbeat', 'magic-notes', 'knowledge'],
|
|
} },
|
|
}
|
|
expect(goodbuddyConfigOperationSchema.parse(operation)).toEqual(operation)
|
|
for (const order of [['magic-notes', 'local-inference'], ['knowledge', 'heartbeat', 'magic-notes', 'magic-notes'], ['knowledge', 'heartbeat', 'magic-notes', 'invalid']]) {
|
|
expect(goodbuddyConfigOperationSchema.safeParse({ ...operation, updates: {
|
|
applicationNavigation: { ...defaultApplicationNavigation, order },
|
|
} }).success).toBe(false)
|
|
}
|
|
})
|
|
|
|
it('publishes one valid generated example for every operation', () => {
|
|
const operationNames = goodbuddyConfigOperationNameSchema.options
|
|
|
|
expect(goodbuddyConfigCommonExamples).toHaveLength(
|
|
operationNames.length
|
|
)
|
|
expect(
|
|
goodbuddyConfigCommonExamples.map(({ operation }) => operation)
|
|
).toEqual(operationNames)
|
|
for (const example of goodbuddyConfigCommonExamples) {
|
|
expect(goodbuddyConfigOperationSchema.parse(example)).toEqual(
|
|
example
|
|
)
|
|
}
|
|
expect(
|
|
goodbuddyConfigCapabilitiesOutputSchema.parse(
|
|
goodbuddyConfigCapabilities
|
|
)
|
|
).toEqual(goodbuddyConfigCapabilities)
|
|
})
|
|
|
|
it('accepts a bounded sequence of strongly typed operations', () => {
|
|
const input = {
|
|
operations: [
|
|
{
|
|
operation: 'application.update',
|
|
updates: {
|
|
magicNotesEnabled: true,
|
|
magicNoteCommentMode: 'after-save-manual',
|
|
magicNoteCanvasPageCount: 8
|
|
}
|
|
},
|
|
{
|
|
operation: 'skill.setAssignments',
|
|
skillId: 'document-writing',
|
|
assignments: ['model', 'continue']
|
|
},
|
|
{
|
|
operation: 'mcp.add',
|
|
connection: {
|
|
name: 'Project MCP',
|
|
description: '',
|
|
allowDynamicTools: false,
|
|
transport: 'http',
|
|
url: 'https://mcp.example.com/tools'
|
|
},
|
|
enabled: false,
|
|
assignments: ['model']
|
|
}
|
|
]
|
|
}
|
|
|
|
expect(goodbuddyConfigPlanInputSchema.parse(input)).toEqual(input)
|
|
})
|
|
|
|
it('keeps custom MCP assignments limited to the direct model', () => {
|
|
expect(() =>
|
|
goodbuddyConfigOperationSchema.parse({
|
|
operation: 'mcp.add',
|
|
connection: {
|
|
name: 'Project MCP',
|
|
description: '',
|
|
allowDynamicTools: false,
|
|
transport: 'http',
|
|
url: 'https://mcp.example.com/tools'
|
|
},
|
|
enabled: true,
|
|
assignments: ['continue']
|
|
})
|
|
).toThrow()
|
|
})
|
|
|
|
it('never accepts MCP secrets or credential-bearing remote URLs', () => {
|
|
const baseConnection = {
|
|
name: 'Project MCP',
|
|
description: '',
|
|
allowDynamicTools: false,
|
|
transport: 'http',
|
|
url: 'https://mcp.example.com/tools'
|
|
}
|
|
|
|
expect(() =>
|
|
goodbuddyConfigOperationSchema.parse({
|
|
operation: 'mcp.add',
|
|
connection: {
|
|
...baseConnection,
|
|
secret: { action: 'replace', value: 'do-not-accept' }
|
|
},
|
|
enabled: true,
|
|
assignments: ['model']
|
|
})
|
|
).toThrow()
|
|
expect(() =>
|
|
goodbuddyConfigOperationSchema.parse({
|
|
operation: 'mcp.update',
|
|
serverId: '00000000-0000-4000-8000-000000000001',
|
|
connection: {
|
|
...baseConnection,
|
|
url: 'https://user:password@mcp.example.com/tools'
|
|
}
|
|
})
|
|
).toThrow()
|
|
expect(() =>
|
|
goodbuddyConfigOperationSchema.parse({
|
|
operation: 'mcp.update',
|
|
serverId: '00000000-0000-4000-8000-000000000001',
|
|
connection: {
|
|
...baseConnection,
|
|
url: 'https://mcp.example.com/tools?token=secret'
|
|
}
|
|
})
|
|
).toThrow()
|
|
})
|
|
|
|
it('only exposes redacted MCP summaries from get', () => {
|
|
const snapshot = {
|
|
application: {
|
|
checkUpdatesOnStartup: true,
|
|
desktopNotificationsEnabled: true,
|
|
updateSource: 'github',
|
|
modelDownloadSource: 'modelscope',
|
|
localToolEnvironment: defaultLocalToolEnvironmentSettings,
|
|
applicationNavigation: defaultApplicationNavigation,
|
|
localInferenceEnabled: true,
|
|
conversationHtmlRenderingEnabled: true,
|
|
remoteProjectsEnabled: false,
|
|
magicNotesEnabled: true,
|
|
magicNotesShowIncompleteTodoCount: true,
|
|
magicNoteCommentMode: 'immediate',
|
|
magicNoteCommentFormat: 'combined',
|
|
magicNoteCanvasPageCount: 1
|
|
},
|
|
skills: [],
|
|
mcpServers: [
|
|
{
|
|
id: '00000000-0000-4000-8000-000000000001',
|
|
name: 'Project MCP',
|
|
description: '',
|
|
enabled: true,
|
|
allowDynamicTools: false,
|
|
assignments: ['model'],
|
|
secretConfigured: true,
|
|
transport: 'http'
|
|
}
|
|
]
|
|
}
|
|
|
|
expect(goodbuddyConfigGetOutputSchema.parse(snapshot)).toEqual(
|
|
snapshot
|
|
)
|
|
expect(() =>
|
|
goodbuddyConfigGetOutputSchema.parse({
|
|
...snapshot,
|
|
mcpServers: [
|
|
{
|
|
...snapshot.mcpServers[0],
|
|
url: 'https://mcp.example.com?token=secret',
|
|
secret: 'secret'
|
|
}
|
|
]
|
|
})
|
|
).toThrow()
|
|
})
|
|
|
|
it('requires an expiring, approved plan and applies only its ID', () => {
|
|
const operation = goodbuddyConfigCommonExamples[0]!
|
|
expect(
|
|
goodbuddyConfigPlanOutputSchema.parse({
|
|
planId: '00000000-0000-4000-8000-000000000002',
|
|
expiresAt: '2030-01-01T00:00:00.000Z',
|
|
operations: [operation],
|
|
steps: [
|
|
{
|
|
index: 0,
|
|
operation: operation.operation,
|
|
summary: 'Update startup checks.',
|
|
risk: 'low',
|
|
reload: 'none',
|
|
destructive: false
|
|
}
|
|
],
|
|
overallRisk: 'low',
|
|
reload: 'none',
|
|
requiresApproval: true
|
|
}).requiresApproval
|
|
).toBe(true)
|
|
expect(
|
|
goodbuddyConfigApplyInputSchema.parse({
|
|
planId: '00000000-0000-4000-8000-000000000002'
|
|
})
|
|
).toEqual({
|
|
planId: '00000000-0000-4000-8000-000000000002'
|
|
})
|
|
expect(() =>
|
|
goodbuddyConfigApplyInputSchema.parse({
|
|
planId: '00000000-0000-4000-8000-000000000002',
|
|
operations: [operation]
|
|
})
|
|
).toThrow()
|
|
})
|
|
|
|
it('catalogs the four request-scoped MCP tools', () => {
|
|
expect(goodbuddyConfigTools.map(({ name }) => name)).toEqual([
|
|
'goodbuddy_config_capabilities',
|
|
'goodbuddy_config_get',
|
|
'goodbuddy_config_plan',
|
|
'goodbuddy_config_apply'
|
|
])
|
|
expect(
|
|
goodbuddyConfigToolByName.get('goodbuddy_config_apply')?.access
|
|
).toBe(
|
|
'write'
|
|
)
|
|
expect(
|
|
goodbuddyConfigTools
|
|
.filter(({ name }) => name !== 'goodbuddy_config_apply')
|
|
.every(({ access }) => access === 'read')
|
|
).toBe(true)
|
|
})
|
|
})
|