@mcoda/codali 0.1.133 → 0.1.135-codali.2

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 (232) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/ORCHESTRATION.md +387 -0
  3. package/README.md +103 -1
  4. package/config/alternate-local.example.json +49 -0
  5. package/config/docdex-runtime.json +21 -0
  6. package/config/orchestration.schema.json +548 -0
  7. package/config/raijin-suku.example.json +172 -0
  8. package/config/terminal-long-scenarios.v1.json +70 -0
  9. package/dist/agents/RoleResolution.d.ts.map +1 -1
  10. package/dist/agents/RoleResolution.js +4 -4
  11. package/dist/api/CodaliApi.d.ts +16 -0
  12. package/dist/api/CodaliApi.d.ts.map +1 -1
  13. package/dist/api/CodaliApi.js +39 -10
  14. package/dist/cli/AskCommand.d.ts +3 -0
  15. package/dist/cli/AskCommand.d.ts.map +1 -1
  16. package/dist/cli/AskCommand.js +76 -13
  17. package/dist/cli/RunCommand.d.ts +4 -0
  18. package/dist/cli/RunCommand.d.ts.map +1 -1
  19. package/dist/cli/RunCommand.js +110 -24
  20. package/dist/cli/TerminalCommand.d.ts +35 -0
  21. package/dist/cli/TerminalCommand.d.ts.map +1 -0
  22. package/dist/cli/TerminalCommand.js +616 -0
  23. package/dist/cli/TerminalCredentials.d.ts +3 -0
  24. package/dist/cli/TerminalCredentials.d.ts.map +1 -0
  25. package/dist/cli/TerminalCredentials.js +89 -0
  26. package/dist/cli/TerminalInput.d.ts +24 -0
  27. package/dist/cli/TerminalInput.d.ts.map +1 -0
  28. package/dist/cli/TerminalInput.js +98 -0
  29. package/dist/cli/TerminalText.d.ts +10 -0
  30. package/dist/cli/TerminalText.d.ts.map +1 -0
  31. package/dist/cli/TerminalText.js +53 -0
  32. package/dist/cli.d.ts.map +1 -1
  33. package/dist/cli.js +33 -4
  34. package/dist/cognitive/ConfiguredPipeline.d.ts +34 -0
  35. package/dist/cognitive/ConfiguredPipeline.d.ts.map +1 -0
  36. package/dist/cognitive/ConfiguredPipeline.js +50 -0
  37. package/dist/cognitive/ValidationRunner.d.ts +4 -0
  38. package/dist/cognitive/ValidationRunner.d.ts.map +1 -1
  39. package/dist/cognitive/ValidationRunner.js +18 -41
  40. package/dist/config/NodeOrchestration.d.ts +21 -0
  41. package/dist/config/NodeOrchestration.d.ts.map +1 -0
  42. package/dist/config/NodeOrchestration.js +54 -0
  43. package/dist/config/OrchestrationConfig.d.ts +100 -0
  44. package/dist/config/OrchestrationConfig.d.ts.map +1 -0
  45. package/dist/config/OrchestrationConfig.js +245 -0
  46. package/dist/connectors/mcp/McpClient.d.ts +3 -1
  47. package/dist/connectors/mcp/McpClient.d.ts.map +1 -1
  48. package/dist/connectors/mcp/McpClient.js +3 -2
  49. package/dist/connectors/mcp/McpServerRegistry.d.ts +2 -2
  50. package/dist/connectors/mcp/McpServerRegistry.d.ts.map +1 -1
  51. package/dist/connectors/mcp/McpServerRegistry.js +39 -16
  52. package/dist/connectors/mcp/McpToolAdapter.js +2 -2
  53. package/dist/connectors/media/ConfiguredMediaTools.d.ts +6 -0
  54. package/dist/connectors/media/ConfiguredMediaTools.d.ts.map +1 -0
  55. package/dist/connectors/media/ConfiguredMediaTools.js +41 -0
  56. package/dist/connectors/media/ImageGenerationTool.js +3 -3
  57. package/dist/connectors/media/MediaArtifactReceipt.d.ts +5 -0
  58. package/dist/connectors/media/MediaArtifactReceipt.d.ts.map +1 -0
  59. package/dist/connectors/media/MediaArtifactReceipt.js +65 -0
  60. package/dist/connectors/media/MediaJobStore.d.ts +68 -0
  61. package/dist/connectors/media/MediaJobStore.d.ts.map +1 -0
  62. package/dist/connectors/media/MediaJobStore.js +199 -0
  63. package/dist/connectors/media/MediaJobWorker.d.ts +2 -0
  64. package/dist/connectors/media/MediaJobWorker.d.ts.map +1 -0
  65. package/dist/connectors/media/MediaJobWorker.js +65 -0
  66. package/dist/connectors/media/RemoteMediaJob.d.ts +6 -0
  67. package/dist/connectors/media/RemoteMediaJob.d.ts.map +1 -0
  68. package/dist/connectors/media/RemoteMediaJob.js +80 -0
  69. package/dist/docdex/DocdexClient.d.ts +18 -1
  70. package/dist/docdex/DocdexClient.d.ts.map +1 -1
  71. package/dist/docdex/DocdexClient.js +135 -19
  72. package/dist/docdex/ManagedDocdex.d.ts +29 -0
  73. package/dist/docdex/ManagedDocdex.d.ts.map +1 -0
  74. package/dist/docdex/ManagedDocdex.js +215 -0
  75. package/dist/docdex/ManagedRuntime.d.ts +28 -0
  76. package/dist/docdex/ManagedRuntime.d.ts.map +1 -0
  77. package/dist/docdex/ManagedRuntime.js +212 -0
  78. package/dist/eval/EvaluationProcess.d.ts +13 -0
  79. package/dist/eval/EvaluationProcess.d.ts.map +1 -0
  80. package/dist/eval/EvaluationProcess.js +76 -0
  81. package/dist/eval/LongWorkflowJourney.d.ts +34 -0
  82. package/dist/eval/LongWorkflowJourney.d.ts.map +1 -0
  83. package/dist/eval/LongWorkflowJourney.js +243 -0
  84. package/dist/eval/PlanningCorpus.d.ts +45 -0
  85. package/dist/eval/PlanningCorpus.d.ts.map +1 -0
  86. package/dist/eval/PlanningCorpus.js +189 -0
  87. package/dist/eval/PlanningCorpusRunner.d.ts +13 -0
  88. package/dist/eval/PlanningCorpusRunner.d.ts.map +1 -0
  89. package/dist/eval/PlanningCorpusRunner.js +89 -0
  90. package/dist/eval/TerminalCorpusRunner.d.ts +36 -0
  91. package/dist/eval/TerminalCorpusRunner.d.ts.map +1 -0
  92. package/dist/eval/TerminalCorpusRunner.js +222 -0
  93. package/dist/eval/TerminalTaskCorpus.d.ts +26 -0
  94. package/dist/eval/TerminalTaskCorpus.d.ts.map +1 -0
  95. package/dist/eval/TerminalTaskCorpus.js +105 -0
  96. package/dist/eval/TerminalWorkflowCorpus.d.ts +11 -0
  97. package/dist/eval/TerminalWorkflowCorpus.d.ts.map +1 -0
  98. package/dist/eval/TerminalWorkflowCorpus.js +116 -0
  99. package/dist/eval/fixtures/TerminalRecoveryJourney.d.ts +4 -0
  100. package/dist/eval/fixtures/TerminalRecoveryJourney.d.ts.map +1 -0
  101. package/dist/eval/fixtures/TerminalRecoveryJourney.js +132 -0
  102. package/dist/gateway/CodaliGateway.d.ts +2 -0
  103. package/dist/gateway/CodaliGateway.d.ts.map +1 -1
  104. package/dist/gateway/CodaliGateway.js +16 -4
  105. package/dist/gateway/ConfiguredGateway.d.ts +23 -0
  106. package/dist/gateway/ConfiguredGateway.d.ts.map +1 -0
  107. package/dist/gateway/ConfiguredGateway.js +44 -0
  108. package/dist/gateway/GatewayTracer.d.ts +1 -1
  109. package/dist/gateway/GatewayTracer.d.ts.map +1 -1
  110. package/dist/gateway/GatewayTracer.js +2 -27
  111. package/dist/gateway/LocalGatewayTaskRunner.d.ts.map +1 -1
  112. package/dist/gateway/LocalGatewayTaskRunner.js +13 -1
  113. package/dist/index.d.ts +23 -0
  114. package/dist/index.d.ts.map +1 -1
  115. package/dist/index.js +12 -0
  116. package/dist/permissions/PermissionGate.d.ts +44 -0
  117. package/dist/permissions/PermissionGate.d.ts.map +1 -0
  118. package/dist/permissions/PermissionGate.js +97 -0
  119. package/dist/providers/ConfiguredEmbeddings.d.ts +43 -0
  120. package/dist/providers/ConfiguredEmbeddings.d.ts.map +1 -0
  121. package/dist/providers/ConfiguredEmbeddings.js +87 -0
  122. package/dist/providers/ConfiguredModelScope.d.ts +69 -0
  123. package/dist/providers/ConfiguredModelScope.d.ts.map +1 -0
  124. package/dist/providers/ConfiguredModelScope.js +113 -0
  125. package/dist/providers/ConfiguredProvider.d.ts +79 -0
  126. package/dist/providers/ConfiguredProvider.d.ts.map +1 -0
  127. package/dist/providers/ConfiguredProvider.js +238 -0
  128. package/dist/providers/ModelServiceError.d.ts +10 -0
  129. package/dist/providers/ModelServiceError.d.ts.map +1 -0
  130. package/dist/providers/ModelServiceError.js +45 -0
  131. package/dist/providers/MswarmWorkerProvider.d.ts.map +1 -1
  132. package/dist/providers/MswarmWorkerProvider.js +4 -0
  133. package/dist/providers/OpenAiCompatibleProvider.d.ts.map +1 -1
  134. package/dist/providers/OpenAiCompatibleProvider.js +134 -52
  135. package/dist/providers/ProviderTypes.d.ts +14 -0
  136. package/dist/providers/ProviderTypes.d.ts.map +1 -1
  137. package/dist/runtime/CodaliJobRuntime.d.ts +6 -0
  138. package/dist/runtime/CodaliJobRuntime.d.ts.map +1 -1
  139. package/dist/runtime/CodaliJobRuntime.js +36 -1
  140. package/dist/runtime/CodaliRuntime.d.ts +30 -0
  141. package/dist/runtime/CodaliRuntime.d.ts.map +1 -1
  142. package/dist/runtime/CodaliRuntime.js +71 -1
  143. package/dist/runtime/CompletionReport.d.ts +5 -0
  144. package/dist/runtime/CompletionReport.d.ts.map +1 -0
  145. package/dist/runtime/CompletionReport.js +12 -0
  146. package/dist/runtime/ProgressTracker.d.ts +17 -0
  147. package/dist/runtime/ProgressTracker.d.ts.map +1 -0
  148. package/dist/runtime/ProgressTracker.js +27 -0
  149. package/dist/runtime/RequestedTestEvidence.d.ts +12 -0
  150. package/dist/runtime/RequestedTestEvidence.d.ts.map +1 -0
  151. package/dist/runtime/RequestedTestEvidence.js +16 -0
  152. package/dist/runtime/RequiredRetrieval.d.ts +13 -0
  153. package/dist/runtime/RequiredRetrieval.d.ts.map +1 -0
  154. package/dist/runtime/RequiredRetrieval.js +25 -0
  155. package/dist/runtime/ReviewSource.d.ts +6 -0
  156. package/dist/runtime/ReviewSource.d.ts.map +1 -0
  157. package/dist/runtime/ReviewSource.js +38 -0
  158. package/dist/runtime/Runner.d.ts +13 -0
  159. package/dist/runtime/Runner.d.ts.map +1 -1
  160. package/dist/runtime/Runner.js +220 -158
  161. package/dist/runtime/SecretRedaction.d.ts +11 -0
  162. package/dist/runtime/SecretRedaction.d.ts.map +1 -0
  163. package/dist/runtime/SecretRedaction.js +85 -0
  164. package/dist/runtime/SessionController.d.ts +148 -0
  165. package/dist/runtime/SessionController.d.ts.map +1 -0
  166. package/dist/runtime/SessionController.js +1356 -0
  167. package/dist/runtime/StructuralEvidence.d.ts +22 -0
  168. package/dist/runtime/StructuralEvidence.d.ts.map +1 -0
  169. package/dist/runtime/StructuralEvidence.js +87 -0
  170. package/dist/runtime/TaskReviewContext.d.ts +34 -0
  171. package/dist/runtime/TaskReviewContext.d.ts.map +1 -0
  172. package/dist/runtime/TaskReviewContext.js +34 -0
  173. package/dist/runtime/ValidationOutput.d.ts +5 -0
  174. package/dist/runtime/ValidationOutput.d.ts.map +1 -0
  175. package/dist/runtime/ValidationOutput.js +32 -0
  176. package/dist/runtime/VerificationCommand.d.ts +3 -0
  177. package/dist/runtime/VerificationCommand.d.ts.map +1 -0
  178. package/dist/runtime/VerificationCommand.js +48 -0
  179. package/dist/runtime/WorkStatusPage.d.ts +15 -0
  180. package/dist/runtime/WorkStatusPage.d.ts.map +1 -0
  181. package/dist/runtime/WorkStatusPage.js +58 -0
  182. package/dist/runtime/WorkspaceLedger.d.ts +13 -0
  183. package/dist/runtime/WorkspaceLedger.d.ts.map +1 -0
  184. package/dist/runtime/WorkspaceLedger.js +145 -0
  185. package/dist/runtime/WorkspaceLock.d.ts.map +1 -1
  186. package/dist/runtime/WorkspaceLock.js +20 -17
  187. package/dist/runtime/WorkspaceSnapshot.d.ts +13 -0
  188. package/dist/runtime/WorkspaceSnapshot.d.ts.map +1 -0
  189. package/dist/runtime/WorkspaceSnapshot.js +88 -0
  190. package/dist/session/AtomicState.d.ts +13 -0
  191. package/dist/session/AtomicState.d.ts.map +1 -0
  192. package/dist/session/AtomicState.js +109 -0
  193. package/dist/session/SessionStoragePath.d.ts +15 -0
  194. package/dist/session/SessionStoragePath.d.ts.map +1 -0
  195. package/dist/session/SessionStoragePath.js +89 -0
  196. package/dist/session/SessionStore.d.ts +9 -0
  197. package/dist/session/SessionStore.d.ts.map +1 -1
  198. package/dist/session/SessionStore.js +181 -47
  199. package/dist/session/WorkState.d.ts +23 -0
  200. package/dist/session/WorkState.d.ts.map +1 -0
  201. package/dist/session/WorkState.js +367 -0
  202. package/dist/session/WorkTypes.d.ts +94 -0
  203. package/dist/session/WorkTypes.d.ts.map +1 -0
  204. package/dist/session/WorkTypes.js +1 -0
  205. package/dist/tools/ToolRegistry.d.ts +2 -0
  206. package/dist/tools/ToolRegistry.d.ts.map +1 -1
  207. package/dist/tools/ToolRegistry.js +12 -2
  208. package/dist/tools/ToolTypes.d.ts +16 -0
  209. package/dist/tools/ToolTypes.d.ts.map +1 -1
  210. package/dist/tools/docdex/DocdexTools.d.ts +2 -0
  211. package/dist/tools/docdex/DocdexTools.d.ts.map +1 -1
  212. package/dist/tools/docdex/DocdexTools.js +17 -2
  213. package/dist/tools/filesystem/FileTools.d.ts.map +1 -1
  214. package/dist/tools/filesystem/FileTools.js +30 -10
  215. package/dist/tools/shell/AsyncProcess.d.ts +16 -0
  216. package/dist/tools/shell/AsyncProcess.d.ts.map +1 -0
  217. package/dist/tools/shell/AsyncProcess.js +94 -0
  218. package/dist/tools/shell/DarwinRuntimeLibraries.d.ts +13 -0
  219. package/dist/tools/shell/DarwinRuntimeLibraries.d.ts.map +1 -0
  220. package/dist/tools/shell/DarwinRuntimeLibraries.js +130 -0
  221. package/dist/tools/shell/HostToolchain.d.ts +19 -0
  222. package/dist/tools/shell/HostToolchain.d.ts.map +1 -0
  223. package/dist/tools/shell/HostToolchain.js +264 -0
  224. package/dist/tools/shell/IsolatedExecutor.d.ts +15 -0
  225. package/dist/tools/shell/IsolatedExecutor.d.ts.map +1 -0
  226. package/dist/tools/shell/IsolatedExecutor.js +134 -0
  227. package/dist/tools/shell/ShellTool.d.ts.map +1 -1
  228. package/dist/tools/shell/ShellTool.js +9 -29
  229. package/dist/tools/shell/ShellWorkingDirectory.d.ts +3 -0
  230. package/dist/tools/shell/ShellWorkingDirectory.d.ts.map +1 -0
  231. package/dist/tools/shell/ShellWorkingDirectory.js +30 -0
  232. package/package.json +27 -24
