modelrig 0.10.0 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/CHANGELOG.md +96 -0
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +1 -0
  4. package/dist/config.d.ts +18 -0
  5. package/dist/config.d.ts.map +1 -1
  6. package/dist/config.js +23 -3
  7. package/dist/doctor-cli.d.ts.map +1 -1
  8. package/dist/doctor-cli.js +2 -1
  9. package/dist/doctor-preflight.d.ts +14 -2
  10. package/dist/doctor-preflight.d.ts.map +1 -1
  11. package/dist/doctor-preflight.js +65 -5
  12. package/dist/feedback/coverage.d.ts.map +1 -1
  13. package/dist/feedback/coverage.js +9 -2
  14. package/dist/index.d.ts +7 -1
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +18 -8
  17. package/dist/init/init-cli.d.ts.map +1 -1
  18. package/dist/init/init-cli.js +21 -4
  19. package/dist/init/observe-cli.js +1 -1
  20. package/dist/init/observe.d.ts +7 -1
  21. package/dist/init/observe.d.ts.map +1 -1
  22. package/dist/init/observe.js +74 -22
  23. package/dist/init/starter.d.ts +36 -0
  24. package/dist/init/starter.d.ts.map +1 -0
  25. package/dist/init/starter.js +85 -0
  26. package/dist/run/raw-finalize.d.ts +49 -3
  27. package/dist/run/raw-finalize.d.ts.map +1 -1
  28. package/dist/run/raw-finalize.js +31 -14
  29. package/dist/run/raw-search-cost.d.ts +3 -2
  30. package/dist/run/raw-search-cost.d.ts.map +1 -1
  31. package/dist/run/raw-search-cost.js +1 -0
  32. package/dist/run/rawonly.d.ts +29 -5
  33. package/dist/run/rawonly.d.ts.map +1 -1
  34. package/dist/run/rawonly.js +54 -19
  35. package/dist/run/record-call.d.ts +104 -0
  36. package/dist/run/record-call.d.ts.map +1 -0
  37. package/dist/run/record-call.js +277 -0
  38. package/dist/telemetry/attempt-meta.d.ts +11 -0
  39. package/dist/telemetry/attempt-meta.d.ts.map +1 -1
  40. package/dist/telemetry/attempt-meta.js +3 -0
  41. package/dist/telemetry/lanes.d.ts +31 -0
  42. package/dist/telemetry/lanes.d.ts.map +1 -0
  43. package/dist/telemetry/lanes.js +41 -0
  44. package/dist/telemetry/org-identity.d.ts +5 -2
  45. package/dist/telemetry/org-identity.d.ts.map +1 -1
  46. package/dist/telemetry/org-identity.js +10 -8
  47. package/docs/agent-skill/SKILL.md +109 -10
  48. package/docs/how-it-fits.md +1 -1
  49. package/docs/instrumentation.md +152 -40
  50. package/docs/llms.txt +92 -9
  51. package/docs/quickstart.md +127 -15
  52. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -25,11 +25,11 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
25
25
  };
26
26
  Object.defineProperty(exports, "__esModule", { value: true });
27
27
  exports.redactApiKey = exports.looksLikeApiKey = exports.hashApiKeySecret = exports.API_KEY_SECRET_BYTES = exports.API_KEY_SCOPES = exports.API_KEY_PREFIX = exports.resolveArtifactsConfig = exports.createToolRegistry = exports.SlotResolutionError = exports.assemblePrompt = exports.createEmbeddedPrompts = exports.createPromptResolver = exports.parseServedPrompt = exports.createPromptCache = exports.createApiPromptFetcher = exports.promptTemplateSha = exports.normalizeManifest = exports.parseAuthoringDoc = exports.assertValidManifest = exports.validateManifest = exports.resolveOtlpConfig = exports.parseOtlpHeaders = exports.decodeOtlpProtobufTraces = exports.looksLikeLogsPayload = exports.normalizeOtlpTraces = exports.startOtlpEmitterIfConfigured = exports.createOtlpEmitter = exports.TRACEPARENT_TAG = exports.parseTraceparent = exports.buildExportTraceRequest = exports.inferenceToSpan = exports.SEMCONV_VERSION = exports.SinkSendError = exports.createDirectSink = exports.createApiSink = exports.createTelemetryExporter = exports.RESERVED_TAG_KEYS = exports.resolvePipelineSha = exports.reservedTagNearMisses = exports.renderRequestForHash = exports.sanitizeMetaForWire = exports.isMetaSafeString = exports.summarizeAttemptMeta = exports.DEFAULT_INGEST_URL = exports.INGEST_PROTOCOL_VERSION_V1 = exports.INGEST_PROTOCOL_VERSION = exports.INGEST_PATH = exports.foreignOrgGrades = exports.stampBatch = exports.loadConfigFromEnv = void 0;
