modelrig 0.11.0 → 0.12.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 (199) hide show
  1. package/CHANGELOG.md +82 -0
  2. package/dist/adapters/anthropic.d.ts +4 -4
  3. package/dist/adapters/anthropic.d.ts.map +1 -1
  4. package/dist/adapters/anthropic.js +8 -1
  5. package/dist/adapters/deepseek.d.ts +2 -4
  6. package/dist/adapters/deepseek.d.ts.map +1 -1
  7. package/dist/adapters/deepseek.js +9 -5
  8. package/dist/adapters/gemini.d.ts +4 -1
  9. package/dist/adapters/gemini.d.ts.map +1 -1
  10. package/dist/adapters/gemini.js +16 -1
  11. package/dist/adapters/grok.d.ts +2 -4
  12. package/dist/adapters/grok.d.ts.map +1 -1
  13. package/dist/adapters/grok.js +8 -4
  14. package/dist/adapters/history-mapping.d.ts +126 -0
  15. package/dist/adapters/history-mapping.d.ts.map +1 -0
  16. package/dist/adapters/history-mapping.js +230 -0
  17. package/dist/adapters/openai-compat.d.ts +2 -4
  18. package/dist/adapters/openai-compat.d.ts.map +1 -1
  19. package/dist/adapters/openai-compat.js +9 -5
  20. package/dist/adapters/openai.d.ts +2 -4
  21. package/dist/adapters/openai.d.ts.map +1 -1
  22. package/dist/adapters/openai.js +8 -4
  23. package/dist/adapters/responses-api.d.ts.map +1 -1
  24. package/dist/adapters/responses-api.js +9 -4
  25. package/dist/artifacts/artifact.d.ts.map +1 -1
  26. package/dist/artifacts/artifact.js +79 -0
  27. package/dist/artifacts/conversation.d.ts +128 -0
  28. package/dist/artifacts/conversation.d.ts.map +1 -0
  29. package/dist/artifacts/conversation.js +172 -0
  30. package/dist/artifacts/index.d.ts +1 -1
  31. package/dist/artifacts/index.d.ts.map +1 -1
  32. package/dist/artifacts/media.d.ts +46 -0
  33. package/dist/artifacts/media.d.ts.map +1 -0
  34. package/dist/artifacts/media.js +88 -0
  35. package/dist/artifacts/run-context.d.ts +61 -2
  36. package/dist/artifacts/run-context.d.ts.map +1 -1
  37. package/dist/artifacts/run-context.js +183 -12
  38. package/dist/artifacts/scrub.d.ts +3 -0
  39. package/dist/artifacts/scrub.d.ts.map +1 -1
  40. package/dist/bakeoff/engine.d.ts.map +1 -1
  41. package/dist/bakeoff/engine.js +34 -7
  42. package/dist/bakeoff/eval-cases.d.ts +5 -0
  43. package/dist/bakeoff/eval-cases.d.ts.map +1 -1
  44. package/dist/bakeoff/eval-cases.js +10 -1
  45. package/dist/bakeoff/replay.d.ts +15 -0
  46. package/dist/bakeoff/replay.d.ts.map +1 -1
  47. package/dist/bakeoff/replay.js +19 -1
  48. package/dist/bakeoff/report.d.ts.map +1 -1
  49. package/dist/bakeoff/report.js +9 -2
  50. package/dist/bakeoff/turn-replay.d.ts +93 -0
  51. package/dist/bakeoff/turn-replay.d.ts.map +1 -0
  52. package/dist/bakeoff/turn-replay.js +150 -0
  53. package/dist/bakeoff/types.d.ts +12 -0
  54. package/dist/bakeoff/types.d.ts.map +1 -1
  55. package/dist/cli.d.ts.map +1 -1
  56. package/dist/cli.js +1 -0
  57. package/dist/config.d.ts +18 -0
  58. package/dist/config.d.ts.map +1 -1
  59. package/dist/config.js +23 -3
  60. package/dist/doctor-preflight.d.ts.map +1 -1
  61. package/dist/doctor-preflight.js +6 -1
  62. package/dist/feedback/grade.d.ts +7 -2
  63. package/dist/feedback/grade.d.ts.map +1 -1
  64. package/dist/feedback/grade.js +14 -0
  65. package/dist/feedback/outcome.d.ts +103 -0
  66. package/dist/feedback/outcome.d.ts.map +1 -0
  67. package/dist/feedback/outcome.js +175 -0
  68. package/dist/gateway/history-bridge.d.ts +32 -0
  69. package/dist/gateway/history-bridge.d.ts.map +1 -0
  70. package/dist/gateway/history-bridge.js +64 -0
  71. package/dist/gateway/serve-client.d.ts.map +1 -1
  72. package/dist/gateway/serve-client.js +6 -0
  73. package/dist/index.d.ts +44 -1
  74. package/dist/index.d.ts.map +1 -1
  75. package/dist/index.js +110 -9
  76. package/dist/init/init-cli.d.ts.map +1 -1
  77. package/dist/init/init-cli.js +21 -4
  78. package/dist/init/observe-cli.js +1 -1
  79. package/dist/init/observe.d.ts +7 -1
  80. package/dist/init/observe.d.ts.map +1 -1
  81. package/dist/init/observe.js +74 -22
  82. package/dist/init/starter.d.ts +36 -0
  83. package/dist/init/starter.d.ts.map +1 -0
  84. package/dist/init/starter.js +85 -0
  85. package/dist/registry/build.d.ts +4 -0
  86. package/dist/registry/build.d.ts.map +1 -1
  87. package/dist/registry/generation-models.d.ts +68 -0
  88. package/dist/registry/generation-models.d.ts.map +1 -0
  89. package/dist/registry/generation-models.js +168 -0
  90. package/dist/registry/model-kind.d.ts +34 -0
  91. package/dist/registry/model-kind.d.ts.map +1 -0
  92. package/dist/registry/model-kind.js +40 -0
  93. package/dist/registry/pricing-shape.d.ts +29 -1
  94. package/dist/registry/pricing-shape.d.ts.map +1 -1
  95. package/dist/registry/pricing-shape.js +9 -0
  96. package/dist/registry/pricing.d.ts +26 -0
  97. package/dist/registry/pricing.d.ts.map +1 -1
  98. package/dist/registry/pricing.js +29 -0
  99. package/dist/registry/rows.d.ts.map +1 -1
  100. package/dist/registry/rows.js +3 -1
  101. package/dist/registry/unit-pricing.d.ts +32 -0
  102. package/dist/registry/unit-pricing.d.ts.map +1 -0
  103. package/dist/registry/unit-pricing.js +62 -0
  104. package/dist/routes/input-loader.d.ts +38 -0
  105. package/dist/routes/input-loader.d.ts.map +1 -0
  106. package/dist/routes/input-loader.js +80 -0
  107. package/dist/routes/loader.d.ts.map +1 -1
  108. package/dist/routes/loader.js +3 -0
  109. package/dist/routes/resolved-bundle.d.ts +2 -0
  110. package/dist/routes/resolved-bundle.d.ts.map +1 -1
  111. package/dist/routes/resolved-bundle.js +3 -0
  112. package/dist/run/cost.d.ts +28 -0
  113. package/dist/run/cost.d.ts.map +1 -1
  114. package/dist/run/cost.js +74 -0
  115. package/dist/run/dispatch.d.ts +4 -1
  116. package/dist/run/dispatch.d.ts.map +1 -1
  117. package/dist/run/dispatch.js +3 -0
  118. package/dist/run/limits.d.ts +88 -0
  119. package/dist/run/limits.d.ts.map +1 -0
  120. package/dist/run/limits.js +155 -0
  121. package/dist/run/messages.d.ts +199 -0
  122. package/dist/run/messages.d.ts.map +1 -0
  123. package/dist/run/messages.js +430 -0
  124. package/dist/run/raw-finalize.d.ts +5 -2
  125. package/dist/run/raw-finalize.d.ts.map +1 -1
  126. package/dist/run/raw-finalize.js +8 -5
  127. package/dist/run/raw-request.d.ts.map +1 -1
  128. package/dist/run/raw-request.js +2 -1
  129. package/dist/run/raw.d.ts +10 -4
  130. package/dist/run/raw.d.ts.map +1 -1
  131. package/dist/run/raw.js +11 -3
  132. package/dist/run/rawonly.d.ts +29 -5
  133. package/dist/run/rawonly.d.ts.map +1 -1
  134. package/dist/run/rawonly.js +54 -19
  135. package/dist/run/record-attempt.d.ts.map +1 -1
  136. package/dist/run/record-attempt.js +16 -6
  137. package/dist/run/record-call.d.ts +13 -2
  138. package/dist/run/record-call.d.ts.map +1 -1
  139. package/dist/run/record-call.js +50 -7
  140. package/dist/run/run.d.ts.map +1 -1
  141. package/dist/run/run.js +12 -8
  142. package/dist/telemetry/attempt-meta.d.ts +49 -1
  143. package/dist/telemetry/attempt-meta.d.ts.map +1 -1
  144. package/dist/telemetry/attempt-meta.js +45 -1
  145. package/dist/telemetry/exporter.d.ts.map +1 -1
  146. package/dist/telemetry/exporter.js +2 -1
  147. package/dist/telemetry/grade-mappers.d.ts +1 -1
  148. package/dist/telemetry/grade-mappers.d.ts.map +1 -1
  149. package/dist/telemetry/grade-mappers.js +7 -1
  150. package/dist/telemetry/grade-task.d.ts +49 -0
  151. package/dist/telemetry/grade-task.d.ts.map +1 -0
  152. package/dist/telemetry/grade-task.js +85 -0
  153. package/dist/telemetry/grades-sql.d.ts +16 -1
  154. package/dist/telemetry/grades-sql.d.ts.map +1 -1
  155. package/dist/telemetry/grades-sql.js +64 -4
  156. package/dist/telemetry/ingest-protocol.d.ts +24 -1
  157. package/dist/telemetry/ingest-protocol.d.ts.map +1 -1
  158. package/dist/telemetry/ingest-protocol.js +72 -43
  159. package/dist/telemetry/otel-content.d.ts +31 -0
  160. package/dist/telemetry/otel-content.d.ts.map +1 -0
  161. package/dist/telemetry/otel-content.js +106 -0
  162. package/dist/telemetry/otel-hierarchy.d.ts +57 -0
  163. package/dist/telemetry/otel-hierarchy.d.ts.map +1 -0
  164. package/dist/telemetry/otel-hierarchy.js +155 -0
  165. package/dist/telemetry/otel-normalize.d.ts +15 -1
  166. package/dist/telemetry/otel-normalize.d.ts.map +1 -1
  167. package/dist/telemetry/otel-normalize.js +24 -39
  168. package/dist/telemetry/sinks.d.ts +4 -1
  169. package/dist/telemetry/sinks.d.ts.map +1 -1
  170. package/dist/telemetry/sinks.js +53 -34
  171. package/dist/telemetry/store-migrations.d.ts.map +1 -1
  172. package/dist/telemetry/store-migrations.js +8 -0
  173. package/dist/telemetry/store.d.ts +9 -0
  174. package/dist/telemetry/store.d.ts.map +1 -1
  175. package/dist/telemetry/store.js +10 -0
  176. package/dist/telemetry/uniform-rows.d.ts +43 -0
  177. package/dist/telemetry/uniform-rows.d.ts.map +1 -0
  178. package/dist/telemetry/uniform-rows.js +139 -0
  179. package/dist/types/failures-teaching.d.ts.map +1 -1
  180. package/dist/types/failures-teaching.js +11 -0
  181. package/dist/types/failures.d.ts +1 -1
  182. package/dist/types/failures.d.ts.map +1 -1
  183. package/dist/types/failures.js +2 -0
  184. package/dist/types/provider.d.ts +12 -0
  185. package/dist/types/provider.d.ts.map +1 -1
  186. package/dist/types/route.d.ts +13 -0
  187. package/dist/types/route.d.ts.map +1 -1
  188. package/dist/types/telemetry.d.ts +14 -1
  189. package/dist/types/telemetry.d.ts.map +1 -1
  190. package/docs/agent-skill/SKILL.md +122 -12
  191. package/docs/how-it-fits.md +4 -4
  192. package/docs/instrumentation.md +148 -44
  193. package/docs/llms.txt +143 -13
  194. package/docs/mcp-oracle.md +15 -4
  195. package/docs/quickstart.md +129 -16
  196. package/package.json +4 -2
  197. package/registry/registry.json +456 -0
  198. package/templates/creative-approval.json +81 -0
  199. package/templates/support-conversation.json +82 -0
