@namzu/sdk 6.1.0 → 7.0.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 (185) hide show
  1. package/CHANGELOG.md +361 -0
  2. package/dist/agents/ReactiveAgent.d.ts.map +1 -1
  3. package/dist/agents/ReactiveAgent.js +5 -0
  4. package/dist/agents/ReactiveAgent.js.map +1 -1
  5. package/dist/agents/SupervisorAgent.d.ts.map +1 -1
  6. package/dist/agents/SupervisorAgent.js +9 -0
  7. package/dist/agents/SupervisorAgent.js.map +1 -1
  8. package/dist/agents/__tests__/supervisor-coordinator-registration.test.js +31 -0
  9. package/dist/agents/__tests__/supervisor-coordinator-registration.test.js.map +1 -1
  10. package/dist/agents/runAgent.d.ts +19 -1
  11. package/dist/agents/runAgent.d.ts.map +1 -1
  12. package/dist/agents/runAgent.js +2 -0
  13. package/dist/agents/runAgent.js.map +1 -1
  14. package/dist/connector/mcp/__tests__/positional-arrays.test.d.ts +2 -0
  15. package/dist/connector/mcp/__tests__/positional-arrays.test.d.ts.map +1 -0
  16. package/dist/connector/mcp/__tests__/positional-arrays.test.js +142 -0
  17. package/dist/connector/mcp/__tests__/positional-arrays.test.js.map +1 -0
  18. package/dist/connector/mcp/adapter.d.ts.map +1 -1
  19. package/dist/connector/mcp/adapter.js +123 -8
  20. package/dist/connector/mcp/adapter.js.map +1 -1
  21. package/dist/constants/agent/index.d.ts +5 -0
  22. package/dist/constants/agent/index.d.ts.map +1 -1
  23. package/dist/constants/agent/index.js +5 -0
  24. package/dist/constants/agent/index.js.map +1 -1
  25. package/dist/constants/plugin/index.d.ts +15 -0
  26. package/dist/constants/plugin/index.d.ts.map +1 -1
  27. package/dist/constants/plugin/index.js +15 -0
  28. package/dist/constants/plugin/index.js.map +1 -1
  29. package/dist/gateway/__tests__/completion-inbox.test.js +17 -0
  30. package/dist/gateway/__tests__/completion-inbox.test.js.map +1 -1
  31. package/dist/gateway/completion-inbox.d.ts.map +1 -1
  32. package/dist/gateway/completion-inbox.js +17 -3
  33. package/dist/gateway/completion-inbox.js.map +1 -1
  34. package/dist/gateway/local.d.ts +11 -0
  35. package/dist/gateway/local.d.ts.map +1 -1
  36. package/dist/gateway/local.js +27 -1
  37. package/dist/gateway/local.js.map +1 -1
  38. package/dist/manager/agent/lifecycle.d.ts.map +1 -1
  39. package/dist/manager/agent/lifecycle.js +6 -0
  40. package/dist/manager/agent/lifecycle.js.map +1 -1
  41. package/dist/provider/thinking-support.d.ts +2 -1
  42. package/dist/provider/thinking-support.d.ts.map +1 -1
  43. package/dist/provider/thinking-support.js +14 -0
  44. package/dist/provider/thinking-support.js.map +1 -1
  45. package/dist/public-runtime.d.ts +1 -1
  46. package/dist/public-runtime.d.ts.map +1 -1
  47. package/dist/public-runtime.js +9 -1
  48. package/dist/public-runtime.js.map +1 -1
  49. package/dist/runtime/query/__tests__/context.test.js +18 -0
  50. package/dist/runtime/query/__tests__/context.test.js.map +1 -1
  51. package/dist/runtime/query/__tests__/effort-reaches-the-wire.test.d.ts +2 -0
  52. package/dist/runtime/query/__tests__/effort-reaches-the-wire.test.d.ts.map +1 -0
  53. package/dist/runtime/query/__tests__/effort-reaches-the-wire.test.js +118 -0
  54. package/dist/runtime/query/__tests__/effort-reaches-the-wire.test.js.map +1 -0
  55. package/dist/runtime/query/__tests__/run-survives-its-own-park.proc-test.d.ts +2 -0
  56. package/dist/runtime/query/__tests__/run-survives-its-own-park.proc-test.d.ts.map +1 -0
  57. package/dist/runtime/query/__tests__/run-survives-its-own-park.proc-test.js +122 -0
  58. package/dist/runtime/query/__tests__/run-survives-its-own-park.proc-test.js.map +1 -0
  59. package/dist/runtime/query/__tests__/tool-timeout.test.js +34 -0
  60. package/dist/runtime/query/__tests__/tool-timeout.test.js.map +1 -1
  61. package/dist/runtime/query/context.d.ts.map +1 -1
  62. package/dist/runtime/query/context.js +16 -1
  63. package/dist/runtime/query/context.js.map +1 -1
  64. package/dist/runtime/query/executor.d.ts.map +1 -1
  65. package/dist/runtime/query/executor.js +11 -1
  66. package/dist/runtime/query/executor.js.map +1 -1
  67. package/dist/runtime/query/iteration/index.d.ts.map +1 -1
  68. package/dist/runtime/query/iteration/index.js +5 -0
  69. package/dist/runtime/query/iteration/index.js.map +1 -1
  70. package/dist/runtime/query/iteration/phases/context.d.ts.map +1 -1
  71. package/dist/runtime/query/iteration/phases/context.js +43 -13
  72. package/dist/runtime/query/iteration/phases/context.js.map +1 -1
  73. package/dist/telemetry/__tests__/model-call-span.test.js +22 -4
  74. package/dist/telemetry/__tests__/model-call-span.test.js.map +1 -1
  75. package/dist/telemetry/__tests__/span-closure.test.js +12 -5
  76. package/dist/telemetry/__tests__/span-closure.test.js.map +1 -1
  77. package/dist/tools/builtins/__tests__/bash.proc-test.d.ts +2 -0
  78. package/dist/tools/builtins/__tests__/bash.proc-test.d.ts.map +1 -0
  79. package/dist/tools/builtins/__tests__/bash.proc-test.js +115 -0
  80. package/dist/tools/builtins/__tests__/bash.proc-test.js.map +1 -0
  81. package/dist/tools/builtins/__tests__/bash.test.d.ts +2 -0
  82. package/dist/tools/builtins/__tests__/bash.test.d.ts.map +1 -0
  83. package/dist/tools/builtins/__tests__/bash.test.js +65 -0
  84. package/dist/tools/builtins/__tests__/bash.test.js.map +1 -0
  85. package/dist/tools/builtins/bash.d.ts.map +1 -1
  86. package/dist/tools/builtins/bash.js +89 -17
  87. package/dist/tools/builtins/bash.js.map +1 -1
  88. package/dist/tools/coordinator/__tests__/allow-delegation.test.d.ts +2 -0
  89. package/dist/tools/coordinator/__tests__/allow-delegation.test.d.ts.map +1 -0
  90. package/dist/tools/coordinator/__tests__/allow-delegation.test.js +94 -0
  91. package/dist/tools/coordinator/__tests__/allow-delegation.test.js.map +1 -0
  92. package/dist/tools/coordinator/__tests__/wait-with-idle-bound.test.d.ts +2 -0
  93. package/dist/tools/coordinator/__tests__/wait-with-idle-bound.test.d.ts.map +1 -0
  94. package/dist/tools/coordinator/__tests__/wait-with-idle-bound.test.js +193 -0
  95. package/dist/tools/coordinator/__tests__/wait-with-idle-bound.test.js.map +1 -0
  96. package/dist/tools/coordinator/index.d.ts +28 -0
  97. package/dist/tools/coordinator/index.d.ts.map +1 -1
  98. package/dist/tools/coordinator/index.js +101 -62
  99. package/dist/tools/coordinator/index.js.map +1 -1
  100. package/dist/tools/coordinator/wait-with-idle-bound.d.ts +66 -0
  101. package/dist/tools/coordinator/wait-with-idle-bound.d.ts.map +1 -0
  102. package/dist/tools/coordinator/wait-with-idle-bound.js +78 -0
  103. package/dist/tools/coordinator/wait-with-idle-bound.js.map +1 -0
  104. package/dist/types/agent/base.d.ts +16 -0
  105. package/dist/types/agent/base.d.ts.map +1 -1
  106. package/dist/types/agent/gateway.d.ts +23 -0
  107. package/dist/types/agent/gateway.d.ts.map +1 -1
  108. package/dist/types/agent/lifecycle-event.d.ts +9 -1
  109. package/dist/types/agent/lifecycle-event.d.ts.map +1 -1
  110. package/dist/types/agent/supervisor.d.ts +27 -0
  111. package/dist/types/agent/supervisor.d.ts.map +1 -1
  112. package/dist/types/agent/task.d.ts +5 -0
  113. package/dist/types/agent/task.d.ts.map +1 -1
  114. package/dist/types/hitl/index.d.ts +10 -0
  115. package/dist/types/hitl/index.d.ts.map +1 -1
  116. package/dist/types/hitl/index.js.map +1 -1
  117. package/dist/types/probe/registry.d.ts +6 -0
  118. package/dist/types/probe/registry.d.ts.map +1 -1
  119. package/dist/types/run/config.d.ts +25 -0
  120. package/dist/types/run/config.d.ts.map +1 -1
  121. package/dist/utils/__tests__/abort-reason.test.d.ts +2 -0
  122. package/dist/utils/__tests__/abort-reason.test.d.ts.map +1 -0
  123. package/dist/utils/__tests__/abort-reason.test.js +48 -0
  124. package/dist/utils/__tests__/abort-reason.test.js.map +1 -0
  125. package/dist/utils/abort.d.ts +26 -0
  126. package/dist/utils/abort.d.ts.map +1 -1
  127. package/dist/utils/abort.js +34 -0
  128. package/dist/utils/abort.js.map +1 -1
  129. package/dist/verification/__tests__/rule-order-and-reason.test.d.ts +2 -0
  130. package/dist/verification/__tests__/rule-order-and-reason.test.d.ts.map +1 -0
  131. package/dist/verification/__tests__/rule-order-and-reason.test.js +126 -0
  132. package/dist/verification/__tests__/rule-order-and-reason.test.js.map +1 -0
  133. package/dist/verification/gate.d.ts +17 -1
  134. package/dist/verification/gate.d.ts.map +1 -1
  135. package/dist/verification/gate.js +58 -2
  136. package/dist/verification/gate.js.map +1 -1
  137. package/dist/verification/index.d.ts +1 -1
  138. package/dist/verification/index.d.ts.map +1 -1
  139. package/dist/verification/index.js +1 -1
  140. package/dist/verification/index.js.map +1 -1
  141. package/package.json +3 -2
  142. package/src/agents/ReactiveAgent.ts +5 -0
  143. package/src/agents/SupervisorAgent.ts +9 -0
  144. package/src/agents/__tests__/supervisor-coordinator-registration.test.ts +37 -0
  145. package/src/agents/runAgent.ts +22 -1
  146. package/src/connector/mcp/__tests__/positional-arrays.test.ts +183 -0
  147. package/src/connector/mcp/adapter.ts +131 -7
  148. package/src/constants/agent/index.ts +5 -0
  149. package/src/constants/plugin/index.ts +15 -0
  150. package/src/gateway/__tests__/completion-inbox.test.ts +23 -0
  151. package/src/gateway/completion-inbox.ts +17 -3
  152. package/src/gateway/local.ts +26 -1
  153. package/src/manager/agent/lifecycle.ts +6 -0
  154. package/src/provider/thinking-support.ts +19 -2
  155. package/src/public-runtime.ts +9 -0
  156. package/src/runtime/query/__tests__/context.test.ts +24 -0
  157. package/src/runtime/query/__tests__/effort-reaches-the-wire.test.ts +135 -0
  158. package/src/runtime/query/__tests__/run-survives-its-own-park.proc-test.ts +127 -0
  159. package/src/runtime/query/__tests__/tool-timeout.test.ts +38 -0
  160. package/src/runtime/query/context.ts +16 -1
  161. package/src/runtime/query/executor.ts +11 -1
  162. package/src/runtime/query/iteration/index.ts +5 -0
  163. package/src/runtime/query/iteration/phases/context.ts +41 -15
  164. package/src/telemetry/__tests__/model-call-span.test.ts +22 -5
  165. package/src/telemetry/__tests__/span-closure.test.ts +12 -5
  166. package/src/tools/builtins/__tests__/bash.proc-test.ts +142 -0
  167. package/src/tools/builtins/__tests__/bash.test.ts +79 -0
  168. package/src/tools/builtins/bash.ts +100 -18
  169. package/src/tools/coordinator/__tests__/allow-delegation.test.ts +120 -0
  170. package/src/tools/coordinator/__tests__/wait-with-idle-bound.test.ts +247 -0
  171. package/src/tools/coordinator/index.ts +112 -65
  172. package/src/tools/coordinator/wait-with-idle-bound.ts +142 -0
  173. package/src/types/agent/base.ts +17 -0
  174. package/src/types/agent/gateway.ts +24 -0
  175. package/src/types/agent/lifecycle-event.ts +7 -0
  176. package/src/types/agent/supervisor.ts +28 -0
  177. package/src/types/agent/task.ts +5 -0
  178. package/src/types/hitl/index.ts +10 -0
  179. package/src/types/probe/registry.ts +6 -0
  180. package/src/types/run/config.ts +26 -0
  181. package/src/utils/__tests__/abort-reason.test.ts +56 -0
  182. package/src/utils/abort.ts +34 -0
  183. package/src/verification/__tests__/rule-order-and-reason.test.ts +149 -0
  184. package/src/verification/gate.ts +61 -3
  185. package/src/verification/index.ts +1 -1
