@tangle-network/agent-eval 0.145.22 → 0.147.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 (153) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/dist/analyst/index.d.ts +13 -13
  3. package/dist/analyst/index.js +6 -6
  4. package/dist/{backend-integrity-HVmWyOaX.d.ts → backend-integrity-Bz8nSrRE.d.ts} +2 -2
  5. package/dist/{backend-integrity-HVmWyOaX.d.ts.map → backend-integrity-Bz8nSrRE.d.ts.map} +1 -1
  6. package/dist/{benchmark-DTQ1RApl.d.ts → benchmark-Cn7ZMFNW.d.ts} +3 -3
  7. package/dist/{benchmark-DTQ1RApl.d.ts.map → benchmark-Cn7ZMFNW.d.ts.map} +1 -1
  8. package/dist/{benchmark-command-CDB_yKqS.js → benchmark-command-BTiysiYU.js} +11 -11
  9. package/dist/{benchmark-command-CDB_yKqS.js.map → benchmark-command-BTiysiYU.js.map} +1 -1
  10. package/dist/benchmarks/index.d.ts +4 -4
  11. package/dist/benchmarks/index.js +3 -3
  12. package/dist/campaign/index.d.ts +8 -8
  13. package/dist/campaign/index.js +5 -5
  14. package/dist/{campaign-CbQXcARJ.js → campaign-DCDdhuv2.js} +7 -7
  15. package/dist/{campaign-CbQXcARJ.js.map → campaign-DCDdhuv2.js.map} +1 -1
  16. package/dist/{capture-fetch-BZiO2cEH.d.ts → capture-fetch-BAx3Gntt.d.ts} +2 -2
  17. package/dist/{capture-fetch-BZiO2cEH.d.ts.map → capture-fetch-BAx3Gntt.d.ts.map} +1 -1
  18. package/dist/{chat-client-BJmwfnjN.js → chat-client-BX8Wh3fn.js} +3 -3
  19. package/dist/{chat-client-BJmwfnjN.js.map → chat-client-BX8Wh3fn.js.map} +1 -1
  20. package/dist/cli.js +2 -2
  21. package/dist/{client-YDkU5QST.d.ts → client-BV7icIfy.d.ts} +2 -2
  22. package/dist/{client-YDkU5QST.d.ts.map → client-BV7icIfy.d.ts.map} +1 -1
  23. package/dist/contract/index.d.ts +10 -10
  24. package/dist/contract/index.js +9 -9
  25. package/dist/{cost-ledger-BSe92yAV.js → cost-ledger-B1qx30B4.js} +2 -2
  26. package/dist/{cost-ledger-BSe92yAV.js.map → cost-ledger-B1qx30B4.js.map} +1 -1
  27. package/dist/{default-registry-DONui3mA.d.ts → default-registry-BUtRMRKk.d.ts} +6 -6
  28. package/dist/{default-registry-DONui3mA.d.ts.map → default-registry-BUtRMRKk.d.ts.map} +1 -1
  29. package/dist/{define-agent-eval-BGxmy4W6.js → define-agent-eval-BqWFz3sK.js} +3 -3
  30. package/dist/{define-agent-eval-BGxmy4W6.js.map → define-agent-eval-BqWFz3sK.js.map} +1 -1
  31. package/dist/{define-agent-eval-DrpgTVPp.d.ts → define-agent-eval-D52ClbX2.d.ts} +5 -5
  32. package/dist/{define-agent-eval-DrpgTVPp.d.ts.map → define-agent-eval-D52ClbX2.d.ts.map} +1 -1
  33. package/dist/{dspy-rlm-engine-B2nst4NR.js → dspy-rlm-engine-BmtOl_kP.js} +4 -4
  34. package/dist/{dspy-rlm-engine-B2nst4NR.js.map → dspy-rlm-engine-BmtOl_kP.js.map} +1 -1
  35. package/dist/{engine-Bc3seRPe.d.ts → engine-CIy18RTX.d.ts} +4 -4
  36. package/dist/{engine-Bc3seRPe.d.ts.map → engine-CIy18RTX.d.ts.map} +1 -1
  37. package/dist/{eval-campaign-DeGLwACc.js → eval-campaign-bmZ6NIIP.js} +2 -2
  38. package/dist/{eval-campaign-DeGLwACc.js.map → eval-campaign-bmZ6NIIP.js.map} +1 -1
  39. package/dist/{exact-types-CYFbvA5U.d.ts → exact-types-rdKFzEnK.d.ts} +2 -2
  40. package/dist/{exact-types-CYFbvA5U.d.ts.map → exact-types-rdKFzEnK.d.ts.map} +1 -1
  41. package/dist/experiment/index.d.ts +5 -5
  42. package/dist/experiment/index.js +3 -3
  43. package/dist/{experiment-tracker-DWHZBAYL.d.ts → experiment-tracker-D9VHwRm-.d.ts} +6 -24
  44. package/dist/experiment-tracker-D9VHwRm-.d.ts.map +1 -0
  45. package/dist/{experiment-tracker-C29gXM4B.js → experiment-tracker-Ym6rEQT1.js} +15 -4
  46. package/dist/experiment-tracker-Ym6rEQT1.js.map +1 -0
  47. package/dist/{external-optimizer-contracts-CKEY98bK.d.ts → external-optimizer-contracts-CSjDLLmr.d.ts} +2 -2
  48. package/dist/{external-optimizer-contracts-CKEY98bK.d.ts.map → external-optimizer-contracts-CSjDLLmr.d.ts.map} +1 -1
  49. package/dist/{external-optimizer-process-DYNizz8W.js → external-optimizer-process-C4AyCcQd.js} +2 -2
  50. package/dist/{external-optimizer-process-DYNizz8W.js.map → external-optimizer-process-C4AyCcQd.js.map} +1 -1
  51. package/dist/{external-optimizer-subprocess-r6dP9DAj.js → external-optimizer-subprocess-DU1KM8yV.js} +3 -3
  52. package/dist/{external-optimizer-subprocess-r6dP9DAj.js.map → external-optimizer-subprocess-DU1KM8yV.js.map} +1 -1
  53. package/dist/{feedback-trajectory-Cg9EDxKB.d.ts → feedback-trajectory-niGeR6uJ.d.ts} +3 -3
  54. package/dist/{feedback-trajectory-Cg9EDxKB.d.ts.map → feedback-trajectory-niGeR6uJ.d.ts.map} +1 -1
  55. package/dist/fuzz.js +1 -1
  56. package/dist/hosted/index.d.ts +2 -2
  57. package/dist/{index-DGrcBMbC.d.ts → index-BjBjxiVv.d.ts} +9 -9
  58. package/dist/{index-DGrcBMbC.d.ts.map → index-BjBjxiVv.d.ts.map} +1 -1
  59. package/dist/index-CKblBxtr.d.ts +1 -0
  60. package/dist/{index-CevPFhDT.d.ts → index-gtjtfLEJ.d.ts} +7 -7
  61. package/dist/{index-CevPFhDT.d.ts.map → index-gtjtfLEJ.d.ts.map} +1 -1
  62. package/dist/index.d.ts +21 -51
  63. package/dist/index.d.ts.map +1 -1
  64. package/dist/index.js +16 -125
  65. package/dist/index.js.map +1 -1
  66. package/dist/{integrity-DDoeWibF.d.ts → integrity-CGfpTE5-.d.ts} +2 -2
  67. package/dist/{integrity-DDoeWibF.d.ts.map → integrity-CGfpTE5-.d.ts.map} +1 -1
  68. package/dist/{kind-factory-CPmSd58s.js → kind-factory-DmAa0h3K.js} +7 -7
  69. package/dist/kind-factory-DmAa0h3K.js.map +1 -0
  70. package/dist/{llm-client-_UE4fU7Z.js → llm-client-BMuxYoZy.js} +2 -2
  71. package/dist/{llm-client-_UE4fU7Z.js.map → llm-client-BMuxYoZy.js.map} +1 -1
  72. package/dist/{llm-judge-B7ffRF8w.js → llm-judge-DrzsVS5k.js} +4 -4
  73. package/dist/{llm-judge-B7ffRF8w.js.map → llm-judge-DrzsVS5k.js.map} +1 -1
  74. package/dist/matrix-C-2Qx1Zr.d.ts +383 -0
  75. package/dist/matrix-C-2Qx1Zr.d.ts.map +1 -0
  76. package/dist/meta-eval/index.d.ts +1 -1
  77. package/dist/{metrics-Cl0L1KUy.js → metrics-Qv-cpptD.js} +15 -8
  78. package/dist/metrics-Qv-cpptD.js.map +1 -0
  79. package/dist/multishot/golden/index.d.ts +230 -0
  80. package/dist/multishot/golden/index.d.ts.map +1 -0
  81. package/dist/multishot/golden/index.js +7686 -0
  82. package/dist/multishot/golden/index.js.map +1 -0
  83. package/dist/multishot/index.d.ts +2 -380
  84. package/dist/multishot/index.d.ts.map +1 -1
  85. package/dist/multishot/index.js +2 -106
  86. package/dist/multishot/index.js.map +1 -1
  87. package/dist/openapi.json +1 -1
  88. package/dist/{produced-state-D3k45S9a.js → produced-state-Dtx60bUQ.js} +4 -4
  89. package/dist/{produced-state-D3k45S9a.js.map → produced-state-Dtx60bUQ.js.map} +1 -1
  90. package/dist/{promotion-policy-BKi5OK5l.d.ts → promotion-policy-CewdjfCJ.d.ts} +2 -2
  91. package/dist/{promotion-policy-BKi5OK5l.d.ts.map → promotion-policy-CewdjfCJ.d.ts.map} +1 -1
  92. package/dist/{provenance-Bb7Zmyj2.d.ts → provenance-LrOEOHQb.d.ts} +6 -6
  93. package/dist/{provenance-Bb7Zmyj2.d.ts.map → provenance-LrOEOHQb.d.ts.map} +1 -1
  94. package/dist/{registry-CZgEmVXb.d.ts → registry-CaqJIDdN.d.ts} +4 -4
  95. package/dist/{registry-CZgEmVXb.d.ts.map → registry-CaqJIDdN.d.ts.map} +1 -1
  96. package/dist/reporting.d.ts +1 -1
  97. package/dist/reporting.js +1 -1
  98. package/dist/{researcher-CC305Ed-.d.ts → researcher-BySlpla_.d.ts} +3 -3
  99. package/dist/{researcher-CC305Ed-.d.ts.map → researcher-BySlpla_.d.ts.map} +1 -1
  100. package/dist/rl.d.ts +3 -3
  101. package/dist/rl.js +2 -2
  102. package/dist/{semantic-concept-judge-BsY2Q0Oq.js → semantic-concept-judge-BI7Rrl5-.js} +3 -3
  103. package/dist/{semantic-concept-judge-BsY2Q0Oq.js.map → semantic-concept-judge-BI7Rrl5-.js.map} +1 -1
  104. package/dist/{sequential-CYwq6Ff_.d.ts → sequential-BhsrMupG.d.ts} +31 -2
  105. package/dist/sequential-BhsrMupG.d.ts.map +1 -0
  106. package/dist/{sequential-Br0mAPHA.js → sequential-CzK5DarL.js} +48 -6
  107. package/dist/sequential-CzK5DarL.js.map +1 -0
  108. package/dist/series-convergence-CjO2QdRW.js.map +1 -1
  109. package/dist/{series-convergence-C9G-GNYK.d.ts → series-convergence-D2fsoJ2w.d.ts} +4 -7
  110. package/dist/{series-convergence-C9G-GNYK.d.ts.map → series-convergence-D2fsoJ2w.d.ts.map} +1 -1
  111. package/dist/{server-cQXve8i4.js → server-D9wQclzG.js} +3 -3
  112. package/dist/{server-cQXve8i4.js.map → server-D9wQclzG.js.map} +1 -1
  113. package/dist/{skillopt-optimization-method-C9MrMgW9.d.ts → skillopt-optimization-method-BoC1Qccx.d.ts} +5 -5
  114. package/dist/{skillopt-optimization-method-C9MrMgW9.d.ts.map → skillopt-optimization-method-BoC1Qccx.d.ts.map} +1 -1
  115. package/dist/{skillopt-optimization-method-Cv3K4DaS.js → skillopt-optimization-method-C_UrqZs2.js} +4 -4
  116. package/dist/{skillopt-optimization-method-Cv3K4DaS.js.map → skillopt-optimization-method-C_UrqZs2.js.map} +1 -1
  117. package/dist/{statistical-heldout-fvxtHnKQ.d.ts → statistical-heldout-uxSpFEjm.d.ts} +2 -2
  118. package/dist/{statistical-heldout-fvxtHnKQ.d.ts.map → statistical-heldout-uxSpFEjm.d.ts.map} +1 -1
  119. package/dist/{store-otlp-CsptLYpN.js → store-otlp-CDYWW_8N.js} +2 -2
  120. package/dist/{store-otlp-CsptLYpN.js.map → store-otlp-CDYWW_8N.js.map} +1 -1
  121. package/dist/{store-tool-spans-Cq9mFd-q.js → store-tool-spans-CykkbOlv.js} +3 -3
  122. package/dist/{store-tool-spans-Cq9mFd-q.js.map → store-tool-spans-CykkbOlv.js.map} +1 -1
  123. package/dist/{store-tool-spans-CV0hRsUp.d.ts → store-tool-spans-D5FhM0_A.d.ts} +4 -4
  124. package/dist/{store-tool-spans-CV0hRsUp.d.ts.map → store-tool-spans-D5FhM0_A.d.ts.map} +1 -1
  125. package/dist/{task-failure-attributes-CpQ4y5RD.js → task-failure-attributes--ZTP3tYO.js} +2 -2
  126. package/dist/{task-failure-attributes-CpQ4y5RD.js.map → task-failure-attributes--ZTP3tYO.js.map} +1 -1
  127. package/dist/{tool-groups-CDDXNKhd.d.ts → tool-groups-zpufabP8.d.ts} +3 -3
  128. package/dist/tool-groups-zpufabP8.d.ts.map +1 -0
  129. package/dist/trace-repair/index.d.ts +1 -1
  130. package/dist/traces.d.ts +7 -7
  131. package/dist/traces.js +4 -4
  132. package/dist/types-B3jzCp0p.js +108 -0
  133. package/dist/types-B3jzCp0p.js.map +1 -0
  134. package/dist/{types-oAsa-fs4.d.ts → types-BohHewKK.d.ts} +2 -2
  135. package/dist/{types-oAsa-fs4.d.ts.map → types-BohHewKK.d.ts.map} +1 -1
  136. package/dist/{types-DABZgDGV.d.ts → types-C1Bmeb8X.d.ts} +3 -3
  137. package/dist/{types-DABZgDGV.d.ts.map → types-C1Bmeb8X.d.ts.map} +1 -1
  138. package/dist/{types-CWcPguwd.d.ts → types-ColZlZtc.d.ts} +2 -2
  139. package/dist/{types-CWcPguwd.d.ts.map → types-ColZlZtc.d.ts.map} +1 -1
  140. package/dist/{types-XBRdmbj8.d.ts → types-DOhGq4S1.d.ts} +1 -7
  141. package/dist/{types-XBRdmbj8.d.ts.map → types-DOhGq4S1.d.ts.map} +1 -1
  142. package/dist/wire/index.d.ts +2 -2
  143. package/dist/wire/index.js +1 -1
  144. package/docs/multishot-golden-records.md +102 -0
  145. package/package.json +7 -2
  146. package/dist/experiment-tracker-C29gXM4B.js.map +0 -1
  147. package/dist/experiment-tracker-DWHZBAYL.d.ts.map +0 -1
  148. package/dist/index-BgHYx1QG.d.ts +0 -1
  149. package/dist/kind-factory-CPmSd58s.js.map +0 -1
  150. package/dist/metrics-Cl0L1KUy.js.map +0 -1
  151. package/dist/sequential-Br0mAPHA.js.map +0 -1
  152. package/dist/sequential-CYwq6Ff_.d.ts.map +0 -1
  153. package/dist/tool-groups-CDDXNKhd.d.ts.map +0 -1
