salmon-loop 0.2.13 → 0.3.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 (224) hide show
  1. package/dist/cli/argv/headless-detection.js +27 -0
  2. package/dist/cli/chat-flow.js +11 -0
  3. package/dist/cli/chat.js +160 -24
  4. package/dist/cli/commands/chat.js +14 -7
  5. package/dist/cli/commands/flow-mode.js +63 -0
  6. package/dist/cli/commands/registry.js +2 -0
  7. package/dist/cli/commands/run/benchmark-artifacts.js +41 -0
  8. package/dist/cli/commands/run/early-errors.js +23 -0
  9. package/dist/cli/commands/run/handler.js +115 -27
  10. package/dist/cli/commands/run/headless-error-writer.js +8 -0
  11. package/dist/cli/commands/run/loop-params.js +2 -0
  12. package/dist/cli/commands/run/mode.js +2 -5
  13. package/dist/cli/commands/run/parse-options.js +16 -0
  14. package/dist/cli/commands/run/persist-session.js +10 -1
  15. package/dist/cli/commands/run/preflight.js +10 -0
  16. package/dist/cli/commands/run/reporter-factory.js +4 -0
  17. package/dist/cli/commands/run/runtime-llm.js +38 -11
  18. package/dist/cli/commands/run/runtime-options.js +2 -2
  19. package/dist/cli/commands/serve.js +97 -77
  20. package/dist/cli/commands/tool-names.js +78 -78
  21. package/dist/cli/headless/anthropic-stream-normalized-encoder.js +6 -1
  22. package/dist/cli/headless/json-protocol.js +37 -0
  23. package/dist/cli/headless/native-stream-normalized-encoder.js +6 -1
  24. package/dist/cli/headless/protocol-metadata.js +22 -0
  25. package/dist/cli/headless/stream-json-protocol.js +34 -1
  26. package/dist/cli/index.js +6 -4
  27. package/dist/cli/locales/en.js +30 -6
  28. package/dist/cli/program-bootstrap.js +10 -5
  29. package/dist/cli/program-commands.js +5 -1
  30. package/dist/cli/reporters/anthropic-stream.js +7 -1
  31. package/dist/cli/reporters/json.js +4 -0
  32. package/dist/cli/reporters/stream-json.js +17 -2
  33. package/dist/cli/run-cli.js +5 -3
  34. package/dist/cli/slash/runtime.js +27 -12
  35. package/dist/cli/ui/components/CommandInput.js +7 -3
  36. package/dist/cli/ui/components/CommandSuggestionList.js +1 -1
  37. package/dist/cli/utils/command-option-source.js +13 -0
  38. package/dist/cli/utils/verify-resolver.js +8 -4
  39. package/dist/cli/utils/worktree-prepare-resolver.js +7 -3
  40. package/dist/core/adapters/fs/file-adapter.js +6 -0
  41. package/dist/core/adapters/fs/filesystem.js +2 -1
  42. package/dist/core/adapters/git/git-adapter.js +78 -1
  43. package/dist/core/backends/salmon-loop/task-executor.js +1 -0
  44. package/dist/core/benchmark/patch-artifact.js +124 -0
  45. package/dist/core/benchmark/swe-bench.js +25 -0
  46. package/dist/core/config/load.js +18 -11
  47. package/dist/core/config/resolve-llm.js +12 -0
  48. package/dist/core/config/resolvers/server.js +0 -6
  49. package/dist/core/config/validate.js +73 -21
  50. package/dist/core/context/gatherers/metadata-gatherer.js +1 -0
  51. package/dist/core/context/gatherers/ripgrep-gatherer.js +84 -2
  52. package/dist/core/context/keywords.js +18 -4
  53. package/dist/core/context/service-deps.js +2 -2
  54. package/dist/core/context/service.js +8 -0
  55. package/dist/core/context/steps/context-gather.js +38 -0
  56. package/dist/core/context/summarization/summarizer.js +55 -12
  57. package/dist/core/context/targeting/target-resolver.js +4 -4
  58. package/dist/core/extensions/index.js +23 -5
  59. package/dist/core/extensions/merge.js +14 -0
  60. package/dist/core/extensions/paths.js +31 -0
  61. package/dist/core/extensions/schemas.js +8 -5
  62. package/dist/core/facades/cli-chat.js +6 -2
  63. package/dist/core/facades/cli-command-chat.js +1 -0
  64. package/dist/core/facades/cli-command-tool-names.js +2 -0
  65. package/dist/core/facades/cli-observability.js +1 -1
  66. package/dist/core/facades/cli-program-bootstrap.js +1 -0
  67. package/dist/core/facades/cli-run-handler.js +4 -2
  68. package/dist/core/facades/cli-run-persist-session.js +1 -0
  69. package/dist/core/facades/cli-serve.js +4 -4
  70. package/dist/core/facades/cli-utils-worktree.js +1 -1
  71. package/dist/core/failure/diagnostics.js +53 -1
  72. package/dist/core/grizzco/dsl/llm-strategy.js +4 -1
  73. package/dist/core/grizzco/engine/outcome/loop-result-mapper.js +67 -9
  74. package/dist/core/grizzco/engine/pipeline/pipeline.js +6 -2
  75. package/dist/core/grizzco/engine/transaction/attempt-failure.js +90 -15
  76. package/dist/core/grizzco/engine/transaction/report-mapper.js +17 -3
  77. package/dist/core/grizzco/engine/transaction/transaction-runner.js +165 -7
  78. package/dist/core/grizzco/flows/AutopilotFlow.js +18 -0
  79. package/dist/core/grizzco/flows/flow-dispatch.js +11 -0
  80. package/dist/core/grizzco/steps/answer.js +13 -14
  81. package/dist/core/grizzco/steps/autopilot.js +396 -0
  82. package/dist/core/grizzco/steps/cache-sharing.js +29 -0
  83. package/dist/core/grizzco/steps/explore.js +37 -21
  84. package/dist/core/grizzco/steps/generateReview.js +2 -5
  85. package/dist/core/grizzco/steps/patch/apply-check.js +10 -0
  86. package/dist/core/grizzco/steps/patch/diff-normalization.js +70 -0
  87. package/dist/core/grizzco/steps/patch/diff-salvage.js +46 -0
  88. package/dist/core/grizzco/steps/patch/prompt-input.js +42 -0
  89. package/dist/core/grizzco/steps/patch.js +105 -146
  90. package/dist/core/grizzco/steps/plan.js +101 -25
  91. package/dist/core/grizzco/steps/preflight.js +5 -6
  92. package/dist/core/grizzco/steps/request-assembly.js +78 -0
  93. package/dist/core/grizzco/steps/research.js +39 -36
  94. package/dist/core/grizzco/steps/tool-runtime.js +47 -0
  95. package/dist/core/grizzco/steps/verify-shared.js +23 -0
  96. package/dist/core/grizzco/steps/verify.js +13 -21
  97. package/dist/core/interaction/orchestration/facade.js +1 -1
  98. package/dist/core/llm/ai-sdk/chat-executor.js +2 -0
  99. package/dist/core/llm/ai-sdk/high-level-phase-specs.js +63 -0
  100. package/dist/core/llm/ai-sdk/message-mapper.js +40 -10
  101. package/dist/core/llm/ai-sdk/provider-factory.js +14 -0
  102. package/dist/core/llm/ai-sdk/request-params.js +113 -1
  103. package/dist/core/llm/ai-sdk/result-mapper.js +16 -0
  104. package/dist/core/llm/ai-sdk.js +112 -27
  105. package/dist/core/llm/capabilities.js +12 -0
  106. package/dist/core/llm/contracts/repair.js +36 -30
  107. package/dist/core/llm/errors.js +83 -2
  108. package/dist/core/llm/message-composition.js +7 -22
  109. package/dist/core/llm/phase-router.js +29 -10
  110. package/dist/core/llm/redact.js +28 -3
  111. package/dist/core/llm/registry.js +2 -0
  112. package/dist/core/llm/request-augmentation.js +55 -0
  113. package/dist/core/llm/request-envelope.js +334 -0
  114. package/dist/core/llm/shared-request-assembly.js +35 -0
  115. package/dist/core/llm/stream-utils.js +13 -4
  116. package/dist/core/llm/utils.js +18 -29
  117. package/dist/core/memory/relevant-retrieval.js +144 -0
  118. package/dist/core/observability/logger.js +11 -2
  119. package/dist/core/patch/diff.js +1 -0
  120. package/dist/core/prompts/registry.js +39 -2
  121. package/dist/core/prompts/runtime.js +50 -12
  122. package/dist/core/prompts/templates/phases/patch_user.hbs +2 -5
  123. package/dist/core/prompts/templates/phases/research_user.hbs +11 -0
  124. package/dist/core/prompts/templates/phases/review_user.hbs +3 -0
  125. package/dist/core/prompts/templates/system/answer_system.hbs +5 -0
  126. package/dist/core/prompts/templates/system/autopilot_system.hbs +11 -0
  127. package/dist/core/prompts/templates/system/explore_system.hbs +14 -23
  128. package/dist/core/prompts/templates/system/main_system.hbs +4 -16
  129. package/dist/core/prompts/templates/system/patch_system.hbs +39 -8
  130. package/dist/core/prompts/templates/system/plan_system.hbs +86 -1
  131. package/dist/core/prompts/templates/system/research_system.hbs +2 -0
  132. package/dist/core/protocols/a2a/agent-card.js +5 -3
  133. package/dist/core/protocols/a2a/sdk/executor.js +2 -1
  134. package/dist/core/protocols/a2a/sdk/server.js +0 -1
  135. package/dist/core/protocols/acp/formal-agent.js +300 -58
  136. package/dist/core/protocols/acp/handlers.js +5 -1
  137. package/dist/core/protocols/acp/permission-provider.js +1 -1
  138. package/dist/core/protocols/shared/flow-mode-mapping.js +23 -0
  139. package/dist/core/public-capabilities/flow-mode-metadata.js +39 -0
  140. package/dist/core/public-capabilities/projections.js +29 -0
  141. package/dist/core/public-capabilities/registry.js +26 -0
  142. package/dist/core/public-capabilities/types.js +2 -0
  143. package/dist/core/runtime/agent-server-runtime.js +47 -43
  144. package/dist/core/runtime/execution-profile.js +67 -0
  145. package/dist/core/session/artifact-state.js +160 -0
  146. package/dist/core/session/compaction/index.js +183 -0
  147. package/dist/core/session/compaction/microcompact.js +78 -0
  148. package/dist/core/session/compaction/tracking.js +48 -0
  149. package/dist/core/session/compaction/types.js +11 -0
  150. package/dist/core/session/compression.js +8 -0
  151. package/dist/core/session/manager.js +244 -8
  152. package/dist/core/session/pruning-strategy.js +55 -9
  153. package/dist/core/session/replacement-preview-provider.js +24 -0
  154. package/dist/core/session/replacement-state.js +131 -0
  155. package/dist/core/session/resume-repair/pipeline.js +79 -0
  156. package/dist/core/session/resume-repair/stages/load-raw-archive-state.js +40 -0
  157. package/dist/core/session/resume-repair/stages/reattach-runtime-state.js +8 -0
  158. package/dist/core/session/resume-repair/stages/recover-orphaned-branches.js +10 -0
  159. package/dist/core/session/resume-repair/stages/relink-boundary-and-tail.js +36 -0
  160. package/dist/core/session/resume-repair/stages/replay-startup-hooks.js +23 -0
  161. package/dist/core/session/resume-repair/stages/rescue-stale-metadata.js +17 -0
  162. package/dist/core/session/resume-repair/types.js +2 -0
  163. package/dist/core/session/summary-sync.js +164 -13
  164. package/dist/core/session/token-tracker.js +6 -0
  165. package/dist/core/skills/audit.js +34 -0
  166. package/dist/core/skills/bridge.js +84 -7
  167. package/dist/core/skills/discovery.js +94 -0
  168. package/dist/core/skills/feature-flags.js +52 -0
  169. package/dist/core/skills/index.js +1 -1
  170. package/dist/core/skills/loader.js +195 -20
  171. package/dist/core/skills/parser.js +296 -24
  172. package/dist/core/skills/permissions.js +117 -0
  173. package/dist/core/skills/runtime/MicroTaskRunner.js +10 -4
  174. package/dist/core/skills/runtime/SkillRunner.js +240 -61
  175. package/dist/core/strata/layers/shadow-driver/shadow-driver.js +37 -7
  176. package/dist/core/strata/layers/worktree.js +67 -10
  177. package/dist/core/strata/runtime/synchronizer.js +29 -2
  178. package/dist/core/streaming/stream-assembler.js +75 -31
  179. package/dist/core/sub-agent/context-snapshot.js +156 -0
  180. package/dist/core/sub-agent/core/loop.js +1 -1
  181. package/dist/core/sub-agent/core/manager.js +119 -20
  182. package/dist/core/sub-agent/dispatch-policy.js +29 -0
  183. package/dist/core/sub-agent/prefix-consistency.js +48 -0
  184. package/dist/core/sub-agent/registry-defaults.js +4 -0
  185. package/dist/core/sub-agent/tools/task-spawn.js +79 -2
  186. package/dist/core/sub-agent/types.js +134 -5
  187. package/dist/core/tools/audit.js +13 -4
  188. package/dist/core/tools/builtin/ast-grep.js +1 -1
  189. package/dist/core/tools/builtin/ast.js +1 -1
  190. package/dist/core/tools/builtin/benchmark.js +360 -0
  191. package/dist/core/tools/builtin/code-search/backends/rg.js +2 -1
  192. package/dist/core/tools/builtin/code-search/executor.js +6 -1
  193. package/dist/core/tools/builtin/code-search/spec.js +26 -2
  194. package/dist/core/tools/builtin/fs.js +256 -23
  195. package/dist/core/tools/builtin/git.js +2 -2
  196. package/dist/core/tools/builtin/index.js +51 -2
  197. package/dist/core/tools/builtin/interaction.js +8 -1
  198. package/dist/core/tools/builtin/plan.js +37 -15
  199. package/dist/core/tools/builtin/shell.js +1 -1
  200. package/dist/core/tools/loader.js +39 -16
  201. package/dist/core/tools/mapper.js +17 -3
  202. package/dist/core/tools/mcp/client.js +2 -1
  203. package/dist/core/tools/parallel/scheduler.js +35 -4
  204. package/dist/core/tools/permissions/permission-rules.js +5 -10
  205. package/dist/core/tools/policy.js +6 -1
  206. package/dist/core/tools/recoverable-tool-errors.js +10 -0
  207. package/dist/core/tools/router.js +24 -6
  208. package/dist/core/tools/session.js +458 -48
  209. package/dist/core/tools/tool-visibility.js +62 -0
  210. package/dist/core/tools/types.js +9 -1
  211. package/dist/core/types/execution.js +4 -0
  212. package/dist/core/types/flow-mode.js +8 -0
  213. package/dist/core/utils/path.js +52 -0
  214. package/dist/core/verification/runner.js +4 -1
  215. package/dist/core/version.js +17 -0
  216. package/dist/languages/typescript/index.js +4 -1
  217. package/dist/locales/en.js +35 -2
  218. package/dist/utils/eol.js +1 -1
  219. package/package.json +14 -7
  220. package/scripts/fix-es-abstract-compat.js +77 -0
  221. package/dist/core/runtime/fastify-server-bundle.js +0 -26
  222. package/dist/core/runtime/sidecar-fastify-plugin.js +0 -35
  223. package/dist/core/runtime/sidecar-paths.js +0 -47
  224. package/dist/core/runtime/sidecar-route-catalog.js +0 -103
