@namzu/sdk 5.1.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.
Files changed (158) hide show
  1. package/CHANGELOG.md +361 -0
  2. package/dist/agents/__tests__/run-agent-forwarding.test.d.ts +2 -0
  3. package/dist/agents/__tests__/run-agent-forwarding.test.d.ts.map +1 -0
  4. package/dist/agents/__tests__/run-agent-forwarding.test.js +76 -0
  5. package/dist/agents/__tests__/run-agent-forwarding.test.js.map +1 -0
  6. package/dist/agents/__tests__/run-completed-stop-reason.test.d.ts +2 -0
  7. package/dist/agents/__tests__/run-completed-stop-reason.test.d.ts.map +1 -0
  8. package/dist/agents/__tests__/run-completed-stop-reason.test.js +50 -0
  9. package/dist/agents/__tests__/run-completed-stop-reason.test.js.map +1 -0
  10. package/dist/agents/index.d.ts +1 -0
  11. package/dist/agents/index.d.ts.map +1 -1
  12. package/dist/agents/index.js +4 -0
  13. package/dist/agents/index.js.map +1 -1
  14. package/dist/agents/runAgent.d.ts +34 -0
  15. package/dist/agents/runAgent.d.ts.map +1 -1
  16. package/dist/agents/runAgent.js +5 -3
  17. package/dist/agents/runAgent.js.map +1 -1
  18. package/dist/config/runtime.d.ts +30 -30
  19. package/dist/constants/tools/__tests__/dangerous-patterns.test.d.ts +2 -0
  20. package/dist/constants/tools/__tests__/dangerous-patterns.test.d.ts.map +1 -0
  21. package/dist/constants/tools/__tests__/dangerous-patterns.test.js +54 -0
  22. package/dist/constants/tools/__tests__/dangerous-patterns.test.js.map +1 -0
  23. package/dist/constants/tools/index.d.ts.map +1 -1
  24. package/dist/constants/tools/index.js +28 -1
  25. package/dist/constants/tools/index.js.map +1 -1
  26. package/dist/contracts/a2a.d.ts +44 -44
  27. package/dist/directory/__tests__/derive.test.d.ts +2 -0
  28. package/dist/directory/__tests__/derive.test.d.ts.map +1 -0
  29. package/dist/directory/__tests__/derive.test.js +111 -0
  30. package/dist/directory/__tests__/derive.test.js.map +1 -0
  31. package/dist/directory/__tests__/load-diagnostics.test.d.ts +2 -0
  32. package/dist/directory/__tests__/load-diagnostics.test.d.ts.map +1 -0
  33. package/dist/directory/__tests__/load-diagnostics.test.js +106 -0
  34. package/dist/directory/__tests__/load-diagnostics.test.js.map +1 -0
  35. package/dist/directory/__tests__/load-directory.test.d.ts +2 -0
  36. package/dist/directory/__tests__/load-directory.test.d.ts.map +1 -0
  37. package/dist/directory/__tests__/load-directory.test.js +196 -0
  38. package/dist/directory/__tests__/load-directory.test.js.map +1 -0
  39. package/dist/directory/__tests__/subagents.test.d.ts +2 -0
  40. package/dist/directory/__tests__/subagents.test.d.ts.map +1 -0
  41. package/dist/directory/__tests__/subagents.test.js +117 -0
  42. package/dist/directory/__tests__/subagents.test.js.map +1 -0
  43. package/dist/directory/__tests__/supervisor-budget.test.d.ts +2 -0
  44. package/dist/directory/__tests__/supervisor-budget.test.d.ts.map +1 -0
  45. package/dist/directory/__tests__/supervisor-budget.test.js +97 -0
  46. package/dist/directory/__tests__/supervisor-budget.test.js.map +1 -0
  47. package/dist/directory/derive-supervisor.d.ts +58 -0
  48. package/dist/directory/derive-supervisor.d.ts.map +1 -0
  49. package/dist/directory/derive-supervisor.js +88 -0
  50. package/dist/directory/derive-supervisor.js.map +1 -0
  51. package/dist/directory/derive.d.ts +12 -0
  52. package/dist/directory/derive.d.ts.map +1 -0
  53. package/dist/directory/derive.js +58 -0
  54. package/dist/directory/derive.js.map +1 -0
  55. package/dist/directory/index.d.ts +7 -0
  56. package/dist/directory/index.d.ts.map +1 -0
  57. package/dist/directory/index.js +5 -0
  58. package/dist/directory/index.js.map +1 -0
  59. package/dist/directory/load.d.ts +14 -0
  60. package/dist/directory/load.d.ts.map +1 -0
  61. package/dist/directory/load.js +488 -0
  62. package/dist/directory/load.js.map +1 -0
  63. package/dist/directory/scan.d.ts +36 -0
  64. package/dist/directory/scan.d.ts.map +1 -0
  65. package/dist/directory/scan.js +136 -0
  66. package/dist/directory/scan.js.map +1 -0
  67. package/dist/directory/types.d.ts +215 -0
  68. package/dist/directory/types.d.ts.map +1 -0
  69. package/dist/directory/types.js +8 -0
  70. package/dist/directory/types.js.map +1 -0
  71. package/dist/plugin/__tests__/path-containment.test.d.ts +2 -0
  72. package/dist/plugin/__tests__/path-containment.test.d.ts.map +1 -0
  73. package/dist/plugin/__tests__/path-containment.test.js +91 -0
  74. package/dist/plugin/__tests__/path-containment.test.js.map +1 -0
  75. package/dist/plugin/lifecycle.d.ts.map +1 -1
  76. package/dist/plugin/lifecycle.js +3 -3
  77. package/dist/plugin/lifecycle.js.map +1 -1
  78. package/dist/plugin/loader.d.ts.map +1 -1
  79. package/dist/plugin/loader.js +12 -2
  80. package/dist/plugin/loader.js.map +1 -1
  81. package/dist/provider/__tests__/model-version.test.d.ts +2 -0
  82. package/dist/provider/__tests__/model-version.test.d.ts.map +1 -0
  83. package/dist/provider/__tests__/model-version.test.js +80 -0
  84. package/dist/provider/__tests__/model-version.test.js.map +1 -0
  85. package/dist/provider/__tests__/strict-schema.test.d.ts +2 -0
  86. package/dist/provider/__tests__/strict-schema.test.d.ts.map +1 -0
  87. package/dist/provider/__tests__/strict-schema.test.js +109 -0
  88. package/dist/provider/__tests__/strict-schema.test.js.map +1 -0
  89. package/dist/provider/model-version.d.ts +60 -0
  90. package/dist/provider/model-version.d.ts.map +1 -0
  91. package/dist/provider/model-version.js +64 -0
  92. package/dist/provider/model-version.js.map +1 -0
  93. package/dist/provider/strict-schema.d.ts +49 -0
  94. package/dist/provider/strict-schema.d.ts.map +1 -0
  95. package/dist/provider/strict-schema.js +112 -0
  96. package/dist/provider/strict-schema.js.map +1 -0
  97. package/dist/public-runtime.d.ts +6 -1
  98. package/dist/public-runtime.d.ts.map +1 -1
  99. package/dist/public-runtime.js +21 -1
  100. package/dist/public-runtime.js.map +1 -1
  101. package/dist/public-types.d.ts +2 -0
  102. package/dist/public-types.d.ts.map +1 -1
  103. package/dist/registry/tool/__tests__/strict-registration.test.d.ts +2 -0
  104. package/dist/registry/tool/__tests__/strict-registration.test.d.ts.map +1 -0
  105. package/dist/registry/tool/__tests__/strict-registration.test.js +82 -0
  106. package/dist/registry/tool/__tests__/strict-registration.test.js.map +1 -0
  107. package/dist/registry/tool/execute.d.ts.map +1 -1
  108. package/dist/registry/tool/execute.js +16 -0
  109. package/dist/registry/tool/execute.js.map +1 -1
  110. package/dist/runtime/query/result.d.ts.map +1 -1
  111. package/dist/runtime/query/result.js +5 -0
  112. package/dist/runtime/query/result.js.map +1 -1
  113. package/dist/tools/builtins/__tests__/edit-insert-reachable.test.js +7 -1
  114. package/dist/tools/builtins/__tests__/edit-insert-reachable.test.js.map +1 -1
  115. package/dist/tools/builtins/__tests__/edit.test.js +1 -1
  116. package/dist/tools/builtins/__tests__/edit.test.js.map +1 -1
  117. package/dist/tools/builtins/edit.d.ts.map +1 -1
  118. package/dist/tools/builtins/edit.js +20 -2
  119. package/dist/tools/builtins/edit.js.map +1 -1
  120. package/dist/types/plugin/index.d.ts +4 -4
  121. package/dist/types/run/events.d.ts +17 -2
  122. package/dist/types/run/events.d.ts.map +1 -1
  123. package/dist/types/run/events.js.map +1 -1
  124. package/dist/types/verification/index.d.ts +6 -6
  125. package/package.json +1 -1
  126. package/src/agents/__tests__/run-agent-forwarding.test.ts +85 -0
  127. package/src/agents/__tests__/run-completed-stop-reason.test.ts +59 -0
  128. package/src/agents/index.ts +8 -0
  129. package/src/agents/runAgent.ts +30 -4
  130. package/src/constants/tools/__tests__/dangerous-patterns.test.ts +62 -0
  131. package/src/constants/tools/index.ts +28 -1
  132. package/src/directory/__tests__/derive.test.ts +135 -0
  133. package/src/directory/__tests__/load-diagnostics.test.ts +126 -0
  134. package/src/directory/__tests__/load-directory.test.ts +243 -0
  135. package/src/directory/__tests__/subagents.test.ts +155 -0
  136. package/src/directory/__tests__/supervisor-budget.test.ts +117 -0
  137. package/src/directory/derive-supervisor.ts +149 -0
  138. package/src/directory/derive.ts +70 -0
  139. package/src/directory/index.ts +27 -0
  140. package/src/directory/load.ts +556 -0
  141. package/src/directory/scan.ts +163 -0
  142. package/src/directory/types.ts +254 -0
  143. package/src/plugin/__tests__/path-containment.test.ts +107 -0
  144. package/src/plugin/lifecycle.ts +3 -3
  145. package/src/plugin/loader.ts +12 -2
  146. package/src/provider/__tests__/model-version.test.ts +93 -0
  147. package/src/provider/__tests__/strict-schema.test.ts +133 -0
  148. package/src/provider/model-version.ts +98 -0
  149. package/src/provider/strict-schema.ts +125 -0
  150. package/src/public-runtime.ts +31 -0
  151. package/src/public-types.ts +8 -0
  152. package/src/registry/tool/__tests__/strict-registration.test.ts +115 -0
  153. package/src/registry/tool/execute.ts +16 -0
  154. package/src/runtime/query/result.ts +5 -0
  155. package/src/tools/builtins/__tests__/edit-insert-reachable.test.ts +8 -2
  156. package/src/tools/builtins/__tests__/edit.test.ts +1 -1
  157. package/src/tools/builtins/edit.ts +20 -2
  158. package/src/types/run/events.ts +15 -2
