@namzu/sdk 5.0.0 → 5.2.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/CHANGELOG.md +463 -0
- package/README.md +2 -2
- package/dist/agents/__tests__/run-agent-forwarding.test.d.ts +2 -0
- package/dist/agents/__tests__/run-agent-forwarding.test.d.ts.map +1 -0
- package/dist/agents/__tests__/run-agent-forwarding.test.js +76 -0
- package/dist/agents/__tests__/run-agent-forwarding.test.js.map +1 -0
- package/dist/agents/__tests__/run-completed-stop-reason.test.d.ts +2 -0
- package/dist/agents/__tests__/run-completed-stop-reason.test.d.ts.map +1 -0
- package/dist/agents/__tests__/run-completed-stop-reason.test.js +50 -0
- package/dist/agents/__tests__/run-completed-stop-reason.test.js.map +1 -0
- package/dist/agents/index.d.ts +1 -0
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js +4 -0
- package/dist/agents/index.js.map +1 -1
- package/dist/agents/runAgent.d.ts +34 -0
- package/dist/agents/runAgent.d.ts.map +1 -1
- package/dist/agents/runAgent.js +5 -3
- package/dist/agents/runAgent.js.map +1 -1
- package/dist/config/runtime.d.ts +30 -30
- package/dist/constants/tools/__tests__/dangerous-patterns.test.d.ts +2 -0
- package/dist/constants/tools/__tests__/dangerous-patterns.test.d.ts.map +1 -0
- package/dist/constants/tools/__tests__/dangerous-patterns.test.js +54 -0
- package/dist/constants/tools/__tests__/dangerous-patterns.test.js.map +1 -0
- package/dist/constants/tools/index.d.ts.map +1 -1
- package/dist/constants/tools/index.js +28 -1
- package/dist/constants/tools/index.js.map +1 -1
- package/dist/contracts/a2a.d.ts +44 -44
- package/dist/directory/__tests__/derive.test.d.ts +2 -0
- package/dist/directory/__tests__/derive.test.d.ts.map +1 -0
- package/dist/directory/__tests__/derive.test.js +111 -0
- package/dist/directory/__tests__/derive.test.js.map +1 -0
- package/dist/directory/__tests__/load-diagnostics.test.d.ts +2 -0
- package/dist/directory/__tests__/load-diagnostics.test.d.ts.map +1 -0
- package/dist/directory/__tests__/load-diagnostics.test.js +106 -0
- package/dist/directory/__tests__/load-diagnostics.test.js.map +1 -0
- package/dist/directory/__tests__/load-directory.test.d.ts +2 -0
- package/dist/directory/__tests__/load-directory.test.d.ts.map +1 -0
- package/dist/directory/__tests__/load-directory.test.js +196 -0
- package/dist/directory/__tests__/load-directory.test.js.map +1 -0
- package/dist/directory/__tests__/subagents.test.d.ts +2 -0
- package/dist/directory/__tests__/subagents.test.d.ts.map +1 -0
- package/dist/directory/__tests__/subagents.test.js +117 -0
- package/dist/directory/__tests__/subagents.test.js.map +1 -0
- package/dist/directory/__tests__/supervisor-budget.test.d.ts +2 -0
- package/dist/directory/__tests__/supervisor-budget.test.d.ts.map +1 -0
- package/dist/directory/__tests__/supervisor-budget.test.js +97 -0
- package/dist/directory/__tests__/supervisor-budget.test.js.map +1 -0
- package/dist/directory/derive-supervisor.d.ts +58 -0
- package/dist/directory/derive-supervisor.d.ts.map +1 -0
- package/dist/directory/derive-supervisor.js +88 -0
- package/dist/directory/derive-supervisor.js.map +1 -0
- package/dist/directory/derive.d.ts +12 -0
- package/dist/directory/derive.d.ts.map +1 -0
- package/dist/directory/derive.js +58 -0
- package/dist/directory/derive.js.map +1 -0
- package/dist/directory/index.d.ts +7 -0
- package/dist/directory/index.d.ts.map +1 -0
- package/dist/directory/index.js +5 -0
- package/dist/directory/index.js.map +1 -0
- package/dist/directory/load.d.ts +14 -0
- package/dist/directory/load.d.ts.map +1 -0
- package/dist/directory/load.js +488 -0
- package/dist/directory/load.js.map +1 -0
- package/dist/directory/scan.d.ts +36 -0
- package/dist/directory/scan.d.ts.map +1 -0
- package/dist/directory/scan.js +136 -0
- package/dist/directory/scan.js.map +1 -0
- package/dist/directory/types.d.ts +215 -0
- package/dist/directory/types.d.ts.map +1 -0
- package/dist/directory/types.js +8 -0
- package/dist/directory/types.js.map +1 -0
- package/dist/plugin/__tests__/path-containment.test.d.ts +2 -0
- package/dist/plugin/__tests__/path-containment.test.d.ts.map +1 -0
- package/dist/plugin/__tests__/path-containment.test.js +91 -0
- package/dist/plugin/__tests__/path-containment.test.js.map +1 -0
- package/dist/plugin/lifecycle.d.ts.map +1 -1
- package/dist/plugin/lifecycle.js +3 -3
- package/dist/plugin/lifecycle.js.map +1 -1
- package/dist/plugin/loader.d.ts.map +1 -1
- package/dist/plugin/loader.js +12 -2
- package/dist/plugin/loader.js.map +1 -1
- package/dist/provider/__tests__/model-version.test.d.ts +2 -0
- package/dist/provider/__tests__/model-version.test.d.ts.map +1 -0
- package/dist/provider/__tests__/model-version.test.js +80 -0
- package/dist/provider/__tests__/model-version.test.js.map +1 -0
- package/dist/provider/__tests__/strict-schema.test.d.ts +2 -0
- package/dist/provider/__tests__/strict-schema.test.d.ts.map +1 -0
- package/dist/provider/__tests__/strict-schema.test.js +109 -0
- package/dist/provider/__tests__/strict-schema.test.js.map +1 -0
- package/dist/provider/__tests__/typed-error-classification.test.d.ts +2 -0
- package/dist/provider/__tests__/typed-error-classification.test.d.ts.map +1 -0
- package/dist/provider/__tests__/typed-error-classification.test.js +123 -0
- package/dist/provider/__tests__/typed-error-classification.test.js.map +1 -0
- package/dist/provider/model-version.d.ts +60 -0
- package/dist/provider/model-version.d.ts.map +1 -0
- package/dist/provider/model-version.js +64 -0
- package/dist/provider/model-version.js.map +1 -0
- package/dist/provider/retry.d.ts.map +1 -1
- package/dist/provider/retry.js +23 -7
- package/dist/provider/retry.js.map +1 -1
- package/dist/provider/strict-schema.d.ts +49 -0
- package/dist/provider/strict-schema.d.ts.map +1 -0
- package/dist/provider/strict-schema.js +112 -0
- package/dist/provider/strict-schema.js.map +1 -0
- package/dist/public-runtime.d.ts +6 -1
- package/dist/public-runtime.d.ts.map +1 -1
- package/dist/public-runtime.js +21 -1
- package/dist/public-runtime.js.map +1 -1
- package/dist/public-tools.d.ts +1 -0
- package/dist/public-tools.d.ts.map +1 -1
- package/dist/public-tools.js +4 -0
- package/dist/public-tools.js.map +1 -1
- package/dist/public-types.d.ts +2 -0
- package/dist/public-types.d.ts.map +1 -1
- package/dist/registry/tool/__tests__/strict-registration.test.d.ts +2 -0
- package/dist/registry/tool/__tests__/strict-registration.test.d.ts.map +1 -0
- package/dist/registry/tool/__tests__/strict-registration.test.js +82 -0
- package/dist/registry/tool/__tests__/strict-registration.test.js.map +1 -0
- package/dist/registry/tool/execute.d.ts.map +1 -1
- package/dist/registry/tool/execute.js +16 -0
- package/dist/registry/tool/execute.js.map +1 -1
- package/dist/runtime/query/__tests__/stream-recovery.test.js +5 -0
- package/dist/runtime/query/__tests__/stream-recovery.test.js.map +1 -1
- package/dist/runtime/query/result.d.ts.map +1 -1
- package/dist/runtime/query/result.js +5 -0
- package/dist/runtime/query/result.js.map +1 -1
- package/dist/tools/builtins/__tests__/edit-insert-reachable.test.js +7 -1
- package/dist/tools/builtins/__tests__/edit-insert-reachable.test.js.map +1 -1
- package/dist/tools/builtins/__tests__/edit.test.js +1 -1
- package/dist/tools/builtins/__tests__/edit.test.js.map +1 -1
- package/dist/tools/builtins/edit.d.ts.map +1 -1
- package/dist/tools/builtins/edit.js +20 -2
- package/dist/tools/builtins/edit.js.map +1 -1
- package/dist/types/plugin/index.d.ts +4 -4
- package/dist/types/provider/errors.d.ts +0 -17
- package/dist/types/provider/errors.d.ts.map +1 -1
- package/dist/types/provider/errors.js +60 -0
- package/dist/types/provider/errors.js.map +1 -1
- package/dist/types/run/events.d.ts +17 -2
- package/dist/types/run/events.d.ts.map +1 -1
- package/dist/types/run/events.js.map +1 -1
- package/dist/types/verification/index.d.ts +6 -6
- package/package.json +1 -1
- package/src/agents/__tests__/run-agent-forwarding.test.ts +85 -0
- package/src/agents/__tests__/run-completed-stop-reason.test.ts +59 -0
- package/src/agents/index.ts +8 -0
- package/src/agents/runAgent.ts +30 -4
- package/src/constants/tools/__tests__/dangerous-patterns.test.ts +62 -0
- package/src/constants/tools/index.ts +28 -1
- package/src/directory/__tests__/derive.test.ts +135 -0
- package/src/directory/__tests__/load-diagnostics.test.ts +126 -0
- package/src/directory/__tests__/load-directory.test.ts +243 -0
- package/src/directory/__tests__/subagents.test.ts +155 -0
- package/src/directory/__tests__/supervisor-budget.test.ts +117 -0
- package/src/directory/derive-supervisor.ts +149 -0
- package/src/directory/derive.ts +70 -0
- package/src/directory/index.ts +27 -0
- package/src/directory/load.ts +556 -0
- package/src/directory/scan.ts +163 -0
- package/src/directory/types.ts +254 -0
- package/src/plugin/__tests__/path-containment.test.ts +107 -0
- package/src/plugin/lifecycle.ts +3 -3
- package/src/plugin/loader.ts +12 -2
- package/src/provider/__tests__/model-version.test.ts +93 -0
- package/src/provider/__tests__/strict-schema.test.ts +133 -0
- package/src/provider/__tests__/typed-error-classification.test.ts +143 -0
- package/src/provider/model-version.ts +98 -0
- package/src/provider/retry.ts +23 -7
- package/src/provider/strict-schema.ts +125 -0
- package/src/public-runtime.ts +31 -0
- package/src/public-tools.ts +4 -0
- package/src/public-types.ts +8 -0
- package/src/registry/tool/__tests__/strict-registration.test.ts +115 -0
- package/src/registry/tool/execute.ts +16 -0
- package/src/runtime/query/__tests__/stream-recovery.test.ts +5 -0
- package/src/runtime/query/result.ts +5 -0
- package/src/tools/builtins/__tests__/edit-insert-reachable.test.ts +8 -2
- package/src/tools/builtins/__tests__/edit.test.ts +1 -1
- package/src/tools/builtins/edit.ts +20 -2
- package/src/types/provider/errors.ts +71 -0
- package/src/types/run/events.ts +15 -2
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { mkdirSync, mkdtempSync, symlinkSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { tmpdir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { describe, expect, it } from 'vitest';
|
|
5
|
+
import { loadDirectory } from '../load.js';
|
|
6
|
+
/**
|
|
7
|
+
* Every case builds a real directory and reads it. A fixture object standing
|
|
8
|
+
* in for the filesystem would pass while the scan, the import and the
|
|
9
|
+
* containment check all did the wrong thing — and the whole package is those
|
|
10
|
+
* three things.
|
|
11
|
+
*
|
|
12
|
+
* `.js` is used for tool files rather than `.ts`. Node's type stripping is
|
|
13
|
+
* real and the loader accepts both, but a test that depends on it would be
|
|
14
|
+
* testing Node's version rather than this code.
|
|
15
|
+
*/
|
|
16
|
+
const CAN_SYMLINK = (() => {
|
|
17
|
+
try {
|
|
18
|
+
const probe = mkdtempSync(join(tmpdir(), 'namzu-proj-sym-'));
|
|
19
|
+
symlinkSync(probe, join(probe, 'self'), 'dir');
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
})();
|
|
26
|
+
function project(files) {
|
|
27
|
+
const root = mkdtempSync(join(tmpdir(), 'namzu-proj-'));
|
|
28
|
+
for (const [relative, body] of Object.entries(files)) {
|
|
29
|
+
const full = join(root, relative);
|
|
30
|
+
mkdirSync(join(full, '..'), { recursive: true });
|
|
31
|
+
writeFileSync(full, body);
|
|
32
|
+
}
|
|
33
|
+
return root;
|
|
34
|
+
}
|
|
35
|
+
const TOOL = (name) => `
|
|
36
|
+
export default {
|
|
37
|
+
name: ${JSON.stringify(name)},
|
|
38
|
+
description: 'a tool',
|
|
39
|
+
inputSchema: { parse: (v) => v, safeParse: (v) => ({ success: true, data: v }) },
|
|
40
|
+
execute: async () => ({ success: true, output: 'ok' }),
|
|
41
|
+
}
|
|
42
|
+
`;
|
|
43
|
+
describe('reading a project directory', () => {
|
|
44
|
+
it('loads instructions, config and tools', async () => {
|
|
45
|
+
const root = project({
|
|
46
|
+
'instructions.md': 'You are helpful.\n',
|
|
47
|
+
'agent.js': 'export default { model: "m", temperature: 0.2 }',
|
|
48
|
+
'tools/search.js': TOOL('search'),
|
|
49
|
+
});
|
|
50
|
+
const { manifest, ok, diagnostics } = await loadDirectory(root);
|
|
51
|
+
expect(ok, JSON.stringify(diagnostics)).toBe(true);
|
|
52
|
+
expect(manifest.instructions).toBe('You are helpful.');
|
|
53
|
+
expect(manifest.config).toMatchObject({ model: 'm', temperature: 0.2 });
|
|
54
|
+
expect(manifest.tools.map((t) => t.definition.name)).toEqual(['search']);
|
|
55
|
+
});
|
|
56
|
+
it('reports a broken tool instead of dropping it', async () => {
|
|
57
|
+
const root = project({
|
|
58
|
+
'instructions.md': 'hi',
|
|
59
|
+
'tools/good.js': TOOL('good'),
|
|
60
|
+
'tools/broken.js': 'this is not valid javascript !!!',
|
|
61
|
+
});
|
|
62
|
+
const { manifest, ok, diagnostics } = await loadDirectory(root);
|
|
63
|
+
expect(ok).toBe(false);
|
|
64
|
+
// The good one still loaded — one bad file does not lose the rest.
|
|
65
|
+
expect(manifest.tools.map((t) => t.definition.name)).toEqual(['good']);
|
|
66
|
+
const failure = diagnostics.find((d) => d.code === 'module_load_failed');
|
|
67
|
+
expect(failure?.path).toContain('broken');
|
|
68
|
+
expect(manifest.sources.find((s) => s.id === 'broken')?.outcome).toBe('failed');
|
|
69
|
+
});
|
|
70
|
+
it('refuses both files when two tools claim one name', async () => {
|
|
71
|
+
const root = project({
|
|
72
|
+
'instructions.md': 'hi',
|
|
73
|
+
'tools/a.js': TOOL('search'),
|
|
74
|
+
'tools/b.js': TOOL('search'),
|
|
75
|
+
});
|
|
76
|
+
const { manifest, ok, diagnostics } = await loadDirectory(root);
|
|
77
|
+
expect(ok).toBe(false);
|
|
78
|
+
expect(diagnostics.some((d) => d.code === 'duplicate_tool_name')).toBe(true);
|
|
79
|
+
// Picking a winner silently is what hides the mistake.
|
|
80
|
+
expect(manifest.tools).toHaveLength(1);
|
|
81
|
+
});
|
|
82
|
+
it('rejects a default export that is not a tool', async () => {
|
|
83
|
+
const root = project({
|
|
84
|
+
'instructions.md': 'hi',
|
|
85
|
+
'tools/x.js': 'export default { hello: 1 }',
|
|
86
|
+
});
|
|
87
|
+
const { ok, diagnostics } = await loadDirectory(root);
|
|
88
|
+
expect(ok).toBe(false);
|
|
89
|
+
expect(diagnostics.some((d) => d.code === 'not_a_tool')).toBe(true);
|
|
90
|
+
});
|
|
91
|
+
it('warns rather than errors when instructions are absent', async () => {
|
|
92
|
+
// `runAgent` treats instructions as optional; this package does not get
|
|
93
|
+
// to overrule the kernel about what a valid agent is.
|
|
94
|
+
const root = project({ 'tools/a.js': TOOL('a') });
|
|
95
|
+
const { ok, diagnostics } = await loadDirectory(root);
|
|
96
|
+
expect(ok).toBe(true);
|
|
97
|
+
expect(diagnostics.find((d) => d.code === 'instructions_missing')?.severity).toBe('warning');
|
|
98
|
+
});
|
|
99
|
+
it('errors on an instructions file that says nothing', async () => {
|
|
100
|
+
const root = project({ 'instructions.md': ' \n' });
|
|
101
|
+
const { ok, diagnostics } = await loadDirectory(root);
|
|
102
|
+
expect(ok).toBe(false);
|
|
103
|
+
expect(diagnostics.find((d) => d.code === 'instructions_empty')?.severity).toBe('error');
|
|
104
|
+
});
|
|
105
|
+
it('reports a malformed config field by name', async () => {
|
|
106
|
+
const root = project({
|
|
107
|
+
'instructions.md': 'hi',
|
|
108
|
+
'agent.js': 'export default { model: 42 }',
|
|
109
|
+
});
|
|
110
|
+
const { ok, diagnostics } = await loadDirectory(root);
|
|
111
|
+
expect(ok).toBe(false);
|
|
112
|
+
expect(diagnostics.find((d) => d.code === 'invalid_config')?.message).toContain('"model"');
|
|
113
|
+
});
|
|
114
|
+
it('ignores dot- and underscore-prefixed entries silently', async () => {
|
|
115
|
+
const root = project({
|
|
116
|
+
'instructions.md': 'hi',
|
|
117
|
+
'tools/real.js': TOOL('real'),
|
|
118
|
+
'tools/_helpers/util.js': 'export const x = 1',
|
|
119
|
+
'tools/.hidden.js': TOOL('hidden'),
|
|
120
|
+
});
|
|
121
|
+
const { manifest, ok, diagnostics } = await loadDirectory(root);
|
|
122
|
+
expect(ok).toBe(true);
|
|
123
|
+
expect(manifest.tools.map((t) => t.definition.name)).toEqual(['real']);
|
|
124
|
+
expect(diagnostics.some((d) => d.code === 'unscanned_directory')).toBe(false);
|
|
125
|
+
});
|
|
126
|
+
it('warns about a subdirectory it did not scan', async () => {
|
|
127
|
+
const root = project({
|
|
128
|
+
'instructions.md': 'hi',
|
|
129
|
+
'tools/nested/deep.js': TOOL('deep'),
|
|
130
|
+
});
|
|
131
|
+
const { diagnostics } = await loadDirectory(root);
|
|
132
|
+
expect(diagnostics.find((d) => d.code === 'unscanned_directory')?.message).toContain('nested');
|
|
133
|
+
});
|
|
134
|
+
it('reports a missing directory rather than throwing', async () => {
|
|
135
|
+
const { ok, diagnostics } = await loadDirectory(join(tmpdir(), 'namzu-does-not-exist-xyz'));
|
|
136
|
+
expect(ok).toBe(false);
|
|
137
|
+
expect(diagnostics[0]?.code).toBe('root_missing');
|
|
138
|
+
});
|
|
139
|
+
it('throws only on programmer error', async () => {
|
|
140
|
+
await expect(loadDirectory('')).rejects.toThrow(TypeError);
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
describe('modules: skip', () => {
|
|
144
|
+
it('gives full structure without importing anything', async () => {
|
|
145
|
+
// The proof is the side effect: a module that would throw on import is
|
|
146
|
+
// listed, and nothing runs.
|
|
147
|
+
const root = project({
|
|
148
|
+
'instructions.md': 'You are helpful.',
|
|
149
|
+
'agent.js': 'throw new Error("agent.js executed")',
|
|
150
|
+
'tools/a.js': 'throw new Error("tool executed")',
|
|
151
|
+
});
|
|
152
|
+
const { manifest, ok } = await loadDirectory(root, { modules: 'skip' });
|
|
153
|
+
expect(ok).toBe(true);
|
|
154
|
+
expect(manifest.instructions).toBe('You are helpful.');
|
|
155
|
+
expect(manifest.sources.map((s) => s.id).sort()).toEqual(['a', 'agent', 'instructions']);
|
|
156
|
+
expect(manifest.sources
|
|
157
|
+
.filter((s) => s.slot !== 'instructions')
|
|
158
|
+
.every((s) => s.outcome === 'not_loaded')).toBe(true);
|
|
159
|
+
expect(manifest.tools).toHaveLength(0);
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
describe('include is an allow-list', () => {
|
|
163
|
+
it('scans only what was asked for', async () => {
|
|
164
|
+
const root = project({ 'instructions.md': 'hi', 'tools/a.js': TOOL('a') });
|
|
165
|
+
const { manifest } = await loadDirectory(root, { include: ['tools'] });
|
|
166
|
+
expect(manifest.included).toEqual(['tools']);
|
|
167
|
+
expect(manifest.instructions).toBe('');
|
|
168
|
+
expect(manifest.tools).toHaveLength(1);
|
|
169
|
+
});
|
|
170
|
+
it('scans nothing when the list is empty', async () => {
|
|
171
|
+
// An allow-list that admits everything when empty is the fail-open
|
|
172
|
+
// shape this estate removed elsewhere.
|
|
173
|
+
const root = project({ 'instructions.md': 'hi', 'tools/a.js': TOOL('a') });
|
|
174
|
+
const { manifest } = await loadDirectory(root, {
|
|
175
|
+
include: [],
|
|
176
|
+
});
|
|
177
|
+
expect(manifest.sources).toHaveLength(0);
|
|
178
|
+
expect(manifest.tools).toHaveLength(0);
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
describe('symlinks are refused, not followed', () => {
|
|
182
|
+
it.skipIf(!CAN_SYMLINK)('does not import a linked tool file', async () => {
|
|
183
|
+
const outside = mkdtempSync(join(tmpdir(), 'namzu-outside-'));
|
|
184
|
+
writeFileSync(join(outside, 'evil.js'), TOOL('evil'));
|
|
185
|
+
const root = project({
|
|
186
|
+
'instructions.md': 'hi',
|
|
187
|
+
'tools/real.js': TOOL('real'),
|
|
188
|
+
});
|
|
189
|
+
symlinkSync(join(outside, 'evil.js'), join(root, 'tools', 'linked.js'), 'file');
|
|
190
|
+
const { manifest, diagnostics } = await loadDirectory(root);
|
|
191
|
+
// The file that would be imported is not the file that was listed.
|
|
192
|
+
expect(manifest.tools.map((t) => t.definition.name)).toEqual(['real']);
|
|
193
|
+
expect(diagnostics.some((d) => d.code === 'symlink_refused')).toBe(true);
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
//# sourceMappingURL=load-directory.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load-directory.test.js","sourceRoot":"","sources":["../../../src/directory/__tests__/load-directory.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subagents.test.d.ts","sourceRoot":"","sources":["../../../src/directory/__tests__/subagents.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { mkdirSync, mkdtempSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { tmpdir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { describe, expect, it } from 'vitest';
|
|
5
|
+
import { deriveSupervisorOptions } from '../derive-supervisor.js';
|
|
6
|
+
import { loadDirectory } from '../load.js';
|
|
7
|
+
/**
|
|
8
|
+
* `SupervisorAgent` needs an `agentIds` roster and a manager that can spawn
|
|
9
|
+
* them. Nothing led from a directory to either, so a multi-agent system could
|
|
10
|
+
* be described on disk and not run.
|
|
11
|
+
*
|
|
12
|
+
* Delegates are loaded by recursion — a delegate directory has the same shape
|
|
13
|
+
* as its parent — capped at one level, because how deep a system may fan out
|
|
14
|
+
* is a topology decision and a directory layout should not make it by default.
|
|
15
|
+
*/
|
|
16
|
+
const provider = { id: 'mock', name: 'Mock' };
|
|
17
|
+
const agentManager = { sendMessage: async () => ({}) };
|
|
18
|
+
function tree(files) {
|
|
19
|
+
const root = mkdtempSync(join(tmpdir(), 'namzu-sub-'));
|
|
20
|
+
for (const [relative, body] of Object.entries(files)) {
|
|
21
|
+
const full = join(root, relative);
|
|
22
|
+
mkdirSync(join(full, '..'), { recursive: true });
|
|
23
|
+
writeFileSync(full, body);
|
|
24
|
+
}
|
|
25
|
+
return root;
|
|
26
|
+
}
|
|
27
|
+
const TOOL = (name) => `
|
|
28
|
+
export default {
|
|
29
|
+
name: ${JSON.stringify(name)},
|
|
30
|
+
description: 'a tool',
|
|
31
|
+
inputSchema: { parse: (v) => v, safeParse: (v) => ({ success: true, data: v }) },
|
|
32
|
+
execute: async () => ({ success: true, output: 'ok' }),
|
|
33
|
+
}
|
|
34
|
+
`;
|
|
35
|
+
const SYSTEM = {
|
|
36
|
+
'instructions.md': 'You coordinate.',
|
|
37
|
+
'agent.js': 'export default { model: "coordinator-model" }',
|
|
38
|
+
'agents/researcher/instructions.md': 'You research.',
|
|
39
|
+
'agents/researcher/agent.js': 'export default { model: "cheap-model" }',
|
|
40
|
+
'agents/researcher/tools/search.js': TOOL('search'),
|
|
41
|
+
'agents/writer/instructions.md': 'You write.',
|
|
42
|
+
};
|
|
43
|
+
describe('a project that declares delegates', () => {
|
|
44
|
+
it('loads each one as a project in its own right', async () => {
|
|
45
|
+
const { manifest, ok, diagnostics } = await loadDirectory(tree(SYSTEM));
|
|
46
|
+
expect(ok, JSON.stringify(diagnostics)).toBe(true);
|
|
47
|
+
expect(manifest.agents.map((a) => a.id).sort()).toEqual(['researcher', 'writer']);
|
|
48
|
+
const researcher = manifest.agents.find((a) => a.id === 'researcher');
|
|
49
|
+
expect(researcher?.manifest.instructions).toBe('You research.');
|
|
50
|
+
expect(researcher?.manifest.tools.map((t) => t.definition.name)).toEqual(['search']);
|
|
51
|
+
expect(researcher?.manifest.config.model).toBe('cheap-model');
|
|
52
|
+
});
|
|
53
|
+
it('surfaces a delegate failure in the parent list', async () => {
|
|
54
|
+
// A delegate that could not load is a fact about THIS project. A caller
|
|
55
|
+
// reading one list should not have to walk the tree to discover the run
|
|
56
|
+
// will be short a specialist.
|
|
57
|
+
const { manifest, ok, diagnostics } = await loadDirectory(tree({ ...SYSTEM, 'agents/writer/tools/bad.js': 'this is not valid !!!' }));
|
|
58
|
+
expect(ok).toBe(false);
|
|
59
|
+
expect(diagnostics.some((d) => d.message.startsWith('agents/writer:'))).toBe(true);
|
|
60
|
+
// The broken one is not offered as a delegate.
|
|
61
|
+
expect(manifest.agents.map((a) => a.id)).toEqual(['researcher']);
|
|
62
|
+
});
|
|
63
|
+
it('refuses to read a second level of delegates', async () => {
|
|
64
|
+
const { manifest, diagnostics } = await loadDirectory(tree({
|
|
65
|
+
...SYSTEM,
|
|
66
|
+
'agents/researcher/agents/deeper/instructions.md': 'You are too deep.',
|
|
67
|
+
}));
|
|
68
|
+
const researcher = manifest.agents.find((a) => a.id === 'researcher');
|
|
69
|
+
expect(researcher?.manifest.agents).toHaveLength(0);
|
|
70
|
+
expect(diagnostics.some((d) => d.code === 'subagent_too_deep')).toBe(true);
|
|
71
|
+
});
|
|
72
|
+
it('imports nothing under modules: skip, delegates included', async () => {
|
|
73
|
+
const { manifest, ok } = await loadDirectory(tree({
|
|
74
|
+
'instructions.md': 'hi',
|
|
75
|
+
'agents/x/instructions.md': 'hi',
|
|
76
|
+
'agents/x/tools/boom.js': 'throw new Error("executed")',
|
|
77
|
+
}), { modules: 'skip' });
|
|
78
|
+
expect(ok).toBe(true);
|
|
79
|
+
expect(manifest.sources.some((s) => s.slot === 'agents')).toBe(true);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
describe('deriving supervisor options', () => {
|
|
83
|
+
it('builds the roster from the directory', async () => {
|
|
84
|
+
const { manifest } = await loadDirectory(tree(SYSTEM));
|
|
85
|
+
const { config, delegates } = deriveSupervisorOptions(manifest, { provider, agentManager });
|
|
86
|
+
expect(config.agentIds.sort()).toEqual(['researcher', 'writer']);
|
|
87
|
+
expect(config.systemPrompt).toBe('You coordinate.');
|
|
88
|
+
expect(config.model).toBe('coordinator-model');
|
|
89
|
+
expect(delegates).toHaveLength(2);
|
|
90
|
+
});
|
|
91
|
+
it('lets a delegate keep its own model and inherit when it has none', async () => {
|
|
92
|
+
// A cheap model for a narrow job is the common case; inheriting
|
|
93
|
+
// unconditionally would bill every specialist at the coordinator rate.
|
|
94
|
+
const { manifest } = await loadDirectory(tree(SYSTEM));
|
|
95
|
+
const { delegates } = deriveSupervisorOptions(manifest, { provider, agentManager });
|
|
96
|
+
expect(delegates.find((d) => d.id === 'researcher')?.model).toBe('cheap-model');
|
|
97
|
+
expect(delegates.find((d) => d.id === 'writer')?.model).toBe('coordinator-model');
|
|
98
|
+
});
|
|
99
|
+
it('carries each delegate its own instructions and tools', async () => {
|
|
100
|
+
const { manifest } = await loadDirectory(tree(SYSTEM));
|
|
101
|
+
const { delegates } = deriveSupervisorOptions(manifest, { provider, agentManager });
|
|
102
|
+
const researcher = delegates.find((d) => d.id === 'researcher');
|
|
103
|
+
expect(researcher?.systemPrompt).toBe('You research.');
|
|
104
|
+
expect(researcher?.tools.has('search')).toBe(true);
|
|
105
|
+
});
|
|
106
|
+
it('refuses a project with no delegates', async () => {
|
|
107
|
+
// An empty roster makes create_task unmountable, so the result would be
|
|
108
|
+
// a coordinator that cannot coordinate — and the caller asked for one.
|
|
109
|
+
const { manifest } = await loadDirectory(tree({ 'instructions.md': 'hi', 'agent.js': 'export default { model: "m" }' }));
|
|
110
|
+
expect(() => deriveSupervisorOptions(manifest, { provider, agentManager })).toThrow(/declares no delegates/);
|
|
111
|
+
});
|
|
112
|
+
it('refuses a manifest whose modules were never loaded', async () => {
|
|
113
|
+
const { manifest } = await loadDirectory(tree(SYSTEM), { modules: 'skip' });
|
|
114
|
+
expect(() => deriveSupervisorOptions(manifest, { provider, agentManager })).toThrow(/modules: "skip"/);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
//# sourceMappingURL=subagents.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subagents.test.js","sourceRoot":"","sources":["../../../src/directory/__tests__/subagents.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supervisor-budget.test.d.ts","sourceRoot":"","sources":["../../../src/directory/__tests__/supervisor-budget.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { mkdirSync, mkdtempSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { tmpdir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { describe, expect, it } from 'vitest';
|
|
5
|
+
import { deriveSupervisorOptions } from '../derive-supervisor.js';
|
|
6
|
+
import { loadDirectory } from '../load.js';
|
|
7
|
+
/**
|
|
8
|
+
* `BaseAgentConfig` declares `tokenBudget` and `timeoutMs` as REQUIRED, and
|
|
9
|
+
* `deriveSupervisorOptions` supplied them only when `agent.ts` happened to
|
|
10
|
+
* name them — which is the uncommon case. An `as SupervisorAgentConfig` made
|
|
11
|
+
* that compile, so the returned object was typed `tokenBudget: number` while
|
|
12
|
+
* holding `undefined`.
|
|
13
|
+
*
|
|
14
|
+
* The consequence is not a type-level nicety. `buildLimitConfig` defaults only
|
|
15
|
+
* `maxIterations`, so an undefined budget and timeout disable BOTH hard stops
|
|
16
|
+
* — a project-derived supervisor ran with no token cap and no wall clock. And
|
|
17
|
+
* the child-spawn guard computes a delegate's allocation from the parent
|
|
18
|
+
* budget, so `undefined` became `NaN`, and `NaN <= 0` is false: the refusal
|
|
19
|
+
* that exists to stop an unfunded child let it through.
|
|
20
|
+
*
|
|
21
|
+
* The cast is now `satisfies`, which is what keeps this from recurring — but
|
|
22
|
+
* a type check is not a test, so the values are asserted here too.
|
|
23
|
+
*/
|
|
24
|
+
const provider = { id: 'mock', name: 'Mock' };
|
|
25
|
+
const agentManager = { sendMessage: async () => ({}) };
|
|
26
|
+
function tree(files) {
|
|
27
|
+
const root = mkdtempSync(join(tmpdir(), 'namzu-budget-'));
|
|
28
|
+
for (const [relative, body] of Object.entries(files)) {
|
|
29
|
+
const full = join(root, relative);
|
|
30
|
+
mkdirSync(join(full, '..'), { recursive: true });
|
|
31
|
+
writeFileSync(full, body);
|
|
32
|
+
}
|
|
33
|
+
return root;
|
|
34
|
+
}
|
|
35
|
+
const MINIMAL = {
|
|
36
|
+
'agent.js': 'export default { model: "m" }',
|
|
37
|
+
'agents/researcher/agent.js': 'export default { model: "m2" }',
|
|
38
|
+
'agents/researcher/instructions.md': 'Research things.',
|
|
39
|
+
};
|
|
40
|
+
describe('a derived supervisor always has a budget and a clock', () => {
|
|
41
|
+
it('defaults both when agent.ts names neither', async () => {
|
|
42
|
+
const { manifest } = await loadDirectory(tree(MINIMAL));
|
|
43
|
+
const { config } = deriveSupervisorOptions(manifest, { provider, agentManager });
|
|
44
|
+
// The exact numbers matter less than that they are finite: a NaN or an
|
|
45
|
+
// undefined here is what silently disabled the limits.
|
|
46
|
+
expect(Number.isFinite(config.tokenBudget)).toBe(true);
|
|
47
|
+
expect(Number.isFinite(config.timeoutMs)).toBe(true);
|
|
48
|
+
expect(config.tokenBudget).toBeGreaterThan(0);
|
|
49
|
+
expect(config.timeoutMs).toBeGreaterThan(0);
|
|
50
|
+
});
|
|
51
|
+
it('uses the same defaults the SDK front door uses', async () => {
|
|
52
|
+
// Imported from the module that owns them rather than through the
|
|
53
|
+
// package entry: this file now lives inside that package, and a
|
|
54
|
+
// self-import resolves to the built `dist`, not to the source under
|
|
55
|
+
// test — which is how a stale build reads as a passing test.
|
|
56
|
+
const { DEFAULT_TIMEOUT_MS, DEFAULT_TOKEN_BUDGET } = await import('../../agents/runAgent.js');
|
|
57
|
+
const { manifest } = await loadDirectory(tree(MINIMAL));
|
|
58
|
+
const { config } = deriveSupervisorOptions(manifest, { provider, agentManager });
|
|
59
|
+
// Two front doors that default differently is a difference nobody would
|
|
60
|
+
// find until a run behaved unlike its sibling.
|
|
61
|
+
expect(config.tokenBudget).toBe(DEFAULT_TOKEN_BUDGET);
|
|
62
|
+
expect(config.timeoutMs).toBe(DEFAULT_TIMEOUT_MS);
|
|
63
|
+
});
|
|
64
|
+
it('still honours what agent.ts declares', async () => {
|
|
65
|
+
const { manifest } = await loadDirectory(tree({
|
|
66
|
+
...MINIMAL,
|
|
67
|
+
'agent.js': 'export default { model: "m", tokenBudget: 1234, timeoutMs: 5678 }',
|
|
68
|
+
}));
|
|
69
|
+
const { config } = deriveSupervisorOptions(manifest, { provider, agentManager });
|
|
70
|
+
expect(config.tokenBudget).toBe(1234);
|
|
71
|
+
expect(config.timeoutMs).toBe(5678);
|
|
72
|
+
});
|
|
73
|
+
it('lets an override win over both', async () => {
|
|
74
|
+
const { manifest } = await loadDirectory(tree(MINIMAL));
|
|
75
|
+
const { config } = deriveSupervisorOptions(manifest, {
|
|
76
|
+
provider,
|
|
77
|
+
agentManager,
|
|
78
|
+
overrides: { tokenBudget: 42 },
|
|
79
|
+
});
|
|
80
|
+
expect(config.tokenBudget).toBe(42);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
describe('a derived supervisor carries the skills it loaded', () => {
|
|
84
|
+
it('passes skills through instead of dropping them', async () => {
|
|
85
|
+
const { manifest } = await loadDirectory(tree({
|
|
86
|
+
...MINIMAL,
|
|
87
|
+
'skills/plan-a-trip/SKILL.md': '---\nname: plan-a-trip\ndescription: Plan a trip\n---\n\nAsk for dates.',
|
|
88
|
+
}));
|
|
89
|
+
expect(manifest.skills).toHaveLength(1);
|
|
90
|
+
const { config } = deriveSupervisorOptions(manifest, { provider, agentManager });
|
|
91
|
+
// Loaded from disk, put on the manifest, and then — before this — left
|
|
92
|
+
// out of the config the supervisor actually runs with.
|
|
93
|
+
expect(config.skills).toHaveLength(1);
|
|
94
|
+
expect(config.skills?.[0]?.metadata.name).toBe('plan-a-trip');
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
//# sourceMappingURL=supervisor-budget.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supervisor-budget.test.js","sourceRoot":"","sources":["../../../src/directory/__tests__/supervisor-budget.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { AgentIdentity } from '../agents/runAgent.js';
|
|
2
|
+
import { ToolRegistry } from '../registry/tool/execute.js';
|
|
3
|
+
import type { SupervisorAgentConfig } from '../types/agent/supervisor.js';
|
|
4
|
+
import type { LLMProvider } from '../types/provider/index.js';
|
|
5
|
+
import type { DirectoryManifest } from './types.js';
|
|
6
|
+
export interface DeriveSupervisorInput {
|
|
7
|
+
readonly provider: LLMProvider;
|
|
8
|
+
/** Wins over `agent.ts`. Required when `agent.ts` names no model. */
|
|
9
|
+
readonly model?: string;
|
|
10
|
+
readonly identity?: Required<AgentIdentity>;
|
|
11
|
+
/**
|
|
12
|
+
* The lifecycle object that actually spawns delegates.
|
|
13
|
+
*
|
|
14
|
+
* Supplied by the host and never built here. An `AgentManager` owns
|
|
15
|
+
* running processes, budgets and cancellation — it is a thing with a
|
|
16
|
+
* lifetime, not a description of one, and this package's whole boundary is
|
|
17
|
+
* that it describes and does not run. Handing back options that carry a
|
|
18
|
+
* manager we constructed would make it a runner wearing a loader's name.
|
|
19
|
+
*/
|
|
20
|
+
readonly agentManager: SupervisorAgentConfig['agentManager'];
|
|
21
|
+
readonly overrides?: Partial<SupervisorAgentConfig>;
|
|
22
|
+
}
|
|
23
|
+
export interface SupervisorPlan {
|
|
24
|
+
/** Ready for `new SupervisorAgent(...).run(input, config)`. */
|
|
25
|
+
readonly config: SupervisorAgentConfig;
|
|
26
|
+
/**
|
|
27
|
+
* What the host must register with its `AgentManager` before running,
|
|
28
|
+
* one per delegate, keyed by the id the supervisor will name.
|
|
29
|
+
*
|
|
30
|
+
* Returned rather than registered: registration is a mutation of the
|
|
31
|
+
* host's manager, and a function that quietly mutates an object it was
|
|
32
|
+
* handed for reference is the kind of surprise this package exists to
|
|
33
|
+
* avoid. The host does it, in one loop it can see.
|
|
34
|
+
*/
|
|
35
|
+
readonly delegates: readonly DelegatePlan[];
|
|
36
|
+
}
|
|
37
|
+
export interface DelegatePlan {
|
|
38
|
+
readonly id: string;
|
|
39
|
+
readonly manifest: DirectoryManifest;
|
|
40
|
+
/** The delegate's own instructions, tools and model, already assembled. */
|
|
41
|
+
readonly systemPrompt: string;
|
|
42
|
+
readonly tools: ToolRegistry;
|
|
43
|
+
readonly model: string;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Turn a project that declares delegates into a supervisor configuration.
|
|
47
|
+
*
|
|
48
|
+
* The counterpart to `deriveRunOptions` for the multi-agent shape, and the
|
|
49
|
+
* same contract: it converts, it does not run. `SupervisorAgent` needs an
|
|
50
|
+
* `agentIds` roster and a manager that can spawn them; this supplies the
|
|
51
|
+
* roster from the directory and leaves the manager to the host.
|
|
52
|
+
*
|
|
53
|
+
* The delegates come back as plans rather than registered agents because
|
|
54
|
+
* registration mutates the host's manager. Two lines in the host, and the host
|
|
55
|
+
* can see exactly what it just gained.
|
|
56
|
+
*/
|
|
57
|
+
export declare function deriveSupervisorOptions(manifest: DirectoryManifest, input: DeriveSupervisorInput): SupervisorPlan;
|
|
58
|
+
//# sourceMappingURL=derive-supervisor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"derive-supervisor.d.ts","sourceRoot":"","sources":["../../src/directory/derive-supervisor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAA;AAC1D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAA;AACzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAA;AAE7D,OAAO,KAAK,EAAE,iBAAiB,EAAiB,MAAM,YAAY,CAAA;AAElE,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAA;IAC9B,qEAAqE;IACrE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAA;IAC3C;;;;;;;;OAQG;IACH,QAAQ,CAAC,YAAY,EAAE,qBAAqB,CAAC,cAAc,CAAC,CAAA;IAC5D,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAA;CACnD;AAED,MAAM,WAAW,cAAc;IAC9B,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAA;IACtC;;;;;;;;OAQG;IACH,QAAQ,CAAC,SAAS,EAAE,SAAS,YAAY,EAAE,CAAA;CAC3C;AAED,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAA;IACpC,2EAA2E;IAC3E,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAA;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACtB;AAsBD;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CACtC,QAAQ,EAAE,iBAAiB,EAC3B,KAAK,EAAE,qBAAqB,GAC1B,cAAc,CA+DhB"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { DEFAULT_TIMEOUT_MS, DEFAULT_TOKEN_BUDGET } from '../agents/runAgent.js';
|
|
2
|
+
import { ToolRegistry } from '../registry/tool/execute.js';
|
|
3
|
+
function toolsOf(manifest) {
|
|
4
|
+
const tools = new ToolRegistry();
|
|
5
|
+
for (const entry of manifest.tools)
|
|
6
|
+
tools.register(entry.definition);
|
|
7
|
+
return tools;
|
|
8
|
+
}
|
|
9
|
+
function delegatePlan(entry, fallbackModel) {
|
|
10
|
+
return {
|
|
11
|
+
id: entry.id,
|
|
12
|
+
manifest: entry.manifest,
|
|
13
|
+
systemPrompt: entry.manifest.instructions,
|
|
14
|
+
tools: toolsOf(entry.manifest),
|
|
15
|
+
// A delegate may name its own model — a cheap one for a narrow job is
|
|
16
|
+
// the common case — and inherits the supervisor's only when it does
|
|
17
|
+
// not. Inheriting unconditionally would silently bill every specialist
|
|
18
|
+
// at the coordinator's rate.
|
|
19
|
+
model: entry.manifest.config.model ?? fallbackModel,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Turn a project that declares delegates into a supervisor configuration.
|
|
24
|
+
*
|
|
25
|
+
* The counterpart to `deriveRunOptions` for the multi-agent shape, and the
|
|
26
|
+
* same contract: it converts, it does not run. `SupervisorAgent` needs an
|
|
27
|
+
* `agentIds` roster and a manager that can spawn them; this supplies the
|
|
28
|
+
* roster from the directory and leaves the manager to the host.
|
|
29
|
+
*
|
|
30
|
+
* The delegates come back as plans rather than registered agents because
|
|
31
|
+
* registration mutates the host's manager. Two lines in the host, and the host
|
|
32
|
+
* can see exactly what it just gained.
|
|
33
|
+
*/
|
|
34
|
+
export function deriveSupervisorOptions(manifest, input) {
|
|
35
|
+
if (manifest.modules === 'skip') {
|
|
36
|
+
throw new Error('This manifest was loaded with modules: "skip", so no tool was imported and no delegate was evaluated. Load with modules: "evaluate" before deriving supervisor options.');
|
|
37
|
+
}
|
|
38
|
+
if (manifest.agents.length === 0) {
|
|
39
|
+
// Not a warning that degrades into a supervisor with nobody to call.
|
|
40
|
+
// An empty roster makes `create_task` unmountable by design, so the
|
|
41
|
+
// result would be a coordinator that cannot coordinate — and the
|
|
42
|
+
// caller asked for a supervisor, which means they expected delegates.
|
|
43
|
+
throw new Error(`${manifest.root} declares no delegates, so there is nothing for a supervisor to coordinate. Add directories under agents/, or use deriveRunOptions for a single agent.`);
|
|
44
|
+
}
|
|
45
|
+
const model = input.model ?? manifest.config.model;
|
|
46
|
+
if (!model) {
|
|
47
|
+
throw new Error(`No model. Declare one in ${manifest.root}/agent.ts as \`export default { model: "…" }\`, or pass \`model\` here.`);
|
|
48
|
+
}
|
|
49
|
+
const delegates = manifest.agents.map((entry) => delegatePlan(entry, model));
|
|
50
|
+
const config = {
|
|
51
|
+
provider: input.provider,
|
|
52
|
+
model,
|
|
53
|
+
agentManager: input.agentManager,
|
|
54
|
+
agentIds: delegates.map((d) => d.id),
|
|
55
|
+
systemPrompt: manifest.instructions,
|
|
56
|
+
tools: toolsOf(manifest),
|
|
57
|
+
// Skills were loaded and then dropped. The manifest reads a whole
|
|
58
|
+
// `skills/` directory and `SupervisorAgentConfig` takes them, and the
|
|
59
|
+
// cast that used to close this object meant nobody was told the field
|
|
60
|
+
// had never been supplied.
|
|
61
|
+
...(manifest.skills.length > 0 ? { skills: manifest.skills.map((s) => s.skill) } : {}),
|
|
62
|
+
// `tokenBudget` and `timeoutMs` are REQUIRED by `BaseAgentConfig`, and
|
|
63
|
+
// this object supplied them only when `agent.ts` happened to declare
|
|
64
|
+
// them — which is the uncommon case. The `as SupervisorAgentConfig`
|
|
65
|
+
// below made that compile, so a directory that named no budget produced
|
|
66
|
+
// a config typed `tokenBudget: number` holding `undefined`, and
|
|
67
|
+
// `buildLimitConfig` then disabled BOTH hard stops: no token cap, no
|
|
68
|
+
// wall clock. Worse, the child-spawn refusal computes its allocation
|
|
69
|
+
// from the parent budget, so `undefined` became `NaN`, and `NaN <= 0`
|
|
70
|
+
// is false — the guard that exists to refuse an unfunded child let it
|
|
71
|
+
// through with a NaN budget.
|
|
72
|
+
//
|
|
73
|
+
// Defaulted to the same numbers `runAgent` uses rather than to a local
|
|
74
|
+
// guess, so the two front doors cannot drift.
|
|
75
|
+
tokenBudget: manifest.config.tokenBudget ?? DEFAULT_TOKEN_BUDGET,
|
|
76
|
+
timeoutMs: manifest.config.timeoutMs ?? DEFAULT_TIMEOUT_MS,
|
|
77
|
+
...(manifest.config.temperature !== undefined
|
|
78
|
+
? { temperature: manifest.config.temperature }
|
|
79
|
+
: {}),
|
|
80
|
+
...(manifest.config.maxIterations !== undefined
|
|
81
|
+
? { maxIterations: manifest.config.maxIterations }
|
|
82
|
+
: {}),
|
|
83
|
+
...(input.identity ?? {}),
|
|
84
|
+
...(input.overrides ?? {}),
|
|
85
|
+
};
|
|
86
|
+
return { config, delegates };
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=derive-supervisor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"derive-supervisor.js","sourceRoot":"","sources":["../../src/directory/derive-supervisor.ts"],"names":[],"mappings":"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"}
|