28
- exports.computeProposal = exports.mirrorBakeoff = exports.runBakeoff = exports.replayVariant = exports.openTelemetryStore = exports.openCaptureStore = exports.SSE_DONE = exports.MODELRIG_REQUEST_HEADERS = exports.MODELRIG_HEADERS = exports.GATEWAY_PROTOCOL_VERSION = exports.MODELS_PATH = exports.CHAT_COMPLETIONS_PATH = exports.classifyLane = exports.ALL_CAPABILITY_FLAGS = exports.PROVIDER_IDS = exports.RAW_ONLY_FIX_HINT = exports.rawOnlyRouteFailure = exports.requireRoutesDir = exports.runRawStream = exports.runRaw = exports.resolveCallConfigForRun = exports.hashUnitKey = exports.armName = exports.drawArm = exports.narrowExperiment = exports.pinFromResolved = exports.parseCallConfig = exports.narrowCallConfigPin = exports.getCallConfig = exports.createCallConfigResolver = exports.createApiCallConfigFetcher = exports.applyCallConfig = exports.assertMirrorSafe = exports.hashResolvedBundle = exports.resolveRouteBundle = exports.bundleFromResolved = exports.runStream = exports.evalCaseCaptureStore = exports.selectEvalCaseCaptures = exports.runBakeoffFromEvalCases = exports.extractEvidenceQuotes = exports.groundednessScore = exports.resolveDeterministicQuality = exports.fieldAccuracy = exports.exactMatch = exports.KEY_SHAPED_PREFIXES = exports.containsKeyShapedString = exports.scrubSecrets = exports.hasScope = exports.parseScopes = void 0;
29
- exports.servedDestinations = exports.DEFAULT_DESTINATION = exports.DESTINATIONS = exports.GEMINI_THINKING_CAPABLE_MODELS = exports.createGeminiAdapter = exports.PROVIDER_KEY_ENV = exports.serveabilityWarnings = exports.checkServeability = exports.writeRouteDraft = exports.buildRouteDraft = exports.splitModelKey = exports.seedCandidates = exports.loadRegistryRows = exports.signatureFor = exports.PROVIDER_SIGNATURES = exports.readObjectLiteral = exports.findCallSitesInText = exports.scanRepoForCallSites = exports.capabilitiesFor = exports.routeNameFor = exports.buildMigrationMarkdown = exports.runInit = exports.renderConfigErrorForTerminal = exports.describeConfigFailure = exports.teachConfigError = exports.classifyConfigProblem = exports.CONFIG_TEACHING = exports.mergeLoadedRoutes = exports.loadRoutesWithExtra = exports.loadRoutes = exports.RouteConfigError = exports.renderFailureForTerminal = exports.teach = exports.FAILURE_TEACHING = exports.isRigFailure = exports.RigFailureError = exports.extractCitations = exports.createTavilySearchProvider = exports.sampleQuality = exports.pairedRegret = exports.wilson95 = exports.aggregateVariantMetrics = exports.OUTPUT_MAX_BYTES = exports.retentionExpiry = exports.truncateOutput = exports.selectArmsToKeep = exports.buildBakeoffSamples = exports.createBakeoffSamplesClient = exports.deriveSwapDirection = exports.bakeoffEvidence = void 0;
30
- exports.PROPOSAL_TTL_DAYS = exports.regretBreachTriggerHash = exports.upgradeTriggerHash = exports.manualChallengerTriggerHash = exports.triggerHash = exports.evaluateEvents = exports.RUNG1_MIN_GRADES = exports.computeCoverage = exports.computeParity = exports.factsUnderCredential = exports.factsFor = exports.PROBE_FRESHNESS_SLO_DAYS = exports.stalenessSentence = exports.probeFreshness = exports.callNotesFor = exports.evaluateChallengerEligibility = exports.requirementPredicates = exports.PREDICATE_GLOSS = exports.ALL_CAPABILITY_PREDICATES = exports.explainEmptySelection = exports.hasCapability = exports.selectModels = exports.parseCapabilityQuery = exports.capabilityFactsFromEntry = exports.loadRegistryFacts = exports.fingerprintSchema = exports.loadManifest = exports.SNAPSHOT_BASIS = exports.describePricingV2 = exports.tierRates = exports.synthesizeFromFlat = exports.seededCachePolicyProviders = exports.getCachePolicy = exports.DEFAULT_CACHE_HYSTERESIS = exports.classifyCacheVerdict = exports.effectiveInputRate = exports.estimateCostUsd = exports.getPricingV2 = exports.getPricing = exports.resolveCandidates = exports.OPENAI_COMPAT_HOSTS = exports.shapeFireworksModelId = exports.classifyCompatFailure = exports.buildOpenAICompatParams = exports.createOpenAICompatAdapter = exports.createGrokAdapter = exports.createAnthropicAdapter = exports.createDeepSeekAdapter = exports.createOpenAIAdapter = exports.destinationSupported = void 0;
31
- exports.RESERVED_DIMENSION_NAMES = exports.METRIC_COLUMNS = exports.DIMENSION_COLUMNS = exports.sinceIsoFor = exports.savedQueryById = exports.SAVED_QUERIES = exports.ANALYTICS_SCAN_CAP = exports.selectableColumnsAreMetaSafe = exports.planAnalyticsRead = exports.evaluateAnalyticsQuery = exports.describeAnalyticsSchema = exports.parseQuery = exports.QueryGrammarError = exports.compileQuery = exports.writePriorsCells = exports.aggregatePairwiseFromTelemetry = exports.aggregatePriors = exports.DEFAULT_WATCH_MONTHLY_USD = exports.watchEnvelopeKey = exports.reserveWatchBudget = exports.WATCH_STATE_KEY = exports.createFileWatchStateStore = exports.createControlPlaneWatchStateStore = exports.createWatchStateStore = exports.saveWatchState = exports.loadWatchState = exports.computeWatchEvents = exports.buildPriceUniverse = exports.runWatchCycle = exports.DEFAULT_MONITOR_CONFIG = exports.createMonitorReads = exports.rollupConformRate = exports.evaluateConformDegradation = exports.runMonitorCycle = exports.assertTransition = exports.createProposalsClient = exports.MONITOR_SOURCE_PREFIX = exports.MONITOR_CYCLE_MARKER = exports.REGRET_MONITOR_MARGIN = exports.REGRET_MONITOR_MIN_N = exports.REGRET_MONITOR_BASELINE_DAYS = exports.REGRET_MONITOR_WINDOW_DAYS = exports.createRegretMonitorReads = exports.regretMonitorConfig = exports.cyclePointFromArtifact = exports.aggregateRegretBand = exports.evaluateRegretDrift = exports.runRegretMonitorCycle = exports.evaluateUpgradeOpportunities = exports.explainCacheContext = void 0;
32
- exports.computeOdometer = exports.createSwapsClient = exports.executeSwap = exports.trialVariantName = exports.buildDeclareTrialChange = exports.buildRestoreYaml = exports.buildSwapChange = exports.runTelemetryQuery = void 0;
28
+ exports.SSE_DONE = exports.MODELRIG_REQUEST_HEADERS = exports.MODELRIG_HEADERS = exports.GATEWAY_PROTOCOL_VERSION = exports.MODELS_PATH = exports.CHAT_COMPLETIONS_PATH = exports.classifyLane = exports.ALL_CAPABILITY_FLAGS = exports.PROVIDER_IDS = exports.RAW_ONLY_FIX_HINT = exports.rawOnlyRouteFailure = exports.requireRoutesDir = exports.RECORDED_TOOLTIP = exports.RECORDED_BADGE = exports.EXTERNAL_LANE = exports.RAW_LANE = exports.callLaneOf = exports.isRoutedLane = exports.runRawStream = exports.runRaw = exports.resolveCallConfigForRun = exports.hashUnitKey = exports.armName = exports.drawArm = exports.narrowExperiment = exports.pinFromResolved = exports.parseCallConfig = exports.narrowCallConfigPin = exports.getCallConfig = exports.createCallConfigResolver = exports.createApiCallConfigFetcher = exports.applyCallConfig = exports.assertMirrorSafe = exports.hashResolvedBundle = exports.resolveRouteBundle = exports.bundleFromResolved = exports.runStream = exports.evalCaseCaptureStore = exports.selectEvalCaseCaptures = exports.runBakeoffFromEvalCases = exports.extractEvidenceQuotes = exports.groundednessScore = exports.resolveDeterministicQuality = exports.fieldAccuracy = exports.exactMatch = exports.KEY_SHAPED_PREFIXES = exports.containsKeyShapedString = exports.scrubSecrets = exports.hasScope = exports.parseScopes = void 0;
29
+ exports.serveabilityWarnings = exports.checkServeability = exports.writeRouteDraft = exports.buildRouteDraft = exports.splitModelKey = exports.seedCandidates = exports.loadRegistryRows = exports.signatureFor = exports.PROVIDER_SIGNATURES = exports.readObjectLiteral = exports.findCallSitesInText = exports.scanRepoForCallSites = exports.capabilitiesFor = exports.routeNameFor = exports.buildMigrationMarkdown = exports.runInit = exports.renderConfigErrorForTerminal = exports.describeConfigFailure = exports.teachConfigError = exports.classifyConfigProblem = exports.CONFIG_TEACHING = exports.mergeLoadedRoutes = exports.loadRoutesWithExtra = exports.loadRoutes = exports.RouteConfigError = exports.renderFailureForTerminal = exports.teach = exports.FAILURE_TEACHING = exports.isRigFailure = exports.RigFailureError = exports.extractCitations = exports.createTavilySearchProvider = exports.sampleQuality = exports.pairedRegret = exports.wilson95 = exports.aggregateVariantMetrics = exports.OUTPUT_MAX_BYTES = exports.retentionExpiry = exports.truncateOutput = exports.selectArmsToKeep = exports.buildBakeoffSamples = exports.createBakeoffSamplesClient = exports.deriveSwapDirection = exports.bakeoffEvidence = exports.computeProposal = exports.mirrorBakeoff = exports.runBakeoff = exports.replayVariant = exports.openTelemetryStore = exports.openCaptureStore = void 0;
30
+ exports.RUNG1_MIN_GRADES = exports.computeCoverage = exports.computeParity = exports.factsUnderCredential = exports.factsFor = exports.PROBE_FRESHNESS_SLO_DAYS = exports.stalenessSentence = exports.probeFreshness = exports.callNotesFor = exports.evaluateChallengerEligibility = exports.requirementPredicates = exports.PREDICATE_GLOSS = exports.ALL_CAPABILITY_PREDICATES = exports.explainEmptySelection = exports.hasCapability = exports.selectModels = exports.parseCapabilityQuery = exports.capabilityFactsFromEntry = exports.loadRegistryFacts = exports.fingerprintSchema = exports.loadManifest = exports.SNAPSHOT_BASIS = exports.describePricingV2 = exports.tierRates = exports.synthesizeFromFlat = exports.seededCachePolicyProviders = exports.getCachePolicy = exports.DEFAULT_CACHE_HYSTERESIS = exports.classifyCacheVerdict = exports.effectiveInputRate = exports.estimateCostUsd = exports.getPricingV2 = exports.getPricing = exports.resolveCandidates = exports.OPENAI_COMPAT_HOSTS = exports.shapeFireworksModelId = exports.classifyCompatFailure = exports.buildOpenAICompatParams = exports.createOpenAICompatAdapter = exports.createGrokAdapter = exports.createAnthropicAdapter = exports.createDeepSeekAdapter = exports.createOpenAIAdapter = exports.destinationSupported = exports.servedDestinations = exports.DEFAULT_DESTINATION = exports.DESTINATIONS = exports.GEMINI_THINKING_CAPABLE_MODELS = exports.createGeminiAdapter = exports.PROVIDER_KEY_ENV = void 0;
31
+ exports.ANALYTICS_SCAN_CAP = exports.selectableColumnsAreMetaSafe = exports.planAnalyticsRead = exports.evaluateAnalyticsQuery = exports.describeAnalyticsSchema = exports.parseQuery = exports.QueryGrammarError = exports.compileQuery = exports.writePriorsCells = exports.aggregatePairwiseFromTelemetry = exports.aggregatePriors = exports.DEFAULT_WATCH_MONTHLY_USD = exports.watchEnvelopeKey = exports.reserveWatchBudget = exports.WATCH_STATE_KEY = exports.createFileWatchStateStore = exports.createControlPlaneWatchStateStore = exports.createWatchStateStore = exports.saveWatchState = exports.loadWatchState = exports.computeWatchEvents = exports.buildPriceUniverse = exports.runWatchCycle = exports.DEFAULT_MONITOR_CONFIG = exports.createMonitorReads = exports.rollupConformRate = exports.evaluateConformDegradation = exports.runMonitorCycle = exports.assertTransition = exports.createProposalsClient = exports.MONITOR_SOURCE_PREFIX = exports.MONITOR_CYCLE_MARKER = exports.REGRET_MONITOR_MARGIN = exports.REGRET_MONITOR_MIN_N = exports.REGRET_MONITOR_BASELINE_DAYS = exports.REGRET_MONITOR_WINDOW_DAYS = exports.createRegretMonitorReads = exports.regretMonitorConfig = exports.cyclePointFromArtifact = exports.aggregateRegretBand = exports.evaluateRegretDrift = exports.runRegretMonitorCycle = exports.evaluateUpgradeOpportunities = exports.explainCacheContext = exports.PROPOSAL_TTL_DAYS = exports.regretBreachTriggerHash = exports.upgradeTriggerHash = exports.manualChallengerTriggerHash = exports.triggerHash = exports.evaluateEvents = void 0;
32
+ exports.computeOdometer = exports.createSwapsClient = exports.executeSwap = exports.trialVariantName = exports.buildDeclareTrialChange = exports.buildRestoreYaml = exports.buildSwapChange = exports.runTelemetryQuery = exports.RESERVED_DIMENSION_NAMES = exports.METRIC_COLUMNS = exports.DIMENSION_COLUMNS = exports.sinceIsoFor = exports.savedQueryById = exports.SAVED_QUERIES = void 0;
33
33
  exports.createRig = createRig;