@@ -0,0 +1,65 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { BashTool } from '../bash.js';
3
+ /**
4
+ * What `bash` promises before it runs anything.
5
+ *
6
+ * These need no shell, so they stay in the unit suite. The ones that actually
7
+ * execute a command live in `bash.proc-test.ts` — spawning real processes
8
+ * beside 2594 unit tests flaked four unrelated timing-sensitive ones, so the
9
+ * process suite is separate and has its own CI step.
10
+ */
11
+ describe('the two clocks agree', () => {
12
+ it('declares a deadline of its own', () => {
13
+ // The executor reads a tool's `timeoutMs` before falling back to its
14
+ // generic default. With none declared, `bash` inherited that default —
15
+ // the same two minutes as its OWN default — so the two agreed by
16
+ // coincidence and diverged the moment a model asked for longer because
17
+ // it knew a build was slow. It got two minutes, from a clock it had not
18
+ // been told about, reported as an abandoned tool rather than as a
19
+ // command that ran out of time.
20
+ expect(BashTool.timeoutMs).toBeDefined();
21
+ });
22
+ it('puts that deadline above the longest the model may request', () => {
23
+ // So this tool's own clock is the one that fires, and the executor's is
24
+ // a backstop rather than a second clock racing it.
25
+ const accepted = BashTool.inputSchema.safeParse({ command: 'true', timeout: 10 * 60 * 1000 });
26
+ expect(accepted.success).toBe(true);
27
+ expect(BashTool.timeoutMs).toBeGreaterThan(10 * 60 * 1000);
28
+ });
29
+ it('refuses an over-long request rather than silently shortening it', () => {
30
+ // Refuse, do not degrade. A number the model was not told had changed
31
+ // is how it learns to distrust its own arguments.
32
+ const overCeiling = BashTool.inputSchema.safeParse({
33
+ command: 'true',
34
+ timeout: 60 * 60 * 1000,
35
+ });
36
+ expect(overCeiling.success, 'the ceiling is not enforced').toBe(false);
37
+ });
38
+ it('refuses a nonsensical deadline', () => {
39
+ expect(BashTool.inputSchema.safeParse({ command: 'true', timeout: 0 }).success).toBe(false);
40
+ expect(BashTool.inputSchema.safeParse({ command: 'true', timeout: -1 }).success).toBe(false);
41
+ });
42
+ it('applies its default when none is given', () => {
43
+ const parsed = BashTool.inputSchema.parse({ command: 'true' });
44
+ expect(parsed.timeout).toBeGreaterThan(0);
45
+ });
46
+ });
47
+ describe('the input is closed before a shell ever sees it', () => {
48
+ it('refuses an empty command', () => {
49
+ expect(BashTool.inputSchema.safeParse({ command: '' }).success).toBe(false);
50
+ });
51
+ it('accepts a numeric timeout sent as a string', () => {
52
+ // Providers do this, and the coercion is deliberate.
53
+ const parsed = BashTool.inputSchema.parse({ command: 'true', timeout: '5000' });
54
+ expect(parsed.timeout).toBe(5000);
55
+ });
56
+ });
57
+ describe('the danger flag reads the command', () => {
58
+ it('marks a destructive command destructive', () => {
59
+ expect(BashTool.isDestructive?.({ command: 'rm -rf /', timeout: 1000 })).toBe(true);
60
+ });
61
+ it('leaves an ordinary command alone', () => {
62
+ expect(BashTool.isDestructive?.({ command: 'ls -la', timeout: 1000 })).toBe(false);
63
+ });
64
+ });
65
+ //# sourceMappingURL=bash.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bash.test.js","sourceRoot":"","sources":["../../../../src/tools/builtins/__tests__/bash.test.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../../src/tools/builtins/bash.ts"],"names":[],"mappings":"AA6CA,eAAO,MAAM,QAAQ;;;EA4GnB,CAAA"}
1
+ {"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../../src/tools/builtins/bash.ts"],"names":[],"mappings":"AAkEA,eAAO,MAAM,QAAQ;;;EA6JnB,CAAA"}
@@ -17,14 +17,32 @@ const execAsync = promisify(exec);
17
17
  // slow; the point is that the DEFAULT is survivable.