@@ -3,11 +3,19 @@ import { ToolRegistry } from "../tools/ToolRegistry.js";
3
3
  import type { ToolContext } from "../tools/ToolTypes.js";
4
4
  import type { RunLogger } from "./RunLogger.js";
5
5
  export interface RunnerOptions {
6
+ signal?: AbortSignal;
7
+ /** A controller may reject a premature final answer within this same bounded loop. */
8
+ continueAfterFinal?: (message: ProviderMessage) => string | undefined | Promise<string | undefined>;
9
+ onMessages?: (messages: ProviderMessage[]) => Promise<void>;
6
10
  provider: Provider;
7
11
  tools: ToolRegistry;
8
12
  context: ToolContext;
9
13
  maxSteps: number;
10
14
  maxToolCalls: number;
15
+ /** Reserve the last bounded worker step for summarizing gathered evidence. */
16
+ finalStepWithoutTools?: boolean;
17
+ /** Combined tool-result character budget per model turn, when bounded. */
18
+ maxToolResultChars?: number;
11
19
  maxTokens?: number;
12
20
  temperature?: number;
13
21
  responseFormat?: ProviderResponseFormat;
@@ -45,11 +53,15 @@ export declare class RunnerBudgetError extends Error {
45
53
  });
46
54
  }
47
55
  export declare class Runner {
56
+ private continueAfterFinal?;
57
+ private onMessages?;
48
58
  private provider;
49
59
  private tools;
50
60
  private context;
51
61
  private maxSteps;
52
62
  private maxToolCalls;
63
+ private finalStepWithoutTools;
64
+ private maxToolResultChars?;
53
65
  private maxTokens?;
54
66
  private temperature?;
55
67
  private responseFormat?;
@@ -60,6 +72,7 @@ export declare class Runner {
60
72
  private streamFlushMs?;
61
73
  private timeoutMs?;
62
74
  private logger?;
75
+ private signal?;
63
76
  constructor(options: RunnerOptions);
64
77
  run(initialMessages: ProviderMessage[]): Promise<RunnerResult>;
65
78
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Runner.d.ts","sourceRoot":"","sources":["../../src/runtime/Runner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EAEV,QAAQ,EACR,eAAe,EACf,eAAe,EACf,sBAAsB,EAEtB,aAAa,EACd,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,EAAE,YAAY,CAAC;IACpB,OAAO,EAAE,WAAW,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,sBAAsB,CAAC;IACxC,UAAU,CAAC,EAAE,eAAe,CAAC,YAAY,CAAC,CAAC;IAC3C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IACtC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,eAAe,CAAC;IAC9B,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB;AAED,MAAM,MAAM,sBAAsB,GAC9B,yBAAyB,GACzB,iCAAiC,GACjC,4BAA4B,CAAC;AAEjC,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,IAAI,EAAE,sBAAsB,CAAC;IACtC,QAAQ,CAAC,QAAQ,EAAE;QACjB,WAAW,EAAE,sBAAsB,CAAC;QACpC,IAAI,EAAE,MAAM,CAAC;QACb,mBAAmB,EAAE,MAAM,CAAC;QAC5B,SAAS,EAAE,MAAM,CAAC;QAClB,cAAc,EAAE,MAAM,CAAC;QACvB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;gBAGA,IAAI,EAAE,sBAAsB,EAC5B,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,mBAAmB,EAAE,MAAM,CAAC;QAC5B,SAAS,EAAE,MAAM,CAAC;QAClB,cAAc,EAAE,MAAM,CAAC;QACvB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB;CAgBJ;AASD,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,SAAS,CAAC,CAAS;IAC3B,OAAO,CAAC,WAAW,CAAC,CAAS;IAC7B,OAAO,CAAC,cAAc,CAAC,CAAyB;IAChD,OAAO,CAAC,UAAU,CAAC,CAAgC;IACnD,OAAO,CAAC,MAAM,CAAC,CAAU;IACzB,OAAO,CAAC,OAAO,CAAC,CAA8B;IAC9C,OAAO,CAAC,OAAO,CAAC,CAA0B;IAC1C,OAAO,CAAC,aAAa,CAAC,CAAS;IAC/B,OAAO,CAAC,SAAS,CAAC,CAAS;IAC3B,OAAO,CAAC,MAAM,CAAC,CAAY;gBAEf,OAAO,EAAE,aAAa;IAkB5B,GAAG,CAAC,eAAe,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC;CAyLrE"}
1
+ {"version":3,"file":"Runner.d.ts","sourceRoot":"","sources":["../../src/runtime/Runner.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { truncateToolResult } from "../tools/TruncateResult.js";
1
2
  export class RunnerBudgetError extends Error {
2
3
  constructor(code, metadata) {
3
4
  super(code === "runner_timeout_exceeded"
@@ -26,6 +27,8 @@ export class Runner {
26
27
  this.context = options.context;
27
28
  this.maxSteps = options.maxSteps;
28
29
  this.maxToolCalls = options.maxToolCalls;
30
+ this.finalStepWithoutTools = options.finalStepWithoutTools === true;
31
+ this.maxToolResultChars = options.maxToolResultChars;
29
32
  this.maxTokens = options.maxTokens;
30
33
  this.temperature = options.temperature;
31
34
  this.responseFormat = options.responseFormat;
@@ -35,181 +38,240 @@ export class Runner {
35
38
  this.onToken = options.onToken;
36
39
  this.streamFlushMs = options.streamFlushMs;
37
40
  this.timeoutMs = options.timeoutMs;
41
+ this.continueAfterFinal = options.continueAfterFinal;
42
+ this.onMessages = options.onMessages;
38
43
  this.logger = options.logger;
44
+ this.signal = options.signal ?? options.context.signal;
39
45
  }
40
46
  async run(initialMessages) {
41
- const messages = [...initialMessages];
42
- let toolCallsExecuted = 0;
43
- let usageTotals;
44
- const deadline = this.timeoutMs ? Date.now() + this.timeoutMs : undefined;
45
- const emitEvent = (event) => {
46
- if (this.onEvent) {
47
- this.onEvent(event);
48
- return;
49
- }
50
- if (event.type === "token") {
51
- this.onToken?.(event.content);
52
- }
53
- };
54
- const emitStatus = (phase, message) => {
55
- this.onEvent?.({ type: "status", phase, message });
56
- };
57
- const recordUsage = (usage) => {
58
- if (!usage)
59
- return;
60
- if (!usageTotals)
61
- usageTotals = {};
62
- if (usage.inputTokens !== undefined) {
63
- usageTotals.inputTokens = (usageTotals.inputTokens ?? 0) + usage.inputTokens;
64
- }
65
- if (usage.outputTokens !== undefined) {
66
- usageTotals.outputTokens = (usageTotals.outputTokens ?? 0) + usage.outputTokens;
67
- }
68
- if (usage.totalTokens !== undefined) {
69
- usageTotals.totalTokens = (usageTotals.totalTokens ?? 0) + usage.totalTokens;
70
- }
71
- };
72
- const timeRemaining = () => {
73
- if (!deadline)
74
- return undefined;
75
- return deadline - Date.now();
76
- };
77
- const throwBudgetError = async (code, step) => {
78
- const error = new RunnerBudgetError(code, {
79
- step,
80
- tool_calls_executed: toolCallsExecuted,
81
- max_steps: this.maxSteps,
82
- max_tool_calls: this.maxToolCalls,
83
- timeout_ms: this.timeoutMs,
84
- });
85
- if (this.logger) {
86
- await this.logger.log("runner_budget_failure", error.metadata);
87
- }
88
- throw error;
89
- };
90
- const withTimeout = async (promise, label) => {
91
- const remaining = timeRemaining();
92
- if (remaining === undefined)
93
- return promise;
94
- if (remaining <= 0) {
95
- await throwBudgetError("runner_timeout_exceeded", -1);
96
- }
97
- let timeoutId;
98
- const timeoutPromise = new Promise((_, reject) => {
99
- timeoutId = setTimeout(() => reject(new Error("Runner timeout exceeded")), remaining);
100
- });
101
- try {
102
- return await Promise.race([promise, timeoutPromise]);
103
- }
104
- catch (error) {
105
- if (error instanceof Error && /Runner timeout exceeded/i.test(error.message)) {
106
- await throwBudgetError("runner_timeout_exceeded", -1);
47
+ this.signal?.throwIfAborted();
48
+ const abortController = new AbortController();
49
+ const onAbort = () => abortController.abort(this.signal?.reason);
50
+ this.signal?.addEventListener("abort", onAbort, { once: true });
51
+ const timeout = this.timeoutMs ? setTimeout(() => abortController.abort(new Error("Runner timeout exceeded")), this.timeoutMs) : undefined;
52
+ const signal = abortController.signal;
53
+ try {
54
+ const messages = [...initialMessages];
55
+ let toolCallsExecuted = 0;
56
+ let usageTotals;
57
+ const deadline = this.timeoutMs ? Date.now() + this.timeoutMs : undefined;
58
+ const emitEvent = (event) => {
59
+ if (signal.aborted)
60
+ return;
61
+ if (this.onEvent) {
62
+ this.onEvent(event);
63
+ return;
64
+ }
65
+ if (event.type === "token") {
66
+ this.onToken?.(event.content);
67
+ }
68
+ };
69
+ const emitStatus = (phase, message) => {
70
+ this.onEvent?.({ type: "status", phase, message });
71
+ };
72
+ const recordUsage = (usage) => {
73
+ if (!usage)
74
+ return;
75
+ if (!usageTotals)
76
+ usageTotals = {};
77
+ if (usage.inputTokens !== undefined) {
78
+ usageTotals.inputTokens = (usageTotals.inputTokens ?? 0) + usage.inputTokens;
79
+ }
80
+ if (usage.outputTokens !== undefined) {
81
+ usageTotals.outputTokens = (usageTotals.outputTokens ?? 0) + usage.outputTokens;
82
+ }
83
+ if (usage.totalTokens !== undefined) {
84
+ usageTotals.totalTokens = (usageTotals.totalTokens ?? 0) + usage.totalTokens;
85
+ }
86
+ };
87
+ const timeRemaining = () => {
88
+ if (!deadline)
89
+ return undefined;
90
+ return deadline - Date.now();
91
+ };
92
+ const throwBudgetError = async (code, step) => {
93
+ const error = new RunnerBudgetError(code, {
94
+ step,
95
+ tool_calls_executed: toolCallsExecuted,
96
+ max_steps: this.maxSteps,
97
+ max_tool_calls: this.maxToolCalls,
98
+ timeout_ms: this.timeoutMs,
99
+ });
100
+ if (this.logger) {
101
+ await this.logger.log("runner_budget_failure", error.metadata);
107
102
  }
108
103
  throw error;
109
- }
110
- finally {
111
- if (timeoutId)
112
- clearTimeout(timeoutId);
113
- }
114
- };
115
- for (let step = 0; step < this.maxSteps; step += 1) {
116
- if (deadline && timeRemaining() <= 0) {
117
- await throwBudgetError("runner_timeout_exceeded", step);
118
- }
119
- const toolSpecs = this.tools.describe().map((tool) => ({
120
- name: tool.name,
121
- description: tool.description,
122
- inputSchema: tool.inputSchema,
123
- }));
124
- const allowTools = toolSpecs.length > 0 && this.toolChoice !== "none";
125
- emitStatus("thinking");
126
- if (this.logger) {
127
- await this.logger.log("provider_request", {
128
- provider: this.provider.name,
129
- messages,
130
- tools: allowTools ? toolSpecs : [],
131
- toolChoice: allowTools ? this.toolChoice ?? "auto" : "none",
132
- responseFormat: this.responseFormat,
133
- temperature: this.temperature,
134
- maxTokens: this.maxTokens,
135
- stream: this.stream ?? false,
104
+ };
105
+ const withTimeout = async (promise, label) => {
106
+ const remaining = timeRemaining();
107
+ if (remaining !== undefined && remaining <= 0) {
108
+ await throwBudgetError("runner_timeout_exceeded", -1);
109
+ }
110
+ let timeoutId;
111
+ const timeoutPromise = new Promise((_, reject) => {
112
+ if (remaining !== undefined)
113
+ timeoutId = setTimeout(() => reject(new Error("Runner timeout exceeded")), remaining);
136
114
  });
137
- }
138
- const response = await withTimeout(this.provider.generate({
139
- messages,
140
- tools: allowTools ? toolSpecs : undefined,
141
- toolChoice: allowTools ? this.toolChoice ?? "auto" : undefined,
142
- maxTokens: this.maxTokens,
143
- temperature: this.temperature,
144
- responseFormat: this.responseFormat,
145
- stream: this.stream,
146
- onEvent: emitEvent,
147
- onToken: (token) => emitEvent({ type: "token", content: token }),
148
- streamFlushMs: this.streamFlushMs,
149
- }), "provider");
150
- recordUsage(response.usage);
151
- messages.push(response.message);
152
- if (this.logger) {
153
- await this.logger.log("provider_response", {
154
- message: response.message,
155
- toolCalls: response.toolCalls,
156
- usage: response.usage,
115
+ let onCancel;
116
+ const cancelled = new Promise((_, reject) => {
117
+ // Provider streams may not honor AbortSignal; never accept their late reply.
118
+ // Tools are allowed to finish their cancellation cleanup before unlocking.
119
+ if (label === "provider") {
120
+ onCancel = () => reject(signal.reason ?? new Error("Cancelled"));
121
+ signal.addEventListener("abort", onCancel, { once: true });
122
+ if (signal.aborted)
123
+ onCancel();
124
+ }
157
125
  });
158
- }
159
- if (!response.toolCalls || response.toolCalls.length === 0) {
160
- return {
161
- finalMessage: response.message,
162
- messages,
163
- toolCallsExecuted,
164
- usage: usageTotals,
165
- };
166
- }
167
- for (const call of response.toolCalls) {
168
- if (toolCallsExecuted >= this.maxToolCalls) {
169
- await throwBudgetError("runner_tool_call_limit_exceeded", step);
126
+ try {
127
+ return await Promise.race([promise, timeoutPromise, cancelled]);
128
+ }
129
+ catch (error) {
130
+ if (error instanceof Error && /Runner timeout exceeded/i.test(error.message)) {
131
+ await throwBudgetError("runner_timeout_exceeded", -1);
132
+ }
133
+ throw error;
134
+ }
135
+ finally {
136
+ if (timeoutId)
137
+ clearTimeout(timeoutId);
138
+ if (onCancel)
139
+ signal.removeEventListener("abort", onCancel);
170
140
  }
171
- toolCallsExecuted += 1;
172
- emitStatus("executing", call.name);
173
- this.onEvent?.({ type: "tool_call", name: call.name, args: call.args });
174
- const result = await withTimeout(this.tools.execute(call.name, call.args, this.context), "tool");
175
- const toolError = result.error;
176
- const content = result.ok
177
- ? result.output
178
- : `ERROR[${toolError?.code ?? "tool_execution_failed"}]: ${toolError?.message ?? "tool failed"}`;
179
- messages.push(buildToolMessage(call, content));
180
- this.onEvent?.({
181
- type: "tool_result",
182
- name: call.name,
183
- output: content,
184
- ok: result.ok,
185
- errorCode: toolError?.code,
186
- retryable: toolError?.retryable,
141
+ };
142
+ for (let step = 0; step < this.maxSteps; step += 1) {
143
+ signal.throwIfAborted();
144
+ if (deadline && timeRemaining() <= 0) {
145
+ await throwBudgetError("runner_timeout_exceeded", step);
146
+ }
147
+ const toolSpecs = this.tools.describe().map((tool) => ({
148
+ name: tool.name,
149
+ description: tool.description,
150
+ inputSchema: tool.inputSchema,
151
+ }));
152
+ const finalSummaryStep = this.finalStepWithoutTools && step > 0 && step === this.maxSteps - 1;
153
+ const allowTools = toolSpecs.length > 0 && this.toolChoice !== "none" && !finalSummaryStep;
154
+ emitStatus("thinking");
155
+ if (this.logger) {
156
+ await this.logger.log("provider_request", {
157
+ provider: this.provider.name,
158
+ messages,
159
+ tools: allowTools ? toolSpecs : [],
160
+ toolChoice: allowTools ? this.toolChoice ?? "auto" : "none",
161
+ responseFormat: this.responseFormat,
162
+ temperature: this.temperature,
163
+ maxTokens: this.maxTokens,
164
+ stream: this.stream ?? false,
165
+ });
166
+ }
167
+ const response = await withTimeout(this.provider.generate({
168
+ signal,
169
+ messages,
170
+ tools: allowTools ? toolSpecs : undefined,
171
+ toolChoice: allowTools ? this.toolChoice ?? "auto" : finalSummaryStep ? "none" : undefined,
172
+ maxTokens: this.maxTokens,
173
+ temperature: this.temperature,
174
+ responseFormat: this.responseFormat,
175
+ stream: this.stream,
176
+ onEvent: emitEvent,
177
+ onToken: (token) => emitEvent({ type: "token", content: token }),
178
+ streamFlushMs: this.streamFlushMs,
179
+ }), "provider");
180
+ recordUsage(response.usage);
181
+ signal.throwIfAborted();
182
+ messages.push({
183
+ ...response.message,
184
+ ...(response.toolCalls?.length ? { toolCalls: response.toolCalls } : {}),
187
185
  });
186
+ await this.onMessages?.([...messages]);
188
187
  if (this.logger) {
189
- await this.logger.log("tool_call", {
188
+ await this.logger.log("provider_response", {
189
+ message: response.message,
190
+ toolCalls: response.toolCalls,
191
+ usage: response.usage,
192
+ });
193
+ }
194
+ if (!response.toolCalls || response.toolCalls.length === 0) {
195
+ const continuation = await this.continueAfterFinal?.(response.message);
196
+ if (continuation) {
197
+ messages.push({ role: "user", content: continuation });
198
+ continue;
199
+ }
200
+ return {
201
+ finalMessage: response.message,
202
+ messages,
203
+ toolCallsExecuted,
204
+ usage: usageTotals,
205
+ };
206
+ }
207
+ for (const call of response.toolCalls) {
208
+ signal.throwIfAborted();
209
+ if (toolCallsExecuted >= this.maxToolCalls) {
210
+ await throwBudgetError("runner_tool_call_limit_exceeded", step);
211
+ }
212
+ toolCallsExecuted += 1;
213
+ emitStatus("executing", call.name);
214
+ this.onEvent?.({ type: "tool_call", name: call.name, args: call.args });
215
+ const result = await withTimeout(this.tools.execute(call.name, call.args, { ...this.context, signal }), "tool");
216
+ const toolError = result.error;
217
+ let content = result.ok
218
+ ? result.output
219
+ : `ERROR[${toolError?.code ?? "tool_execution_failed"}]: ${toolError?.message ?? "tool failed"}`;
220
+ if (result.ok && this.maxToolResultChars && this.maxToolResultChars > 0) {
221
+ const limit = Math.max(1, Math.floor(this.maxToolResultChars / response.toolCalls.length));
222
+ let structured = result.data;
223
+ if (structured === undefined) {
224
+ try {
225
+ structured = JSON.parse(content);
226
+ }
227
+ catch { /* Plain-text tool output. */ }
228
+ }
229
+ content = truncateToolResult(structured, content, limit).text;
230
+ }
231
+ if (result.invocationReceipt) {
232
+ content += `\n\n[Tool metadata: invocation receipt ID ${result.invocationReceipt.id}; receiptRef=${result.invocationReceipt.reference}]`;
233
+ }
234
+ messages.push(buildToolMessage(call, content));
235
+ await this.onMessages?.([...messages]);
236
+ this.onEvent?.({
237
+ type: "tool_result",
190
238
  name: call.name,
239
+ output: content,
191
240
  ok: result.ok,
192
- error: toolError?.message,
193
- error_code: toolError?.code,
194
- error_category: toolError?.category,
195
- error_retryable: toolError?.retryable,
196
- error_details: toolError?.details,
241
+ errorCode: toolError?.code,
242
+ retryable: toolError?.retryable,
197
243
  });
198
- if (toolError) {
199
- await this.logger.logSafetyEvent({
200
- phase: "act",
201
- category: "tool",
202
- code: toolError.code,
203
- disposition: toolError.retryable ? "retryable" : "non_retryable",
204
- tool: call.name,
205
- message: toolError.message,
206
- details: toolError.details,
244
+ if (this.logger) {
245
+ await this.logger.log("tool_call", {
246
+ name: call.name,
247
+ ok: result.ok,
248
+ error: toolError?.message,
249
+ error_code: toolError?.code,
250
+ error_category: toolError?.category,
251
+ error_retryable: toolError?.retryable,
252
+ error_details: toolError?.details,
207
253
  });
254
+ if (toolError) {
255
+ await this.logger.logSafetyEvent({
256
+ phase: "act",
257
+ category: "tool",
258
+ code: toolError.code,
259
+ disposition: toolError.retryable ? "retryable" : "non_retryable",
260
+ tool: call.name,
261
+ message: toolError.message,
262
+ details: toolError.details,
263
+ });
264
+ }
208
265
  }
209
266
  }
210
267
  }
268
+ await throwBudgetError("runner_step_limit_exceeded", this.maxSteps);
269
+ throw new Error("unreachable_runner_budget_path");
270
+ }
271
+ finally {
272
+ if (timeout)
273
+ clearTimeout(timeout);
274
+ this.signal?.removeEventListener("abort", onAbort);
211
275
  }
212
- await throwBudgetError("runner_step_limit_exceeded", this.maxSteps);
213
- throw new Error("unreachable_runner_budget_path");
214
276
  }
215
277
  }
@@ -0,0 +1,11 @@
1
+ /** Register credentials when resolved; do not scan or expose unrelated environment values. */
2
+ export declare const registerSecretValue: (value: string) => void;
3
+ export declare const redactSecretValues: (value: string) => string;
4
+ /** Hold incomplete credential-shaped words so split chunks cannot expose a prefix or tail. */
5
+ export declare class StreamingSecretRedactor {
6
+ private pending;
7
+ private droppingWord;
8
+ write(chunk: string): string;
9
+ finish(): string;
10
+ }
11
+ //# sourceMappingURL=SecretRedaction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SecretRedaction.d.ts","sourceRoot":"","sources":["../../src/runtime/SecretRedaction.ts"],"names":[],"mappings":"AAaA,8FAA8F;AAC9F,eAAO,MAAM,mBAAmB,GAAI,OAAO,MAAM,KAAG,IAEnD,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,OAAO,MAAM,KAAG,MAKlD,CAAC;AAEF,8FAA8F;AAC9F,qBAAa,uBAAuB;IAClC,OAAO,CAAC,OAAO,CAAM;IACrB,OAAO,CAAC,YAAY,CAAS;IAC7B,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IA4B5B,MAAM,IAAI,MAAM;CAUjB"}
@@ -0,0 +1,85 @@
1
+ const knownSecrets = new Set();
2
+ const patterns = [
3
+ /\bBearer\s+[A-Za-z0-9._~+/=-]{12,}/gi,
4
+ /\bsk-[A-Za-z0-9_-]{16,}\b/g,
5
+ /\bsk_[A-Za-z0-9]+_[A-Za-z0-9_]{8,}\b/g,
6
+ /\bgh[pousr]_[A-Za-z0-9_]{20,}\b/g,
7
+ /\bglpat-[A-Za-z0-9_-]{16,}\b/g,
8
+ /\bxox[abprs]-[A-Za-z0-9-]{10,}\b/g,
9
+ /\bAKIA[0-9A-Z]{16}\b/g,
10
+ /\bAIza[0-9A-Za-z_-]{30,}\b/g,
11
+ /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g,
12
+ ];
13
+ /** Register credentials when resolved; do not scan or expose unrelated environment values. */
14
+ export const registerSecretValue = (value) => {
15
+ if (value.length >= 4) {
16
+ knownSecrets.add(value);
17
+ knownSecrets.add(JSON.stringify(value).slice(1, -1));
18
+ }
19
+ };
20
+ export const redactSecretValues = (value) => {
21
+ let output = value;
22
+ for (const secret of [...knownSecrets].sort((a, b) => b.length - a.length))
23
+ output = output.split(secret).join("[redacted]");
24
+ for (const pattern of patterns)
25
+ output = output.replace(pattern, "[redacted]");
26
+ return output;
27
+ };
28
+ /** Hold incomplete credential-shaped words so split chunks cannot expose a prefix or tail. */
29
+ export class StreamingSecretRedactor {
30
+ constructor() {
31
+ this.pending = "";
32
+ this.droppingWord = false;
33
+ }
34
+ write(chunk) {
35
+ if (this.droppingWord) {
36
+ const boundary = chunk.search(/[^A-Za-z0-9._~+/=-]/);
37
+ if (boundary < 0)
38
+ return "";
39
+ chunk = chunk.slice(boundary);
40
+ this.droppingWord = false;
41
+ }
42
+ this.pending += chunk;
43
+ let cutoff = this.pending.search(/[A-Za-z0-9._~+/=-]*$/);
44
+ const bearer = /\bBearer\s+[A-Za-z0-9._~+/=-]*$/i.exec(this.pending);
45
+ if (bearer)
46
+ cutoff = Math.min(cutoff, bearer.index);
47
+ for (const secret of knownSecrets) {
48
+ // An exact credential may contain spaces/punctuation, unlike a bearer word.
49
+ for (let at = this.pending.indexOf(secret); at >= 0; at = this.pending.indexOf(secret, at + 1)) {
50
+ if (at < cutoff && at + secret.length > cutoff)
51
+ cutoff = at;
52
+ }
53
+ for (let size = Math.min(secret.length - 1, this.pending.length); size > 0; size--) {
54
+ if (this.pending.endsWith(secret.slice(0, size))) {
55
+ cutoff = Math.min(cutoff, this.pending.length - size);
56
+ break;
57
+ }
58
+ }
59
+ }
60
+ let output = redactSecretValues(this.pending.slice(0, cutoff));
61
+ this.pending = this.pending.slice(cutoff);
62
+ // Never release a truncated prefix; discard an oversized unbroken token.
63
+ const longestCredential = Math.max(0, ...[...knownSecrets].map(secret => secret.length));
64
+ if (this.pending.length > Math.max(65536, longestCredential)) {
65
+ output += "[redacted oversized token]";
66
+ this.pending = "";
67
+ this.droppingWord = true;
68
+ }
69
+ return output;
70
+ }
71
+ finish() {
72
+ let output = redactSecretValues(this.pending);
73
+ for (const secret of knownSecrets) {
74
+ for (let size = Math.min(secret.length - 1, output.length); size >= 4; size--) {
75
+ if (output.endsWith(secret.slice(0, size))) {
76
+ output = `${output.slice(0, -size)}[redacted]`;
77
+ break;
78
+ }
79
+ }
80
+ }
81
+ this.pending = "";
82
+ this.droppingWord = false;
83
+ return output;
84
+ }
85
+ }