@@ -0,0 +1,383 @@
1
+ import { p as CostProvenance } from "./cost-ledger-DbQdN3nO.js";
2
+ import { w as JudgeScore } from "./types-C1Bmeb8X.js";
3
+ import { o as MatrixResult } from "./index-D_P7Ye43.js";
4
+ import { AgentProfile } from "@tangle-network/agent-interface";
5
+ //#region src/multishot/judges.d.ts
6
+ declare const DEFAULT_JUDGE_MODEL = "openai/gpt-4o-mini";
7
+ interface JudgeDimension {
8
+ /** JSON field name + score key. */
9
+ key: string;
10
+ /** Description shown in the judge's user prompt. */
11
+ description: string;
12
+ }
13
+ interface JudgeConfig<TInput> {
14
+ /** Display name (for trace + log). */
15
+ name: string;
16
+ /** Model used for this judge. */
17
+ model?: string;
18
+ /** 0-10 scored dimensions. */
19
+ dimensions: JudgeDimension[];
20
+ /** Judge system prompt — sets persona + JSON-only constraint. */
21
+ systemPrompt: string;
22
+ /** Build the user prompt from the typed input. Must include "Respond with
23
+ * ONLY this JSON: { ... }" listing each dimension key. */
24
+ buildPrompt: (input: TInput) => string;
25
+ /** Optional model + api overrides. */
26
+ apiKey?: string;
27
+ baseUrl?: string;
28
+ /** Maximum output tokens for the judge response. Defaults to 1500. */
29
+ maxTokens?: number;
30
+ }
31
+ interface JudgeRunResult {
32
+ /** Semantic result; failed scores remain non-throwing so matrix aggregation can exclude them. */
33
+ score: JudgeScore;
34
+ /** Cost of the completed call, separate from diagnostic provider metadata. */
35
+ cost: CostProvenance;
36
+ }
37
+ declare function runJudge<TInput>(judge: JudgeConfig<TInput>, input: TInput): Promise<JudgeRunResult>;
38
+ /** Convenience: stringified dimension list for inclusion in a judge prompt.
39
+ * Returns lines like `- audience_fit: Does this match what the audience cares about? (0-10)`. */
40
+ declare function renderDimensions(dims: readonly JudgeDimension[]): string;
41
+ /** Convenience: build the "Respond with ONLY this JSON" footer for a judge prompt. */
42
+ declare function renderJsonFooter(dims: readonly JudgeDimension[]): string;
43
+ //#endregion
44
+ //#region src/multishot/types.d.ts
45
+ interface MultishotMessage {
46
+ role: 'user' | 'assistant' | 'tool';
47
+ content: string;
48
+ toolCallId?: string;
49
+ toolCalls?: Array<{
50
+ id: string;
51
+ name: string;
52
+ args: Record<string, unknown>;
53
+ }>;
54
+ }
55
+ interface MultishotArtifact {
56
+ type: string;
57
+ turn: number;
58
+ invocation: {
59
+ name: string;
60
+ args: Record<string, unknown>;
61
+ };
62
+ content: string;
63
+ }
64
+ interface MultishotResult {
65
+ transcript: MultishotMessage[];
66
+ artifacts: MultishotArtifact[];
67
+ toolCalls: number;
68
+ durationMs: number;
69
+ /** Known spend. A subtotal, not a total, when `costProvenance.kind` is
70
+ * `uncaptured`. */
71
+ costUsd: number;
72
+ /** Origin of `costUsd`. A shot that priced every call reports `estimated`
73
+ * or `observed`; a shot with a call the router priced at nothing reports
74
+ * `uncaptured`, and the matrix records the cell as under-counted instead of
75
+ * presenting the subtotal as a complete estimate.
76
+ *
77
+ * Optional so an engine written before this field keeps working; the matrix
78
+ * then judges the cell on judge receipts alone, as it did before. */
79
+ costProvenance?: CostProvenance;
80
+ }
81
+ interface MultishotToolDefinition {
82
+ type: 'function';
83
+ function: {
84
+ name: string;
85
+ description: string;
86
+ parameters: Record<string, unknown>;
87
+ };
88
+ }
89
+ /** One chat-completion request the multishot loop issues for a single agent
90
+ * (or driver) inference step. Mirrors the OpenAI-compat body the loop would
91
+ * otherwise POST to the Tangle router. */
92
+ interface MultishotTransportRequest {
93
+ model: string;
94
+ messages: Array<Record<string, unknown>>;
95
+ tools?: MultishotToolDefinition[];
96
+ temperature?: number;
97
+ maxTokens?: number;
98
+ signal?: AbortSignal;
99
+ }
100
+ interface MultishotTransportToolCall {
101
+ id: string;
102
+ type: 'function';
103
+ function: {
104
+ name: string;
105
+ arguments: string;
106
+ };
107
+ }
108
+ interface MultishotTransportResponse {
109
+ message: {
110
+ content?: string | null;
111
+ tool_calls?: MultishotTransportToolCall[];
112
+ };
113
+ usage?: {
114
+ prompt_tokens?: number;
115
+ completion_tokens?: number;
116
+ };
117
+ /** Actual spend for this call. When omitted, the loop meters cost from
118
+ * `usage` via the per-model router estimator (estimateRouterCost). */
119
+ costUsd?: number;
120
+ }
121
+ /** Execution seam for one leg of the multishot loop. When provided, it
122
+ * replaces the internal router HTTP call for that leg — the loop still owns
123
+ * turn scheduling, tool dispatch, transcript capture, and cost metering.
124
+ * agent-eval has no dependency on agent-runtime; adapt agent-runtime's
125
+ * resolveAgentBackend (or any sandbox/cli-bridge/router client) into this
126
+ * signature product-side. */
127
+ type MultishotTransport = (req: MultishotTransportRequest) => Promise<MultishotTransportResponse>;
128
+ type MultishotToolExecutor = (args: Record<string, unknown>, ctx: {
129
+ apiKey: string;
130
+ baseUrl: string;
131
+ signal?: AbortSignal;
132
+ }) => Promise<{
133
+ content: string;
134
+ costUsd: number;
135
+ }>;
136
+ interface MultishotPersona {
137
+ /** Stable identifier — used for per-cell artifact paths + matrix axis keys. */
138
+ id: string;
139
+ /** Per-domain payload (income/profile/voice/etc.) shaped by the consumer. */
140
+ [k: string]: unknown;
141
+ }
142
+ /**
143
+ * Persona-shaping callbacks. Both are OPTIONAL: when omitted, the loop derives
144
+ * them from the `AgentProfile` + persona payload (see `defaultShapeFromProfile`)
145
+ * so a pure-profile call — `runMultishot({ profile, persona })` — works with no
146
+ * role-builder functions. Provide callbacks only to override the derived shape.
147
+ */
148
+ interface MultishotShape<TPersona extends MultishotPersona> {
149
+ /** Opening user message (turn 0) — the persona's first ask. */
150
+ buildOpener?: (persona: TPersona) => string;
151
+ /** System prompt the driver LLM uses to roleplay the persona. Should set
152
+ * voice, goals, constraints, time-pressure, and the "never go silent" rule. */
153
+ buildDriverSystemPrompt?: (persona: TPersona) => string;
154
+ }
155
+ declare class MultishotDriverEmptyError extends Error {
156
+ readonly turn: number;
157
+ constructor(turn: number);
158
+ }
159
+ declare class MultishotFatalToolError extends Error {
160
+ constructor(message: string);
161
+ }
162
+ declare class MultishotShotResultError extends Error {
163
+ constructor(reason: string);
164
+ }
165
+ /** Contract guard for the value a caller-supplied shot resolves with. The
166
+ * matrix writes per-cell artifacts, builds judge inputs, and meters cost from
167
+ * this value, so a malformed result must stop the cell instead of scoring a
168
+ * degraded one. Two silent degradations this closes: an artifact with no
169
+ * `type` matches neither the code nor the content artifact set, so the cell
170
+ * scores as though the artifact was never produced; a non-finite `costUsd`
171
+ * reaches `summary.totalCostUsd` and makes every cost number NaN.
172
+ *
173
+ * A rejected cell is still billed: the matrix cell reads the shot's own
174
+ * `costUsd` when it is a usable amount and declares that spend on the throw,
175
+ * so money the shot spent before returning a malformed result stays in the
176
+ * cumulative sum the cost ceiling reads. A result whose `costUsd` is itself
177
+ * malformed carries no usable amount, and the cell records as `uncaptured`.
178
+ *
179
+ * Every required field of `MultishotMessage` and `MultishotArtifact` is
180
+ * checked, including `toolCalls` elements and `invocation.args`. Optional
181
+ * fields are checked only when present. */
182
+ declare function assertMultishotShotResult(value: unknown): asserts value is MultishotResult;
183
+ //#endregion
184
+ //#region src/multishot/multishot.d.ts
185
+ interface RunMultishotOptions<TPersona extends MultishotPersona> {
186
+ profile: AgentProfile;
187
+ persona: TPersona;
188
+ /** Persona-shaping callbacks. Optional — omitted callbacks are derived from
189
+ * the profile + persona payload, so a pure-profile call works. */
190
+ shape?: MultishotShape<TPersona>;
191
+ /** Tool definitions advertised to the agent. Defaults to delegate_research + delegate_code. */
192
+ tools?: MultishotToolDefinition[];
193
+ /** Map from tool name → executor invoked inline when the agent emits a tool_call. */
194
+ toolExecutors?: Record<string, MultishotToolExecutor>;
195
+ /** Map from tool name → artifact type label written into MultishotArtifact.type.
196
+ * Tools without a mapping still execute, but their results aren't surfaced as
197
+ * typed artifacts (only as tool messages in the transcript). */
198
+ artifactTypeFor?: (toolName: string) => string | undefined;
199
+ maxTurns?: number;
200
+ agentModel?: string;
201
+ driverModel?: string;
202
+ /** Fallback driver models tried when the primary simulated-user model returns empty twice. */
203
+ driverFallbackModels?: string[];
204
+ /** Maximum output tokens for the first agent call in each assistant turn. */
205
+ agentMaxTokens?: number;
206
+ /** Maximum output tokens for agent follow-up calls after tool results. */
207
+ toolFollowupMaxTokens?: number;
208
+ /** Maximum output tokens for each simulated-user driver response. */
209
+ driverMaxTokens?: number;
210
+ /** Maximum tool calls the agent may dispatch inside one assistant turn. */
211
+ maxToolDispatches?: number;
212
+ /** Execution seam for the agent leg. When provided, every agent inference
213
+ * step goes through this function instead of the router HTTP call; the
214
+ * string levers (agentModel, apiKey, baseUrl) stop applying to that leg.
215
+ * apiKey/baseUrl are still resolved for tool executors and any leg
216
+ * without an injected transport. */
217
+ agentTransport?: MultishotTransport;
218
+ /** Execution seam for the simulated-user driver leg (symmetric to
219
+ * agentTransport). Driver model fallback rotation still applies — the
220
+ * transport receives each candidate model in turn. */
221
+ driverTransport?: MultishotTransport;
222
+ apiKey?: string;
223
+ baseUrl?: string;
224
+ signal?: AbortSignal;
225
+ }
226
+ /** One multishot shot — the conversation engine `runMultishotMatrix` invokes
227
+ * once per cell. `runMultishot` is the default implementation.
228
+ *
229
+ * An alternative engine (a graph-backed conversation, a replay of a recorded
230
+ * transcript, a sandbox-hosted agent) implements this exact signature and
231
+ * reaches the matrix through `RunMultishotMatrixOptions.runShot`. The matrix
232
+ * keeps every other cell mechanic — cell fan-out, concurrency, the cost
233
+ * ceiling, the judge slots, the cell composite, and the per-cell writers — so
234
+ * swapping the engine needs no copy of the cell body. */
235
+ type MultishotShot<TPersona extends MultishotPersona> = (opts: RunMultishotOptions<TPersona>) => Promise<MultishotResult>;
236
+ declare function runMultishot<TPersona extends MultishotPersona>(opts: RunMultishotOptions<TPersona>): Promise<MultishotResult>;
237
+ //#endregion
238
+ //#region src/multishot/matrix.d.ts
239
+ interface ConversationJudgeInput<TPersona extends MultishotPersona> {
240
+ transcript: MultishotMessage[];
241
+ persona: TPersona;
242
+ }
243
+ interface ArtifactJudgeInput<TPersona extends MultishotPersona> {
244
+ artifact: MultishotArtifact;
245
+ persona: TPersona;
246
+ }
247
+ interface MultishotJudges<TPersona extends MultishotPersona> {
248
+ /** Scores the full transcript end-to-end (always runs). */
249
+ conversation: JudgeConfig<ConversationJudgeInput<TPersona>>;
250
+ /** Scores each code-type artifact. Optional — omit when domain has no code artifacts. */
251
+ codeReview?: JudgeConfig<ArtifactJudgeInput<TPersona>>;
252
+ /** Scores each non-code (research/content/template) artifact. Optional. */
253
+ contentQuality?: JudgeConfig<ArtifactJudgeInput<TPersona>>;
254
+ /** Which artifact types route to codeReview. Defaults to ['code']. */
255
+ codeArtifactTypes?: string[];
256
+ /** Which artifact types route to contentQuality. Defaults to ['research']. */
257
+ contentArtifactTypes?: string[];
258
+ }
259
+ interface CellCompositeScore {
260
+ composite: number;
261
+ conversation: JudgeScore;
262
+ codeReview?: {
263
+ perArtifact: Array<JudgeScore & {
264
+ turn: number;
265
+ type: string;
266
+ }>;
267
+ composite: number;
268
+ };
269
+ contentQuality?: {
270
+ perArtifact: Array<JudgeScore & {
271
+ turn: number;
272
+ type: string;
273
+ }>;
274
+ composite: number;
275
+ };
276
+ }
277
+ interface RunMultishotMatrixOptions<TPersona extends MultishotPersona> {
278
+ /** AgentProfile axis (matrix primary). */
279
+ profiles: Array<{
280
+ id: string;
281
+ value: AgentProfile;
282
+ }>;
283
+ /** Persona axis. */
284
+ personas: TPersona[];
285
+ /** Persona-shaping callbacks. Optional — omitted callbacks are derived per
286
+ * cell from that cell's profile + persona payload (pure-profile path). */
287
+ shape?: MultishotShape<TPersona>;
288
+ /** Judge configurations. */
289
+ judges: MultishotJudges<TPersona>;
290
+ /** Tool definitions advertised to the agent. Defaults to delegate_research + delegate_code. */
291
+ tools?: MultishotToolDefinition[];
292
+ /** Map from tool name → inline executor. Must align with `tools`. */
293
+ toolExecutors?: Record<string, MultishotToolExecutor>;
294
+ /** Tool name → artifact type label. Defaults to research/code mapping. */
295
+ artifactTypeFor?: (toolName: string) => string | undefined;
296
+ /** Where per-cell artifacts land. Cells write to `<runDir>/<profileId>/<personaId>/rep-N/`. */
297
+ runDir: string;
298
+ /** Replicates per (profile, persona) cell. */
299
+ reps?: number;
300
+ /** Max conversation turns per cell. */
301
+ maxTurns?: number;
302
+ /** Maximum tool calls the agent may dispatch inside one assistant turn. */
303
+ maxToolDispatches?: number;
304
+ /** Max concurrent cells. */
305
+ maxConcurrency?: number;
306
+ /** Total $ ceiling across the matrix; cells aborted past this. */
307
+ costCeiling?: number;
308
+ /** Upper bound on what one cell can spend. A cell whose cost is a subtotal
309
+ * is charged this bound against `costCeiling` instead of its known amount,
310
+ * so hidden spend cannot walk the run past its budget. */
311
+ maxCellCostUsd?: number;
312
+ /** Agent model. */
313
+ agentModel?: string;
314
+ /** Driver model. */
315
+ driverModel?: string;
316
+ /** Fallback driver models tried when the primary simulated-user model returns empty twice. */
317
+ driverFallbackModels?: string[];
318
+ /** Maximum output tokens for the first agent call in each assistant turn. */
319
+ agentMaxTokens?: number;
320
+ /** Maximum output tokens for agent follow-up calls after tool results. */
321
+ toolFollowupMaxTokens?: number;
322
+ /** Maximum output tokens for each simulated-user driver response. */
323
+ driverMaxTokens?: number;
324
+ /** Maximum output tokens for each judge response. */
325
+ judgeMaxTokens?: number;
326
+ /** Execution seam for the agent leg of every cell — replaces the router
327
+ * HTTP call when provided (see RunMultishotOptions.agentTransport).
328
+ * Judges are unaffected; configure those via MultishotJudges. */
329
+ agentTransport?: MultishotTransport;
330
+ /** Execution seam for the simulated-user driver leg of every cell. */
331
+ driverTransport?: MultishotTransport;
332
+ /** Conversation engine for every cell. Defaults to `runMultishot`.
333
+ *
334
+ * The matrix owns everything around the shot — cell fan-out, concurrency,
335
+ * the cost ceiling, the judge slots, the cell composite, the per-cell
336
+ * artifact writers and the run summary — and forwards the whole cell input
337
+ * to this function, so an alternative engine replaces ONLY the
338
+ * conversation. Every option on this interface that `runMultishot` accepts
339
+ * reaches the shot unchanged. `RunMultishotOptions.signal` has no
340
+ * matrix-level counterpart and is not forwarded; a shot owns its own
341
+ * cancellation.
342
+ *
343
+ * A shot that resolves with a value outside `MultishotResult` throws
344
+ * `MultishotShotResultError` for that cell. The default engine is never
345
+ * used as a fallback. */
346
+ runShot?: MultishotShot<TPersona>;
347
+ /** Pass-thru fields. */
348
+ apiKey?: string;
349
+ baseUrl?: string;
350
+ }
351
+ /** Per-cell output the multishot matrix records in `MatrixResult.cells`.
352
+ * A consumer that supplies its own `runShot` reads the matrix through this
353
+ * type instead of declaring a structural copy. */
354
+ interface MultishotCellOutput {
355
+ turns: number;
356
+ toolCalls: number;
357
+ artifactCount: number;
358
+ }
359
+ interface CellCompositeInput {
360
+ conversation: JudgeScore;
361
+ /** Present iff the codeReview judge is configured. */
362
+ codeReviews?: ReadonlyArray<JudgeScore>;
363
+ /** Present iff the contentQuality judge is configured. */
364
+ contentReviews?: ReadonlyArray<JudgeScore>;
365
+ }
366
+ /** Cell composite = mean over configured judge slots, excluding failed
367
+ * scores: a failed conversation judge or an all-failed artifact slot carries
368
+ * no signal and is dropped from the mean. `composite` is 0 only when EVERY
369
+ * configured slot failed (`allJudgesFailed` distinguishes that from a real
370
+ * zero). Pure — exported for deterministic testing. */
371
+ declare function computeCellComposite(input: CellCompositeInput): {
372
+ composite: number;
373
+ codeComposite: number;
374
+ contentComposite: number;
375
+ allJudgesFailed: boolean;
376
+ };
377
+ interface RunMultishotMatrixResult {
378
+ matrix: MatrixResult<MultishotCellOutput>;
379
+ }
380
+ declare function runMultishotMatrix<TPersona extends MultishotPersona>(opts: RunMultishotMatrixOptions<TPersona>): Promise<RunMultishotMatrixResult>;
381
+ //#endregion
382
+ export { JudgeConfig as A, MultishotToolExecutor as C, MultishotTransportToolCall as D, MultishotTransportResponse as E, runJudge as F, JudgeRunResult as M, renderDimensions as N, assertMultishotShotResult as O, renderJsonFooter as P, MultishotToolDefinition as S, MultishotTransportRequest as T, MultishotMessage as _, MultishotCellOutput as a, MultishotShape as b, RunMultishotMatrixResult as c, MultishotShot as d, RunMultishotOptions as f, MultishotFatalToolError as g, MultishotDriverEmptyError as h, ConversationJudgeInput as i, JudgeDimension as j, DEFAULT_JUDGE_MODEL as k, computeCellComposite as l, MultishotArtifact as m, CellCompositeInput as n, MultishotJudges as o, runMultishot as p, CellCompositeScore as r, RunMultishotMatrixOptions as s, ArtifactJudgeInput as t, runMultishotMatrix as u, MultishotPersona as v, MultishotTransport as w, MultishotShotResultError as x, MultishotResult as y };
383
+ //# sourceMappingURL=matrix-C-2Qx1Zr.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matrix-C-2Qx1Zr.d.ts","names":[],"sources":["../src/multishot/judges.ts","../src/multishot/types.ts","../src/multishot/multishot.ts","../src/multishot/matrix.ts"],"mappings":";;;;;cAyBa;UAEI;;EAEf;;EAEA;;UAGe,YAAY;;EAE3B;;EAEA;;EAEA,YAAY;;EAEZ;;;EAGA,cAAc,OAAO;;EAErB;EACA;;EAEA;;UAGe;;EAEf,OAAO;;EAEP,MAAM;;iBAGc,SAAS,QAC7B,OAAO,YAAY,SACnB,OAAO,SACN,QAAQ;;;iBAkIK,iBAAiB,eAAe;;iBAKhC,iBAAiB,eAAe;;;UClM/B;EACf;EACA;EACA;EACA,YAAY;IAAQ;IAAY;IAAc,MAAM;;;UAGrC;EACf;EACA;EACA;IAAc;IAAc,MAAM;;EAClC;;UAGe;EACf,YAAY;EACZ,WAAW;EACX;EACA;;;EAGA;;;;;;;;EAQA,iBAAiB;;UAGF;EACf;EACA;IACE;IACA;IACA,YAAY;;;;;;UAOC;EACf;EACA,UAAU,MAAM;EAChB,QAAQ;EACR;EACA;EACA,SAAS;;UAGM;EACf;EACA;EACA;IAAY;IAAc;;;UAGX;EACf;IAAW;IAAyB,aAAa;;EACjD;IAAU;IAAwB;;;;EAGlC;;;;;;;;KASU,sBACV,KAAK,8BACF,QAAQ;KAED,yBACV,MAAM,yBACN;EAAO;EAAgB;EAAiB,SAAS;MAC9C;EAAU;EAAiB;;UAEf;;EAEf;;GAEC;;;;;;;;UASc,eAAe,iBAAiB;;EAE/C,eAAe,SAAS;;;EAGxB,2BAA2B,SAAS;;cAGzB,kCAAkC;WACjB;EAA5B,YAA4B;;cAMjB,gCAAgC;EAC3C,YAAY;;cAMD,iCAAiC;EAC5C,YAAY;;;;;;;;;;;;;;;;;;;iBAyBE,0BAA0B,yBAAyB,SAAS;;;UCpH3D,oBAAoB,iBAAiB;EACpD,SAAS;EACT,SAAS;;;EAGT,QAAQ,eAAe;;EAEvB,QAAQ;;EAER,gBAAgB,eAAe;;;;EAI/B,mBAAmB;EACnB;EACA;EACA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;;;;;EAMA,iBAAiB;;;;EAIjB,kBAAkB;EAClB;EACA;EACA,SAAS;;;;;;;;;;;KAYC,cAAc,iBAAiB,qBACzC,MAAM,oBAAoB,cACvB,QAAQ;iBAWS,aAAa,iBAAiB,kBAClD,MAAM,oBAAoB,YACzB,QAAQ;;;UCtEM,uBAAuB,iBAAiB;EACvD,YAAY;EACZ,SAAS;;UAGM,mBAAmB,iBAAiB;EACnD,UAAU;EACV,SAAS;;UAGM,gBAAgB,iBAAiB;;EAEhD,cAAc,YAAY,uBAAuB;;EAEjD,aAAa,YAAY,mBAAmB;;EAE5C,iBAAiB,YAAY,mBAAmB;;EAEhD;;EAEA;;UAGe;EACf;EACA,cAAc;EACd;IACE,aAAa,MAAM;MAAe;MAAc;;IAChD;;EAEF;IACE,aAAa,MAAM;MAAe;MAAc;;IAChD;;;UAIa,0BAA0B,iBAAiB;;EAE1D,UAAU;IAAQ;IAAY,OAAO;;;EAErC,UAAU;;;EAGV,QAAQ,eAAe;;EAEvB,QAAQ,gBAAgB;;EAExB,QAAQ;;EAER,gBAAgB,eAAe;;EAE/B,mBAAmB;;EAEnB;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;;;EAIA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;;;EAIA,iBAAiB;;EAEjB,kBAAkB;;;;;;;;;;;;;;;EAelB,UAAU,cAAc;;EAExB;EACA;;;;;UAMe;EACf;EACA;EACA;;UAoBe;EACf,cAAc;;EAEd,cAAc,cAAc;;EAE5B,iBAAiB,cAAc;;;;;;;iBAQjB,qBAAqB,OAAO;EAC1C;EACA;EACA;EACA;;UAuBe;EACf,QAAQ,aAAa;;iBAGD,mBAAmB,iBAAiB,kBACxD,MAAM,0BAA0B,YAC/B,QAAQ"}
@@ -1,7 +1,7 @@
1
1
  import { f as Run } from "../schema-BtVldJ3T.js";
