@inflexa-ai/harness 0.39.2 → 0.41.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 (184) hide show
  1. package/README.md +2 -3
  2. package/dist/agents/conversation-agent.d.ts +3 -0
  3. package/dist/agents/conversation-agent.js +13 -2
  4. package/dist/agents/report-session-agent.d.ts +3 -0
  5. package/dist/agents/report-session-agent.js +2 -0
  6. package/dist/agents/sandbox/cheminformatics-agent.js +0 -3
  7. package/dist/agents/sandbox/shared.d.ts +11 -2
  8. package/dist/agents/sandbox/shared.js +4 -0
  9. package/dist/app/chat-turn.d.ts +104 -12
  10. package/dist/app/chat-turn.js +180 -21
  11. package/dist/app/message-assembly.d.ts +16 -52
  12. package/dist/app/message-assembly.js +41 -68
  13. package/dist/app/run-activity.d.ts +4 -6
  14. package/dist/app/run-activity.js +7 -27
  15. package/dist/app/spawn-report-session.d.ts +6 -11
  16. package/dist/app/spawn-report-session.js +5 -6
  17. package/dist/app/synthesize-run.d.ts +3 -0
  18. package/dist/app/synthesize-run.js +1 -0
  19. package/dist/billing/usage-recorder.d.ts +3 -4
  20. package/dist/billing/usage-recorder.js +3 -4
  21. package/dist/contracts/chat-parts.d.ts +11 -1
  22. package/dist/contracts/chat-parts.js +1 -0
  23. package/dist/contracts/index.d.ts +1 -1
  24. package/dist/contracts/part-registry.js +1 -0
  25. package/dist/contracts/report-blocks.d.ts +8 -8
  26. package/dist/contracts/schemas/chat-parts.d.ts +32 -9
  27. package/dist/contracts/schemas/chat-parts.js +10 -0
  28. package/dist/execution/artifact-metadata.d.ts +26 -33
  29. package/dist/execution/artifact-metadata.js +44 -106
  30. package/dist/execution/post-step-pipeline.d.ts +23 -16
  31. package/dist/execution/post-step-pipeline.js +19 -21
  32. package/dist/execution/run-synthesis.d.ts +3 -0
  33. package/dist/execution/run-synthesis.js +11 -1
  34. package/dist/execution/step-summary.d.ts +21 -30
  35. package/dist/execution/step-summary.js +30 -57
  36. package/dist/index.d.ts +9 -8
  37. package/dist/index.js +15 -34
  38. package/dist/lib/zod-issues.js +2 -4
  39. package/dist/loop/compaction.d.ts +20 -0
  40. package/dist/loop/compaction.js +2 -0
  41. package/dist/loop/continue-agent.d.ts +40 -0
  42. package/dist/loop/continue-agent.js +38 -0
  43. package/dist/loop/metrics.d.ts +30 -22
  44. package/dist/loop/metrics.js +51 -22
  45. package/dist/loop/run-agent.d.ts +111 -13
  46. package/dist/loop/run-agent.js +467 -220
  47. package/dist/loop/run-to-terminal.d.ts +16 -17
  48. package/dist/loop/run-to-terminal.js +24 -35
  49. package/dist/loop/tool-mask.d.ts +23 -0
  50. package/dist/loop/tool-mask.js +46 -0
  51. package/dist/loop/tool-output.d.ts +48 -0
  52. package/dist/loop/tool-output.js +79 -0
  53. package/dist/loop/types.d.ts +6 -3
  54. package/dist/memory/ai-sdk-message-storage.d.ts +49 -2
  55. package/dist/memory/ai-sdk-message-storage.js +78 -2
  56. package/dist/memory/conversation-display-recorder.d.ts +6 -0
  57. package/dist/memory/conversation-display-recorder.js +64 -22
  58. package/dist/memory/conversation-display-replay.d.ts +5 -14
  59. package/dist/memory/conversation-display-replay.js +66 -32
  60. package/dist/memory/conversation-display-storage.d.ts +2 -1
  61. package/dist/memory/conversation-display-storage.js +2 -1
  62. package/dist/memory/conversation-view.d.ts +53 -0
  63. package/dist/memory/conversation-view.js +130 -0
  64. package/dist/memory/count-tokens.d.ts +5 -7
  65. package/dist/memory/count-tokens.js +7 -9
  66. package/dist/memory/thread-history.d.ts +74 -102
  67. package/dist/memory/thread-history.js +181 -246
  68. package/dist/memory/thread-store.d.ts +3 -3
  69. package/dist/memory/thread-store.js +7 -2
  70. package/dist/memory/tool-call-integrity.d.ts +15 -21
  71. package/dist/memory/tool-call-integrity.js +31 -38
  72. package/dist/memory/working-memory.d.ts +2 -5
  73. package/dist/memory/working-memory.js +2 -5
  74. package/dist/prompts/SOUL.d.ts +2 -2
  75. package/dist/prompts/SOUL.js +2 -7
  76. package/dist/prompts/analogical-reasoner.d.ts +1 -1
  77. package/dist/prompts/analogical-reasoner.js +16 -32
  78. package/dist/prompts/briefing.js +1 -1
  79. package/dist/prompts/compaction.d.ts +4 -0
  80. package/dist/prompts/compaction.js +24 -0
  81. package/dist/prompts/conversation.d.ts +1 -1
  82. package/dist/prompts/conversation.js +26 -35
  83. package/dist/prompts/execute-analysis/step-summary.js +7 -5
  84. package/dist/prompts/literature-reviewer.d.ts +1 -1
  85. package/dist/prompts/literature-reviewer.js +29 -34
  86. package/dist/prompts/planner.js +15 -29
  87. package/dist/prompts/report-session.d.ts +1 -1
  88. package/dist/prompts/report-session.js +2 -33
  89. package/dist/prompts/sandbox/bulk-transcriptomics-agent.d.ts +1 -1
  90. package/dist/prompts/sandbox/bulk-transcriptomics-agent.js +1 -2
  91. package/dist/prompts/sandbox/cheminformatics-agent.d.ts +1 -1
  92. package/dist/prompts/sandbox/cheminformatics-agent.js +10 -29
  93. package/dist/prompts/sandbox/chromatin-agent.d.ts +1 -1
  94. package/dist/prompts/sandbox/chromatin-agent.js +1 -2
  95. package/dist/prompts/sandbox/data-profiler.js +6 -3
  96. package/dist/prompts/sandbox/dna-methylation-agent.d.ts +1 -1
  97. package/dist/prompts/sandbox/dna-methylation-agent.js +2 -7
  98. package/dist/prompts/sandbox/drug-repurposing-agent.d.ts +1 -1
  99. package/dist/prompts/sandbox/drug-repurposing-agent.js +20 -24
  100. package/dist/prompts/sandbox/enrichment-agent.d.ts +1 -1
  101. package/dist/prompts/sandbox/enrichment-agent.js +3 -2
  102. package/dist/prompts/sandbox/genomic-variant-agent.d.ts +1 -1
  103. package/dist/prompts/sandbox/genomic-variant-agent.js +0 -2
  104. package/dist/prompts/sandbox/immune-profiling-agent.d.ts +1 -1
  105. package/dist/prompts/sandbox/immune-profiling-agent.js +7 -14
  106. package/dist/prompts/sandbox/metabolomics-agent.d.ts +1 -1
  107. package/dist/prompts/sandbox/metabolomics-agent.js +0 -2
  108. package/dist/prompts/sandbox/microbiome-agent.d.ts +1 -1
  109. package/dist/prompts/sandbox/microbiome-agent.js +14 -21
  110. package/dist/prompts/sandbox/multi-omics-integration-agent.d.ts +1 -1
  111. package/dist/prompts/sandbox/multi-omics-integration-agent.js +9 -19
  112. package/dist/prompts/sandbox/multimodal-sc-agent.d.ts +1 -1
  113. package/dist/prompts/sandbox/multimodal-sc-agent.js +4 -5
  114. package/dist/prompts/sandbox/network-agent.d.ts +1 -1
  115. package/dist/prompts/sandbox/network-agent.js +7 -8
  116. package/dist/prompts/sandbox/pkpd-clinical-response-agent.d.ts +1 -1
  117. package/dist/prompts/sandbox/pkpd-clinical-response-agent.js +19 -19
  118. package/dist/prompts/sandbox/proteomics-agent.d.ts +1 -1
  119. package/dist/prompts/sandbox/proteomics-agent.js +3 -4
  120. package/dist/prompts/sandbox/scientific-executor.d.ts +1 -1
  121. package/dist/prompts/sandbox/scientific-executor.js +7 -10
  122. package/dist/prompts/sandbox/single-cell-agent.d.ts +1 -1
  123. package/dist/prompts/sandbox/single-cell-agent.js +2 -4
  124. package/dist/prompts/sandbox/spatial-omics-agent.d.ts +1 -1
  125. package/dist/prompts/sandbox/spatial-omics-agent.js +3 -5
  126. package/dist/prompts/sandbox/statistical-modeling-agent.d.ts +1 -1
  127. package/dist/prompts/sandbox/statistical-modeling-agent.js +1 -1
  128. package/dist/prompts/sandbox/translational-safety-agent.d.ts +1 -1
  129. package/dist/prompts/sandbox/translational-safety-agent.js +10 -19
  130. package/dist/prompts/sandbox-standards.d.ts +7 -7
  131. package/dist/prompts/sandbox-standards.js +74 -76
  132. package/dist/prompts/synthesis-agent.d.ts +1 -1
  133. package/dist/prompts/synthesis-agent.js +16 -42
  134. package/dist/providers/ai-sdk.d.ts +39 -6
  135. package/dist/providers/ai-sdk.js +117 -18
  136. package/dist/providers/errors.d.ts +2 -0
  137. package/dist/providers/errors.js +5 -0
  138. package/dist/providers/prompt-cache.d.ts +43 -41
  139. package/dist/providers/prompt-cache.js +47 -41
  140. package/dist/providers/reasoning.d.ts +10 -21
  141. package/dist/providers/reasoning.js +10 -21
  142. package/dist/providers/types.d.ts +21 -5
  143. package/dist/report-model/authoring-grammar.d.ts +2 -2
  144. package/dist/runtime/assemble.d.ts +9 -7
  145. package/dist/runtime/assemble.js +7 -3
  146. package/dist/sandbox/create-sandbox.d.ts +2 -2
  147. package/dist/sandbox/submit-exec.d.ts +1 -1
  148. package/dist/schemas/artifact-manifest.d.ts +4 -4
  149. package/dist/state/init.js +39 -4
  150. package/dist/state/purge-analysis.js +4 -0
  151. package/dist/state/tool-outputs.d.ts +4 -0
  152. package/dist/state/tool-outputs.js +30 -0
  153. package/dist/tasks/data-profile.d.ts +3 -0
  154. package/dist/tasks/data-profile.js +2 -0
  155. package/dist/tools/ad-hoc-router.d.ts +8 -0
  156. package/dist/tools/ad-hoc-router.js +21 -2
  157. package/dist/tools/display/show-user.d.ts +1 -1
  158. package/dist/tools/execute-analysis.d.ts +3 -0
  159. package/dist/tools/execute-analysis.js +9 -1
  160. package/dist/tools/read-tool-output.d.ts +7 -0
  161. package/dist/tools/read-tool-output.js +130 -0
  162. package/dist/tools/research/generate-analogy-report.d.ts +10 -26
  163. package/dist/tools/research/generate-analogy-report.js +76 -163
  164. package/dist/tools/research/generate-plan.d.ts +3 -0
  165. package/dist/tools/research/generate-plan.js +4 -1
  166. package/dist/tools/research/literature-reviewer.d.ts +3 -0
  167. package/dist/tools/research/literature-reviewer.js +3 -0
  168. package/dist/tools/sandbox/report-blocker.d.ts +18 -5
  169. package/dist/tools/sandbox/report-blocker.js +54 -6
  170. package/dist/tools/sandbox/submit-file-metadata.d.ts +30 -0
  171. package/dist/tools/sandbox/submit-file-metadata.js +67 -0
  172. package/dist/tools/start-report-session.d.ts +1 -3
  173. package/dist/tools/start-report-session.js +0 -2
  174. package/dist/tools/workspace/execute-command.js +7 -4
  175. package/dist/tools/workspace/result-bounds.d.ts +4 -4
  176. package/dist/tools/workspace/result-bounds.js +6 -5
  177. package/dist/tools/workspace/workspace-search.d.ts +1 -1
  178. package/dist/workflows/execute-analysis.d.ts +3 -0
  179. package/dist/workflows/execute-analysis.js +1 -0
  180. package/dist/workflows/sandbox-step.d.ts +30 -9
  181. package/dist/workflows/sandbox-step.js +37 -8
  182. package/package.json +9 -9
  183. package/dist/providers/anthropic.d.ts +0 -25
  184. package/dist/providers/anthropic.js +0 -28