@@ -0,0 +1,111 @@
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 { deriveRunOptions } from '../derive.js';
6
+ import { loadDirectory } from '../load.js';
7
+ const provider = { id: 'mock', name: 'Mock' };
8
+ function project(files) {
9
+ const root = mkdtempSync(join(tmpdir(), 'namzu-derive-'));
10
+ for (const [relative, body] of Object.entries(files)) {
11
+ const full = join(root, relative);
12
+ mkdirSync(join(full, '..'), { recursive: true });
13
+ writeFileSync(full, body);
14
+ }
15
+ return root;
16
+ }
17
+ const TOOL = (name) => `
18
+ export default {
19
+ name: ${JSON.stringify(name)},
20
+ description: 'a tool',
21
+ inputSchema: { parse: (v) => v, safeParse: (v) => ({ success: true, data: v }) },
22
+ execute: async () => ({ success: true, output: 'ok' }),
23
+ }
24
+ `;
25
+ describe('turning a manifest into run options', () => {
26
+ it('carries instructions, config and tools across', async () => {
27
+ const root = project({
28
+ 'instructions.md': 'You are terse.',
29
+ 'agent.js': 'export default { model: "m", maxIterations: 3 }',
30
+ 'tools/a.js': TOOL('a'),
31
+ });
32
+ const { manifest } = await loadDirectory(root);
33
+ const options = deriveRunOptions(manifest, { provider, prompt: 'hi' });
34
+ expect(options.model).toBe('m');
35
+ expect(options.instructions).toBe('You are terse.');
36
+ expect(options.maxIterations).toBe(3);
37
+ expect(options.tools?.has('a')).toBe(true);
38
+ });
39
+ it('points the working directory at the project, not the host', async () => {
40
+ // Left unset this defaults to the host's cwd, which aims the file
41
+ // tools' containment at the host's own source tree.
42
+ const root = project({
43
+ 'instructions.md': 'hi',
44
+ 'agent.js': 'export default { model: "m" }',
45
+ });
46
+ const { manifest } = await loadDirectory(root);
47
+ expect(deriveRunOptions(manifest, { provider, prompt: 'hi' }).workingDirectory).toBe(manifest.root);
48
+ });
49
+ it('lets an explicit model win over agent.ts', async () => {
50
+ const root = project({
51
+ 'instructions.md': 'hi',
52
+ 'agent.js': 'export default { model: "from-file" }',
53
+ });
54
+ const { manifest } = await loadDirectory(root);
55
+ expect(deriveRunOptions(manifest, { provider, prompt: 'hi', model: 'explicit' }).model).toBe('explicit');
56
+ });
57
+ it('refuses when nothing names a model', async () => {
58
+ const root = project({ 'instructions.md': 'hi' });
59
+ const { manifest } = await loadDirectory(root);
60
+ expect(() => deriveRunOptions(manifest, { provider, prompt: 'hi' })).toThrow(/No model/);
61
+ });
62
+ it('forwards a name only when agent.ts declared one', async () => {
63
+ // A name guessed from a directory basename becomes the agent id in
64
+ // traces, where two sibling projects both called `agent` merge into one
65
+ // attribution bucket.
66
+ const declared = project({
67
+ 'instructions.md': 'hi',
68
+ 'agent.js': 'export default { model: "m", name: "researcher" }',
69
+ });
70
+ const guessed = project({
71
+ 'instructions.md': 'hi',
72
+ 'agent.js': 'export default { model: "m" }',
73
+ });
74
+ const withName = deriveRunOptions((await loadDirectory(declared)).manifest, {
75
+ provider,
76
+ prompt: 'x',
77
+ });
78
+ const without = deriveRunOptions((await loadDirectory(guessed)).manifest, {
79
+ provider,
80
+ prompt: 'x',
81
+ });
82
+ expect(withName.name).toBe('researcher');
83
+ expect(without.name).toBeUndefined();
84
+ });
85
+ it('refuses a manifest whose modules were never loaded', async () => {
86
+ // `manifest.tools` is empty for a reason that has nothing to do with
87
+ // the project. Running it would produce an agent with no capabilities
88
+ // and no indication why.
89
+ const root = project({
90
+ 'instructions.md': 'hi',
91
+ 'agent.js': 'export default { model: "m" }',
92
+ 'tools/a.js': TOOL('a'),
93
+ });
94
+ const { manifest } = await loadDirectory(root, { modules: 'skip' });
95
+ expect(() => deriveRunOptions(manifest, { provider, prompt: 'hi' })).toThrow(/modules: "skip"/);
96
+ });
97
+ it('lets overrides win over everything', async () => {
98
+ const root = project({
99
+ 'instructions.md': 'hi',
100
+ 'agent.js': 'export default { model: "m", maxIterations: 3 }',
101
+ });
102
+ const { manifest } = await loadDirectory(root);
103
+ const options = deriveRunOptions(manifest, {
104
+ provider,
105
+ prompt: 'hi',
106
+ overrides: { maxIterations: 99 },
107
+ });
108
+ expect(options.maxIterations).toBe(99);
109
+ });
110
+ });
111
+ //# sourceMappingURL=derive.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"derive.test.js","sourceRoot":"","sources":["../../../src/directory/__tests__/derive.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=load-diagnostics.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-diagnostics.test.d.ts","sourceRoot":"","sources":["../../../src/directory/__tests__/load-diagnostics.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,106 @@
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 { loadDirectory } from '../load.js';
6
+ /**
7
+ * Three refusals this loader claimed to make and did not.
8
+ *
9
+ * Each is the same shape: a check that existed, read the wrong thing, and
10
+ * therefore reported the wrong answer while looking correct in review. A
11
+ * loader whose entire job is to say what is wrong with a directory has to be
12
+ * held to the diagnostics it actually emits, not the ones its code appears to
13
+ * emit.
14
+ */
15
+ function project(files) {
16
+ const root = mkdtempSync(join(tmpdir(), 'namzu-diag-'));
17
+ for (const [relative, body] of Object.entries(files)) {
18
+ const full = join(root, relative);
19
+ mkdirSync(join(full, '..'), { recursive: true });
20
+ writeFileSync(full, body);
21
+ }
22
+ return root;
23
+ }
24
+ describe('a tool that would crash later is refused now', () => {
25
+ it('rejects a default export with no inputSchema', async () => {
26
+ // `name` and `execute` alone used to pass. The object then registered
27
+ // clean and died in `toLLMTools()` on `inputSchema._def` — a TypeError
28
+ // naming neither this file nor this loader.
29
+ const root = project({
30
+ 'tools/broken.js': `
31
+ export default {
32
+ name: 'broken',
33
+ description: 'no schema',
34
+ execute: async () => ({ success: true }),
35
+ }
36
+ `,
37
+ });
38
+ const { manifest, diagnostics, ok } = await loadDirectory(root);
39
+ expect(ok).toBe(false);
40
+ expect(diagnostics.map((d) => d.code)).toContain('not_a_tool');
41
+ expect(manifest.tools).toHaveLength(0);
42
+ });
43
+ it('still accepts a hand-written tool that satisfies the published type', async () => {
44
+ // The required set and no more: demanding `defineTool`'s extras would
45
+ // make this loader refuse an object the SDK's own type accepts.
46
+ const root = project({
47
+ 'tools/fine.js': `
48
+ export default {
49
+ name: 'fine',
50
+ description: 'a tool',
51
+ inputSchema: { parse: (v) => v },
52
+ execute: async () => ({ success: true }),
53
+ }
54
+ `,
55
+ });
56
+ const { manifest, ok } = await loadDirectory(root);
57
+ expect(ok).toBe(true);
58
+ expect(manifest.tools).toHaveLength(1);
59
+ });
60
+ });
61
+ describe('an import failure explains itself', () => {
62
+ it('gives the extension hint for a module it cannot resolve', async () => {
63
+ // The hint is chosen from Node's error CODE. It used to be matched
64
+ // against the message, which never contains the code, so every hint in
65
+ // the function was unreachable and every author got the bare error.
66
+ const root = project({
67
+ 'tools/importer.js': `
68
+ import './nowhere-at-all.js'
69
+ export default { name: 'x', description: 'x', inputSchema: {}, execute: async () => ({}) }
70
+ `,
71
+ });
72
+ const { diagnostics } = await loadDirectory(root);
73
+ const failed = diagnostics.find((d) => d.code === 'module_load_failed');
74
+ expect(failed).toBeDefined();
75
+ expect(failed?.cause).toContain('real extension');
76
+ });
77
+ });
78
+ describe('agent.ts metadata is checked, not assumed', () => {
79
+ it('refuses metadata values that are not strings', async () => {
80
+ // Typed `Record<string, string>` and admitted on `typeof === 'object'`,
81
+ // so the values were never looked at and the type was a promise this
82
+ // loader did not keep.
83
+ const root = project({
84
+ 'agent.js': 'export default { model: "m", metadata: { count: 1 } }',
85
+ });
86
+ const { diagnostics, ok } = await loadDirectory(root);
87
+ expect(ok).toBe(false);
88
+ expect(diagnostics.some((d) => d.code === 'invalid_config')).toBe(true);
89
+ });
90
+ it('refuses an array, which typeof calls an object', async () => {
91
+ const root = project({
92
+ 'agent.js': 'export default { model: "m", metadata: ["a", "b"] }',
93
+ });
94
+ const { ok } = await loadDirectory(root);
95
+ expect(ok).toBe(false);
96
+ });
97
+ it('accepts a metadata object of strings', async () => {
98
+ const root = project({
99
+ 'agent.js': 'export default { model: "m", metadata: { team: "core" } }',
100
+ });
101
+ const { manifest, ok } = await loadDirectory(root);
102
+ expect(ok).toBe(true);
103
+ expect(manifest.config.metadata).toEqual({ team: 'core' });
104
+ });
105
+ });
106
+ //# sourceMappingURL=load-diagnostics.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-diagnostics.test.js","sourceRoot":"","sources":["../../../src/directory/__tests__/load-diagnostics.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=load-directory.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-directory.test.d.ts","sourceRoot":"","sources":["../../../src/directory/__tests__/load-directory.test.ts"],"names":[],"mappings":""}
@@ -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":"AAAA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAC5E,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAE7C,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE1C;;;;;;;;;GASG;AAEH,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE;IACzB,IAAI,CAAC;QACJ,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAA;QAC5D,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,KAAK,CAAC,CAAA;QAC9C,OAAO,IAAI,CAAA;IACZ,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,KAAK,CAAA;IACb,CAAC;AACF,CAAC,CAAC,EAAE,CAAA;AAEJ,SAAS,OAAO,CAAC,KAA6B;IAC7C,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,aAAa,CAAC,CAAC,CAAA;IACvD,KAAK,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACtD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;QACjC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QAChD,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;IAC1B,CAAC;IACD,OAAO,IAAI,CAAA;AACZ,CAAC;AAED,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC;;UAErB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;;;;;CAK7B,CAAA;AAED,QAAQ,CAAC,6BAA6B,EAAE,GAAG,EAAE;IAC5C,EAAE,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;QACrD,MAAM,IAAI,GAAG,OAAO,CAAC;YACpB,iBAAiB,EAAE,oBAAoB;YACvC,UAAU,EAAE,iDAAiD;YAC7D,iBAAiB,EAAE,IAAI,CAAC,QAAQ,CAAC;SACjC,CAAC,CAAA;QAEF,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,WAAW,EAAE,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAA;QAE/D,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAClD,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAA;QACtD,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,CAAA;QACvE,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAA;IACzE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,8CAA8C,EAAE,KAAK,IAAI,EAAE;QAC7D,MAAM,IAAI,GAAG,OAAO,CAAC;YACpB,iBAAiB,EAAE,IAAI;YACvB,eAAe,EAAE,IAAI,CAAC,MAAM,CAAC;YAC7B,iBAAiB,EAAE,kCAAkC;SACrD,CAAC,CAAA;QAEF,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,WAAW,EAAE,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAA;QAE/D,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACtB,mEAAmE;QACnE,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;QACtE,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,oBAAoB,CAAC,CAAA;QACxE,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAA;QACzC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IAChF,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;QACjE,MAAM,IAAI,GAAG,OAAO,CAAC;YACpB,iBAAiB,EAAE,IAAI;YACvB,YAAY,EAAE,IAAI,CAAC,QAAQ,CAAC;YAC5B,YAAY,EAAE,IAAI,CAAC,QAAQ,CAAC;SAC5B,CAAC,CAAA;QAEF,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,WAAW,EAAE,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAA;QAE/D,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACtB,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,qBAAqB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC5E,uDAAuD;QACvD,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;IACvC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;QAC5D,MAAM,IAAI,GAAG,OAAO,CAAC;YACpB,iBAAiB,EAAE,IAAI;YACvB,YAAY,EAAE,6BAA6B;SAC3C,CAAC,CAAA;QAEF,MAAM,EAAE,EAAE,EAAE,WAAW,EAAE,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAA;QAErD,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACtB,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACpE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;QACtE,wEAAwE;QACxE,sDAAsD;QACtD,MAAM,IAAI,GAAG,OAAO,CAAC,EAAE,YAAY,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QAEjD,MAAM,EAAE,EAAE,EAAE,WAAW,EAAE,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAA;QAErD,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACrB,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,sBAAsB,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;IAC7F,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;QACjE,MAAM,IAAI,GAAG,OAAO,CAAC,EAAE,iBAAiB,EAAE,OAAO,EAAE,CAAC,CAAA;QAEpD,MAAM,EAAE,EAAE,EAAE,WAAW,EAAE,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAA;QAErD,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACtB,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,oBAAoB,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACzF,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;QACzD,MAAM,IAAI,GAAG,OAAO,CAAC;YACpB,iBAAiB,EAAE,IAAI;YACvB,UAAU,EAAE,8BAA8B;SAC1C,CAAC,CAAA;QAEF,MAAM,EAAE,EAAE,EAAE,WAAW,EAAE,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAA;QAErD,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACtB,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,gBAAgB,CAAC,EAAE,OAAO,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAA;IAC3F,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;QACtE,MAAM,IAAI,GAAG,OAAO,CAAC;YACpB,iBAAiB,EAAE,IAAI;YACvB,eAAe,EAAE,IAAI,CAAC,MAAM,CAAC;YAC7B,wBAAwB,EAAE,oBAAoB;YAC9C,kBAAkB,EAAE,IAAI,CAAC,QAAQ,CAAC;SAClC,CAAC,CAAA;QAEF,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,WAAW,EAAE,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAA;QAE/D,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACrB,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;QACtE,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,qBAAqB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC9E,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QAC3D,MAAM,IAAI,GAAG,OAAO,CAAC;YACpB,iBAAiB,EAAE,IAAI;YACvB,sBAAsB,EAAE,IAAI,CAAC,MAAM,CAAC;SACpC,CAAC,CAAA;QAEF,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAA;QAEjD,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,qBAAqB,CAAC,EAAE,OAAO,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAA;IAC/F,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;QACjE,MAAM,EAAE,EAAE,EAAE,WAAW,EAAE,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,0BAA0B,CAAC,CAAC,CAAA;QAE3F,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACtB,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAA;IAClD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;QAChD,MAAM,MAAM,CAAC,aAAa,CAAC,EAAY,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;IACrE,CAAC,CAAC,CAAA;AACH,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;QAChE,uEAAuE;QACvE,4BAA4B;QAC5B,MAAM,IAAI,GAAG,OAAO,CAAC;YACpB,iBAAiB,EAAE,kBAAkB;YACrC,UAAU,EAAE,sCAAsC;YAClD,YAAY,EAAE,kCAAkC;SAChD,CAAC,CAAA;QAEF,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,GAAG,MAAM,aAAa,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAA;QAEvE,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACrB,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAA;QACtD,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC,CAAA;QACxF,MAAM,CACL,QAAQ,CAAC,OAAO;aACd,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,cAAc,CAAC;aACxC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,YAAY,CAAC,CAC1C,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACZ,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;IACvC,CAAC,CAAC,CAAA;AACH,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IACzC,EAAE,CAAC,+BAA+B,EAAE,KAAK,IAAI,EAAE;QAC9C,MAAM,IAAI,GAAG,OAAO,CAAC,EAAE,iBAAiB,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QAE1E,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,aAAa,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;QAEtE,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAA;QAC5C,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACtC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;IACvC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;QACrD,mEAAmE;QACnE,uCAAuC;QACvC,MAAM,IAAI,GAAG,OAAO,CAAC,EAAE,iBAAiB,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QAE1E,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,aAAa,CAAC,IAAI,EAAE;YAC9C,OAAO,EAAE,EAA0B;SACnC,CAAC,CAAA;QAEF,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;QACxC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;IACvC,CAAC,CAAC,CAAA;AACH,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,oCAAoC,EAAE,GAAG,EAAE;IACnD,EAAE,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,CAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;QACxE,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAA;QAC7D,aAAa,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAA;QACrD,MAAM,IAAI,GAAG,OAAO,CAAC;YACpB,iBAAiB,EAAE,IAAI;YACvB,eAAe,EAAE,IAAI,CAAC,MAAM,CAAC;SAC7B,CAAC,CAAA;QACF,WAAW,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,CAAA;QAE/E,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAA;QAE3D,mEAAmE;QACnE,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;QACtE,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACzE,CAAC,CAAC,CAAA;AACH,CAAC,CAAC,CAAA"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=subagents.test.d.ts.map
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=supervisor-budget.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"supervisor-budget.test.d.ts","sourceRoot":"","sources":["../../../src/directory/__tests__/supervisor-budget.test.ts"],"names":[],"mappings":""}