crosscheck-mcp 0.2.28 → 0.2.30

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/dist/embed.js CHANGED
@@ -7,6 +7,7 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
7
7
  });
8
8
 
9
9
  // src/entrypoints/embed.ts
10
+ import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
10
11
  import { existsSync as existsSync11 } from "fs";
11
12
  import path12 from "path";
12
13
  import { fileURLToPath as fileURLToPath2 } from "url";
@@ -178,6 +179,11 @@ function reasoningSharesOutputBudget(provider) {
178
179
  }
179
180
 
180
181
  // src/providers/types.ts
182
+ var IMAGE_MEDIA_TYPES = ["image/png", "image/jpeg", "image/webp", "image/gif"];
183
+ function imagesOf(m) {
184
+ if (m.role !== "user" || !Array.isArray(m.images)) return [];
185
+ return m.images.filter((i) => Boolean(i) && typeof i.data === "string" && i.data.length > 0 && IMAGE_MEDIA_TYPES.includes(i.mediaType));
186
+ }
181
187
  var ProviderError = class extends Error {
182
188
  name = "ProviderError";
183
189
  kind;
@@ -491,6 +497,52 @@ function rejectsDisabledThinking(model) {
491
497
  const m = model.toLowerCase();
492
498
  return ADAPTIVE_THINKING_PREFIXES.some((p) => m.startsWith(p));
493
499
  }
500
+ var NO_FORCED_TOOL_PREFIXES = [
501
+ "claude-fable-5-1",
502
+ "claude-mythos-5-1",
503
+ "claude-opus-5-5",
504
+ "claude-sonnet-5-5"
505
+ ];
506
+ function rejectsForcedToolUse(model) {
507
+ const m = model.toLowerCase();
508
+ return NO_FORCED_TOOL_PREFIXES.some((p) => m.startsWith(p));
509
+ }
510
+ var UNSUPPORTED_SCHEMA_KEYS = /* @__PURE__ */ new Set([
511
+ "minimum",
512
+ "maximum",
513
+ "exclusiveMinimum",
514
+ "exclusiveMaximum",
515
+ "multipleOf",
516
+ "minLength",
517
+ "maxLength",
518
+ "pattern",
519
+ "minItems",
520
+ "maxItems",
521
+ "uniqueItems",
522
+ "minProperties",
523
+ "maxProperties",
524
+ "$schema"
525
+ ]);
526
+ function toStructuredOutputSchema(schema) {
527
+ const walk = (node) => {
528
+ if (Array.isArray(node)) return node.map(walk);
529
+ if (!node || typeof node !== "object") return node;
530
+ const out = {};
531
+ for (const [k, v] of Object.entries(node)) {
532
+ if (UNSUPPORTED_SCHEMA_KEYS.has(k)) continue;
533
+ if (k === "properties" && v && typeof v === "object") {
534
+ out[k] = Object.fromEntries(Object.entries(v).map(([pk, pv]) => [pk, walk(pv)]));
535
+ } else if (["items", "anyOf", "allOf", "oneOf", "not", "$defs", "definitions"].includes(k)) {
536
+ out[k] = k === "$defs" || k === "definitions" ? Object.fromEntries(Object.entries(v ?? {}).map(([dk, dv]) => [dk, walk(dv)])) : walk(v);
537
+ } else {
538
+ out[k] = v;
539
+ }
540
+ }
541
+ if (out["type"] === "object" || "properties" in out) out["additionalProperties"] = false;
542
+ return out;
543
+ };
544
+ return walk(schema);
545
+ }
494
546
  var ANTHROPIC_STRUCTURED_TOOL_NAME = "structured_output";
495
547
  function applyPromptCaching(body, env = process.env) {
496
548
  const flag = (env["CROSSCHECK_ANTHROPIC_PROMPT_CACHE"] ?? "").trim();
@@ -520,7 +572,12 @@ function buildAnthropicRequest(opts) {
520
572
  }
521
573
  continue;
522
574
  }
523
- convo.push({ role: m.role, content: typeof m.content === "string" ? m.content : "" });
575
+ const text = typeof m.content === "string" ? m.content : "";
576
+ const images = imagesOf(m);
577
+ convo.push(images.length ? { role: m.role, content: [
578
+ ...images.map((i) => ({ type: "image", source: { type: "base64", media_type: i.mediaType, data: i.data } })),
579
+ { type: "text", text }
580
+ ] } : { role: m.role, content: text });
524
581
  }
