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 @@
|
|
|
1
|
+
{"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../../src/artifacts/conversation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ARC-1 — conversations as runs: `rig.conversation(id, { agent, user?, tenant? })`.
|
|
4
|
+
*
|
|
5
|
+
* A conversation (support chat, sales thread, agent task loop) is ONE `runs`
|
|
6
|
+
* row: `pipeline = agent`, `episode_key = <your conversation id>`,
|
|
7
|
+
* `meta.trigger = "conversation"`. Each turn is a set of `steps` in that run.
|
|
8
|
+
* No new table (ARC-D1). The returned handle IS the run handle `run.start`
|
|
9
|
+
* returns (`runId`, `end`), plus `turn(fn)` and the conversation id.
|
|
10
|
+
*
|
|
11
|
+
* ── TURN STEPS — THE RULE ─────────────────────────────────────────────────
|
|
12
|
+
* - `conversation.turn(fn)` opens turn n+1 (n starts at 0 — or, on re-entry,
|
|
13
|
+
* at the highest turn already recorded for this run) and every `rig.run` /
|
|
14
|
+
* `rig.runRaw` / `rig.recordCall` inside `fn` records under step key
|
|
15
|
+
* `turn:<n>.<k>`, where k = 1, 2, … is the call's index WITHIN the turn.
|
|
16
|
+
* (Why `.k`: a repeated step key inside one run is read as a RETRY — the
|
|
17
|
+
* context bumps `attempt_no` for the same key — so two calls in one turn
|
|
18
|
+
* must not share `turn:<n>`. `turn:<n>.<k>` keeps every call its own step
|
|
19
|
+
* while the turn number stays the prefix every reader groups on.)
|
|
20
|
+
* - A call made on the conversation OUTSIDE any `turn()` attaches to the
|
|
21
|
+
* CURRENT turn (turn 1 if none was opened yet).
|
|
22
|
+
* - An explicit `stepKey` (or `tags.step`) from the caller always wins — the
|
|
23
|
+
* turn rule only replaces the auto-minted key.
|
|
24
|
+
* - Retries/fallbacks of ONE call reuse its key (attempt_no distinguishes them).
|
|
25
|
+
*
|
|
26
|
+
* ── RE-ENTRY ──────────────────────────────────────────────────────────────
|
|
27
|
+
* A later request with the same `(agent, id)` re-enters the open run instead of
|
|
28
|
+
* starting a new one: first this process's open conversations, then the LOCAL
|
|
29
|
+
* store's newest `running` run for `(agent, id)` (so a restarted worker
|
|
30
|
+
* continues the run and its turn numbering). Cross-process re-entry (another
|
|
31
|
+
* HTTP worker with its own store) is OUT OF SCOPE for the SDK: a race or a
|
|
32
|
+
* second worker produces a second run with the same episode_key, which 00031
|
|
33
|
+
* already tolerates and the console groups by conversation id. Pin with the
|
|
34
|
+
* returned `runId` if you need one run.
|
|
35
|
+
*
|
|
36
|
+
* ── CLOSING ───────────────────────────────────────────────────────────────
|
|
37
|
+
* `conversation.end(status = "succeeded")`. Conversations rarely end cleanly, so
|
|
38
|
+
* the server's idle sweep (`conversation-idle-close`) also closes `running`
|
|
39
|
+
* conversations idle past the org's `idle_close_minutes` (default 30).
|
|
40
|
+
*
|
|
41
|
+
* ── CONCURRENCY ───────────────────────────────────────────────────────────
|
|
42
|
+
* `rig.conversation()` makes the run ambient on the current async path (like
|
|
43
|
+
* `run.start`, via `enterWith`). `turn(fn)` runs `fn` inside its OWN scope
|
|
44
|
+
* (`AsyncLocalStorage.run`), so overlapping turns of DIFFERENT conversations in
|
|
45
|
+
* one process never cross-attribute.
|
|
46
|
+
*
|
|
47
|
+
* Inert (a pass-through `turn`, no rows) when the run namespace is disabled.
|
|
48
|
+
*/
|
|
49
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
50
|
+
exports.TurnCounter = exports.TURN_STEP_PREFIX = void 0;
|
|
51
|
+
exports.turnStepKey = turnStepKey;
|
|
52
|
+
exports.turnNumberOf = turnNumberOf;
|
|
53
|
+
exports.maxTurnOf = maxTurnOf;
|
|
54
|
+
exports.turnStateOf = turnStateOf;
|
|
55
|
+
exports.conversationTags = conversationTags;
|
|
56
|
+
exports.createConversation = createConversation;
|
|
57
|
+
/** The step-key prefix of a conversation turn. */
|
|
58
|
+
exports.TURN_STEP_PREFIX = "turn:";
|
|
59
|
+
/** `turn:<n>.<k>` — turn n, k-th call within it. */
|
|
60
|
+
function turnStepKey(turn, call) {
|
|
61
|
+
return `${exports.TURN_STEP_PREFIX}${turn}.${call}`;
|
|
62
|
+
}
|
|
63
|
+
const TURN_KEY_RE = /^turn:(\d+)(?:\.(\d+))?$/;
|
|
64
|
+
/** The turn number a step key belongs to, or null when it is not a turn key.
|
|
65
|
+
* Accepts `turn:<n>` (an explicit caller key) and `turn:<n>.<k>`. */
|
|
66
|
+
function turnNumberOf(stepKey) {
|
|
67
|
+
const m = TURN_KEY_RE.exec(stepKey);
|
|
68
|
+
return m === null ? null : Number(m[1]);
|
|
69
|
+
}
|
|
70
|
+
/** The highest turn among recorded step keys (0 when none). */
|
|
71
|
+
function maxTurnOf(stepKeys) {
|
|
72
|
+
let max = 0;
|
|
73
|
+
for (const k of stepKeys) {
|
|
74
|
+
const n = turnNumberOf(k);
|
|
75
|
+
if (n !== null && n > max)
|
|
76
|
+
max = n;
|
|
77
|
+
}
|
|
78
|
+
return max;
|
|
79
|
+
}
|
|
80
|
+
/** The highest turn AND the highest call index within it — the counter seed on
|
|
81
|
+
* re-entry, so a call that attaches to the current turn never reuses a recorded
|
|
82
|
+
* `turn:<n>.<k>` key (a reused key would read as a retry). */
|
|
83
|
+
function turnStateOf(stepKeys) {
|
|
84
|
+
let turn = 0;
|
|
85
|
+
let call = 0;
|
|
86
|
+
for (const k of stepKeys) {
|
|
87
|
+
const m = TURN_KEY_RE.exec(k);
|
|
88
|
+
if (m === null)
|
|
89
|
+
continue;
|
|
90
|
+
const n = Number(m[1]);
|
|
91
|
+
const c = m[2] !== undefined ? Number(m[2]) : 0;
|
|
92
|
+
if (n > turn) {
|
|
93
|
+
turn = n;
|
|
94
|
+
call = c;
|
|
95
|
+
}
|
|
96
|
+
else if (n === turn && c > call) {
|
|
97
|
+
call = c;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return { turn, call };
|
|
101
|
+
}
|
|
102
|
+
/** Per-conversation turn bookkeeping: which turn is current and the next call
|
|
103
|
+
* index within it. Pure; one per conversation context. */
|
|
104
|
+
class TurnCounter {
|
|
105
|
+
/** Seed from a re-entered run: the current turn and its highest call index. */
|
|
106
|
+
constructor(startAfterTurn = 0, startAfterCall = 0) {
|
|
107
|
+
this.turnNo = startAfterTurn;
|
|
108
|
+
this.callNo = startAfterTurn === 0 ? 0 : startAfterCall;
|
|
109
|
+
}
|
|
110
|
+
/** Open the next turn; returns its number. */
|
|
111
|
+
open() {
|
|
112
|
+
this.turnNo += 1;
|
|
113
|
+
this.callNo = 0;
|
|
114
|
+
return this.turnNo;
|
|
115
|
+
}
|
|
116
|
+
/** The current turn (0 before any). */
|
|
117
|
+
current() {
|
|
118
|
+
return this.turnNo;
|
|
119
|
+
}
|
|
120
|
+
/** Mint the step key for the next call: the current turn (turn 1 if none was
|
|
121
|
+
* opened yet), next call index. */
|
|
122
|
+
mint() {
|
|
123
|
+
if (this.turnNo === 0)
|
|
124
|
+
this.open();
|
|
125
|
+
this.callNo += 1;
|
|
126
|
+
return turnStepKey(this.turnNo, this.callNo);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
exports.TurnCounter = TurnCounter;
|
|
130
|
+
/** The step tags a conversation stamps on every call (caller tags win). */
|
|
131
|
+
function conversationTags(opts) {
|
|
132
|
+
return {
|
|
133
|
+
...(opts.user !== undefined && opts.user !== "" ? { user: opts.user } : {}),
|
|
134
|
+
...(opts.tenant !== undefined && opts.tenant !== "" ? { subject: opts.tenant } : {}),
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
function inertConversation(id) {
|
|
138
|
+
return {
|
|
139
|
+
runId: "",
|
|
140
|
+
conversationId: id,
|
|
141
|
+
resumed: false,
|
|
142
|
+
currentTurn: () => 0,
|
|
143
|
+
turn: async (fn) => fn(),
|
|
144
|
+
end() { },
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
/** Build a conversation handle over a host. Bad `id`/`agent` is a caller bug and
|
|
148
|
+
* throws (like `buildGradeRow`); a disabled namespace is inert. */
|
|
149
|
+
function createConversation(host, id, opts) {
|
|
150
|
+
if (typeof id !== "string" || id.trim() === "" || id.length > 200) {
|
|
151
|
+
throw new Error("rig.conversation(id, …) needs your conversation id: a non-empty string of at most 200 characters");
|
|
152
|
+
}
|
|
153
|
+
if (typeof opts?.agent !== "string" || opts.agent.trim() === "") {
|
|
154
|
+
throw new Error("rig.conversation(id, { agent }) needs the agent name — it becomes the run's pipeline");
|
|
155
|
+
}
|
|
156
|
+
if (!host.enabled)
|
|
157
|
+
return inertConversation(id);
|
|
158
|
+
const { ctx, resumed } = host.openOrResume(id, opts);
|
|
159
|
+
host.enter(ctx);
|
|
160
|
+
const counter = host.counterOf(ctx);
|
|
161
|
+
return {
|
|
162
|
+
runId: host.runIdOf(ctx),
|
|
163
|
+
conversationId: id,
|
|
164
|
+
resumed,
|
|
165
|
+
currentTurn: () => counter.current(),
|
|
166
|
+
turn: (fn) => {
|
|
167
|
+
counter.open();
|
|
168
|
+
return host.runIn(ctx, async () => fn());
|
|
169
|
+
},
|
|
170
|
+
end: (status, endOpts) => host.end(ctx, status, endOpts),
|
|
171
|
+
};
|
|
172
|
+
}
|
|
@@ -11,7 +11,7 @@ import type { ArtifactContentConfig, ArtifactsConfig } from "../config";
|
|
|
11
11
|
import type { TaskSettingsResolver } from "../settings/task-settings";
|
|
12
12
|
import type { ArtifactStore } from "../telemetry/artifact-store";
|
|
13
13
|
export { getActiveRunContext, createRunNamespace } from "./run-context";
|
|
14
|
-
export type { RunNamespace, RunHandle, RunStartOptions, RunStatus, ActiveRunContext, ArtifactBuffer, GroundTruthStepInput, } from "./run-context";
|
|
14
|
+
export type { RunNamespace, RunHandle, RunStartOptions, RunEndOptions, RunStatus, ActiveRunContext, ArtifactBuffer, GroundTruthStepInput, } from "./run-context";
|
|
15
15
|
export { step } from "./step";
|
|
16
16
|
export { createArtifactApi } from "./artifact";
|
|
17
17
|
export { openArtifactStore } from "../telemetry/artifact-store";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/artifacts/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/artifacts/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ARC-4 — generated media as artifacts, under UC-3 M2 posture (a) (ruled
|
|
3
|
+
* 2026-08-31): image / video / audio bytes ride the existing artifact store with
|
|
4
|
+
* `type: image/* | video/* | audio/*`, and are flagged **unscreened** — the
|
|
5
|
+
* scrub engine is text-only, so ModelRig never scanned them for PII/PHI. Honest,
|
|
6
|
+
* never silent: the flag rides the EXISTING `artifacts.scrub` jsonb (00039) as
|
|
7
|
+
* `{ mode: "off", blocked: false, findings: [], unscreened: "media" }` — zero
|
|
8
|
+
* DDL, no new column. A vision-model screen is the designed PAID follow-on (b).
|
|
9
|
+
*
|
|
10
|
+
* Fail-closed custody: when the effective scrub mode is `redact` or `block`
|
|
11
|
+
* (a `pii`/`phi` classification forces the floor), media bytes are NOT uploaded
|
|
12
|
+
* — the policy cannot be honoured on bytes the engine cannot read.
|
|
13
|
+
*/
|
|
14
|
+
import type { ScrubMode, ScrubSummary } from "./scrub";
|
|
15
|
+
/** The media-type families that are generated assets (the `type` prefix). */
|
|
16
|
+
export declare const MEDIA_TYPE_PREFIXES: readonly ["image/", "video/", "audio/"];
|
|
17
|
+
/**
|
|
18
|
+
* ARC-4 fix F6 — the media MIME types an artifact may be SAVED as. Raster
|
|
19
|
+
* images, common video and audio only: anything else in the image/video/audio
|
|
20
|
+
* families — notably `image/svg+xml`, which can carry script, or a type with
|
|
21
|
+
* parameters — is refused (a teaching warn, nothing recorded). `isMediaType`
|
|
22
|
+
* stays the broad family test the text-only readers use to never decode bytes.
|
|
23
|
+
*/
|
|
24
|
+
export declare const MEDIA_MIME_ALLOWLIST: readonly ["image/png", "image/jpeg", "image/webp", "image/gif", "video/mp4", "video/webm", "audio/mpeg", "audio/wav", "audio/ogg", "audio/webm"];
|
|
25
|
+
/** True only for an exact allowlisted media type (trimmed, case-insensitive). */
|
|
26
|
+
export declare function isAllowedMediaType(type: string): boolean;
|
|
27
|
+
/** The teaching refusal for a non-allowlisted media type (nothing recorded). */
|
|
28
|
+
export declare function warnRefusedMediaType(name: string, type: string): null;
|
|
29
|
+
/** The one `unscreened` value: media the text scrub engine cannot read. */
|
|
30
|
+
export declare const UNSCREENED_MEDIA: "media";
|
|
31
|
+
/** True for an artifact `type` that names image/video/audio content. */
|
|
32
|
+
export declare function isMediaType(type: string): boolean;
|
|
33
|
+
/** The scrub record every media artifact row carries: nothing ran (`off`),
|
|
34
|
+
* nothing found, and the explicit unscreened flag. */
|
|
35
|
+
export declare function unscreenedMediaScrub(): ScrubSummary;
|
|
36
|
+
/** ARC-4 fix F5 — the truthful record when custody REFUSED the upload because
|
|
37
|
+
* the effective mode (redact/block, incl. the pii/phi floor) cannot be applied
|
|
38
|
+
* to bytes: that mode, `blocked: true`, still flagged unscreened. */
|
|
39
|
+
export declare function refusedMediaScrub(mode: ScrubMode): ScrubSummary;
|
|
40
|
+
/** The bytes of a media value: a Buffer/Uint8Array as-is (binary), anything
|
|
41
|
+
* else serialized as the text path does (e.g. a base64 string or a URL). */
|
|
42
|
+
export declare function mediaBytes(value: unknown): Buffer;
|
|
43
|
+
/** Whether custody may upload media bytes under this effective scrub mode:
|
|
44
|
+
* `off`/`detect` upload (flagged unscreened); `redact`/`block` refuse. */
|
|
45
|
+
export declare function mediaUploadAllowed(mode: ScrubMode): boolean;
|
|
46
|
+
//# sourceMappingURL=media.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media.d.ts","sourceRoot":"","sources":["../../src/artifacts/media.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvD,6EAA6E;AAC7E,eAAO,MAAM,mBAAmB,yCAA0C,CAAC;AAE3E;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,kJAWvB,CAAC;AAIX,iFAAiF;AACjF,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAExD;AAED,gFAAgF;AAChF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAMrE;AAED,2EAA2E;AAC3E,eAAO,MAAM,gBAAgB,EAAG,OAAgB,CAAC;AAEjD,wEAAwE;AACxE,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGjD;AAED;sDACsD;AACtD,wBAAgB,oBAAoB,IAAI,YAAY,CAEnD;AAED;;qEAEqE;AACrE,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,GAAG,YAAY,CAE/D;AAED;4EAC4E;AAC5E,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAKjD;AAED;0EAC0E;AAC1E,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAE3D"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ARC-4 — generated media as artifacts, under UC-3 M2 posture (a) (ruled
|
|
4
|
+
* 2026-08-31): image / video / audio bytes ride the existing artifact store with
|
|
5
|
+
* `type: image/* | video/* | audio/*`, and are flagged **unscreened** — the
|
|
6
|
+
* scrub engine is text-only, so ModelRig never scanned them for PII/PHI. Honest,
|
|
7
|
+
* never silent: the flag rides the EXISTING `artifacts.scrub` jsonb (00039) as
|
|
8
|
+
* `{ mode: "off", blocked: false, findings: [], unscreened: "media" }` — zero
|
|
9
|
+
* DDL, no new column. A vision-model screen is the designed PAID follow-on (b).
|
|
10
|
+
*
|
|
11
|
+
* Fail-closed custody: when the effective scrub mode is `redact` or `block`
|
|
12
|
+
* (a `pii`/`phi` classification forces the floor), media bytes are NOT uploaded
|
|
13
|
+
* — the policy cannot be honoured on bytes the engine cannot read.
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.UNSCREENED_MEDIA = exports.MEDIA_MIME_ALLOWLIST = exports.MEDIA_TYPE_PREFIXES = void 0;
|
|
17
|
+
exports.isAllowedMediaType = isAllowedMediaType;
|
|
18
|
+
exports.warnRefusedMediaType = warnRefusedMediaType;
|
|
19
|
+
exports.isMediaType = isMediaType;
|
|
20
|
+
exports.unscreenedMediaScrub = unscreenedMediaScrub;
|
|
21
|
+
exports.refusedMediaScrub = refusedMediaScrub;
|
|
22
|
+
exports.mediaBytes = mediaBytes;
|
|
23
|
+
exports.mediaUploadAllowed = mediaUploadAllowed;
|
|
24
|
+
/** The media-type families that are generated assets (the `type` prefix). */
|
|
25
|
+
exports.MEDIA_TYPE_PREFIXES = ["image/", "video/", "audio/"];
|
|
26
|
+
/**
|
|
27
|
+
* ARC-4 fix F6 — the media MIME types an artifact may be SAVED as. Raster
|
|
28
|
+
* images, common video and audio only: anything else in the image/video/audio
|
|
29
|
+
* families — notably `image/svg+xml`, which can carry script, or a type with
|
|
30
|
+
* parameters — is refused (a teaching warn, nothing recorded). `isMediaType`
|
|
31
|
+
* stays the broad family test the text-only readers use to never decode bytes.
|
|
32
|
+
*/
|
|
33
|
+
exports.MEDIA_MIME_ALLOWLIST = [
|
|
34
|
+
"image/png",
|
|
35
|
+
"image/jpeg",
|
|
36
|
+
"image/webp",
|
|
37
|
+
"image/gif",
|
|
38
|
+
"video/mp4",
|
|
39
|
+
"video/webm",
|
|
40
|
+
"audio/mpeg",
|
|
41
|
+
"audio/wav",
|
|
42
|
+
"audio/ogg",
|
|
43
|
+
"audio/webm",
|
|
44
|
+
];
|
|
45
|
+
const ALLOWED = new Set(exports.MEDIA_MIME_ALLOWLIST);
|
|
46
|
+
/** True only for an exact allowlisted media type (trimmed, case-insensitive). */
|
|
47
|
+
function isAllowedMediaType(type) {
|
|
48
|
+
return ALLOWED.has(type.trim().toLowerCase());
|
|
49
|
+
}
|
|
50
|
+
/** The teaching refusal for a non-allowlisted media type (nothing recorded). */
|
|
51
|
+
function warnRefusedMediaType(name, type) {
|
|
52
|
+
console.warn(`[modelrig artifacts] media artifact "${name}" NOT recorded: type "${type}" is not an allowed media type. ` +
|
|
53
|
+
`fix_hint: save as one of ${exports.MEDIA_MIME_ALLOWLIST.join(", ")} (convert SVG to PNG), or as a text/json artifact.`);
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
/** The one `unscreened` value: media the text scrub engine cannot read. */
|
|
57
|
+
exports.UNSCREENED_MEDIA = "media";
|
|
58
|
+
/** True for an artifact `type` that names image/video/audio content. */
|
|
59
|
+
function isMediaType(type) {
|
|
60
|
+
const t = type.trim().toLowerCase();
|
|
61
|
+
return exports.MEDIA_TYPE_PREFIXES.some((p) => t.startsWith(p) && t.length > p.length);
|
|
62
|
+
}
|
|
63
|
+
/** The scrub record every media artifact row carries: nothing ran (`off`),
|
|
64
|
+
* nothing found, and the explicit unscreened flag. */
|
|
65
|
+
function unscreenedMediaScrub() {
|
|
66
|
+
return { mode: "off", blocked: false, findings: [], unscreened: exports.UNSCREENED_MEDIA };
|
|
67
|
+
}
|
|
68
|
+
/** ARC-4 fix F5 — the truthful record when custody REFUSED the upload because
|
|
69
|
+
* the effective mode (redact/block, incl. the pii/phi floor) cannot be applied
|
|
70
|
+
* to bytes: that mode, `blocked: true`, still flagged unscreened. */
|
|
71
|
+
function refusedMediaScrub(mode) {
|
|
72
|
+
return { mode, blocked: true, findings: [], unscreened: exports.UNSCREENED_MEDIA };
|
|
73
|
+
}
|
|
74
|
+
/** The bytes of a media value: a Buffer/Uint8Array as-is (binary), anything
|
|
75
|
+
* else serialized as the text path does (e.g. a base64 string or a URL). */
|
|
76
|
+
function mediaBytes(value) {
|
|
77
|
+
if (Buffer.isBuffer(value))
|
|
78
|
+
return value;
|
|
79
|
+
if (value instanceof Uint8Array)
|
|
80
|
+
return Buffer.from(value.buffer, value.byteOffset, value.byteLength);
|
|
81
|
+
const serialized = typeof value === "string" ? value : JSON.stringify(value ?? null);
|
|
82
|
+
return Buffer.from(serialized, "utf8");
|
|
83
|
+
}
|
|
84
|
+
/** Whether custody may upload media bytes under this effective scrub mode:
|
|
85
|
+
* `off`/`detect` upload (flagged unscreened); `redact`/`block` refuse. */
|
|
86
|
+
function mediaUploadAllowed(mode) {
|
|
87
|
+
return mode === "off" || mode === "detect";
|
|
88
|
+
}
|
|
@@ -21,12 +21,20 @@
|
|
|
21
21
|
*/
|
|
22
22
|
import type { RunRow, StepRow } from "../types/telemetry";
|
|
23
23
|
import type { RunMetaV1 } from "../telemetry/attempt-meta";
|
|
24
|
+
import { type ConversationHandle, type ConversationOptions } from "./conversation";
|
|
25
|
+
import { RunLimitExceeded, type RunLimits } from "../run/limits";
|
|
24
26
|
/** The narrow buffer the run/artifact namespace writes through — the local
|
|
25
27
|
* telemetry store satisfies it. Kept narrow so this module depends on the row
|
|
26
28
|
* shapes, not the whole store surface (and cannot reach captures). */
|
|
27
29
|
export interface ArtifactBuffer {
|
|
28
30
|
recordRun(row: RunRow): void;
|
|
29
31
|
recordStep(row: StepRow): void;
|
|
32
|
+
/** ARC-1 conversation re-entry (optional — the local telemetry store has it):
|
|
33
|
+
* the newest `running` run for (pipeline, episode_key) + its step keys. */
|
|
34
|
+
findOpenRun?(pipeline: string, episodeKey: string): {
|
|
35
|
+
readonly row: RunRow;
|
|
36
|
+
readonly stepKeys: readonly string[];
|
|
37
|
+
} | null;
|
|
30
38
|
}
|
|
31
39
|
export type RunStatus = RunRow["status"];
|
|
32
40
|
export interface RunStartOptions {
|
|
@@ -51,6 +59,10 @@ export interface RunStartOptions {
|
|
|
51
59
|
* try/catch'd). Absent ⇒ the run still auto-fills a git sha when one resolves,
|
|
52
60
|
* else `runs.meta` is null. */
|
|
53
61
|
readonly meta?: RunMetaV1;
|
|
62
|
+
/** ARC-5: per-run limits checked BEFORE each run/runRaw dispatch (run/limits.ts).
|
|
63
|
+
* A breach throws RunLimitExceeded and ends the run `failed` with
|
|
64
|
+
* `failure_reason: limit:<which>`. Recorded on `RunMeta.limits`. */
|
|
65
|
+
readonly limits?: RunLimits;
|
|
54
66
|
}
|
|
55
67
|
/** Test-only: clear the once-per-process RunMeta-sanitize warning latch. */
|
|
56
68
|
export declare function resetRunMetaWarningsForTest(): void;
|
|
@@ -63,6 +75,14 @@ export interface GroundTruthStepInput {
|
|
|
63
75
|
readonly startedAt: string;
|
|
64
76
|
readonly endedAt: string;
|
|
65
77
|
readonly failureClass: string | null;
|
|
78
|
+
/** ARC-5: this attempt's cost — accumulated toward `limits.maxUsd`. */
|
|
79
|
+
readonly costUsd?: number | null;
|
|
80
|
+
/** ARC-5: the tool calls the model requested on this attempt (name + raw JSON
|
|
81
|
+
* args; HASHED by the limits accumulator, never kept). Undefined ⇒ unknown. */
|
|
82
|
+
readonly toolCalls?: readonly {
|
|
83
|
+
readonly name: string;
|
|
84
|
+
readonly arguments: string;
|
|
85
|
+
}[];
|
|
66
86
|
}
|
|
67
87
|
export interface ActiveRunContext {
|
|
68
88
|
readonly runId: string;
|
|
@@ -72,6 +92,9 @@ export interface ActiveRunContext {
|
|
|
72
92
|
readonly traceId: string | null;
|
|
73
93
|
/** Zero-retention gate (chunk B): true ⇒ artifact.save refuses fail-closed. */
|
|
74
94
|
readonly zeroRetention: boolean;
|
|
95
|
+
/** ARC-1: tags a conversation stamps on every call in it (`user`, `subject`)
|
|
96
|
+
* UNDER the caller's own tags. Undefined for a plain run (byte-identical). */
|
|
97
|
+
readonly defaultTags?: Readonly<Record<string, string>>;
|
|
75
98
|
/** Record that an artifact was loaded in the current run (chunk B lineage). */
|
|
76
99
|
noteLoad(artifactId: string): void;
|
|
77
100
|
/** Return AND clear the loaded-artifact ids — the set a subsequent save
|
|
@@ -99,6 +122,12 @@ export interface ActiveRunContext {
|
|
|
99
122
|
* and never thrown into the run loop. Marks its key as the ambient step. */
|
|
100
123
|
emitGroundTruthStep(input: GroundTruthStepInput): void;
|
|
101
124
|
}
|
|
125
|
+
/** R9: options for ending a run. */
|
|
126
|
+
export interface RunEndOptions {
|
|
127
|
+
/** An identifier (≤128 chars, no whitespace — e.g. a gate code). Written to
|
|
128
|
+
* `runs.meta.failure_reason` when the run ends `failed`; ignored otherwise. */
|
|
129
|
+
readonly failureReason?: string;
|
|
130
|
+
}
|
|
102
131
|
/** RC-1: the `run_id` tag value an active run context stamps on every attempt
|
|
103
132
|
* row of BOTH lanes when the caller supplied none — the run's `episodeKey`
|
|
104
133
|
* (what the `/projects` tree joins on) or, without one, the run's id. Never
|
|
@@ -110,6 +139,17 @@ export declare function withRunIdTag<T extends {
|
|
|
110
139
|
/** The active run context, or null when none is set (namespace disabled, or no
|
|
111
140
|
* run.start on this async path). Read by the run loop's auto-step seam. */
|
|
112
141
|
export declare function getActiveRunContext(): ActiveRunContext | null;
|
|
142
|
+
/**
|
|
143
|
+
* ARC-5 pre-dispatch check — the ONE call `run()` and `runRaw()` make before a
|
|
144
|
+
* provider dispatch. Reads the ambient run (INCLUDING one already stopped at a
|
|
145
|
+
* limit, so it keeps refusing on that path). No run, or a run with no limits ⇒
|
|
146
|
+
* null, zero work. On a fresh breach it ends the run `failed` with
|
|
147
|
+
* `failure_reason: limit:<which>` and returns the typed error to throw.
|
|
148
|
+
* `ctx` overrides the ambient lookup (the raw stream captures it at entry).
|
|
149
|
+
*/
|
|
150
|
+
export declare function runLimitRefusal(ctx?: ActiveRunContext | null): RunLimitExceeded | null;
|
|
151
|
+
/** Throwing form of {@link runLimitRefusal} — `run()` / `runRaw()` call this. */
|
|
152
|
+
export declare function enforceRunLimits(ctx?: ActiveRunContext | null): void;
|
|
113
153
|
/** True when `key` is a valid caller-supplied step key (spec §3). */
|
|
114
154
|
export declare function isValidStepKey(key: string): boolean;
|
|
115
155
|
/** Resolve a ground-truth step key for either lane (spec §3): an explicit
|
|
@@ -123,7 +163,7 @@ export declare function resetStepKeyWarningsForTest(): void;
|
|
|
123
163
|
/** A handle a caller holds to end a run it started. */
|
|
124
164
|
export interface RunHandle {
|
|
125
165
|
readonly runId: string;
|
|
126
|
-
end(status?: RunStatus): void;
|
|
166
|
+
end(status?: RunStatus, opts?: RunEndOptions): void;
|
|
127
167
|
}
|
|
128
168
|
/** The `run` namespace, bound to one rig's buffer + gate. Disabled ⇒ inert. */
|
|
129
169
|
export interface RunNamespace {
|
|
@@ -134,16 +174,35 @@ export interface RunNamespace {
|
|
|
134
174
|
* For concurrent runs use `scope()`. Disabled ⇒ no-op inert handle. */
|
|
135
175
|
start(opts: RunStartOptions): RunHandle;
|
|
136
176
|
/** End the active run with a terminal status (default "succeeded"). */
|
|
137
|
-
end(status?: RunStatus): void;
|
|
177
|
+
end(status?: RunStatus, opts?: RunEndOptions): void;
|
|
178
|
+
/** R9: record why the ACTIVE run is failing (a gate code). Applied to
|
|
179
|
+
* `runs.meta.failure_reason` if the run then ends `failed` — e.g. a
|
|
180
|
+
* `scope()` whose callback throws. No active run / disabled ⇒ no-op. */
|
|
181
|
+
setFailureReason(reason: string): void;
|
|
138
182
|
/** Concurrency-safe run scope. Runs `fn` inside `AsyncLocalStorage.run`, so
|
|
139
183
|
* overlapping `scope()` calls each keep their OWN ambient run context — the
|
|
140
184
|
* correct primitive for `Promise.all` over items. Ends the run "succeeded" on
|
|
141
185
|
* return, "failed" if `fn` throws (then rethrows). Disabled ⇒ runs `fn` with
|
|
142
186
|
* no context. */
|
|
143
187
|
scope<T>(opts: RunStartOptions, fn: () => Promise<T>): Promise<T>;
|
|
188
|
+
/** ARC-1: open (or re-enter) a conversation run — see artifacts/conversation.ts
|
|
189
|
+
* for the turn-step rule. Disabled ⇒ an inert handle whose `turn` just runs fn. */
|
|
190
|
+
conversation(id: string, opts: ConversationOptions): ConversationHandle;
|
|
191
|
+
/** M4 test seam: how many conversations the in-process registry holds. */
|
|
192
|
+
openConversationCount(): number;
|
|
144
193
|
}
|
|
194
|
+
/** ARC-1 (fix round 1, M4): the in-process open-conversation registry's bounds.
|
|
195
|
+
* An entry idle longer than the TTL (the server's default idle-close window) or
|
|
196
|
+
* past the LRU cap is EVICTED — not ended: the run stays `running` in the local
|
|
197
|
+
* store, so a later `rig.conversation(id)` re-enters it through `findOpenRun`. */
|
|
198
|
+
export declare const MAX_OPEN_CONVERSATIONS = 10000;
|
|
199
|
+
export declare const OPEN_CONVERSATION_IDLE_MS: number;
|
|
145
200
|
export declare function createRunNamespace(deps: {
|
|
146
201
|
readonly buffer: ArtifactBuffer;
|
|
147
202
|
readonly enabled: boolean;
|
|
203
|
+
/** M4 test seams: registry cap / idle TTL / clock. */
|
|
204
|
+
readonly maxOpenConversations?: number;
|
|
205
|
+
readonly conversationIdleMs?: number;
|
|
206
|
+
readonly now?: () => number;
|
|
148
207
|
}): RunNamespace;
|
|
149
208
|
//# sourceMappingURL=run-context.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-context.d.ts","sourceRoot":"","sources":["../../src/artifacts/run-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"run-context.d.ts","sourceRoot":"","sources":["../../src/artifacts/run-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAG3D,OAAO,EAKL,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACzB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAML,gBAAgB,EAGhB,KAAK,SAAS,EAEf,MAAM,eAAe,CAAC;AAGvB;;sEAEsE;AACtE,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAAC;IAC/B;+EAC2E;IAC3E,WAAW,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG;QAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,GAAG,IAAI,CAAC;CAC3H;AAED,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;AAEzC,MAAM,WAAW,eAAe;IAC9B,8DAA8D;IAC9D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,mEAAmE;IACnE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B;;wEAEoE;IACpE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B;;;oCAGgC;IAChC,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IACjC;;;;mCAI+B;IAC/B,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC;IAC1B;;wEAEoE;IACpE,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC;CAC7B;AA4CD,4EAA4E;AAC5E,wBAAgB,2BAA2B,IAAI,IAAI,CAElD;AAED;gFACgF;AAChF,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,uEAAuE;IACvE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC;mFAC+E;IAC/E,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACvF;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,qEAAqE;IACrE,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,8EAA8E;IAC9E,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,+EAA+E;IAC/E,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC;kFAC8E;IAC9E,QAAQ,CAAC,WAAW,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACxD,+EAA+E;IAC/E,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC;;uFAEmF;IACnF,aAAa,IAAI,MAAM,EAAE,CAAC;IAC1B;;;wEAGoE;IACpE,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACnC;;;;;;;;;+DAS2D;IAC3D,cAAc,IAAI,MAAM,GAAG,IAAI,CAAC;IAChC;;gFAE4E;IAC5E,mBAAmB,CAAC,KAAK,EAAE,oBAAoB,GAAG,IAAI,CAAC;CACxD;AAwBD,oCAAoC;AACpC,MAAM,WAAW,aAAa;IAC5B;mFAC+E;IAC/E,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC;AAID;;;wEAGwE;AACxE,wBAAgB,YAAY,CAAC,CAAC,SAAS;IAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;CAAE,EAC7G,IAAI,EAAE,CAAC,EACP,GAAG,EAAE,gBAAgB,GAAG,IAAI,GAC3B,CAAC,CAMH;AAED;2EAC2E;AAC3E,wBAAgB,mBAAmB,IAAI,gBAAgB,GAAG,IAAI,CAG7D;AAcD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,GAAG,CAAC,EAAE,gBAAgB,GAAG,IAAI,GAAG,gBAAgB,GAAG,IAAI,CAStF;AAED,iFAAiF;AACjF,wBAAgB,gBAAgB,CAAC,GAAG,CAAC,EAAE,gBAAgB,GAAG,IAAI,GAAG,IAAI,CAGpE;AAQD,qEAAqE;AACrE,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEnD;AAID;;;;8EAI8E;AAC9E,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,IAAI,EAAE,MAAM,MAAM,GACjB,MAAM,CAYR;AAED,2EAA2E;AAC3E,wBAAgB,2BAA2B,IAAI,IAAI,CAElD;AAED,uDAAuD;AACvD,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,GAAG,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;CACrD;AAED,+EAA+E;AAC/E,MAAM,WAAW,YAAY;IAC3B;;;;2EAIuE;IACvE,KAAK,CAAC,IAAI,EAAE,eAAe,GAAG,SAAS,CAAC;IACxC,uEAAuE;IACvE,GAAG,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IACpD;;4EAEwE;IACxE,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC;;;;qBAIiB;IACjB,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAClE;uFACmF;IACnF,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,GAAG,kBAAkB,CAAC;IACxE,0EAA0E;IAC1E,qBAAqB,IAAI,MAAM,CAAC;CACjC;AASD;;;kFAGkF;AAClF,eAAO,MAAM,sBAAsB,QAAS,CAAC;AAC7C,eAAO,MAAM,yBAAyB,QAAc,CAAC;AAErD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACvC,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,sDAAsD;IACtD,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IACvC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC7B,GAAG,YAAY,CAkRf"}
|