@@ -10,6 +10,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
10
10
  exports.loadRegistryRows = loadRegistryRows;
11
11
  const node_fs_1 = require("node:fs");
12
12
  const node_path_1 = require("node:path");
13
+ const model_kind_1 = require("./model-kind");
13
14
  function packagedRegistryDir() {
14
15
  // dist/ and src/ both sit one level under the package root.
15
16
  return (0, node_path_1.join)(__dirname, "..", "..", "registry");
@@ -38,7 +39,8 @@ function loadRegistryRows(registryPath) {
38
39
  const dir = registryFile.slice(0, Math.max(registryFile.lastIndexOf("/"), 0));
39
40
  const leaderboard = readJson((0, node_path_1.join)(dir, "leaderboard.json")) ?? [];
40
41
  const effective = new Map(leaderboard.map((r) => [r.model_key, r.effective_usd_per_1k_conformant ?? null]));
41
- return (registry.models ?? []).map((entry) => {
42
+ // ARC-4 rank wall: declared-only generation models never enter selection.
43
+ return (registry.models ?? []).filter(model_kind_1.isRankable).map((entry) => {
42
44
  const [provider] = entry.model_key.split("/");
43
45
  return {
44
46
  key: entry.model_key,
@@ -0,0 +1,32 @@
1
+ /**
2
+ * ARC-4 — the registry half of unit pricing: a DECLARED-ONLY generation entry's
3
+ * `pricing_v2.modality` unit rates, read from the packaged registry.json. Only
4
+ * a non-`llm` entry (model-kind.ts) whose modality carries `provenance` (source
5
+ * + as_of) answers; anything else is "no registry price" and the caller falls
6
+ * through to the vendored pricing map (run/cost.ts `estimateUnitCostUsd`).
7
+ */
8
+ import { type GenerationKind } from "./model-kind";
9
+ import type { ModalityRates } from "./pricing-shape";
10
+ export interface RegistryUnitRates {
11
+ readonly modelKey: string;
12
+ readonly kind: GenerationKind;
13
+ readonly modality: ModalityRates;
14
+ }
15
+ interface RegistryEntryShape {
16
+ readonly model_key?: unknown;
17
+ readonly kind?: unknown;
18
+ readonly declared?: {
19
+ readonly pricing_v2?: {
20
+ readonly modality?: ModalityRates | null;
21
+ } | null;
22
+ } | null;
23
+ }
24
+ /** Build the lookup from registry entries (exported for tests and the registry
25
+ * drift test). */
26
+ export declare function unitRatesIndex(models: readonly RegistryEntryShape[]): Map<string, RegistryUnitRates>;
27
+ /** The registry's unit rates for `provider/model`, or null. */
28
+ export declare function getRegistryUnitRates(provider: string, model: string): RegistryUnitRates | null;
29
+ /** Test-only: replace (or with null, reset) the loaded registry index. */
30
+ export declare function setRegistryUnitRatesForTest(models: readonly RegistryEntryShape[] | null): void;
31
+ export {};
32
+ //# sourceMappingURL=unit-pricing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unit-pricing.d.ts","sourceRoot":"","sources":["../../src/registry/unit-pricing.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,EAAe,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;CAClC;AAED,UAAU,kBAAkB;IAC1B,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,QAAQ,CAAC,EAAE;QAAE,QAAQ,CAAC,UAAU,CAAC,EAAE;YAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,aAAa,GAAG,IAAI,CAAA;SAAE,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;CAC1G;AAcD;kBACkB;AAClB,wBAAgB,cAAc,CAAC,MAAM,EAAE,SAAS,kBAAkB,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CASpG;AAkBD,+DAA+D;AAC/D,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI,CAE9F;AAED,0EAA0E;AAC1E,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,SAAS,kBAAkB,EAAE,GAAG,IAAI,GAAG,IAAI,CAE9F"}
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ /**
3
+ * ARC-4 — the registry half of unit pricing: a DECLARED-ONLY generation entry's
4
+ * `pricing_v2.modality` unit rates, read from the packaged registry.json. Only
5
+ * a non-`llm` entry (model-kind.ts) whose modality carries `provenance` (source
6
+ * + as_of) answers; anything else is "no registry price" and the caller falls
7
+ * through to the vendored pricing map (run/cost.ts `estimateUnitCostUsd`).
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.unitRatesIndex = unitRatesIndex;
11
+ exports.getRegistryUnitRates = getRegistryUnitRates;
12
+ exports.setRegistryUnitRatesForTest = setRegistryUnitRatesForTest;
13
+ const node_fs_1 = require("node:fs");
14
+ const node_path_1 = require("node:path");
15
+ const model_kind_1 = require("./model-kind");
16
+ let cached = null;
17
+ function packagedRegistryPath() {
18
+ // dist/ and src/ both sit one level under the package root.
19
+ return (0, node_path_1.join)(__dirname, "..", "..", "registry", "registry.json");
20
+ }
21
+ function hasProvenance(m) {
22
+ const p = m?.provenance;
23
+ return p != null && typeof p.source === "string" && p.source !== "" && typeof p.as_of === "string" && p.as_of !== "";
24
+ }
25
+ /** Build the lookup from registry entries (exported for tests and the registry
26
+ * drift test). */
27
+ function unitRatesIndex(models) {
28
+ const out = new Map();
29
+ for (const e of models) {
30
+ if (typeof e.model_key !== "string" || !(0, model_kind_1.isModelKind)(e.kind) || e.kind === "llm")
31
+ continue;
32
+ const modality = e.declared?.pricing_v2?.modality;
33
+ if (!hasProvenance(modality))
34
+ continue;
35
+ out.set(e.model_key, { modelKey: e.model_key, kind: e.kind, modality });
36
+ }
37
+ return out;
38
+ }
39
+ function load() {
40
+ if (cached === null) {
41
+ const path = packagedRegistryPath();
42
+ let models = [];
43
+ if ((0, node_fs_1.existsSync)(path)) {
44
+ try {
45
+ models = (JSON.parse((0, node_fs_1.readFileSync)(path, "utf8")).models ?? []);
46
+ }
47
+ catch {
48
+ models = []; // an unreadable registry is "no registry price", never a throw
49
+ }
50
+ }
51
+ cached = unitRatesIndex(models);
52
+ }
53
+ return cached;
54
+ }
55
+ /** The registry's unit rates for `provider/model`, or null. */
56
+ function getRegistryUnitRates(provider, model) {
57
+ return load().get(`${provider}/${model}`) ?? null;
58
+ }
59
+ /** Test-only: replace (or with null, reset) the loaded registry index. */
60
+ function setRegistryUnitRatesForTest(models) {
61
+ cached = models === null ? null : unitRatesIndex(models);
62
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Route INPUT contract at load — ARC-β messages lane (builder-prompt-02 §1.3).
3
+ * Carved out of routes/loader.ts (near the 700-LOC cap), like output-loader.ts.
4
+ *
5
+ * YAML forms accepted for `input:`:
6
+ * (absent) → variables (the default; byte-identical)
7
+ * input: variables → variables (explicit; identical to absent)
8
+ * input: messages → a chat / tool-loop route
9
+ * input: { kind: messages } → same
10
+ * input: { kind: variables } → variables
11
+ *
12
+ * The parsed result OMITS `inputKind` for variables so an existing route's
13
+ * bundle (and its `bundle_sha`) is unchanged; only `messages` is ever carried.
14
+ *
15
+ * Fail-closed pairing: `repair:` re-asks without the conversation (ruling M1);
16
+ * `mask:` and `screen:` operate on the rendered user slot
17
+ * and the declared untrusted variables — they do not yet see caller history.
18
+ * Rather than serve a conversation the guard cannot read, a messages route that
19
+ * declares either is a LOAD error that says so.
20
+ */
21
+ export declare const INPUT_KINDS: ReadonlySet<string>;
22
+ export interface ParsedInputBlock {
23
+ /** Present ONLY for `messages` (variables ⇒ omitted ⇒ byte-identical bundle). */
24
+ readonly inputKind?: "messages";
25
+ }
26
+ export interface InputBlockContext {
27
+ readonly maskDeclared: boolean;
28
+ readonly screenDeclared: boolean;
29
+ /** A `repair:` rung on the route or any variant (architect ruling M1). */
30
+ readonly repairDeclared: boolean;
31
+ }
32
+ /** The teaching problem for a messages route that also declares mask/screen —
33
+ * shared by the loader and the run-time guard (mirror bundles skip the loader). */
34
+ export declare function messagesGuardConflict(ctx: InputBlockContext): string | null;
35
+ /** Parse the bundle's `input:` key. Pushes teaching problems; returns `{}` for
36
+ * variables (absent / explicit) so the bundle spread adds nothing. */
37
+ export declare function parseInputBlock(raw: unknown, ctx: InputBlockContext, problems: string[]): ParsedInputBlock;
38
+ //# sourceMappingURL=input-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-loader.d.ts","sourceRoot":"","sources":["../../src/routes/input-loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,eAAO,MAAM,WAAW,EAAE,WAAW,CAAC,MAAM,CAAsC,CAAC;AAGnF,MAAM,WAAW,gBAAgB;IAC/B,iFAAiF;IACjF,QAAQ,CAAC,SAAS,CAAC,EAAE,UAAU,CAAC;CACjC;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,0EAA0E;IAC1E,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;CAClC;AAMD;mFACmF;AACnF,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,iBAAiB,GAAG,MAAM,GAAG,IAAI,CAkB3E;AAED;sEACsE;AACtE,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,gBAAgB,CAyB1G"}
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ /**
3
+ * Route INPUT contract at load — ARC-β messages lane (builder-prompt-02 §1.3).
4
+ * Carved out of routes/loader.ts (near the 700-LOC cap), like output-loader.ts.
5
+ *
6
+ * YAML forms accepted for `input:`:
7
+ * (absent) → variables (the default; byte-identical)
8
+ * input: variables → variables (explicit; identical to absent)
9
+ * input: messages → a chat / tool-loop route
10
+ * input: { kind: messages } → same
11
+ * input: { kind: variables } → variables
12
+ *
13
+ * The parsed result OMITS `inputKind` for variables so an existing route's
14
+ * bundle (and its `bundle_sha`) is unchanged; only `messages` is ever carried.
15
+ *
16
+ * Fail-closed pairing: `repair:` re-asks without the conversation (ruling M1);
17
+ * `mask:` and `screen:` operate on the rendered user slot
18
+ * and the declared untrusted variables — they do not yet see caller history.
19
+ * Rather than serve a conversation the guard cannot read, a messages route that
20
+ * declares either is a LOAD error that says so.
21
+ */
22
+ Object.defineProperty(exports, "__esModule", { value: true });
23
+ exports.INPUT_KINDS = void 0;
24
+ exports.messagesGuardConflict = messagesGuardConflict;
25
+ exports.parseInputBlock = parseInputBlock;
26
+ exports.INPUT_KINDS = new Set(["variables", "messages"]);
27
+ const INPUT_BLOCK_KEYS = new Set(["kind"]);
28
+ function isRecord(v) {
29
+ return typeof v === "object" && v !== null && !Array.isArray(v);
30
+ }
31
+ /** The teaching problem for a messages route that also declares mask/screen —
32
+ * shared by the loader and the run-time guard (mirror bundles skip the loader). */
33
+ function messagesGuardConflict(ctx) {
34
+ // Architect ruling M1 (2026-10-24): the repair rung re-asks WITHOUT the
35
+ // conversation, so on a messages route it would answer a turn it cannot see —
36
+ // refused rather than served a context-free "corrected" reply.
37
+ if (ctx.repairDeclared) {
38
+ return ("input: messages cannot be combined with repair: — the repair rung re-asks the model without the " +
39
+ "conversation, so a repaired reply would answer a turn it cannot see. Remove repair: (route and variants) " +
40
+ "from this route; an invalid reply is retried from the content_invalid budget instead (see messages-lane.md)");
41
+ }
42
+ const which = [ctx.maskDeclared ? "mask:" : null, ctx.screenDeclared ? "screen:" : null].filter((x) => x !== null);
43
+ if (which.length === 0)
44
+ return null;
45
+ return (`input: messages cannot be combined with ${which.join(" / ")} yet — masking and screening read the rendered ` +
46
+ "user slot and declared variables, not caller history, so the conversation would pass unguarded. Remove " +
47
+ `${which.join(" / ")} from this route, or serve the content as variables (see messages-lane.md)`);
48
+ }
49
+ /** Parse the bundle's `input:` key. Pushes teaching problems; returns `{}` for
50
+ * variables (absent / explicit) so the bundle spread adds nothing. */
51
+ function parseInputBlock(raw, ctx, problems) {
52
+ if (raw === undefined || raw === null)
53
+ return {};
54
+ let kind;
55
+ if (typeof raw === "string") {
56
+ kind = raw;
57
+ }
58
+ else if (isRecord(raw)) {
59
+ for (const key of Object.keys(raw)) {
60
+ if (!INPUT_BLOCK_KEYS.has(key))
61
+ problems.push(`input.${key} is not a known key — the block is {kind: variables|messages}`);
62
+ }
63
+ kind = raw.kind;
64
+ }
65
+ else {
66
+ problems.push(`input must be "variables", "messages", or {kind} — got ${JSON.stringify(raw)}`);
67
+ return {};
68
+ }
69
+ if (typeof kind !== "string" || !exports.INPUT_KINDS.has(kind)) {
70
+ problems.push(`input kind "${String(kind)}" is not one of [variables, messages] — write \`input: { kind: messages }\` for a ` +
71
+ "chat or tool-loop route, or omit it for a variables route (the default)");
72
+ return {};
73
+ }
74
+ if (kind === "variables")
75
+ return {};
76
+ const conflict = messagesGuardConflict(ctx);
77
+ if (conflict !== null)
78
+ problems.push(conflict);
79
+ return { inputKind: "messages" };
80
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/routes/loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,OAAO,KAAK,EAKV,WAAW,EAGZ,MAAM,gBAAgB,CAAC;AAaxB,OAAO,EAAE,sBAAsB,EAAE,kCAAkC,EAAE,8BAA8B,EAAE,MAAM,mBAAmB,CAAC;AAE/H;;;;;GAKG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;gBAEzB,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;KAAO;CAOxF;AA+BD,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAAC;IAChC,IAAI,IAAI,SAAS,WAAW,EAAE,CAAC;CAChC;AA2aD;;;;;;;GAOG;AACH;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,YAAY,CAItF;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,GAAG,YAAY,CAyB1F;AAED;;yBAEyB;AACzB,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,EAAE,CA6CtE;AAED,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,CA2C1D"}
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/routes/loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,OAAO,KAAK,EAKV,WAAW,EAGZ,MAAM,gBAAgB,CAAC;AAcxB,OAAO,EAAE,sBAAsB,EAAE,kCAAkC,EAAE,8BAA8B,EAAE,MAAM,mBAAmB,CAAC;AAE/H;;;;;GAKG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;gBAEzB,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;KAAO;CAOxF;AA+BD,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAAC;IAChC,IAAI,IAAI,SAAS,WAAW,EAAE,CAAC;CAChC;AA6aD;;;;;;;GAOG;AACH;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,YAAY,CAItF;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,GAAG,YAAY,CAyB1F;AAED;;yBAEyB;AACzB,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,EAAE,CA6CtE;AAED,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,CA2C1D"}
@@ -24,6 +24,7 @@ const screen_loader_1 = require("./screen-loader");
24
24
  const prompt_loader_1 = require("./prompt-loader"); // issue #5 (R1): `prompt.user` + the prompt block (moved out for the LOC cap)
25
25
  const mask_loader_1 = require("./mask-loader");
26
26
  const objective_loader_1 = require("./objective-loader");
27
+ const input_loader_1 = require("./input-loader");
27
28
  const output_loader_1 = require("./output-loader"); // issue #1: `output: text` (prose) + the schema reader (moved out for the LOC cap)
28
29
  // Re-exported so existing importers of "./loader" keep resolving these advisories
29
30
  // (they live in ./loader-warnings to hold loader.ts under the 700-LOC cap).
@@ -392,6 +393,7 @@ function loadBundleFile(filePath) {
392
393
  // x-trust) — parsed in prompt-loader.ts; both templates are files relative to
393
394
  // the bundle and share one declared-variable list.
394
395
  const { systemTemplate, userTemplate, variables, variableTrust } = (0, prompt_loader_1.parsePromptBlock)(doc.prompt, bundleDir, problems);
396
+ const input = (0, input_loader_1.parseInputBlock)(doc.input, { maskDeclared: mask !== undefined, screenDeclared: screen !== undefined, repairDeclared: repair !== undefined || variants.some((v) => v.repair !== undefined) }, problems); // ARC-β `input: messages` (input-loader.ts)
395
397
  (0, screen_loader_1.pushUndeclaredVariableProblems)(systemTemplate, groundingQuery, variables, problems, userTemplate);
396
398
  if (problems.length > 0) {
397
399
  throw new RouteConfigError("invalid route bundle", { file: filePath, problems });
@@ -443,6 +445,7 @@ function loadBundleFile(filePath) {
443
445
  prefer: Object.freeze(prefer),
444
446
  systemTemplate,
445
447
  ...(userTemplate !== undefined ? { userTemplate } : {}), // issue #5 (R1): present ONLY when declared (absent ⇒ unchanged bundle_sha)
448
+ ...input, // ARC-β inputKind — present ONLY for `input: messages` (variables ⇒ nothing added)
446
449
  variables: Object.freeze(variables),
447
450
  policy,
448
451
  ...(repair !== undefined ? { repair } : {}),
@@ -56,6 +56,8 @@ export interface ResolvedRouteBundle {
56
56
  * `bundle_sha`), so the hosted/mirror lane renders the same user turn and a
57
57
  * cache handle composes there too. */
58
58
  readonly userTemplate?: string;
59
+ /** ARC-β — `input: messages`, carried ONLY when declared (unchanged `bundle_sha` otherwise). */
60
+ readonly inputKind?: "messages";
59
61
  readonly variables: readonly string[];
60
62
  readonly policy: RoutePolicy;
61
63
  readonly repair?: RepairPolicy;
@@ -1 +1 @@
1
- {"version":3,"file":"resolved-bundle.d.ts","sourceRoot":"","sources":["../../src/routes/resolved-bundle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAG7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EACV,aAAa,EACb,UAAU,EACV,YAAY,EACZ,WAAW,EACX,WAAW,EACX,WAAW,EACX,YAAY,EACb,MAAM,gBAAgB,CAAC;AAExB;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,iFAAiF;IACjF,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC;;;+EAG2E;IAC3E,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,UAAU,EAAE,SAAS,aAAa,EAAE,CAAC;IAC9C,QAAQ,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;IACzC,QAAQ,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC;IACvC,4DAA4D;IAC5D,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC;;;0CAGsC;IACtC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,CAAC;IAC3C,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC;iFAC6E;IAC7E,QAAQ,CAAC,iBAAiB,CAAC,EAAE,QAAQ,GAAG,WAAW,CAAC;IACpD;;;;2BAIuB;IACvB,QAAQ,CAAC,aAAa,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;IAC/D;;;;;;;;;;;mBAWe;IACf,QAAQ,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;IACrC;;;;;;;mCAO+B;IAC/B,QAAQ,CAAC,IAAI,CAAC,EAAE,kBAAkB,CAAC;IACnC;;;;;oEAKgE;IAChE,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC;CAC9B;AAED;sEACsE;AACtE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,GAAG,mBAAmB,CA8B3E;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAe1D;AAiBD,mEAAmE;AACnE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,mBAAmB,GAAG,MAAM,CAEvE;AAED;gFACgF;AAChF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,mBAAmB,GAAG,MAAM,CAEtE;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,WAAW,CAoE5D;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,YAAY,CAclE"}
1
+ {"version":3,"file":"resolved-bundle.d.ts","sourceRoot":"","sources":["../../src/routes/resolved-bundle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAG7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EACV,aAAa,EACb,UAAU,EACV,YAAY,EACZ,WAAW,EACX,WAAW,EACX,WAAW,EACX,YAAY,EACb,MAAM,gBAAgB,CAAC;AAExB;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,iFAAiF;IACjF,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC;;;+EAG2E;IAC3E,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,UAAU,EAAE,SAAS,aAAa,EAAE,CAAC;IAC9C,QAAQ,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;IACzC,QAAQ,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC;IACvC,4DAA4D;IAC5D,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC;;;0CAGsC;IACtC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,gGAAgG;IAChG,QAAQ,CAAC,SAAS,CAAC,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,CAAC;IAC3C,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC;iFAC6E;IAC7E,QAAQ,CAAC,iBAAiB,CAAC,EAAE,QAAQ,GAAG,WAAW,CAAC;IACpD;;;;2BAIuB;IACvB,QAAQ,CAAC,aAAa,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;IAC/D;;;;;;;;;;;mBAWe;IACf,QAAQ,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;IACrC;;;;;;;mCAO+B;IAC/B,QAAQ,CAAC,IAAI,CAAC,EAAE,kBAAkB,CAAC;IACnC;;;;;oEAKgE;IAChE,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC;CAC9B;AAED;sEACsE;AACtE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,GAAG,mBAAmB,CA+B3E;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAe1D;AAiBD,mEAAmE;AACnE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,mBAAmB,GAAG,MAAM,CAEvE;AAED;gFACgF;AAChF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,mBAAmB,GAAG,MAAM,CAEtE;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,WAAW,CAsE5D;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,YAAY,CAclE"}
@@ -51,6 +51,7 @@ function resolveRouteBundle(bundle) {
51
51
  prefer: bundle.prefer,
52
52
  systemTemplate: bundle.systemTemplate,
53
53
  ...(bundle.userTemplate !== undefined ? { userTemplate: bundle.userTemplate } : {}), // issue #5 (R1)
54
+ ...(bundle.inputKind === "messages" ? { inputKind: "messages" } : {}), // ARC-β
54
55
  variables: bundle.variables,
55
56
  policy: bundle.policy,
56
57
  ...(bundle.repair !== undefined ? { repair: bundle.repair } : {}),
@@ -174,6 +175,8 @@ function bundleFromResolved(raw) {
174
175
  // Issue #5 (R1): a mirrored `prompt.user` rebuilds as the user turn; anything
175
176
  // but a non-empty string ⇒ absent ⇒ the fixed trigger (byte-identical).
176
177
  ...(typeof b.userTemplate === "string" && b.userTemplate !== "" ? { userTemplate: b.userTemplate } : {}),
178
+ // ARC-β: only the literal "messages" rebuilds a messages route (anything else ⇒ variables).
179
+ ...(b.inputKind === "messages" ? { inputKind: "messages" } : {}),
177
180
  variables: Object.freeze([...(b.variables ?? [])]),
178
181
  policy: b.policy,
179
182
  ...(b.repair !== undefined ? { repair: b.repair } : {}),
@@ -20,6 +20,7 @@
20
20
  * WITHOUT a served tier and so prices at base. That is a money path and is
21
21
  * deliberately not changed alongside this; tracked for the next money-path MR.
22
22
  */
23
+ import type { RecordedUnits, UnitKey } from "../telemetry/attempt-meta";
23
24
  import type { ModelPricing } from "../registry/pricing";
24
25
  import type { AdapterUsage, ProviderId, ServiceTier } from "../types/provider";
25
26
  /** The `servedTier` an attempt reports, when the caller has it — optional so
@@ -64,5 +65,32 @@ export declare function costComponents(provider: ProviderId, model: string, usag
64
65
  /** Pre-dispatch upper-bound estimate for the envelope precheck: prompt
65
66
  * length + the full output bound, at real pricing or the conservative rate. */
66
67
  export declare function dispatchEstimateUsd(provider: ProviderId, model: string, promptChars: number, unpricedRatePerTok: number): number;
68
+ /** Where a unit price came from. */
69
+ export type UnitPriceSource = "registry" | "pricing-map";
70
+ export interface UnitCost {
71
+ /** USD for the call's BILLED unit; 0 when unpriced. */
72
+ readonly costUsd: number;
73
+ /** True when the call reported units ModelRig cannot price (never guessed). */
74
+ readonly pricingMissing: boolean;
75
+ /** The unit the price applies to (one per model — the others are recorded,
76
+ * not priced, so a TTS call's seconds never double-bill its characters). */
77
+ readonly billedUnit: UnitKey | null;
78
+ readonly usdPerUnit: number | null;
79
+ readonly source: UnitPriceSource | null;
80
+ }
81
+ /**
82
+ * ARC-4 — the list-price cost of a call's non-token units. The chain, first
83
+ * hit wins (dev-rule L5 — never guessed, NEVER synthesized from token rates):
84
+ * 1. the registry: a declared generation entry's `pricing_v2.modality` unit
85
+ * rate, which must carry provenance (source + as_of);
86
+ * 2. the vendored LiteLLM pricing map's per-mode unit key;
87
+ * 3. else `pricingMissing: true`, cost 0.
88
+ * Each model bills ONE unit (its kind / mode decides which); other units are
89
+ * recorded on `meta.units` but not priced. A call whose billed unit is absent
90
+ * or zero while it reports other units is `pricingMissing` (we cannot price what
91
+ * it reported). `steps` is never billed. No units (or all zero) ⇒ $0, not
92
+ * missing. Pure apart from the cached registry/map reads.
93
+ */
94
+ export declare function estimateUnitCostUsd(provider: string, model: string, units: RecordedUnits | undefined): UnitCost;
67
95
  export {};
68
96
  //# sourceMappingURL=cost.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cost.d.ts","sourceRoot":"","sources":["../../src/run/cost.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGxD,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAS/E;uEACuE;AACvE,KAAK,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC;AAE3D;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,UAAU,EACpB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,WAAW,GAAG,SAAS,GAClC,YAAY,GAAG,IAAI,CAiBrB;AAED,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAC1C,eAAO,MAAM,0BAA0B,QAAS,CAAC;AAEjD;;yEAEyE;AACzE,eAAO,MAAM,kCAAkC,MAAM,CAAC;AAEtD,MAAM,WAAW,WAAW;IAC1B,kEAAkE;IAClE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,uEAAuE;IACvE,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;CAClC;AAED,wBAAgB,WAAW,CACzB,QAAQ,EAAE,UAAU,EACpB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,YAAY,EACnB,kBAAkB,EAAE,MAAM,GACzB,WAAW,CAoBb;AAED;;;;;4EAK4E;AAC5E,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,UAAU,EACpB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,IAAI,CACT,YAAY,EACZ,UAAU,GAAG,WAAW,GAAG,cAAc,GAAG,kBAAkB,GAAG,oBAAoB,CACtF,GACC,SAAS,GACV;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAmB5F;AAED;+EAC+E;AAC/E,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,UAAU,EACpB,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,EACnB,kBAAkB,EAAE,MAAM,GACzB,MAAM,CAOR"}
1
+ {"version":3,"file":"cost.d.ts","sourceRoot":"","sources":["../../src/run/cost.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AACxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGxD,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAS/E;uEACuE;AACvE,KAAK,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC;AAE3D;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,UAAU,EACpB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,WAAW,GAAG,SAAS,GAClC,YAAY,GAAG,IAAI,CAiBrB;AAED,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAC1C,eAAO,MAAM,0BAA0B,QAAS,CAAC;AAEjD;;yEAEyE;AACzE,eAAO,MAAM,kCAAkC,MAAM,CAAC;AAEtD,MAAM,WAAW,WAAW;IAC1B,kEAAkE;IAClE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,uEAAuE;IACvE,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;CAClC;AAED,wBAAgB,WAAW,CACzB,QAAQ,EAAE,UAAU,EACpB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,YAAY,EACnB,kBAAkB,EAAE,MAAM,GACzB,WAAW,CAoBb;AAED;;;;;4EAK4E;AAC5E,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,UAAU,EACpB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,IAAI,CACT,YAAY,EACZ,UAAU,GAAG,WAAW,GAAG,cAAc,GAAG,kBAAkB,GAAG,oBAAoB,CACtF,GACC,SAAS,GACV;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAmB5F;AAED;+EAC+E;AAC/E,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,UAAU,EACpB,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,EACnB,kBAAkB,EAAE,MAAM,GACzB,MAAM,CAOR;AAID,oCAAoC;AACpC,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,aAAa,CAAC;AAEzD,MAAM,WAAW,QAAQ;IACvB,uDAAuD;IACvD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,+EAA+E;IAC/E,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC;gFAC4E;IAC5E,QAAQ,CAAC,UAAU,EAAE,OAAO,GAAG,IAAI,CAAC;IACpC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,CAAC;CACzC;AAiDD;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,SAAS,GAAG,QAAQ,CAc/G"}
package/dist/run/cost.js CHANGED
@@ -27,7 +27,9 @@ exports.pricingForServedTier = pricingForServedTier;
27
27
  exports.attemptCost = attemptCost;
28
28
  exports.costComponents = costComponents;
29
29
  exports.dispatchEstimateUsd = dispatchEstimateUsd;
30
+ exports.estimateUnitCostUsd = estimateUnitCostUsd;
30
31
  const pricing_1 = require("../registry/pricing");
32
+ const unit_pricing_1 = require("../registry/unit-pricing");
31
33
  const pricing_shape_1 = require("../registry/pricing-shape");
32
34
  /** The served tiers that carry their own published rates (issue #2). `standard`
33
35
  * is `base` by definition; an unlisted tier bills at base (fail-closed, L5). */
@@ -121,3 +123,75 @@ function dispatchEstimateUsd(provider, model, promptChars, unpricedRatePerTok) {
121
123
  }
122
124
  return (0, pricing_1.estimateCostUsd)(pricing, promptTokens, exports.ESTIMATE_MAX_OUTPUT_TOKENS, 0);
123
125
  }
126
+ /** The registry profile of a declared generation model: its kind names the
127
+ * billed unit; the rate is the matching `pricing_v2.modality` field. */
128
+ function registryProfile(provider, model) {
129
+ const r = (0, unit_pricing_1.getRegistryUnitRates)(provider, model);
130
+ if (r === null)
131
+ return null;
132
+ const m = r.modality;
133
+ switch (r.kind) {
134
+ case "image_gen":
135
+ return { billedUnit: "images", usdPerUnit: m.image_per_unit ?? null };
136
+ case "video_gen":
137
+ return { billedUnit: "seconds", usdPerUnit: m.video_per_second ?? null };
138
+ case "tts":
139
+ return m.characters_per_million != null
140
+ ? { billedUnit: "characters", usdPerUnit: m.characters_per_million / 1000000 }
141
+ : { billedUnit: "seconds", usdPerUnit: m.audio_per_second ?? null };
142
+ case "stt":
143
+ return { billedUnit: "seconds", usdPerUnit: m.audio_per_second ?? null };
144
+ }
145
+ }
146
+ /** The vendored pricing map's profile, by LiteLLM mode (pricing.ts
147
+ * `getMapUnitRates` documents which key is the billed unit per mode). */
148
+ function mapProfile(provider, model) {
149
+ const r = (0, pricing_1.getMapUnitRates)(provider, model);
150
+ if (r === null)
151
+ return null;
152
+ switch (r.mode) {
153
+ case "image_generation":
154
+ return { billedUnit: "images", usdPerUnit: r.perImage };
155
+ case "video_generation":
156
+ case "audio_transcription":
157
+ return { billedUnit: "seconds", usdPerUnit: r.perSecond };
158
+ case "audio_speech":
159
+ return r.perCharacter !== null
160
+ ? { billedUnit: "characters", usdPerUnit: r.perCharacter }
161
+ : { billedUnit: "seconds", usdPerUnit: r.perSecond };
162
+ default:
163
+ return null;
164
+ }
165
+ }
166
+ const UNPRICED = { costUsd: 0, pricingMissing: true, billedUnit: null, usdPerUnit: null, source: null };
167
+ /**
168
+ * ARC-4 — the list-price cost of a call's non-token units. The chain, first
169
+ * hit wins (dev-rule L5 — never guessed, NEVER synthesized from token rates):
170
+ * 1. the registry: a declared generation entry's `pricing_v2.modality` unit
171
+ * rate, which must carry provenance (source + as_of);
172
+ * 2. the vendored LiteLLM pricing map's per-mode unit key;
173
+ * 3. else `pricingMissing: true`, cost 0.
174
+ * Each model bills ONE unit (its kind / mode decides which); other units are
175
+ * recorded on `meta.units` but not priced. A call whose billed unit is absent
176
+ * or zero while it reports other units is `pricingMissing` (we cannot price what
177
+ * it reported). `steps` is never billed. No units (or all zero) ⇒ $0, not
178
+ * missing. Pure apart from the cached registry/map reads.
179
+ */
180
+ function estimateUnitCostUsd(provider, model, units) {
181
+ const any = units !== undefined && Object.values(units).some((v) => typeof v === "number" && v > 0);
182
+ if (!any || units === undefined)
183
+ return { costUsd: 0, pricingMissing: false, billedUnit: null, usdPerUnit: null, source: null };
184
+ const candidates = [
185
+ ["registry", registryProfile(provider, model)],
186
+ ["pricing-map", mapProfile(provider, model)],
187
+ ];
188
+ for (const [source, profile] of candidates) {
189
+ if (profile === null || profile.usdPerUnit === null)
190
+ continue;
191
+ const count = units[profile.billedUnit] ?? 0;
192
+ if (count <= 0)
193
+ return { ...UNPRICED, billedUnit: profile.billedUnit, source };
194
+ return { costUsd: count * profile.usdPerUnit, pricingMissing: false, billedUnit: profile.billedUnit, usdPerUnit: profile.usdPerUnit, source };
195
+ }
196
+ return UNPRICED;
197
+ }
@@ -8,7 +8,7 @@
8
8
  * Tool *execution* is never ours (spec §4.4); these helpers normalize the
9
9
  * protocol and surface it — nothing here runs a tool.
10
10
  */
11
- import type { AdapterRequest, AdapterResult, CandidateRef, ProviderAdapter, ServiceTier, ToolDefinition } from "../types/provider";
11
+ import type { AdapterRequest, AdapterResult, CandidateRef, ProviderAdapter, ServiceTier, ToolCall, ToolDefinition } from "../types/provider";
12
12
  import type { RigFailure } from "../types/failures";
13
13
  import type { OutputKind, RouteBundle, RunMeta, RunOptions, RunResult, RunTags } from "../types/route";
14
14
  import type { TelemetryRung, TelemetryStore } from "../types/telemetry";
@@ -53,6 +53,9 @@ export interface AttemptTelemetry {
53
53
  * `summarizeAttemptMeta` with this row's provider/model/usage. Absent ⇒ the
54
54
  * recorder builds a minimal envelope from usage + cost alone (never null-only). */
55
55
  readonly metaInputs?: AttemptMetaSource;
56
+ /** ARC-5: the tool calls the model requested on this attempt (tool-call path
57
+ * only) — hashed by the run-limit repeat detector, never stored. */
58
+ readonly toolCalls?: readonly ToolCall[];
56
59
  /** SDK-owned extra telemetry tags merged onto the row (Q1 quality gate stamps
57
60
  * `quality` / `quality_score` here). Never carries `rung` — the recorder
58
61
  * stamps that last so a caller cannot override it. */
@@ -1 +1 @@
1
- {"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../src/run/dispatch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../src/run/dispatch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EACb,YAAY,EACZ,eAAe,EACf,WAAW,EACX,QAAQ,EACR,cAAc,EACf,MAAM,mBAAmB,CAAC;AAG3B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACvG,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACxE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAKnE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACrE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAsD,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAExG,OAAO,KAAK,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAG3E;oEACoE;AACpE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC;IACjC;wEACoE;IACpE,QAAQ,CAAC,UAAU,EAAE,WAAW,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B;6DACyD;IACzD,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;0BACsB;IACtB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI,CAAC;IACpC,6EAA6E;IAC7E,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,2EAA2E;IAC3E,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAClC;;gEAE4D;IAC5D,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC;IAC9B;;;uFAGmF;IACnF,QAAQ,CAAC,UAAU,CAAC,EAAE,iBAAiB,CAAC;IACxC;wEACoE;IACpE,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,QAAQ,EAAE,CAAC;IACzC;;0DAEsD;IACtD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C;;6EAEyE;IACzE,QAAQ,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC;IAC5B;;;8BAG0B;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC;CACjC;AAED;;;+DAG+D;AAC/D,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACtC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC;;+EAE2E;IAC3E,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;IAC7C,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;CAC5C,GAAG,iBAAiB,CAYpB;AAED;gEACgE;AAChE,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,gBAAgB,KAAK,MAAM,CAAC;AAElE;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAE/E;AAED;;4EAE4E;AAC5E,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,cAAc,EACzB,KAAK,EAAE,WAAW,EAClB,aAAa,EAAE,OAAO,EACtB,aAAa,EAAE,MAAM,GAAG,IAAI,EAC5B,gBAAgB,EAAE,MAAM,EACxB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,eAAe,GACtB,IAAI,CAyCN;AAED;;8EAE8E;AAC9E,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAYvD;AAED;;0CAE0C;AAC1C,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,KAAK,IAAI,CAAC;AAEzE,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC;IACjC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,+EAA+E;IAC/E,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B;;;8EAG0E;IAC1E,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,gBAAgB,EAAE,GAAG,IAAI,CAAC;IAC9D;;oEAEgE;IAChE,QAAQ,CAAC,qBAAqB,CAAC,EAAE,OAAO,CAAC;CAC1C;AAED;uDACuD;AACvD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,mBAAmB,GAAG,cAAc,CAkC9E;AAED;4CAC4C;AAC5C,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,WAAW,EAClB,SAAS,EAAE,YAAY,EACvB,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,MAAM,GACtB,cAAc,CAmBhB;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,eAAe,EACxB,GAAG,EAAE,cAAc,EACnB,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,aAAa,CAAC,CAuBxB;AAED;2EAC2E;AAC3E,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;CAC1B;AAED;;;mDAGmD;AACnD,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,oBAAoB,GAAG,IAAI,CAAC;CAC9C;AAED;;2EAE2E;AAC3E,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,QAAQ,GAAG,SAAS,CAKtF;AAED;;;;;;4BAM4B;AAC5B,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;IAC3C,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC;CACxC;AASD;;;;;;;;;GASG;AACH,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,eAAe,EACxB,KAAK,EAAE,mBAAmB,EAC1B,OAAO,EAAE,eAAe,GAAG,SAAS,EACpC,MAAM,EAAE,SAAS,GAChB,OAAO,CAAC,eAAe,CAAC,CAwF1B;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,aAAa,EAAE;QAAE,EAAE,EAAE,IAAI,CAAA;KAAE,CAAC,CAAC;IACtD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACrD,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC;kDAC8C;IAC9C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,wEAAwE;IACxE,QAAQ,CAAC,UAAU,CAAC,EAAE,iBAAiB,CAAC;IACxC;gFAC4E;IAC5E,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;CAC/C;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,mBAAmB,GAAG,SAAS,CAmD/F"}
@@ -151,6 +151,8 @@ function buildAdapterRequest(parts) {
151
151
  ...(route.policy.sampling !== undefined ? { sampling: route.policy.sampling } : {}),
152
152
  ...(opts.tools !== undefined ? { tools: opts.tools } : {}),
153
153
  ...(opts.toolChoice !== undefined ? { toolChoice: opts.toolChoice } : {}),
154
+ // ARC-β messages lane: the (run-validated) history; absent ⇒ no key ⇒ byte-identical.
155
+ ...(opts.messages !== undefined ? { history: opts.messages } : {}),
154
156
  };
155
157
  }
156
158
  /** Build the repair-attempt AdapterRequest (no tools — repair re-asks for the
@@ -348,6 +350,7 @@ function emitToolCallResult(record, parts) {
348
350
  // dispatch or a serve (its cost still counts).
349
351
  rung: "tool_call",
350
352
  ...(parts.metaInputs !== undefined ? { metaInputs: parts.metaInputs } : {}),
353
+ ...(result.toolCalls !== undefined ? { toolCalls: result.toolCalls } : {}), // ARC-5 repeat-tool detector
351
354
  });
352
355
  return {
353
356
  output: null,
@@ -0,0 +1,88 @@
1
+ /**
2
+ * ARC-5 — run limits: an inline loop and budget guard, per run, in-process.
3
+ *
4
+ * run.start({ pipeline, limits: { maxUsd, maxCalls, maxWallMs, maxRepeatToolCall } })
5
+ * rig.conversation(id, { agent, limits })
6
+ *
7
+ * Every call inside an ambient run passes through the SDK, so the SDK can refuse
8
+ * the NEXT dispatch once a limit is reached — something an observability tool
9
+ * structurally cannot. On breach the dispatch throws a typed
10
+ * {@link RunLimitExceeded} (`failureClass: "limit_exceeded"`, terminal), the
11
+ * run's `RunMeta.failure_reason` becomes `limit:<which>`, and the run ends
12
+ * `failed`. A run that stopped at a limit keeps refusing on that async path.
13
+ *
14
+ * `recordCall` cannot prevent a call it did not dispatch: it ACCUMULATES (cost,
15
+ * call count) and the next `run`/`runRaw` throws. Distinct from envelopes (org /
16
+ * route money budgets, server-side, monthly): limits are per run and immediate.
17
+ *
18
+ * `maxRepeatToolCall: n` trips when the SAME tool name + argument hash is
19
+ * requested n times IN A ROW (a stuck agent loop). Only a SHA-256 of the
20
+ * canonical JSON arguments is kept — never the argument content.
21
+ *
22
+ * Everything here is PURE (state in, state out); run-context.ts holds the state.
23
+ */
24
+ import { RigFailureError } from "../types/failures";
25
+ import type { LimitFailureReason } from "../telemetry/attempt-meta";
26
+ export interface RunLimits {
27
+ /** Stop once the run's accumulated cost reaches this many USD. */
28
+ readonly maxUsd?: number;
29
+ /** Stop once this many calls have been made in the run. */
30
+ readonly maxCalls?: number;
31
+ /** Stop once this many milliseconds have passed since the run started. */
32
+ readonly maxWallMs?: number;
33
+ /** Stop once the same tool + arguments has been requested this many times in a row. */
34
+ readonly maxRepeatToolCall?: number;
35
+ }
36
+ export type LimitName = "max_usd" | "max_calls" | "max_wall_ms" | "max_repeat_tool_call";
37
+ export interface LimitBreach {
38
+ readonly which: LimitName;
39
+ readonly limit: number;
40
+ readonly observed: number;
41
+ }
42
+ /** The accumulated run state the check reads. Hashes only for tool calls. */
43
+ export interface RunLimitState {
44
+ readonly costUsd: number;
45
+ readonly calls: number;
46
+ readonly startedAtMs: number;
47
+ /** `<tool name>:<sha256 of canonical args>` of the last requested tool call. */
48
+ readonly lastToolSig: string | null;
49
+ /** How many times in a row `lastToolSig` was requested. */
50
+ readonly repeatCount: number;
51
+ }
52
+ /** One recorded call as the accumulator sees it. `toolCalls` undefined ⇒ the
53
+ * lane cannot say (a recorded call) — the repeat streak is left untouched; an
54
+ * empty array ⇒ a reply with no tool call, which breaks the streak. */
55
+ export interface LimitCallObservation {
56
+ readonly costUsd?: number | null;
57
+ /** True for a pre-dispatch refusal (no provider call happened) — not counted. */
58
+ readonly notDispatched?: boolean;
59
+ readonly toolCalls?: readonly {
60
+ readonly name: string;
61
+ readonly arguments: string;
62
+ }[];
63
+ }
64
+ export declare function initialLimitState(startedAtMs: number): RunLimitState;
65
+ /** `<name>:<sha256(canonical JSON args)>` — the ONLY form a tool call is kept in. */
66
+ export declare function toolCallSignature(name: string, argsJson: string): string;
67
+ /** Fold one recorded call into the state (pure). */
68
+ export declare function accumulate(state: RunLimitState, call: LimitCallObservation): RunLimitState;
69
+ /** PURE pre-dispatch check: the first limit already reached, or null. Order:
70
+ * money, calls, wall clock, repeat loop. */
71
+ export declare function checkRunLimits(state: RunLimitState, limits: RunLimits, nowMs: number): LimitBreach | null;
72
+ /** `limit:<which>` — the RunMeta.failure_reason a breach writes. */
73
+ export declare function limitFailureReason(which: LimitName): LimitFailureReason;
74
+ /** Validate caller limits (a caller bug throws with the fix). Returns null for
75
+ * an empty / absent object — no limits, no state, byte-identical runs. */
76
+ export declare function validateRunLimits(limits: RunLimits | undefined): RunLimits | null;
77
+ /** The snake_case copy recorded on `RunMeta.limits` (metadata-safe numbers). */
78
+ export declare function limitsForMeta(limits: RunLimits): Readonly<Record<string, number>>;
79
+ /** The typed error a refused dispatch throws. A `RigFailureError` (class
80
+ * `limit_exceeded`, terminal) carrying which limit, its value and the observed one. */
81
+ export declare class RunLimitExceeded extends RigFailureError {
82
+ readonly which: LimitName;
83
+ readonly limit: number;
84
+ readonly observed: number;
85
+ readonly runId: string;
86
+ constructor(breach: LimitBreach, runId: string);
87
+ }
88
+ //# sourceMappingURL=limits.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"limits.d.ts","sourceRoot":"","sources":["../../src/run/limits.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAEpE,MAAM,WAAW,SAAS;IACxB,kEAAkE;IAClE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,0EAA0E;IAC1E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,uFAAuF;IACvF,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CACrC;AAED,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,aAAa,GAAG,sBAAsB,CAAC;AAEzF,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,6EAA6E;AAC7E,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,gFAAgF;IAChF,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,2DAA2D;IAC3D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED;;uEAEuE;AACvE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,iFAAiF;IACjF,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACvF;AAED,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,aAAa,CAEpE;AAaD,qFAAqF;AACrF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQxE;AAED,oDAAoD;AACpD,wBAAgB,UAAU,CAAC,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,oBAAoB,GAAG,aAAa,CAmB1F;AAED;4CAC4C;AAC5C,wBAAgB,cAAc,CAAC,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAezG;AAED,oEAAoE;AACpE,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,SAAS,GAAG,kBAAkB,CAEvE;AAED;0EAC0E;AAC1E,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,IAAI,CAmBjF;AAED,gFAAgF;AAChF,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAOjF;AAED;uFACuF;AACvF,qBAAa,gBAAiB,SAAQ,eAAe;IACnD,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAEX,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM;CAc/C"}