525
582
  const body = {
526
583
  model: opts.model,
@@ -542,7 +599,12 @@ function buildAnthropicRequest(opts) {
542
599
  body.thinking = { type: "disabled" };
543
600
  }
544
601
  }
545
- if (opts.jsonSchema) {
602
+ if (opts.jsonSchema && rejectsForcedToolUse(opts.model)) {
603
+ body.output_config = {
604
+ ...body.output_config ?? {},
605
+ format: { type: "json_schema", schema: toStructuredOutputSchema(opts.jsonSchema) }
606
+ };
607
+ } else if (opts.jsonSchema) {
546
608
  body.tools = [{
547
609
  name: ANTHROPIC_STRUCTURED_TOOL_NAME,
548
610
  description: "Emit a single JSON object matching the requested schema.",
@@ -755,7 +817,10 @@ function buildGeminiRequest(opts) {
755
817
  const role = m.role === "user" ? "user" : "model";
756
818
  contents.push({
757
819
  role,
758
- parts: [{ text: typeof m.content === "string" ? m.content : "" }]
820
+ parts: [
821
+ ...imagesOf(m).map((i) => ({ inline_data: { mime_type: i.mediaType, data: i.data } })),
822
+ { text: typeof m.content === "string" ? m.content : "" }
823
+ ]
759
824
  });
760
825
  }
761
826
  const body = {
@@ -923,10 +988,11 @@ function supportsNativeJsonSchema(provider, model) {
923
988
  return true;
924
989
  }
925
990
  function buildOpenAICompatibleRequest(opts) {
926
- const msgs = opts.messages.map((m) => ({
927
- role: m.role,
928
- content: typeof m.content === "string" ? m.content : ""
929
- }));
991
+ const msgs = opts.messages.map((m) => {
992
+ const text = typeof m.content === "string" ? m.content : "";
993
+ const images = imagesOf(m);
994
+ return images.length ? { role: m.role, content: [{ type: "text", text }, ...images.map((i) => ({ type: "image_url", image_url: { url: `data:${i.mediaType};base64,${i.data}` } }))] } : { role: m.role, content: text };
995
+ });
930
996
  const body = {
931
997
  model: opts.model,
932
998
  messages: msgs
@@ -943,7 +1009,15 @@ function buildOpenAICompatibleRequest(opts) {
943
1009
  json_schema: {
944
1010
  name: "structured_output",
945
1011
  schema: opts.jsonSchema,
946
- strict: true
1012
+ // NOT strict. Strict mode requires `additionalProperties: false` on
1013
+ // every object and every property listed in `required` — the
1014
+ // engine's schemas don't meet that, so every structured OpenAI call
1015
+ // (planner, judges, synthesis) was a 400, unnoticed until the canary
1016
+ // grew a structured check (2026-10-11). Non-strict still shapes the
1017
+ // reply to the schema, and structured.ts validates it against the
1018
+ // full schema regardless, so strictness added a failure mode and no
1019
+ // safety.
1020
+ strict: false
947
1021
  }
948
1022
  };
949
1023
  }
@@ -1231,7 +1305,7 @@ import { z } from "zod";
1231
1305
 
1232
1306
  // src/server-meta.ts
1233
1307
  var SERVER_NAME = "crosscheck-agent";
1234
- var SERVER_VERSION = true ? "0.2.28" : "0.0.0-dev";
1308
+ var SERVER_VERSION = true ? "0.2.30" : "0.0.0-dev";
1235
1309
 
1236
1310
  // src/tools/audit.ts
1237
1311
  import { readdirSync, readFileSync as readFileSync3, statSync } from "fs";
@@ -4195,6 +4269,7 @@ async function pickAutoPanel(storage, purpose, n, providers, allowlist) {
4195
4269
  }
4196
4270
 
4197
4271
  // src/core/super-mode.ts
4272
+ import { AsyncLocalStorage } from "async_hooks";
4198
4273
  var SUPER_MODELS = {
4199
4274
  // Fable 5.1 verified present on the account; 5 as the fallback for accounts
4200
4275
  // that haven't been granted 5.1 yet.
@@ -4237,7 +4312,12 @@ function parseChain(v) {
4237
4312
  }
4238
4313
  return out;
4239
4314
  }
4240
- function superChainFor(provider, env = process.env) {
4315
+ var superEnvStore = new AsyncLocalStorage();
4316
+ function withSuperEnv(env, fn) {
4317
+ return superEnvStore.run(env, fn);
4318
+ }
4319
+ var currentEnv = () => superEnvStore.getStore() ?? process.env;
4320
+ function superChainFor(provider, env = currentEnv()) {
4241
4321
  const varName = SUPER_ENV_VARS[provider];
4242
4322
  const user = varName ? parseChain(env[varName]) : [];
4243
4323
  if (user.length > 0) {
@@ -4246,14 +4326,14 @@ function superChainFor(provider, env = process.env) {
4246
4326
  }
4247
4327
  return SUPER_MODELS[provider] ?? [];
4248
4328
  }
4249
- function superPrimary(provider, env = process.env) {
4329
+ function superPrimary(provider, env = currentEnv()) {
4250
4330
  return superChainFor(provider, env)[0];
4251
4331
  }
4252
4332
  var SUPER_PROVIDER_NAMES = Object.keys(SUPER_MODELS);
4253
4333
  function isSuperRequested(args) {
4254
4334
  return args["super"] === true;
4255
4335
  }
4256
- function retargetForSuper(p, env = process.env) {
4336
+ function retargetForSuper(p, env = currentEnv()) {
4257
4337
  const chain = superChainFor(p.name, env);
4258
4338
  if (chain.length === 0) return p;
4259
4339
  const [primary, ...fallbacks] = chain;
@@ -6331,9 +6411,22 @@ import path6 from "path";
6331
6411
  import { performance as performance7 } from "perf_hooks";
6332
6412
 
6333
6413
  // src/core/progress.ts
6334
- import { AsyncLocalStorage } from "async_hooks";
6414
+ import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
6335
6415
  import { performance as performance6 } from "perf_hooks";
6336
- var progressStorage = new AsyncLocalStorage();
6416
+ var progressStorage = new AsyncLocalStorage2();
6417
+ async function withProgress(token, sendNotification, fn) {
6418
+ if (token === void 0 || token === null) {
6419
+ return fn();
6420
+ }
6421
+ const ctx = {
6422
+ token,
6423
+ wallStart: performance6.now(),
6424
+ cpuStart: process.cpuUsage(),
6425
+ step: { value: 0 },
6426
+ sendNotification
6427
+ };
6428
+ return progressStorage.run(ctx, fn);
6429
+ }
6337
6430
  async function emitProgress(message, opts) {
6338
6431
  const ctx = progressStorage.getStore();
6339
6432
  const wallStart = ctx ? ctx.wallStart : performance6.now();
@@ -7863,6 +7956,16 @@ function buildCallContext(args) {
7863
7956
  var CREATE_DOC_MAX_BYTES = 32 * 1024;
7864
7957
  var CREATE_AUDIT_THRESHOLD = 0.7;
7865
7958
  async function runCreate(args, opts) {
7959
+ const subEnvelopes = [];
7960
+ const tracked = (fn) => async (...a) => {
7961
+ const out = await fn(...a);
7962
+ subEnvelopes.push(out);
7963
+ return out;
7964
+ };
7965
+ const confer = tracked(runConfer);
7966
+ const orchestrate = tracked(runOrchestrate);
7967
+ const review = tracked(runReview);
7968
+ const audit = tracked(runAudit);
7866
7969
  const instruction = typeof args["instruction"] === "string" ? args["instruction"] : String(args["instruction"] ?? "");
7867
7970
  if (!instruction) {
7868
7971
  return errorEnvelope6(
@@ -7899,7 +8002,7 @@ ${constraints}
7899
8002
 
7900
8003
  ` : "") + `DOCUMENTS (${okCount} of ${descriptors.length} ingested):
7901
8004
  ${documentsPayload}`;
7902
- const scope = await runConfer({
8005
+ const scope = await confer({
7903
8006
  question: "We are about to orchestrate a full plan->build->review->audit lifecycle for this instruction. List 3-6 concrete sub-tasks (each with a one-line description and a difficulty: low|med|high), any critical assumptions, and any missing-information risks. Be concise and decisive \u2014 your output will be used to build the orchestration DAG.\n\nINSTRUCTION:\n" + instruction,
7904
8007
  context: contextBlock,
7905
8008
  ...providers !== void 0 ? { providers } : {},
@@ -7926,7 +8029,7 @@ ${scopeAnswer || "(none)"}
7926
8029
  };
7927
8030
  if (providers !== void 0) orchestrateArgs["providers"] = providers;
7928
8031
  if (planOnly) orchestrateArgs["plan_only"] = true;
7929
- let orchestration = await runOrchestrate(orchestrateArgs, {
8032
+ let orchestration = await orchestrate(orchestrateArgs, {
7930
8033
  providers: opts.providers,
7931
8034
  allowlist: opts.allowlist ?? null,
7932
8035
  moderator,
@@ -7955,7 +8058,7 @@ ${scopeAnswer || "(none)"}
7955
8058
  }
7956
8059
  let reviewEnvelope = null;
7957
8060
  if (!skipReview && typeof orchestration["final"] === "string" && orchestration["final"]) {
7958
- reviewEnvelope = await runReview({
8061
+ reviewEnvelope = await review({
7959
8062
  snippet: orchestration["final"],
7960
8063
  intent: `final deliverable for: ${instruction}`,
7961
8064
  ...providers !== void 0 ? { providers } : {},
@@ -7975,7 +8078,7 @@ ${scopeAnswer || "(none)"}
7975
8078
  const panelExhausted = producingPanel.length > 0 && producingPanel.every(
7976
8079
  (p) => p in opts.providers || Object.keys(opts.providers).includes(p.toLowerCase())
7977
8080
  ) && producingPanel.length >= Object.keys(opts.providers).length;
7978
- auditEnvelope = await runAudit({
8081
+ auditEnvelope = await audit({
7979
8082
  output_to_audit: orchestration["final"],
7980
8083
  producing_panelists: producingPanel,
7981
8084
  ...auditRubric !== void 0 ? { rubric: auditRubric } : {},
@@ -8004,7 +8107,7 @@ ${retryConstraints}
8004
8107
  DOCUMENTS:
8005
8108
  ${documentsPayload}`
8006
8109
  };
8007
- const retryOrchestration = await runOrchestrate(
8110
+ const retryOrchestration = await orchestrate(
8008
8111
  retryOrchestrateArgs,
8009
8112
  {
8010
8113
  providers: opts.providers,
@@ -8018,7 +8121,7 @@ ${documentsPayload}`
8018
8121
  if (typeof retryOrchestration["final"] === "string" && retryOrchestration["final"]) {
8019
8122
  const retryPanel = computeProducingPanel(retryOrchestration);
8020
8123
  const retryPanelExhausted = retryPanel.length > 0 && retryPanel.length >= Object.keys(opts.providers).length;
8021
- auditEnvelope = await runAudit({
8124
+ auditEnvelope = await audit({
8022
8125
  output_to_audit: retryOrchestration["final"],
8023
8126
  producing_panelists: retryPanel,
8024
8127
  ...auditRubric !== void 0 ? { rubric: auditRubric } : {},
@@ -8093,9 +8196,28 @@ ${documentsPayload}`
8093
8196
  ["auditor", "items", "overall_score", "passed", "rubric"]
8094
8197
  ),
8095
8198
  artifacts,
8096
- warnings
8199
+ warnings,
8200
+ ...combinedUsage(subEnvelopes)
8097
8201
  };
8098
8202
  }
8203
+ function combinedUsage(envelopes) {
8204
+ const usages = [];
8205
+ const byCallTiming = [];
8206
+ let wall = 0, cpu = 0;
8207
+ for (const env of envelopes) {
8208
+ const e = env ?? {};
8209
+ const calls = e["usage"]?.["by_call"] ?? [];
8210
+ const t = e["timing"] ?? {};
8211
+ const timing = Array.isArray(t["by_call"]) ? t["by_call"] : [];
8212
+ if (!Array.isArray(calls) || calls.length === 0) continue;
8213
+ usages.push(...calls);
8214
+ if (timing.length === calls.length) byCallTiming.push(...timing);
8215
+ else for (const c of calls) byCallTiming.push({ provider: c.provider, model: c.model, purpose: c.purpose ?? null, wall_ms: 0, cpu_ms: 0, cache_hit: false });
8216
+ wall += Number(t["wall_ms"] ?? 0) || 0;
8217
+ cpu += Number(t["cpu_ms"] ?? 0) || 0;
8218
+ }
8219
+ return { usage: aggregateUsage(usages), timing: { wall_ms: wall, cpu_ms: cpu, by_call: byCallTiming } };
8220
+ }
8099
8221
  async function ingestDocuments(documents, sessionId, opts) {
8100
8222
  if (documents.length === 0) return [];
8101
8223
  const out = [];
@@ -11572,7 +11694,7 @@ var CHECK_INTERVAL_SECONDS = 3 * 24 * 60 * 60;
11572
11694
  var DEFAULT_PACKAGE = "crosscheck-cli";
11573
11695
  var FETCH_TIMEOUT_MS = 3e3;
11574
11696
  function engineVersion() {
11575
- return true ? "0.2.28" : "0.0.0-dev";
11697
+ return true ? "0.2.30" : "0.0.0-dev";
11576
11698
  }
11577
11699
  function defaultUpdateCachePath() {
11578
11700
  const base = process.env["CROSSCHECK_DATA_DIR"] || path9.join(os.homedir() || os.tmpdir(), ".crosscheck");
@@ -13363,6 +13485,133 @@ var ENGINE_TO_VAULT = { xai: "grok" };
13363
13485
  function vaultId(engineName) {
13364
13486
  return ENGINE_TO_VAULT[engineName] ?? engineName;
13365
13487
  }
13488
+ var ACTIVITY_TEXT_CAP = 8e3;
13489
+ var ASKED_CAP = 280;
13490
+ var VISION_PROVIDERS = ["anthropic", "openai", "gemini", "grok"];
13491
+ var NO_IMAGE_PURPOSES = /* @__PURE__ */ new Set(["early_stop", "extract", "canary", "classify"]);
13492
+ var MAX_RUN_IMAGES = 8;
13493
+ function withRunImages(args, provider, images) {
13494
+ if (!images?.length || NO_IMAGE_PURPOSES.has(args.purpose ?? "")) return args;
13495
+ const msgs = [...args.messages];
13496
+ let idx = -1;
13497
+ for (let i = msgs.length - 1; i >= 0; i--) if (msgs[i]?.role === "user") {
13498
+ idx = i;
13499
+ break;
13500
+ }
13501
+ if (idx < 0) return args;
13502
+ const m = msgs[idx];
13503
+ if (VISION_PROVIDERS.includes(provider)) {
13504
+ msgs[idx] = { ...m, images: [...m.images ?? [], ...images] };
13505
+ } else {
13506
+ const n = images.length;
13507
+ msgs[idx] = {
13508
+ ...m,
13509
+ content: `${m.content}
13510
+
13511
+ [The user also attached ${n} image${n === 1 ? "" : "s"} that this model can't see. Don't guess at ${n === 1 ? "its" : "their"} contents \u2014 work from the text, and say so if the answer depends on ${n === 1 ? "it" : "them"}.]`
13512
+ };
13513
+ }
13514
+ return { ...args, messages: msgs };
13515
+ }
13516
+ var runContext = new AsyncLocalStorage3();
13517
+ var SYNTHESIS_PURPOSES = /* @__PURE__ */ new Set(["synth", "moderator", "recombine", "judge", "unify"]);
13518
+ function exemptFromSkip(ctx, provider, purpose) {
13519
+ return provider === ctx.moderator && SYNTHESIS_PURPOSES.has(purpose);
13520
+ }
13521
+ function skippedError(provider, why, limitMs) {
13522
+ return new ProviderError(
13523
+ "client",
13524
+ why === "timeout" ? `${provider}: stopped after ${Math.round((limitMs ?? 0) / 1e3)}s (your per-model time limit)` : `${provider}: stopped waiting (you skipped it)`,
13525
+ { transient: false }
13526
+ );
13527
+ }
13528
+ function lastUserText(args) {
13529
+ const msgs = args.messages;
13530
+ for (let i = msgs.length - 1; i >= 0; i--) {
13531
+ const m = msgs[i];
13532
+ if (m && m.role === "user" && typeof m.content === "string") {
13533
+ const t = m.content.replace(/\s+/g, " ").trim();
13534
+ return t.length > ASKED_CAP ? `${t.slice(0, ASKED_CAP - 1)}\u2026` : t;
13535
+ }
13536
+ }
13537
+ return "";
13538
+ }
13539
+ function withActivity(p) {
13540
+ const send = p.send.bind(p);
13541
+ return {
13542
+ name: p.name,
13543
+ model: p.model,
13544
+ ...p.fallbackModels ? { fallbackModels: p.fallbackModels } : {},
13545
+ send: async (args) => {
13546
+ const ctx = runContext.getStore();
13547
+ if (!ctx) return send(args);
13548
+ const callId = ctx.nextCallId();
13549
+ const provider = vaultId(p.name);
13550
+ const model = args.modelOverride ?? p.model;
13551
+ const purpose = args.purpose ?? "worker";
13552
+ const started = Date.now();
13553
+ const exempt = exemptFromSkip(ctx, provider, purpose);
13554
+ if (!exempt && ctx.skipped.has(provider)) throw skippedError(provider, "user");
13555
+ ctx.emit({ type: "call.start", runId: ctx.runId, at: started, callId, provider, model, purpose, asked: lastUserText(args) });
13556
+ const controller = new AbortController();
13557
+ if (args.signal) {
13558
+ if (args.signal.aborted) controller.abort(args.signal.reason);
13559
+ else args.signal.addEventListener("abort", () => controller.abort(args.signal.reason), { once: true });
13560
+ }
13561
+ let stopped;
13562
+ if (!exempt) ctx.inflight.set(callId, { provider, purpose, controller });
13563
+ const timer = !exempt && ctx.callTimeoutMs && ctx.callTimeoutMs > 0 ? setTimeout(() => {
13564
+ stopped = "timeout";
13565
+ controller.abort("timeout");
13566
+ }, ctx.callTimeoutMs) : void 0;
13567
+ controller.signal.addEventListener("abort", () => {
13568
+ if (!stopped && controller.signal.reason === "skip") stopped = "user";
13569
+ }, { once: true });
13570
+ try {
13571
+ const res = await send({ ...withRunImages(args, provider, ctx.images), signal: controller.signal });
13572
+ const text = typeof res.text === "string" ? res.text : "";
13573
+ ctx.emit({
13574
+ type: "call.done",
13575
+ runId: ctx.runId,
13576
+ at: Date.now(),
13577
+ callId,
13578
+ provider,
13579
+ model,
13580
+ purpose,
13581
+ ok: true,
13582
+ ms: Date.now() - started,
13583
+ text: text.slice(0, ACTIVITY_TEXT_CAP),
13584
+ truncated: text.length > ACTIVITY_TEXT_CAP,
13585
+ error: null,
13586
+ usage: usageOf(res)
13587
+ });
13588
+ return res;
13589
+ } catch (err) {
13590
+ const out = stopped ? skippedError(provider, stopped, ctx.callTimeoutMs) : err;
13591
+ ctx.emit({
13592
+ type: "call.done",
13593
+ runId: ctx.runId,
13594
+ at: Date.now(),
13595
+ callId,
13596
+ provider,
13597
+ model,
13598
+ purpose,
13599
+ ok: false,
13600
+ ms: Date.now() - started,
13601
+ text: "",
13602
+ truncated: false,
13603
+ error: out instanceof Error ? out.message : String(out),
13604
+ usage: null,
13605
+ ...stopped ? { stopped } : {}
13606
+ });
13607
+ throw out;
13608
+ } finally {
13609
+ if (timer) clearTimeout(timer);
13610
+ ctx.inflight.delete(callId);
13611
+ }
13612
+ }
13613
+ };
13614
+ }
13366
13615
  function usageOf(answer) {
13367
13616
  const u = answer["usage"];
13368
13617
  if (!u || typeof u !== "object") return null;
@@ -13398,6 +13647,8 @@ function bundledPricingPath() {
13398
13647
  }
13399
13648
  }
13400
13649
  var runCounter = 0;
13650
+ var callCounter = 0;
13651
+ var nextCallId = () => ++callCounter;
13401
13652
  function nextRunId() {
13402
13653
  runCounter += 1;
13403
13654
  return `run_${Date.now().toString(36)}_${runCounter}`;
@@ -13412,11 +13663,19 @@ function createEmbeddedEngine(opts) {
13412
13663
  const varName = MODEL_ENV[provider.trim().toLowerCase()];
13413
13664
  if (varName && model) env[varName] = model;
13414
13665
  }
13666
+ const superEnv = {};
13667
+ for (const [provider, model] of Object.entries(opts.superModels ?? {})) {
13668
+ const p = provider.trim().toLowerCase();
13669
+ const varName = SUPER_ENV_VARS[p === "grok" ? "xai" : p];
13670
+ if (varName && model) superEnv[varName] = model;
13671
+ }
13415
13672
  const pricingPath = [opts.pricingPath, bundledPricingPath()].find(
13416
13673
  (p) => Boolean(p) && existsSync11(p)
13417
13674
  );
13418
13675
  const pricing = pricingPath ? loadPricing(pricingPath) : {};
13419
- const built = buildProviders({ env, pricing });
13676
+ const built = Object.fromEntries(
13677
+ Object.entries(buildProviders({ env, pricing })).map(([name, p]) => [name, withActivity(p)])
13678
+ );
13420
13679
  const moderator = opts.moderator ?? "anthropic";
13421
13680
  const tools = registerCoreTools({ providers: built, pricing });
13422
13681
  const providerIds = Object.keys(built).map(vaultId).sort();
@@ -13433,7 +13692,8 @@ function createEmbeddedEngine(opts) {
13433
13692
  if (!tool) return Promise.reject(new Error(`unknown tool: ${name}`));
13434
13693
  return Promise.resolve(tool.handler(args));
13435
13694
  };
13436
- const run = async (name, args, onEvent) => {
13695
+ const liveRuns = /* @__PURE__ */ new Map();
13696
+ const run = async (name, args, onEvent, runOpts = {}) => {
13437
13697
  const runId = nextRunId();
13438
13698
  const started = Date.now();
13439
13699
  const emit = (e) => {
@@ -13442,6 +13702,79 @@ function createEmbeddedEngine(opts) {
13442
13702
  } catch {
13443
13703
  }
13444
13704
  };
13705
+ const ctx = {
13706
+ runId,
13707
+ emit,
13708
+ nextCallId,
13709
+ skipped: /* @__PURE__ */ new Set(),
13710
+ inflight: /* @__PURE__ */ new Map(),
13711
+ moderator: vaultId(moderator),
13712
+ ...runOpts.callTimeoutMs && runOpts.callTimeoutMs > 0 ? { callTimeoutMs: runOpts.callTimeoutMs } : {},
13713
+ ...runOpts.images?.length ? { images: runOpts.images.filter((i) => IMAGE_MEDIA_TYPES.includes(i.mediaType) && typeof i.data === "string" && i.data.length > 0).slice(0, MAX_RUN_IMAGES) } : {}
13714
+ };
13715
+ liveRuns.set(runId, ctx);
13716
+ try {
13717
+ return await runContext.run(ctx, () => withProgress(runId, (n) => {
13718
+ if (n.params.message) emit({ type: "progress", runId, at: Date.now(), message: n.params.message });
13719
+ }, () => withSuperEnv(superEnv, () => runInner(name, args, runId, started, emit))));
13720
+ } finally {
13721
+ liveRuns.delete(runId);
13722
+ }
13723
+ };
13724
+ const skip = (runId, provider) => {
13725
+ const ctx = liveRuns.get(runId);
13726
+ if (!ctx) return 0;
13727
+ ctx.skipped.add(provider);
13728
+ let stopped = 0;
13729
+ for (const call2 of ctx.inflight.values()) {
13730
+ if (call2.provider === provider && !exemptFromSkip(ctx, call2.provider, call2.purpose)) {
13731
+ call2.controller.abort("skip");
13732
+ stopped += 1;
13733
+ }
13734
+ }
13735
+ return stopped;
13736
+ };
13737
+ const ask = async (o) => {
13738
+ const engineName = Object.keys(built).find((n) => vaultId(n) === o.provider);
13739
+ const base = engineName ? built[engineName] : void 0;
13740
+ if (!base) {
13741
+ return { ok: false, text: "", json: null, model: o.model ?? "", error: `No ${o.provider} key is configured, so it can't be asked.` };
13742
+ }
13743
+ const provider = o.model && o.model !== base.model ? retargetProvider(base, o.model) : base;
13744
+ const maxTokens = o.maxTokens ?? 8e3;
13745
+ const doAsk = async () => {
13746
+ if (o.schema) {
13747
+ const res = await requestStructured(provider, o.messages, o.schema, { maxTokens, purpose: o.purpose, maxRetries: 1 });
13748
+ return {
13749
+ ok: res.obj !== null,
13750
+ text: res.answer.response ?? "",
13751
+ json: res.obj,
13752
+ error: res.obj !== null ? null : res.answer.error ?? res.errors.join("; ") ?? "invalid reply",
13753
+ model: provider.model
13754
+ };
13755
+ }
13756
+ const a = await askOne(provider, o.messages, { maxTokens, temperature: 0.3, purpose: o.purpose });
13757
+ return { ok: !a.error, text: a.response ?? "", json: null, error: a.error ?? null, model: provider.model };
13758
+ };
13759
+ if (!o.runId || !o.onEvent) return doAsk();
13760
+ const sink = o.onEvent;
13761
+ const emit = (e) => {
13762
+ try {
13763
+ sink(e);
13764
+ } catch {
13765
+ }
13766
+ };
13767
+ const ctx = {
13768
+ runId: o.runId,
13769
+ emit,
13770
+ nextCallId,
13771
+ skipped: /* @__PURE__ */ new Set(),
13772
+ inflight: /* @__PURE__ */ new Map(),
13773
+ moderator: o.provider
13774
+ };
13775
+ return runContext.run(ctx, doAsk);
13776
+ };
13777
+ const runInner = async (name, args, runId, started, emit) => {
13445
13778
  emit({
13446
13779
  type: "run.start",
13447
13780
  runId,
@@ -13519,8 +13852,16 @@ function createEmbeddedEngine(opts) {
13519
13852
  providers: providerIds,
13520
13853
  models,
13521
13854
  listTools: () => [...tools.keys()],
13855
+ requiredArgs: (name) => {
13856
+ const tool = tools.get(name);
13857
+ if (!tool) return null;
13858
+ const req = tool.inputSchema?.required;
13859
+ return Array.isArray(req) ? req.filter((x) => typeof x === "string") : [];
13860
+ },
13522
13861
  call,
13523
13862
  run,
13863
+ skip,
13864
+ ask,
13524
13865
  close: async () => {
13525
13866
  await flush().catch(() => {
13526
13867
  });
@@ -13529,15 +13870,21 @@ function createEmbeddedEngine(opts) {
13529
13870
  }
13530
13871
  var __test_internals = { usageOf, textOf, errorOf, vaultId };
13531
13872
  export {
13873
+ ACTIVITY_TEXT_CAP,
13532
13874
  DEFAULT_EXCLUDED_PROVIDERS,
13533
13875
  DEFAULT_FALLBACKS,
13534
13876
  DEFAULT_MODELS,
13877
+ IMAGE_MEDIA_TYPES,
13878
+ MAX_RUN_IMAGES,
13879
+ SUPER_MODELS,
13880
+ VISION_PROVIDERS,
13535
13881
  KEY_ENV as __KEY_ENV,
13536
13882
  MODEL_ENV as __MODEL_ENV,
13537
13883
  __test_internals,
13538
13884
  createEmbeddedEngine,
13539
13885
  isAlive,
13540
13886
  listProcesses,
13541
- processRegistryPath
13887
+ processRegistryPath,
13888
+ withRunImages
13542
13889
  };
13543
13890
  //# sourceMappingURL=embed.js.map