mirror of
https://github.com/Ryder-Sun/Meldwork.git
synced 2026-11-07 06:56:03 -10:00
local-workspace-agent-invocation.cjs held four independent pieces of logic inside one 1500-line method. They now live in small modules with their own tests, and the invocation only wires them together: - collaboration/collaboration-receipt.cjs: parse and normalise the receipt (unchanged behaviour; the existing receipt tests now import it directly) - runs/invocation-watchdog.cjs: startup, inactivity and stall windows - collaboration/answer-marker-filter.cjs: hides control markers while the answer streams - agents/agent-permission-policy.cjs: automatic answers to permission requests, read-only turns only approve side-effect-free tools Two latent defects fixed on the way: - the watchdog cleared its timer on the first event without re-arming it, so an Agent that went silent right after its first event was never stopped - the marker filter upper-cased the buffer to find markers, which shifts the cut position for characters whose upper-case form is longer (e.g. ss) Checked with: node --test on the new module tests; npm --prefix desktop run test:workspace (595 pass).
56 lines
2.0 KiB
JavaScript
56 lines
2.0 KiB
JavaScript
const test = require('node:test')
|
|
const assert = require('node:assert/strict')
|
|
const { automaticPermissionResponse } = require('../../src/agents/agent-permission-policy.cjs')
|
|
|
|
const options = [
|
|
{ optionId: 'allow-always', kind: 'allow_always', name: 'Always' },
|
|
{ optionId: 'allow', kind: 'allow_once', name: 'Allow' },
|
|
{ optionId: 'reject', kind: 'reject_once', name: 'Reject' },
|
|
]
|
|
|
|
test('read-only turns approve only tools without side effects', () => {
|
|
for (const kind of ['read', 'search', 'fetch', 'think']) {
|
|
assert.deepEqual(
|
|
automaticPermissionResponse({ toolCall: { kind }, options }, { allowWrite: false }),
|
|
{ status: 'approved', optionId: 'allow' },
|
|
kind,
|
|
)
|
|
}
|
|
for (const kind of ['edit', 'delete', 'move', 'execute', 'switch_mode', 'other', undefined]) {
|
|
assert.deepEqual(
|
|
automaticPermissionResponse({ toolCall: { kind }, options }, { allowWrite: false }),
|
|
{ status: 'rejected', optionId: 'reject' },
|
|
String(kind),
|
|
)
|
|
}
|
|
})
|
|
|
|
test('a refused request without a reject option is answered with null instead of the user gate', () => {
|
|
assert.equal(automaticPermissionResponse({
|
|
toolCall: { kind: 'execute' },
|
|
options: [{ optionId: 'allow', kind: 'allow_once' }],
|
|
}, { allowWrite: false }), null)
|
|
})
|
|
|
|
test('writable turns approve everything the Agent offers, preferring a one-time allow', () => {
|
|
assert.deepEqual(
|
|
automaticPermissionResponse({ toolCall: { kind: 'execute' }, options }, { allowWrite: true }),
|
|
{ status: 'approved', optionId: 'allow' },
|
|
)
|
|
assert.deepEqual(
|
|
automaticPermissionResponse({
|
|
toolCall: { kind: 'edit' },
|
|
options: [{ optionId: 'only', kind: 'something_else' }],
|
|
}, { allowWrite: true }),
|
|
{ status: 'approved', optionId: 'only' },
|
|
)
|
|
})
|
|
|
|
test('with nothing to choose the caller must ask the user', () => {
|
|
assert.equal(
|
|
automaticPermissionResponse({ toolCall: { kind: 'read' }, options: [] }, { allowWrite: false }),
|
|
undefined,
|
|
)
|
|
assert.equal(automaticPermissionResponse(null, { allowWrite: true }), undefined)
|
|
})
|