18
18
  const DEFAULT_BASH_TIMEOUT_MS = readPositiveIntEnv('NAMZU_BASH_TIMEOUT_MS', 2 * 60 * 1000);
19
19
  const DEFAULT_BASH_MAX_BUFFER_BYTES = readPositiveIntEnv('NAMZU_BASH_MAX_BUFFER_BYTES', 100 * 1024 * 1024);
20
+ /**
21
+ * The longest deadline this tool will accept from the model.
22
+ *
23
+ * There are two clocks on a bash call and until now only one of them was
24
+ * declared. This tool enforces `input.timeout` itself; the EXECUTOR enforces
25
+ * a separate per-tool deadline, and with none declared here it fell back to
26
+ * its own generic default — also two minutes. The two agreed by coincidence,
27
+ * so a model that asked for five minutes because it knew the build was slow
28
+ * got two, from a clock it had not been told about, reported as an abandoned
29
+ * tool rather than as a command that ran out of time.
30
+ *
31
+ * So the tool declares a ceiling and the executor is given a deadline above
32
+ * it (see `timeoutMs` on the definition), which makes this the only clock
33
+ * that can fire in practice. A request past the ceiling is REFUSED rather
34
+ * than quietly clamped: the model asked for something specific, and silently
35
+ * giving it a different number is how it learns to distrust the answer.
36
+ */
37
+ const MAX_BASH_TIMEOUT_MS = readPositiveIntEnv('NAMZU_BASH_MAX_TIMEOUT_MS', 10 * 60 * 1000);
20
38
  const inputSchema = z.object({
21
39
  command: z
22
40
  .string()
23
41
  .min(1)
24
42
  .describe('The bash command to execute. Required, non-empty. Single command per call (use `&&` / `;` chaining for compound commands). Avoid heredocs that span more than a few hundred bytes — large content should be created with `write`, then extended with `edit` insertLine: "end", not piped into bash.'),
25
43
  timeout: z
26
- .preprocess((v) => (typeof v === 'string' ? Number(v) : v), z.number().default(DEFAULT_BASH_TIMEOUT_MS))
27
- .describe(`Command timeout in milliseconds. Default: ${DEFAULT_BASH_TIMEOUT_MS}`),
44
+ .preprocess((v) => (typeof v === 'string' ? Number(v) : v), z.number().positive().max(MAX_BASH_TIMEOUT_MS).default(DEFAULT_BASH_TIMEOUT_MS))
45
+ .describe(`Command timeout in milliseconds. Default: ${DEFAULT_BASH_TIMEOUT_MS}, maximum: ${MAX_BASH_TIMEOUT_MS}. For work that legitimately runs longer than the maximum, start it in the background and poll, rather than holding the turn open.`),
28
46
  });