2
2
  import { s as TraceStore } from "../store-CT9YIIve.js";
3
3
  import { a as ContinuousCalibrationResult, n as CandidateScore, o as GoldenItem, r as ContinuousAgreement, t as CalibrationResult } from "../judge-calibration-C5CbMYce.js";
4
- import { n as SeriesConvergenceResult, o as CorpusAgreementReport, t as SeriesConvergenceOptions } from "../series-convergence-C9G-GNYK.js";
4
+ import { n as SeriesConvergenceResult, o as CorpusAgreementReport, t as SeriesConvergenceOptions } from "../series-convergence-D2fsoJ2w.js";
5
5
  import { a as OutcomeFilter, i as InMemoryOutcomeStore, n as FileSystemOutcomeStore, o as OutcomeStore, r as FileSystemOutcomeStoreOptions, t as DeploymentOutcome } from "../outcome-store-BYHIuO0e.js";
6
6
  import { a as rubricPredictiveValidity, i as RubricRanking, n as RubricPredictiveValidityInput, r as RubricPredictiveValidityReport, t as RubricOutcomePair } from "../rubric-predictive-validity-C7LnNvF2.js";
7
7
  //#region src/meta-eval/correlation-study.d.ts
@@ -24,6 +24,10 @@ const MODEL_PRICING = {
24
24
  "claude-3-haiku-20240307": {
25
25
  input: 25e-5,
26
26
  output: .00125
27
+ },
28
+ "glm-5.3": {
29
+ input: .00168,
30
+ output: .00528
27
31
  }
28
32
  };
