@orion-agents/orion-code 0.1.0 → 0.1.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 (251) hide show
  1. package/README.md +107 -67
  2. package/README.zh-CN.md +192 -217
  3. package/dist/cli.js +23 -21
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/index.d.ts +1 -1
  6. package/dist/commands/index.d.ts.map +1 -1
  7. package/dist/commands/index.js +397 -212
  8. package/dist/commands/index.js.map +1 -1
  9. package/dist/commands/target-command.d.ts.map +1 -1
  10. package/dist/commands/target-command.js +43 -9
  11. package/dist/commands/target-command.js.map +1 -1
  12. package/dist/commands/types.d.ts +33 -0
  13. package/dist/commands/types.d.ts.map +1 -1
  14. package/dist/commands/types.js +5 -1
  15. package/dist/commands/types.js.map +1 -1
  16. package/dist/core/agent.d.ts.map +1 -1
  17. package/dist/core/agent.js +2 -2
  18. package/dist/core/agent.js.map +1 -1
  19. package/dist/framework/external-assertion.d.ts +65 -0
  20. package/dist/framework/external-assertion.d.ts.map +1 -0
  21. package/dist/framework/external-assertion.js +571 -0
  22. package/dist/framework/external-assertion.js.map +1 -0
  23. package/dist/framework/index.d.ts +6 -4
  24. package/dist/framework/index.d.ts.map +1 -1
  25. package/dist/framework/index.js +4 -1
  26. package/dist/framework/index.js.map +1 -1
  27. package/dist/framework/query.d.ts +18 -1
  28. package/dist/framework/query.d.ts.map +1 -1
  29. package/dist/framework/query.js +65 -28
  30. package/dist/framework/query.js.map +1 -1
  31. package/dist/framework/tool-scheduler.d.ts +2 -0
  32. package/dist/framework/tool-scheduler.d.ts.map +1 -1
  33. package/dist/framework/tool-scheduler.js +23 -9
  34. package/dist/framework/tool-scheduler.js.map +1 -1
  35. package/dist/framework/tool-serializer.d.ts.map +1 -1
  36. package/dist/framework/tool-serializer.js +20 -4
  37. package/dist/framework/tool-serializer.js.map +1 -1
  38. package/dist/framework/tool.d.ts +11 -5
  39. package/dist/framework/tool.d.ts.map +1 -1
  40. package/dist/framework/tool.js.map +1 -1
  41. package/dist/harness/context-harness.d.ts.map +1 -1
  42. package/dist/harness/context-harness.js +4 -3
  43. package/dist/harness/context-harness.js.map +1 -1
  44. package/dist/harness/drift-guard.d.ts.map +1 -1
  45. package/dist/harness/drift-guard.js +14 -5
  46. package/dist/harness/drift-guard.js.map +1 -1
  47. package/dist/harness/safety.d.ts.map +1 -1
  48. package/dist/harness/safety.js +19 -3
  49. package/dist/harness/safety.js.map +1 -1
  50. package/dist/init.d.ts +1 -1
  51. package/dist/init.d.ts.map +1 -1
  52. package/dist/init.js +115 -34
  53. package/dist/init.js.map +1 -1
  54. package/dist/ink-ui/screens/ReplScreen.d.ts.map +1 -1
  55. package/dist/ink-ui/screens/ReplScreen.js +4 -1
  56. package/dist/ink-ui/screens/ReplScreen.js.map +1 -1
  57. package/dist/memory/storage.d.ts.map +1 -1
  58. package/dist/memory/storage.js +1 -0
  59. package/dist/memory/storage.js.map +1 -1
  60. package/dist/memory/store.d.ts.map +1 -1
  61. package/dist/memory/store.js +11 -5
  62. package/dist/memory/store.js.map +1 -1
  63. package/dist/migration/command.d.ts.map +1 -1
  64. package/dist/migration/command.js +6 -1
  65. package/dist/migration/command.js.map +1 -1
  66. package/dist/migration/migrate.d.ts.map +1 -1
  67. package/dist/migration/migrate.js +4 -1
  68. package/dist/migration/migrate.js.map +1 -1
  69. package/dist/print-ui/launch.d.ts +4 -0
  70. package/dist/print-ui/launch.d.ts.map +1 -1
  71. package/dist/print-ui/launch.js +102 -9
  72. package/dist/print-ui/launch.js.map +1 -1
  73. package/dist/product/identity.d.ts +2 -2
  74. package/dist/product/identity.d.ts.map +1 -1
  75. package/dist/product/identity.js +2 -2
  76. package/dist/product/identity.js.map +1 -1
  77. package/dist/product/index.d.ts +2 -1
  78. package/dist/product/index.d.ts.map +1 -1
  79. package/dist/product/index.js +5 -1
  80. package/dist/product/index.js.map +1 -1
  81. package/dist/product/version.d.ts +12 -0
  82. package/dist/product/version.d.ts.map +1 -0
  83. package/dist/product/version.js +31 -0
  84. package/dist/product/version.js.map +1 -0
  85. package/dist/runtime/agent-runtime-controller.d.ts +49 -0
  86. package/dist/runtime/agent-runtime-controller.d.ts.map +1 -1
  87. package/dist/runtime/agent-runtime-controller.js +1048 -81
  88. package/dist/runtime/agent-runtime-controller.js.map +1 -1
  89. package/dist/runtime/agent-runtime-protocol.d.ts +14 -2
  90. package/dist/runtime/agent-runtime-protocol.d.ts.map +1 -1
  91. package/dist/runtime/agent-runtime-protocol.js +18 -0
  92. package/dist/runtime/agent-runtime-protocol.js.map +1 -1
  93. package/dist/runtime/chat-controller.d.ts +6 -0
  94. package/dist/runtime/chat-controller.d.ts.map +1 -1
  95. package/dist/runtime/chat-controller.js +226 -20
  96. package/dist/runtime/chat-controller.js.map +1 -1
  97. package/dist/runtime/goals/accounting.d.ts +28 -0
  98. package/dist/runtime/goals/accounting.d.ts.map +1 -1
  99. package/dist/runtime/goals/accounting.js +69 -0
  100. package/dist/runtime/goals/accounting.js.map +1 -1
  101. package/dist/runtime/goals/completion-audit.d.ts +13 -8
  102. package/dist/runtime/goals/completion-audit.d.ts.map +1 -1
  103. package/dist/runtime/goals/completion-audit.js +598 -16
  104. package/dist/runtime/goals/completion-audit.js.map +1 -1
  105. package/dist/runtime/goals/coordinator.d.ts +44 -5
  106. package/dist/runtime/goals/coordinator.d.ts.map +1 -1
  107. package/dist/runtime/goals/coordinator.js +1124 -58
  108. package/dist/runtime/goals/coordinator.js.map +1 -1
  109. package/dist/runtime/goals/evidence.d.ts +37 -0
  110. package/dist/runtime/goals/evidence.d.ts.map +1 -0
  111. package/dist/runtime/goals/evidence.js +300 -0
  112. package/dist/runtime/goals/evidence.js.map +1 -0
  113. package/dist/runtime/goals/presentation.d.ts +4 -0
  114. package/dist/runtime/goals/presentation.d.ts.map +1 -0
  115. package/dist/runtime/goals/presentation.js +50 -0
  116. package/dist/runtime/goals/presentation.js.map +1 -0
  117. package/dist/runtime/goals/prompt.d.ts.map +1 -1
  118. package/dist/runtime/goals/prompt.js +38 -8
  119. package/dist/runtime/goals/prompt.js.map +1 -1
  120. package/dist/runtime/goals/tools.d.ts +18 -1
  121. package/dist/runtime/goals/tools.d.ts.map +1 -1
  122. package/dist/runtime/goals/tools.js +308 -28
  123. package/dist/runtime/goals/tools.js.map +1 -1
  124. package/dist/runtime/goals/types.d.ts +241 -7
  125. package/dist/runtime/goals/types.d.ts.map +1 -1
  126. package/dist/runtime/goals/types.js +8 -2
  127. package/dist/runtime/goals/types.js.map +1 -1
  128. package/dist/runtime/subagents/child-executor-guard.d.ts +12 -4
  129. package/dist/runtime/subagents/child-executor-guard.d.ts.map +1 -1
  130. package/dist/runtime/subagents/child-executor-guard.js +397 -61
  131. package/dist/runtime/subagents/child-executor-guard.js.map +1 -1
  132. package/dist/runtime/subagents/presets.d.ts +4 -5
  133. package/dist/runtime/subagents/presets.d.ts.map +1 -1
  134. package/dist/runtime/subagents/presets.js +18 -33
  135. package/dist/runtime/subagents/presets.js.map +1 -1
  136. package/dist/runtime/subagents/production.d.ts +3 -1
  137. package/dist/runtime/subagents/production.d.ts.map +1 -1
  138. package/dist/runtime/subagents/production.js +37 -7
  139. package/dist/runtime/subagents/production.js.map +1 -1
  140. package/dist/runtime/subagents/runner.d.ts.map +1 -1
  141. package/dist/runtime/subagents/runner.js +24 -3
  142. package/dist/runtime/subagents/runner.js.map +1 -1
  143. package/dist/runtime/subagents/runtime-integration.d.ts +3 -0
  144. package/dist/runtime/subagents/runtime-integration.d.ts.map +1 -1
  145. package/dist/runtime/subagents/runtime-integration.js +18 -7
  146. package/dist/runtime/subagents/runtime-integration.js.map +1 -1
  147. package/dist/runtime/subagents/supervisor.d.ts +4 -4
  148. package/dist/runtime/subagents/supervisor.d.ts.map +1 -1
  149. package/dist/runtime/subagents/supervisor.js +39 -19
  150. package/dist/runtime/subagents/supervisor.js.map +1 -1
  151. package/dist/runtime/subagents/types.d.ts +7 -0
  152. package/dist/runtime/subagents/types.d.ts.map +1 -1
  153. package/dist/runtime/subagents/types.js +12 -1
  154. package/dist/runtime/subagents/types.js.map +1 -1
  155. package/dist/runtime/ui-events.d.ts +10 -0
  156. package/dist/runtime/ui-events.d.ts.map +1 -1
  157. package/dist/runtime/ui-events.js +5 -5
  158. package/dist/runtime/ui-events.js.map +1 -1
  159. package/dist/runtime/ui-view-model.d.ts +3 -3
  160. package/dist/runtime/ui-view-model.d.ts.map +1 -1
  161. package/dist/runtime/ui-view-model.js +11 -4
  162. package/dist/runtime/ui-view-model.js.map +1 -1
  163. package/dist/services/config.d.ts +18 -7
  164. package/dist/services/config.d.ts.map +1 -1
  165. package/dist/services/config.js +79 -57
  166. package/dist/services/config.js.map +1 -1
  167. package/dist/services/doctor.d.ts.map +1 -1
  168. package/dist/services/doctor.js +164 -18
  169. package/dist/services/doctor.js.map +1 -1
  170. package/dist/services/global-config.d.ts +1 -1
  171. package/dist/services/global-config.d.ts.map +1 -1
  172. package/dist/services/goal-storage.d.ts +9 -4
  173. package/dist/services/goal-storage.d.ts.map +1 -1
  174. package/dist/services/goal-storage.js +1113 -75
  175. package/dist/services/goal-storage.js.map +1 -1
  176. package/dist/services/llm.d.ts +19 -0
  177. package/dist/services/llm.d.ts.map +1 -1
  178. package/dist/services/llm.js +153 -20
  179. package/dist/services/llm.js.map +1 -1
  180. package/dist/services/model-registry.d.ts +1 -1
  181. package/dist/services/model-registry.d.ts.map +1 -1
  182. package/dist/services/model-registry.js +69 -19
  183. package/dist/services/model-registry.js.map +1 -1
  184. package/dist/services/provider-resilience/coordinator.d.ts +2 -1
  185. package/dist/services/provider-resilience/coordinator.d.ts.map +1 -1
  186. package/dist/services/provider-resilience/coordinator.js +7 -6
  187. package/dist/services/provider-resilience/coordinator.js.map +1 -1
  188. package/dist/services/provider-resilience/error-classifier.d.ts.map +1 -1
  189. package/dist/services/provider-resilience/error-classifier.js +67 -17
  190. package/dist/services/provider-resilience/error-classifier.js.map +1 -1
  191. package/dist/services/provider-resilience/types.d.ts +1 -1
  192. package/dist/services/provider-resilience/types.d.ts.map +1 -1
  193. package/dist/services/provider-resilience/types.js.map +1 -1
  194. package/dist/services/redaction.d.ts.map +1 -1
  195. package/dist/services/redaction.js +9 -1
  196. package/dist/services/redaction.js.map +1 -1
  197. package/dist/services/session-storage.d.ts +12 -1
  198. package/dist/services/session-storage.d.ts.map +1 -1
  199. package/dist/services/session-storage.js +23 -7
  200. package/dist/services/session-storage.js.map +1 -1
  201. package/dist/services/storage-maintenance.d.ts +73 -3
  202. package/dist/services/storage-maintenance.d.ts.map +1 -1
  203. package/dist/services/storage-maintenance.js +771 -104
  204. package/dist/services/storage-maintenance.js.map +1 -1
  205. package/dist/services/task-manager.d.ts.map +1 -1
  206. package/dist/services/task-manager.js +2 -2
  207. package/dist/services/task-manager.js.map +1 -1
  208. package/dist/services/web-search-adapters.d.ts.map +1 -1
  209. package/dist/services/web-search-adapters.js +89 -49
  210. package/dist/services/web-search-adapters.js.map +1 -1
  211. package/dist/services/web-search-mcp.d.ts.map +1 -1
  212. package/dist/services/web-search-mcp.js +34 -37
  213. package/dist/services/web-search-mcp.js.map +1 -1
  214. package/dist/services/workspace-state.d.ts +4 -0
  215. package/dist/services/workspace-state.d.ts.map +1 -1
  216. package/dist/services/workspace-state.js +30 -9
  217. package/dist/services/workspace-state.js.map +1 -1
  218. package/dist/terminal-ui/completion.js +1 -1
  219. package/dist/terminal-ui/completion.js.map +1 -1
  220. package/dist/terminal-ui/launch.d.ts +3 -0
  221. package/dist/terminal-ui/launch.d.ts.map +1 -1
  222. package/dist/terminal-ui/launch.js +26 -98
  223. package/dist/terminal-ui/launch.js.map +1 -1
  224. package/dist/tools/git.d.ts.map +1 -1
  225. package/dist/tools/git.js +275 -27
  226. package/dist/tools/git.js.map +1 -1
  227. package/dist/tools/index.d.ts +2 -0
  228. package/dist/tools/index.d.ts.map +1 -1
  229. package/dist/tools/index.js +29 -10
  230. package/dist/tools/index.js.map +1 -1
  231. package/dist/tools/mcp.d.ts.map +1 -1
  232. package/dist/tools/mcp.js +20 -12
  233. package/dist/tools/mcp.js.map +1 -1
  234. package/dist/tools/web.d.ts.map +1 -1
  235. package/dist/tools/web.js +38 -14
  236. package/dist/tools/web.js.map +1 -1
  237. package/dist/tui-ui/layout.d.ts.map +1 -1
  238. package/dist/tui-ui/layout.js +36 -23
  239. package/dist/tui-ui/layout.js.map +1 -1
  240. package/dist/tui-ui/pickers.d.ts.map +1 -1
  241. package/dist/tui-ui/pickers.js +5 -4
  242. package/dist/tui-ui/pickers.js.map +1 -1
  243. package/dist/tui-ui/runner.d.ts +1 -0
  244. package/dist/tui-ui/runner.d.ts.map +1 -1
  245. package/dist/tui-ui/runner.js +15 -17
  246. package/dist/tui-ui/runner.js.map +1 -1
  247. package/dist/tui-ui/state.d.ts +6 -0
  248. package/dist/tui-ui/state.d.ts.map +1 -1
  249. package/dist/tui-ui/state.js +61 -30
  250. package/dist/tui-ui/state.js.map +1 -1
  251. package/package.json +14 -9