@@ -0,0 +1,48 @@
1
+ import { createHash } from 'crypto';
2
+ function digest(value) {
3
+ return createHash('sha256').update(value, 'utf8').digest('hex');
4
+ }
5
+ export function buildSystemPrefixDigest(parts) {
6
+ return digest([parts.phase, parts.namespace ?? 'default', parts.contextHash ?? 'missing'].join('\u001f'));
7
+ }
8
+ export function buildToolSchemaHash(parts) {
9
+ const names = [...(parts.allowedToolNames ?? [])].sort();
10
+ return digest([parts.phase, ...names].join('\u001f'));
11
+ }
12
+ export function validateSharedPrefixConsistency(args) {
13
+ const requestSharing = args.requestSnapshot?.cacheSharing;
14
+ const runtimeSharing = args.runtimeSnapshot?.cacheSharing;
15
+ if (!runtimeSharing || !requestSharing) {
16
+ return { compatible: false, reason: 'missing_cache_sharing_snapshot' };
17
+ }
18
+ if (!runtimeSharing.contextHash ||
19
+ !runtimeSharing.toolSchemaHash ||
20
+ !runtimeSharing.systemPrefixDigest) {
21
+ return { compatible: false, reason: 'runtime_missing_cache_digest_fields' };
22
+ }
23
+ if (!requestSharing.contextHash ||
24
+ !requestSharing.toolSchemaHash ||
25
+ !requestSharing.systemPrefixDigest) {
26
+ return { compatible: false, reason: 'request_missing_cache_digest_fields' };
27
+ }
28
+ const expected = {
29
+ contextHash: runtimeSharing.contextHash,
30
+ toolSchemaHash: runtimeSharing.toolSchemaHash,
31
+ systemPrefixDigest: runtimeSharing.systemPrefixDigest,
32
+ };
33
+ const actual = {
34
+ contextHash: requestSharing.contextHash,
35
+ toolSchemaHash: requestSharing.toolSchemaHash,
36
+ systemPrefixDigest: requestSharing.systemPrefixDigest,
37
+ };
38
+ const compatible = expected.contextHash === actual.contextHash &&
39
+ expected.toolSchemaHash === actual.toolSchemaHash &&
40
+ expected.systemPrefixDigest === actual.systemPrefixDigest;
41
+ return {
42
+ compatible,
43
+ reason: compatible ? undefined : 'cache_critical_prefix_mismatch',
44
+ expected,
45
+ actual,
46
+ };
47
+ }
48
+ //# sourceMappingURL=prefix-consistency.js.map
@@ -9,6 +9,7 @@ const DEFAULT_SUB_AGENT_PROFILES = [
9
9
  stratagem: 'investigator',
10
10
  maxTokens: 50000,
11
11
  maxAttempts: 3,
12
+ timeoutMs: 60_000,
12
13
  },