29
33
  /** Family-level pricing fallbacks (per-1K), matched against a normalized id
@@ -88,19 +92,22 @@ const FAMILY_PRICING = [
88
92
  }]
89
93
  ];
90
94
  /** Normalize a model id for pricing: drop a `@snapshot` suffix, lowercase,
91
- * and keep the final harness/provider-prefixed segment so family regexes
92
- * match (`opencode/zai-coding-plan/glm-5.1` → `glm-5.1`). */
93
- function normalizeModelId(model) {
94
- return (model.split("@")[0] ?? model).trim().toLowerCase();
95
+ * and return both the complete harness/provider-prefixed id and its final
96
+ * served-model segment (`opencode/zai-coding-plan/glm-5.3` → full id plus
97
+ * `glm-5.3`). Exact rows are checked against both before family fallback. */
98
+ function normalizedModelIds(model) {
99
+ const id = (model.split("@")[0] ?? model).trim().toLowerCase();
100
+ const finalSegment = id.slice(id.lastIndexOf("/") + 1);
101
+ return finalSegment === id ? [id] : [id, finalSegment];
95
102
  }
96
103
  /** Resolve pricing for a model id: exact table, then family fallback.
97
104
  * Returns null when the id matches nothing (caller decides — never a
98
105
  * silent-zero masquerading as a real $0 cost). */
99
106
  function resolveModelPricing(model) {
100
107
  if (MODEL_PRICING[model]) return MODEL_PRICING[model];
101
- const id = normalizeModelId(model);
102
- if (MODEL_PRICING[id]) return MODEL_PRICING[id];
103
- for (const [pattern, price] of FAMILY_PRICING) if (pattern.test(id)) return price;
108
+ const ids = normalizedModelIds(model);
109
+ for (const id of ids) if (MODEL_PRICING[id]) return MODEL_PRICING[id];
110
+ for (const [pattern, price] of FAMILY_PRICING) if (ids.some((id) => pattern.test(id))) return price;
104
111
  return null;
105
112
  }
106
113
  /** True when `model` has known pricing (exact or family). Lets cost-aware
@@ -130,4 +137,4 @@ function estimateCost(inputTokens, outputTokens, model) {
130
137
  //#endregion
131
138
  export { resolveModelPricing as a, isModelPriced as i, estimateCost as n, estimateTokens as r, MODEL_PRICING as t };
132
139
 
133
- //# sourceMappingURL=metrics-Cl0L1KUy.js.map
140
+ //# sourceMappingURL=metrics-Qv-cpptD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics-Qv-cpptD.js","names":[],"sources":["../src/metrics.ts"],"sourcesContent":["interface TokenPrice {\n input: number\n output: number\n}\n\n/** Per-1K token pricing for exact model ids. */\nexport const MODEL_PRICING: Record<string, TokenPrice> = {\n 'gpt-4o': { input: 0.0025, output: 0.01 },\n 'gpt-4o-mini': { input: 0.00015, output: 0.0006 },\n 'gpt-4-turbo': { input: 0.01, output: 0.03 },\n 'claude-sonnet-4-20250514': { input: 0.003, output: 0.015 },\n 'claude-opus-4-20250514': { input: 0.015, output: 0.075 },\n 'claude-3-haiku-20240307': { input: 0.00025, output: 0.00125 },\n // Router response-header rates observed for the exact served model on\n // 2026-08-15. Keep this exact row ahead of the deliberately coarse family\n // fallback so glm-5.3 campaign costs are not understated by ~2.5x.\n 'glm-5.3': { input: 0.00168, output: 0.00528 },\n}\n\n/** Family-level pricing fallbacks (per-1K), matched against a normalized id\n * after exact lookup misses. Ordered — first match wins. Covers the model\n * ids actually used through the Tangle router + cli-bridge harnesses\n * (`claude-code/sonnet`, `opencode/zai-coding-plan/glm-5.1`,\n * `kimi-code/kimi-k2.6`, `deepseek-v4-pro`, `anthropic/claude-sonnet-4-6`, …),\n * none of which appear in the exact table above — without this they priced\n * to a silent $0, blanking every cost/Pareto axis downstream. */\nconst FAMILY_PRICING: Array<[RegExp, TokenPrice]> = [\n [/claude.*opus/, { input: 0.015, output: 0.075 }],\n [/claude.*haiku/, { input: 0.0008, output: 0.004 }],\n [/claude.*sonnet|claude-code|claude-sonnet/, { input: 0.003, output: 0.015 }],\n [/gpt-4o-mini/, { input: 0.00015, output: 0.0006 }],\n [/gpt-5|gpt-4\\.1|o[134]\\b/, { input: 0.00125, output: 0.01 }],\n [/gpt-4o|gpt-4/, { input: 0.0025, output: 0.01 }],\n [/deepseek/, { input: 0.0003, output: 0.0011 }],\n [/glm|zhipu|zai/, { input: 0.0006, output: 0.0022 }],\n [/kimi|moonshot/, { input: 0.0006, output: 0.0025 }],\n [/qwen/, { input: 0.0004, output: 0.0012 }],\n [/gemini.*flash/, { input: 0.0001, output: 0.0004 }],\n [/gemini/, { input: 0.00125, output: 0.005 }],\n [/llama/, { input: 0.0002, output: 0.0006 }],\n]\n\n/** Normalize a model id for pricing: drop a `@snapshot` suffix, lowercase,\n * and return both the complete harness/provider-prefixed id and its final\n * served-model segment (`opencode/zai-coding-plan/glm-5.3` → full id plus\n * `glm-5.3`). Exact rows are checked against both before family fallback. */\nfunction normalizedModelIds(model: string): string[] {\n const id = (model.split('@')[0] ?? model).trim().toLowerCase()\n const finalSegment = id.slice(id.lastIndexOf('/') + 1)\n return finalSegment === id ? [id] : [id, finalSegment]\n}\n\n/** Resolve pricing for a model id: exact table, then family fallback.\n * Returns null when the id matches nothing (caller decides — never a\n * silent-zero masquerading as a real $0 cost). */\nexport function resolveModelPricing(model: string): TokenPrice | null {\n if (MODEL_PRICING[model]) return MODEL_PRICING[model]\n const ids = normalizedModelIds(model)\n for (const id of ids) {\n if (MODEL_PRICING[id]) return MODEL_PRICING[id]\n }\n for (const [pattern, price] of FAMILY_PRICING) {\n if (ids.some((id) => pattern.test(id))) return price\n }\n return null\n}\n\n/** True when `model` has known pricing (exact or family). Lets cost-aware\n * callers distinguish a real $0 from an unpriced model. */\nexport function isModelPriced(model: string): boolean {\n return resolveModelPricing(model) !== null\n}\n\nconst warnedUnpricedModels = new Set<string>()\n\n/** Estimate token count from string length (chars / 4 approximation) */\nexport function estimateTokens(text: string): number {\n return Math.ceil(text.length / 4)\n}\n\n/** Calculate cost in USD from token counts and model. Unknown models warn\n * once (not a silent zero) and return 0 so callers that ignore pricing keep\n * working; cost-sensitive callers should gate on {@link isModelPriced}. */\nexport function estimateCost(inputTokens: number, outputTokens: number, model: string): number {\n const pricing = resolveModelPricing(model)\n if (!pricing) {\n if (!warnedUnpricedModels.has(model)) {\n warnedUnpricedModels.add(model)\n console.warn(\n `estimateCost: no pricing for model \"${model}\" — returning 0; add it to ` +\n 'MODEL_PRICING/FAMILY_PRICING (cost/Pareto axes will be blank until then)',\n )\n }\n return 0\n }\n return (inputTokens / 1000) * pricing.input + (outputTokens / 1000) * pricing.output\n}\n\n/**\n * TokenCounter — accumulates token usage and cost across turns.\n */\nexport class TokenCounter {\n private totalInput = 0\n private totalOutput = 0\n private totalCost = 0\n private model: string\n\n constructor(model = 'gpt-4o') {\n this.model = model\n }\n\n /** Record tokens for a turn, returns per-turn cost */\n record(inputTokens: number, outputTokens: number): number {\n this.totalInput += inputTokens\n this.totalOutput += outputTokens\n const cost = estimateCost(inputTokens, outputTokens, this.model)\n this.totalCost += cost\n return cost\n }\n\n /** Estimate and record from raw text */\n recordFromText(\n inputText: string,\n outputText: string,\n ): { inputTokens: number; outputTokens: number; cost: number } {\n const inputTokens = estimateTokens(inputText)\n const outputTokens = estimateTokens(outputText)\n const cost = this.record(inputTokens, outputTokens)\n return { inputTokens, outputTokens, cost }\n }\n\n getTotalInput(): number {\n return this.totalInput\n }\n getTotalOutput(): number {\n return this.totalOutput\n }\n getTotalCost(): number {\n return this.totalCost\n }\n}\n"],"mappings":";;AAMA,MAAa,gBAA4C;CACvD,UAAU;EAAE,OAAO;EAAQ,QAAQ;CAAK;CACxC,eAAe;EAAE,OAAO;EAAS,QAAQ;CAAO;CAChD,eAAe;EAAE,OAAO;EAAM,QAAQ;CAAK;CAC3C,4BAA4B;EAAE,OAAO;EAAO,QAAQ;CAAM;CAC1D,0BAA0B;EAAE,OAAO;EAAO,QAAQ;CAAM;CACxD,2BAA2B;EAAE,OAAO;EAAS,QAAQ;CAAQ;CAI7D,WAAW;EAAE,OAAO;EAAS,QAAQ;CAAQ;AAC/C;;;;;;;;AASA,MAAM,iBAA8C;CAClD,CAAC,gBAAgB;EAAE,OAAO;EAAO,QAAQ;CAAM,CAAC;CAChD,CAAC,iBAAiB;EAAE,OAAO;EAAQ,QAAQ;CAAM,CAAC;CAClD,CAAC,4CAA4C;EAAE,OAAO;EAAO,QAAQ;CAAM,CAAC;CAC5E,CAAC,eAAe;EAAE,OAAO;EAAS,QAAQ;CAAO,CAAC;CAClD,CAAC,2BAA2B;EAAE,OAAO;EAAS,QAAQ;CAAK,CAAC;CAC5D,CAAC,gBAAgB;EAAE,OAAO;EAAQ,QAAQ;CAAK,CAAC;CAChD,CAAC,YAAY;EAAE,OAAO;EAAQ,QAAQ;CAAO,CAAC;CAC9C,CAAC,iBAAiB;EAAE,OAAO;EAAQ,QAAQ;CAAO,CAAC;CACnD,CAAC,iBAAiB;EAAE,OAAO;EAAQ,QAAQ;CAAO,CAAC;CACnD,CAAC,QAAQ;EAAE,OAAO;EAAQ,QAAQ;CAAO,CAAC;CAC1C,CAAC,iBAAiB;EAAE,OAAO;EAAQ,QAAQ;CAAO,CAAC;CACnD,CAAC,UAAU;EAAE,OAAO;EAAS,QAAQ;CAAM,CAAC;CAC5C,CAAC,SAAS;EAAE,OAAO;EAAQ,QAAQ;CAAO,CAAC;AAC7C;;;;;AAMA,SAAS,mBAAmB,OAAyB;CACnD,MAAM,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,MAAA,CAAO,KAAK,CAAC,CAAC,YAAY;CAC7D,MAAM,eAAe,GAAG,MAAM,GAAG,YAAY,GAAG,IAAI,CAAC;CACrD,OAAO,iBAAiB,KAAK,CAAC,EAAE,IAAI,CAAC,IAAI,YAAY;AACvD;;;;AAKA,SAAgB,oBAAoB,OAAkC;CACpE,IAAI,cAAc,QAAQ,OAAO,cAAc;CAC/C,MAAM,MAAM,mBAAmB,KAAK;CACpC,KAAK,MAAM,MAAM,KACf,IAAI,cAAc,KAAK,OAAO,cAAc;CAE9C,KAAK,MAAM,CAAC,SAAS,UAAU,gBAC7B,IAAI,IAAI,MAAM,OAAO,QAAQ,KAAK,EAAE,CAAC,GAAG,OAAO;CAEjD,OAAO;AACT;;;AAIA,SAAgB,cAAc,OAAwB;CACpD,OAAO,oBAAoB,KAAK,MAAM;AACxC;AAEA,MAAM,uCAAuB,IAAI,IAAY;;AAG7C,SAAgB,eAAe,MAAsB;CACnD,OAAO,KAAK,KAAK,KAAK,SAAS,CAAC;AAClC;;;;AAKA,SAAgB,aAAa,aAAqB,cAAsB,OAAuB;CAC7F,MAAM,UAAU,oBAAoB,KAAK;CACzC,IAAI,CAAC,SAAS;EACZ,IAAI,CAAC,qBAAqB,IAAI,KAAK,GAAG;GACpC,qBAAqB,IAAI,KAAK;GAC9B,QAAQ,KACN,uCAAuC,MAAM,oGAE/C;EACF;EACA,OAAO;CACT;CACA,OAAQ,cAAc,MAAQ,QAAQ,QAAS,eAAe,MAAQ,QAAQ;AAChF"}