@@ -40,6 +40,7 @@ exports.createToolEventPresenter = createToolEventPresenter;
40
40
  exports.loadSessionIntoRuntime = loadSessionIntoRuntime;
41
41
  exports.closeSession = closeSession;
42
42
  const commands_1 = require("../commands");
43
+ const async_hooks_1 = require("async_hooks");
43
44
  const parser_1 = require("../commands/parser");
44
45
  const path = __importStar(require("path"));
45
46
  const session_storage_1 = require("../services/session-storage");
@@ -397,7 +398,14 @@ function appendAssistantNotice(messages, notice) {
397
398
  function recordTraceEvent(events, sessionId, event) {
398
399
  if (!sessionId)
399
400
  return null;
400
- const traceEvent = (0, session_storage_1.appendSessionTraceEvent)(sessionId, event);
401
+ const goal = goalTraceContext.getStore();
402
+ const traceEvent = (0, session_storage_1.appendSessionTraceEvent)(sessionId, {
403
+ ...event,
404
+ goalId: goal?.goalId,
405
+ goalRevision: goal?.goalRevision,
406
+ goalInputKind: goal?.goalInputKind,
407
+ goalStopReason: goal?.getStopReason(),
408
+ });
401
409
  if (traceEvent) {
402
410
  events.traceEventRecorded?.(traceEvent);
403
411
  }
@@ -485,9 +493,12 @@ function structuredToolFinishActivity(event, seq, options = {}) {
485
493
  const outputBytes = event.outputBytes ?? Buffer.byteLength(durableOutput, 'utf8');
486
494
  const aggregatePresentation = (0, aggregate_tool_presenter_1.presentAggregateToolResult)(event.name, durableOutput, outputBytes);
487
495
  const aggregate = aggregatePresentation?.view;
488
- const storedArtifact = event.artifactRef ?? (options.projectPath && durableOutput && (outputBytes > tool_output_presentation_1.DEFAULT_TOOL_OUTPUT_POLICY.inlineMaxBytes || aggregate)
489
- ? (0, tool_artifacts_1.storeArtifact)(options.projectPath, event.name, durableOutput, outputBytes) ?? undefined
490
- : undefined);
496
+ const storedArtifact = event.artifactRef ??
497
+ (options.projectPath &&
498
+ durableOutput &&
499
+ (outputBytes > tool_output_presentation_1.DEFAULT_TOOL_OUTPUT_POLICY.inlineMaxBytes || aggregate)
500
+ ? ((0, tool_artifacts_1.storeArtifact)(options.projectPath, event.name, durableOutput, outputBytes) ?? undefined)
501
+ : undefined);
491
502
  const artifactRef = storedArtifact
492
503
  ? { id: storedArtifact.id, outputBytes: storedArtifact.outputBytes }
493
504
  : undefined;
@@ -645,13 +656,13 @@ function sessionMessagesToTranscriptEntries(sessionId, options = {}) {
645
656
  : durable;
646
657
  const durableOutput = typeof durable.output === 'string' ? durable.output : '';
647
658
  const displayOutput = typeof modelVisible.output === 'string' ? modelVisible.output : durableOutput;
648
- const outputBytes = trace?.outputBytes
649
- ?? (durable.schemaVersion === 1 ? durable.outputBytes : undefined)
650
- ?? Buffer.byteLength(durableOutput, 'utf8');
659
+ const outputBytes = trace?.outputBytes ??
660
+ (durable.schemaVersion === 1 ? durable.outputBytes : undefined) ??
661
+ Buffer.byteLength(durableOutput, 'utf8');
651
662
  const artifactId = durable.artifactRef?.id ?? trace?.artifactId;
652
663
  fallbackToolSequence += 1;
653
664
  const sequence = message.toolCallId
654
- ? sequenceByCallId.get(message.toolCallId) ?? fallbackToolSequence
665
+ ? (sequenceByCallId.get(message.toolCallId) ?? fallbackToolSequence)
655
666
  : fallbackToolSequence;
656
667
  const outputView = options.includeToolOutputViews && call && message.toolCallId
657
668
  ? (0, tool_output_presentation_1.createToolOutputView)({
@@ -764,6 +775,7 @@ function createAssistantStreamPresenter(events, abortSignal) {
764
775
  },
765
776
  };
766
777
  }
778
+ const goalTraceContext = new async_hooks_1.AsyncLocalStorage();
767
779
  class LocalFastPathBlockedError extends Error {
768
780
  constructor(message) {
769
781
  super(message);
@@ -902,6 +914,7 @@ function createToolEventPresenter(events, options = {}) {
902
914
  outputBytes: toolActivity.outputView.detailRef.outputBytes,
903
915
  }
904
916
  : event.artifactRef,
917
+ externalAssertion: event.externalAssertion,
905
918
  sequence: seq,
906
919
  batchCount: event.batchCount,
907
920
  batchIndex: event.batchIndex,
@@ -979,6 +992,14 @@ class AgentChatController {
979
992
  const text = input.trim();
980
993
  if (!text)
981
994
  return;
995
+ // Every root input owns a fresh accounting snapshot. Commands and local
996
+ // fast paths are known zero-provider turns; runChat changes tokenUsage to
997
+ // null before networking so missing provider usage remains fail-closed.
998
+ const storeWithState = this.runtime.store;
999
+ storeWithState.setState?.({
1000
+ tokenUsage: { promptTokens: 0, completionTokens: 0 },
1001
+ lastLoopStats: undefined,
1002
+ });
982
1003
  const parsed = (0, parser_1.parseInput)(text);
983
1004
  if (!parsed.isCommand) {
984
1005
  const localFastPath = parseLocalFastPath(text);
@@ -990,11 +1011,17 @@ class AgentChatController {
990
1011
  return;
991
1012
  }
992
1013
  if (parsed.name === 'clear') {
993
- this.events.clearTranscript();
1014
+ if (this.events.clearView) {
1015
+ this.events.clearView();
1016
+ }
1017
+ else {
1018
+ this.events.clearTranscript();
1019
+ }
994
1020
  this.events.setStatus('View cleared. Conversation context is preserved.');
995
1021
  return;
996
1022
  }
997
1023
  if (parsed.name === 'exit' || parsed.name === 'quit' || parsed.name === 'q') {
1024
+ this.events.shutdownRequested?.('user request');
998
1025
  await this.runtime.shutdown();
999
1026
  return;
1000
1027
  }
@@ -1016,7 +1043,67 @@ class AgentChatController {
1016
1043
  return;
1017
1044
  }
1018
1045
  const ctx = this.createCommandContext(options.abortSignal, options.turnId);
1019
- const { result, output } = await captureConsoleOutput(() => command.execute(ctx, parsed.args));
1046
+ let commandProviderAttempts = 0;
1047
+ const commandProviderPreflight = async (context) => {
1048
+ commandProviderAttempts += 1;
1049
+ return this.controllerOptions.beforeProviderRequest
1050
+ ? this.controllerOptions.beforeProviderRequest(context)
1051
+ : { available: true };
1052
+ };
1053
+ const restoreProviderPreflight = typeof this.runtime.llm?.setProviderRequestPreflight === 'function'
1054
+ ? this.runtime.llm.setProviderRequestPreflight(commandProviderPreflight)
1055
+ : undefined;
1056
+ const commandUsage = { promptTokens: 0, completionTokens: 0 };
1057
+ let commandUsageEvents = 0;
1058
+ const unsubscribeCommandUsage = typeof this.runtime.llm?.subscribeUsage === 'function'
1059
+ ? this.runtime.llm.subscribeUsage(event => {
1060
+ commandUsageEvents += 1;
1061
+ commandUsage.promptTokens += event.usage.promptTokens;
1062
+ commandUsage.completionTokens += event.usage.completionTokens;
1063
+ })
1064
+ : undefined;
1065
+ let result;
1066
+ let output;
1067
+ try {
1068
+ ({ result, output } = await captureConsoleOutput(() => command.execute(ctx, parsed.args)));
1069
+ }
1070
+ finally {
1071
+ unsubscribeCommandUsage?.();
1072
+ restoreProviderPreflight?.();
1073
+ if (commandUsage.promptTokens > 0 || commandUsage.completionTokens > 0) {
1074
+ this.runtime.store.setTokenUsage(commandUsage);
1075
+ }
1076
+ const providerRequests = Math.max(commandProviderAttempts, commandUsageEvents);
1077
+ if (providerRequests > 0) {
1078
+ const diagnostics = getLastRequestDiagnostics(this.runtime.llm);
1079
+ const retryCount = diagnostics?.retryCount ?? 0;
1080
+ const fallbackCount = diagnostics?.fallbackTriggered ? 1 : 0;
1081
+ this.setLoopStats({
1082
+ turnsStarted: 1,
1083
+ llmRequests: providerRequests,
1084
+ toolCalls: 0,
1085
+ readOnlyToolCalls: 0,
1086
+ unsafeToolCalls: 0,
1087
+ toolResultBytes: 0,
1088
+ modelVisibleToolBytes: 0,
1089
+ summarizedBytes: 0,
1090
+ finishReason: commandUsageEvents > 0 ? 'completed' : 'failed',
1091
+ providerRetryCount: retryCount,
1092
+ providerRetryDelayMs: diagnostics?.retryDelayMs,
1093
+ providerRetryErrorTypes: diagnostics?.retryErrorTypes,
1094
+ providerLastRetryErrorType: diagnostics?.lastRetryErrorType,
1095
+ providerLastRetryStatus: diagnostics?.lastRetryStatus,
1096
+ providerFallbackCount: fallbackCount,
1097
+ providerFallbackFromModel: diagnostics?.fallbackFromModel,
1098
+ providerFallbackToModel: diagnostics?.fallbackToModel,
1099
+ providerFinalModel: diagnostics?.finalModel,
1100
+ providerUsingFallback: diagnostics?.usingFallback,
1101
+ singleReadOnlyStreak: 0,
1102
+ batchReadSuggestionCount: 0,
1103
+ localFastPathUsed: false,
1104
+ });
1105
+ }
1106
+ }
1020
1107
  if (output) {
1021
1108
  this.events.append({
1022
1109
  role: result.success ? 'system' : 'error',
@@ -1051,6 +1138,25 @@ class AgentChatController {
1051
1138
  await this.runChat(result.chatInput ?? parsed.args, options);
1052
1139
  }
1053
1140
  }
1141
+ async runRequest(request, options = {}) {
1142
+ const internalInput = request.text?.trim() ||
1143
+ 'Continue pursuing the active goal from its persisted plan and evidence.';
1144
+ const run = () => this.runInput(internalInput, {
1145
+ ...options,
1146
+ persistAsUserMessage: request.persistAsUserMessage,
1147
+ inputKind: request.inputKind,
1148
+ });
1149
+ if (!request.goal) {
1150
+ await run();
1151
+ return;
1152
+ }
1153
+ await goalTraceContext.run({
1154
+ goalId: request.goal.goalId,
1155
+ goalRevision: request.goal.revision,
1156
+ goalInputKind: request.inputKind,
1157
+ getStopReason: () => this.goalCoordinator?.goal?.stopReason?.message,
1158
+ }, run);
1159
+ }
1054
1160
  async runLocalFastPath(input, action, options = {}) {
1055
1161
  const activeSession = this.runtime.getSession() ??
1056
1162
  this.runtime.ensureSession() ??
@@ -1082,7 +1188,9 @@ class AgentChatController {
1082
1188
  note: compactMiddle(action.label, 160),
1083
1189
  });
1084
1190
  }
1085
- this.runtime.store.addMessage({ role: 'user', content: input });
1191
+ if (options.persistAsUserMessage !== false) {
1192
+ this.runtime.store.addMessage({ role: 'user', content: input });
1193
+ }
1086
1194
  this.events.setStatus(`Running local ${action.label}...`);
1087
1195
  try {
1088
1196
  const tool = (0, tools_1.getRuntimeTools)().find(candidate => candidate.name === action.tool);
@@ -1247,9 +1355,7 @@ class AgentChatController {
1247
1355
  ensureSession: this.runtime.ensureSession,
1248
1356
  setSession: session => {
1249
1357
  this.runtime.setSession(session);
1250
- const renderer = this.controllerOptions.uiRenderer
1251
- ?? this.runtime.config.ui?.renderer
1252
- ?? 'terminal';
1358
+ const renderer = this.controllerOptions.uiRenderer ?? this.runtime.config.ui?.renderer ?? 'terminal';
1253
1359
  this.events.replaceTranscript(sessionMessagesToTranscriptEntries(session.id, {
1254
1360
  includeToolOutputViews: renderer === 'tui',
1255
1361
  }));
@@ -1269,6 +1375,17 @@ class AgentChatController {
1269
1375
  this.events.append({ role: 'system', content: text });
1270
1376
  }
1271
1377
  },
1378
+ clearView: () => {
1379
+ if (this.events.clearView) {
1380
+ this.events.clearView();
1381
+ }
1382
+ else {
1383
+ this.events.clearTranscript();
1384
+ }
1385
+ },
1386
+ requestShutdown: reason => {
1387
+ this.events.shutdownRequested?.(reason);
1388
+ },
1272
1389
  uiRenderer: this.controllerOptions.uiRenderer ?? this.runtime.config.ui?.renderer ?? 'terminal',
1273
1390
  uiCapabilities: (0, ui_events_1.resolveUiRendererCapabilities)(this.controllerOptions.uiCapabilities, this.controllerOptions.uiRenderer ?? this.runtime.config.ui?.renderer),
1274
1391
  };
@@ -1332,7 +1449,7 @@ class AgentChatController {
1332
1449
  if (!bundle)
1333
1450
  return stats;
1334
1451
  const usage = bundle.getAggregateUsage();
1335
- if (usage.modelRequests === 0 && usage.toolCalls === 0)
1452
+ if (usage.modelRequests === 0 && usage.toolCalls === 0 && usage.usageComplete === true)
1336
1453
  return stats;
1337
1454
  const subtaskCount = bundle.getSubtaskCount();
1338
1455
  const subagentSuffix = `subagents: ${usage.modelRequests} req/${usage.toolCalls} calls across ${subtaskCount} task(s)`;
@@ -1341,6 +1458,11 @@ class AgentChatController {
1341
1458
  llmRequests: (stats.llmRequests ?? 0) + usage.modelRequests,
1342
1459
  toolCalls: (stats.toolCalls ?? 0) + usage.toolCalls,
1343
1460
  readOnlyToolCalls: (stats.readOnlyToolCalls ?? 0) + usage.toolCalls,
1461
+ subagentPromptTokens: usage.promptTokens,
1462
+ subagentCompletionTokens: usage.completionTokens,
1463
+ subagentTotalTokens: usage.promptTokens + usage.completionTokens,
1464
+ usageAccountingComplete: stats.usageAccountingComplete !== false &&
1465
+ usage.usageComplete === true,
1344
1466
  continuationHint: stats.continuationHint
1345
1467
  ? `${stats.continuationHint} (${subagentSuffix})`
1346
1468
  : subagentSuffix,
@@ -1363,6 +1485,9 @@ class AgentChatController {
1363
1485
  });
1364
1486
  return;
1365
1487
  }
1488
+ // Usage belongs to a single root turn. Clear the previous snapshot before
1489
+ // any provider request so failures without usage cannot inherit stale data.
1490
+ this.runtime.store.setState({ tokenUsage: null });
1366
1491
  const abortSignal = options.abortSignal;
1367
1492
  const turnId = traceTurnId(options.turnId);
1368
1493
  const activeSession = this.runtime.getSession() ??
@@ -1379,7 +1504,7 @@ class AgentChatController {
1379
1504
  sessionId,
1380
1505
  });
1381
1506
  const appliedSkillNames = skillResolution.skills.map(skill => skill.name);
1382
- if (sessionId) {
1507
+ if (sessionId && options.persistAsUserMessage !== false) {
1383
1508
  (0, session_storage_1.appendSessionMessage)(sessionId, {
1384
1509
  role: 'user',
1385
1510
  content: input,
@@ -1394,7 +1519,9 @@ class AgentChatController {
1394
1519
  });
1395
1520
  appendWorkspaceSnapshotTrace(this.events, sessionId, turnId, 'pre_turn', preWorkspace);
1396
1521
  }
1397
- this.runtime.store.addMessage({ role: 'user', content: input });
1522
+ if (options.persistAsUserMessage !== false) {
1523
+ this.runtime.store.addMessage({ role: 'user', content: input });
1524
+ }
1398
1525
  (0, prompt_context_1.refreshProjectInstructions)(this.runtime.store, this.runtime.cwd);
1399
1526
  const snapshot = this.runtime.store.getSnapshot();
1400
1527
  const harness = (0, harness_1.createContextHarness)({
@@ -1407,7 +1534,9 @@ class AgentChatController {
1407
1534
  completionGate: true,
1408
1535
  },
1409
1536
  });
1410
- const intent = harness.updateContractFromUserInput(input);
1537
+ const intent = harness.updateContractFromUserInput(options.inputKind === 'goal_continuation'
1538
+ ? (this.goalCoordinator?.goal?.objective ?? input)
1539
+ : input);
1411
1540
  harness.recordAppliedSkills(skillResolution.skills);
1412
1541
  // Reconcile diagnostic: when harness state is present but objective may be incomplete
1413
1542
  if (snapshot.harnessState &&
@@ -1463,6 +1592,7 @@ class AgentChatController {
1463
1592
  // R6: wire child usage callback so CostTracker records subagent
1464
1593
  // token consumption. Injected by AgentRuntimeController via chatOptions.
1465
1594
  onChildUsage: this.controllerOptions.onChildUsage,
1595
+ beforeProviderRequest: this.controllerOptions.beforeProviderRequest,
1466
1596
  })
1467
1597
  : null;
1468
1598
  const subtaskTool = subagentBundle?.tool ?? null;
@@ -1486,6 +1616,9 @@ class AgentChatController {
1486
1616
  { role: 'system', content: systemPrompt.static, cacheControl: { type: 'ephemeral' } },
1487
1617
  ...(systemPrompt.dynamic ? [{ role: 'system', content: systemPrompt.dynamic }] : []),
1488
1618
  ...snapshot.conversationHistory,
1619
+ ...(options.persistAsUserMessage === false
1620
+ ? [{ role: 'user', content: input }]
1621
+ : []),
1489
1622
  ];
1490
1623
  let finalContent = '';
1491
1624
  let finalUsage;
@@ -1546,6 +1679,26 @@ class AgentChatController {
1546
1679
  let observedUnsafeToolCalls = 0;
1547
1680
  let observedToolResultBytes = 0;
1548
1681
  let observedModelVisibleToolBytes = 0;
1682
+ const restoreProviderPreflight = typeof this.runtime.llm.setProviderRequestPreflight === 'function'
1683
+ ? this.runtime.llm.setProviderRequestPreflight(this.controllerOptions.beforeProviderRequest)
1684
+ : undefined;
1685
+ const persistInterruptedAccounting = (rootUsage, stats, usageAccountingComplete) => {
1686
+ const accountingStats = {
1687
+ ...stats,
1688
+ finishReason: 'cancelled',
1689
+ usageAccountingComplete,
1690
+ };
1691
+ const interruptedStats = this.foldSubagentUsage(accountingStats, subagentBundle);
1692
+ this.setLoopStats(interruptedStats);
1693
+ const subagentUsage = subagentBundle?.getAggregateUsage();
1694
+ const knownZeroRootUsage = usageAccountingComplete && interruptedStats.llmRequests === 0;
1695
+ if (rootUsage || knownZeroRootUsage) {
1696
+ this.runtime.store.setTokenUsage({
1697
+ promptTokens: (rootUsage?.promptTokens ?? 0) + (subagentUsage?.promptTokens ?? 0),
1698
+ completionTokens: (rootUsage?.completionTokens ?? 0) + (subagentUsage?.completionTokens ?? 0),
1699
+ });
1700
+ }
1701
+ };
1549
1702
  try {
1550
1703
  for await (const event of (0, framework_1.query)({
1551
1704
  messages,
@@ -1758,6 +1911,14 @@ class AgentChatController {
1758
1911
  });
1759
1912
  }
1760
1913
  break;
1914
+ case 'warning':
1915
+ this.events.append({
1916
+ role: 'status',
1917
+ statusTone: 'warning',
1918
+ title: 'harness',
1919
+ content: event.message,
1920
+ });
1921
+ break;
1761
1922
  case 'message':
1762
1923
  finalContent = event.content;
1763
1924
  assistantStream.ensureMessage(event.content);
@@ -1836,6 +1997,19 @@ class AgentChatController {
1836
1997
  }
1837
1998
  const wasAborted = abortSignal?.aborted === true;
1838
1999
  if (wasAborted) {
2000
+ const stats = pendingCompleteStats ??
2001
+ (0, framework_1.createFailedLoopStats)({
2002
+ loopBudget,
2003
+ diagnostics: observedLlmRequests > 0 ? getLastRequestDiagnostics(this.runtime.llm) : undefined,
2004
+ turnsStarted: observedTurnsStarted,
2005
+ llmRequests: observedLlmRequests,
2006
+ toolCalls: observedToolCalls,
2007
+ readOnlyToolCalls: observedReadOnlyToolCalls,
2008
+ unsafeToolCalls: observedUnsafeToolCalls,
2009
+ toolResultBytes: observedToolResultBytes,
2010
+ modelVisibleToolBytes: observedModelVisibleToolBytes,
2011
+ });
2012
+ persistInterruptedAccounting(finalUsage, stats, finalUsage !== undefined || stats.llmRequests === 0);
1839
2013
  assistantStream.discardSegment();
1840
2014
  this.events.setStatus('Interrupted.');
1841
2015
  removeTrailingUserMessage(this.runtime);
@@ -2062,10 +2236,30 @@ class AgentChatController {
2062
2236
  gc.deferContinuation();
2063
2237
  }
2064
2238
  }
2065
- catch { /* best effort */ }
2239
+ catch {
2240
+ /* best effort */
2241
+ }
2066
2242
  return;
2067
2243
  }
2068
2244
  if (isAbortError(error, abortSignal)) {
2245
+ const interruptedStats = error instanceof framework_1.QueryLoopError
2246
+ ? error.stats
2247
+ : (0, framework_1.createFailedLoopStats)({
2248
+ loopBudget,
2249
+ diagnostics: observedLlmRequests > 0 ? getLastRequestDiagnostics(this.runtime.llm) : undefined,
2250
+ turnsStarted: observedTurnsStarted,
2251
+ llmRequests: observedLlmRequests,
2252
+ toolCalls: observedToolCalls,
2253
+ readOnlyToolCalls: observedReadOnlyToolCalls,
2254
+ unsafeToolCalls: observedUnsafeToolCalls,
2255
+ toolResultBytes: observedToolResultBytes,
2256
+ modelVisibleToolBytes: observedModelVisibleToolBytes,
2257
+ });
2258
+ const interruptedRootUsage = error instanceof framework_1.QueryLoopError ? error.aggregateUsage : undefined;
2259
+ // A thrown abort after a provider request started can only prove a
2260
+ // lower bound: the in-flight request may be billable even when its
2261
+ // final usage chunk never arrived.
2262
+ persistInterruptedAccounting(interruptedRootUsage, interruptedStats, interruptedStats.llmRequests === 0);
2069
2263
  assistantStream.discardSegment();
2070
2264
  this.events.setStatus('Interrupted.');
2071
2265
  removeTrailingUserMessage(this.runtime);
@@ -2098,7 +2292,7 @@ class AgentChatController {
2098
2292
  errorLayer: errorLayerForChatError(error),
2099
2293
  });
2100
2294
  this.events.setStatus('Turn failed. Ready for the next input.');
2101
- const failedStats = error instanceof framework_1.QueryLoopError
2295
+ const failedStats = this.foldSubagentUsage(error instanceof framework_1.QueryLoopError
2102
2296
  ? error.stats
2103
2297
  : (0, framework_1.createFailedLoopStats)({
2104
2298
  loopBudget,
@@ -2110,7 +2304,16 @@ class AgentChatController {
2110
2304
  unsafeToolCalls: observedUnsafeToolCalls,
2111
2305
  toolResultBytes: observedToolResultBytes,
2112
2306
  modelVisibleToolBytes: observedModelVisibleToolBytes,
2307
+ }), subagentBundle);
2308
+ const rootUsage = error instanceof framework_1.QueryLoopError ? error.aggregateUsage : undefined;
2309
+ const subagentUsage = subagentBundle?.getAggregateUsage();
2310
+ const hasSubagentUsage = (subagentUsage?.promptTokens ?? 0) > 0 || (subagentUsage?.completionTokens ?? 0) > 0;
2311
+ if (rootUsage || hasSubagentUsage) {
2312
+ this.runtime.store.setTokenUsage({
2313
+ promptTokens: (rootUsage?.promptTokens ?? 0) + (subagentUsage?.promptTokens ?? 0),
2314
+ completionTokens: (rootUsage?.completionTokens ?? 0) + (subagentUsage?.completionTokens ?? 0),
2113
2315
  });
2316
+ }
2114
2317
  this.setLoopStats(failedStats);
2115
2318
  if (sessionId) {
2116
2319
  recordProviderTraceEvents(this.events, sessionId, turnId, failedStats);
@@ -2158,6 +2361,9 @@ class AgentChatController {
2158
2361
  this.runtime.store.setState({ conversationHistory: history.slice(0, -1) });
2159
2362
  }
2160
2363
  }
2364
+ finally {
2365
+ restoreProviderPreflight?.();
2366
+ }
2161
2367
  }
2162
2368
  }
2163
2369
  exports.AgentChatController = AgentChatController;