13
14
  {
14
15
  id: 'surgeon',
@@ -20,6 +21,7 @@ const DEFAULT_SUB_AGENT_PROFILES = [
20
21
  stratagem: 'surgeon',
21
22
  maxTokens: 100000,
22
23
  maxAttempts: 5,
24
+ timeoutMs: 180_000,
23
25
  },
24
26
  {
25
27
  id: 'reviewer',
@@ -31,6 +33,7 @@ const DEFAULT_SUB_AGENT_PROFILES = [
31
33
  stratagem: 'investigator',
32
34
  maxTokens: 30000,
33
35
  maxAttempts: 2,
36
+ timeoutMs: 60_000,
34
37
  },
35
38
  {
36
39
  id: 'cleaner',
@@ -42,6 +45,7 @@ const DEFAULT_SUB_AGENT_PROFILES = [
42
45
  stratagem: 'surgeon',
43
46
  maxTokens: 50000,
44
47
  maxAttempts: 3,
48
+ timeoutMs: 120_000,
45
49
  },
46
50
  ];
47
51
  export function registerDefaultSubAgentProfiles(registry) {
@@ -1,8 +1,54 @@
1
1
  import { z } from 'zod';
2
2
  import { text } from '../../../locales/index.js';
3
+ import { recordAuditEvent } from '../../observability/audit-trail.js';
4
+ import { Phase } from '../../types/runtime.js';
5
+ import { mergeSubAgentContextSnapshot } from '../context-snapshot.js';
3
6
  import { createSubAgentController } from '../controller.js';
4
7
  import { SubAgentManager } from '../core/manager.js';
8
+ import { validateSharedPrefixConsistency } from '../prefix-consistency.js';
5
9
  import { SubAgentRequestSchema } from '../types.js';
10
+ function normalizeDispatchRequest(input, ctx) {
11
+ const requested = {
12
+ ...input,
13
+ session_target: input.session_target ?? 'isolated',
14
+ expected_output: input.expected_output ??
15
+ (input.agent_ref === 'surgeon' || input.agent_ref === 'cleaner'
16
+ ? 'patch'
17
+ : input.agent_ref === 'reviewer'
18
+ ? 'review'
19
+ : 'diagnosis'),
20
+ };
21
+ if (requested.session_target !== 'shared') {
22
+ return requested;
23
+ }
24
+ const consistency = validateSharedPrefixConsistency({
25
+ requestSnapshot: requested.contextSnapshot,
26
+ runtimeSnapshot: ctx.contextSnapshot,
27
+ });
28
+ if (!consistency.compatible) {
29
+ recordAuditEvent('sub_agent.shared.prefix_consistency_failed', {
30
+ metric: 'shared_fallback_rate',
31
+ fallbackMode: 'isolated',
32
+ reason: consistency.reason,
33
+ expected: consistency.expected,
34
+ actual: consistency.actual,
35
+ }, {
36
+ source: 'smallfry',
37
+ severity: 'medium',
38
+ scope: 'session',
39
+ phase: ctx.phase,
40
+ });
41
+ return {
42
+ ...requested,
43
+ session_target: 'isolated',
44
+ contextSnapshot: undefined,
45
+ };
46
+ }
47
+ return {
48
+ ...requested,
49
+ contextSnapshot: mergeSubAgentContextSnapshot(requested.contextSnapshot, ctx.contextSnapshot),
50
+ };
51
+ }
6
52
  /**
7
53
  * agent_dispatch (Internal: Smallfry Dispatcher)
8
54
  * The primary tool for spawning autonomous sub-agents to handle specialized sub-tasks.
@@ -13,17 +59,48 @@ export const subAgentTaskSpec = {
13
59
  intent: 'AGENT',
14
60
  description: text.smallfry.ui.spawnToolDescription,
15
61
  riskLevel: 'medium',
62
+ defaultTimeoutMs: 180_000,
16
63
  // This tool is proposal-only: it may read the repo and produce structured proposals,
17
64
  // but it MUST NOT mutate the user's workspace from within the calling phase.
18
65
  sideEffects: ['none', 'fs_read', 'git_read'],
19
66
  concurrency: 'parallel_ok', // Smallfrys handle their own isolation
20
- allowedPhases: ['PLAN', 'CONTEXT'],
67
+ allowedPhases: [Phase.PLAN, Phase.CONTEXT, Phase.AUTOPILOT],
21
68
  inputSchema: SubAgentRequestSchema,
22
69
  outputSchema: z.any(), // Maps to SubAgentResult
70
+ examples: [
71
+ {
72
+ description: 'Ask a read-only explorer to inspect failing tests before editing',
73
+ input: {
74
+ agent_ref: 'explorer',
75
+ task: 'Inspect src/order.js, src/inventory.js, and test/order.test.js. Identify why the order pricing tests fail and return a concise diagnosis with recommended files to edit.',
76
+ contextFiles: ['src/order.js', 'src/inventory.js', 'test/order.test.js'],
77
+ expected_output: 'diagnosis',
78
+ },
79
+ output: {
80
+ success: true,
81
+ agent_ref: 'explorer',
82
+ summary: '<diagnosis and recommended next steps>',
83
+ },
84
+ },
85
+ {
86
+ description: 'Ask a reviewer to audit a proposed implementation',
87
+ input: {
88
+ agent_ref: 'reviewer',
89
+ task: 'Review the current changes for correctness, missing edge cases, and behavior covered by tests. Return findings only.',
90
+ expected_output: 'review',
91
+ },
92
+ output: {
93
+ success: true,
94
+ agent_ref: 'reviewer',
95
+ summary: '<review findings>',
96
+ },
97
+ },
98
+ ],
23
99
  executor: async (input, ctx) => {
24
100
  const manager = new SubAgentManager(ctx, ctx.subAgentController ?? createSubAgentController());
101
+ const request = normalizeDispatchRequest(input, ctx);
25
102
  // Launch the Smallfry via the manager
26
- return await manager.execute(input);
103
+ return await manager.execute(request);
27
104
  },
28
105
  };
29
106
  //# sourceMappingURL=task-spawn.js.map
@@ -1,19 +1,148 @@
1
1
  import { z } from 'zod';
2
+ export const SUB_AGENT_CONTEXT_SNAPSHOT_VERSION = 1;
3
+ /**
4
+ * Versioned protocol contract for sub-agent context snapshot fields.
5
+ *
6
+ * - `clone`: mutable request/runtime data must be deep-cloned before dispatch.
7
+ * - `share`: session-scoped coordination metadata is intentionally shared.
8
+ */
9
+ export const SUB_AGENT_CONTEXT_SNAPSHOT_FIELD_SEMANTICS = {
10
+ conversationContext: 'clone',
11
+ artifactHints: 'clone',
12
+ toolCallingAudit: 'clone',
13
+ replacementState: 'clone',
14
+ planRuntime: 'share',
15
+ cacheSharing: 'share',
16
+ };
17
+ const SubAgentContextMessageSchema = z.object({
18
+ role: z.enum(['system', 'user', 'assistant', 'tool']),
19
+ content: z.string(),
20
+ name: z.string().optional(),
21
+ reasoning_content: z.string().optional(),
22
+ tool_calls: z.array(z.unknown()).optional(),
23
+ tool_call_id: z.string().optional(),
24
+ });
2
25
  /**
3
26
  * Zod Schema for validation
4
27
  */
5
28
  export const SubAgentRequestSchema = z.object({
6
29
  agent_ref: z
7
30
  .string()
8
- .describe('The specialized agent role to dispatch (e.g., explorer, surgeon)'),
9
- task: z.string().describe('The specific task or instruction for the sub-agent'),
10
- contextFiles: z.array(z.string()).optional(),
31
+ .min(1)
32
+ .describe('Required specialized agent role: explorer for read-only investigation, reviewer for audit, surgeon for implementation proposals, cleaner for lint/format cleanup.'),
33
+ task: z
34
+ .string()
35
+ .min(1)
36
+ .describe('Required concrete delegated mission. Include relevant files, failure symptoms, and the exact desired deliverable. Never leave this empty.'),
37
+ contextFiles: z
38
+ .array(z.string().describe('Repo-relative file path relevant to the delegated mission.'))
39
+ .optional()
40
+ .describe('Optional repo-relative files the sub-agent should inspect first.'),
11
41
  recursionDepth: z.number().optional().default(0),
12
42
  session_target: z
13
43
  .enum(['isolated', 'shared'])
14
44
  .default('isolated')
15
- .describe('Whether the session should be isolated (shadow worktree) or shared'),
16
- timeout_seconds: z.number().optional().describe('Maximum execution time in seconds'),
45
+ .describe('Optional runtime strategy. Omit unless shared context is explicitly needed.'),
46
+ timeout_seconds: z
47
+ .preprocess((value) => {
48
+ if (typeof value !== 'string')
49
+ return value;
50
+ const trimmed = value.trim();
51
+ if (!/^\d+(?:\.\d+)?$/.test(trimmed))
52
+ return value;
53
+ return Number(trimmed);
54
+ }, z.number().positive())
55
+ .optional()
56
+ .describe('Maximum execution time in seconds'),
57
+ expected_output: z
58
+ .enum(['diagnosis', 'patch', 'review'])
59
+ .optional()
60
+ .describe('Expected deliverable. Use patch for coder-style implementation proposals.'),
61
+ contextSnapshot: z
62
+ .object({
63
+ version: z.literal(SUB_AGENT_CONTEXT_SNAPSHOT_VERSION).optional().default(1),
64
+ conversationContext: z.array(SubAgentContextMessageSchema).optional(),
65
+ artifactHints: z
66
+ .object({
67
+ verifyArtifact: z
68
+ .object({
69
+ handle: z.string(),
70
+ mimeType: z.string(),
71
+ sha256: z.string(),
72
+ size: z.number(),
73
+ })
74
+ .optional(),
75
+ subAgentPatchArtifacts: z
76
+ .array(z.object({
77
+ handle: z.string(),
78
+ mimeType: z.string(),
79
+ sha256: z.string(),
80
+ size: z.number(),
81
+ }))
82
+ .optional(),
83
+ subAgentAuditArtifacts: z
84
+ .array(z.object({
85
+ handle: z.string(),
86
+ mimeType: z.string(),
87
+ sha256: z.string(),
88
+ size: z.number(),
89
+ }))
90
+ .optional(),
91
+ recentReadArtifacts: z
92
+ .array(z.object({
93
+ path: z.string(),
94
+ artifact: z.object({
95
+ handle: z.string(),
96
+ mimeType: z.string(),
97
+ sha256: z.string(),
98
+ size: z.number(),
99
+ }),
100
+ }))
101
+ .optional(),
102
+ toolResultPreviewArtifacts: z
103
+ .array(z.object({
104
+ label: z.string(),
105
+ artifact: z.object({
106
+ handle: z.string(),
107
+ mimeType: z.string(),
108
+ sha256: z.string(),
109
+ size: z.number(),
110
+ }),
111
+ }))
112
+ .optional(),
113
+ })
114
+ .optional(),
115
+ toolCallingAudit: z.array(z.record(z.string(), z.unknown())).optional(),
116
+ replacementState: z
117
+ .object({
118
+ schemaVersion: z.number(),
119
+ entries: z.record(z.string(), z.object({
120
+ toolResultId: z.string(),
121
+ decision: z.enum(['kept', 'replaced']),
122
+ preview: z.string(),
123
+ frozenAt: z.number(),
124
+ sourceArtifactHandle: z.string().optional(),
125
+ identityVersion: z.string(),
126
+ hashAlgorithm: z.string(),
127
+ })),
128
+ })
129
+ .optional(),
130
+ planRuntime: z
131
+ .object({
132
+ sessionId: z.string(),
133
+ planPathHint: z.string(),
134
+ })
135
+ .optional(),
136
+ cacheSharing: z
137
+ .object({
138
+ namespace: z.string().optional(),
139
+ contextHash: z.string().optional(),
140
+ toolSchemaHash: z.string().optional(),
141
+ systemPrefixDigest: z.string().optional(),
142
+ })
143
+ .optional(),
144
+ })
145
+ .optional(),
17
146
  budgetOverride: z
18
147
  .object({
19
148
  maxTokens: z.number().optional(),
@@ -1,5 +1,5 @@
1
1
  import { text } from '../../locales/index.js';
2
- import { getLogger } from '../observability/logger.js';
2
+ import { tryGetLogger } from '../observability/logger.js';
3
3
  import { Phase } from '../types/runtime.js';
4
4
  import { sanitizeErrorMessage } from '../utils/sanitizer.js';
5
5
  export class ToolAuditLogger {
@@ -29,7 +29,10 @@ export class ToolAuditLogger {
29
29
  decision,
30
30
  };
31
31
  this.logs.push(entry);
32
- getLogger().debug(text.audit.event('Start', spec.name, decision.allowed ? 'allowed' : 'denied'));
32
+ const logger = tryGetLogger();
33
+ if (logger) {
34
+ logger.debug(text.audit.event('Start', spec.name, decision.allowed ? 'allowed' : 'denied'));
35
+ }
33
36
  }
34
37
  onEnd(result) {
35
38
  const phase = (result.id && this.callPhaseIndex.get(result.id)) ||
@@ -48,7 +51,10 @@ export class ToolAuditLogger {
48
51
  errorMessage: result.error?.message ? sanitizeErrorMessage(result.error.message) : undefined,
49
52
  };
50
53
  this.logs.push(entry);
51
- getLogger().debug(text.audit.event('End', result.toolName, result.status));
54
+ const logger = tryGetLogger();
55
+ if (logger) {
56
+ logger.debug(text.audit.event('End', result.toolName, result.status));
57
+ }
52
58
  if (result.id) {
53
59
  this.callPhaseIndex.delete(result.id);
54
60
  }
@@ -69,7 +75,10 @@ export class ToolAuditLogger {
69
75
  authPersist: event.persist,
70
76
  };
71
77
  this.logs.push(entry);
72
- getLogger().debug(text.audit.event('Authorization', event.toolName, event.outcome));
78
+ const logger = tryGetLogger();
79
+ if (logger) {
80
+ logger.debug(text.audit.event('Authorization', event.toolName, event.outcome));
81
+ }
73
82
  this.options?.onAuthorizationDecision?.(event);
74
83
  const updated = this.updateAuthorizationSummary(event.source);
75
84
  if (updated && this.options?.onAuthorizationSummary) {
@@ -29,7 +29,7 @@ export const astGrepSpec = {
29
29
  })),
30
30
  error: z.string().optional(),
31
31
  }),
32
- allowedPhases: [Phase.CONTEXT, Phase.EXPLORE, Phase.PLAN],
32
+ allowedPhases: [Phase.CONTEXT, Phase.EXPLORE, Phase.PLAN, Phase.AUTOPILOT],
33
33
  };
34
34
  /**
35
35
  * Executes the ast-grep search.
@@ -29,7 +29,7 @@ export const astDefsRefsSpec = {
29
29
  location: z.any(),
30
30
  })),
31
31
  }),
32
- allowedPhases: [Phase.CONTEXT, Phase.EXPLORE, Phase.PLAN],
32
+ allowedPhases: [Phase.CONTEXT, Phase.EXPLORE, Phase.PLAN, Phase.AUTOPILOT],
33
33
  };
34
34
  /**
35
35
  * Builtin tool to query AST definitions and references