@animalabs/agent-framework 0.19.0 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -0
- package/dist/src/agent.d.ts +22 -0
- package/dist/src/agent.d.ts.map +1 -1
- package/dist/src/agent.js +128 -10
- package/dist/src/agent.js.map +1 -1
- package/dist/src/api/types.d.ts +1 -1
- package/dist/src/api/types.d.ts.map +1 -1
- package/dist/src/code-execution/py-runner.d.ts +10 -1
- package/dist/src/code-execution/py-runner.d.ts.map +1 -1
- package/dist/src/code-execution/py-runner.js +27 -2
- package/dist/src/code-execution/py-runner.js.map +1 -1
- package/dist/src/code-execution/tool-definition.d.ts +21 -0
- package/dist/src/code-execution/tool-definition.d.ts.map +1 -1
- package/dist/src/code-execution/tool-definition.js +34 -0
- package/dist/src/code-execution/tool-definition.js.map +1 -1
- package/dist/src/framework.d.ts +153 -2
- package/dist/src/framework.d.ts.map +1 -1
- package/dist/src/framework.js +1169 -76
- package/dist/src/framework.js.map +1 -1
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +4 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcpl/capability-grant.d.ts +1 -1
- package/dist/src/mcpl/capability-grant.d.ts.map +1 -1
- package/dist/src/mcpl/capability-grant.js +49 -5
- package/dist/src/mcpl/capability-grant.js.map +1 -1
- package/dist/src/mcpl/channel-registry.d.ts +59 -2
- package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
- package/dist/src/mcpl/channel-registry.js +106 -6
- package/dist/src/mcpl/channel-registry.js.map +1 -1
- package/dist/src/mcpl/index.d.ts +3 -0
- package/dist/src/mcpl/index.d.ts.map +1 -1
- package/dist/src/mcpl/index.js +3 -0
- package/dist/src/mcpl/index.js.map +1 -1
- package/dist/src/mcpl/push-coalescer.d.ts +318 -0
- package/dist/src/mcpl/push-coalescer.d.ts.map +1 -0
- package/dist/src/mcpl/push-coalescer.js +709 -0
- package/dist/src/mcpl/push-coalescer.js.map +1 -0
- package/dist/src/mcpl/push-handler.d.ts +7 -2
- package/dist/src/mcpl/push-handler.d.ts.map +1 -1
- package/dist/src/mcpl/push-handler.js +43 -4
- package/dist/src/mcpl/push-handler.js.map +1 -1
- package/dist/src/mcpl/server-connection.d.ts +18 -0
- package/dist/src/mcpl/server-connection.d.ts.map +1 -1
- package/dist/src/mcpl/server-connection.js +44 -1
- package/dist/src/mcpl/server-connection.js.map +1 -1
- package/dist/src/mcpl/tool-classes.d.ts +71 -0
- package/dist/src/mcpl/tool-classes.d.ts.map +1 -0
- package/dist/src/mcpl/tool-classes.js +170 -0
- package/dist/src/mcpl/tool-classes.js.map +1 -0
- package/dist/src/mcpl/tool-glob.d.ts +16 -0
- package/dist/src/mcpl/tool-glob.d.ts.map +1 -0
- package/dist/src/mcpl/tool-glob.js +41 -0
- package/dist/src/mcpl/tool-glob.js.map +1 -0
- package/dist/src/mcpl/tool-lifecycle.d.ts +253 -0
- package/dist/src/mcpl/tool-lifecycle.d.ts.map +1 -0
- package/dist/src/mcpl/tool-lifecycle.js +592 -0
- package/dist/src/mcpl/tool-lifecycle.js.map +1 -0
- package/dist/src/mcpl/transport.d.ts +12 -0
- package/dist/src/mcpl/transport.d.ts.map +1 -1
- package/dist/src/mcpl/transport.js +33 -1
- package/dist/src/mcpl/transport.js.map +1 -1
- package/dist/src/mcpl/types.d.ts +66 -1
- package/dist/src/mcpl/types.d.ts.map +1 -1
- package/dist/src/mcpl/types.js +6 -0
- package/dist/src/mcpl/types.js.map +1 -1
- package/dist/src/modules/discord/index.js +1 -1
- package/dist/src/modules/discord/index.js.map +1 -1
- package/dist/src/modules/history/index.d.ts +85 -0
- package/dist/src/modules/history/index.d.ts.map +1 -1
- package/dist/src/modules/history/index.js +1019 -24
- package/dist/src/modules/history/index.js.map +1 -1
- package/dist/src/modules/history/semantic.d.ts +202 -0
- package/dist/src/modules/history/semantic.d.ts.map +1 -0
- package/dist/src/modules/history/semantic.js +418 -0
- package/dist/src/modules/history/semantic.js.map +1 -0
- package/dist/src/modules/index.d.ts +2 -1
- package/dist/src/modules/index.d.ts.map +1 -1
- package/dist/src/modules/index.js.map +1 -1
- package/dist/src/tool-result-guard.d.ts +82 -0
- package/dist/src/tool-result-guard.d.ts.map +1 -0
- package/dist/src/tool-result-guard.js +306 -0
- package/dist/src/tool-result-guard.js.map +1 -0
- package/dist/src/types/agent.d.ts +14 -0
- package/dist/src/types/agent.d.ts.map +1 -1
- package/dist/src/types/framework.d.ts +21 -0
- package/dist/src/types/framework.d.ts.map +1 -1
- package/dist/src/types/trace.d.ts +17 -0
- package/dist/src/types/trace.d.ts.map +1 -1
- package/dist/test/channel-registry-routing.test.js +59 -0
- package/dist/test/channel-registry-routing.test.js.map +1 -1
- package/dist/test/code-execution.test.js +139 -0
- package/dist/test/code-execution.test.js.map +1 -1
- package/dist/test/helpers/coalescing-fixture.d.ts +72 -0
- package/dist/test/helpers/coalescing-fixture.d.ts.map +1 -0
- package/dist/test/helpers/coalescing-fixture.js +145 -0
- package/dist/test/helpers/coalescing-fixture.js.map +1 -0
- package/dist/test/helpers/coalescing-kill-child.d.ts +2 -0
- package/dist/test/helpers/coalescing-kill-child.d.ts.map +1 -0
- package/dist/test/helpers/coalescing-kill-child.js +24 -0
- package/dist/test/helpers/coalescing-kill-child.js.map +1 -0
- package/dist/test/history-module-realstore.test.d.ts +2 -0
- package/dist/test/history-module-realstore.test.d.ts.map +1 -0
- package/dist/test/history-module-realstore.test.js +363 -0
- package/dist/test/history-module-realstore.test.js.map +1 -0
- package/dist/test/history-module-semantic.test.d.ts +2 -0
- package/dist/test/history-module-semantic.test.d.ts.map +1 -0
- package/dist/test/history-module-semantic.test.js +213 -0
- package/dist/test/history-module-semantic.test.js.map +1 -0
- package/dist/test/history-module-ux.test.d.ts +2 -0
- package/dist/test/history-module-ux.test.d.ts.map +1 -0
- package/dist/test/history-module-ux.test.js +304 -0
- package/dist/test/history-module-ux.test.js.map +1 -0
- package/dist/test/history-module.test.js +25 -1
- package/dist/test/history-module.test.js.map +1 -1
- package/dist/test/history-semantic-review-findings.test.d.ts +2 -0
- package/dist/test/history-semantic-review-findings.test.d.ts.map +1 -0
- package/dist/test/history-semantic-review-findings.test.js +338 -0
- package/dist/test/history-semantic-review-findings.test.js.map +1 -0
- package/dist/test/history-semantic-sync-converges.test.d.ts +2 -0
- package/dist/test/history-semantic-sync-converges.test.d.ts.map +1 -0
- package/dist/test/history-semantic-sync-converges.test.js +109 -0
- package/dist/test/history-semantic-sync-converges.test.js.map +1 -0
- package/dist/test/mcpl-capability-grant.test.js +3 -1
- package/dist/test/mcpl-capability-grant.test.js.map +1 -1
- package/dist/test/mcpl-child-env.test.d.ts +2 -0
- package/dist/test/mcpl-child-env.test.d.ts.map +1 -0
- package/dist/test/mcpl-child-env.test.js +69 -0
- package/dist/test/mcpl-child-env.test.js.map +1 -0
- package/dist/test/mcpl-coalescing.test.d.ts +2 -0
- package/dist/test/mcpl-coalescing.test.d.ts.map +1 -0
- package/dist/test/mcpl-coalescing.test.js +1050 -0
- package/dist/test/mcpl-coalescing.test.js.map +1 -0
- package/dist/test/mcpl-list-status.test.js +4 -0
- package/dist/test/mcpl-list-status.test.js.map +1 -1
- package/dist/test/mcpl-tool-class-listing.test.d.ts +2 -0
- package/dist/test/mcpl-tool-class-listing.test.d.ts.map +1 -0
- package/dist/test/mcpl-tool-class-listing.test.js +147 -0
- package/dist/test/mcpl-tool-class-listing.test.js.map +1 -0
- package/dist/test/mcpl-tool-classes.test.d.ts +7 -0
- package/dist/test/mcpl-tool-classes.test.d.ts.map +1 -0
- package/dist/test/mcpl-tool-classes.test.js +80 -0
- package/dist/test/mcpl-tool-classes.test.js.map +1 -0
- package/dist/test/mcpl-tool-lifecycle-e2e.test.d.ts +2 -0
- package/dist/test/mcpl-tool-lifecycle-e2e.test.d.ts.map +1 -0
- package/dist/test/mcpl-tool-lifecycle-e2e.test.js +237 -0
- package/dist/test/mcpl-tool-lifecycle-e2e.test.js.map +1 -0
- package/dist/test/mcpl-tool-lifecycle-emitter.test.d.ts +11 -0
- package/dist/test/mcpl-tool-lifecycle-emitter.test.d.ts.map +1 -0
- package/dist/test/mcpl-tool-lifecycle-emitter.test.js +307 -0
- package/dist/test/mcpl-tool-lifecycle-emitter.test.js.map +1 -0
- package/dist/test/mcpl-tool-lifecycle.test.d.ts +11 -0
- package/dist/test/mcpl-tool-lifecycle.test.d.ts.map +1 -0
- package/dist/test/mcpl-tool-lifecycle.test.js +270 -0
- package/dist/test/mcpl-tool-lifecycle.test.js.map +1 -0
- package/dist/test/silent-heartbeat.test.d.ts +2 -0
- package/dist/test/silent-heartbeat.test.d.ts.map +1 -0
- package/dist/test/silent-heartbeat.test.js +154 -0
- package/dist/test/silent-heartbeat.test.js.map +1 -0
- package/dist/test/tool-result-guard.test.d.ts +2 -0
- package/dist/test/tool-result-guard.test.d.ts.map +1 -0
- package/dist/test/tool-result-guard.test.js +1081 -0
- package/dist/test/tool-result-guard.test.js.map +1 -0
- package/dist/test/trunk-channel-routing.test.js +67 -0
- package/dist/test/trunk-channel-routing.test.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/agent.ts +128 -10
- package/src/api/types.ts +2 -0
- package/src/code-execution/py-runner.ts +34 -2
- package/src/code-execution/tool-definition.ts +46 -0
- package/src/framework.ts +1201 -80
- package/src/index.ts +13 -0
- package/src/mcpl/capability-grant.ts +54 -6
- package/src/mcpl/channel-registry.ts +115 -7
- package/src/mcpl/index.ts +29 -0
- package/src/mcpl/push-coalescer.ts +821 -0
- package/src/mcpl/push-handler.ts +40 -4
- package/src/mcpl/server-connection.ts +48 -2
- package/src/mcpl/tool-classes.ts +188 -0
- package/src/mcpl/tool-glob.ts +36 -0
- package/src/mcpl/tool-lifecycle.ts +730 -0
- package/src/mcpl/transport.ts +35 -1
- package/src/mcpl/types.ts +69 -1
- package/src/modules/discord/index.ts +1 -1
- package/src/modules/history/index.ts +1089 -24
- package/src/modules/history/semantic.ts +473 -0
- package/src/modules/index.ts +2 -1
- package/src/tool-result-guard.ts +318 -0
- package/src/types/agent.ts +15 -0
- package/src/types/framework.ts +23 -0
- package/src/types/trace.ts +17 -0
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RFC-007 end to end: a real framework, two real MCPL servers over stdio, a
|
|
3
|
+
* scripted model turn.
|
|
4
|
+
*
|
|
5
|
+
* provider — offers `click` (classed `computer`) and `run` (unclassed,
|
|
6
|
+
* returns an error result)
|
|
7
|
+
* observer — granted toolLifecycle.observe + inputs (narrowed by tool
|
|
8
|
+
* name to prov--*), sends a tools/observe filter asking for click
|
|
9
|
+
* coordinates and every other call's full arguments
|
|
10
|
+
*
|
|
11
|
+
* The agent calls prov--click, prov--run and the observer's own obs--ping in
|
|
12
|
+
* one round. The observer must see: click with ONLY the requested fields;
|
|
13
|
+
* run with its class empty and its arguments withheld (unclassed tools never
|
|
14
|
+
* carry arguments); run's terminal as completed+isError; nothing at all for
|
|
15
|
+
* its own tool; and no tool result anywhere.
|
|
16
|
+
*/
|
|
17
|
+
import { describe, it, before, after } from 'node:test';
|
|
18
|
+
import assert from 'node:assert/strict';
|
|
19
|
+
import { tmpdir } from 'node:os';
|
|
20
|
+
import { mkdtempSync, rmSync, readFileSync, existsSync, writeFileSync } from 'node:fs';
|
|
21
|
+
import { join } from 'node:path';
|
|
22
|
+
import { AgentFramework } from '../src/index.js';
|
|
23
|
+
import { MockMembrane, createMockResponse } from './helpers/mock-membrane.js';
|
|
24
|
+
const FIXTURE = join(import.meta.dirname, 'fixtures/tool-lifecycle-mcpl-server.mjs');
|
|
25
|
+
class Trigger {
|
|
26
|
+
name = 'trigger';
|
|
27
|
+
async start(_ctx) { }
|
|
28
|
+
async stop() { }
|
|
29
|
+
getTools() { return []; }
|
|
30
|
+
async handleToolCall() { return { success: false, error: 'no tools', isError: true }; }
|
|
31
|
+
async onProcess(event, _state) {
|
|
32
|
+
if (event.type === 'external-message') {
|
|
33
|
+
// Wake the named agents when the event names them (broadcast skips
|
|
34
|
+
// conversation forks), everyone otherwise.
|
|
35
|
+
const targets = event.targetAgents;
|
|
36
|
+
return {
|
|
37
|
+
addMessages: [{ participant: 'User', content: [{ type: 'text', text: 'go' }] }],
|
|
38
|
+
requestInference: targets ?? true,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
return {};
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async function waitFor(cond, what, timeoutMs = 15_000) {
|
|
45
|
+
const deadline = Date.now() + timeoutMs;
|
|
46
|
+
while (Date.now() < deadline) {
|
|
47
|
+
if (cond())
|
|
48
|
+
return;
|
|
49
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
50
|
+
}
|
|
51
|
+
throw new Error(`timed out waiting for: ${what}`);
|
|
52
|
+
}
|
|
53
|
+
const readLog = (path) => existsSync(path) ? readFileSync(path, 'utf8').split('\n').filter(Boolean).map((l) => JSON.parse(l)) : [];
|
|
54
|
+
describe('tool lifecycle end to end (RFC-007)', () => {
|
|
55
|
+
let tempDir;
|
|
56
|
+
let obsLog;
|
|
57
|
+
let provLog;
|
|
58
|
+
let diePath;
|
|
59
|
+
let membrane;
|
|
60
|
+
let framework;
|
|
61
|
+
before(async () => {
|
|
62
|
+
tempDir = mkdtempSync(join(tmpdir(), 'tool-lifecycle-e2e-'));
|
|
63
|
+
obsLog = join(tempDir, 'observer.jsonl');
|
|
64
|
+
provLog = join(tempDir, 'provider.jsonl');
|
|
65
|
+
diePath = join(tempDir, 'provider.die');
|
|
66
|
+
membrane = new MockMembrane();
|
|
67
|
+
framework = await AgentFramework.create({
|
|
68
|
+
storePath: join(tempDir, 'test.chronicle'),
|
|
69
|
+
membrane: membrane.asMembrane(),
|
|
70
|
+
agents: [{ name: 'scout', model: 'test-model', systemPrompt: 'You are scout.' }],
|
|
71
|
+
modules: [new Trigger()],
|
|
72
|
+
mcplServers: [
|
|
73
|
+
{
|
|
74
|
+
id: 'prov',
|
|
75
|
+
toolPrefix: 'prov',
|
|
76
|
+
command: process.execPath,
|
|
77
|
+
args: [FIXTURE],
|
|
78
|
+
env: { ROLE: 'provider', LOG_PATH: provLog, DIE_PATH: diePath },
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
id: 'obs',
|
|
82
|
+
toolPrefix: 'obs',
|
|
83
|
+
command: process.execPath,
|
|
84
|
+
args: [FIXTURE],
|
|
85
|
+
env: {
|
|
86
|
+
ROLE: 'observer',
|
|
87
|
+
LOG_PATH: obsLog,
|
|
88
|
+
FILTER: JSON.stringify([
|
|
89
|
+
{ match: { serverTool: 'click' }, input: ['x', 'y', 'target.window_id'] },
|
|
90
|
+
{ match: {}, input: true },
|
|
91
|
+
]),
|
|
92
|
+
},
|
|
93
|
+
// Narrowed by NAME, which admits prov--run: only the class
|
|
94
|
+
// exclusion (unclassed never carries arguments) can withhold it.
|
|
95
|
+
toolLifecycle: { observe: {}, inputs: { tools: ['prov--*'] } },
|
|
96
|
+
},
|
|
97
|
+
],
|
|
98
|
+
});
|
|
99
|
+
await framework.start();
|
|
100
|
+
await waitFor(() => readLog(obsLog).some((e) => e.event === 'observe-applied'), 'observer filter applied');
|
|
101
|
+
await waitFor(() => ['prov--click', 'prov--run', 'obs--ping'].every((n) => framework.getAllTools().some((t) => t.name === n)), 'MCPL tools listed');
|
|
102
|
+
});
|
|
103
|
+
after(async () => {
|
|
104
|
+
await framework?.stop();
|
|
105
|
+
if (tempDir)
|
|
106
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
107
|
+
});
|
|
108
|
+
it('lists every tool with its effective class, source, and server (RFC-008 §6)', () => {
|
|
109
|
+
const byTool = new Map(framework.listToolClasses().map((e) => [e.tool, e]));
|
|
110
|
+
assert.deepEqual(byTool.get('prov--click'), { tool: 'prov--click', class: ['computer'], source: 'server', serverId: 'prov' });
|
|
111
|
+
assert.deepEqual(byTool.get('prov--run'), { tool: 'prov--run', class: [], source: 'none', serverId: 'prov' });
|
|
112
|
+
assert.deepEqual(byTool.get('obs--ping'), { tool: 'obs--ping', class: ['body'], source: 'server', serverId: 'obs' });
|
|
113
|
+
const prov = framework.listMcplServers().find((s) => s.id === 'prov');
|
|
114
|
+
assert.deepEqual(prov.toolClasses.map((t) => `${t.serverTool}:${t.class.join('+') || '-'}:${t.source}`), [
|
|
115
|
+
'click:computer:server', 'run:-:none',
|
|
116
|
+
]);
|
|
117
|
+
});
|
|
118
|
+
it('reports other servers\' calls with requested fields only, never results', async () => {
|
|
119
|
+
const policy = readLog(obsLog).find((e) => e.event === 'policy');
|
|
120
|
+
assert.ok((policy?.effectiveCapabilities).includes('toolLifecycle.inputs'), 'the policy block granted both paths');
|
|
121
|
+
membrane.pushResponse(createMockResponse([
|
|
122
|
+
{ type: 'text', text: 'Acting.' },
|
|
123
|
+
{
|
|
124
|
+
type: 'tool_use', id: 'toolu_01AAAAAAAAAAAAAAAAAAAAAA', name: 'prov--click',
|
|
125
|
+
input: { x: 812, y: 440, button: 'left', target: { window_id: 3312, title: 'Invoice.pdf' } },
|
|
126
|
+
},
|
|
127
|
+
{ type: 'tool_use', id: 'toolu_01BBBBBBBBBBBBBBBBBBBBBB', name: 'prov--run', input: { cmd: 'make secret-arg' } },
|
|
128
|
+
{ type: 'tool_use', id: 'toolu_01CCCCCCCCCCCCCCCCCCCCCC', name: 'obs--ping', input: {} },
|
|
129
|
+
], 'tool_use'));
|
|
130
|
+
membrane.pushResponse(createMockResponse([{ type: 'text', text: 'Done.' }]));
|
|
131
|
+
framework.pushEvent({
|
|
132
|
+
type: 'external-message',
|
|
133
|
+
source: 'test',
|
|
134
|
+
content: [{ type: 'text', text: 'go' }],
|
|
135
|
+
metadata: {},
|
|
136
|
+
triggerInference: true,
|
|
137
|
+
});
|
|
138
|
+
const lifecycle = () => readLog(obsLog).filter((e) => e.event === 'lifecycle').map((e) => e.params);
|
|
139
|
+
await waitFor(() => lifecycle().length >= 4, 'two calls, both phases');
|
|
140
|
+
// Let the turn finish, so a stray or duplicate notification would land
|
|
141
|
+
// before the counts below are taken.
|
|
142
|
+
await waitFor(() => membrane.lastStream?.receivedToolResults.length === 1, 'tool results returned to the model');
|
|
143
|
+
await new Promise((r) => setTimeout(r, 300));
|
|
144
|
+
const events = lifecycle();
|
|
145
|
+
const byTool = (tool, phase) => events.filter((p) => p.tool === tool && p.phase === phase);
|
|
146
|
+
// Own tool: the observer saw its own call as tools/call, never as lifecycle.
|
|
147
|
+
assert.ok(readLog(obsLog).some((e) => e.event === 'tools-call' && e.name === 'ping'));
|
|
148
|
+
assert.equal(events.filter((p) => p.tool === 'obs--ping').length, 0, 'own tools are excluded');
|
|
149
|
+
// click: classed computer → the requested fields and nothing else.
|
|
150
|
+
const [clickStart] = byTool('prov--click', 'started');
|
|
151
|
+
assert.deepEqual(clickStart.class, ['computer']);
|
|
152
|
+
assert.equal(clickStart.serverId, 'prov');
|
|
153
|
+
assert.equal(clickStart.serverTool, 'click');
|
|
154
|
+
assert.equal(clickStart.conversationId, 'scout');
|
|
155
|
+
assert.deepEqual(clickStart.input, { x: 812, y: 440, target: { window_id: 3312 } });
|
|
156
|
+
const [clickEnd] = byTool('prov--click', 'completed');
|
|
157
|
+
assert.equal(clickEnd.toolCallId, clickStart.toolCallId);
|
|
158
|
+
assert.equal(clickEnd.inferenceId, clickStart.inferenceId);
|
|
159
|
+
assert.equal(clickEnd.isError, false);
|
|
160
|
+
assert.equal(typeof clickEnd.durationMs, 'number');
|
|
161
|
+
// run: unclassed → arguments withheld though the rule asked; error RESULT
|
|
162
|
+
// is a completed call with isError, not a failure.
|
|
163
|
+
const [runStart] = byTool('prov--run', 'started');
|
|
164
|
+
assert.deepEqual(runStart.class, []);
|
|
165
|
+
assert.equal(runStart.input, undefined);
|
|
166
|
+
assert.equal(runStart.inputWithheld, true);
|
|
167
|
+
const [runEnd] = byTool('prov--run', 'completed');
|
|
168
|
+
assert.equal(runEnd.isError, true);
|
|
169
|
+
// Exactly one opening and one terminal per call.
|
|
170
|
+
assert.equal(events.length, 4);
|
|
171
|
+
const wire = JSON.stringify(events);
|
|
172
|
+
for (const secret of ['RESULT-MARKER', 'secret-arg', 'Invoice.pdf', 'left']) {
|
|
173
|
+
assert.ok(!wire.includes(secret), `"${secret}" must not reach the observer`);
|
|
174
|
+
}
|
|
175
|
+
// The provider, which holds no toolLifecycle grant, received nothing.
|
|
176
|
+
assert.equal(readLog(provLog).filter((e) => e.event === 'lifecycle').length, 0);
|
|
177
|
+
});
|
|
178
|
+
it('a provider that dies takes its classes with it, and calls to it are never reported (review #3, #4)', async () => {
|
|
179
|
+
const internals = framework;
|
|
180
|
+
assert.deepEqual(internals.describeToolForLifecycle('prov--click').class, ['computer'], 'classed while alive');
|
|
181
|
+
writeFileSync(diePath, '');
|
|
182
|
+
await waitFor(() => internals.mcplServerRegistry?.getServer('prov') == null, 'provider removed from the registry');
|
|
183
|
+
// #3: the stale declaration is gone — unclassed (restrictive) until re-listed.
|
|
184
|
+
assert.deepEqual(internals.describeToolForLifecycle('prov--click').class, []);
|
|
185
|
+
const before = readLog(obsLog).filter((e) => e.event === 'lifecycle').length;
|
|
186
|
+
membrane.pushResponse(createMockResponse([
|
|
187
|
+
{ type: 'tool_use', id: 'toolu_01DDDDDDDDDDDDDDDDDDDDDD', name: 'prov--click', input: { x: 1, y: 2 } },
|
|
188
|
+
], 'tool_use'));
|
|
189
|
+
membrane.pushResponse(createMockResponse([{ type: 'text', text: 'It is gone.' }]));
|
|
190
|
+
framework.pushEvent({
|
|
191
|
+
type: 'external-message',
|
|
192
|
+
source: 'test',
|
|
193
|
+
content: [{ type: 'text', text: 'again' }],
|
|
194
|
+
metadata: {},
|
|
195
|
+
triggerInference: true,
|
|
196
|
+
});
|
|
197
|
+
await waitFor(() => (membrane.lastStream?.receivedToolResults.length ?? 0) >= 1
|
|
198
|
+
&& membrane.lastStream !== null && membrane.calls.length >= 2, 'the refused call answered');
|
|
199
|
+
await new Promise((r) => setTimeout(r, 300));
|
|
200
|
+
const after = readLog(obsLog).filter((e) => e.event === 'lifecycle').length;
|
|
201
|
+
assert.equal(after, before, 'a call the host refused (provider gone) produces no events');
|
|
202
|
+
});
|
|
203
|
+
it('a host-tool refusal (conversation-bound channel guard) is never reported (re-review #1)', async () => {
|
|
204
|
+
const internals = framework;
|
|
205
|
+
// Make scout a conversation fork bound to one channel: the guard in
|
|
206
|
+
// dispatchChannelToolCall refuses channel_open before it runs.
|
|
207
|
+
internals.conversationAgentHomes.set('scout', 'disc:guild:home');
|
|
208
|
+
try {
|
|
209
|
+
const before = readLog(obsLog).filter((e) => e.event === 'lifecycle').length;
|
|
210
|
+
const callsBefore = membrane.calls.length;
|
|
211
|
+
membrane.pushResponse(createMockResponse([
|
|
212
|
+
{ type: 'tool_use', id: 'toolu_01EEEEEEEEEEEEEEEEEEEEEE', name: 'channel_open', input: { channelId: 'disc:guild:other' } },
|
|
213
|
+
], 'tool_use'));
|
|
214
|
+
membrane.pushResponse(createMockResponse([{ type: 'text', text: 'Refused.' }]));
|
|
215
|
+
framework.pushEvent({
|
|
216
|
+
type: 'external-message',
|
|
217
|
+
source: 'test',
|
|
218
|
+
content: [{ type: 'text', text: 'open another channel' }],
|
|
219
|
+
metadata: {},
|
|
220
|
+
triggerInference: true,
|
|
221
|
+
// Broadcast wakes skip conversation forks; address scout directly.
|
|
222
|
+
targetAgents: ['scout'],
|
|
223
|
+
});
|
|
224
|
+
await waitFor(() => membrane.calls.length > callsBefore
|
|
225
|
+
&& (membrane.lastStream?.receivedToolResults.length ?? 0) >= 1, 'the refused call answered');
|
|
226
|
+
const answer = JSON.stringify(membrane.lastStream.receivedToolResults[0]);
|
|
227
|
+
assert.match(answer, /cannot open channels/, 'the guard did refuse it');
|
|
228
|
+
await new Promise((r) => setTimeout(r, 300));
|
|
229
|
+
const after = readLog(obsLog).filter((e) => e.event === 'lifecycle').length;
|
|
230
|
+
assert.equal(after, before, 'a refused host-tool call produces no events');
|
|
231
|
+
}
|
|
232
|
+
finally {
|
|
233
|
+
internals.conversationAgentHomes.delete('scout');
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
//# sourceMappingURL=mcpl-tool-lifecycle-e2e.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcpl-tool-lifecycle-e2e.test.js","sourceRoot":"","sources":["../../test/mcpl-tool-lifecycle-e2e.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCPL RFC-007 tool lifecycle — the emitter's pairing (started at dispatch →
|
|
3
|
+
* exactly one terminal, to exactly the connection epochs the opening went
|
|
4
|
+
* to, unless their grant no longer covers the call), host-unique call ids,
|
|
5
|
+
* and the grant computation for the two toolLifecycle paths.
|
|
6
|
+
*
|
|
7
|
+
* Tests named "review #N" are regressions for the Greptile review of
|
|
8
|
+
* agent-framework PR #199.
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=mcpl-tool-lifecycle-emitter.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcpl-tool-lifecycle-emitter.test.d.ts","sourceRoot":"","sources":["../../test/mcpl-tool-lifecycle-emitter.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCPL RFC-007 tool lifecycle — the emitter's pairing (started at dispatch →
|
|
3
|
+
* exactly one terminal, to exactly the connection epochs the opening went
|
|
4
|
+
* to, unless their grant no longer covers the call), host-unique call ids,
|
|
5
|
+
* and the grant computation for the two toolLifecycle paths.
|
|
6
|
+
*
|
|
7
|
+
* Tests named "review #N" are regressions for the Greptile review of
|
|
8
|
+
* agent-framework PR #199.
|
|
9
|
+
*/
|
|
10
|
+
import { test, describe } from 'node:test';
|
|
11
|
+
import assert from 'node:assert/strict';
|
|
12
|
+
import { CapabilityGrant, computeGrant } from '../src/mcpl/capability-grant.js';
|
|
13
|
+
import { ToolLifecycleEmitter, openingFor, parseToolObserveParams, } from '../src/mcpl/tool-lifecycle.js';
|
|
14
|
+
const OBSERVE = 'toolLifecycle.observe';
|
|
15
|
+
const INPUTS = 'toolLifecycle.inputs';
|
|
16
|
+
function observer(id, paths, filter = null) {
|
|
17
|
+
const sent = [];
|
|
18
|
+
return {
|
|
19
|
+
id,
|
|
20
|
+
grant: new CapabilityGrant(new Set(paths), []),
|
|
21
|
+
toolObserveFilter: filter,
|
|
22
|
+
transportEpoch: 0,
|
|
23
|
+
sendToolLifecycle: (p) => { sent.push(p); },
|
|
24
|
+
sent,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function rules(raw) {
|
|
28
|
+
const parsed = parseToolObserveParams({ rules: raw });
|
|
29
|
+
assert.ok(parsed.ok, `rules should parse: ${JSON.stringify(raw)}`);
|
|
30
|
+
return parsed.rules;
|
|
31
|
+
}
|
|
32
|
+
const DEFAULT_INPUTS = { observe: {}, inputs: { classes: 'default' } };
|
|
33
|
+
function harness(opts) {
|
|
34
|
+
let clock = 1000;
|
|
35
|
+
const emitter = new ToolLifecycleEmitter({
|
|
36
|
+
observers: () => opts.observers,
|
|
37
|
+
configFor: (id) => opts.config?.[id],
|
|
38
|
+
describe: (tool) => {
|
|
39
|
+
const sep = tool.indexOf('--');
|
|
40
|
+
const cls = opts.classes?.[tool] ?? ['shell'];
|
|
41
|
+
return sep > 0
|
|
42
|
+
? { class: cls, serverId: tool.slice(0, sep), serverTool: tool.slice(sep + 2) }
|
|
43
|
+
: { class: cls };
|
|
44
|
+
},
|
|
45
|
+
}, () => clock);
|
|
46
|
+
return { emitter, tick: (ms) => { clock += ms; } };
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* What the framework does at its dispatch point: register, run dispatch
|
|
50
|
+
* (whose refusal sites may call refuse()), then open.
|
|
51
|
+
*/
|
|
52
|
+
function dispatch(emitter, agent, inferenceId, call, refusedByHost = false) {
|
|
53
|
+
emitter.register(agent, inferenceId, call);
|
|
54
|
+
if (refusedByHost)
|
|
55
|
+
emitter.refuse(agent, call.id);
|
|
56
|
+
emitter.open(agent, call.id);
|
|
57
|
+
}
|
|
58
|
+
/** An Anthropic-shaped, provider-unique tool_use id. */
|
|
59
|
+
const TOOLU = (n) => `toolu_01${String(n).padStart(22, '0')}`;
|
|
60
|
+
describe('ToolLifecycleEmitter', () => {
|
|
61
|
+
test('started at dispatch, completed on result — isError from the result, never its content', () => {
|
|
62
|
+
const o = observer('obs', [OBSERVE]);
|
|
63
|
+
const { emitter, tick } = harness({ observers: [o] });
|
|
64
|
+
dispatch(emitter, 'scout', 'inf_1', { id: TOOLU(1), name: 'prov--run', input: { cmd: 'make' } });
|
|
65
|
+
assert.deepEqual(o.sent.map((p) => p.phase), ['started']);
|
|
66
|
+
tick(40);
|
|
67
|
+
emitter.onResult('scout', TOOLU(1), { success: true, isError: true, data: 'SECRET-OUTPUT' });
|
|
68
|
+
assert.deepEqual(o.sent.map((p) => p.phase), ['started', 'completed']);
|
|
69
|
+
assert.equal(o.sent[1].isError, true);
|
|
70
|
+
assert.equal(o.sent[1].durationMs, 40);
|
|
71
|
+
assert.equal(o.sent[0].toolCallId, o.sent[1].toolCallId);
|
|
72
|
+
assert.ok(!JSON.stringify(o.sent).includes('SECRET-OUTPUT'), 'vector 26: no outcome leakage');
|
|
73
|
+
for (const p of o.sent) {
|
|
74
|
+
for (const k of ['result', 'output', 'content'])
|
|
75
|
+
assert.equal(k in p, false, `vector 27: no ${k}`);
|
|
76
|
+
}
|
|
77
|
+
assert.equal(emitter.openCount, 0);
|
|
78
|
+
});
|
|
79
|
+
test('review #6 — an error RESULT is completed+isError; only a marked dispatch failure is failed', () => {
|
|
80
|
+
const o = observer('obs', [OBSERVE]);
|
|
81
|
+
const { emitter } = harness({ observers: [o] });
|
|
82
|
+
dispatch(emitter, 'scout', 'inf_1', { id: TOOLU(2), name: 'utils', input: {} });
|
|
83
|
+
emitter.onResult('scout', TOOLU(2), { success: false, isError: true });
|
|
84
|
+
dispatch(emitter, 'scout', 'inf_1', { id: TOOLU(3), name: 'prov--run', input: {} });
|
|
85
|
+
emitter.markDispatchFailure('scout', TOOLU(3));
|
|
86
|
+
emitter.onResult('scout', TOOLU(3), { success: false, isError: true });
|
|
87
|
+
const terminals = o.sent.filter((p) => p.phase !== 'started');
|
|
88
|
+
assert.deepEqual(terminals.map((p) => `${p.tool}:${p.phase}:${p.isError}`), [
|
|
89
|
+
'utils:completed:true',
|
|
90
|
+
'prov--run:failed:undefined',
|
|
91
|
+
]);
|
|
92
|
+
});
|
|
93
|
+
test('review #4 — a call the host refuses before executing (provider gone, policy) produces no events', () => {
|
|
94
|
+
const o = observer('obs', [OBSERVE, INPUTS], rules([{ match: {}, input: true }]));
|
|
95
|
+
const { emitter } = harness({ observers: [o], config: { obs: DEFAULT_INPUTS } });
|
|
96
|
+
dispatch(emitter, 'scout', 'inf_1', { id: TOOLU(4), name: 'gone--click', input: { x: 1 } }, true);
|
|
97
|
+
emitter.onResult('scout', TOOLU(4), { success: false, isError: true });
|
|
98
|
+
assert.equal(o.sent.length, 0);
|
|
99
|
+
assert.equal(emitter.openCount, 0);
|
|
100
|
+
});
|
|
101
|
+
test('re-review #1 — a host-tool refusal (conversation-bound channel guard) produces no events', () => {
|
|
102
|
+
const o = observer('obs', [OBSERVE]);
|
|
103
|
+
const { emitter } = harness({ observers: [o], classes: { channel_open: ['comms'] } });
|
|
104
|
+
dispatch(emitter, 'fork-1', 'inf_1', { id: TOOLU(40), name: 'channel_open', input: { channelId: 'x' } }, true);
|
|
105
|
+
emitter.onResult('fork-1', TOOLU(40), { success: false, isError: true });
|
|
106
|
+
assert.equal(o.sent.length, 0, 'never reported as started or completed');
|
|
107
|
+
// refuse() after the opening went out changes nothing: refusal is only
|
|
108
|
+
// meaningful before execution, and the call is then paired normally.
|
|
109
|
+
dispatch(emitter, 'scout', 'inf_2', { id: TOOLU(41), name: 'prov--a', input: {} });
|
|
110
|
+
emitter.refuse('scout', TOOLU(41));
|
|
111
|
+
emitter.onResult('scout', TOOLU(41), { success: true });
|
|
112
|
+
assert.deepEqual(o.sent.map((p) => p.phase), ['started', 'completed']);
|
|
113
|
+
});
|
|
114
|
+
test('review #2 — two agents with the same short call id never cross', () => {
|
|
115
|
+
const o = observer('obs', [OBSERVE]);
|
|
116
|
+
const { emitter } = harness({ observers: [o] });
|
|
117
|
+
dispatch(emitter, 'alice', 'inf_a', { id: 'call_0', name: 'prov--a', input: {} });
|
|
118
|
+
dispatch(emitter, 'bob', 'inf_b', { id: 'call_0', name: 'prov--b', input: {} });
|
|
119
|
+
emitter.markDispatchFailure('bob', 'call_0');
|
|
120
|
+
emitter.onResult('bob', 'call_0', { success: false, isError: true });
|
|
121
|
+
emitter.onResult('alice', 'call_0', { success: true });
|
|
122
|
+
const byTool = (tool) => o.sent.filter((p) => p.tool === tool).map((p) => p.phase);
|
|
123
|
+
assert.deepEqual(byTool('prov--a'), ['started', 'completed']);
|
|
124
|
+
assert.deepEqual(byTool('prov--b'), ['started', 'failed']);
|
|
125
|
+
const ids = new Set(o.sent.filter((p) => p.phase === 'started').map((p) => p.toolCallId));
|
|
126
|
+
assert.equal(ids.size, 2, 'distinct host ids for the two call_0s');
|
|
127
|
+
});
|
|
128
|
+
test('review #5 — a stream end aborts only its own inference ids, never a successor\'s calls', () => {
|
|
129
|
+
const o = observer('obs', [OBSERVE]);
|
|
130
|
+
const { emitter } = harness({ observers: [o] });
|
|
131
|
+
dispatch(emitter, 'scout', 'inf_old', { id: TOOLU(5), name: 'prov--a', input: {} });
|
|
132
|
+
dispatch(emitter, 'scout', 'inf_new', { id: TOOLU(6), name: 'prov--b', input: {} });
|
|
133
|
+
dispatch(emitter, 'other', 'inf_x', { id: TOOLU(7), name: 'prov--c', input: {} });
|
|
134
|
+
emitter.abortOpen('scout', ['inf_old']);
|
|
135
|
+
assert.deepEqual(o.sent.filter((p) => p.phase === 'aborted').map((p) => p.tool), ['prov--a']);
|
|
136
|
+
emitter.onResult('scout', TOOLU(6), { success: true });
|
|
137
|
+
assert.deepEqual(o.sent.filter((p) => p.tool === 'prov--b').map((p) => p.phase), ['started', 'completed']);
|
|
138
|
+
emitter.onResult('scout', TOOLU(5), { success: true });
|
|
139
|
+
assert.equal(o.sent.filter((p) => p.tool === 'prov--a').length, 2, 'no second terminal after abort');
|
|
140
|
+
assert.equal(emitter.openCount, 1, "the other agent's call stays open");
|
|
141
|
+
});
|
|
142
|
+
test('re-review #2 — durationMs counts from before dispatch, so synchronous work inside dispatch is included', () => {
|
|
143
|
+
const o = observer('obs', [OBSERVE]);
|
|
144
|
+
const { emitter, tick } = harness({ observers: [o] });
|
|
145
|
+
emitter.register('scout', 'inf_1', { id: TOOLU(42), name: 'sleep', input: {} });
|
|
146
|
+
tick(25); // a synchronous tool doing its work inside dispatch
|
|
147
|
+
emitter.open('scout', TOOLU(42));
|
|
148
|
+
tick(5); // the queued result waiting to be processed
|
|
149
|
+
emitter.onResult('scout', TOOLU(42), { success: true });
|
|
150
|
+
assert.deepEqual(o.sent.map((p) => p.phase), ['started', 'completed']);
|
|
151
|
+
assert.equal(o.sent[1].durationMs, 30);
|
|
152
|
+
});
|
|
153
|
+
test('parallel calls pair by toolCallId', () => {
|
|
154
|
+
const o = observer('obs', [OBSERVE]);
|
|
155
|
+
const { emitter } = harness({ observers: [o] });
|
|
156
|
+
dispatch(emitter, 'scout', 'inf_1', { id: TOOLU(8), name: 'prov--a', input: {} });
|
|
157
|
+
dispatch(emitter, 'scout', 'inf_1', { id: TOOLU(9), name: 'prov--b', input: {} });
|
|
158
|
+
emitter.onResult('scout', TOOLU(9), { success: true });
|
|
159
|
+
emitter.onResult('scout', TOOLU(8), { success: true });
|
|
160
|
+
assert.deepEqual(o.sent.map((p) => `${p.toolCallId}:${p.phase}`), [
|
|
161
|
+
`${TOOLU(8)}:started`, `${TOOLU(9)}:started`, `${TOOLU(9)}:completed`, `${TOOLU(8)}:completed`,
|
|
162
|
+
]);
|
|
163
|
+
});
|
|
164
|
+
test('observe revoked mid-call → no terminal; inputs revoked mid-call → terminal still sent (§4.5)', () => {
|
|
165
|
+
const a = observer('a', [OBSERVE]);
|
|
166
|
+
const b = observer('b', [OBSERVE, INPUTS]);
|
|
167
|
+
const { emitter } = harness({ observers: [a, b] });
|
|
168
|
+
dispatch(emitter, 'scout', 'inf_1', { id: TOOLU(10), name: 'prov--a', input: {} });
|
|
169
|
+
a.grant = a.grant.without(OBSERVE);
|
|
170
|
+
b.grant = b.grant.without(INPUTS);
|
|
171
|
+
emitter.onResult('scout', TOOLU(10), { success: true });
|
|
172
|
+
assert.deepEqual(a.sent.map((p) => p.phase), ['started']);
|
|
173
|
+
assert.deepEqual(b.sent.map((p) => p.phase), ['started', 'completed']);
|
|
174
|
+
});
|
|
175
|
+
test('review #7 — a reconnected observer never gets a terminal for an opening its old transport saw', () => {
|
|
176
|
+
const o = observer('obs', [OBSERVE]);
|
|
177
|
+
const { emitter } = harness({ observers: [o] });
|
|
178
|
+
dispatch(emitter, 'scout', 'inf_1', { id: TOOLU(11), name: 'prov--a', input: {} });
|
|
179
|
+
o.transportEpoch++; // reconnect; grant re-established
|
|
180
|
+
emitter.onResult('scout', TOOLU(11), { success: true });
|
|
181
|
+
assert.deepEqual(o.sent.map((p) => p.phase), ['started']);
|
|
182
|
+
});
|
|
183
|
+
test('a filter change mid-call does not suppress the terminal (§6.5)', () => {
|
|
184
|
+
const o = observer('obs', [OBSERVE]);
|
|
185
|
+
const { emitter } = harness({ observers: [o] });
|
|
186
|
+
dispatch(emitter, 'scout', 'inf_1', { id: TOOLU(12), name: 'prov--a', input: {} });
|
|
187
|
+
o.toolObserveFilter = [];
|
|
188
|
+
emitter.onResult('scout', TOOLU(12), { success: true });
|
|
189
|
+
assert.deepEqual(o.sent.map((p) => p.phase), ['started', 'completed']);
|
|
190
|
+
});
|
|
191
|
+
test('terminals go only where the opening went', () => {
|
|
192
|
+
const early = observer('early', [OBSERVE]);
|
|
193
|
+
const late = observer('late', []);
|
|
194
|
+
const { emitter } = harness({ observers: [early, late] });
|
|
195
|
+
dispatch(emitter, 'scout', 'inf_1', { id: TOOLU(13), name: 'prov--a', input: {} });
|
|
196
|
+
late.grant = new CapabilityGrant(new Set([OBSERVE]), []);
|
|
197
|
+
emitter.onResult('scout', TOOLU(13), { success: true });
|
|
198
|
+
assert.deepEqual(early.sent.map((p) => p.phase), ['started', 'completed']);
|
|
199
|
+
assert.equal(late.sent.length, 0, 'granted mid-call: no terminal without an opening');
|
|
200
|
+
});
|
|
201
|
+
test('review #9 — ids: provider-unique toolu ids kept; everything else and any repeat minted (§3)', () => {
|
|
202
|
+
const o = observer('obs', [OBSERVE]);
|
|
203
|
+
const { emitter } = harness({ observers: [o] });
|
|
204
|
+
const run = (id) => {
|
|
205
|
+
dispatch(emitter, 'scout', 'inf', { id, name: 'prov--a', input: {} });
|
|
206
|
+
emitter.onResult('scout', id, { success: true });
|
|
207
|
+
};
|
|
208
|
+
run('call_0');
|
|
209
|
+
run('call_0');
|
|
210
|
+
run(TOOLU(14));
|
|
211
|
+
run(TOOLU(14));
|
|
212
|
+
run('call_abcdefghijklmnopqrstuvwxyz0123'); // long, but not a provider-guaranteed format
|
|
213
|
+
const opened = o.sent.filter((p) => p.phase === 'started').map((p) => p.toolCallId);
|
|
214
|
+
assert.equal(new Set(opened).size, 5, `ids must be unique: ${opened.join(', ')}`);
|
|
215
|
+
assert.ok(opened[0].startsWith('call_0~'));
|
|
216
|
+
assert.equal(opened[2], TOOLU(14), 'a provider-unique id is used as is');
|
|
217
|
+
assert.notEqual(opened[3], TOOLU(14), 'its repeat is minted over');
|
|
218
|
+
assert.ok(opened[4].startsWith('call_abcdefghijklmnopqrstuvwxyz0123~'), 'unknown formats are minted');
|
|
219
|
+
});
|
|
220
|
+
test('inert while nothing observes: register tracks nothing', () => {
|
|
221
|
+
const o = observer('obs', []);
|
|
222
|
+
const { emitter } = harness({ observers: [o] });
|
|
223
|
+
dispatch(emitter, 'scout', 'inf', { id: TOOLU(15), name: 'prov--a', input: {} });
|
|
224
|
+
assert.equal(emitter.openCount, 0);
|
|
225
|
+
});
|
|
226
|
+
test('the filter and the grant compose end to end', () => {
|
|
227
|
+
const o = observer('obs', [OBSERVE, INPUTS], rules([
|
|
228
|
+
{ match: { serverTool: 'click' }, input: ['x', 'y'] },
|
|
229
|
+
{ match: { class: 'comms' }, report: false },
|
|
230
|
+
{ match: {} },
|
|
231
|
+
]));
|
|
232
|
+
const { emitter } = harness({
|
|
233
|
+
observers: [o],
|
|
234
|
+
config: { obs: DEFAULT_INPUTS },
|
|
235
|
+
classes: { 'computer--click': ['computer'], 'chat--send': ['comms'], 'blender--execute': [] },
|
|
236
|
+
});
|
|
237
|
+
const go = (id, name, input) => {
|
|
238
|
+
dispatch(emitter, 'scout', 'inf', { id, name, input });
|
|
239
|
+
emitter.onResult('scout', id, { success: true });
|
|
240
|
+
};
|
|
241
|
+
go(TOOLU(20), 'computer--click', { x: 1, y: 2, button: 'left' });
|
|
242
|
+
go(TOOLU(21), 'chat--send', { text: 'private words' });
|
|
243
|
+
go(TOOLU(22), 'blender--execute', { code: 'import bpy' });
|
|
244
|
+
const started = o.sent.filter((p) => p.phase === 'started');
|
|
245
|
+
assert.deepEqual(started.map((p) => p.tool), ['computer--click', 'blender--execute']);
|
|
246
|
+
assert.deepEqual(started[0].input, { x: 1, y: 2 });
|
|
247
|
+
assert.equal(started[1].input, undefined);
|
|
248
|
+
assert.ok(!JSON.stringify(o.sent).includes('private words'));
|
|
249
|
+
assert.ok(!JSON.stringify(o.sent).includes('import bpy'));
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
// ── Grant computation and config robustness ─────────────────────────────────
|
|
253
|
+
describe('toolLifecycle grant', () => {
|
|
254
|
+
const caps = (o) => ({ version: '0.5', ...o });
|
|
255
|
+
const quiet = (fn) => {
|
|
256
|
+
const orig = console.error;
|
|
257
|
+
console.error = () => { };
|
|
258
|
+
try {
|
|
259
|
+
return fn();
|
|
260
|
+
}
|
|
261
|
+
finally {
|
|
262
|
+
console.error = orig;
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
const anyCall = {
|
|
266
|
+
toolCallId: TOOLU(30), inferenceId: 'inf', conversationId: 'scout', tool: 'prov--a',
|
|
267
|
+
class: ['shell'], serverId: 'prov', serverTool: 'a', input: {},
|
|
268
|
+
};
|
|
269
|
+
test('vector 49 — advertised but not granted by default', () => {
|
|
270
|
+
const g = quiet(() => computeGrant(caps({ toolLifecycle: true }), {}));
|
|
271
|
+
assert.equal(g.has(OBSERVE), false);
|
|
272
|
+
assert.equal(g.has(INPUTS), false);
|
|
273
|
+
assert.ok(g.deniedPaths.includes(OBSERVE) && g.deniedPaths.includes(INPUTS));
|
|
274
|
+
});
|
|
275
|
+
test('vector 50 — a policy object is the explicit grant of the path it states', () => {
|
|
276
|
+
const g1 = quiet(() => computeGrant(caps({ toolLifecycle: true }), { toolLifecycle: { observe: {} } }));
|
|
277
|
+
assert.equal(g1.has(OBSERVE), true);
|
|
278
|
+
assert.equal(g1.has(INPUTS), false);
|
|
279
|
+
const g2 = quiet(() => computeGrant(caps({ toolLifecycle: true }), { toolLifecycle: { observe: {}, inputs: { classes: 'default' } } }));
|
|
280
|
+
assert.equal(g2.has(INPUTS), true);
|
|
281
|
+
});
|
|
282
|
+
test('review #1 — `observe: false` (or null, or a string) grants nothing', () => {
|
|
283
|
+
for (const value of [false, null, 'yes', 0]) {
|
|
284
|
+
const g = quiet(() => computeGrant(caps({ toolLifecycle: true }), { toolLifecycle: { observe: value } }));
|
|
285
|
+
assert.equal(g.has(OBSERVE), false, JSON.stringify(value));
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
test('review #1 — a non-object narrowing under an explicit grant admits nothing', () => {
|
|
289
|
+
const o = observer('obs', [OBSERVE]);
|
|
290
|
+
for (const observe of [false, null, 'x', { tools: 'prov--*' }, { conversations: 7 }, { classes: 'shell' }]) {
|
|
291
|
+
assert.equal(openingFor(o, { observe }, anyCall, 'started'), null, JSON.stringify(observe));
|
|
292
|
+
}
|
|
293
|
+
assert.ok(openingFor(o, { observe: { tools: ['prov--*'] } }, anyCall, 'started'));
|
|
294
|
+
assert.ok(openingFor(o, undefined, anyCall, 'started'), 'absent narrowing = the grant is enough');
|
|
295
|
+
});
|
|
296
|
+
test('enabledCapabilities grants explicitly too; never beyond the advertisement', () => {
|
|
297
|
+
const g = quiet(() => computeGrant(caps({ toolLifecycle: { observe: true } }), { enabledCapabilities: ['toolLifecycle.*'] }));
|
|
298
|
+
assert.equal(g.has(OBSERVE), true);
|
|
299
|
+
assert.equal(g.has(INPUTS), false, 'inputs was not advertised');
|
|
300
|
+
});
|
|
301
|
+
test('review #8 — an unknown params member is rejected, not read as "no rules"', () => {
|
|
302
|
+
const r = parseToolObserveParams({ ruless: [{ match: {} }] });
|
|
303
|
+
assert.equal(r.ok, false);
|
|
304
|
+
assert.equal(parseToolObserveParams({ rules: [], _meta: { trace: 'x' } }).ok, true, "MCP's _meta is allowed");
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
//# sourceMappingURL=mcpl-tool-lifecycle-emitter.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcpl-tool-lifecycle-emitter.test.js","sourceRoot":"","sources":["../../test/mcpl-tool-lifecycle-emitter.test.ts"],"names":[],"mappings":"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"}
|