@@ -1,25 +1,29 @@
1
1
  /**
2
2
  * Agent-loop OTel metrics, exported through the global MeterProvider.
3
3
  *
4
- * Every `runAgent` completion records, keyed by `agent_id`:
4
+ * Each LLM call records its token counters when it completes. A durable step
5
+ * that a recovery replays returns its stored reply and skips the body, so a
6
+ * replay never double-counts a call.
7
+ *
8
+ * Cache-write tokens are billed at a premium and only pay off once something
9
+ * reads them. Each counter carries `agent_id`, plus `model` and `provider`
10
+ * when the response reports them. Session provenance is not a label: agents
11
+ * that share one root provenance also share one series. Providers do not
12
+ * agree on whether `outputTokens` includes the reasoning tokens, so the
13
+ * reasoning counter keeps a `provider` label.
14
+ *
15
+ * Each `runAgent` completion also records, with the `agent_id` label only:
5
16
  * - cortex.harness.agent.iterations — histogram of LLM iterations per run.
6
17
  * A creeping distribution is a leading indicator of prompt drift.
7
- * - cortex.harness.agent.cap_hits — counter, incremented once per run
8
- * that exhausted `maxIterations` and took the forced wrap-up path.
9
- * - cortex.harness.agent.input_tokens / .output_tokens — counters, summed
10
- * over every LLM call the run made (the wrap-up included).
11
- * - cortex.harness.agent.cache_read_tokens — counter, prefix tokens served
12
- * from the prompt cache.
13
- * - cortex.harness.agent.cache_write_tokens — counter, prefix tokens written
14
- * into it (billed at a premium; only pays off once something reads it).
18
+ * - cortex.harness.agent.cap_hits — counter, incremented once per run that
19
+ * exhausted `maxIterations` and took the forced wrap-up path.
15
20
  *
16
21
  * The two cache counters are what make prompt caching *observable*: the hit
17
22
  * rate for an agent type is `cache_read_tokens / input_tokens` (the harness's
18
23
  * `inputTokens` is the total billed prefix, cache reads included). A flat-zero
19
24
  * `cache_read_tokens` against a non-zero `cache_write_tokens` means every write
20
25
  * is being thrown away — either a cache defeater is shifting the prefix (see
21
- * `providers/prompt-cache.ts`) or the endpoint ignores cache directives
22
- * outright, as the Claude Max OAuth path does.
26
+ * `providers/prompt-cache.ts`) or the endpoint ignores cache directives.
23
27
  *
24
28
  * Token counters are recorded only from what a provider actually reports; a
25
29
  * provider that reports no usage contributes nothing rather than zero.
@@ -43,11 +47,11 @@ function getInstruments() {
43
47
  description: "runAgent completions that exhausted maxIterations and took the " + "forced wrap-up path",
44
48
  }),
45
49
  inputTokens: meter.createCounter("cortex.harness.agent.input_tokens", {
46
- description: "Input tokens billed across every LLM call in a runAgent completion, cache reads included",
50
+ description: "Input tokens billed for each completed LLM call, cache reads included",
47
51
  unit: "{token}",
48
52
  }),
49
53
  outputTokens: meter.createCounter("cortex.harness.agent.output_tokens", {
50
- description: "Output tokens generated across every LLM call in a runAgent completion",
54
+ description: "Output tokens generated by each completed LLM call",
51
55
  unit: "{token}",
52
56
  }),
53
57
  cacheReadTokens: meter.createCounter("cortex.harness.agent.cache_read_tokens", {
@@ -58,6 +62,10 @@ function getInstruments() {
58
62
  description: "Prompt-prefix tokens written into the provider's prompt cache",
59
63
  unit: "{token}",
60
64
  }),
65
+ reasoningTokens: meter.createCounter("cortex.harness.agent.reasoning_tokens", {
66
+ description: "Reasoning tokens of each completed LLM call, as the provider reports them",
67
+ unit: "{token}",
68
+ }),
61
69
  };
62
70
  }
63
71
  return instruments;
@@ -88,16 +96,27 @@ export function hasReportedUsage(usage) {
88
96
  return false;
89
97
  return Object.values(usage).some((value) => value !== undefined);
90
98
  }
91
- /** Record one completed `runAgent` invocation. */
92
- export function recordAgentRun(run) {
93
- const { iterations, capHits, inputTokens, outputTokens, cacheReadTokens, cacheWriteTokens } = getInstruments();
94
- const attributes = { agent_id: run.agentId };
95
- iterations.record(run.iterations, attributes);
96
- if (run.cappedOut)
97
- capHits.add(1, attributes);
98
- const usage = run.usage;
99
+ /**
100
+ * Maps a step's response to grow its token counters. Use inside the step
101
+ * body, `provider.chat(...).map(countChatTokens(agentId))`. A call that gives
102
+ * `err` counts nothing.
103
+ */
104
+ export function countChatTokens(agentId) {
105
+ return (response) => {
106
+ recordChatCall({ agentId, response });
107
+ return response;
108
+ };
109
+ }
110
+ export function recordChatCall(call) {
111
+ const { usage, servedModelId, provider } = call.response;
99
112
  if (usage === undefined)
100
113
  return;
114
+ const { inputTokens, outputTokens, cacheReadTokens, cacheWriteTokens, reasoningTokens } = getInstruments();
115
+ const attributes = {
116
+ agent_id: call.agentId,
117
+ ...(servedModelId === undefined ? {} : { model: servedModelId }),
118
+ ...(provider === undefined ? {} : { provider }),
119
+ };
101
120
  if (usage.inputTokens !== undefined)
102
121
  inputTokens.add(usage.inputTokens, attributes);
103
122
  if (usage.outputTokens !== undefined)
@@ -106,9 +125,19 @@ export function recordAgentRun(run) {
106
125
  cacheReadTokens.add(usage.cacheReadInputTokens, attributes);
107
126
  if (usage.cacheCreationInputTokens !== undefined)
108
127
  cacheWriteTokens.add(usage.cacheCreationInputTokens, attributes);
128
+ if (usage.reasoningTokens !== undefined)
129
+ reasoningTokens.add(usage.reasoningTokens, attributes);
130
+ }
131
+ /** Record one completed `runAgent` invocation. */
132
+ export function recordAgentRun(run) {
133
+ const { iterations, capHits } = getInstruments();
134
+ const attributes = { agent_id: run.agentId };
135
+ iterations.record(run.iterations, attributes);
136
+ if (run.cappedOut)
137
+ capHits.add(1, attributes);
109
138
  }
110
139
  /**
111
- * Drop the memoized instruments so the next `recordAgentRun` rebinds to a
140
+ * Drop the memoized instruments so the next record rebinds to a
112
141
  * freshly-registered `MeterProvider`. Test-only — production registers its
113
142
  * provider once at startup.
114
143
  */
@@ -2,9 +2,12 @@ import { type FinishReason } from "ai";
2
2
  import type { AgentSession } from "../auth/types.js";
3
3
  import type { UsageRecorder } from "../billing/usage-recorder.js";
4
4
  import type { Logger } from "../lib/logger.js";
5
- import type { AgentChat, ChatRequest, PromptCachePolicy, ReasoningPolicy } from "../providers/types.js";
5
+ import { type CompactionPolicy } from "./compaction.js";
6
+ import type { AgentChat, ChatRequest, ChatResponse, PromptCachePolicy, ReasoningPolicy } from "../providers/types.js";
6
7
  import { type AskApproval, type AskRequest } from "../tools/approval/contract.js";
7
8
  import { type AgentRunUsage } from "./metrics.js";
9
+ import { type ToolBudget, type ToolMask } from "./tool-mask.js";
10
+ import { type ToolOutputStore } from "./tool-output.js";
8
11
  import type { AgentDefinition, EmitFn, LoopMessage, RunStep } from "./types.js";
9
12
  export interface AgentFinish {
10
13
  readonly reason: FinishReason | "aborted" | "max_iterations" | "denied";
@@ -31,6 +34,19 @@ export interface RunAgentResult {
31
34
  readonly messages: LoopMessage[];
32
35
  readonly finish: AgentFinish;
33
36
  }
37
+ /** A request that the provider refused for its content: the HTTP status and the text of the provider error. */
38
+ export interface RequestRefusal {
39
+ readonly status: number;
40
+ readonly message: string;
41
+ }
42
+ /** The result of a segment. A segment that ends on a refusal of its request carries the refusal. */
43
+ export interface SegmentResult extends RunAgentResult {
44
+ readonly refusal?: RequestRefusal;
45
+ }
46
+ /** The messages that the loop appended after the last call of the round sink. */
47
+ export interface AgentRound {
48
+ readonly messages: readonly LoopMessage[];
49
+ }
34
50
  export interface StepNameFormatter {
35
51
  llm(iteration: number): string;
36
52
  tool(toolName: string, toolUseId: string): string;
@@ -40,6 +56,17 @@ export interface RunAgentOptions {
40
56
  readonly provider: AgentChat;
41
57
  readonly signal: AbortSignal;
42
58
  readonly emit: EmitFn;
59
+ /**
60
+ * The round sink. The loop awaits it before each model request, at each exit, and before a throw.
61
+ * A durable loop passes no sink, because DBOS replays the loop body.
62
+ */
63
+ readonly onRound?: (round: AgentRound) => Promise<void>;
64
+ /**
65
+ * The compaction policy. Each request then sends the view of the transcript, and the loop compacts
66
+ * before a task request whose view passes the budget. A durable loop passes no policy, because
67
+ * `recordsAfter` reads the database outside a step.
68
+ */
69
+ readonly compaction?: CompactionPolicy;
43
70
  /**
44
71
  * Per-turn user-approval seam threaded into every tool's `ToolContext` as
45
72
  * `ctx.ask`. A conversation tool calls it to pause for an explicit user
@@ -53,8 +80,10 @@ export interface RunAgentOptions {
53
80
  readonly runStep: RunStep;
54
81
  readonly formatStepName?: StepNameFormatter;
55
82
  readonly isFatalLoopError?: (err: unknown) => boolean;
56
- /** Tool-selection policy for in-loop model calls. The cap wrap-up forbids a
57
- * tool call regardless. */
83
+ /**
84
+ * Tool choice for every request of this run: part of the prefix that the
85
+ * prompt cache and a signed thinking block bind to.
86
+ */
58
87
  readonly toolChoice?: ChatRequest["toolChoice"];
59
88
  /**
60
89
  * Optional outcome predicate for loop-driving agents whose result is
@@ -62,6 +91,13 @@ export interface RunAgentOptions {
62
91
  * dispatch round, once every sibling tool result has been appended.
63
92
  */
64
93
  readonly resolved?: () => boolean;
94
+ /**
95
+ * Tools allowed to run per request. The full tool set stays declared either
96
+ * way, since it is part of the cache/thinking-block prefix.
97
+ */
98
+ readonly toolMask?: ToolMask;
99
+ /** Max calls per tool for this run; a call in the same round counts against the budget too. */
100
+ readonly toolBudget?: ToolBudget;
65
101
  /**
66
102
  * Prompt-cache policy for every LLM call this run makes. Defaults to
67
103
  * `DEFAULT_PROMPT_CACHE` (5m) — an agent loop always re-sends its prefix, so
@@ -75,16 +111,9 @@ export interface RunAgentOptions {
75
111
  */
76
112
  readonly promptCache?: PromptCachePolicy;
77
113
  /**
78
- * Reasoning policy for every LLM call this run makes. Defaults to
79
- * `DEFAULT_REASONING` (`xhigh`) — an agent loop drives tools over many
80
- * iterations, and a shallow turn there costs more in wasted calls than the
81
- * deeper turn costs in tokens. The provider package resolves the name for
82
- * the model that it is bound to.
83
- *
84
- * The policy lives here, on the run, rather than on the provider, for the
85
- * same reason that the cache policy does: a one-shot LLM call elsewhere has
86
- * its own depth needs and must not inherit the depth of a loop. A host on a
87
- * model with no reasoning support passes `"provider-default"`.
114
+ * The reasoning effort for each LLM call of this run, the forced wrap-up
115
+ * included. Anthropic discards its message cache when the top-level
116
+ * effort changes, so the run must send the same value, or none, throughout.
88
117
  */
89
118
  readonly reasoning?: ReasoningPolicy;
90
119
  /**
@@ -104,6 +133,8 @@ export interface RunAgentOptions {
104
133
  * and it logs the reason of an `err` when the result arrives.
105
134
  */
106
135
  readonly usageRecorder?: UsageRecorder;
136
+ /** Keeps the text of each cut tool result. A run with no store cuts, and it keeps nothing. */
137
+ readonly toolOutputStore?: ToolOutputStore;
107
138
  /**
108
139
  * The turn's usage accumulator, supplied by whatever ran this loop as part
109
140
  * of a larger turn (a sub-agent-running tool passes `ctx.turnUsage`). A run
@@ -121,5 +152,72 @@ export interface RunAgentOptions {
121
152
  */
122
153
  readonly invocationId?: string;
123
154
  }
155
+ /** A run that receives no turn accumulator is the turn's root. See `RunAgentOptions.turnUsage`. */
156
+ export declare const isTurnRoot: (opts: RunAgentOptions) => boolean;
124
157
  export declare function runAgent(agent: AgentDefinition, initial: readonly LoopMessage[], session: AgentSession, opts: RunAgentOptions): Promise<RunAgentResult>;
158
+ /** The harness request of the wrap-up at the iteration cap. */
159
+ export declare const WRAP_UP_REQUEST = "You reached the limit of tool rounds for this run, thus no tool can run now. Answer in text with the results that you have.";
160
+ /** The cap of wrap-up requests: one answer, and one more request after a refused call. */
161
+ export declare const WRAP_UP_MAX_REQUESTS = 2;
162
+ /** One stretch of model requests of a conversation, under one mask. */
163
+ export interface LoopSegment {
164
+ /** The tools that can run for each request of the segment. Absent lets each declared tool run. */
165
+ readonly mask: ToolMask | undefined;
166
+ readonly maxRequests: number;
167
+ readonly stepNames: StepNameFormatter;
168
+ /** The `index` of the first request of the segment in its `iteration` events. */
169
+ readonly firstIndex: number;
170
+ /** A harness request that the segment appends, as a synthetic user message, before its first request. */
171
+ readonly requestText?: string;
172
+ /**
173
+ * The segment runs after the iteration cap: its requests do not count as
174
+ * iterations, and the last one always ends the run, whatever its reply.
175
+ */
176
+ readonly closesCappedRun?: boolean;
177
+ /** The loop compacts before a request of the segment whose view passes the budget of the policy. */
178
+ readonly checksBudget?: boolean;
179
+ /** A refusal of a request, a `provider` error with the status `400` or `413`, ends the segment with no new message. */
180
+ readonly endsOnRequestRefusal?: boolean;
181
+ }
182
+ /**
183
+ * One conversation, open for its segments. Each segment extends the same
184
+ * prefix (system prompt, tools, tool choice) as the one before it.
185
+ */
186
+ export interface OpenLoop {
187
+ /** Run one segment: the result of the run when a reply ends it, or `"capped"` when the segment used its cap. */
188
+ runSegment(segment: LoopSegment): Promise<SegmentResult | "capped">;
189
+ /** End a run after its last segment used its cap. */
190
+ endCapped(): Promise<RunAgentResult>;
191
+ }
192
+ /**
193
+ * Open the loop over one conversation. `metricAgentId` is the id that usage
194
+ * and run metrics count under, which is not always `agent.id`.
195
+ */
196
+ export declare function openLoop(agent: AgentDefinition, initial: readonly LoopMessage[], session: AgentSession, opts: RunAgentOptions, metricAgentId: string): OpenLoop;
197
+ /** What one completed LLM call is accounted under. */
198
+ export interface ChatCallAccounting {
199
+ readonly session: AgentSession;
200
+ readonly agentId: string;
201
+ readonly callPath: readonly string[];
202
+ /**
203
+ * The deterministic name inside the record key, for example `llm-{n}` for
204
+ * a loop call or `adhoc-route` for a direct call.
205
+ */
206
+ readonly stepName: string;
207
+ /** The id of the tool call that makes the call, when the call runs inside a tool dispatch. */
208
+ readonly invocationId?: string;
209
+ readonly usageRecorder: UsageRecorder;
210
+ /** The sink that the notice helper logs the reason of a recorder `err` to. */
211
+ readonly logger: Logger;
212
+ /** The accumulators that the usage of the call folds into, for example the run total and the turn total. */
213
+ readonly rollups: readonly AgentRunUsage[];
214
+ }
215
+ /**
216
+ * Called at the fold point, before any run-ending branch, so an aborted or
217
+ * dead run is still accounted. Token counters grow inside the call's step
218
+ * body, not here, because a replay re-delivers the stored reply to this
219
+ * function too; the record re-sends under the same idempotency key, which an
220
+ * upserting sink counts once.
221
+ */
222
+ export declare function accountForChatCall(reply: ChatResponse, call: ChatCallAccounting): void;
125
223
  export declare function finalText(messages: readonly LoopMessage[]): string;