@namzu/cli 0.6.0 → 0.7.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/dist/__tests__/permission-rules-reach-the-turn.test.d.ts +31 -0
- package/dist/__tests__/permission-rules-reach-the-turn.test.d.ts.map +1 -0
- package/dist/__tests__/permission-rules-reach-the-turn.test.js +132 -0
- package/dist/__tests__/permission-rules-reach-the-turn.test.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +16 -3
- package/dist/cli.js.map +1 -1
- package/dist/cli.test.js +7 -1
- package/dist/cli.test.js.map +1 -1
- package/dist/commands/__tests__/run-flags.test.js +0 -1
- package/dist/commands/__tests__/run-flags.test.js.map +1 -1
- package/dist/commands/__tests__/run-stream-flags.test.js +0 -1
- package/dist/commands/__tests__/run-stream-flags.test.js.map +1 -1
- package/dist/commands/run-stream.d.ts +3 -3
- package/dist/commands/run-stream.js +3 -3
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +4 -0
- package/dist/commands/run.js.map +1 -1
- package/dist/commands/stubs.d.ts +10 -0
- package/dist/commands/stubs.d.ts.map +1 -1
- package/dist/commands/stubs.js +12 -2
- package/dist/commands/stubs.js.map +1 -1
- package/dist/config/load.d.ts.map +1 -1
- package/dist/config/load.js +20 -4
- package/dist/config/load.js.map +1 -1
- package/dist/config/schema.d.ts +0 -12
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js.map +1 -1
- package/dist/doctor/checks/credentials.d.ts +20 -0
- package/dist/doctor/checks/credentials.d.ts.map +1 -0
- package/dist/doctor/checks/credentials.js +58 -0
- package/dist/doctor/checks/credentials.js.map +1 -0
- package/dist/doctor/checks/credentials.test.d.ts +10 -0
- package/dist/doctor/checks/credentials.test.d.ts.map +1 -0
- package/dist/doctor/checks/credentials.test.js +47 -0
- package/dist/doctor/checks/credentials.test.js.map +1 -0
- package/dist/doctor/checks/index.d.ts +2 -1
- package/dist/doctor/checks/index.d.ts.map +1 -1
- package/dist/doctor/checks/index.js +3 -1
- package/dist/doctor/checks/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/integrations/providers/discover.d.ts +3 -8
- package/dist/integrations/providers/discover.d.ts.map +1 -1
- package/dist/integrations/providers/discover.js +2 -12
- package/dist/integrations/providers/discover.js.map +1 -1
- package/dist/integrations/providers/discover.test.js +1 -28
- package/dist/integrations/providers/discover.test.js.map +1 -1
- package/dist/integrations/providers/index.d.ts +0 -1
- package/dist/integrations/providers/index.d.ts.map +1 -1
- package/dist/integrations/providers/index.js +0 -1
- package/dist/integrations/providers/index.js.map +1 -1
- package/dist/integrations/providers/oauth.d.ts +1 -1
- package/dist/integrations/providers/oauth.js +1 -1
- package/dist/integrations/providers/preferences.d.ts +2 -2
- package/dist/integrations/providers/preferences.js +2 -2
- package/dist/integrations/sessions/store.js +1 -1
- package/dist/integrations/sessions/store.js.map +1 -1
- package/dist/integrations/updates.d.ts +4 -12
- package/dist/integrations/updates.d.ts.map +1 -1
- package/dist/integrations/updates.js +6 -53
- package/dist/integrations/updates.js.map +1 -1
- package/dist/tui/App.d.ts.map +1 -1
- package/dist/tui/App.js +23 -131
- package/dist/tui/App.js.map +1 -1
- package/dist/tui/Picker.d.ts +4 -4
- package/dist/tui/Picker.d.ts.map +1 -1
- package/dist/tui/Picker.js +6 -8
- package/dist/tui/Picker.js.map +1 -1
- package/dist/tui/__tests__/deferred-tool-discovery.test.d.ts +24 -0
- package/dist/tui/__tests__/deferred-tool-discovery.test.d.ts.map +1 -0
- package/dist/tui/__tests__/deferred-tool-discovery.test.js +111 -0
- package/dist/tui/__tests__/deferred-tool-discovery.test.js.map +1 -0
- package/dist/tui/__tests__/to-agent-event.test.js +88 -0
- package/dist/tui/__tests__/to-agent-event.test.js.map +1 -1
- package/dist/tui/__tests__/working-directory.test.js +0 -6
- package/dist/tui/__tests__/working-directory.test.js.map +1 -1
- package/dist/tui/agent.d.ts +16 -2
- package/dist/tui/agent.d.ts.map +1 -1
- package/dist/tui/agent.js +83 -30
- package/dist/tui/agent.js.map +1 -1
- package/dist/tui/slashCommands.d.ts +0 -6
- package/dist/tui/slashCommands.d.ts.map +1 -1
- package/dist/tui/slashCommands.js +1 -21
- package/dist/tui/slashCommands.js.map +1 -1
- package/dist/tui/types.d.ts +12 -0
- package/dist/tui/types.d.ts.map +1 -1
- package/package.json +4 -5
- package/dist/commands/tools.d.ts +0 -16
- package/dist/commands/tools.d.ts.map +0 -1
- package/dist/commands/tools.js +0 -161
- package/dist/commands/tools.js.map +0 -1
- package/dist/integrations/clawtool/agents.d.ts +0 -31
- package/dist/integrations/clawtool/agents.d.ts.map +0 -1
- package/dist/integrations/clawtool/agents.js +0 -30
- package/dist/integrations/clawtool/agents.js.map +0 -1
- package/dist/integrations/clawtool/agents.test.d.ts +0 -2
- package/dist/integrations/clawtool/agents.test.d.ts.map +0 -1
- package/dist/integrations/clawtool/agents.test.js +0 -79
- package/dist/integrations/clawtool/agents.test.js.map +0 -1
- package/dist/integrations/clawtool/auth.d.ts +0 -26
- package/dist/integrations/clawtool/auth.d.ts.map +0 -1
- package/dist/integrations/clawtool/auth.js +0 -56
- package/dist/integrations/clawtool/auth.js.map +0 -1
- package/dist/integrations/clawtool/auth.test.d.ts +0 -2
- package/dist/integrations/clawtool/auth.test.d.ts.map +0 -1
- package/dist/integrations/clawtool/auth.test.js +0 -40
- package/dist/integrations/clawtool/auth.test.js.map +0 -1
- package/dist/integrations/clawtool/binary.d.ts +0 -25
- package/dist/integrations/clawtool/binary.d.ts.map +0 -1
- package/dist/integrations/clawtool/binary.js +0 -50
- package/dist/integrations/clawtool/binary.js.map +0 -1
- package/dist/integrations/clawtool/binary.test.d.ts +0 -2
- package/dist/integrations/clawtool/binary.test.d.ts.map +0 -1
- package/dist/integrations/clawtool/binary.test.js +0 -50
- package/dist/integrations/clawtool/binary.test.js.map +0 -1
- package/dist/integrations/clawtool/daemon.d.ts +0 -37
- package/dist/integrations/clawtool/daemon.d.ts.map +0 -1
- package/dist/integrations/clawtool/daemon.js +0 -109
- package/dist/integrations/clawtool/daemon.js.map +0 -1
- package/dist/integrations/clawtool/daemon.test.d.ts +0 -11
- package/dist/integrations/clawtool/daemon.test.d.ts.map +0 -1
- package/dist/integrations/clawtool/daemon.test.js +0 -118
- package/dist/integrations/clawtool/daemon.test.js.map +0 -1
- package/dist/integrations/clawtool/dispatch.d.ts +0 -33
- package/dist/integrations/clawtool/dispatch.d.ts.map +0 -1
- package/dist/integrations/clawtool/dispatch.js +0 -155
- package/dist/integrations/clawtool/dispatch.js.map +0 -1
- package/dist/integrations/clawtool/dispatch.test.d.ts +0 -2
- package/dist/integrations/clawtool/dispatch.test.d.ts.map +0 -1
- package/dist/integrations/clawtool/dispatch.test.js +0 -138
- package/dist/integrations/clawtool/dispatch.test.js.map +0 -1
- package/dist/integrations/clawtool/index.d.ts +0 -11
- package/dist/integrations/clawtool/index.d.ts.map +0 -1
- package/dist/integrations/clawtool/index.js +0 -10
- package/dist/integrations/clawtool/index.js.map +0 -1
- package/dist/integrations/clawtool/mcp.d.ts +0 -51
- package/dist/integrations/clawtool/mcp.d.ts.map +0 -1
- package/dist/integrations/clawtool/mcp.js +0 -174
- package/dist/integrations/clawtool/mcp.js.map +0 -1
- package/dist/integrations/clawtool/mcp.test.d.ts +0 -2
- package/dist/integrations/clawtool/mcp.test.d.ts.map +0 -1
- package/dist/integrations/clawtool/mcp.test.js +0 -126
- package/dist/integrations/clawtool/mcp.test.js.map +0 -1
- package/dist/integrations/clawtool/paths.d.ts +0 -8
- package/dist/integrations/clawtool/paths.d.ts.map +0 -1
- package/dist/integrations/clawtool/paths.js +0 -19
- package/dist/integrations/clawtool/paths.js.map +0 -1
- package/dist/integrations/clawtool/peers.d.ts +0 -67
- package/dist/integrations/clawtool/peers.d.ts.map +0 -1
- package/dist/integrations/clawtool/peers.js +0 -150
- package/dist/integrations/clawtool/peers.js.map +0 -1
- package/dist/integrations/clawtool/plugin.d.ts +0 -42
- package/dist/integrations/clawtool/plugin.d.ts.map +0 -1
- package/dist/integrations/clawtool/plugin.js +0 -38
- package/dist/integrations/clawtool/plugin.js.map +0 -1
- package/dist/integrations/clawtool/state.d.ts +0 -11
- package/dist/integrations/clawtool/state.d.ts.map +0 -1
- package/dist/integrations/clawtool/state.js +0 -41
- package/dist/integrations/clawtool/state.js.map +0 -1
- package/dist/integrations/clawtool/state.test.d.ts +0 -2
- package/dist/integrations/clawtool/state.test.d.ts.map +0 -1
- package/dist/integrations/clawtool/state.test.js +0 -38
- package/dist/integrations/clawtool/state.test.js.map +0 -1
- package/dist/integrations/clawtool/tooling.d.ts +0 -52
- package/dist/integrations/clawtool/tooling.d.ts.map +0 -1
- package/dist/integrations/clawtool/tooling.js +0 -91
- package/dist/integrations/clawtool/tooling.js.map +0 -1
- package/dist/integrations/clawtool/tooling.test.d.ts +0 -2
- package/dist/integrations/clawtool/tooling.test.d.ts.map +0 -1
- package/dist/integrations/clawtool/tooling.test.js +0 -58
- package/dist/integrations/clawtool/tooling.test.js.map +0 -1
- package/dist/integrations/clawtool/types.d.ts +0 -41
- package/dist/integrations/clawtool/types.d.ts.map +0 -1
- package/dist/integrations/clawtool/types.js +0 -9
- package/dist/integrations/clawtool/types.js.map +0 -1
- package/dist/integrations/providers/secrets.d.ts +0 -37
- package/dist/integrations/providers/secrets.d.ts.map +0 -1
- package/dist/integrations/providers/secrets.js +0 -69
- package/dist/integrations/providers/secrets.js.map +0 -1
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `search_tools` is mounted where there is something to find, and not where
|
|
3
|
+
* there is not.
|
|
4
|
+
*
|
|
5
|
+
* The two registries come from the same builder, so "does the CLI register
|
|
6
|
+
* search_tools" has one answer from one call site and a different correct
|
|
7
|
+
* answer from the other — the shape that hides behind a green suite. The
|
|
8
|
+
* session passes a `taskStore`, so `query()` registers the task tools deferred
|
|
9
|
+
* and the search has a roster of three. A sub-agent is built with no task
|
|
10
|
+
* store, so nothing in its registry is deferred and the tool could only ever
|
|
11
|
+
* answer "no deferred tools matching X" — a capability advertised every turn
|
|
12
|
+
* that costs a turn to discover it is unusable.
|
|
13
|
+
*
|
|
14
|
+
* Removing the peer-daemon catalog is what created the asymmetry: that catalog
|
|
15
|
+
* used to supply BOTH registries, so both were justified in mounting the tool.
|
|
16
|
+
* Only one lost its supplier, and from the side that still works the loss is
|
|
17
|
+
* invisible.
|
|
18
|
+
*
|
|
19
|
+
* So this asserts the CONTRAST, not either half: a test that only checked the
|
|
20
|
+
* session would pass with the tool wrongly mounted on the sub-agent, which is
|
|
21
|
+
* exactly the state this file was written against.
|
|
22
|
+
*/
|
|
23
|
+
import { mkdtempSync, rmSync } from 'node:fs';
|
|
24
|
+
import { tmpdir } from 'node:os';
|
|
25
|
+
import { join } from 'node:path';
|
|
26
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
27
|
+
vi.mock('@namzu/sdk', async (importOriginal) => {
|
|
28
|
+
const actual = await importOriginal();
|
|
29
|
+
return {
|
|
30
|
+
...actual,
|
|
31
|
+
query: () => (async function* () { })(),
|
|
32
|
+
};
|
|
33
|
+
});
|
|
34
|
+
// The sub-agent's registry is built by a callback the session hands to this
|
|
35
|
+
// factory, so capturing the callback is the only way to see what a sub-agent
|
|
36
|
+
// would actually get — and it is the real wiring, not a re-derivation of it.
|
|
37
|
+
let capturedBuildTools = null;
|
|
38
|
+
vi.mock('../../integrations/subagents/runtime.js', () => ({
|
|
39
|
+
createSubagentRuntime: async (opts) => {
|
|
40
|
+
capturedBuildTools = opts.buildTools;
|
|
41
|
+
return {
|
|
42
|
+
gateway: {},
|
|
43
|
+
agentTool: {
|
|
44
|
+
name: 'Agent',
|
|
45
|
+
description: 'stub',
|
|
46
|
+
inputSchema: { type: 'object', properties: {} },
|
|
47
|
+
execute: async () => ({ success: true, output: '' }),
|
|
48
|
+
},
|
|
49
|
+
allowedAgentIds: [],
|
|
50
|
+
};
|
|
51
|
+
},
|
|
52
|
+
}));
|
|
53
|
+
let workDir;
|
|
54
|
+
beforeEach(() => {
|
|
55
|
+
capturedBuildTools = null;
|
|
56
|
+
workDir = mkdtempSync(join(tmpdir(), 'namzu-deferred-'));
|
|
57
|
+
});
|
|
58
|
+
afterEach(() => {
|
|
59
|
+
rmSync(workDir, { recursive: true, force: true });
|
|
60
|
+
});
|
|
61
|
+
const prefs = {
|
|
62
|
+
version: 2,
|
|
63
|
+
provider: 'anthropic',
|
|
64
|
+
subagents: { active: [] },
|
|
65
|
+
};
|
|
66
|
+
function detectedAnthropic() {
|
|
67
|
+
return [
|
|
68
|
+
{
|
|
69
|
+
entry: {
|
|
70
|
+
id: 'anthropic',
|
|
71
|
+
label: 'Anthropic',
|
|
72
|
+
defaultModel: 'claude-sonnet-4-5',
|
|
73
|
+
requiresApiKey: true,
|
|
74
|
+
envVars: ['ANTHROPIC_API_KEY'],
|
|
75
|
+
},
|
|
76
|
+
source: 'env',
|
|
77
|
+
apiKey: 'sk-ant-not-a-real-key',
|
|
78
|
+
alternatives: [],
|
|
79
|
+
},
|
|
80
|
+
];
|
|
81
|
+
}
|
|
82
|
+
describe('search_tools is mounted only where a deferred roster exists', () => {
|
|
83
|
+
it('the session offers it and a sub-agent does not', async () => {
|
|
84
|
+
const { createAgentSession } = await import('../agent.js');
|
|
85
|
+
const session = await createAgentSession(prefs, detectedAnthropic(), { cwd: workDir });
|
|
86
|
+
expect(session.hasProvider).toBe(true);
|
|
87
|
+
// The session opens a task store, so query() defers the task tools and
|
|
88
|
+
// the search has a roster.
|
|
89
|
+
expect(session.toolNames).toContain('search_tools');
|
|
90
|
+
expect(capturedBuildTools, 'the session must hand the sub-agent factory a tool builder').not.toBeNull();
|
|
91
|
+
const subagentTools = capturedBuildTools();
|
|
92
|
+
const subagentNames = subagentTools.listNames();
|
|
93
|
+
// The whole point: same builder, and this side must NOT have it.
|
|
94
|
+
expect(subagentNames).not.toContain('search_tools');
|
|
95
|
+
// And the sub-agent is not stripped of everything else in the process —
|
|
96
|
+
// an assertion that would still hold if `buildTools` returned an empty
|
|
97
|
+
// registry, which would "pass" the line above for the wrong reason.
|
|
98
|
+
expect(subagentNames).toContain('bash');
|
|
99
|
+
expect(subagentNames).toContain('read');
|
|
100
|
+
});
|
|
101
|
+
it('leaves the sub-agent nothing deferred, which is why the tool is withheld', async () => {
|
|
102
|
+
const { createAgentSession } = await import('../agent.js');
|
|
103
|
+
await createAgentSession(prefs, detectedAnthropic(), { cwd: workDir });
|
|
104
|
+
const subagentTools = capturedBuildTools();
|
|
105
|
+
const deferred = subagentTools
|
|
106
|
+
.listNames()
|
|
107
|
+
.filter((n) => subagentTools.getAvailability(n) === 'deferred');
|
|
108
|
+
expect(deferred).toEqual([]);
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
//# sourceMappingURL=deferred-tool-discovery.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deferred-tool-discovery.test.js","sourceRoot":"","sources":["../../../src/tui/__tests__/deferred-tool-discovery.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -46,4 +46,92 @@ describe('toAgentEvent carries the stop reason across', () => {
|
|
|
46
46
|
expect(mapped).toEqual({ kind: 'error', message: 'boom' });
|
|
47
47
|
});
|
|
48
48
|
});
|
|
49
|
+
describe('compaction is reported, not silent', () => {
|
|
50
|
+
// Compaction deletes messages irrecoverably. The kernel emits both outcomes
|
|
51
|
+
// specifically so a host can surface the loss; this host used to drop them
|
|
52
|
+
// at `default: return null`, one function from the screen.
|
|
53
|
+
it('says which counts became which, and nothing it cannot substantiate', () => {
|
|
54
|
+
const mapped = toAgentEvent({
|
|
55
|
+
type: 'compaction_completed',
|
|
56
|
+
runId: 'run_1',
|
|
57
|
+
iteration: 3,
|
|
58
|
+
messagesBefore: 42,
|
|
59
|
+
messagesAfter: 9,
|
|
60
|
+
tokensBefore: 120_000,
|
|
61
|
+
tokensAfter: 38_000,
|
|
62
|
+
measuredBy: 'provider',
|
|
63
|
+
contextWindowTokens: 200_000,
|
|
64
|
+
windowSource: 'model-table',
|
|
65
|
+
reachedResetThreshold: true,
|
|
66
|
+
});
|
|
67
|
+
expect(mapped).toMatchObject({ kind: 'context', shed: true });
|
|
68
|
+
const text = mapped.text;
|
|
69
|
+
expect(text).toContain('42');
|
|
70
|
+
expect(text).toContain('9');
|
|
71
|
+
expect(text).toContain('120k');
|
|
72
|
+
// It must NOT claim to know what was lost — only the counts are checkable.
|
|
73
|
+
expect(text).not.toMatch(/turns? \d+-\d+|removed the/i);
|
|
74
|
+
});
|
|
75
|
+
it('marks an estimate as an estimate', () => {
|
|
76
|
+
// Quoting an estimate as a measurement is the same lie as quoting a
|
|
77
|
+
// summary as an enumeration, in miniature.
|
|
78
|
+
const mapped = toAgentEvent({
|
|
79
|
+
type: 'compaction_completed',
|
|
80
|
+
runId: 'run_1',
|
|
81
|
+
iteration: 3,
|
|
82
|
+
messagesBefore: 10,
|
|
83
|
+
messagesAfter: 4,
|
|
84
|
+
tokensBefore: 9000,
|
|
85
|
+
tokensAfter: 3000,
|
|
86
|
+
measuredBy: 'estimate',
|
|
87
|
+
contextWindowTokens: 200_000,
|
|
88
|
+
windowSource: 'default',
|
|
89
|
+
reachedResetThreshold: false,
|
|
90
|
+
});
|
|
91
|
+
expect(mapped.text).toContain('estimated');
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
describe('the three decline causes get three sentences', () => {
|
|
95
|
+
// Collapsing them into "compaction failed" puts the reader back where the
|
|
96
|
+
// silence did — the same reason a rule denial had to quote the rule.
|
|
97
|
+
function failure(cause, error) {
|
|
98
|
+
const mapped = toAgentEvent({
|
|
99
|
+
type: 'compaction_failed',
|
|
100
|
+
runId: 'run_1',
|
|
101
|
+
iteration: 2,
|
|
102
|
+
cause,
|
|
103
|
+
messages: 31,
|
|
104
|
+
...(error ? { error } : {}),
|
|
105
|
+
});
|
|
106
|
+
expect(mapped).toMatchObject({ kind: 'context', shed: false });
|
|
107
|
+
return mapped.text;
|
|
108
|
+
}
|
|
109
|
+
it('a thrown reducer may work next time, and carries its own error', () => {
|
|
110
|
+
const text = failure('reducer_threw', 'provider returned 400');
|
|
111
|
+
expect(text).toContain('provider returned 400');
|
|
112
|
+
expect(text).toContain('a later pass may succeed');
|
|
113
|
+
});
|
|
114
|
+
it('shedding nothing is a fact, not an error, and will not change', () => {
|
|
115
|
+
const text = failure('shed_nothing');
|
|
116
|
+
expect(text).toContain('later passes will answer the same');
|
|
117
|
+
// Not dressed as a failure: an irreducible history is a true statement
|
|
118
|
+
// about the conversation, and calling it one sends someone hunting a
|
|
119
|
+
// bug that is not there.
|
|
120
|
+
expect(text).not.toMatch(/failed|error/i);
|
|
121
|
+
});
|
|
122
|
+
it('a split tool pair is a reducer bug and suggests no user action', () => {
|
|
123
|
+
const text = failure('split_tool_pair');
|
|
124
|
+
expect(text).toContain('bug in the reducer');
|
|
125
|
+
expect(text).not.toMatch(/try again|later pass|retry/i);
|
|
126
|
+
});
|
|
127
|
+
it('every cause states the history is unchanged', () => {
|
|
128
|
+
for (const cause of ['reducer_threw', 'shed_nothing', 'split_tool_pair']) {
|
|
129
|
+
expect(failure(cause)).toContain('31 messages unchanged');
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
it('no two causes produce the same sentence', () => {
|
|
133
|
+
const texts = ['reducer_threw', 'shed_nothing', 'split_tool_pair'].map((c) => failure(c));
|
|
134
|
+
expect(new Set(texts).size).toBe(3);
|
|
135
|
+
});
|
|
136
|
+
});
|
|
49
137
|
//# sourceMappingURL=to-agent-event.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"to-agent-event.test.js","sourceRoot":"","sources":["../../../src/tui/__tests__/to-agent-event.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAI7C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE1C;;;;;;;;;GASG;AAEH,MAAM,KAAK,GAAG,UAAmB,CAAA;AAEjC,QAAQ,CAAC,6CAA6C,EAAE,GAAG,EAAE;IAC5D,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC7D,MAAM,MAAM,GAAG,YAAY,CAAC;YAC3B,IAAI,EAAE,eAAe;YACrB,KAAK;YACL,MAAM,EAAE,EAAE;YACV,UAAU,EAAE,kBAAkB;SAClB,CAAC,CAAA;QAEd,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,kBAAkB,EAAE,CAAC,CAAA;IACzE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;QACtE,oEAAoE;QACpE,qEAAqE;QACrE,sDAAsD;QACtD,MAAM,MAAM,GAAG,YAAY,CAAC;YAC3B,IAAI,EAAE,eAAe;YACrB,KAAK;YACL,MAAM,EAAE,IAAI;YACZ,UAAU,EAAE,UAAU;SACV,CAAC,CAAA;QAEd,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,CAAA;IACjE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACzD,MAAM,MAAM,GAAG,YAAY,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAc,CAAC,CAAA;QAEvF,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAA;IACzC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QAClD,MAAM,MAAM,GAAG,YAAY,CAAC;YAC3B,IAAI,EAAE,YAAY;YAClB,KAAK;YACL,KAAK,EAAE,MAAM;SACD,CAAC,CAAA;QAEd,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAA;IAC3D,CAAC,CAAC,CAAA;AACH,CAAC,CAAC,CAAA"}
|
|
1
|
+
{"version":3,"file":"to-agent-event.test.js","sourceRoot":"","sources":["../../../src/tui/__tests__/to-agent-event.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAI7C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE1C;;;;;;;;;GASG;AAEH,MAAM,KAAK,GAAG,UAAmB,CAAA;AAEjC,QAAQ,CAAC,6CAA6C,EAAE,GAAG,EAAE;IAC5D,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC7D,MAAM,MAAM,GAAG,YAAY,CAAC;YAC3B,IAAI,EAAE,eAAe;YACrB,KAAK;YACL,MAAM,EAAE,EAAE;YACV,UAAU,EAAE,kBAAkB;SAClB,CAAC,CAAA;QAEd,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,kBAAkB,EAAE,CAAC,CAAA;IACzE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;QACtE,oEAAoE;QACpE,qEAAqE;QACrE,sDAAsD;QACtD,MAAM,MAAM,GAAG,YAAY,CAAC;YAC3B,IAAI,EAAE,eAAe;YACrB,KAAK;YACL,MAAM,EAAE,IAAI;YACZ,UAAU,EAAE,UAAU;SACV,CAAC,CAAA;QAEd,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,CAAA;IACjE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACzD,MAAM,MAAM,GAAG,YAAY,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAc,CAAC,CAAA;QAEvF,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAA;IACzC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QAClD,MAAM,MAAM,GAAG,YAAY,CAAC;YAC3B,IAAI,EAAE,YAAY;YAClB,KAAK;YACL,KAAK,EAAE,MAAM;SACD,CAAC,CAAA;QAEd,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAA;IAC3D,CAAC,CAAC,CAAA;AACH,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,oCAAoC,EAAE,GAAG,EAAE;IACnD,4EAA4E;IAC5E,2EAA2E;IAC3E,2DAA2D;IAC3D,EAAE,CAAC,oEAAoE,EAAE,GAAG,EAAE;QAC7E,MAAM,MAAM,GAAG,YAAY,CAAC;YAC3B,IAAI,EAAE,sBAAsB;YAC5B,KAAK,EAAE,OAAO;YACd,SAAS,EAAE,CAAC;YACZ,cAAc,EAAE,EAAE;YAClB,aAAa,EAAE,CAAC;YAChB,YAAY,EAAE,OAAO;YACrB,WAAW,EAAE,MAAM;YACnB,UAAU,EAAE,UAAU;YACtB,mBAAmB,EAAE,OAAO;YAC5B,YAAY,EAAE,aAAa;YAC3B,qBAAqB,EAAE,IAAI;SAClB,CAAC,CAAA;QAEX,MAAM,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;QAC7D,MAAM,IAAI,GAAI,MAA2B,CAAC,IAAI,CAAA;QAC9C,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;QAC5B,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;QAC3B,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;QAC9B,2EAA2E;QAC3E,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,6BAA6B,CAAC,CAAA;IACxD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC3C,oEAAoE;QACpE,2CAA2C;QAC3C,MAAM,MAAM,GAAG,YAAY,CAAC;YAC3B,IAAI,EAAE,sBAAsB;YAC5B,KAAK,EAAE,OAAO;YACd,SAAS,EAAE,CAAC;YACZ,cAAc,EAAE,EAAE;YAClB,aAAa,EAAE,CAAC;YAChB,YAAY,EAAE,IAAI;YAClB,WAAW,EAAE,IAAI;YACjB,UAAU,EAAE,UAAU;YACtB,mBAAmB,EAAE,OAAO;YAC5B,YAAY,EAAE,SAAS;YACvB,qBAAqB,EAAE,KAAK;SACnB,CAAC,CAAA;QAEX,MAAM,CAAE,MAA2B,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,CAAA;IACjE,CAAC,CAAC,CAAA;AACH,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,8CAA8C,EAAE,GAAG,EAAE;IAC7D,0EAA0E;IAC1E,qEAAqE;IACrE,SAAS,OAAO,CAAC,KAAa,EAAE,KAAc;QAC7C,MAAM,MAAM,GAAG,YAAY,CAAC;YAC3B,IAAI,EAAE,mBAAmB;YACzB,KAAK,EAAE,OAAO;YACd,SAAS,EAAE,CAAC;YACZ,KAAK;YACL,QAAQ,EAAE,EAAE;YACZ,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAClB,CAAC,CAAA;QACX,MAAM,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;QAC9D,OAAQ,MAA2B,CAAC,IAAI,CAAA;IACzC,CAAC;IAED,EAAE,CAAC,gEAAgE,EAAE,GAAG,EAAE;QACzE,MAAM,IAAI,GAAG,OAAO,CAAC,eAAe,EAAE,uBAAuB,CAAC,CAAA;QAE9D,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAA;QAC/C,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,0BAA0B,CAAC,CAAA;IACnD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;QACxE,MAAM,IAAI,GAAG,OAAO,CAAC,cAAc,CAAC,CAAA;QAEpC,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,mCAAmC,CAAC,CAAA;QAC3D,uEAAuE;QACvE,qEAAqE;QACrE,yBAAyB;QACzB,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,CAAA;IAC1C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,gEAAgE,EAAE,GAAG,EAAE;QACzE,MAAM,IAAI,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAA;QAEvC,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAA;QAC5C,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,6BAA6B,CAAC,CAAA;IACxD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACtD,KAAK,MAAM,KAAK,IAAI,CAAC,eAAe,EAAE,cAAc,EAAE,iBAAiB,CAAC,EAAE,CAAC;YAC1E,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAA;QAC1D,CAAC;IACF,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QAClD,MAAM,KAAK,GAAG,CAAC,eAAe,EAAE,cAAc,EAAE,iBAAiB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAA;QAEzF,MAAM,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACpC,CAAC,CAAC,CAAA;AACH,CAAC,CAAC,CAAA"}
|
|
@@ -14,12 +14,6 @@ import { tmpdir } from 'node:os';
|
|
|
14
14
|
import { join } from 'node:path';
|
|
15
15
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
16
16
|
import { getBuiltinTools } from '@namzu/sdk';
|
|
17
|
-
// The clawtool catalog is a live probe of another process. Nothing here is
|
|
18
|
-
// about it, and an absent daemon costs the load timeout, so it is stubbed to
|
|
19
|
-
// the empty catalog it degrades to anyway.
|
|
20
|
-
vi.mock('../../integrations/clawtool/tooling.js', () => ({
|
|
21
|
-
loadClawtoolToolDefinitions: vi.fn(async () => []),
|
|
22
|
-
}));
|
|
23
17
|
// Only `query` is replaced; everything else the module under test imports —
|
|
24
18
|
// the tool registry, the disk stores, the provider registry the vendor package
|
|
25
19
|
// registers into — stays real, because a fake of those would not be able to
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"working-directory.test.js","sourceRoot":"","sources":["../../../src/tui/__tests__/working-directory.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAExE,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAK5C,
|
|
1
|
+
{"version":3,"file":"working-directory.test.js","sourceRoot":"","sources":["../../../src/tui/__tests__/working-directory.test.ts"],"names":[],"mappings":"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"}
|
package/dist/tui/agent.d.ts
CHANGED
|
@@ -46,6 +46,22 @@ export type AgentEvent = {
|
|
|
46
46
|
readonly kind: 'usage';
|
|
47
47
|
readonly totalTokens: number;
|
|
48
48
|
readonly costUsd: number;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Context was discarded, or an attempt to discard it declined.
|
|
52
|
+
*
|
|
53
|
+
* Everything else this session fixed was the run quietly not doing what the
|
|
54
|
+
* operator asked. This is the same class with the opposite sign: the run
|
|
55
|
+
* quietly doing something they did not ask for. Compaction deletes messages
|
|
56
|
+
* irrecoverably, and the first time a user learned it existed was when the
|
|
57
|
+
* agent had forgotten something they were relying on — which reads as the
|
|
58
|
+
* model being stupid rather than the harness dropping context.
|
|
59
|
+
*/
|
|
60
|
+
| {
|
|
61
|
+
readonly kind: 'context';
|
|
62
|
+
readonly text: string;
|
|
63
|
+
/** False when the compaction declined and the history is unchanged. */
|
|
64
|
+
readonly shed: boolean;
|
|
49
65
|
} | {
|
|
50
66
|
readonly kind: 'task';
|
|
51
67
|
readonly subject: string;
|
|
@@ -108,8 +124,6 @@ export interface AgentSession {
|
|
|
108
124
|
readonly providerSummary: string | null;
|
|
109
125
|
readonly modelSummary: string | null;
|
|
110
126
|
readonly toolNames: readonly string[];
|
|
111
|
-
/** Count of clawtool tools registered deferred (loadable via search_tools). */
|
|
112
|
-
readonly deferredToolCount: number;
|
|
113
127
|
readonly errorHint: string | null;
|
|
114
128
|
send(messages: readonly Message[], opts?: SendOptions): AsyncIterable<AgentEvent>;
|
|
115
129
|
}
|
package/dist/tui/agent.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/tui/agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAKN,KAAK,OAAO,EACZ,KAAK,SAAS,EAEd,KAAK,aAAa,EAClB,KAAK,QAAQ,EAGb,KAAK,SAAS,EACd,KAAK,UAAU,EAGf,KAAK,QAAQ,EACb,KAAK,QAAQ,EACb,KAAK,eAAe,EAEpB,KAAK,gBAAgB,EAIrB,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/tui/agent.ts"],"names":[],"mappings":"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"}
|
package/dist/tui/agent.js
CHANGED
|
@@ -22,7 +22,6 @@
|
|
|
22
22
|
*/
|
|
23
23
|
import { DiskMemoryStore, DiskTaskStore, ProviderRegistry, SearchToolsTool, ToolRegistry, buildMemoryTools, getBuiltinTools, query, } from '@namzu/sdk';
|
|
24
24
|
import { join } from 'node:path';
|
|
25
|
-
import { loadClawtoolToolDefinitions } from '../integrations/clawtool/tooling.js';
|
|
26
25
|
import { PROVIDER_REGISTRY, discoverProviders, ensureFreshAnthropicToken, findDetected, isAnthropicOAuthToken, readAgentKeychainCredential, readPreferences, } from '../integrations/providers/index.js';
|
|
27
26
|
import { createSubagentRuntime } from '../integrations/subagents/runtime.js';
|
|
28
27
|
import { composeMemoryPrompt, readMemory } from '../memory/store.js';
|
|
@@ -96,7 +95,7 @@ const NAMZU_IDENTITY = [
|
|
|
96
95
|
'- Never invent file paths, command output, URLs, research findings, or results. If you announce an action ("running…", "delegating…"), you MUST immediately make the tool call — do not narrate an action and then skip it.',
|
|
97
96
|
'- If a capability or tool is unavailable (e.g. no web access, a tool is missing, a sub-agent failed), say so plainly and stop — do not improvise a fake result.',
|
|
98
97
|
'- When you delegate with the `Agent` tool, report only what the sub-agent actually returned in its tool result; if it wrote files, verify with a tool before claiming paths.',
|
|
99
|
-
'- A reply from a tool that delegates to ANOTHER agent (
|
|
98
|
+
'- A reply from a tool that delegates to ANOTHER agent (a connector that runs another agent, an A2A `tasks/send`, a remote peer) is that agent\'s unverified CLAIM, not fact — another model can hallucinate. If it says it ran a command, wrote a file, or "here is the output", treat that as narrative and confirm it yourself with a deterministic tool (a real shell like `bash.run`, a file read) before reporting it as done. Distinguish such conversational agent calls from deterministic tools, and never present another agent\'s prose as your own verified result.',
|
|
100
99
|
].join('\n');
|
|
101
100
|
function buildToolRegistry(cwd) {
|
|
102
101
|
const registry = new ToolRegistry();
|
|
@@ -106,8 +105,14 @@ function buildToolRegistry(cwd) {
|
|
|
106
105
|
// MEMORY.md that's injected into the prompt).
|
|
107
106
|
const memoryStore = new DiskMemoryStore({ baseDir: join(cwd, '.namzu') });
|
|
108
107
|
registry.register(buildMemoryTools(memoryStore, memoryStore.getIndex()));
|
|
109
|
-
// `search_tools`
|
|
110
|
-
|
|
108
|
+
// `search_tools` is deliberately NOT registered here. It is only useful
|
|
109
|
+
// where deferred tools exist, and that differs between this function's two
|
|
110
|
+
// callers: the session below passes a `taskStore`, so query() registers the
|
|
111
|
+
// task tools deferred and the search has a roster; a sub-agent is built with
|
|
112
|
+
// no task store, so its registry has nothing deferred and the tool could
|
|
113
|
+
// only ever answer "no deferred tools matching X" — a capability advertised
|
|
114
|
+
// every turn that costs a turn to discover is unusable. Mounting it is the
|
|
115
|
+
// caller's decision, made where the roster is known.
|
|
111
116
|
return registry;
|
|
112
117
|
}
|
|
113
118
|
export async function createAgentSession(prefs, detected, options = {}) {
|
|
@@ -164,13 +169,9 @@ export async function createAgentSession(prefs, detected, options = {}) {
|
|
|
164
169
|
}
|
|
165
170
|
};
|
|
166
171
|
const registry = buildToolRegistry(cwd);
|
|
167
|
-
//
|
|
168
|
-
//
|
|
169
|
-
|
|
170
|
-
// down / slow clawtool just yields zero deferred tools, non-fatal.
|
|
171
|
-
const clawtoolTools = await loadClawtoolToolDefinitions({ skipNames: registry.listNames() });
|
|
172
|
-
if (clawtoolTools.length > 0)
|
|
173
|
-
registry.register(clawtoolTools, 'deferred');
|
|
172
|
+
// This session passes a `taskStore` to query() below, which registers the
|
|
173
|
+
// task tools deferred — so `search_tools` has something to find here.
|
|
174
|
+
registry.register([SearchToolsTool]);
|
|
174
175
|
// Native sub-agents: register the canonical `Agent` tool so the model can
|
|
175
176
|
// delegate a self-contained task to a fresh sub-agent (own context window).
|
|
176
177
|
// Best-effort — if the runtime can't stand up, the chat still works.
|
|
@@ -186,14 +187,10 @@ export async function createAgentSession(prefs, detected, options = {}) {
|
|
|
186
187
|
model,
|
|
187
188
|
buildProvider: () => constructProvider(prefs.provider, det ? { ...det, apiKey: currentToken ?? det.apiKey } : det, model),
|
|
188
189
|
buildTools: () => {
|
|
189
|
-
// Sub-agents get the
|
|
190
|
-
//
|
|
191
|
-
//
|
|
192
|
-
|
|
193
|
-
const r = buildToolRegistry(cwd);
|
|
194
|
-
if (clawtoolTools.length > 0)
|
|
195
|
-
r.register(clawtoolTools, 'deferred');
|
|
196
|
-
return r;
|
|
190
|
+
// Sub-agents get the parent's working set minus `search_tools`:
|
|
191
|
+
// they run without a task store, so nothing in their registry is
|
|
192
|
+
// deferred and there is nothing for a search to load.
|
|
193
|
+
return buildToolRegistry(cwd);
|
|
197
194
|
},
|
|
198
195
|
verificationGate: gateFor(options.rules),
|
|
199
196
|
onEvent: (e) => {
|
|
@@ -209,10 +206,14 @@ export async function createAgentSession(prefs, detected, options = {}) {
|
|
|
209
206
|
// Sub-agents unavailable this session — non-fatal.
|
|
210
207
|
}
|
|
211
208
|
const activeToolNames = registry.getCallableTools().map((t) => t.name);
|
|
212
|
-
|
|
213
|
-
//
|
|
214
|
-
//
|
|
215
|
-
//
|
|
209
|
+
// Task store → query registers task_create / task_update / task_list as
|
|
210
|
+
// DEFERRED tools and emits task_created/task_updated, so the agent can track
|
|
211
|
+
// a plan for the current request. Tasks are run-scoped.
|
|
212
|
+
//
|
|
213
|
+
// "Deferred" is why this session mounts `search_tools` above: these three are
|
|
214
|
+
// the roster it searches. They are registered inside query(), after this
|
|
215
|
+
// function returns, which is why the connect line reports no count of them —
|
|
216
|
+
// counting here would mean restating query's registration order in the CLI.
|
|
216
217
|
const taskStore = new DiskTaskStore({
|
|
217
218
|
baseDir: join(cwd, '.namzu'),
|
|
218
219
|
defaultRunId: 'run_namzu-cli',
|
|
@@ -226,7 +227,6 @@ export async function createAgentSession(prefs, detected, options = {}) {
|
|
|
226
227
|
providerSummary: entry.label,
|
|
227
228
|
modelSummary: model,
|
|
228
229
|
toolNames: activeToolNames,
|
|
229
|
-
deferredToolCount,
|
|
230
230
|
errorHint: null,
|
|
231
231
|
send: async function* (messages, opts) {
|
|
232
232
|
// Renew a lapsed OAuth token before the turn runs (no-op for valid
|
|
@@ -404,7 +404,11 @@ async function* runTurn({ provider, model, tools, scope, workingDirectory, rules
|
|
|
404
404
|
tools,
|
|
405
405
|
taskStore,
|
|
406
406
|
...(taskGateway ? { taskGateway } : {}),
|
|
407
|
-
|
|
407
|
+
// `gateFor`, not the bare default: the default's `rules` is a hardcoded
|
|
408
|
+
// empty array, so passing it here discarded the operator's rules on the
|
|
409
|
+
// path that runs every top-level turn. The sub-agent path called
|
|
410
|
+
// `gateFor` and this one did not.
|
|
411
|
+
verificationGate: gateFor(rules),
|
|
408
412
|
compactionConfig: COMPACTION_CONFIG,
|
|
409
413
|
// The CLI owns its process end to end, so it can safely hand the
|
|
410
414
|
// termination path to the kernel: a Ctrl-C mid-run now leaves a
|
|
@@ -513,7 +517,7 @@ export function makeResumeHandler(approval, onPermission, mode = onPermission ?
|
|
|
513
517
|
/**
|
|
514
518
|
* Tools known to only observe, never mutate. Anything NOT in this set
|
|
515
519
|
* prompts for approval (safe-by-default: unknown and future tools — e.g.
|
|
516
|
-
* bridged
|
|
520
|
+
* bridged connector tools — are treated as needing consent). Matched
|
|
517
521
|
* case-insensitively so `Read`/`read` both count.
|
|
518
522
|
*/
|
|
519
523
|
const READ_ONLY_TOOLS = new Set([
|
|
@@ -593,10 +597,60 @@ export function toAgentEvent(event) {
|
|
|
593
597
|
kind: 'error',
|
|
594
598
|
message: event.failure ? `[${event.failure.code}] ${event.error}` : event.error,
|
|
595
599
|
};
|
|
600
|
+
case 'compaction_completed':
|
|
601
|
+
return { kind: 'context', text: describeCompaction(event), shed: true };
|
|
602
|
+
case 'compaction_failed':
|
|
603
|
+
return { kind: 'context', text: describeCompactionFailure(event), shed: false };
|
|
596
604
|
default:
|
|
597
605
|
return null;
|
|
598
606
|
}
|
|
599
607
|
}
|
|
608
|
+
/**
|
|
609
|
+
* What a completed compaction may honestly claim.
|
|
610
|
+
*
|
|
611
|
+
* Only what is checkable: which counts became which. Compaction summarises, so
|
|
612
|
+
* it cannot enumerate what was lost — the loss is fidelity, not a set of
|
|
613
|
+
* removable items, and "removed the file contents from turns 3-8" is a claim
|
|
614
|
+
* that cannot be substantiated and is worse than silence the first time it is
|
|
615
|
+
* subtly wrong.
|
|
616
|
+
*
|
|
617
|
+
* `measuredBy` is carried for the same reason: an estimate quoted as a
|
|
618
|
+
* measurement is that same lie in miniature, and the kernel already knows which
|
|
619
|
+
* it had.
|
|
620
|
+
*/
|
|
621
|
+
function describeCompaction(event) {
|
|
622
|
+
const k = (n) => (n >= 1000 ? `${Math.round(n / 1000)}k` : String(n));
|
|
623
|
+
const qualifier = event.measuredBy === 'estimate' ? ' (estimated)' : '';
|
|
624
|
+
return `context compacted — ${event.messagesBefore} messages replaced by ${event.messagesAfter}, ~${k(event.tokensBefore)} → ~${k(event.tokensAfter)} tokens${qualifier}`;
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* What a declined compaction says, which is three different things.
|
|
628
|
+
*
|
|
629
|
+
* Collapsing them into "compaction failed" would put the reader back where the
|
|
630
|
+
* silence did — the same reason a rule denial had to quote the rule rather than
|
|
631
|
+
* name its type. One may work next pass, one will decline identically forever,
|
|
632
|
+
* and one is a bug in the reducer with no user action at all.
|
|
633
|
+
*
|
|
634
|
+
* Every case states that the history is unchanged, because the kernel installs
|
|
635
|
+
* a reduction whole or not at all. That is a fact worth giving the reader
|
|
636
|
+
* rather than making them wonder what survived.
|
|
637
|
+
*/
|
|
638
|
+
function describeCompactionFailure(event) {
|
|
639
|
+
const held = `${event.messages} messages unchanged`;
|
|
640
|
+
switch (event.cause) {
|
|
641
|
+
case 'reducer_threw':
|
|
642
|
+
return `context not compacted — the reducer failed${event.error ? `: ${event.error}` : ''}. ${held}; a later pass may succeed`;
|
|
643
|
+
case 'shed_nothing':
|
|
644
|
+
// Deliberately not phrased as an error. An irreducible history is a
|
|
645
|
+
// true statement about the conversation, and dressing it as a
|
|
646
|
+
// failure sends someone looking for a bug that is not there.
|
|
647
|
+
return `context could not be reduced further — nothing left to shed. ${held}; later passes will answer the same`;
|
|
648
|
+
case 'split_tool_pair':
|
|
649
|
+
// No suggested action, because there is none for the user. Offering
|
|
650
|
+
// one would be worse than silence.
|
|
651
|
+
return `context not compacted — the reducer produced a history splitting a tool call from its result, so it was refused. ${held}; this is a bug in the reducer`;
|
|
652
|
+
}
|
|
653
|
+
}
|
|
600
654
|
/** Render a sub-agent's tool steps as a `├─/└─` tree for the Agent result. */
|
|
601
655
|
function asTree(steps) {
|
|
602
656
|
return steps.map((s, i) => `${i === steps.length - 1 ? '└─' : '├─'} ${s}`);
|
|
@@ -673,7 +727,7 @@ export function toolStartDetail(toolName, input) {
|
|
|
673
727
|
return undefined;
|
|
674
728
|
const obj = input;
|
|
675
729
|
const str = (k) => (typeof obj[k] === 'string' ? obj[k] : undefined);
|
|
676
|
-
const name = toolName.toLowerCase()
|
|
730
|
+
const name = toolName.toLowerCase();
|
|
677
731
|
if (name === 'write') {
|
|
678
732
|
const content = str('content');
|
|
679
733
|
return content !== undefined ? clampLines(content) : undefined;
|
|
@@ -692,7 +746,7 @@ export function toolStartDetail(toolName, input) {
|
|
|
692
746
|
}
|
|
693
747
|
return undefined;
|
|
694
748
|
}
|
|
695
|
-
/** Parse a string as a JSON object, or null.
|
|
749
|
+
/** Parse a string as a JSON object, or null. Connector tools return JSON. */
|
|
696
750
|
function parseJsonObject(s) {
|
|
697
751
|
const t = s.trim();
|
|
698
752
|
if (!(t.startsWith('{') || t.startsWith('[')))
|
|
@@ -745,7 +799,7 @@ function resultToLines(result) {
|
|
|
745
799
|
* results are pretty-printed / unwrapped so they don't read as a raw blob.
|
|
746
800
|
*/
|
|
747
801
|
export function toolEndDetail(toolName, result) {
|
|
748
|
-
const name = toolName.toLowerCase()
|
|
802
|
+
const name = toolName.toLowerCase();
|
|
749
803
|
if (name === 'edit' || name === 'write')
|
|
750
804
|
return undefined;
|
|
751
805
|
if (result.trim().length === 0)
|
|
@@ -778,7 +832,6 @@ function emptySession(errorHint) {
|
|
|
778
832
|
providerSummary: null,
|
|
779
833
|
modelSummary: null,
|
|
780
834
|
toolNames: [],
|
|
781
|
-
deferredToolCount: 0,
|
|
782
835
|
errorHint,
|
|
783
836
|
send: async function* () {
|
|
784
837
|
yield { kind: 'error', message: errorHint };
|