34
34
  const build_adapters_1 = require("./adapters/build-adapters");
35
35
  const config_1 = require("./config");
@@ -41,6 +41,7 @@ const tools_register_1 = require("./prompts/tools-register");
41
41
  const run_1 = require("./run/run");
42
42
  const stream_1 = require("./run/stream");
43
43
  const raw_1 = require("./run/raw");
44
+ const record_call_1 = require("./run/record-call");
44
45
  const node_path_1 = require("node:path");
45
46
  const node_os_1 = require("node:os");
46
47
  const grounding_1 = require("./run/grounding");
@@ -69,10 +70,11 @@ const DEFAULT_REPLAY_ENVELOPE_USD = 10;
69
70
  function createRig(config) {
70
71
  // CE-8 (R1): `routesDir: null` is a first-class runRaw-only rig — skip route
71
72
  // loading, the manifest, and the serveability gate; route methods throw below.
72
- const routes = config.routesDir === null ? (0, rawonly_1.emptyRouteStore)() : (0, rawonly_1.loadRoutesOrReport)(config, config.routesDir);
73
+ const routesDir = (0, rawonly_1.effectiveRoutesDir)(config); // SURF-1: absent DEFAULT dir ⇒ warn + raw-only; explicit ⇒ load (throws if missing)
74
+ const routes = routesDir === null ? (0, rawonly_1.emptyRouteStore)() : (0, rawonly_1.loadRoutesOrReport)(config, routesDir);
73
75
  // rig.yaml lives at the rig dir root, one level above routes/
74
76
  // (modelrig/rig.yaml next to modelrig/routes/ — cost-dimensions-design §2a).
75
- const manifest = config.routesDir === null ? null : (0, manifest_1.loadManifest)((0, node_path_1.dirname)(config.routesDir));
77
+ const manifest = routesDir === null ? null : (0, manifest_1.loadManifest)((0, node_path_1.dirname)(routesDir));
76
78
  // Registry facts load BEFORE adapters: the A1 compat hosts take their
77
79
  // capability profile from the registry, never from the dialect.
78
80
  const registryFacts = (0, facts_1.loadRegistryFacts)(config.registryPath);
@@ -250,6 +252,7 @@ function createRig(config) {
250
252
  runRawStream(input) {
251
253
  return (0, raw_1.runRawStream)(rawDeps, input);
252
254
  },
255
+ recordCall: (input) => (0, record_call_1.recordCall)(rawDeps, input),
253
256
  grade: gradeApi.grade,
254
257
  replay(route, opts) {
255
258
  return (0, replay_1.replayVariant)(deps, captureStoreForReplay(), {
@@ -326,7 +329,7 @@ function createRig(config) {
326
329
  // CE-8 (R1): a runRaw-only rig (routesDir: null) has no routes — override
327
330
  // every route-dependent surface to throw a teaching invariant_violation.
328
331
  // Spread LAST so it wins over the real methods above; empty for a routed rig.
329
- ...(config.routesDir === null ? (0, rawonly_1.rawOnlyRouteMethods)() : {}),
332
+ ...(routesDir === null ? (0, rawonly_1.rawOnlyRouteMethods)(config.routesDir === null ? "routesDir-null" : "absent-default") : {}),
330
333
  };
331
334
  }
332
335
  var config_2 = require("./config");
@@ -471,6 +474,13 @@ Object.defineProperty(exports, "resolveCallConfigForRun", { enumerable: true, ge
471
474
  var raw_2 = require("./run/raw");
472
475
  Object.defineProperty(exports, "runRaw", { enumerable: true, get: function () { return raw_2.runRaw; } });
473
476
  Object.defineProperty(exports, "runRawStream", { enumerable: true, get: function () { return raw_2.runRawStream; } });
477
+ var lanes_1 = require("./telemetry/lanes");
478
+ Object.defineProperty(exports, "isRoutedLane", { enumerable: true, get: function () { return lanes_1.isRoutedLane; } });
479
+ Object.defineProperty(exports, "callLaneOf", { enumerable: true, get: function () { return lanes_1.callLaneOf; } });
480
+ Object.defineProperty(exports, "RAW_LANE", { enumerable: true, get: function () { return lanes_1.RAW_LANE; } });
481
+ Object.defineProperty(exports, "EXTERNAL_LANE", { enumerable: true, get: function () { return lanes_1.EXTERNAL_LANE; } });
482
+ Object.defineProperty(exports, "RECORDED_BADGE", { enumerable: true, get: function () { return lanes_1.RECORDED_BADGE; } });
483
+ Object.defineProperty(exports, "RECORDED_TOOLTIP", { enumerable: true, get: function () { return lanes_1.RECORDED_TOOLTIP; } });
474
484
  // CE-8 runRaw-only (routesDir: null): the string-narrowing guard route-required
475
485
  // consumers (server, oracle) use, plus the teaching failure it throws.
476
486
  var rawonly_2 = require("./run/rawonly");
@@ -1 +1 @@
1
- {"version":3,"file":"init-cli.d.ts","sourceRoot":"","sources":["../../src/init/init-cli.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AASH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAGlD,wBAAgB,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAwFnD"}
1
+ {"version":3,"file":"init-cli.d.ts","sourceRoot":"","sources":["../../src/init/init-cli.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AASH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAelD,wBAAgB,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CA+FnD"}
@@ -15,13 +15,23 @@ const rawonly_1 = require("../run/rawonly");
15
15
  const rows_1 = require("../registry/rows");
16
16
  const observe_cli_1 = require("./observe-cli");
17
17
  const run_1 = require("./run");
18
+ const starter_1 = require("./starter");
19
+ /** Write the starter route's schema + prompt (SURF-1, audit #2) and say so. */
20
+ function writeStarter(routesDir) {
21
+ const starter = (0, starter_1.writeStarterFiles)(routesDir, { existsSync: node_fs_1.existsSync, mkdirSync: node_fs_1.mkdirSync, writeFileSync: node_fs_1.writeFileSync }, { join: node_path_1.join, dirname: node_path_1.dirname });
22
+ if (starter.written.length > 0) {
23
+ console.log(`\nwrote the starter route's schema and prompt (${starter.written.join(", ")}), so the\n` +
24
+ "example.support_summarize route shown in the console and the docs validates as pasted.");
25
+ }
26
+ }
18
27
  function cmdInit(flags) {
19
28
  // `init --observe` is the observe-first (T0/T1) alias for `modelrig observe`.
20
29
  if (flags.bare.has("observe"))
21
30
  return (0, observe_cli_1.cmdObserve)(flags);
22
31
  const root = (0, node_path_1.resolve)(flags.positional[0] ?? ".");
23
32
  const config = (0, config_1.loadConfigFromEnv)();
24
- const draftsDir = flags.named.get("out") ?? (0, node_path_1.join)((0, rawonly_1.requireRoutesDir)(config, "modelrig init"), "drafts");
33
+ const routesDir = (0, rawonly_1.requireRoutesDir)(config, "modelrig init");
34
+ const draftsDir = flags.named.get("out") ?? (0, node_path_1.join)(routesDir, "drafts");
25
35
  const scope = (0, observe_cli_1.scopeFrom)(flags);
26
36
  // Registry rows seed the challenger candidates. A missing/unbuilt registry
27
37
  // is not fatal — drafts then carry the incumbent alone, and say so.
@@ -44,6 +54,9 @@ function cmdInit(flags) {
44
54
  ...(scope !== undefined ? { scope } : {}),
45
55
  });
46
56
  if (flags.bare.has("json")) {
57
+ const starter = flags.bare.has("dry-run")
58
+ ? { written: [], skipped: [] }
59
+ : (0, starter_1.writeStarterFiles)(routesDir, { existsSync: node_fs_1.existsSync, mkdirSync: node_fs_1.mkdirSync, writeFileSync: node_fs_1.writeFileSync }, { join: node_path_1.join, dirname: node_path_1.dirname });
47
60
  console.log(JSON.stringify({
48
61
  sitesFound: result.sitesFound,
49
62
  filesScanned: result.filesScanned,
@@ -56,17 +69,20 @@ function cmdInit(flags) {
56
69
  model: d.site.model,
57
70
  notes: d.site.notes,
58
71
  })),
59
- written: result.written,
60
- skipped: result.skipped,
72
+ written: [...result.written, ...starter.written],
73
+ skipped: [...result.skipped, ...starter.skipped],
61
74
  }, null, 2));
62
75
  return 0;
63
76
  }
64
77
  console.log(`modelrig init — scanned ${result.filesScanned} file(s) under ${root}` +
65
78
  (scope !== undefined ? ` (scoped to ${scope.join(", ")})` : "") +
66
79
  `\nfound ${result.sitesFound} provider call site(s)`);
80
+ const dryRun = flags.bare.has("dry-run");
67
81
  if (result.sitesFound === 0) {
68
82
  console.log("\nNothing to draft. If you know there are model calls here, they may sit behind a helper\n" +
69
83
  "that hides the SDK — point init at the file that actually calls the provider.");
84
+ if (!dryRun)
85
+ writeStarter(routesDir);
70
86
  return 0;
71
87
  }
72
88
  for (const draft of result.drafts) {
@@ -76,10 +92,11 @@ function cmdInit(flags) {
76
92
  if (result.filesSkipped.length > 0) {
77
93
  console.log(`\n${result.filesSkipped.length} file(s) skipped (too large or unreadable).`);
78
94
  }
79
- if (flags.bare.has("dry-run")) {
95
+ if (dryRun) {
80
96
  console.log("\n--dry-run: nothing written.");
81
97
  return 0;
82
98
  }
99
+ writeStarter(routesDir);
83
100
  console.log(`\nwrote ${result.written.length} file(s) to ${draftsDir}` +
84
101
  (result.skipped.length > 0 ? ` (${result.skipped.length} left alone — already there)` : "") +
85
102
  `\nread ${(0, node_path_1.join)(draftsDir, "MIGRATION.md")} next. Your source was not touched.`);
@@ -69,6 +69,6 @@ function cmdObserve(flags) {
69
69
  console.log(`\nwrote ${result.written.length} file(s) to ${outDir}` +
70
70
  (result.skipped.length > 0 ? ` (${result.skipped.length} left alone — already there)` : "") +
71
71
  `\nread ${(0, node_path_1.join)(outDir, "OBSERVE.md")} next — apply the wiring diffs one step at a time.` +
72
- "\nObserve changes no behaviour; with no control plane configured your pipeline is byte-for-byte the same.");
72
+ "\nObserve changes no behaviour; with no MODELRIG_API_KEY set your pipeline is byte-for-byte the same.");
73
73
  return 0;
74
74
  }
@@ -70,7 +70,13 @@ export interface ObserveDeps {
70
70
  export declare function stepKeyFor(site: CallSite, used: Set<string>): string;
71
71
  /** The generated seam. Self-contained and fresh (never resurrected from git
72
72
  * history — that is the point of onboarding-test run-2). Mirrors the reference
73
- * `recordStep` in instrumentation.md, plus a `withRun` boundary wrapper. */
73
+ * `recordStep` in instrumentation.md, plus a `withRun` boundary wrapper.
74
+ *
75
+ * SURF-1 (audit #1, #6): the rig is built `routesDir: null` (observe needs no
76
+ * routes, and the default dir is absent in a fresh repo — the old seam crashed
77
+ * the customer's app on import), and `recordStep` reports the provider call
78
+ * through `rig.recordCall` so the step carries tokens and a cost and the call
79
+ * shows on /inferences. */
74
80
  export declare function seamContent(): string;
75
81
  export declare function buildObserveMarkdown(plans: readonly ObservePlan[], seamPath: string, result: {
76
82
  sitesFound: number;
@@ -1 +1 @@
1
- {"version":3,"file":"observe.d.ts","sourceRoot":"","sources":["../../src/init/observe.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE9C;kFACkF;AAClF,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,gFAAgF;IAChF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,wDAAwD;IACxD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,SAAS,WAAW,EAAE,CAAC;IACvC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,6DAA6D;IAC7D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,wDAAwD;IACxD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,uEAAuE;IACvE,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAED,MAAM,WAAW,cAAe,SAAQ,aAAa;IACnD,0CAA0C;IAC1C,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,iFAAiF;IACjF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,EAAE,cAAc,GAAG;QAC5B,UAAU,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;QACnC,SAAS,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE;YAAE,SAAS,EAAE,OAAO,CAAA;SAAE,KAAK,IAAI,CAAC;QAC1D,aAAa,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;KAC1D,CAAC;IACF,QAAQ,CAAC,IAAI,EAAE;QACb,IAAI,EAAE,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,KAAK,MAAM,CAAC;QACrC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC;QAC/C,OAAO,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;QAC/B,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;KAC/C,CAAC;CACH;AAKD;iFACiF;AACjF,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,CAQpE;AAED;;4EAE4E;AAC5E,wBAAgB,WAAW,IAAI,MAAM,CA6DpC;AAoCD,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,SAAS,WAAW,EAAE,EAC7B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,EACrF,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,GACxB,MAAM,CAmHR;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,GAAE,cAAmB,GAAG,aAAa,CA6DzF"}
1
+ {"version":3,"file":"observe.d.ts","sourceRoot":"","sources":["../../src/init/observe.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE9C;kFACkF;AAClF,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,gFAAgF;IAChF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,wDAAwD;IACxD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,SAAS,WAAW,EAAE,CAAC;IACvC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,6DAA6D;IAC7D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,wDAAwD;IACxD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,uEAAuE;IACvE,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAED,MAAM,WAAW,cAAe,SAAQ,aAAa;IACnD,0CAA0C;IAC1C,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,iFAAiF;IACjF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,EAAE,cAAc,GAAG;QAC5B,UAAU,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;QACnC,SAAS,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE;YAAE,SAAS,EAAE,OAAO,CAAA;SAAE,KAAK,IAAI,CAAC;QAC1D,aAAa,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;KAC1D,CAAC;IACF,QAAQ,CAAC,IAAI,EAAE;QACb,IAAI,EAAE,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,KAAK,MAAM,CAAC;QACrC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC;QAC/C,OAAO,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;QAC/B,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;KAC/C,CAAC;CACH;AAUD;iFACiF;AACjF,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,CAQpE;AAED;;;;;;;;2BAQ2B;AAC3B,wBAAgB,WAAW,IAAI,MAAM,CA6EpC;AA6DD,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,SAAS,WAAW,EAAE,EAC7B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,EACrF,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,GACxB,MAAM,CA0HR;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,GAAE,cAAmB,GAAG,aAAa,CA6DzF"}
@@ -25,6 +25,10 @@ exports.seamContent = seamContent;
25
25
  exports.buildObserveMarkdown = buildObserveMarkdown;
26
26
  exports.runObserve = runObserve;
27
27
  const finder_1 = require("./finder");
28
+ /** The `environment` expression the wiring diff proposes. Assembled so this
29
+ * source file never holds the literal env-read token (package invariant: only
30
+ * config.ts reads the environment). */
31
+ const ENV_EXPR = `${["process", "env", "NODE_ENV"].join(".")} ?? "development"`;
28
32
  const normalize = (s) => s.replace(/[^A-Za-z0-9]+/g, "_").replace(/^_|_$/g, "").toLowerCase();
29
33
  /** A stable step key from a call site: `<dir>_<file>_<line>`, deduped so two
30
34
  * sites never collide. Deterministic, so a second run proposes the same keys. */
@@ -40,33 +44,43 @@ function stepKeyFor(site, used) {
40
44
  }
41
45
  /** The generated seam. Self-contained and fresh (never resurrected from git
42
46
  * history — that is the point of onboarding-test run-2). Mirrors the reference
43
- * `recordStep` in instrumentation.md, plus a `withRun` boundary wrapper. */
47
+ * `recordStep` in instrumentation.md, plus a `withRun` boundary wrapper.
48
+ *
49
+ * SURF-1 (audit #1, #6): the rig is built `routesDir: null` (observe needs no
50
+ * routes, and the default dir is absent in a fresh repo — the old seam crashed
51
+ * the customer's app on import), and `recordStep` reports the provider call
52
+ * through `rig.recordCall` so the step carries tokens and a cost and the call
53
+ * shows on /inferences. */
44
54
  function seamContent() {
45
55
  return `/**
46
56
  * ModelRig observe seam — generated by \`modelrig observe\`.
47
57
  *
48
58
  * This is YOURS to keep and edit; it is generated fresh (not copied from any
49
59
  * deleted seam) so it always matches the current SDK. It records each pipeline
50
- * run as a run -> step -> artifact chain you click through in the console.
60
+ * run as a run -> step -> artifact chain you click through in the console, and
61
+ * each model call as a recorded inference with its tokens and cost.
51
62
  *
52
- * Observe-only: no routes move, no model calls are rerouted. With no control
53
- * plane configured (or the org capture posture set to off) every call here is
54
- * inert and your pipeline behaves byte-for-byte as before. Nothing here ever
55
- * throws into your pipeline — a telemetry write that fails is logged and
63
+ * Observe-only: no routes move, no model calls are rerouted. Your code keeps
64
+ * calling the provider with your own key; this file only REPORTS what happened.
65
+ * With no MODELRIG_API_KEY (or the org capture posture set to off) every call
66
+ * here is inert and your pipeline behaves byte-for-byte as before. Nothing here
67
+ * ever throws into your pipeline — a telemetry write that fails is logged and
56
68
  * dropped (instrumentation.md, "Never throws into your pipeline").
57
69
  *
58
70
  * Docs: https://modelrig.dev/instrumentation.html
59
71
  */
60
72
 
61
- import { createRig, loadConfigFromEnv, type Rig } from "modelrig";
73
+ import { createRig, loadConfigFromEnv, type RecordCallInput, type Rig } from "modelrig";
62
74
 
63
- const rig: Rig = createRig(loadConfigFromEnv());
75
+ // routesDir: null — observe needs no route files, so the rig is raw-only and
76
+ // never looks for ./modelrig/routes (importing this file cannot throw).
77
+ const rig: Rig = createRig({ ...loadConfigFromEnv(), routesDir: null });
64
78
 
65
79
  /** Open a run context around a whole pipeline, close it on success/failure.
66
80
  * \`episodeKey\` is a grouping key (a natural choice: your per-run attempt id),
67
- * not a unique id. Pass \`environment\` (e.g. your NODE_ENV) to tag the run.
68
- * Use \`rig.artifacts.run.scope(...)\` instead for concurrent runs in one
69
- * process. */
81
+ * not a unique id. Pass \`environment\` (e.g. your NODE_ENV) so the Env column
82
+ * on /runs is filled. Use \`rig.artifacts.run.scope(...)\` instead for
83
+ * concurrent runs in one process. */
70
84
  export async function withRun<T>(
71
85
  opts: { pipeline: string; episodeKey: string; environment?: string },
72
86
  body: () => Promise<T>,
@@ -86,14 +100,20 @@ export async function withRun<T>(
86
100
  }
87
101
  }
88
102
 
89
- /** Save prompt + raw + parsed for one step, link lineage, flag conformance.
90
- * A stage whose model call does NOT go through the rig still produces
91
- * artifacts (with \`stepKey\` set and no step row) — correct and honest; the
92
- * console renders "cost n/a" rather than inventing a number. */
103
+ /** The provider call your code made, as the provider reported it. Recorded with
104
+ * \`rig.recordCall\` so the step carries tokens and a cost ("recorded ·
105
+ * unverified": ModelRig did not dispatch it). */
106
+ export type StepCall = Omit<RecordCallInput, "stepKey">;
107
+
108
+ /** Record one step: report the provider call (tokens → cost on /runs and
109
+ * /inferences), save prompt + raw + parsed, link lineage, flag conformance.
110
+ * Leave \`call\` out only when you have no usage numbers; the step then shows
111
+ * "cost n/a". */
93
112
  export function recordStep(
94
113
  stepKey: string,
95
- work: { prompt: string; rawText: string; json: unknown; conforms: boolean },
114
+ work: { prompt: string; rawText: string; json: unknown; conforms: boolean; call?: StepCall },
96
115
  ): void {
116
+ if (work.call !== undefined) rig.recordCall({ ...work.call, stepKey });
97
117
  const p = rig.artifacts.artifact.save(work.prompt, { name: \`\${stepKey}.prompt\`, type: "prompt", stepKey });
98
118
  const raw = rig.artifacts.artifact.save(work.rawText, { name: \`\${stepKey}.raw\`, type: "raw_response", stepKey });
99
119
  const parsed = rig.artifacts.artifact.save(work.json, { name: \`\${stepKey}.output\`, type: "step_output", task: stepKey, stepKey });
@@ -101,6 +121,12 @@ export function recordStep(
101
121
  if (raw && parsed) rig.artifacts.artifact.link(parsed, raw, "derived_from");
102
122
  if (parsed) rig.grade({ kind: "artifact", id: parsed.id }, { score: work.conforms ? 1 : 0, kind: "deterministic", grader: "schema-check" });
103
123
  }
124
+
125
+ /** Flush and close the rig. Await it once at shutdown (a one-shot script that
126
+ * exits without it can lose the last batch). */
127
+ export function closeRig(): Promise<void> {
128
+ return rig.close();
129
+ }
104
130
  `;
105
131
  }
106
132
  /** The import specifier a source file uses to reach the seam. Best-effort
@@ -110,12 +136,36 @@ function importSpecifier(fromFile, seamPath, path) {
110
136
  const rel = path.relative(path.dirname(fromFile), noExt);
111
137
  return rel.startsWith(".") ? rel : `./${rel}`;
112
138
  }
113
- function recordStepSnippet(stepKey) {
139
+ /** How the customer's provider response reports usage, per provider family —
140
+ * the expressions the wiring diff proposes for `call.usage` (the human/agent
141
+ * adjusts the variable name). Unknown providers get a placeholder. */
142
+ const USAGE_EXPR = {
143
+ openai: { tokensIn: "res.usage?.prompt_tokens ?? 0", tokensOut: "res.usage?.completion_tokens ?? 0" },
144
+ deepseek: { tokensIn: "res.usage?.prompt_tokens ?? 0", tokensOut: "res.usage?.completion_tokens ?? 0" },
145
+ grok: { tokensIn: "res.usage?.prompt_tokens ?? 0", tokensOut: "res.usage?.completion_tokens ?? 0" },
146
+ deepinfra: { tokensIn: "res.usage?.prompt_tokens ?? 0", tokensOut: "res.usage?.completion_tokens ?? 0" },
147
+ fireworks: { tokensIn: "res.usage?.prompt_tokens ?? 0", tokensOut: "res.usage?.completion_tokens ?? 0" },
148
+ anthropic: { tokensIn: "res.usage.input_tokens", tokensOut: "res.usage.output_tokens" },
149
+ // Gemini bills thinking tokens as output: candidates + thoughts (SURF-1 QA).
150
+ gemini: {
151
+ tokensIn: "res.usageMetadata?.promptTokenCount ?? 0",
152
+ tokensOut: "(res.usageMetadata?.candidatesTokenCount ?? 0) + (res.usageMetadata?.thoughtsTokenCount ?? 0)",
153
+ },
154
+ };
155
+ function recordStepSnippet(site, stepKey) {
156
+ const usage = USAGE_EXPR[site.provider] ?? { tokensIn: "/* input tokens */ 0", tokensOut: "/* output tokens */ 0" };
157
+ const model = site.model !== null ? JSON.stringify(site.model) : site.modelExpression ?? '"<model id>"';
114
158
  return (`recordStep(${JSON.stringify(stepKey)}, {\n` +
115
159
  ` prompt, // the assembled prompt string\n` +
116
160
  ` rawText, // the model's raw text, pre-parse\n` +
117
161
  ` json: parsed, // your parsed/validated output\n` +
118
162
  ` conforms, // did it satisfy your schema?\n` +
163
+ ` call: { // what the provider reported → tokens + cost (rig.recordCall)\n` +
164
+ ` provider: ${JSON.stringify(site.provider)},\n` +
165
+ ` model: ${model},\n` +
166
+ ` usage: { tokensIn: ${usage.tokensIn}, tokensOut: ${usage.tokensOut} },\n` +
167
+ ` latencyMs, // Date.now() after the call minus before it\n` +
168
+ ` },\n` +
119
169
  `});`);
120
170
  }
121
171
  /** The run boundary is most likely the shallowest detected file (the entry
@@ -139,7 +189,7 @@ function buildObserveMarkdown(plans, seamPath, result, path) {
139
189
  "**Nothing in your source has changed.** `modelrig observe` generated one seam helper",
140
190
  `(\`${seamPath}\`) and this plan. Observe is **not migration**: no routes were drafted, no`,
141
191
  "model calls rerouted. Applying the wiring below records each run as a run → step →",
142
- "artifact chain you click through in the console — and with the flag off, your pipeline",
192
+ "artifact chain you click through in the console — and with no key set, your pipeline",
143
193
  "behaves **byte-for-byte** as before.",
144
194
  "",
145
195
  `Detected **${result.sitesFound} model call site(s)** across ${result.filesScanned} scanned file(s);`,
@@ -154,9 +204,11 @@ function buildObserveMarkdown(plans, seamPath, result, path) {
154
204
  "",
155
205
  "```bash",
156
206
  "export MODELRIG_API_KEY=<key> # mint at https://app.modelrig.ai (/keys)",
157
- "# export MODELRIG_ARTIFACT_STEPS=step_a,step_b # optional: instrument a subset",
158
207
  "```",
159
208
  "",
209
+ "The seam builds its rig with `routesDir: null`: observe needs no route files, so importing",
210
+ "it never looks for `./modelrig/routes`.",
211
+ "",
160
212
  "> **Human handoff (one step, once).** Seeing these runs **in the console** needs a free",
161
213
  "> account + an API key minted at <https://app.modelrig.ai> (`/keys`) — a console login a",
162
214
  "> coding agent cannot perform. Set `MODELRIG_API_KEY=<key>` once a human provides it; the",
@@ -174,7 +226,7 @@ function buildObserveMarkdown(plans, seamPath, result, path) {
174
226
  lines.push("## 2. Open a run context around the pipeline", "", boundary === null
175
227
  ? "Wrap your pipeline's entry point in `withRun(...)` from the seam helper:"
176
228
  : `Your pipeline entry looks like \`${boundary}\` (the shallowest detected call site — a` +
177
- " heuristic; move this if your real entry is elsewhere). Wrap it in `withRun(...)`:", "", "```diff", `+ import { withRun } from "${boundaryImport}";`, "", "- export async function runPipeline(input) {", "- /* ... your steps ... */", "- }", "+ export async function runPipeline(input) {", "+ return withRun(", '+ { pipeline: "my-pipeline", episodeKey: input.attemptId },', "+ async () => {", "+ /* ... your steps ... */", "+ },", "+ );", "+ }", "```", "", "## 3. Record each step's work products", "", "Each detected model call is one step. After the call parses its output, add a `recordStep`", "(the diffs below quote the call line so you can find it):", "");
229
+ " heuristic; move this if your real entry is elsewhere). Wrap it in `withRun(...)`:", "", "```diff", `+ import { withRun } from "${boundaryImport}";`, "", "- export async function runPipeline(input) {", "- /* ... your steps ... */", "- }", "+ export async function runPipeline(input) {", "+ return withRun(", `+ { pipeline: "my-pipeline", episodeKey: input.attemptId, environment: ${ENV_EXPR} },`, "+ async () => {", "+ /* ... your steps ... */", "+ },", "+ );", "+ }", "```", "", "## 3. Record each step's work products", "", "Each detected model call is one step. After the call parses its output, add a `recordStep`", "(the diffs below quote the call line so you can find it). Its `call` field reports what the", "provider returned through `rig.recordCall`, so the step carries tokens and a cost and the call", "shows on /inferences as \"recorded · unverified\". Time the call (`const t0 = Date.now()` before,", "`const latencyMs = Date.now() - t0` after) and rename `res` to your response variable:", "");
178
230
  // Group the per-site wiring diffs by file so each file gets one import line.
179
231
  const byFile = new Map();
180
232
  for (const plan of plans) {
@@ -190,7 +242,7 @@ function buildObserveMarkdown(plans, seamPath, result, path) {
190
242
  }
191
243
  lines.push("```", "");
192
244
  }
193
- lines.push("## 4. See it", "", "Run your pipeline once, then open the console: **Runs** lists the run, `/runs/[id]` renders", "the semantic chain (artifacts grouped by step, with hashes and evaluation badges), and", "`/artifacts/[id]` shows one artifact's lineage. Un-routed steps show **cost n/a** — correct", "for observe-only; nothing routes through the rig yet.", "", "## When you are ready to migrate (later, optional)", "", "Observe answers *what is my pipeline doing?* When you want to *change what serves a step*,", "that is route extraction (T2) — a separate, behaviour-affecting move behind its own review:", "`modelrig init --scope <this pipeline>`. Observe first is the safer order.", "");
245
+ lines.push("## 4. See it", "", "Run your pipeline once, then open the console: **Runs** lists the run, `/runs/[id]` renders", "the semantic chain (artifacts grouped by step, with hashes and evaluation badges), and", "`/artifacts/[id]` shows one artifact's lineage, and **Inferences** lists each recorded call", "with its cost. A step you wired without `call` shows **cost n/a**: ModelRig has no usage", "numbers for it. In a script that exits, `await closeRig()` once at the end so the last batch", "ships. Calls your code makes outside `recordStep` stay invisible: https://modelrig.dev/not-captured.html", "", "## When you are ready to migrate (later, optional)", "", "Observe answers *what is my pipeline doing?* When you want to *change what serves a step*,", "that is route extraction (T2) — a separate, behaviour-affecting move behind its own review:", "`modelrig init --scope <this pipeline>`. Observe first is the safer order.", "");
194
246
  return `${lines.join("\n")}\n`;
195
247
  }
196
248
  function runObserve(deps, options = {}) {
@@ -198,7 +250,7 @@ function runObserve(deps, options = {}) {
198
250
  const used = new Set();
199
251
  const plans = scan.sites.map((site) => {
200
252
  const stepKey = stepKeyFor(site, used);
201
- return { site, stepKey, snippet: recordStepSnippet(stepKey) };
253
+ return { site, stepKey, snippet: recordStepSnippet(site, stepKey) };
202
254
  });
203
255
  const seamPath = deps.path.join(deps.outDir, "record-step.ts");
204
256
  // Import specifiers and prose are computed root-relative — call sites come
@@ -0,0 +1,36 @@
1
+ /**
2
+ * The starter route's companion files (SURF-1, audit #2). Every on-ramp shows
3
+ * the same starter route, `example.support_summarize` (console
4
+ * STARTER_ROUTE_YAML, www /get-started, quickstart §3), and that YAML references
5
+ * `./schemas/support_summarize.schema.json` and
6
+ * `./prompts/support_summarize.system.md`. Neither shipped in the npm tarball,
7
+ * so a customer who pasted the route got "schema file not found" from
8
+ * `modelrig validate`. `modelrig init` now writes both next to the routes dir
9
+ * (never clobbering), and `surf1-setup.test.ts` asserts these constants equal the
10
+ * package's own committed example files and that the starter validates.
11
+ *
12
+ * They are support files, not routes: the loader reads only top-level *.yaml,
13
+ * so writing them can never change what a rig serves.
14
+ */
15
+ /** Path of each companion file, relative to the routes directory. */
16
+ export declare const STARTER_SCHEMA_PATH = "schemas/support_summarize.schema.json";
17
+ export declare const STARTER_PROMPT_PATH = "prompts/support_summarize.system.md";
18
+ export declare const STARTER_SCHEMA_JSON = "{\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"title\": \"support_summarize\",\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\"summary\", \"handoff\"],\n \"properties\": {\n \"summary\": {\n \"type\": \"string\",\n \"minLength\": 40,\n \"description\": \"One paragraph a human agent can act on without reading the thread.\"\n },\n \"severity\": { \"type\": \"string\", \"enum\": [\"low\", \"normal\", \"high\", \"urgent\"] },\n \"handoff\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\"team\", \"reason\"],\n \"properties\": {\n \"team\": { \"type\": \"string\", \"enum\": [\"billing\", \"technical\", \"account\", \"none\"] },\n \"reason\": { \"type\": \"string\", \"minLength\": 10 }\n }\n }\n }\n}\n";
19
+ export declare const STARTER_PROMPT_MD = "You summarise a customer support ticket for the agent who picks it up next.\n\nProduct: {{product}}\n\nEarlier context on this customer (may be \"none\"):\n{{priorContext}}\n\nTicket:\n{{ticket}}\n\nWrite one actionable paragraph, judge severity, and name the team it should go\nto (or `none` if the summary closes it).\n\n{{#unless capability.structured_native}}\nReturn ONLY a JSON object matching this shape \u2014 no prose, no code fence:\n{\"summary\": string, \"severity\": \"low\"|\"normal\"|\"high\"|\"urgent\",\n \"handoff\": {\"team\": \"billing\"|\"technical\"|\"account\"|\"none\", \"reason\": string}}\n{{/unless}}\n";
20
+ export interface StarterFs {
21
+ existsSync: (p: string) => boolean;
22
+ mkdirSync: (p: string, o: {
23
+ recursive: boolean;
24
+ }) => void;
25
+ writeFileSync: (p: string, c: string, e: "utf8") => void;
26
+ }
27
+ /** Write the starter's schema and prompt under `routesDir`, leaving any file that
28
+ * already exists alone (it is the customer's). Returns what was written/skipped. */
29
+ export declare function writeStarterFiles(routesDir: string, fs: StarterFs, path: {
30
+ join: (...parts: string[]) => string;
31
+ dirname: (p: string) => string;
32
+ }): {
33
+ written: string[];
34
+ skipped: string[];
35
+ };
36
+ //# sourceMappingURL=starter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"starter.d.ts","sourceRoot":"","sources":["../../src/init/starter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,qEAAqE;AACrE,eAAO,MAAM,mBAAmB,0CAA0C,CAAC;AAC3E,eAAO,MAAM,mBAAmB,wCAAwC,CAAC;AAEzE,eAAO,MAAM,mBAAmB,w2BAwB/B,CAAC;AAEF,eAAO,MAAM,iBAAiB,0nBAkB7B,CAAC;AAEF,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;IACnC,SAAS,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;IAC1D,aAAa,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1D;AAED;oFACoF;AACpF,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,EAAE,EAAE,SAAS,EACb,IAAI,EAAE;IAAE,IAAI,EAAE,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,KAAK,MAAM,CAAC;IAAC,OAAO,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;CAAE,GAC7E;IAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAiB1C"}
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ /**
3
+ * The starter route's companion files (SURF-1, audit #2). Every on-ramp shows
4
+ * the same starter route, `example.support_summarize` (console
5
+ * STARTER_ROUTE_YAML, www /get-started, quickstart §3), and that YAML references
6
+ * `./schemas/support_summarize.schema.json` and
7
+ * `./prompts/support_summarize.system.md`. Neither shipped in the npm tarball,
8
+ * so a customer who pasted the route got "schema file not found" from
9
+ * `modelrig validate`. `modelrig init` now writes both next to the routes dir
10
+ * (never clobbering), and `surf1-setup.test.ts` asserts these constants equal the
11
+ * package's own committed example files and that the starter validates.
12
+ *
13
+ * They are support files, not routes: the loader reads only top-level *.yaml,
14
+ * so writing them can never change what a rig serves.
15
+ */
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.STARTER_PROMPT_MD = exports.STARTER_SCHEMA_JSON = exports.STARTER_PROMPT_PATH = exports.STARTER_SCHEMA_PATH = void 0;
18
+ exports.writeStarterFiles = writeStarterFiles;
19
+ /** Path of each companion file, relative to the routes directory. */
20
+ exports.STARTER_SCHEMA_PATH = "schemas/support_summarize.schema.json";
21
+ exports.STARTER_PROMPT_PATH = "prompts/support_summarize.system.md";
22
+ exports.STARTER_SCHEMA_JSON = `{
23
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
24
+ "title": "support_summarize",
25
+ "type": "object",
26
+ "additionalProperties": false,
27
+ "required": ["summary", "handoff"],
28
+ "properties": {
29
+ "summary": {
30
+ "type": "string",
31
+ "minLength": 40,
32
+ "description": "One paragraph a human agent can act on without reading the thread."
33
+ },
34
+ "severity": { "type": "string", "enum": ["low", "normal", "high", "urgent"] },
35
+ "handoff": {
36
+ "type": "object",
37
+ "additionalProperties": false,
38
+ "required": ["team", "reason"],
39
+ "properties": {
40
+ "team": { "type": "string", "enum": ["billing", "technical", "account", "none"] },
41
+ "reason": { "type": "string", "minLength": 10 }
42
+ }
43
+ }
44
+ }
45
+ }
46
+ `;
47
+ exports.STARTER_PROMPT_MD = `You summarise a customer support ticket for the agent who picks it up next.
48
+
49
+ Product: {{product}}
50
+
51
+ Earlier context on this customer (may be "none"):
52
+ {{priorContext}}
53
+
54
+ Ticket:
55
+ {{ticket}}
56
+
57
+ Write one actionable paragraph, judge severity, and name the team it should go
58
+ to (or \`none\` if the summary closes it).
59
+
60
+ {{#unless capability.structured_native}}
61
+ Return ONLY a JSON object matching this shape — no prose, no code fence:
62
+ {"summary": string, "severity": "low"|"normal"|"high"|"urgent",
63
+ "handoff": {"team": "billing"|"technical"|"account"|"none", "reason": string}}
64
+ {{/unless}}
65
+ `;
66
+ /** Write the starter's schema and prompt under `routesDir`, leaving any file that
67
+ * already exists alone (it is the customer's). Returns what was written/skipped. */
68
+ function writeStarterFiles(routesDir, fs, path) {
69
+ const written = [];
70
+ const skipped = [];
71
+ for (const [rel, body] of [
72
+ [exports.STARTER_SCHEMA_PATH, exports.STARTER_SCHEMA_JSON],
73
+ [exports.STARTER_PROMPT_PATH, exports.STARTER_PROMPT_MD],
74
+ ]) {
75
+ const file = path.join(routesDir, rel);
76
+ if (fs.existsSync(file)) {
77
+ skipped.push(file);
78
+ continue;
79
+ }
80
+ fs.mkdirSync(path.dirname(file), { recursive: true });
81
+ fs.writeFileSync(file, body, "utf8");
82
+ written.push(file);
83
+ }
84
+ return { written, skipped };
85
+ }
@@ -9,14 +9,50 @@
9
9
  * recorder — NO route/registry/capability-gate dependency.
10
10
  */
11
11
  import { type ActiveRunContext } from "../artifacts/run-context";
12
- import type { AdapterResult, ServiceTier } from "../types/provider";
13
- import type { RunResult } from "../types/route";
12
+ import type { AdapterResult, AdapterUsage, ProviderId, ServiceTier } from "../types/provider";
13
+ import type { RunResult, RunTags } from "../types/route";
14
+ import type { AttemptMetaV1 } from "../telemetry/attempt-meta";
15
+ import type { TelemetryRow, TelemetryStore } from "../types/telemetry";
14
16
  import type { RawRunDeps, RawRunInput } from "./raw";
15
17
  /** R1 — the teaching `fixHint` attached to a `timeout` failure on the raw lane:
16
18
  * it names the elapsed budget, the tier, that tier's advertised target, and the
17
19
  * two fixes (raise `timeoutMs`, or drop to `standard`). Built from
18
20
  * `RAW_TIMEOUT_DEFAULT_MS` so the default it quotes can never drift. */
19
21
  export declare function rawTimeoutFixHint(input: RawRunInput, tier: ServiceTier): string;
22
+ export interface RawRowParts {
23
+ readonly id: string;
24
+ readonly rawModelId: string;
25
+ /** A `ProviderId` on the raw lane; any non-empty string on a recorded call
26
+ * (OBS-1 `rig.recordCall` accepts providers ModelRig has no adapter for). */
27
+ readonly provider: ProviderId | string;
28
+ readonly model: string;
29
+ readonly usage?: AdapterUsage;
30
+ readonly costUsd: number;
31
+ readonly latencyMs: number;
32
+ /** CE-2 F2: the DECLARED service tier (default "standard"), reported truthfully
33
+ * on the row instead of the old hardcode. */
34
+ readonly requestedTier: ServiceTier;
35
+ /** OBS-1: the served tier when no `usage` is supplied — unused on the raw
36
+ * lane (absent ⇒ `usage.servedTier ?? "standard"`, byte-identical). */
37
+ readonly servedTier?: ServiceTier;
38
+ readonly failureClass: TelemetryRow["failureClass"];
39
+ readonly tags: RunTags;
40
+ readonly pricingMissing: boolean;
41
+ /** CE-1: the customer cache key applied to this raw dispatch, or null. */
42
+ readonly cacheKey?: string | null;
43
+ /** The per-call ladder key (spec §2.1 R0). The raw lane is a single-attempt,
44
+ * single-candidate dispatch: one call_id, attempt_seq 1, candidate_index 0. */
45
+ readonly callId: string;
46
+ /** WI-1 attempt envelope (spec §2) — built by the SAME producer the routed
47
+ * lane uses (lane parity), from the SAME rendered-request canonicalization. */
48
+ readonly meta?: AttemptMetaV1 | null;
49
+ }
50
+ /** Write the metered raw-lane telemetry row. Mirrors the run loop's minimal
51
+ * `recordSearchCostRow` shape: only load-bearing fields set, route = the
52
+ * `provider/model` handle the caller used, lane + key_ownership riding in
53
+ * `tags_json`. The exporter mirrors it on its normal cadence — no lane column,
54
+ * no schema change (telemetry map, 2026-08-10). */
55
+ export declare function recordRawRow(telemetry: TelemetryStore, p: RawRowParts): void;
20
56
  /** The active-run-context binding a raw call resolves ONCE at entry (the ALS
21
57
  * boundary — read synchronously before the stream generator defers), so
22
58
  * `finalizeRaw` can mirror the call into a ground-truth step (G1 spec §4). Null
@@ -34,7 +70,17 @@ export interface RawStepContext {
34
70
  * unconditionally, as the routed lane does. Fail-open: no context ⇒ null and no
35
71
  * step is ever recorded; the dispatch is byte-identical to pre-G1.
36
72
  */
37
- export declare function prepareRawStep(deps: RawRunDeps, input: RawRunInput): RawStepContext | null;
73
+ export declare function prepareRawStep(deps: Pick<RawRunDeps, "manifest">, input: {
74
+ readonly provider: string;
75
+ readonly model: string;
76
+ readonly stepKey?: string;
77
+ readonly tags?: RunTags;
78
+ }): RawStepContext | null;
79
+ /** G1: mirror one lane-B inference (raw, or an OBS-1 recorded call) into a
80
+ * ground-truth step — parity with the routed lane's record-attempt. No-op when
81
+ * no run context was captured at entry. Fail-open is handled inside
82
+ * `emitGroundTruthStep` (buffer errors are swallowed). */
83
+ export declare function emitRawStep(step: RawStepContext | null, task: string, inferenceId: string, failureClass: string | null): void;
38
84
  /**
39
85
  * Turn an `AdapterResult` into a RunResult, recording exactly one telemetry row.
40
86
  * Shared by the buffered and streaming paths so cost/telemetry are byte-identical.
@@ -1 +1 @@
1
- {"version":3,"file":"raw-finalize.d.ts","sourceRoot":"","sources":["../../src/run/raw-finalize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AASH,OAAO,EAIL,KAAK,gBAAgB,EACtB,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EACV,aAAa,EAGb,WAAW,EACZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAW,SAAS,EAAW,MAAM,gBAAgB,CAAC;AAKlE,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAErD;;;wEAGwE;AACxE,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,GAAG,MAAM,CAS/E;AA6ED;;;kFAGkF;AAClF,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAClC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,GAAG,cAAc,GAAG,IAAI,CAU1F;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,WAAW,EAClB,MAAM,EAAE,aAAa,EACrB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,cAAc,GAAG,IAAI,GAC1B,SAAS,CA6JX"}
1
+ {"version":3,"file":"raw-finalize.d.ts","sourceRoot":"","sources":["../../src/run/raw-finalize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AASH,OAAO,EAIL,KAAK,gBAAgB,EACtB,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EACV,aAAa,EACb,YAAY,EACZ,UAAU,EACV,WAAW,EACZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAW,SAAS,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE/D,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEvE,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAErD;;;wEAGwE;AACxE,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,GAAG,MAAM,CAS/E;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B;iFAC6E;IAC7E,QAAQ,CAAC,QAAQ,EAAE,UAAU,GAAG,MAAM,CAAC;IACvC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,CAAC,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;iDAC6C;IAC7C,QAAQ,CAAC,aAAa,EAAE,WAAW,CAAC;IACpC;2EACuE;IACvE,QAAQ,CAAC,UAAU,CAAC,EAAE,WAAW,CAAC;IAClC,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC,cAAc,CAAC,CAAC;IACpD,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,0EAA0E;IAC1E,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC;mFAC+E;IAC/E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;mFAC+E;IAC/E,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;CACtC;AAED;;;;mDAImD;AACnD,wBAAgB,YAAY,CAAC,SAAS,EAAE,cAAc,EAAE,CAAC,EAAE,WAAW,GAAG,IAAI,CA4C5E;AAED;;;kFAGkF;AAClF,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAClC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,EAClC,KAAK,EAAE;IAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GAC/G,cAAc,GAAG,IAAI,CAUvB;AAED;;;0DAG0D;AAC1D,wBAAgB,WAAW,CACzB,IAAI,EAAE,cAAc,GAAG,IAAI,EAC3B,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,GAAG,IAAI,GAC1B,IAAI,CAUN;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,WAAW,EAClB,MAAM,EAAE,aAAa,EACrB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,cAAc,GAAG,IAAI,GAC1B,SAAS,CA8JX"}