modelrig 0.9.0 → 0.11.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 +227 -0
- package/README.md +51 -27
- package/data/PROVENANCE.md +14 -0
- package/data/pricing-map.json +26 -0
- package/dist/adapters/attempt-meta-map.d.ts +8 -1
- package/dist/adapters/attempt-meta-map.d.ts.map +1 -1
- package/dist/adapters/attempt-meta-map.js +4 -0
- package/dist/adapters/build-adapters.js +2 -2
- package/dist/adapters/gemini.d.ts +28 -1
- package/dist/adapters/gemini.d.ts.map +1 -1
- package/dist/adapters/gemini.js +38 -9
- package/dist/adapters/grok.d.ts.map +1 -1
- package/dist/adapters/grok.js +53 -4
- package/dist/adapters/openai-compat.d.ts +8 -2
- package/dist/adapters/openai-compat.d.ts.map +1 -1
- package/dist/adapters/openai-compat.js +8 -1
- package/dist/adapters/openai-stream.d.ts +10 -2
- package/dist/adapters/openai-stream.d.ts.map +1 -1
- package/dist/adapters/openai-stream.js +5 -1
- package/dist/adapters/openai.d.ts +10 -1
- package/dist/adapters/openai.d.ts.map +1 -1
- package/dist/adapters/openai.js +57 -7
- package/dist/adapters/responses-api.d.ts +61 -0
- package/dist/adapters/responses-api.d.ts.map +1 -0
- package/dist/adapters/responses-api.js +124 -0
- package/dist/artifacts/artifact.d.ts +20 -0
- package/dist/artifacts/artifact.d.ts.map +1 -1
- package/dist/artifacts/artifact.js +207 -171
- package/dist/artifacts/index.d.ts +3 -1
- package/dist/artifacts/index.d.ts.map +1 -1
- package/dist/artifacts/index.js +8 -1
- package/dist/bakeoff/groundedness.d.ts +58 -0
- package/dist/bakeoff/groundedness.d.ts.map +1 -0
- package/dist/bakeoff/groundedness.js +165 -0
- package/dist/bakeoff/quality.d.ts +14 -1
- package/dist/bakeoff/quality.d.ts.map +1 -1
- package/dist/bakeoff/quality.js +10 -0
- package/dist/bakeoff/replay.d.ts.map +1 -1
- package/dist/bakeoff/replay.js +4 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +8 -0
- package/dist/config.d.ts +31 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +23 -0
- package/dist/doctor-cli.d.ts +7 -0
- package/dist/doctor-cli.d.ts.map +1 -0
- package/dist/doctor-cli.js +68 -0
- package/dist/doctor-preflight.d.ts +64 -0
- package/dist/doctor-preflight.d.ts.map +1 -0
- package/dist/doctor-preflight.js +167 -0
- package/dist/feedback/coverage.d.ts.map +1 -1
- package/dist/feedback/coverage.js +9 -2
- package/dist/feedback/grade.d.ts +8 -1
- package/dist/feedback/grade.d.ts.map +1 -1
- package/dist/feedback/grade.js +4 -0
- package/dist/gateway/http-protocol.d.ts +19 -0
- package/dist/gateway/http-protocol.d.ts.map +1 -1
- package/dist/gateway/serve-client.d.ts +99 -0
- package/dist/gateway/serve-client.d.ts.map +1 -0
- package/dist/gateway/serve-client.js +360 -0
- package/dist/index.d.ts +31 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +71 -8
- package/dist/prompts/manifest.d.ts +128 -0
- package/dist/prompts/manifest.d.ts.map +1 -0
- package/dist/prompts/manifest.js +214 -0
- package/dist/prompts/prompt-fetch.d.ts +84 -0
- package/dist/prompts/prompt-fetch.d.ts.map +1 -0
- package/dist/prompts/prompt-fetch.js +120 -0
- package/dist/prompts/prompt-resolve.d.ts +76 -0
- package/dist/prompts/prompt-resolve.d.ts.map +1 -0
- package/dist/prompts/prompt-resolve.js +93 -0
- package/dist/prompts/slot-resolver.d.ts +91 -0
- package/dist/prompts/slot-resolver.d.ts.map +1 -0
- package/dist/prompts/slot-resolver.js +135 -0
- package/dist/prompts/tools-register.d.ts +60 -0
- package/dist/prompts/tools-register.d.ts.map +1 -0
- package/dist/prompts/tools-register.js +48 -0
- package/dist/prompts/version-hash.d.ts +29 -0
- package/dist/prompts/version-hash.d.ts.map +1 -0
- package/dist/prompts/version-hash.js +54 -0
- package/dist/prompts-export-cli.d.ts +21 -0
- package/dist/prompts-export-cli.d.ts.map +1 -0
- package/dist/prompts-export-cli.js +130 -0
- package/dist/registry/cache-policy.d.ts.map +1 -1
- package/dist/registry/cache-policy.js +22 -0
- package/dist/registry/pricing-shape.d.ts +38 -8
- package/dist/registry/pricing-shape.d.ts.map +1 -1
- package/dist/registry/pricing-shape.js +40 -12
- package/dist/registry/pricing.d.ts +6 -5
- package/dist/registry/pricing.d.ts.map +1 -1
- package/dist/registry/pricing.js +9 -5
- package/dist/routes/destination-loader.d.ts +16 -0
- package/dist/routes/destination-loader.d.ts.map +1 -0
- package/dist/routes/destination-loader.js +29 -0
- package/dist/routes/draft.d.ts +7 -0
- package/dist/routes/draft.d.ts.map +1 -1
- package/dist/routes/draft.js +12 -0
- package/dist/routes/loader.d.ts.map +1 -1
- package/dist/routes/loader.js +27 -54
- package/dist/routes/output-loader.d.ts +42 -0
- package/dist/routes/output-loader.d.ts.map +1 -0
- package/dist/routes/output-loader.js +112 -0
- package/dist/routes/prompt-loader.d.ts +49 -0
- package/dist/routes/prompt-loader.d.ts.map +1 -0
- package/dist/routes/prompt-loader.js +113 -0
- package/dist/routes/resolved-bundle.d.ts +19 -0
- package/dist/routes/resolved-bundle.d.ts.map +1 -1
- package/dist/routes/resolved-bundle.js +24 -0
- package/dist/routes/screen-loader.d.ts +1 -1
- package/dist/routes/screen-loader.d.ts.map +1 -1
- package/dist/routes/screen-loader.js +8 -1
- package/dist/run/accept.d.ts +3 -0
- package/dist/run/accept.d.ts.map +1 -1
- package/dist/run/accept.js +1 -0
- package/dist/run/cost.d.ts +31 -2
- package/dist/run/cost.d.ts.map +1 -1
- package/dist/run/cost.js +57 -2
- package/dist/run/destination.d.ts +39 -0
- package/dist/run/destination.d.ts.map +1 -0
- package/dist/run/destination.js +45 -0
- package/dist/run/dispatch.d.ts +25 -3
- package/dist/run/dispatch.d.ts.map +1 -1
- package/dist/run/dispatch.js +26 -4
- package/dist/run/raw-defaults.d.ts.map +1 -1
- package/dist/run/raw-defaults.js +6 -1
- package/dist/run/raw-finalize.d.ts +96 -0
- package/dist/run/raw-finalize.d.ts.map +1 -0
- package/dist/run/raw-finalize.js +283 -0
- package/dist/run/raw-knobs.d.ts +36 -0
- package/dist/run/raw-knobs.d.ts.map +1 -0
- package/dist/run/raw-knobs.js +99 -0
- package/dist/run/raw-request.d.ts +24 -0
- package/dist/run/raw-request.d.ts.map +1 -0
- package/dist/run/raw-request.js +69 -0
- package/dist/run/raw-schema.d.ts +76 -0
- package/dist/run/raw-schema.d.ts.map +1 -0
- package/dist/run/raw-schema.js +166 -0
- package/dist/run/raw-search-cost.d.ts +49 -0
- package/dist/run/raw-search-cost.d.ts.map +1 -0
- package/dist/run/raw-search-cost.js +79 -0
- package/dist/run/raw-support.d.ts +64 -6
- package/dist/run/raw-support.d.ts.map +1 -1
- package/dist/run/raw-support.js +84 -11
- package/dist/run/raw.d.ts +25 -26
- package/dist/run/raw.d.ts.map +1 -1
- package/dist/run/raw.js +30 -351
- package/dist/run/record-attempt.d.ts +8 -0
- package/dist/run/record-attempt.d.ts.map +1 -1
- package/dist/run/record-attempt.js +26 -12
- package/dist/run/record-call.d.ts +104 -0
- package/dist/run/record-call.d.ts.map +1 -0
- package/dist/run/record-call.js +277 -0
- package/dist/run/repair-attempt.d.ts +68 -0
- package/dist/run/repair-attempt.d.ts.map +1 -0
- package/dist/run/repair-attempt.js +180 -0
- package/dist/run/resolve-destination.d.ts +49 -0
- package/dist/run/resolve-destination.d.ts.map +1 -0
- package/dist/run/resolve-destination.js +76 -0
- package/dist/run/routing-docs.d.ts.map +1 -1
- package/dist/run/routing-docs.js +9 -4
- package/dist/run/run.d.ts +30 -1
- package/dist/run/run.d.ts.map +1 -1
- package/dist/run/run.js +75 -148
- package/dist/run/telemetry-row.d.ts +92 -0
- package/dist/run/telemetry-row.d.ts.map +1 -0
- package/dist/run/telemetry-row.js +81 -0
- package/dist/run/validate.d.ts +12 -1
- package/dist/run/validate.d.ts.map +1 -1
- package/dist/run/validate.js +31 -0
- package/dist/run/web-search-pricing.d.ts +43 -0
- package/dist/run/web-search-pricing.d.ts.map +1 -0
- package/dist/run/web-search-pricing.js +56 -0
- package/dist/settings/grading-guide.d.ts +27 -1
- package/dist/settings/grading-guide.d.ts.map +1 -1
- package/dist/status.d.ts +6 -0
- package/dist/status.d.ts.map +1 -1
- package/dist/status.js +4 -1
- package/dist/telemetry/artifact-store.d.ts.map +1 -1
- package/dist/telemetry/artifact-store.js +11 -0
- package/dist/telemetry/attempt-meta.d.ts +66 -1
- package/dist/telemetry/attempt-meta.d.ts.map +1 -1
- package/dist/telemetry/attempt-meta.js +27 -1
- package/dist/telemetry/exporter-setup.d.ts +2 -0
- package/dist/telemetry/exporter-setup.d.ts.map +1 -1
- package/dist/telemetry/exporter-setup.js +6 -1
- package/dist/telemetry/grade-mappers.d.ts +5 -2
- package/dist/telemetry/grade-mappers.d.ts.map +1 -1
- package/dist/telemetry/grade-mappers.js +8 -2
- package/dist/telemetry/grades-sql.d.ts +4 -1
- package/dist/telemetry/grades-sql.d.ts.map +1 -1
- package/dist/telemetry/grades-sql.js +26 -3
- package/dist/telemetry/ingest-protocol.d.ts +26 -2
- package/dist/telemetry/ingest-protocol.d.ts.map +1 -1
- package/dist/telemetry/ingest-protocol.js +32 -29
- package/dist/telemetry/lanes.d.ts +31 -0
- package/dist/telemetry/lanes.d.ts.map +1 -0
- package/dist/telemetry/lanes.js +41 -0
- package/dist/telemetry/org-identity.d.ts +47 -0
- package/dist/telemetry/org-identity.d.ts.map +1 -0
- package/dist/telemetry/org-identity.js +100 -0
- package/dist/telemetry/route-registration.d.ts +48 -0
- package/dist/telemetry/route-registration.d.ts.map +1 -0
- package/dist/telemetry/route-registration.js +77 -0
- package/dist/telemetry/sinks.d.ts +10 -1
- package/dist/telemetry/sinks.d.ts.map +1 -1
- package/dist/telemetry/sinks.js +52 -6
- package/dist/telemetry/store-migrations.d.ts.map +1 -1
- package/dist/telemetry/store-migrations.js +13 -0
- package/dist/tenancy/api-key-format.d.ts +16 -1
- package/dist/tenancy/api-key-format.d.ts.map +1 -1
- package/dist/tenancy/api-key-format.js +17 -0
- package/dist/types/provider.d.ts +20 -3
- package/dist/types/provider.d.ts.map +1 -1
- package/dist/types/provider.js +1 -0
- package/dist/types/route.d.ts +76 -0
- package/dist/types/route.d.ts.map +1 -1
- package/dist/types/telemetry.d.ts +30 -2
- package/dist/types/telemetry.d.ts.map +1 -1
- package/docs/agent-skill/SKILL.md +75 -5
- package/docs/instrumentation.md +98 -36
- package/docs/llms.txt +96 -16
- package/docs/managed-serving.md +150 -0
- package/docs/mcp-oracle.md +75 -2
- package/docs/migration-playbook.md +5 -4
- package/docs/quickstart.md +169 -83
- package/package.json +3 -2
- package/registry/registry.json +82 -0
- package/dist/feedback/feedback.d.ts +0 -35
- package/dist/feedback/feedback.d.ts.map +0 -1
- package/dist/feedback/feedback.js +0 -39
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PSR-2 — the content-hash id for a prompt version (`template_sha`).
|
|
3
|
+
*
|
|
4
|
+
* A prompt version is identified by the sha256 of its `template` + `manifest`
|
|
5
|
+
* (spec §2, the Humanloop content-hash pattern: identical content ⇒ no
|
|
6
|
+
* duplicate row). This is the ONE definition of that hash, used by:
|
|
7
|
+
* • the ingest + create-version writer (dedupe: an identical re-ingest resolves
|
|
8
|
+
* to the existing row rather than appending a byte-identical version), and
|
|
9
|
+
* • the served-projection check (does routes.bundle carry THIS version? — the
|
|
10
|
+
* "served this call" marker compares template_sha, PSR-2b).
|
|
11
|
+
*
|
|
12
|
+
* The manifest is CANONICALIZED first (object keys sorted recursively, array
|
|
13
|
+
* order preserved) so a semantically-identical manifest always hashes the same
|
|
14
|
+
* regardless of key order in the source artifact — the same discipline
|
|
15
|
+
* `resolved-bundle.ts` uses for `bundle_sha`. Callers MUST normalize the manifest
|
|
16
|
+
* ({@link normalizeManifest}) before hashing so incidental unknown keys never
|
|
17
|
+
* split the dedupe. Pure + dependency-free (node:crypto only).
|
|
18
|
+
*/
|
|
19
|
+
import type { Manifest } from "./manifest";
|
|
20
|
+
/**
|
|
21
|
+
* The content-hash id of a prompt version — `sha256:<hex>`, self-describing so a
|
|
22
|
+
* future algorithm change is visible in the stored value rather than silent
|
|
23
|
+
* (parity with `hashResolvedBundle`). The template is hashed verbatim; the
|
|
24
|
+
* manifest is canonicalized. The two are joined with a NUL separator that cannot
|
|
25
|
+
* appear in the template, so no `(template, manifest)` pair can collide with a
|
|
26
|
+
* different pair by boundary ambiguity.
|
|
27
|
+
*/
|
|
28
|
+
export declare function promptTemplateSha(template: string, manifest: Manifest): string;
|
|
29
|
+
//# sourceMappingURL=version-hash.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version-hash.d.ts","sourceRoot":"","sources":["../../src/prompts/version-hash.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAkB3C;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAO9E"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* PSR-2 — the content-hash id for a prompt version (`template_sha`).
|
|
4
|
+
*
|
|
5
|
+
* A prompt version is identified by the sha256 of its `template` + `manifest`
|
|
6
|
+
* (spec §2, the Humanloop content-hash pattern: identical content ⇒ no
|
|
7
|
+
* duplicate row). This is the ONE definition of that hash, used by:
|
|
8
|
+
* • the ingest + create-version writer (dedupe: an identical re-ingest resolves
|
|
9
|
+
* to the existing row rather than appending a byte-identical version), and
|
|
10
|
+
* • the served-projection check (does routes.bundle carry THIS version? — the
|
|
11
|
+
* "served this call" marker compares template_sha, PSR-2b).
|
|
12
|
+
*
|
|
13
|
+
* The manifest is CANONICALIZED first (object keys sorted recursively, array
|
|
14
|
+
* order preserved) so a semantically-identical manifest always hashes the same
|
|
15
|
+
* regardless of key order in the source artifact — the same discipline
|
|
16
|
+
* `resolved-bundle.ts` uses for `bundle_sha`. Callers MUST normalize the manifest
|
|
17
|
+
* ({@link normalizeManifest}) before hashing so incidental unknown keys never
|
|
18
|
+
* split the dedupe. Pure + dependency-free (node:crypto only).
|
|
19
|
+
*/
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.promptTemplateSha = promptTemplateSha;
|
|
22
|
+
const node_crypto_1 = require("node:crypto");
|
|
23
|
+
/** Deterministic JSON: object keys sorted recursively, array order preserved.
|
|
24
|
+
* The same value always produces the same bytes, so the hash is stable across
|
|
25
|
+
* processes. Mirrors resolved-bundle.ts's canonicalize (kept local so the two
|
|
26
|
+
* hashers stay independently auditable). */
|
|
27
|
+
function canonicalize(value) {
|
|
28
|
+
if (Array.isArray(value))
|
|
29
|
+
return value.map(canonicalize);
|
|
30
|
+
if (value !== null && typeof value === "object") {
|
|
31
|
+
const out = {};
|
|
32
|
+
for (const key of Object.keys(value).sort()) {
|
|
33
|
+
out[key] = canonicalize(value[key]);
|
|
34
|
+
}
|
|
35
|
+
return out;
|
|
36
|
+
}
|
|
37
|
+
return value;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* The content-hash id of a prompt version — `sha256:<hex>`, self-describing so a
|
|
41
|
+
* future algorithm change is visible in the stored value rather than silent
|
|
42
|
+
* (parity with `hashResolvedBundle`). The template is hashed verbatim; the
|
|
43
|
+
* manifest is canonicalized. The two are joined with a NUL separator that cannot
|
|
44
|
+
* appear in the template, so no `(template, manifest)` pair can collide with a
|
|
45
|
+
* different pair by boundary ambiguity.
|
|
46
|
+
*/
|
|
47
|
+
function promptTemplateSha(template, manifest) {
|
|
48
|
+
const canonicalManifest = JSON.stringify(canonicalize(manifest));
|
|
49
|
+
const hash = (0, node_crypto_1.createHash)("sha256");
|
|
50
|
+
hash.update(template, "utf8");
|
|
51
|
+
hash.update("\0", "utf8");
|
|
52
|
+
hash.update(canonicalManifest, "utf8");
|
|
53
|
+
return `sha256:${hash.digest("hex")}`;
|
|
54
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `modelrig prompts export` — PSR-3 (spec §3, the anti-lock-in gate).
|
|
3
|
+
*
|
|
4
|
+
* modelrig prompts export --route <route> [--out modelrig/routes]
|
|
5
|
+
* [--label prod | --version N] [--segment default] [--json]
|
|
6
|
+
*
|
|
7
|
+
* Fetches a prompt version from the ModelRig System-of-Record
|
|
8
|
+
* (`GET /v1/prompts/:route/export`, key-authed — a read needs only an org-scoped
|
|
9
|
+
* key) and writes its git files: the authored `template` to `<route>.md` and the
|
|
10
|
+
* assembly `manifest` to a sibling `<route>.manifest.json`, BYTE-FAITHFULLY. The
|
|
11
|
+
* command then PROVES the round-trip locally — it re-hashes the written files the
|
|
12
|
+
* way the store would (validate → normalize → hash) and checks the content id
|
|
13
|
+
* matches what ModelRig returned. ModelRig being your prompt's primary store
|
|
14
|
+
* never traps it in git.
|
|
15
|
+
*
|
|
16
|
+
* Goes through the API boundary (T12: the CLI never holds a DB client); the
|
|
17
|
+
* server scopes the read to the key's org (T11).
|
|
18
|
+
*/
|
|
19
|
+
import type { Flags } from "./cli";
|
|
20
|
+
export declare function cmdPromptsExport(flags: Flags): Promise<number>;
|
|
21
|
+
//# sourceMappingURL=prompts-export-cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts-export-cli.d.ts","sourceRoot":"","sources":["../src/prompts-export-cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAMH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AA0CnC,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CA4EpE"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* `modelrig prompts export` — PSR-3 (spec §3, the anti-lock-in gate).
|
|
4
|
+
*
|
|
5
|
+
* modelrig prompts export --route <route> [--out modelrig/routes]
|
|
6
|
+
* [--label prod | --version N] [--segment default] [--json]
|
|
7
|
+
*
|
|
8
|
+
* Fetches a prompt version from the ModelRig System-of-Record
|
|
9
|
+
* (`GET /v1/prompts/:route/export`, key-authed — a read needs only an org-scoped
|
|
10
|
+
* key) and writes its git files: the authored `template` to `<route>.md` and the
|
|
11
|
+
* assembly `manifest` to a sibling `<route>.manifest.json`, BYTE-FAITHFULLY. The
|
|
12
|
+
* command then PROVES the round-trip locally — it re-hashes the written files the
|
|
13
|
+
* way the store would (validate → normalize → hash) and checks the content id
|
|
14
|
+
* matches what ModelRig returned. ModelRig being your prompt's primary store
|
|
15
|
+
* never traps it in git.
|
|
16
|
+
*
|
|
17
|
+
* Goes through the API boundary (T12: the CLI never holds a DB client); the
|
|
18
|
+
* server scopes the read to the key's org (T11).
|
|
19
|
+
*/
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.cmdPromptsExport = cmdPromptsExport;
|
|
22
|
+
const node_fs_1 = require("node:fs");
|
|
23
|
+
const node_path_1 = require("node:path");
|
|
24
|
+
const config_1 = require("./config");
|
|
25
|
+
const index_1 = require("./index");
|
|
26
|
+
const DEFAULT_OUT = "modelrig/routes";
|
|
27
|
+
function usage() {
|
|
28
|
+
return [
|
|
29
|
+
"usage: modelrig prompts export --route <route> [--out modelrig/routes]",
|
|
30
|
+
" [--label prod | --version N] [--segment default] [--json]",
|
|
31
|
+
"",
|
|
32
|
+
"Exports a prompt version from ModelRig back to git files (the anti-lock-in guarantee):",
|
|
33
|
+
" <route>.md the authored prompt template, verbatim",
|
|
34
|
+
" <route>.manifest.json the assembly manifest (structure only)",
|
|
35
|
+
"A version re-created from these files carries the SAME content hash — proven after write.",
|
|
36
|
+
"",
|
|
37
|
+
" MODELRIG_API_KEY a rig_sk_ key in your org (a read needs no special scope)",
|
|
38
|
+
" MODELRIG_INGEST_URL optional — the server base; defaults to the hosted API",
|
|
39
|
+
].join("\n");
|
|
40
|
+
}
|
|
41
|
+
/** The content id a version re-created from the written files would carry — the
|
|
42
|
+
* store's write discipline (validate → normalize → hash) run locally, so the
|
|
43
|
+
* round-trip is proven without a second server call. */
|
|
44
|
+
function recreatedSha(templateFile, manifestFile) {
|
|
45
|
+
let parsed;
|
|
46
|
+
try {
|
|
47
|
+
parsed = JSON.parse(manifestFile);
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
const validated = (0, index_1.validateManifest)(parsed);
|
|
53
|
+
if (!validated.ok)
|
|
54
|
+
return null;
|
|
55
|
+
return (0, index_1.promptTemplateSha)(templateFile, (0, index_1.normalizeManifest)(validated.manifest));
|
|
56
|
+
}
|
|
57
|
+
async function cmdPromptsExport(flags) {
|
|
58
|
+
// The subcommand token ("export") is flags.positional[0]; require it explicitly
|
|
59
|
+
// so `modelrig prompts` (no verb) prints usage rather than guessing.
|
|
60
|
+
if (flags.positional[0] !== "export") {
|
|
61
|
+
console.error(usage());
|
|
62
|
+
return 1;
|
|
63
|
+
}
|
|
64
|
+
const route = flags.named.get("route");
|
|
65
|
+
const out = flags.named.get("out") ?? DEFAULT_OUT;
|
|
66
|
+
const label = flags.named.get("label");
|
|
67
|
+
const versionRaw = flags.named.get("version");
|
|
68
|
+
const segment = flags.named.get("segment");
|
|
69
|
+
const asJson = flags.bare.has("json");
|
|
70
|
+
const exp = (0, config_1.loadConfigFromEnv)().export;
|
|
71
|
+
const api = exp !== undefined && exp.mode === "api" ? exp : undefined;
|
|
72
|
+
const base = api !== undefined ? new URL(api.ingestUrl).origin : "";
|
|
73
|
+
const key = api?.apiKey ?? "";
|
|
74
|
+
if (route === undefined || route === "" || base === "" || key === "") {
|
|
75
|
+
console.error(usage());
|
|
76
|
+
return 1;
|
|
77
|
+
}
|
|
78
|
+
const query = [];
|
|
79
|
+
if (versionRaw !== undefined && versionRaw !== "")
|
|
80
|
+
query.push(`version=${encodeURIComponent(versionRaw)}`);
|
|
81
|
+
else if (label !== undefined && label !== "")
|
|
82
|
+
query.push(`label=${encodeURIComponent(label)}`);
|
|
83
|
+
if (segment !== undefined && segment !== "")
|
|
84
|
+
query.push(`segment=${encodeURIComponent(segment)}`);
|
|
85
|
+
const suffix = query.length > 0 ? `?${query.join("&")}` : "";
|
|
86
|
+
let res;
|
|
87
|
+
try {
|
|
88
|
+
res = await fetch(`${base}/v1/prompts/${encodeURIComponent(route)}/export${suffix}`, {
|
|
89
|
+
headers: { authorization: `Bearer ${key}` },
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
console.error(`prompts export: could not reach ${base}: ${err instanceof Error ? err.message : String(err)}`);
|
|
94
|
+
return 1;
|
|
95
|
+
}
|
|
96
|
+
const payload = (await res.json().catch(() => ({})));
|
|
97
|
+
if (!res.ok) {
|
|
98
|
+
console.error(`prompts export ${res.status}: ${[payload.error, payload.fix_hint].filter(Boolean).join(" — ") || "failed"}`);
|
|
99
|
+
return 1;
|
|
100
|
+
}
|
|
101
|
+
const files = payload.files ?? [];
|
|
102
|
+
if (files.length === 0 || payload.template_sha === undefined) {
|
|
103
|
+
console.error("prompts export: the server returned no files");
|
|
104
|
+
return 1;
|
|
105
|
+
}
|
|
106
|
+
// Write each file under --out, creating directories as needed.
|
|
107
|
+
const written = [];
|
|
108
|
+
for (const f of files) {
|
|
109
|
+
const dest = (0, node_path_1.join)(out, f.path);
|
|
110
|
+
(0, node_fs_1.mkdirSync)((0, node_path_1.dirname)(dest), { recursive: true });
|
|
111
|
+
(0, node_fs_1.writeFileSync)(dest, f.content);
|
|
112
|
+
written.push(dest);
|
|
113
|
+
}
|
|
114
|
+
// Prove the round-trip from the bytes on disk (never trust the transfer): the
|
|
115
|
+
// template file + the manifest file must re-hash to the server's content id.
|
|
116
|
+
const md = files.find((f) => f.path.endsWith(".md"));
|
|
117
|
+
const mf = files.find((f) => f.path.endsWith(".manifest.json"));
|
|
118
|
+
const rehashed = md !== undefined && mf !== undefined ? recreatedSha(md.content, mf.content) : null;
|
|
119
|
+
const roundTripped = rehashed !== null && rehashed === payload.template_sha;
|
|
120
|
+
if (asJson) {
|
|
121
|
+
console.log(JSON.stringify({ route: payload.route, version: payload.version, template_sha: payload.template_sha, written, round_trip: roundTripped }, null, 2));
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
console.log(`Exported ${route} version ${String(payload.version)} → ${written.join(", ")}`);
|
|
125
|
+
console.log(roundTripped
|
|
126
|
+
? `Round-trip verified: re-creating from these files reproduces the same content hash (${payload.template_sha.slice(0, 12)}…). Your prompt is not locked in.`
|
|
127
|
+
: "WARNING: the written files did NOT re-hash to the server's content id — do not rely on this export; re-run.");
|
|
128
|
+
}
|
|
129
|
+
return roundTripped ? 0 : 1;
|
|
130
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache-policy.d.ts","sourceRoot":"","sources":["../../src/registry/cache-policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B;4CACwC;IACxC,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC;;;2EAGuE;IACvE,QAAQ,CAAC,IAAI,EAAE,sBAAsB,GAAG,kBAAkB,GAAG,YAAY,CAAC;IAC1E,0EAA0E;IAC1E,QAAQ,CAAC,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5C;4CACwC;IACxC,QAAQ,CAAC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7C;sFACkF;IAClF,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAC;IACtC;8EAC0E;IAC1E,QAAQ,CAAC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7C;mDAC+C;IAC/C,QAAQ,CAAC,eAAe,EAAE,kBAAkB,GAAG,eAAe,GAAG,eAAe,GAAG,IAAI,CAAC;IACxF;8EAC0E;IAC1E,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAC;IACtC,qEAAqE;IACrE,QAAQ,CAAC,oBAAoB,EAAE,OAAO,CAAC;IACvC,qDAAqD;IACrD,QAAQ,CAAC,aAAa,EAClB,WAAW,GACX,gBAAgB,GAChB,oBAAoB,GACpB,iBAAiB,GACjB,mBAAmB,CAAC;IACxB;;8BAE0B;IAC1B,QAAQ,CAAC,0BAA0B,EAAE,OAAO,CAAC;IAC7C,4DAA4D;IAC5D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;
|
|
1
|
+
{"version":3,"file":"cache-policy.d.ts","sourceRoot":"","sources":["../../src/registry/cache-policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B;4CACwC;IACxC,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC;;;2EAGuE;IACvE,QAAQ,CAAC,IAAI,EAAE,sBAAsB,GAAG,kBAAkB,GAAG,YAAY,CAAC;IAC1E,0EAA0E;IAC1E,QAAQ,CAAC,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5C;4CACwC;IACxC,QAAQ,CAAC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7C;sFACkF;IAClF,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAC;IACtC;8EAC0E;IAC1E,QAAQ,CAAC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7C;mDAC+C;IAC/C,QAAQ,CAAC,eAAe,EAAE,kBAAkB,GAAG,eAAe,GAAG,eAAe,GAAG,IAAI,CAAC;IACxF;8EAC0E;IAC1E,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAC;IACtC,qEAAqE;IACrE,QAAQ,CAAC,oBAAoB,EAAE,OAAO,CAAC;IACvC,qDAAqD;IACrD,QAAQ,CAAC,aAAa,EAClB,WAAW,GACX,gBAAgB,GAChB,oBAAoB,GACpB,iBAAiB,GACjB,mBAAmB,CAAC;IACxB;;8BAE0B;IAC1B,QAAQ,CAAC,0BAA0B,EAAE,OAAO,CAAC;IAC7C,4DAA4D;IAC5D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAqMD;;;;eAIe;AACf,wBAAgB,qBAAqB,IAAI,WAAW,CAiBnD;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,UAAU,GAAG,WAAW,CAEhE;AAED,+EAA+E;AAC/E,wBAAgB,0BAA0B,IAAI,SAAS,UAAU,EAAE,CAElE"}
|
|
@@ -199,6 +199,28 @@ const POLICIES = {
|
|
|
199
199
|
as_of: AS_OF,
|
|
200
200
|
policy_version: AS_OF,
|
|
201
201
|
},
|
|
202
|
+
// Z.ai / Zhipu (B4a) — GLM context caching is not verified first-party here
|
|
203
|
+
// (docs egress-blocked at build time), so fail-closed to cache_supported:false,
|
|
204
|
+
// identical L5 posture to DeepInfra. The raw-lane `cache.key` still maps to the
|
|
205
|
+
// OpenAI-dialect `prompt_cache_key` HINT (raw-support.ts) — that is call-shaping,
|
|
206
|
+
// not a claim that a warm cache exists on our path. Revisit when a first-party
|
|
207
|
+
// Z.ai caching page can be cited (then flip with a new as_of).
|
|
208
|
+
zai: {
|
|
209
|
+
cache_supported: false,
|
|
210
|
+
mode: "automatic_prefix",
|
|
211
|
+
default_ttl_seconds: null,
|
|
212
|
+
extended_ttl_seconds: null,
|
|
213
|
+
ttl_refresh_on_read: false,
|
|
214
|
+
min_cacheable_tokens: null,
|
|
215
|
+
cache_key_param: null,
|
|
216
|
+
reports_read_tokens: false,
|
|
217
|
+
reports_write_tokens: false,
|
|
218
|
+
usage_dialect: "openai_details",
|
|
219
|
+
provider_affinity_required: false,
|
|
220
|
+
source: "z.ai — cached rates unverified first-party (fail-closed, L5)",
|
|
221
|
+
as_of: AS_OF,
|
|
222
|
+
policy_version: AS_OF,
|
|
223
|
+
},
|
|
202
224
|
};
|
|
203
225
|
/** The fail-closed policy for any provider not seeded (spec §3): caching is
|
|
204
226
|
* assumed OFF until a first-party source says otherwise — identical posture to
|
|
@@ -29,11 +29,32 @@ export interface TokenRates {
|
|
|
29
29
|
* ⇒ the 1h write bucket bills at `cache_write` (fail-closed, dev-rule L5). */
|
|
30
30
|
readonly cache_write_1h?: number | null;
|
|
31
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Per-component tier multipliers (issue #2). A vendor's tier does not always
|
|
34
|
+
* scale every component by one number: Google's Gemini `flex` (and batch) is
|
|
35
|
+
* 0.5× input + output while cache read is "Same as Standard" — so a single
|
|
36
|
+
* scalar over-discounts the cached portion. An ABSENT component here is EXEMPT
|
|
37
|
+
* (multiplier 1.0 — the standard rate), never a guess: write a component
|
|
38
|
+
* explicitly when the vendor publishes a different multiplier for it (L5).
|
|
39
|
+
*/
|
|
40
|
+
export interface TierComponentMultipliers {
|
|
41
|
+
readonly input: number;
|
|
42
|
+
readonly output: number;
|
|
43
|
+
/** absent/null ⇒ 1.0 (exempt — bills at the standard cache-read rate). */
|
|
44
|
+
readonly cache_read?: number | null;
|
|
45
|
+
readonly cache_write?: number | null;
|
|
46
|
+
readonly cache_write_1h?: number | null;
|
|
47
|
+
}
|
|
48
|
+
/** A tier multiplier: one scalar over EVERY component (`1.25`), or a
|
|
49
|
+
* per-component block (`{ input: 0.5, output: 0.5, cache_read: 1.0 }`). */
|
|
50
|
+
export type TierMultiplier = number | TierComponentMultipliers;
|
|
32
51
|
/** MULTIPLIERS on `base` (1.0 = base), NOT absolute rates. */
|
|
33
52
|
export interface ServingTiers {
|
|
34
|
-
readonly priority?:
|
|
35
|
-
readonly fast?:
|
|
36
|
-
readonly region_us?:
|
|
53
|
+
readonly priority?: TierMultiplier | null;
|
|
54
|
+
readonly fast?: TierMultiplier | null;
|
|
55
|
+
readonly region_us?: TierMultiplier | null;
|
|
56
|
+
/** Gemini flex (issue #2): `{ input: 0.5, output: 0.5, cache_read: 1.0 }`. */
|
|
57
|
+
readonly flex?: TierMultiplier | null;
|
|
37
58
|
}
|
|
38
59
|
/** A rate change that applies above a token threshold. */
|
|
39
60
|
export interface ContextBand {
|
|
@@ -101,12 +122,21 @@ export declare const SNAPSHOT_BASIS = "base \u00B7 standard tier \u00B7 text";
|
|
|
101
122
|
* the caller supplies provenance. `source` defaults to the snapshot lane.
|
|
102
123
|
*/
|
|
103
124
|
export declare function synthesizeFromFlat(input: number, output: number, cache_read: number | null, asOf: string, source?: string): ModelPricingV2;
|
|
104
|
-
export type ServingTierName = "priority" | "fast" | "region_us";
|
|
125
|
+
export type ServingTierName = "priority" | "fast" | "region_us" | "flex";
|
|
126
|
+
/** Resolve a tier multiplier to one multiplier PER component. A scalar scales
|
|
127
|
+
* every component (the original contract, byte-identical); a per-component
|
|
128
|
+
* block fills an absent component with 1.0 — EXEMPT, i.e. the standard rate. */
|
|
129
|
+
export declare function tierComponentMultipliers(mult: TierMultiplier): Required<{
|
|
130
|
+
[K in keyof TierComponentMultipliers]: number;
|
|
131
|
+
}>;
|
|
105
132
|
/**
|
|
106
|
-
* Absolute rates for a serving tier = `base × multiplier
|
|
107
|
-
* the tier's multiplier is absent — fail-closed, so no
|
|
108
|
-
* tier price the model never published.
|
|
109
|
-
* component present on `base
|
|
133
|
+
* Absolute rates for a serving tier = `base × multiplier`, PER COMPONENT.
|
|
134
|
+
* Returns `null` when the tier's multiplier is absent — fail-closed, so no
|
|
135
|
+
* surface (and no cost row) can carry a tier price the model never published.
|
|
136
|
+
* A scalar multiplier scales every rate component present on `base`; a
|
|
137
|
+
* per-component block scales each component by its own multiplier, with an
|
|
138
|
+
* absent component exempt (1.0) — issue #2: Gemini flex discounts input and
|
|
139
|
+
* output but NOT cache read.
|
|
110
140
|
*/
|
|
111
141
|
export declare function tierRates(pricing: ModelPricingV2, tier: ServingTierName): TokenRates | null;
|
|
112
142
|
/** A display-ready projection of a price. `basis` is always present, so a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pricing-shape.d.ts","sourceRoot":"","sources":["../../src/registry/pricing-shape.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,+BAA+B;IAC/B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,uEAAuE;IACvE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC;kFAC8E;IAC9E,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzC;AAED,8DAA8D;AAC9D,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,
|
|
1
|
+
{"version":3,"file":"pricing-shape.d.ts","sourceRoot":"","sources":["../../src/registry/pricing-shape.ts"],"names":[],"mappings":"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"}
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
23
|
exports.SNAPSHOT_BASIS = void 0;
|
|
24
24
|
exports.synthesizeFromFlat = synthesizeFromFlat;
|
|
25
|
+
exports.tierComponentMultipliers = tierComponentMultipliers;
|
|
25
26
|
exports.tierRates = tierRates;
|
|
26
27
|
exports.describePricingV2 = describePricingV2;
|
|
27
28
|
/** The basis string for a snapshot-synthesized (base-only, standard, text)
|
|
@@ -52,25 +53,44 @@ function synthesizeFromFlat(input, output, cache_read, asOf, source = "litellm-s
|
|
|
52
53
|
function scale(rate, mult) {
|
|
53
54
|
return rate === null || rate === undefined ? null : rate * mult;
|
|
54
55
|
}
|
|
56
|
+
/** Resolve a tier multiplier to one multiplier PER component. A scalar scales
|
|
57
|
+
* every component (the original contract, byte-identical); a per-component
|
|
58
|
+
* block fills an absent component with 1.0 — EXEMPT, i.e. the standard rate. */
|
|
59
|
+
function tierComponentMultipliers(mult) {
|
|
60
|
+
if (typeof mult === "number") {
|
|
61
|
+
return { input: mult, output: mult, cache_read: mult, cache_write: mult, cache_write_1h: mult };
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
input: mult.input,
|
|
65
|
+
output: mult.output,
|
|
66
|
+
cache_read: mult.cache_read ?? 1,
|
|
67
|
+
cache_write: mult.cache_write ?? 1,
|
|
68
|
+
cache_write_1h: mult.cache_write_1h ?? 1,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
55
71
|
/**
|
|
56
|
-
* Absolute rates for a serving tier = `base × multiplier
|
|
57
|
-
* the tier's multiplier is absent — fail-closed, so no
|
|
58
|
-
* tier price the model never published.
|
|
59
|
-
* component present on `base
|
|
72
|
+
* Absolute rates for a serving tier = `base × multiplier`, PER COMPONENT.
|
|
73
|
+
* Returns `null` when the tier's multiplier is absent — fail-closed, so no
|
|
74
|
+
* surface (and no cost row) can carry a tier price the model never published.
|
|
75
|
+
* A scalar multiplier scales every rate component present on `base`; a
|
|
76
|
+
* per-component block scales each component by its own multiplier, with an
|
|
77
|
+
* absent component exempt (1.0) — issue #2: Gemini flex discounts input and
|
|
78
|
+
* output but NOT cache read.
|
|
60
79
|
*/
|
|
61
80
|
function tierRates(pricing, tier) {
|
|
62
81
|
const mult = pricing.tiers?.[tier];
|
|
63
82
|
if (mult === null || mult === undefined)
|
|
64
83
|
return null;
|
|
84
|
+
const m = tierComponentMultipliers(mult);
|
|
65
85
|
return {
|
|
66
|
-
input: pricing.base.input *
|
|
67
|
-
output: pricing.base.output *
|
|
68
|
-
cache_read: scale(pricing.base.cache_read,
|
|
69
|
-
cache_write: scale(pricing.base.cache_write,
|
|
70
|
-
cache_write_1h: scale(pricing.base.cache_write_1h,
|
|
86
|
+
input: pricing.base.input * m.input,
|
|
87
|
+
output: pricing.base.output * m.output,
|
|
88
|
+
cache_read: scale(pricing.base.cache_read, m.cache_read),
|
|
89
|
+
cache_write: scale(pricing.base.cache_write, m.cache_write),
|
|
90
|
+
cache_write_1h: scale(pricing.base.cache_write_1h, m.cache_write_1h),
|
|
71
91
|
};
|
|
72
92
|
}
|
|
73
|
-
const TIER_ORDER = ["priority", "fast", "region_us"];
|
|
93
|
+
const TIER_ORDER = ["priority", "fast", "region_us", "flex"];
|
|
74
94
|
/** USD-per-token → "$X.XX" per Mtok. Adaptive precision: a pricing-authority
|
|
75
95
|
* surface must not misrepresent a rate — `$0.075/M` renders as `$0.075`, not a
|
|
76
96
|
* rounded `$0.07`/`$0.08`. Shows up to 6 decimals, trailing zeros trimmed, with
|
|
@@ -94,8 +114,16 @@ function describePricingV2(pricing) {
|
|
|
94
114
|
const tiers = [];
|
|
95
115
|
for (const name of TIER_ORDER) {
|
|
96
116
|
const rates = tierRates(pricing, name);
|
|
97
|
-
if (rates
|
|
98
|
-
|
|
117
|
+
if (rates === null)
|
|
118
|
+
continue;
|
|
119
|
+
// Every scaled tier that publishes a cache-read rate states it explicitly,
|
|
120
|
+
// so a reader never infers the cache rate from the in/out multiplier
|
|
121
|
+
// (gemini flex: in/out 0.5× but cache read NOT discounted). Only a tier whose
|
|
122
|
+
// input equals base (a 1.0× tier) omits the note.
|
|
123
|
+
const cacheNote = rates.cache_read != null && pricing.base.cache_read != null && rates.input !== pricing.base.input
|
|
124
|
+
? ` · cache read ${perMtok(rates.cache_read)}`
|
|
125
|
+
: "";
|
|
126
|
+
tiers.push({ name, rate: `${inOut(rates)}${cacheNote}` });
|
|
99
127
|
}
|
|
100
128
|
const contextBands = (pricing.context_bands ?? []).map((b) => `above ${b.above_tokens.toLocaleString()} tok: ${inOut(b.rates)}`);
|
|
101
129
|
const modality = [];
|
|
@@ -25,11 +25,12 @@ export interface ModelPricing {
|
|
|
25
25
|
}
|
|
26
26
|
export declare function getPricing(provider: ProviderId, model: string): ModelPricing | null;
|
|
27
27
|
/**
|
|
28
|
-
* The richer `ModelPricingV2`
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
28
|
+
* The richer `ModelPricingV2` on file for a model, if any — resolved by the SAME
|
|
29
|
+
* key precedence as {@link getPricing} (snapshot wins on a shared key; a snapshot
|
|
30
|
+
* entry yields its hand-grafted `pricing_v2` when it has one — issue #2's gemini
|
|
31
|
+
* tiers — else null → the caller synthesizes from the flat rate; an overlay or
|
|
32
|
+
* manual entry yields its own block). Returns null when no richer shape is on
|
|
33
|
+
* file. Never guesses: absence is `base`-only downstream.
|
|
33
34
|
*/
|
|
34
35
|
export declare function getPricingV2(provider: ProviderId, model: string): ModelPricingV2 | null;
|
|
35
36
|
export declare function estimateCostUsd(pricing: ModelPricing, tokensIn: number, tokensOut: number, tokensCached: number,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pricing.d.ts","sourceRoot":"","sources":["../../src/registry/pricing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7C;;uEAEmE;IACnE,QAAQ,CAAC,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5C;;sEAEkE;IAClE,QAAQ,CAAC,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/C;
|
|
1
|
+
{"version":3,"file":"pricing.d.ts","sourceRoot":"","sources":["../../src/registry/pricing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7C;;uEAEmE;IACnE,QAAQ,CAAC,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5C;;sEAEkE;IAClE,QAAQ,CAAC,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/C;AA+DD,wBAAgB,UAAU,CAAC,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CA6BnF;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAYvF;AAED,wBAAgB,eAAe,CAC7B,OAAO,EAAE,YAAY,EACrB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM;AACpB;;;0CAG0C;AAC1C,gBAAgB,SAAI;AACpB,+EAA+E;AAC/E,kBAAkB,SAAI,GACrB,MAAM,CAsBR"}
|
package/dist/registry/pricing.js
CHANGED
|
@@ -29,6 +29,9 @@ const KEY_PREFIXES = {
|
|
|
29
29
|
// Fireworks pricing keys carry the accounts/… wire prefix.
|
|
30
30
|
deepinfra: ["deepinfra/"],
|
|
31
31
|
fireworks: ["fireworks_ai/accounts/fireworks/models/", "fireworks_ai/"],
|
|
32
|
+
// Z.ai (B4a): GLM models keyed under "zai/" in the snapshot. Registry entries
|
|
33
|
+
// carry their own declared pricing, so this only gaps-fills a future snapshot.
|
|
34
|
+
zai: ["zai/"],
|
|
32
35
|
};
|
|
33
36
|
let cachedMap = null;
|
|
34
37
|
/** Host-swept gap-filler (scripts/pricing-sweep.ts): prices for models the
|
|
@@ -77,11 +80,12 @@ function getPricing(provider, model) {
|
|
|
77
80
|
return null;
|
|
78
81
|
}
|
|
79
82
|
/**
|
|
80
|
-
* The richer `ModelPricingV2`
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
83
|
+
* The richer `ModelPricingV2` on file for a model, if any — resolved by the SAME
|
|
84
|
+
* key precedence as {@link getPricing} (snapshot wins on a shared key; a snapshot
|
|
85
|
+
* entry yields its hand-grafted `pricing_v2` when it has one — issue #2's gemini
|
|
86
|
+
* tiers — else null → the caller synthesizes from the flat rate; an overlay or
|
|
87
|
+
* manual entry yields its own block). Returns null when no richer shape is on
|
|
88
|
+
* file. Never guesses: absence is `base`-only downstream.
|
|
85
89
|
*/
|
|
86
90
|
function getPricingV2(provider, model) {
|
|
87
91
|
if (model === "")
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serving-`destination` route-field validation (Unified Route U2, ruling D-2).
|
|
3
|
+
* Extracted from loader.ts so loader.ts holds under the 700-LOC cap (same reason
|
|
4
|
+
* loader-warnings.ts / screen-loader.ts were carved out). Hand-written validation
|
|
5
|
+
* mirroring the loader's PROVIDERS/TIERS pattern: a route's `destination:` is
|
|
6
|
+
* checked against the DESTINATIONS vocabulary (the ONE source of truth in
|
|
7
|
+
* run/destination.ts — no second list to drift); an unknown value pushes a
|
|
8
|
+
* teaching problem (the caller turns it into a RouteConfigError). Absent ⇒
|
|
9
|
+
* undefined ⇒ resolves to `direct` at run time ⇒ BYTE-IDENTICAL.
|
|
10
|
+
*/
|
|
11
|
+
import type { Destination } from "../run/destination";
|
|
12
|
+
/** Validate a route bundle's `destination:` value. Absent/null ⇒ undefined
|
|
13
|
+
* (defaults to `direct`); a known value ⇒ that `Destination`; an unknown value ⇒
|
|
14
|
+
* a pushed problem and undefined. */
|
|
15
|
+
export declare function parseDestination(raw: unknown, problems: string[]): Destination | undefined;
|
|
16
|
+
//# sourceMappingURL=destination-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"destination-loader.d.ts","sourceRoot":"","sources":["../../src/routes/destination-loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAMtD;;qCAEqC;AACrC,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,WAAW,GAAG,SAAS,CAO1F"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Serving-`destination` route-field validation (Unified Route U2, ruling D-2).
|
|
4
|
+
* Extracted from loader.ts so loader.ts holds under the 700-LOC cap (same reason
|
|
5
|
+
* loader-warnings.ts / screen-loader.ts were carved out). Hand-written validation
|
|
6
|
+
* mirroring the loader's PROVIDERS/TIERS pattern: a route's `destination:` is
|
|
7
|
+
* checked against the DESTINATIONS vocabulary (the ONE source of truth in
|
|
8
|
+
* run/destination.ts — no second list to drift); an unknown value pushes a
|
|
9
|
+
* teaching problem (the caller turns it into a RouteConfigError). Absent ⇒
|
|
10
|
+
* undefined ⇒ resolves to `direct` at run time ⇒ BYTE-IDENTICAL.
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.parseDestination = parseDestination;
|
|
14
|
+
const destination_1 = require("../run/destination");
|
|
15
|
+
/** The serving-`destination` vocabulary as a lookup set, mirroring the loader's
|
|
16
|
+
* PROVIDERS/TIERS ReadonlySets. */
|
|
17
|
+
const DESTINATIONS = new Set(destination_1.DESTINATIONS);
|
|
18
|
+
/** Validate a route bundle's `destination:` value. Absent/null ⇒ undefined
|
|
19
|
+
* (defaults to `direct`); a known value ⇒ that `Destination`; an unknown value ⇒
|
|
20
|
+
* a pushed problem and undefined. */
|
|
21
|
+
function parseDestination(raw, problems) {
|
|
22
|
+
if (raw === undefined || raw === null)
|
|
23
|
+
return undefined;
|
|
24
|
+
if (typeof raw !== "string" || !DESTINATIONS.has(raw)) {
|
|
25
|
+
problems.push(`destination "${String(raw)}" is not one of [${[...DESTINATIONS].join(", ")}]`);
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
return raw;
|
|
29
|
+
}
|
package/dist/routes/draft.d.ts
CHANGED
|
@@ -34,6 +34,13 @@ export interface RouteDraftSpec {
|
|
|
34
34
|
readonly variables: readonly string[];
|
|
35
35
|
/** JSON Schema for the output; null drafts an unstructured route. */
|
|
36
36
|
readonly outputSchema: object | null;
|
|
37
|
+
/** `output: text` (issue #1) — a prose/markdown route, returned verbatim.
|
|
38
|
+
* Absent / `"json"` ⇒ nothing is emitted (the loader default). `text` with a
|
|
39
|
+
* non-null `outputSchema` is refused here, as the loader would refuse it. */
|
|
40
|
+
readonly outputKind?: "json" | "text";
|
|
41
|
+
/** `prompt.user` (issue #5, R1) — the per-call user-turn template, written
|
|
42
|
+
* to `prompts/<name>.user.md` and declared beside `prompt.system`. */
|
|
43
|
+
readonly userPrompt?: string;
|
|
37
44
|
readonly require?: readonly string[];
|
|
38
45
|
readonly prefer?: readonly string[];
|
|
39
46
|
readonly policy?: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"draft.d.ts","sourceRoot":"","sources":["../../src/routes/draft.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,mEAAmE;IACnE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,sDAAsD;IACtD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,SAAS,cAAc,EAAE,CAAC;IAC/C;wCACoC;IACpC,QAAQ,CAAC,SAAS,CAAC,EAAE;QAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAClF,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,qEAAqE;IACrE,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,MAAM,CAAC,EAAE;QAChB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAC5B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;KACrD,CAAC;IACF,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B;6EACyE;IACzE,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACzC;AAED,MAAM,WAAW,SAAS;IACxB,6CAA6C;IAC7C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,CAAC;CACtC;AAmBD,wBAAgB,eAAe,CAAC,IAAI,EAAE,cAAc,GAAG,UAAU,
|
|
1
|
+
{"version":3,"file":"draft.d.ts","sourceRoot":"","sources":["../../src/routes/draft.ts"],"names":[],"mappings":"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"}
|
package/dist/routes/draft.js
CHANGED
|
@@ -40,10 +40,15 @@ function buildRouteDraft(spec) {
|
|
|
40
40
|
throw new Error(`route draft "${spec.route}" has no candidates — a route with nothing allowed to serve it ` +
|
|
41
41
|
"cannot run. Name at least one provider/model.");
|
|
42
42
|
}
|
|
43
|
+
if (spec.outputKind === "text" && spec.outputSchema !== null) {
|
|
44
|
+
throw new Error(`route draft "${spec.route}" declares output: text AND a schema — a prose route has no schema. ` +
|
|
45
|
+
"Drop the schema, or draft a JSON route.");
|
|
46
|
+
}
|
|
43
47
|
const name = slug(spec.route);
|
|
44
48
|
const files = [];
|
|
45
49
|
const schemaRef = spec.outputSchema === null ? null : `./schemas/${name}.schema.json`;
|
|
46
50
|
const promptRef = `./prompts/${name}.system.md`;
|
|
51
|
+
const userPromptRef = spec.userPrompt === undefined ? null : `./prompts/${name}.user.md`;
|
|
47
52
|
const lines = [
|
|
48
53
|
"# ModelRig route bundle — DRAFT. Nothing in your app calls this yet.",
|
|
49
54
|
"# Read it, edit it, move it up one directory into modelrig/routes/, then",
|
|
@@ -55,6 +60,8 @@ function buildRouteDraft(spec) {
|
|
|
55
60
|
lines.push(`# ${line}`);
|
|
56
61
|
}
|
|
57
62
|
lines.push("#", "# Candidates are ordered incumbent-first: the model you already use leads,", "# so the first run reproduces today's behavior. The cheaper probed", "# alternatives below it are what a bake-off would put to the test.", "#", "# `prefer` is empty ON PURPOSE. Adding `cost` re-sorts these candidates by", "# price, which would hand the first run to the cheapest model rather than", "# to your incumbent — the opposite of a like-for-like migration. Prove a", "# cheaper model with a bake-off, then switch to it deliberately.", `route: ${yamlString(spec.route)}`, "version: 1");
|
|
63
|
+
if (spec.outputKind === "text")
|
|
64
|
+
lines.push("output: text # prose/markdown, returned verbatim (no schema:)");
|
|
58
65
|
if (schemaRef !== null)
|
|
59
66
|
lines.push(`schema: ${schemaRef}`);
|
|
60
67
|
lines.push("candidates:");
|
|
@@ -78,6 +85,8 @@ function buildRouteDraft(spec) {
|
|
|
78
85
|
lines.push(`prefer: [${(spec.prefer ?? []).map(yamlString).join(", ")}]`);
|
|
79
86
|
lines.push("prompt:");
|
|
80
87
|
lines.push(` system: ${promptRef}`);
|
|
88
|
+
if (userPromptRef !== null)
|
|
89
|
+
lines.push(` user: ${userPromptRef} # per-call user turn (the delta next to a cache handle)`);
|
|
81
90
|
lines.push(` variables: [${spec.variables.map(yamlString).join(", ")}]` +
|
|
82
91
|
(spec.variables.length === 0 ? " # no {{variables}} detected — the prompt is static" : ""));
|
|
83
92
|
const policy = spec.policy ?? {};
|
|
@@ -105,6 +114,9 @@ function buildRouteDraft(spec) {
|
|
|
105
114
|
});
|
|
106
115
|
}
|
|
107
116
|
files.push({ path: `prompts/${name}.system.md`, contents: ensureTrailingNewline(spec.systemPrompt) });
|
|
117
|
+
if (spec.userPrompt !== undefined) {
|
|
118
|
+
files.push({ path: `prompts/${name}.user.md`, contents: ensureTrailingNewline(spec.userPrompt) });
|
|
119
|
+
}
|
|
108
120
|
return { route: spec.route, files };
|
|
109
121
|
}
|
|
110
122
|
function ensureTrailingNewline(text) {
|