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.
- package/CHANGELOG.md +82 -0
- package/dist/adapters/anthropic.d.ts +4 -4
- package/dist/adapters/anthropic.d.ts.map +1 -1
- package/dist/adapters/anthropic.js +8 -1
- package/dist/adapters/deepseek.d.ts +2 -4
- package/dist/adapters/deepseek.d.ts.map +1 -1
- package/dist/adapters/deepseek.js +9 -5
- package/dist/adapters/gemini.d.ts +4 -1
- package/dist/adapters/gemini.d.ts.map +1 -1
- package/dist/adapters/gemini.js +16 -1
- package/dist/adapters/grok.d.ts +2 -4
- package/dist/adapters/grok.d.ts.map +1 -1
- package/dist/adapters/grok.js +8 -4
- package/dist/adapters/history-mapping.d.ts +126 -0
- package/dist/adapters/history-mapping.d.ts.map +1 -0
- package/dist/adapters/history-mapping.js +230 -0
- package/dist/adapters/openai-compat.d.ts +2 -4
- package/dist/adapters/openai-compat.d.ts.map +1 -1
- package/dist/adapters/openai-compat.js +9 -5
- package/dist/adapters/openai.d.ts +2 -4
- package/dist/adapters/openai.d.ts.map +1 -1
- package/dist/adapters/openai.js +8 -4
- package/dist/adapters/responses-api.d.ts.map +1 -1
- package/dist/adapters/responses-api.js +9 -4
- package/dist/artifacts/artifact.d.ts.map +1 -1
- package/dist/artifacts/artifact.js +79 -0
- package/dist/artifacts/conversation.d.ts +128 -0
- package/dist/artifacts/conversation.d.ts.map +1 -0
- package/dist/artifacts/conversation.js +172 -0
- package/dist/artifacts/index.d.ts +1 -1
- package/dist/artifacts/index.d.ts.map +1 -1
- package/dist/artifacts/media.d.ts +46 -0
- package/dist/artifacts/media.d.ts.map +1 -0
- package/dist/artifacts/media.js +88 -0
- package/dist/artifacts/run-context.d.ts +61 -2
- package/dist/artifacts/run-context.d.ts.map +1 -1
- package/dist/artifacts/run-context.js +183 -12
- package/dist/artifacts/scrub.d.ts +3 -0
- package/dist/artifacts/scrub.d.ts.map +1 -1
- package/dist/bakeoff/engine.d.ts.map +1 -1
- package/dist/bakeoff/engine.js +34 -7
- package/dist/bakeoff/eval-cases.d.ts +5 -0
- package/dist/bakeoff/eval-cases.d.ts.map +1 -1
- package/dist/bakeoff/eval-cases.js +10 -1
- package/dist/bakeoff/replay.d.ts +15 -0
- package/dist/bakeoff/replay.d.ts.map +1 -1
- package/dist/bakeoff/replay.js +19 -1
- package/dist/bakeoff/report.d.ts.map +1 -1
- package/dist/bakeoff/report.js +9 -2
- package/dist/bakeoff/turn-replay.d.ts +93 -0
- package/dist/bakeoff/turn-replay.d.ts.map +1 -0
- package/dist/bakeoff/turn-replay.js +150 -0
- package/dist/bakeoff/types.d.ts +12 -0
- package/dist/bakeoff/types.d.ts.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +1 -0
- package/dist/config.d.ts +18 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +23 -3
- package/dist/doctor-preflight.d.ts.map +1 -1
- package/dist/doctor-preflight.js +6 -1
- package/dist/feedback/grade.d.ts +7 -2
- package/dist/feedback/grade.d.ts.map +1 -1
- package/dist/feedback/grade.js +14 -0
- package/dist/feedback/outcome.d.ts +103 -0
- package/dist/feedback/outcome.d.ts.map +1 -0
- package/dist/feedback/outcome.js +175 -0
- package/dist/gateway/history-bridge.d.ts +32 -0
- package/dist/gateway/history-bridge.d.ts.map +1 -0
- package/dist/gateway/history-bridge.js +64 -0
- package/dist/gateway/serve-client.d.ts.map +1 -1
- package/dist/gateway/serve-client.js +6 -0
- package/dist/index.d.ts +44 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +110 -9
- package/dist/init/init-cli.d.ts.map +1 -1
- package/dist/init/init-cli.js +21 -4
- package/dist/init/observe-cli.js +1 -1
- package/dist/init/observe.d.ts +7 -1
- package/dist/init/observe.d.ts.map +1 -1
- package/dist/init/observe.js +74 -22
- package/dist/init/starter.d.ts +36 -0
- package/dist/init/starter.d.ts.map +1 -0
- package/dist/init/starter.js +85 -0
- package/dist/registry/build.d.ts +4 -0
- package/dist/registry/build.d.ts.map +1 -1
- package/dist/registry/generation-models.d.ts +68 -0
- package/dist/registry/generation-models.d.ts.map +1 -0
- package/dist/registry/generation-models.js +168 -0
- package/dist/registry/model-kind.d.ts +34 -0
- package/dist/registry/model-kind.d.ts.map +1 -0
- package/dist/registry/model-kind.js +40 -0
- package/dist/registry/pricing-shape.d.ts +29 -1
- package/dist/registry/pricing-shape.d.ts.map +1 -1
- package/dist/registry/pricing-shape.js +9 -0
- package/dist/registry/pricing.d.ts +26 -0
- package/dist/registry/pricing.d.ts.map +1 -1
- package/dist/registry/pricing.js +29 -0
- package/dist/registry/rows.d.ts.map +1 -1
- package/dist/registry/rows.js +3 -1
- package/dist/registry/unit-pricing.d.ts +32 -0
- package/dist/registry/unit-pricing.d.ts.map +1 -0
- package/dist/registry/unit-pricing.js +62 -0
- package/dist/routes/input-loader.d.ts +38 -0
- package/dist/routes/input-loader.d.ts.map +1 -0
- package/dist/routes/input-loader.js +80 -0
- package/dist/routes/loader.d.ts.map +1 -1
- package/dist/routes/loader.js +3 -0
- package/dist/routes/resolved-bundle.d.ts +2 -0
- package/dist/routes/resolved-bundle.d.ts.map +1 -1
- package/dist/routes/resolved-bundle.js +3 -0
- package/dist/run/cost.d.ts +28 -0
- package/dist/run/cost.d.ts.map +1 -1
- package/dist/run/cost.js +74 -0
- package/dist/run/dispatch.d.ts +4 -1
- package/dist/run/dispatch.d.ts.map +1 -1
- package/dist/run/dispatch.js +3 -0
- package/dist/run/limits.d.ts +88 -0
- package/dist/run/limits.d.ts.map +1 -0
- package/dist/run/limits.js +155 -0
- package/dist/run/messages.d.ts +199 -0
- package/dist/run/messages.d.ts.map +1 -0
- package/dist/run/messages.js +430 -0
- package/dist/run/raw-finalize.d.ts +5 -2
- package/dist/run/raw-finalize.d.ts.map +1 -1
- package/dist/run/raw-finalize.js +8 -5
- package/dist/run/raw-request.d.ts.map +1 -1
- package/dist/run/raw-request.js +2 -1
- package/dist/run/raw.d.ts +10 -4
- package/dist/run/raw.d.ts.map +1 -1
- package/dist/run/raw.js +11 -3
- package/dist/run/rawonly.d.ts +29 -5
- package/dist/run/rawonly.d.ts.map +1 -1
- package/dist/run/rawonly.js +54 -19
- package/dist/run/record-attempt.d.ts.map +1 -1
- package/dist/run/record-attempt.js +16 -6
- package/dist/run/record-call.d.ts +13 -2
- package/dist/run/record-call.d.ts.map +1 -1
- package/dist/run/record-call.js +50 -7
- package/dist/run/run.d.ts.map +1 -1
- package/dist/run/run.js +12 -8
- package/dist/telemetry/attempt-meta.d.ts +49 -1
- package/dist/telemetry/attempt-meta.d.ts.map +1 -1
- package/dist/telemetry/attempt-meta.js +45 -1
- package/dist/telemetry/exporter.d.ts.map +1 -1
- package/dist/telemetry/exporter.js +2 -1
- package/dist/telemetry/grade-mappers.d.ts +1 -1
- package/dist/telemetry/grade-mappers.d.ts.map +1 -1
- package/dist/telemetry/grade-mappers.js +7 -1
- package/dist/telemetry/grade-task.d.ts +49 -0
- package/dist/telemetry/grade-task.d.ts.map +1 -0
- package/dist/telemetry/grade-task.js +85 -0
- package/dist/telemetry/grades-sql.d.ts +16 -1
- package/dist/telemetry/grades-sql.d.ts.map +1 -1
- package/dist/telemetry/grades-sql.js +64 -4
- package/dist/telemetry/ingest-protocol.d.ts +24 -1
- package/dist/telemetry/ingest-protocol.d.ts.map +1 -1
- package/dist/telemetry/ingest-protocol.js +72 -43
- package/dist/telemetry/otel-content.d.ts +31 -0
- package/dist/telemetry/otel-content.d.ts.map +1 -0
- package/dist/telemetry/otel-content.js +106 -0
- package/dist/telemetry/otel-hierarchy.d.ts +57 -0
- package/dist/telemetry/otel-hierarchy.d.ts.map +1 -0
- package/dist/telemetry/otel-hierarchy.js +155 -0
- package/dist/telemetry/otel-normalize.d.ts +15 -1
- package/dist/telemetry/otel-normalize.d.ts.map +1 -1
- package/dist/telemetry/otel-normalize.js +24 -39
- package/dist/telemetry/sinks.d.ts +4 -1
- package/dist/telemetry/sinks.d.ts.map +1 -1
- package/dist/telemetry/sinks.js +53 -34
- package/dist/telemetry/store-migrations.d.ts.map +1 -1
- package/dist/telemetry/store-migrations.js +8 -0
- package/dist/telemetry/store.d.ts +9 -0
- package/dist/telemetry/store.d.ts.map +1 -1
- package/dist/telemetry/store.js +10 -0
- package/dist/telemetry/uniform-rows.d.ts +43 -0
- package/dist/telemetry/uniform-rows.d.ts.map +1 -0
- package/dist/telemetry/uniform-rows.js +139 -0
- package/dist/types/failures-teaching.d.ts.map +1 -1
- package/dist/types/failures-teaching.js +11 -0
- package/dist/types/failures.d.ts +1 -1
- package/dist/types/failures.d.ts.map +1 -1
- package/dist/types/failures.js +2 -0
- package/dist/types/provider.d.ts +12 -0
- package/dist/types/provider.d.ts.map +1 -1
- package/dist/types/route.d.ts +13 -0
- package/dist/types/route.d.ts.map +1 -1
- package/dist/types/telemetry.d.ts +14 -1
- package/dist/types/telemetry.d.ts.map +1 -1
- package/docs/agent-skill/SKILL.md +122 -12
- package/docs/how-it-fits.md +4 -4
- package/docs/instrumentation.md +148 -44
- package/docs/llms.txt +143 -13
- package/docs/mcp-oracle.md +15 -4
- package/docs/quickstart.md +129 -16
- package/package.json +4 -2
- package/registry/registry.json +456 -0
- package/templates/creative-approval.json +81 -0
- package/templates/support-conversation.json +82 -0
package/dist/registry/rows.js
CHANGED
|
@@ -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
|
-
|
|
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;
|
|
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"}
|
package/dist/routes/loader.js
CHANGED
|
@@ -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,
|
|
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 } : {}),
|
package/dist/run/cost.d.ts
CHANGED
|
@@ -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
|
package/dist/run/cost.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cost.d.ts","sourceRoot":"","sources":["../../src/run/cost.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;
|
|
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
|
+
}
|
package/dist/run/dispatch.d.ts
CHANGED
|
@@ -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"}
|
package/dist/run/dispatch.js
CHANGED
|
@@ -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"}
|