29
47
  function isDangerousCommand(command) {
30
48
  return DANGEROUS_PATTERNS.some((pattern) => pattern.test(command));
@@ -38,6 +56,12 @@ export const BashTool = defineTool({
38
56
  readOnly: false,
39
57
  destructive: (input) => isDangerousCommand(input.command),
40
58
  concurrencySafe: false,
59
+ // Above the ceiling the input schema accepts, so the executor's deadline
60
+ // is a backstop rather than a second clock racing this tool's own. It used
61
+ // to be undefined, which meant the executor's generic default applied —
62
+ // the same two minutes as this tool's DEFAULT, so they agreed by accident
63
+ // and diverged the moment a model asked for longer.
64
+ timeoutMs: MAX_BASH_TIMEOUT_MS + 30_000,
41
65
  async execute(input, context) {
42
66
  if (isDangerousCommand(input.command)) {
43
67
  return {
@@ -111,23 +135,71 @@ export const BashTool = defineTool({
111
135
  // a Stop tore down the model stream and left the command running,
112
136
  // and the executor's deadline could only ever DETACH from the tool
113
137
  // rather than end the work it started.
114
- const { stdout, stderr } = await execAsync(input.command, {
115
- cwd: context.workingDirectory,
116
- timeout: input.timeout,
117
- env: { ...process.env, ...context.env },
118
- maxBuffer: DEFAULT_BASH_MAX_BUFFER_BYTES,
119
- signal: context.abortSignal,
120
- });
121
- const output = [stdout ? `STDOUT:\n${stdout}` : '', stderr ? `STDERR:\n${stderr}` : '']
122
- .filter(Boolean)
123
- .join('\n\n');
124
- return {
125
- success: true,
126
- output: output || '(no output)',
127
- data: { exitCode: 0 },
128
- };
138
+ // `exec` REJECTS on a non-zero exit, on its own timeout, and on a
139
+ // kill — and the rejection carries `stdout`, `stderr`, `code` and
140
+ // `killed`. Letting it propagate threw all of that away: the registry
141
+ // turned the throw into a structured failure, so the model was told a
142
+ // command failed and not one word about how.
143
+ //
144
+ // That is the common case, not an edge one. A failing test run and a
145
+ // failing build are the two things an agent runs bash for most, and
146
+ // both exit non-zero WITH the output that explains why. The sandbox
147
+ // branch above already reports all of it; this branch did not, so the
148
+ // same command told the model two different amounts depending on where
149
+ // it happened to run.
150
+ try {
151
+ const { stdout, stderr } = await execAsync(input.command, {
152
+ cwd: context.workingDirectory,
153
+ timeout: input.timeout,
154
+ env: { ...process.env, ...context.env },
155
+ maxBuffer: DEFAULT_BASH_MAX_BUFFER_BYTES,
156
+ signal: context.abortSignal,
157
+ });
158
+ return {
159
+ success: true,
160
+ output: formatShellOutput(stdout, stderr) || '(no output)',
161
+ data: { exitCode: 0 },
162
+ };
163
+ }
164
+ catch (err) {
165
+ const failure = err;
166
+ // A caller-owned Stop is the caller's, not a command failure.
167
+ if (context.abortSignal?.aborted)
168
+ throw err;
169
+ // `exec` reports its own timeout as a kill, and the distinction
170
+ // matters to the model: "ran out of time" is a different next move
171
+ // from "exited 1".
172
+ const timedOut = failure.killed === true && failure.signal === 'SIGTERM';
173
+ const exitCode = typeof failure.code === 'number' ? failure.code : undefined;
174
+ const output = formatShellOutput(failure.stdout, failure.stderr);
175
+ return {
176
+ success: false,
177
+ output: output || '(no output)',
178
+ data: {
179
+ ...(exitCode !== undefined ? { exitCode } : {}),
180
+ timedOut,
181
+ ...(failure.signal ? { signal: failure.signal } : {}),
182
+ },
183
+ error: timedOut
184
+ ? `Command timed out after ${input.timeout}ms. Any output it produced before the deadline is above.`
185
+ : exitCode !== undefined
186
+ ? `Command exited with code ${exitCode}`
187
+ : `Command failed: ${failure.message}`,
188
+ };
189
+ }
129
190
  },
130
191
  });
192
+ /**
193
+ * The two streams, labelled, with empty ones left out.
194
+ *
195
+ * Shared by the success and failure paths so a command tells the model the
196
+ * same shape either way — the failure path used to tell it nothing at all.
197
+ */
198
+ function formatShellOutput(stdout, stderr) {
199
+ return [stdout ? `STDOUT:\n${stdout}` : '', stderr ? `STDERR:\n${stderr}` : '']
200
+ .filter(Boolean)
201
+ .join('\n\n');
202
+ }
131
203
  function readPositiveIntEnv(key, fallback) {
132
204
  const value = process.env[key]?.trim();
133
205
  if (!value)
@@ -1 +1 @@
1
- {"version":3,"file":"bash.js","sourceRoot":"","sources":["../../../src/tools/builtins/bash.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bash.js","sourceRoot":"","sources":["../../../src/tools/builtins/bash.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=allow-delegation.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"allow-delegation.test.d.ts","sourceRoot":"","sources":["../../../../src/tools/coordinator/__tests__/allow-delegation.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,94 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { buildCoordinatorTools } from '../index.js';
3
+ /**
4
+ * Whether a run may delegate is not the same question as who it may delegate
5
+ * to, and only the caller can answer the first.
6
+ *
7
+ * The roster answers WHO. It cannot answer WHETHER, because two runs are
8
+ * indistinguishable in it: a supervisor whose roster happens to hold one
9
+ * specialist, where delegating is the point; and a run whose own persona IS
10
+ * that specialist, where delegating is delegating to itself. A host builds the
11
+ * second by putting a specialist's persona into the supervisor shell and its
12
+ * id into the roster — so a predicate comparing the roster against the
13
+ * executing agent sees two different ids and cheerfully says "can delegate".
14
+ *
15
+ * Measured before this existed: such a run carried `create_task`,
16
+ * `wait_for_task`, `cancel_task` and `agent_task_list`, byte-identical to a
17
+ * run that could actually delegate, and the model could only discover the
18
+ * refusal by spending a turn on it.
19
+ */
20
+ const gateway = {
21
+ listTasks: () => [],
22
+ onTaskCompleted: () => () => { },
23
+ };
24
+ function namesFor(opts) {
25
+ return buildCoordinatorTools({
26
+ gateway,
27
+ workingDirectory: '/tmp/test',
28
+ allowedAgentIds: opts.agentIds,
29
+ ...(opts.allowDelegation !== undefined ? { allowDelegation: opts.allowDelegation } : {}),
30
+ ...(opts.withHitl
31
+ ? { resumeHandler: (async () => ({ action: 'continue' })), runId: 'run_1' }
32
+ : {}),
33
+ }).map((t) => t.name);
34
+ }
35
+ describe('a run can decline to delegate while still naming who it would have called', () => {
36
+ it('withholds the delegation tools when delegation is off', () => {
37
+ const names = namesFor({ agentIds: ['specialist'], allowDelegation: false });
38
+ expect(names).not.toContain('create_task');
39
+ expect(names).not.toContain('wait_for_task');
40
+ expect(names).not.toContain('cancel_task');
41
+ });
42
+ it('produces exactly the empty-roster surface', () => {
43
+ // The two reasons differ but the outcome is the same one tool, so a
44
+ // reader does not have to hold two shapes in their head.
45
+ expect(namesFor({ agentIds: ['specialist'], allowDelegation: false })).toEqual(namesFor({ agentIds: [] }));
46
+ });
47
+ it('keeps the listing, because a run may still want to see what is running', () => {
48
+ expect(namesFor({ agentIds: ['specialist'], allowDelegation: false })).toContain('agent_task_list');
49
+ });
50
+ it('leaves the human channel alone — that is not delegation', () => {
51
+ // `approve_plan` and `ask_user_question` are the HITL park surface. A
52
+ // run that must not delegate needs them as much as any other.
53
+ const names = namesFor({ agentIds: ['specialist'], allowDelegation: false, withHitl: true });
54
+ expect(names).toContain('ask_user_question');
55
+ });
56
+ });
57
+ describe('an absent flag changes nothing', () => {
58
+ it('mounts the full surface, as it always did', () => {
59
+ const names = namesFor({ agentIds: ['specialist'] });
60
+ expect(names).toContain('create_task');
61
+ expect(names).toContain('wait_for_task');
62
+ expect(names).toContain('cancel_task');
63
+ expect(names).toContain('agent_task_list');
64
+ });
65
+ it('is identical to opting in explicitly', () => {
66
+ // So adopting the flag cannot change a caller that says yes out loud.
67
+ expect(namesFor({ agentIds: ['a', 'b'], allowDelegation: true })).toEqual(namesFor({ agentIds: ['a', 'b'] }));
68
+ });
69
+ it('still withholds everything on an empty roster, flag or no flag', () => {
70
+ expect(namesFor({ agentIds: [], allowDelegation: true })).toEqual(['agent_task_list']);
71
+ });
72
+ });
73
+ describe('the flag is absolute', () => {
74
+ it('cannot be overridden back on', () => {
75
+ // Worth a test precisely because the opposite is the intuitive guess:
76
+ // "explicit beats implicit" would say a runtime override should win.
77
+ // It cannot, mechanically — the override pass in SupervisorAgent runs
78
+ // over the array this builder returns, and there is no entry for it to
79
+ // act on. And it should not: both values come from the same caller in
80
+ // the same call, so "this run must not delegate" plus "give it
81
+ // create_task" is a caller contradicting itself, not one who knows
82
+ // something extra.
83
+ //
84
+ // Same rule the empty roster has always had.
85
+ const tools = buildCoordinatorTools({
86
+ gateway,
87
+ workingDirectory: '/tmp/test',
88
+ allowedAgentIds: ['specialist'],
89
+ allowDelegation: false,
90
+ });
91
+ expect(tools.find((t) => t.name === 'create_task')).toBeUndefined();
92
+ });
93
+ });
94
+ //# sourceMappingURL=allow-delegation.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"allow-delegation.test.js","sourceRoot":"","sources":["../../../../src/tools/coordinator/__tests__/allow-delegation.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=wait-with-idle-bound.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wait-with-idle-bound.test.d.ts","sourceRoot":"","sources":["../../../../src/tools/coordinator/__tests__/wait-with-idle-bound.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,193 @@
1
+ import { describe, expect, it, vi } from 'vitest';
2
+ import { describeWaitTimeout, waitForTaskWithBounds } from '../wait-with-idle-bound.js';
3
+ /**
4
+ * A wall clock cannot tell a slow worker from a stuck one.
5
+ *
6
+ * The bound before this was an hour of elapsed time, and an hour has to do
7
+ * two incompatible jobs: be long enough for a child doing real work, and
8
+ * short enough to notice one that wedged. It cannot be both, so a worker
9
+ * stuck in minute two held the supervisor for another fifty-eight, and one
10
+ * making steady progress at minute fifty-nine was killed for being slow.
11
+ *
12
+ * These tests drive both clocks with a fake one, because the real bounds are
13
+ * measured in minutes and a test that actually waits them out is a test
14
+ * nobody runs.
15
+ */
16
+ function gatewayFor(opts) {
17
+ let resolveWait;
18
+ const listeners = new Set();
19
+ const handle = {
20
+ taskId: 'tsk_1',
21
+ agentId: 'worker',
22
+ state: 'completed',
23
+ createdAt: 0,
24
+ completedAt: 1,
25
+ };
26
+ const gateway = {
27
+ waitForTask: () => new Promise((resolve) => {
28
+ resolveWait = resolve;
29
+ opts.settle?.(resolve);
30
+ }),
31
+ ...(opts.withProgress === false
32
+ ? {}
33
+ : {
34
+ onTaskProgress: (cb) => {
35
+ listeners.add(cb);
36
+ return () => listeners.delete(cb);
37
+ },
38
+ }),
39
+ };
40
+ return {
41
+ gateway,
42
+ progress: () => {
43
+ for (const cb of listeners)
44
+ cb('tsk_1');
45
+ },
46
+ finish: () => resolveWait?.(handle),
47
+ };
48
+ }
49
+ /** A clock the test moves by hand. */
50
+ function fakeClock() {
51
+ let t = 1_000_000;
52
+ return {
53
+ now: () => t,
54
+ advance: (ms) => {
55
+ t += ms;
56
+ },
57
+ };
58
+ }
59
+ describe('a worker that is still working is not killed for being slow', () => {
60
+ it('keeps waiting past the idle bound while progress keeps arriving', async () => {
61
+ vi.useFakeTimers();
62
+ try {
63
+ const clock = fakeClock();
64
+ const { gateway, progress, finish } = gatewayFor({});
65
+ const waiting = waitForTaskWithBounds(gateway, 'tsk_1', { runMs: 60_000, idleMs: 5_000 }, clock.now);
66
+ // Four times the idle bound in elapsed time, but never quiet for
67
+ // more than half of it.
68
+ for (let i = 0; i < 8; i += 1) {
69
+ clock.advance(2_500);
70
+ progress();
71
+ await vi.advanceTimersByTimeAsync(1_000);
72
+ }
73
+ finish();
74
+ await vi.advanceTimersByTimeAsync(1_000);
75
+ expect((await waiting).kind, 'a working worker was cut off').toBe('completed');
76
+ }
77
+ finally {
78
+ vi.useRealTimers();
79
+ }
80
+ });
81
+ });
82
+ describe('a worker that has gone quiet is reported as quiet', () => {
83
+ it('fires the idle bound and says which clock it was', async () => {
84
+ vi.useFakeTimers();
85
+ try {
86
+ const clock = fakeClock();
87
+ const { gateway } = gatewayFor({});
88
+ const waiting = waitForTaskWithBounds(gateway, 'tsk_1', { runMs: 600_000, idleMs: 5_000 }, clock.now);
89
+ clock.advance(6_000);
90
+ await vi.advanceTimersByTimeAsync(1_100);
91
+ const outcome = await waiting;
92
+ expect(outcome.kind).toBe('timeout');
93
+ if (outcome.kind !== 'timeout')
94
+ return;
95
+ // The distinction is the point: "went quiet" and "ran too long"
96
+ // are different diagnoses and the caller acts on the message.
97
+ expect(outcome.cause).toBe('idle');
98
+ expect(outcome.idleBoundArmed).toBe(true);
99
+ }
100
+ finally {
101
+ vi.useRealTimers();
102
+ }
103
+ });
104
+ it('says it went quiet, and that the worker was not cancelled', () => {
105
+ const text = describeWaitTimeout({
106
+ kind: 'timeout',
107
+ cause: 'idle',
108
+ elapsedMs: 30_000,
109
+ idleBoundArmed: true,
110
+ });
111
+ expect(text).toContain('went quiet');
112
+ // A wait that ran out is a statement about the WAITER. Losing an
113
+ // eight-minute worker's output because a short clock expired is the
114
+ // bug this whole area has been unpicking.
115
+ expect(text).toContain('not been cancelled');
116
+ });
117
+ });
118
+ describe('the run bound still catches a worker that never stops', () => {
119
+ it('fires on elapsed time even while progress keeps arriving', async () => {
120
+ vi.useFakeTimers();
121
+ try {
122
+ const clock = fakeClock();
123
+ const { gateway, progress } = gatewayFor({});
124
+ const waiting = waitForTaskWithBounds(gateway, 'tsk_1', { runMs: 10_000, idleMs: 5_000 }, clock.now);
125
+ for (let i = 0; i < 6; i += 1) {
126
+ clock.advance(2_000);
127
+ progress();
128
+ await vi.advanceTimersByTimeAsync(1_000);
129
+ }
130
+ const outcome = await waiting;
131
+ expect(outcome.kind).toBe('timeout');
132
+ if (outcome.kind !== 'timeout')
133
+ return;
134
+ expect(outcome.cause).toBe('run');
135
+ }
136
+ finally {
137
+ vi.useRealTimers();
138
+ }
139
+ });
140
+ });
141
+ describe('a gateway that cannot see its children', () => {
142
+ it('is bounded by the wall clock alone, as it was before', async () => {
143
+ vi.useFakeTimers();
144
+ try {
145
+ const clock = fakeClock();
146
+ const { gateway } = gatewayFor({ withProgress: false });
147
+ const waiting = waitForTaskWithBounds(gateway, 'tsk_1', { runMs: 10_000, idleMs: 1_000 }, clock.now);
148
+ // Far past the idle bound, and it must NOT fire — there is no
149
+ // signal, so silence carries no information.
150
+ clock.advance(5_000);
151
+ await vi.advanceTimersByTimeAsync(1_100);
152
+ clock.advance(6_000);
153
+ await vi.advanceTimersByTimeAsync(1_100);
154
+ const outcome = await waiting;
155
+ expect(outcome.kind).toBe('timeout');
156
+ if (outcome.kind !== 'timeout')
157
+ return;
158
+ expect(outcome.cause).toBe('run');
159
+ // And the degradation is visible rather than silent.
160
+ expect(outcome.idleBoundArmed).toBe(false);
161
+ }
162
+ finally {
163
+ vi.useRealTimers();
164
+ }
165
+ });
166
+ it('says so, instead of implying the worker was stuck', () => {
167
+ const text = describeWaitTimeout({
168
+ kind: 'timeout',
169
+ cause: 'run',
170
+ elapsedMs: 3_600_000,
171
+ idleBoundArmed: false,
172
+ });
173
+ expect(text).toContain('cannot report progress');
174
+ });
175
+ });
176
+ describe('a completion always wins', () => {
177
+ it('returns the handle rather than a timeout when the task finishes first', async () => {
178
+ vi.useFakeTimers();
179
+ try {
180
+ const clock = fakeClock();
181
+ const { gateway, finish } = gatewayFor({});
182
+ const waiting = waitForTaskWithBounds(gateway, 'tsk_1', { runMs: 10_000, idleMs: 5_000 }, clock.now);
183
+ finish();
184
+ await vi.advanceTimersByTimeAsync(10);
185
+ const outcome = await waiting;
186
+ expect(outcome.kind).toBe('completed');
187
+ }
188
+ finally {
189
+ vi.useRealTimers();
190
+ }
191
+ });
192
+ });
193
+ //# sourceMappingURL=wait-with-idle-bound.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wait-with-idle-bound.test.js","sourceRoot":"","sources":["../../../../src/tools/coordinator/__tests__/wait-with-idle-bound.test.ts"],"names":[],"mappings":"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"}
@@ -24,6 +24,15 @@ export interface CoordinatorToolsOptions {
24
24
  workingDirectory: string;
25
25
  runtimeContext?: AgentRuntimeContext;
26
26
  allowedAgentIds: string[];
27
+ /**
28
+ * May this run delegate at all? Defaults to true.
29
+ *
30
+ * Same field, same name, as SupervisorAgentConfig.allowDelegation — the
31
+ * name is kept identical deliberately. This options bag already renames
32
+ * agentIds to allowedAgentIds, and a second rename on the road between
33
+ * the config and the decision would make the road untraceable.
34
+ */
35
+ allowDelegation?: boolean;
27
36
  taskStore?: TaskStore;
28
37
  runId?: RunId;
29
38
  getPlanManager?: () => PlanManager | undefined;
@@ -89,5 +98,24 @@ export interface CoordinatorToolsOptions {
89
98
  * iteration ceiling both still apply above this.
90
99
  */
91
100
  export declare const DELEGATION_TIMEOUT_MS: number;
101
+ /**
102
+ * How long a delegated worker may say nothing before the wait gives up.
103
+ *
104
+ * The hour above answers "how long is too long". It cannot also answer
105
+ * "how quiet is too quiet", because it has to be generous enough for a
106
+ * child doing real work — which makes it useless as a stall detector. A
107
+ * worker wedged in its second minute held the supervisor for another
108
+ * fifty-eight under that number alone.
109
+ *
110
+ * Five minutes of silence, because a worker between tool calls can be
111
+ * quiet for a while legitimately — a long model turn emits nothing until
112
+ * it starts streaming — and the cost of guessing low is killing a wait on
113
+ * a worker that was fine. Guessing high only delays a diagnosis. Set
114
+ * `NAMZU_DELEGATION_IDLE_MS` to change it.
115
+ *
116
+ * Only armed when the gateway can report progress at all; see
117
+ * `TaskGateway.onTaskProgress`.
118
+ */
119
+ export declare const DELEGATION_IDLE_MS: number;
92
120
  export declare function buildCoordinatorTools(opts: CoordinatorToolsOptions): ToolDefinition[];
93
121
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/coordinator/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAA;AACxE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAA;AAClE,OAAO,KAAK,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAA;AAChG,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAA;AACpE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAA;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAsB,MAAM,2BAA2B,CAAA;AAClF,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAA;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAA;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAK/D,MAAM,MAAM,oBAAoB,GAAG,CAClC,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE;IACL,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC1B,KACG,IAAI,CAAA;AAET,MAAM,WAAW,uBAAuB;IACvC,OAAO,EAAE,WAAW,CAAA;IACpB,gBAAgB,EAAE,MAAM,CAAA;IACxB,cAAc,CAAC,EAAE,mBAAmB,CAAA;IACpC,eAAe,EAAE,MAAM,EAAE,CAAA;IAEzB,SAAS,CAAC,EAAE,SAAS,CAAA;IAErB,KAAK,CAAC,EAAE,KAAK,CAAA;IAEb,cAAc,CAAC,EAAE,MAAM,WAAW,GAAG,SAAS,CAAA;IAE9C,cAAc,CAAC,EAAE,oBAAoB,CAAA;IAErC;;;;;;;;OAQG;IACH,eAAe,CAAC,EAAE,eAAe,CAAA;IAEjC;;;;;OAKG;IACH,aAAa,CAAC,EAAE,aAAa,CAAA;IAE7B;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,oBAAoB,CAAA;IAEpC;;;;;;;;OAQG;IACH,cAAc,CAAC,EAAE,cAAc,CAAA;CAC/B;AA+ID;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,qBAAqB,QAAiB,CAAA;AAEnD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,uBAAuB,GAAG,cAAc,EAAE,CAkvBrF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/coordinator/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAA;AACxE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAA;AAClE,OAAO,KAAK,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAA;AAChG,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAA;AACpE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAA;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAsB,MAAM,2BAA2B,CAAA;AAClF,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAA;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAA;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAM/D,MAAM,MAAM,oBAAoB,GAAG,CAClC,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE;IACL,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC1B,KACG,IAAI,CAAA;AAET,MAAM,WAAW,uBAAuB;IACvC,OAAO,EAAE,WAAW,CAAA;IACpB,gBAAgB,EAAE,MAAM,CAAA;IACxB,cAAc,CAAC,EAAE,mBAAmB,CAAA;IACpC,eAAe,EAAE,MAAM,EAAE,CAAA;IAEzB;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,OAAO,CAAA;IAEzB,SAAS,CAAC,EAAE,SAAS,CAAA;IAErB,KAAK,CAAC,EAAE,KAAK,CAAA;IAEb,cAAc,CAAC,EAAE,MAAM,WAAW,GAAG,SAAS,CAAA;IAE9C,cAAc,CAAC,EAAE,oBAAoB,CAAA;IAErC;;;;;;;;OAQG;IACH,eAAe,CAAC,EAAE,eAAe,CAAA;IAEjC;;;;;OAKG;IACH,aAAa,CAAC,EAAE,aAAa,CAAA;IAE7B;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,oBAAoB,CAAA;IAEpC;;;;;;;;OAQG;IACH,cAAc,CAAC,EAAE,cAAc,CAAA;CAC/B;AA+ID;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,qBAAqB,QAAiB,CAAA;AAEnD;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,kBAAkB,QAAgE,CAAA;AAS/F,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,uBAAuB,GAAG,cAAc,EAAE,CA2vBrF"}