modelrig 0.11.1 → 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 +34 -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/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 +106 -6
- package/dist/init/observe.d.ts.map +1 -1
- package/dist/init/observe.js +3 -3
- 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/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 +16 -3
- package/docs/how-it-fits.md +3 -3
- package/docs/instrumentation.md +15 -6
- package/docs/llms.txt +55 -7
- package/docs/mcp-oracle.md +15 -4
- package/docs/quickstart.md +6 -5
- 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
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* THE grade-task key (GRADE-RAW, grade-ux-plan.md §1 item 2) — which TASK a
|
|
4
|
+
* telemetry row is graded under. ONE helper; every grading surface (teaching
|
|
5
|
+
* feed, auto-grade enqueue, calibration subject attribution, the /grades
|
|
6
|
+
* rollup, the grader's subject loader and the ingest-side task registration)
|
|
7
|
+
* keys through it, so they can never disagree about where a call belongs.
|
|
8
|
+
*
|
|
9
|
+
* • A ROUTED call is graded under its route (`inferences.route`).
|
|
10
|
+
* • A raw-lane (`rig.runRaw`) or recorded (`rig.recordCall`) call stores
|
|
11
|
+
* `provider/model` in `inferences.route` — not a task anyone would write a
|
|
12
|
+
* grading guide for. Its task is the customer's step name, `tags.step`,
|
|
13
|
+
* when present and a valid task name. Otherwise it falls back to the route
|
|
14
|
+
* (honest: an unnamed raw call has no task of its own).
|
|
15
|
+
*
|
|
16
|
+
* The SDK's auto step key inside a run (`<provider>/<model>#<n>`) contains a
|
|
17
|
+
* `/`, so it is never a valid task name and never becomes a task — a grader is
|
|
18
|
+
* for a step the customer named.
|
|
19
|
+
*
|
|
20
|
+
* Pure, dependency-free (the server, the console and stampBatch import it).
|
|
21
|
+
*/
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
exports.MAX_REGISTERED_STEPS_PER_BATCH = exports.TASK_NAME_RULE = exports.TASK_NAME_PATTERN = void 0;
|
|
24
|
+
exports.isValidTaskName = isValidTaskName;
|
|
25
|
+
exports.stepTaskOf = stepTaskOf;
|
|
26
|
+
exports.gradeTaskOf = gradeTaskOf;
|
|
27
|
+
exports.registrableStepTasks = registrableStepTasks;
|
|
28
|
+
const lanes_1 = require("./lanes");
|
|
29
|
+
/** A task name is one URL path segment (`/v1/tasks/<task>/settings`): starts
|
|
30
|
+
* with a letter or digit, then letters, digits, `.`, `_`, `:` or `-`; at most
|
|
31
|
+
* 128 characters. No `/`, no spaces. */
|
|
32
|
+
exports.TASK_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;
|
|
33
|
+
/** The teaching copy every bad-name refusal uses (one wording, everywhere). */
|
|
34
|
+
exports.TASK_NAME_RULE = "a task name starts with a letter or digit and then uses only letters, digits, '.', '_', ':' or '-' (max 128 chars, no '/' or spaces)";
|
|
35
|
+
/** At most this many NEW step tasks are registered per ingest batch (abuse
|
|
36
|
+
* cap: a batch cannot mint an unbounded number of task rows). Excess steps are
|
|
37
|
+
* not lost — they register on a later batch that carries them. */
|
|
38
|
+
exports.MAX_REGISTERED_STEPS_PER_BATCH = 50;
|
|
39
|
+
function isValidTaskName(value) {
|
|
40
|
+
return typeof value === "string" && exports.TASK_NAME_PATTERN.test(value);
|
|
41
|
+
}
|
|
42
|
+
function tagsOf(row) {
|
|
43
|
+
let raw = row.tags;
|
|
44
|
+
if (raw === undefined && typeof row.tagsJson === "string")
|
|
45
|
+
raw = row.tagsJson;
|
|
46
|
+
if (typeof raw === "string") {
|
|
47
|
+
try {
|
|
48
|
+
raw = JSON.parse(raw);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return {};
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return typeof raw === "object" && raw !== null && !Array.isArray(raw) ? raw : {};
|
|
55
|
+
}
|
|
56
|
+
/** The step a raw/recorded row names, or null (routed row, no step, or a step
|
|
57
|
+
* that is not a valid task name). */
|
|
58
|
+
function stepTaskOf(row) {
|
|
59
|
+
const tags = tagsOf(row);
|
|
60
|
+
if ((0, lanes_1.isRoutedLane)(tags.lane))
|
|
61
|
+
return null;
|
|
62
|
+
return isValidTaskName(tags.step) ? tags.step : null;
|
|
63
|
+
}
|
|
64
|
+
/** The task a row is graded under: `tags.step` for a raw/recorded row that names
|
|
65
|
+
* a valid step, else `route`. */
|
|
66
|
+
function gradeTaskOf(row) {
|
|
67
|
+
return stepTaskOf(row) ?? row.route;
|
|
68
|
+
}
|
|
69
|
+
/** The distinct step tasks a batch of rows names, first-seen order, capped at
|
|
70
|
+
* {@link MAX_REGISTERED_STEPS_PER_BATCH}. Routed rows contribute nothing (route
|
|
71
|
+
* sync owns their task rows). */
|
|
72
|
+
function registrableStepTasks(rows, cap = exports.MAX_REGISTERED_STEPS_PER_BATCH) {
|
|
73
|
+
const out = [];
|
|
74
|
+
const seen = new Set();
|
|
75
|
+
for (const row of rows) {
|
|
76
|
+
if (out.length >= cap)
|
|
77
|
+
break;
|
|
78
|
+
const step = stepTaskOf(row);
|
|
79
|
+
if (step === null || seen.has(step))
|
|
80
|
+
continue;
|
|
81
|
+
seen.add(step);
|
|
82
|
+
out.push(step);
|
|
83
|
+
}
|
|
84
|
+
return out;
|
|
85
|
+
}
|
|
@@ -16,7 +16,7 @@ import type Database from "better-sqlite3";
|
|
|
16
16
|
import type { GradeRow } from "../types/telemetry";
|
|
17
17
|
/** `CREATE TABLE IF NOT EXISTS grades …` — safe to run on every open. Mirrors
|
|
18
18
|
* `public.grades` minus the export-stamped columns (org handling below). */
|
|
19
|
-
export declare const GRADES_TABLE_SQL = "\nCREATE TABLE IF NOT EXISTS grades (\n id TEXT PRIMARY KEY,\n ts TEXT,\n subject_kind TEXT NOT NULL CHECK (subject_kind IN ('inference','run','artifact')),\n subject_id TEXT NOT NULL,\n score REAL NOT NULL,\n scale_max REAL,\n scale_label TEXT,\n comment TEXT,\n kind TEXT NOT NULL CHECK (kind IN ('human','model-judge','deterministic')),\n grader TEXT,\n source TEXT,\n org_id TEXT,\n created_by TEXT,\n criteria TEXT\n);\nCREATE INDEX IF NOT EXISTS idx_grades_subject ON grades (subject_kind, subject_id);\n";
|
|
19
|
+
export declare const GRADES_TABLE_SQL = "\nCREATE TABLE IF NOT EXISTS grades (\n id TEXT PRIMARY KEY,\n ts TEXT,\n subject_kind TEXT NOT NULL CHECK (subject_kind IN ('inference','run','artifact')),\n subject_id TEXT NOT NULL,\n score REAL NOT NULL,\n scale_max REAL,\n scale_label TEXT,\n comment TEXT,\n kind TEXT NOT NULL CHECK (kind IN ('human','model-judge','deterministic','outcome')),\n grader TEXT,\n source TEXT,\n org_id TEXT,\n created_by TEXT,\n criteria TEXT,\n value REAL,\n idempotency_key TEXT\n);\nCREATE INDEX IF NOT EXISTS idx_grades_subject ON grades (subject_kind, subject_id);\n";
|
|
20
20
|
/** The row shape as it sits in SQLite (snake_case, nullable columns as read back). */
|
|
21
21
|
export interface GradeDbRow {
|
|
22
22
|
id: string;
|
|
@@ -35,6 +35,11 @@ export interface GradeDbRow {
|
|
|
35
35
|
/** JSON-encoded per-criterion breakdown (call-qa F4), or null for a
|
|
36
36
|
* single-score grade / a row written before the v16 rung. */
|
|
37
37
|
criteria: string | null;
|
|
38
|
+
/** ARC-3 (v17): the raw outcome value, or null (every non-outcome grade, and
|
|
39
|
+
* any row written before the v17 rung). */
|
|
40
|
+
value: number | null;
|
|
41
|
+
/** ARC-3 L3 (v17): an outcome's idempotency key, or null. */
|
|
42
|
+
idempotency_key: string | null;
|
|
38
43
|
}
|
|
39
44
|
/** Prepare the grade insert statement against an open handle. INSERT OR IGNORE:
|
|
40
45
|
* a grade id is unique, and a re-inserted id (e.g. the backfill racing a live
|
|
@@ -53,4 +58,14 @@ export declare function backfillGradesFromFeedback(db: Database.Database): void;
|
|
|
53
58
|
* (grade primitive, GP-1). Same mapping as migration 00070's evaluation leg.
|
|
54
59
|
* Idempotent. Runs when the artifact store opens (it owns that table). */
|
|
55
60
|
export declare function backfillGradesFromEvaluations(db: Database.Database): void;
|
|
61
|
+
/** v17 (ARC-3, mirrors 00089): widen the local `grades.kind` CHECK with
|
|
62
|
+
* `'outcome'` and add the nullable `value` column. SQLite cannot ALTER a CHECK,
|
|
63
|
+
* so a table whose stored DDL lacks `'outcome'` is REBUILT into the current
|
|
64
|
+
* shape (= GRADES_TABLE_SQL) with every column AND the rowid copied (the v15
|
|
65
|
+
* pattern, plus rowid preservation so the exporter's `:grades` rowid watermark
|
|
66
|
+
* neither re-exports nor skips a row); a table
|
|
67
|
+
* that already allows it only gains `value` if absent. Idempotent: guarded on
|
|
68
|
+
* the stored DDL + `table_info`, so a re-open no-ops. No grades table ⇒ no-op
|
|
69
|
+
* (SCHEMA_SQL creates the current shape). */
|
|
70
|
+
export declare function migrateGradesToV17(db: Database.Database): void;
|
|
56
71
|
//# sourceMappingURL=grades-sql.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grades-sql.d.ts","sourceRoot":"","sources":["../../src/telemetry/grades-sql.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAkB,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEnE;4EAC4E;AAC5E,eAAO,MAAM,gBAAgB,
|
|
1
|
+
{"version":3,"file":"grades-sql.d.ts","sourceRoot":"","sources":["../../src/telemetry/grades-sql.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAkB,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEnE;4EAC4E;AAC5E,eAAO,MAAM,gBAAgB,gpBAoB5B,CAAC;AAEF,sFAAsF;AACtF,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B;iEAC6D;IAC7D,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;+CAC2C;IAC3C,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,6DAA6D;IAC7D,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAWD;;iCAEiC;AACjC,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,QAAQ,CAAC,SAAS,CAE5E;AAED,8DAA8D;AAC9D,wBAAgB,eAAe,CAAC,GAAG,EAAE,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAsBtE;AAED,sDAAsD;AACtD,wBAAgB,UAAU,CAAC,CAAC,EAAE,UAAU,GAAG,QAAQ,CAyBlD;AAcD;;;yCAGyC;AACzC,wBAAgB,0BAA0B,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,IAAI,CAetE;AAED;;0EAE0E;AAC1E,wBAAgB,6BAA6B,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,IAAI,CAgBzE;AAED;;;;;;;;6CAQ6C;AAC7C,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,IAAI,CAwC9D"}
|
|
@@ -20,6 +20,7 @@ exports.gradeBindParams = gradeBindParams;
|
|
|
20
20
|
exports.toGradeRow = toGradeRow;
|
|
21
21
|
exports.backfillGradesFromFeedback = backfillGradesFromFeedback;
|
|
22
22
|
exports.backfillGradesFromEvaluations = backfillGradesFromEvaluations;
|
|
23
|
+
exports.migrateGradesToV17 = migrateGradesToV17;
|
|
23
24
|
/** `CREATE TABLE IF NOT EXISTS grades …` — safe to run on every open. Mirrors
|
|
24
25
|
* `public.grades` minus the export-stamped columns (org handling below). */
|
|
25
26
|
exports.GRADES_TABLE_SQL = `
|
|
@@ -32,22 +33,24 @@ CREATE TABLE IF NOT EXISTS grades (
|
|
|
32
33
|
scale_max REAL,
|
|
33
34
|
scale_label TEXT,
|
|
34
35
|
comment TEXT,
|
|
35
|
-
kind TEXT NOT NULL CHECK (kind IN ('human','model-judge','deterministic')),
|
|
36
|
+
kind TEXT NOT NULL CHECK (kind IN ('human','model-judge','deterministic','outcome')),
|
|
36
37
|
grader TEXT,
|
|
37
38
|
source TEXT,
|
|
38
39
|
org_id TEXT,
|
|
39
40
|
created_by TEXT,
|
|
40
|
-
criteria TEXT
|
|
41
|
+
criteria TEXT,
|
|
42
|
+
value REAL,
|
|
43
|
+
idempotency_key TEXT
|
|
41
44
|
);
|
|
42
45
|
CREATE INDEX IF NOT EXISTS idx_grades_subject ON grades (subject_kind, subject_id);
|
|
43
46
|
`;
|
|
44
47
|
const INSERT_GRADE_SQL = `
|
|
45
48
|
INSERT OR IGNORE INTO grades (
|
|
46
49
|
id, ts, subject_kind, subject_id, score, scale_max, scale_label, comment,
|
|
47
|
-
kind, grader, source, org_id, created_by, criteria
|
|
50
|
+
kind, grader, source, org_id, created_by, criteria, value, idempotency_key
|
|
48
51
|
) VALUES (
|
|
49
52
|
@id, @ts, @subject_kind, @subject_id, @score, @scale_max, @scale_label, @comment,
|
|
50
|
-
@kind, @grader, @source, @org_id, @created_by, @criteria
|
|
53
|
+
@kind, @grader, @source, @org_id, @created_by, @criteria, @value, @idempotency_key
|
|
51
54
|
)`;
|
|
52
55
|
/** Prepare the grade insert statement against an open handle. INSERT OR IGNORE:
|
|
53
56
|
* a grade id is unique, and a re-inserted id (e.g. the backfill racing a live
|
|
@@ -75,6 +78,8 @@ function gradeBindParams(row) {
|
|
|
75
78
|
// single-score grade). One column, no sidecar table locally — the server is
|
|
76
79
|
// where it fans out to `grade_criteria`.
|
|
77
80
|
criteria: row.criteria !== undefined ? JSON.stringify(row.criteria) : null,
|
|
81
|
+
value: row.value ?? null,
|
|
82
|
+
idempotency_key: row.idempotencyKey ?? null,
|
|
78
83
|
};
|
|
79
84
|
}
|
|
80
85
|
/** Read one SQLite grade row back into a GradeRow. */
|
|
@@ -98,6 +103,10 @@ function toGradeRow(r) {
|
|
|
98
103
|
// byte-identical for a plain grade. A malformed value degrades to absent
|
|
99
104
|
// rather than throwing on the export read.
|
|
100
105
|
...parseCriteriaColumn(r.criteria),
|
|
106
|
+
// ARC-3: spread-iff — a null value (every non-outcome grade) leaves the field
|
|
107
|
+
// ABSENT so the exported wire stays byte-identical for a plain grade.
|
|
108
|
+
...(r.value !== null && r.value !== undefined ? { value: r.value } : {}),
|
|
109
|
+
...(typeof r.idempotency_key === "string" ? { idempotencyKey: r.idempotency_key } : {}),
|
|
101
110
|
};
|
|
102
111
|
}
|
|
103
112
|
/** Narrow the stored JSON `criteria` column to a spread-iff-present GradeRow
|
|
@@ -154,3 +163,54 @@ function backfillGradesFromEvaluations(db) {
|
|
|
154
163
|
WHERE COALESCE(e.artifact_id, e.run_id) IS NOT NULL
|
|
155
164
|
`);
|
|
156
165
|
}
|
|
166
|
+
/** v17 (ARC-3, mirrors 00089): widen the local `grades.kind` CHECK with
|
|
167
|
+
* `'outcome'` and add the nullable `value` column. SQLite cannot ALTER a CHECK,
|
|
168
|
+
* so a table whose stored DDL lacks `'outcome'` is REBUILT into the current
|
|
169
|
+
* shape (= GRADES_TABLE_SQL) with every column AND the rowid copied (the v15
|
|
170
|
+
* pattern, plus rowid preservation so the exporter's `:grades` rowid watermark
|
|
171
|
+
* neither re-exports nor skips a row); a table
|
|
172
|
+
* that already allows it only gains `value` if absent. Idempotent: guarded on
|
|
173
|
+
* the stored DDL + `table_info`, so a re-open no-ops. No grades table ⇒ no-op
|
|
174
|
+
* (SCHEMA_SQL creates the current shape). */
|
|
175
|
+
function migrateGradesToV17(db) {
|
|
176
|
+
const cols = db.prepare("PRAGMA table_info(grades)").all();
|
|
177
|
+
if (cols.length === 0)
|
|
178
|
+
return;
|
|
179
|
+
const ddl = db.prepare("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'grades'").get()?.sql ?? "";
|
|
180
|
+
if (ddl.includes("'outcome'")) {
|
|
181
|
+
if (!cols.some((c) => c.name === "value"))
|
|
182
|
+
db.exec("ALTER TABLE grades ADD COLUMN value REAL");
|
|
183
|
+
if (!cols.some((c) => c.name === "idempotency_key"))
|
|
184
|
+
db.exec("ALTER TABLE grades ADD COLUMN idempotency_key TEXT");
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
const hasCriteria = cols.some((c) => c.name === "criteria");
|
|
188
|
+
const copied = "id, ts, subject_kind, subject_id, score, scale_max, scale_label, comment, kind, grader, source, org_id, created_by";
|
|
189
|
+
// L7: ONE transaction — a crash mid-rebuild rolls back to the intact v16 table
|
|
190
|
+
// (never a dropped `grades` with the rows stranded in grades_v17).
|
|
191
|
+
db.transaction(() => db.exec(`
|
|
192
|
+
CREATE TABLE grades_v17 (
|
|
193
|
+
id TEXT PRIMARY KEY,
|
|
194
|
+
ts TEXT,
|
|
195
|
+
subject_kind TEXT NOT NULL CHECK (subject_kind IN ('inference','run','artifact')),
|
|
196
|
+
subject_id TEXT NOT NULL,
|
|
197
|
+
score REAL NOT NULL,
|
|
198
|
+
scale_max REAL,
|
|
199
|
+
scale_label TEXT,
|
|
200
|
+
comment TEXT,
|
|
201
|
+
kind TEXT NOT NULL CHECK (kind IN ('human','model-judge','deterministic','outcome')),
|
|
202
|
+
grader TEXT,
|
|
203
|
+
source TEXT,
|
|
204
|
+
org_id TEXT,
|
|
205
|
+
created_by TEXT,
|
|
206
|
+
criteria TEXT,
|
|
207
|
+
value REAL,
|
|
208
|
+
idempotency_key TEXT
|
|
209
|
+
);
|
|
210
|
+
INSERT OR IGNORE INTO grades_v17 (rowid, ${copied}${hasCriteria ? ", criteria" : ""})
|
|
211
|
+
SELECT rowid, ${copied}${hasCriteria ? ", criteria" : ""} FROM grades ORDER BY rowid;
|
|
212
|
+
DROP TABLE grades;
|
|
213
|
+
ALTER TABLE grades_v17 RENAME TO grades;
|
|
214
|
+
CREATE INDEX IF NOT EXISTS idx_grades_subject ON grades (subject_kind, subject_id);
|
|
215
|
+
`))();
|
|
216
|
+
}
|
|
@@ -123,7 +123,7 @@ export interface WireGrade {
|
|
|
123
123
|
readonly scale_max: number | null;
|
|
124
124
|
readonly scale_label: string | null;
|
|
125
125
|
readonly comment: string | null;
|
|
126
|
-
readonly kind: "human" | "model-judge" | "deterministic";
|
|
126
|
+
readonly kind: "human" | "model-judge" | "deterministic" | "outcome";
|
|
127
127
|
readonly grader: string | null;
|
|
128
128
|
readonly source: string | null;
|
|
129
129
|
readonly created_by: string | null;
|
|
@@ -144,6 +144,14 @@ export interface WireGrade {
|
|
|
144
144
|
}[];
|
|
145
145
|
readonly comment?: string;
|
|
146
146
|
}[];
|
|
147
|
+
/** ARC-3 (00089): the raw business value of an OUTCOME grade. Carried
|
|
148
|
+
* spread-iff-present (only `kind: "outcome"` rows), so every other grade's
|
|
149
|
+
* wire shape is byte-identical to pre-ARC; the server refuses it on any other
|
|
150
|
+
* kind and refuses outcome rows entirely until 00089 is applied (503). */
|
|
151
|
+
readonly value?: number | null;
|
|
152
|
+
/** ARC-3 L3: an outcome's idempotency key — the server re-derives the grade id
|
|
153
|
+
* as outcomeGradeId(key org, name, idempotency_key). Never written to a column. */
|
|
154
|
+
readonly idempotency_key?: string;
|
|
147
155
|
}
|
|
148
156
|
export interface WireEnvelope {
|
|
149
157
|
readonly envelope_key: string;
|
|
@@ -330,6 +338,21 @@ export interface StampOptions {
|
|
|
330
338
|
readonly declaredBundles?: boolean;
|
|
331
339
|
}
|
|
332
340
|
export declare function stampBatch(batch: IngestBatch, tenancy: Tenancy, opts?: StampOptions): TableWrite[];
|
|
341
|
+
/**
|
|
342
|
+
* GRADE-RAW (grade-ux-plan §1 item 1): the step-task registration write for a
|
|
343
|
+
* batch — a raw-lane or recorded call that names a step (`tags.step`) registers
|
|
344
|
+
* that step as a task, so a grading guide can be written for it. Or null when
|
|
345
|
+
* the batch names no step.
|
|
346
|
+
*
|
|
347
|
+
* DELIBERATELY NOT part of `stampBatch` (architect S2-1): it is a BEST-EFFORT
|
|
348
|
+
* write both sinks issue only AFTER the batch's rows are confirmed, with any
|
|
349
|
+
* error swallowed — a refused registration must never turn a batch of
|
|
350
|
+
* inferences into a poison-skipped 422. merge=false (ignore-duplicates on the
|
|
351
|
+
* PK): it never rewrites an existing row (a route-synced task, or a step's
|
|
352
|
+
* settings/guide); a retry is a no-op. Tenant from the PRINCIPAL only (T3).
|
|
353
|
+
* Capped per batch (registrableStepTasks).
|
|
354
|
+
*/
|
|
355
|
+
export declare function stepTaskRegistration(batch: IngestBatch, tenancy: Tenancy): TableWrite | null;
|
|
333
356
|
/** What `/v1/ingest` answers. Counts only — a per-row error list on a
|
|
334
357
|
* fire-and-forget telemetry path is a payload nobody reads and a leak surface
|
|
335
358
|
* nobody audits. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ingest-protocol.d.ts","sourceRoot":"","sources":["../../src/telemetry/ingest-protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"ingest-protocol.d.ts","sourceRoot":"","sources":["../../src/telemetry/ingest-protocol.ts"],"names":[],"mappings":"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"}
|
|
@@ -34,8 +34,11 @@
|
|
|
34
34
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
35
35
|
exports.DEFAULT_INGEST_URL = exports.INGEST_PROTOCOL_VERSION_V1 = exports.INGEST_PROTOCOL_VERSION = exports.INGEST_PATH = exports.foreignOrgGrades = void 0;
|
|
36
36
|
exports.stampBatch = stampBatch;
|
|
37
|
+
exports.stepTaskRegistration = stepTaskRegistration;
|
|
37
38
|
const fingerprint_1 = require("../registry/fingerprint");
|
|
38
39
|
const grade_mappers_1 = require("./grade-mappers");
|
|
40
|
+
const uniform_rows_1 = require("./uniform-rows");
|
|
41
|
+
const grade_task_1 = require("./grade-task");
|
|
39
42
|
var grade_mappers_2 = require("./grade-mappers");
|
|
40
43
|
Object.defineProperty(exports, "foreignOrgGrades", { enumerable: true, get: function () { return grade_mappers_2.foreignOrgGrades; } });
|
|
41
44
|
/** The path the api sink posts to. Spelled once. */
|
|
@@ -88,14 +91,13 @@ function stampBatch(batch, tenancy, opts = {}) {
|
|
|
88
91
|
}
|
|
89
92
|
taskRows.push(taskRow);
|
|
90
93
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
merge: true,
|
|
97
|
-
|
|
98
|
-
});
|
|
94
|
+
// merge=true: a task row is a mutable projection of the latest sync, like
|
|
95
|
+
// the routes mirror, unlike inferences. onConflict on the PK (S5). Split by
|
|
96
|
+
// key set (COV-1c, PGRST102): a bundle-less task row must neither fail nor
|
|
97
|
+
// null out its bundled neighbours' schema columns.
|
|
98
|
+
for (const group of (0, uniform_rows_1.splitByKeySet)(taskRows)) {
|
|
99
|
+
writes.push({ table: "tasks", onConflict: "org_id,task", merge: true, rows: group });
|
|
100
|
+
}
|
|
99
101
|
const routeRow = (r) => ({
|
|
100
102
|
org_id: tenancy.org_id,
|
|
101
103
|
route: r.route,
|
|
@@ -130,31 +132,31 @@ function stampBatch(batch, tenancy, opts = {}) {
|
|
|
130
132
|
}
|
|
131
133
|
}
|
|
132
134
|
if (batch.runs !== undefined && batch.runs.length > 0) {
|
|
133
|
-
|
|
134
|
-
//
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
})
|
|
157
|
-
}
|
|
135
|
+
const runRows = batch.runs.map((r) => ({
|
|
136
|
+
// Field-by-field from the principal's tenancy — org_id and source_id are
|
|
137
|
+
// NEVER carried on the wire (T3). source_id identifies the rig instance,
|
|
138
|
+
// exactly like inferences.
|
|
139
|
+
org_id: tenancy.org_id,
|
|
140
|
+
id: r.id,
|
|
141
|
+
source_id: tenancy.source_id,
|
|
142
|
+
pipeline: r.pipeline,
|
|
143
|
+
pipeline_version: r.pipeline_version,
|
|
144
|
+
environment: r.environment,
|
|
145
|
+
episode_key: r.episode_key,
|
|
146
|
+
started_at: r.started_at,
|
|
147
|
+
ended_at: r.ended_at,
|
|
148
|
+
status: r.status,
|
|
149
|
+
updated_at: now,
|
|
150
|
+
// WI-1 (spec §3): the run metadata envelope. spread-iff-present (the
|
|
151
|
+
// 00027 pattern) — a run without `meta` leaves runs.meta untouched.
|
|
152
|
+
...(r.meta !== undefined && r.meta !== null ? { meta: r.meta } : {}),
|
|
153
|
+
}));
|
|
154
|
+
// runs are a mutable projection (start → end): merge=true on the PK (S5).
|
|
155
|
+
// Split by key set (COV-1c, PGRST102): a meta-less run row must not fail,
|
|
156
|
+
// or null out, a neighbour's meta.
|
|
157
|
+
for (const group of (0, uniform_rows_1.splitByKeySet)(runRows)) {
|
|
158
|
+
writes.push({ table: "runs", onConflict: "org_id,id", merge: true, rows: group });
|
|
159
|
+
}
|
|
158
160
|
}
|
|
159
161
|
if (batch.steps !== undefined && batch.steps.length > 0) {
|
|
160
162
|
writes.push({
|
|
@@ -163,7 +165,8 @@ function stampBatch(batch, tenancy, opts = {}) {
|
|
|
163
165
|
table: "steps",
|
|
164
166
|
onConflict: "org_id,run_id,step_key,attempt_no",
|
|
165
167
|
merge: false,
|
|
166
|
-
|
|
168
|
+
// fillNulls (COV-1c, PGRST102): merge=false, so a null never rewrites a row.
|
|
169
|
+
rows: (0, uniform_rows_1.fillNulls)(batch.steps.map((s) => ({
|
|
167
170
|
org_id: tenancy.org_id,
|
|
168
171
|
run_id: s.run_id,
|
|
169
172
|
step_key: s.step_key,
|
|
@@ -185,7 +188,7 @@ function stampBatch(batch, tenancy, opts = {}) {
|
|
|
185
188
|
// ground-truth step carries no `attested`, so the column stays null and
|
|
186
189
|
// the 00038 CHECK holds. An SDK batch never sets it → byte-identical.
|
|
187
190
|
...(s.attested !== undefined ? { attested: s.attested } : {}),
|
|
188
|
-
})),
|
|
191
|
+
})), ["attested"]),
|
|
189
192
|
});
|
|
190
193
|
}
|
|
191
194
|
if (batch.artifacts !== undefined && batch.artifacts.length > 0) {
|
|
@@ -193,7 +196,7 @@ function stampBatch(batch, tenancy, opts = {}) {
|
|
|
193
196
|
table: "artifacts",
|
|
194
197
|
onConflict: "org_id,id",
|
|
195
198
|
merge: false, // an artifact metadata row is a fact; a retry must not rewrite it
|
|
196
|
-
rows: batch.artifacts.map((a) => ({
|
|
199
|
+
rows: (0, uniform_rows_1.fillNulls)(batch.artifacts.map((a) => ({
|
|
197
200
|
org_id: tenancy.org_id,
|
|
198
201
|
id: a.id,
|
|
199
202
|
run_id: a.run_id,
|
|
@@ -214,7 +217,7 @@ function stampBatch(batch, tenancy, opts = {}) {
|
|
|
214
217
|
// spread-iff-present (00027 pattern): a batch without `scrub` (older SDK,
|
|
215
218
|
// custody off) leaves the column null rather than overwriting it.
|
|
216
219
|
...(a.scrub !== undefined ? { scrub: a.scrub } : {}),
|
|
217
|
-
})),
|
|
220
|
+
})), ["scrub"]),
|
|
218
221
|
});
|
|
219
222
|
}
|
|
220
223
|
if (batch.artifact_edges !== undefined && batch.artifact_edges.length > 0) {
|
|
@@ -280,12 +283,11 @@ function stampBatch(batch, tenancy, opts = {}) {
|
|
|
280
283
|
// An inference is a fact that happened. A retry must not be able to
|
|
281
284
|
// rewrite it — idempotent by doing nothing, not by overwriting.
|
|
282
285
|
merge: false,
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
})),
|
|
286
|
+
// ONE key set for every row (COV-1c): a PostgREST bulk insert 400s with
|
|
287
|
+
// PGRST102 when keys differ — a web-search surcharge row (meta: null)
|
|
288
|
+
// beside metered rows (meta set) used to drop the whole batch. merge=false
|
|
289
|
+
// makes writing absent columns as their defaults safe.
|
|
290
|
+
rows: batch.inferences.map((row) => (0, uniform_rows_1.normalizeInferenceRow)(row, tenancy)),
|
|
289
291
|
});
|
|
290
292
|
}
|
|
291
293
|
if (batch.watermarkAt !== undefined) {
|
|
@@ -329,3 +331,30 @@ function stampBatch(batch, tenancy, opts = {}) {
|
|
|
329
331
|
}
|
|
330
332
|
return writes;
|
|
331
333
|
}
|
|
334
|
+
/**
|
|
335
|
+
* GRADE-RAW (grade-ux-plan §1 item 1): the step-task registration write for a
|
|
336
|
+
* batch — a raw-lane or recorded call that names a step (`tags.step`) registers
|
|
337
|
+
* that step as a task, so a grading guide can be written for it. Or null when
|
|
338
|
+
* the batch names no step.
|
|
339
|
+
*
|
|
340
|
+
* DELIBERATELY NOT part of `stampBatch` (architect S2-1): it is a BEST-EFFORT
|
|
341
|
+
* write both sinks issue only AFTER the batch's rows are confirmed, with any
|
|
342
|
+
* error swallowed — a refused registration must never turn a batch of
|
|
343
|
+
* inferences into a poison-skipped 422. merge=false (ignore-duplicates on the
|
|
344
|
+
* PK): it never rewrites an existing row (a route-synced task, or a step's
|
|
345
|
+
* settings/guide); a retry is a no-op. Tenant from the PRINCIPAL only (T3).
|
|
346
|
+
* Capped per batch (registrableStepTasks).
|
|
347
|
+
*/
|
|
348
|
+
function stepTaskRegistration(batch, tenancy) {
|
|
349
|
+
if (batch.inferences === undefined || batch.inferences.length === 0)
|
|
350
|
+
return null;
|
|
351
|
+
const steps = (0, grade_task_1.registrableStepTasks)(batch.inferences);
|
|
352
|
+
if (steps.length === 0)
|
|
353
|
+
return null;
|
|
354
|
+
return {
|
|
355
|
+
table: "tasks",
|
|
356
|
+
onConflict: "org_id,task",
|
|
357
|
+
merge: false,
|
|
358
|
+
rows: steps.map((task) => ({ org_id: tenancy.org_id, task, source: "registered" })),
|
|
359
|
+
};
|
|
360
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ARC-6 / ARC-D6 — OTLP content extraction, GATED. M14 is UNRULED, so this
|
|
3
|
+
* ships OFF: the server calls it ONLY when its feature gate is on AND the org's
|
|
4
|
+
* capture posture is `managed` (modelrig-server otlp-content.ts). With the gate
|
|
5
|
+
* off nothing here runs, and the normalizer (otel-normalize.ts) keeps its STOP
|
|
6
|
+
* invariant: zero content read.
|
|
7
|
+
*
|
|
8
|
+
* When it does run: for each GENERATION span (operation class `generation`) it
|
|
9
|
+
* reads the gen_ai input/output message attributes as TEXT — string-valued
|
|
10
|
+
* only (kvlist/bytes are never decoded) — across the vintages:
|
|
11
|
+
* input: gen_ai.input.messages · gen_ai.prompt (deprecated) ·
|
|
12
|
+
* ai.prompt.messages · ai.prompt (Vercel AI SDK)
|
|
13
|
+
* output: gen_ai.output.messages · gen_ai.completion (deprecated) ·
|
|
14
|
+
* ai.response.text (Vercel AI SDK)
|
|
15
|
+
* The first present attribute per role wins. Pure; scrub + custody are the
|
|
16
|
+
* server's (the same scrub the import path uses, then the custody store).
|
|
17
|
+
*/
|
|
18
|
+
export declare const CONTENT_INPUT_CHAIN: readonly ["gen_ai.input.messages", "gen_ai.prompt", "ai.prompt.messages", "ai.prompt"];
|
|
19
|
+
export declare const CONTENT_OUTPUT_CHAIN: readonly ["gen_ai.output.messages", "gen_ai.completion", "ai.response.text"];
|
|
20
|
+
export interface ExtractedContent {
|
|
21
|
+
/** Lowercase hex trace + span id (the attested step's identity). */
|
|
22
|
+
readonly traceId: string;
|
|
23
|
+
readonly spanId: string;
|
|
24
|
+
readonly role: "input" | "output";
|
|
25
|
+
/** Which attribute it came from. */
|
|
26
|
+
readonly attribute: string;
|
|
27
|
+
readonly text: string;
|
|
28
|
+
}
|
|
29
|
+
/** Extract generation-span message text from a decoded TracesData body. */
|
|
30
|
+
export declare function extractGenerationContent(data: unknown): ExtractedContent[];
|
|
31
|
+
//# sourceMappingURL=otel-content.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"otel-content.d.ts","sourceRoot":"","sources":["../../src/telemetry/otel-content.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,eAAO,MAAM,mBAAmB,wFAAyF,CAAC;AAC1H,eAAO,MAAM,oBAAoB,8EAA+E,CAAC;AAEjH,MAAM,WAAW,gBAAgB;IAC/B,oEAAoE;IACpE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAC;IAClC,oCAAoC;IACpC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AA+CD,2EAA2E;AAC3E,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,OAAO,GAAG,gBAAgB,EAAE,CAwB1E"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ARC-6 / ARC-D6 — OTLP content extraction, GATED. M14 is UNRULED, so this
|
|
4
|
+
* ships OFF: the server calls it ONLY when its feature gate is on AND the org's
|
|
5
|
+
* capture posture is `managed` (modelrig-server otlp-content.ts). With the gate
|
|
6
|
+
* off nothing here runs, and the normalizer (otel-normalize.ts) keeps its STOP
|
|
7
|
+
* invariant: zero content read.
|
|
8
|
+
*
|
|
9
|
+
* When it does run: for each GENERATION span (operation class `generation`) it
|
|
10
|
+
* reads the gen_ai input/output message attributes as TEXT — string-valued
|
|
11
|
+
* only (kvlist/bytes are never decoded) — across the vintages:
|
|
12
|
+
* input: gen_ai.input.messages · gen_ai.prompt (deprecated) ·
|
|
13
|
+
* ai.prompt.messages · ai.prompt (Vercel AI SDK)
|
|
14
|
+
* output: gen_ai.output.messages · gen_ai.completion (deprecated) ·
|
|
15
|
+
* ai.response.text (Vercel AI SDK)
|
|
16
|
+
* The first present attribute per role wins. Pure; scrub + custody are the
|
|
17
|
+
* server's (the same scrub the import path uses, then the custody store).
|
|
18
|
+
*/
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.CONTENT_OUTPUT_CHAIN = exports.CONTENT_INPUT_CHAIN = void 0;
|
|
21
|
+
exports.extractGenerationContent = extractGenerationContent;
|
|
22
|
+
const otel_hierarchy_1 = require("./otel-hierarchy");
|
|
23
|
+
exports.CONTENT_INPUT_CHAIN = ["gen_ai.input.messages", "gen_ai.prompt", "ai.prompt.messages", "ai.prompt"];
|
|
24
|
+
exports.CONTENT_OUTPUT_CHAIN = ["gen_ai.output.messages", "gen_ai.completion", "ai.response.text"];
|
|
25
|
+
const isRec = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
26
|
+
const HEX = /^[0-9a-fA-F]+$/;
|
|
27
|
+
function hexId(v, bytes) {
|
|
28
|
+
if (typeof v === "string" && HEX.test(v) && v.length === bytes * 2 && !/^0+$/.test(v))
|
|
29
|
+
return v.toLowerCase();
|
|
30
|
+
if (typeof v === "string" && /^[A-Za-z0-9+/]+={0,2}$/.test(v)) {
|
|
31
|
+
const hex = Buffer.from(v, "base64").toString("hex");
|
|
32
|
+
if (hex.length === bytes * 2 && !/^0+$/.test(hex))
|
|
33
|
+
return hex;
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
/** String attributes only — content shapes (kvlist/bytes) are never decoded. */
|
|
38
|
+
function stringAttrs(attributes) {
|
|
39
|
+
const out = new Map();
|
|
40
|
+
for (const kv of Array.isArray(attributes) ? attributes : []) {
|
|
41
|
+
if (!isRec(kv) || typeof kv.key !== "string" || !isRec(kv.value))
|
|
42
|
+
continue;
|
|
43
|
+
const s = kv.value.stringValue;
|
|
44
|
+
if (typeof s === "string" && s !== "")
|
|
45
|
+
out.set(kv.key, s);
|
|
46
|
+
}
|
|
47
|
+
return out;
|
|
48
|
+
}
|
|
49
|
+
/** The raw operation the normalizer would classify — the same priority. */
|
|
50
|
+
function operationOf(attrs) {
|
|
51
|
+
const oi = attrs.get("openinference.span.kind");
|
|
52
|
+
if (oi !== undefined)
|
|
53
|
+
return oi.toLowerCase();
|
|
54
|
+
const op = attrs.get("gen_ai.operation.name");
|
|
55
|
+
if (op !== undefined)
|
|
56
|
+
return op;
|
|
57
|
+
if (attrs.has("gen_ai.tool.name") || attrs.has("tool.name"))
|
|
58
|
+
return "execute_tool";
|
|
59
|
+
for (const k of ["gen_ai.response.model", "ai.model.id", "gen_ai.request.model", "llm.response.model", "llm.model_name", "model"]) {
|
|
60
|
+
if (attrs.has(k))
|
|
61
|
+
return "chat";
|
|
62
|
+
}
|
|
63
|
+
return "span";
|
|
64
|
+
}
|
|
65
|
+
function first(attrs, chain) {
|
|
66
|
+
for (const k of chain) {
|
|
67
|
+
const v = attrs.get(k);
|
|
68
|
+
if (v !== undefined)
|
|
69
|
+
return [k, v];
|
|
70
|
+
}
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
/** Extract generation-span message text from a decoded TracesData body. */
|
|
74
|
+
function extractGenerationContent(data) {
|
|
75
|
+
const out = [];
|
|
76
|
+
if (!isRec(data))
|
|
77
|
+
return out;
|
|
78
|
+
const rsList = data.resourceSpans ?? data.resource_spans;
|
|
79
|
+
for (const rs of Array.isArray(rsList) ? rsList : []) {
|
|
80
|
+
if (!isRec(rs))
|
|
81
|
+
continue;
|
|
82
|
+
const ssList = rs.scopeSpans ?? rs.scope_spans;
|
|
83
|
+
for (const ss of Array.isArray(ssList) ? ssList : []) {
|
|
84
|
+
if (!isRec(ss))
|
|
85
|
+
continue;
|
|
86
|
+
for (const span of Array.isArray(ss.spans) ? ss.spans : []) {
|
|
87
|
+
if (!isRec(span))
|
|
88
|
+
continue;
|
|
89
|
+
const traceId = hexId(span.traceId ?? span.trace_id, 16);
|
|
90
|
+
const spanId = hexId(span.spanId ?? span.span_id, 8);
|
|
91
|
+
if (traceId === null || spanId === null)
|
|
92
|
+
continue;
|
|
93
|
+
const attrs = stringAttrs(span.attributes);
|
|
94
|
+
if ((0, otel_hierarchy_1.operationClassOf)(operationOf(attrs)) !== "generation")
|
|
95
|
+
continue;
|
|
96
|
+
const input = first(attrs, exports.CONTENT_INPUT_CHAIN);
|
|
97
|
+
const output = first(attrs, exports.CONTENT_OUTPUT_CHAIN);
|
|
98
|
+
if (input !== null)
|
|
99
|
+
out.push({ traceId, spanId, role: "input", attribute: input[0], text: input[1] });
|
|
100
|
+
if (output !== null)
|
|
101
|
+
out.push({ traceId, spanId, role: "output", attribute: output[0], text: output[1] });
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return out;
|
|
106
|
+
}
|