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.cjs CHANGED
@@ -31,16 +31,22 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  // src/entrypoints/embed.ts
32
32
  var embed_exports = {};
33
33
  __export(embed_exports, {
34
+ ACTIVITY_TEXT_CAP: () => ACTIVITY_TEXT_CAP,
34
35
  DEFAULT_EXCLUDED_PROVIDERS: () => DEFAULT_EXCLUDED_PROVIDERS,
35
36
  DEFAULT_FALLBACKS: () => DEFAULT_FALLBACKS,
36
37
  DEFAULT_MODELS: () => DEFAULT_MODELS,
38
+ IMAGE_MEDIA_TYPES: () => IMAGE_MEDIA_TYPES,
39
+ MAX_RUN_IMAGES: () => MAX_RUN_IMAGES,
40
+ SUPER_MODELS: () => SUPER_MODELS,
41
+ VISION_PROVIDERS: () => VISION_PROVIDERS,
37
42
  __KEY_ENV: () => KEY_ENV,
38
43
  __MODEL_ENV: () => MODEL_ENV,
39
44
  __test_internals: () => __test_internals,
40
45
  createEmbeddedEngine: () => createEmbeddedEngine,
41
46
  isAlive: () => isAlive,
42
47
  listProcesses: () => listProcesses,
43
- processRegistryPath: () => processRegistryPath
48
+ processRegistryPath: () => processRegistryPath,
49
+ withRunImages: () => withRunImages
44
50
  });
45
51
  module.exports = __toCommonJS(embed_exports);
46
52
 
@@ -49,6 +55,7 @@ var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${_
49
55
  var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
50
56
 
51
57
  // src/entrypoints/embed.ts
58
+ var import_node_async_hooks3 = require("async_hooks");
52
59
  var import_node_fs16 = require("fs");
53
60
  var import_node_path15 = __toESM(require("path"), 1);
54
61
  var import_node_url2 = require("url");
@@ -220,6 +227,11 @@ function reasoningSharesOutputBudget(provider) {
220
227
  }
221
228
 
222
229
  // src/providers/types.ts
230
+ var IMAGE_MEDIA_TYPES = ["image/png", "image/jpeg", "image/webp", "image/gif"];
231
+ function imagesOf(m) {
232
+ if (m.role !== "user" || !Array.isArray(m.images)) return [];
233
+ return m.images.filter((i) => Boolean(i) && typeof i.data === "string" && i.data.length > 0 && IMAGE_MEDIA_TYPES.includes(i.mediaType));
234
+ }
223
235
  var ProviderError = class extends Error {
224
236
  name = "ProviderError";
225
237
  kind;
@@ -533,6 +545,52 @@ function rejectsDisabledThinking(model) {
533
545
  const m = model.toLowerCase();
534
546
  return ADAPTIVE_THINKING_PREFIXES.some((p) => m.startsWith(p));
535
547
  }
548
+ var NO_FORCED_TOOL_PREFIXES = [
549
+ "claude-fable-5-1",
550
+ "claude-mythos-5-1",
551
+ "claude-opus-5-5",
552
+ "claude-sonnet-5-5"
553
+ ];
554
+ function rejectsForcedToolUse(model) {
555
+ const m = model.toLowerCase();
556
+ return NO_FORCED_TOOL_PREFIXES.some((p) => m.startsWith(p));
557
+ }
558
+ var UNSUPPORTED_SCHEMA_KEYS = /* @__PURE__ */ new Set([
559
+ "minimum",
560
+ "maximum",
561
+ "exclusiveMinimum",
562
+ "exclusiveMaximum",
563
+ "multipleOf",
564
+ "minLength",
565
+ "maxLength",
566
+ "pattern",
567
+ "minItems",
568
+ "maxItems",
569
+ "uniqueItems",
570
+ "minProperties",
571
+ "maxProperties",
572
+ "$schema"
573
+ ]);
574
+ function toStructuredOutputSchema(schema) {
575
+ const walk = (node) => {
576
+ if (Array.isArray(node)) return node.map(walk);
577
+ if (!node || typeof node !== "object") return node;
578
+ const out = {};
579
+ for (const [k, v] of Object.entries(node)) {
580
+ if (UNSUPPORTED_SCHEMA_KEYS.has(k)) continue;
581
+ if (k === "properties" && v && typeof v === "object") {
582
+ out[k] = Object.fromEntries(Object.entries(v).map(([pk, pv]) => [pk, walk(pv)]));
583
+ } else if (["items", "anyOf", "allOf", "oneOf", "not", "$defs", "definitions"].includes(k)) {
584
+ out[k] = k === "$defs" || k === "definitions" ? Object.fromEntries(Object.entries(v ?? {}).map(([dk, dv]) => [dk, walk(dv)])) : walk(v);
585
+ } else {
586
+ out[k] = v;
587
+ }
588
+ }
589
+ if (out["type"] === "object" || "properties" in out) out["additionalProperties"] = false;
590
+ return out;
591
+ };
592
+ return walk(schema);
593
+ }
536
594
  var ANTHROPIC_STRUCTURED_TOOL_NAME = "structured_output";
537
595
  function applyPromptCaching(body, env = process.env) {
538
596
  const flag = (env["CROSSCHECK_ANTHROPIC_PROMPT_CACHE"] ?? "").trim();
@@ -562,7 +620,12 @@ function buildAnthropicRequest(opts) {
562
620
  }
563
621
  continue;
564
622
  }
565
- convo.push({ role: m.role, content: typeof m.content === "string" ? m.content : "" });
623
+ const text = typeof m.content === "string" ? m.content : "";
624
+ const images = imagesOf(m);
625
+ convo.push(images.length ? { role: m.role, content: [
626
+ ...images.map((i) => ({ type: "image", source: { type: "base64", media_type: i.mediaType, data: i.data } })),
627
+ { type: "text", text }
628
+ ] } : { role: m.role, content: text });
566
629
  }
567
630
  const body = {
568
631
  model: opts.model,
@@ -584,7 +647,12 @@ function buildAnthropicRequest(opts) {
584
647
  body.thinking = { type: "disabled" };
585
648
  }
586
649
  }
587
- if (opts.jsonSchema) {
650
+ if (opts.jsonSchema && rejectsForcedToolUse(opts.model)) {
651
+ body.output_config = {
652
+ ...body.output_config ?? {},
653
+ format: { type: "json_schema", schema: toStructuredOutputSchema(opts.jsonSchema) }
654
+ };
655
+ } else if (opts.jsonSchema) {
588
656
  body.tools = [{
589
657
  name: ANTHROPIC_STRUCTURED_TOOL_NAME,
590
658
  description: "Emit a single JSON object matching the requested schema.",
@@ -797,7 +865,10 @@ function buildGeminiRequest(opts) {
797
865
  const role = m.role === "user" ? "user" : "model";
798
866
  contents.push({
799
867
  role,
800
- parts: [{ text: typeof m.content === "string" ? m.content : "" }]
868
+ parts: [
869
+ ...imagesOf(m).map((i) => ({ inline_data: { mime_type: i.mediaType, data: i.data } })),
870
+ { text: typeof m.content === "string" ? m.content : "" }
871
+ ]
801
872
  });
802
873
  }
803
874
  const body = {
@@ -965,10 +1036,11 @@ function supportsNativeJsonSchema(provider, model) {
965
1036
  return true;
966
1037
  }
967
1038
  function buildOpenAICompatibleRequest(opts) {
968
- const msgs = opts.messages.map((m) => ({
969
- role: m.role,
970
- content: typeof m.content === "string" ? m.content : ""
971
- }));
1039
+ const msgs = opts.messages.map((m) => {
1040
+ const text = typeof m.content === "string" ? m.content : "";
1041
+ const images = imagesOf(m);
1042
+ 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 };
1043
+ });
972
1044
  const body = {
973
1045
  model: opts.model,
974
1046
  messages: msgs
@@ -985,7 +1057,15 @@ function buildOpenAICompatibleRequest(opts) {
985
1057
  json_schema: {
986
1058
  name: "structured_output",
987
1059
  schema: opts.jsonSchema,
988
- strict: true
1060
+ // NOT strict. Strict mode requires `additionalProperties: false` on
1061
+ // every object and every property listed in `required` — the
1062
+ // engine's schemas don't meet that, so every structured OpenAI call
1063
+ // (planner, judges, synthesis) was a 400, unnoticed until the canary
1064
+ // grew a structured check (2026-10-11). Non-strict still shapes the
1065
+ // reply to the schema, and structured.ts validates it against the
1066
+ // full schema regardless, so strictness added a failure mode and no
1067
+ // safety.
1068
+ strict: false
989
1069
  }
990
1070
  };
991
1071
  }
@@ -1273,7 +1353,7 @@ var import_zod = require("zod");
1273
1353
 
1274
1354
  // src/server-meta.ts
1275
1355
  var SERVER_NAME = "crosscheck-agent";
1276
- var SERVER_VERSION = true ? "0.2.28" : "0.0.0-dev";
1356
+ var SERVER_VERSION = true ? "0.2.30" : "0.0.0-dev";
1277
1357
 
1278
1358
  // src/tools/audit.ts
1279
1359
  var import_node_fs4 = require("fs");
@@ -4237,6 +4317,7 @@ async function pickAutoPanel(storage, purpose, n, providers, allowlist) {
4237
4317
  }
4238
4318
 
4239
4319
  // src/core/super-mode.ts
4320
+ var import_node_async_hooks = require("async_hooks");
4240
4321
  var SUPER_MODELS = {
4241
4322
  // Fable 5.1 verified present on the account; 5 as the fallback for accounts
4242
4323
  // that haven't been granted 5.1 yet.
@@ -4279,7 +4360,12 @@ function parseChain(v) {
4279
4360
  }
4280
4361
  return out;
4281
4362
  }
4282
- function superChainFor(provider, env = process.env) {
4363
+ var superEnvStore = new import_node_async_hooks.AsyncLocalStorage();
4364
+ function withSuperEnv(env, fn) {
4365
+ return superEnvStore.run(env, fn);
4366
+ }
4367
+ var currentEnv = () => superEnvStore.getStore() ?? process.env;
4368
+ function superChainFor(provider, env = currentEnv()) {
4283
4369
  const varName = SUPER_ENV_VARS[provider];
4284
4370
  const user = varName ? parseChain(env[varName]) : [];
4285
4371
  if (user.length > 0) {
@@ -4288,14 +4374,14 @@ function superChainFor(provider, env = process.env) {
4288
4374
  }
4289
4375
  return SUPER_MODELS[provider] ?? [];
4290
4376
  }
4291
- function superPrimary(provider, env = process.env) {
4377
+ function superPrimary(provider, env = currentEnv()) {
4292
4378
  return superChainFor(provider, env)[0];
4293
4379
  }
4294
4380
  var SUPER_PROVIDER_NAMES = Object.keys(SUPER_MODELS);
4295
4381
  function isSuperRequested(args) {
4296
4382
  return args["super"] === true;
4297
4383
  }
4298
- function retargetForSuper(p, env = process.env) {
4384
+ function retargetForSuper(p, env = currentEnv()) {
4299
4385
  const chain = superChainFor(p.name, env);
4300
4386
  if (chain.length === 0) return p;
4301
4387
  const [primary, ...fallbacks] = chain;
@@ -6366,9 +6452,22 @@ var import_node_path9 = __toESM(require("path"), 1);
6366
6452
  var import_node_perf_hooks6 = require("perf_hooks");
6367
6453
 
6368
6454
  // src/core/progress.ts
6369
- var import_node_async_hooks = require("async_hooks");
6455
+ var import_node_async_hooks2 = require("async_hooks");
6370
6456
  var import_node_perf_hooks5 = require("perf_hooks");
6371
- var progressStorage = new import_node_async_hooks.AsyncLocalStorage();
6457
+ var progressStorage = new import_node_async_hooks2.AsyncLocalStorage();
6458
+ async function withProgress(token, sendNotification, fn) {
6459
+ if (token === void 0 || token === null) {
6460
+ return fn();
6461
+ }
6462
+ const ctx = {
6463
+ token,
6464
+ wallStart: import_node_perf_hooks5.performance.now(),
6465
+ cpuStart: process.cpuUsage(),
6466
+ step: { value: 0 },
6467
+ sendNotification
6468
+ };
6469
+ return progressStorage.run(ctx, fn);
6470
+ }
6372
6471
  async function emitProgress(message, opts) {
6373
6472
  const ctx = progressStorage.getStore();
6374
6473
  const wallStart = ctx ? ctx.wallStart : import_node_perf_hooks5.performance.now();
@@ -7888,6 +7987,16 @@ function buildCallContext(args) {
7888
7987
  var CREATE_DOC_MAX_BYTES = 32 * 1024;
7889
7988
  var CREATE_AUDIT_THRESHOLD = 0.7;
7890
7989
  async function runCreate(args, opts) {
7990
+ const subEnvelopes = [];
7991
+ const tracked = (fn) => async (...a) => {
7992
+ const out = await fn(...a);
7993
+ subEnvelopes.push(out);
7994
+ return out;
7995
+ };
7996
+ const confer = tracked(runConfer);
7997
+ const orchestrate = tracked(runOrchestrate);
7998
+ const review = tracked(runReview);
7999
+ const audit = tracked(runAudit);
7891
8000
  const instruction = typeof args["instruction"] === "string" ? args["instruction"] : String(args["instruction"] ?? "");
7892
8001
  if (!instruction) {
7893
8002
  return errorEnvelope6(
@@ -7924,7 +8033,7 @@ ${constraints}
7924
8033
 
7925
8034
  ` : "") + `DOCUMENTS (${okCount} of ${descriptors.length} ingested):
7926
8035
  ${documentsPayload}`;
7927
- const scope = await runConfer({
8036
+ const scope = await confer({
7928
8037
  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,
7929
8038
  context: contextBlock,
7930
8039
  ...providers !== void 0 ? { providers } : {},
@@ -7951,7 +8060,7 @@ ${scopeAnswer || "(none)"}
7951
8060
  };
7952
8061
  if (providers !== void 0) orchestrateArgs["providers"] = providers;
7953
8062
  if (planOnly) orchestrateArgs["plan_only"] = true;
7954
- let orchestration = await runOrchestrate(orchestrateArgs, {
8063
+ let orchestration = await orchestrate(orchestrateArgs, {
7955
8064
  providers: opts.providers,
7956
8065
  allowlist: opts.allowlist ?? null,
7957
8066
  moderator,
@@ -7980,7 +8089,7 @@ ${scopeAnswer || "(none)"}
7980
8089
  }
7981
8090
  let reviewEnvelope = null;
7982
8091
  if (!skipReview && typeof orchestration["final"] === "string" && orchestration["final"]) {
7983
- reviewEnvelope = await runReview({
8092
+ reviewEnvelope = await review({
7984
8093
  snippet: orchestration["final"],
7985
8094
  intent: `final deliverable for: ${instruction}`,
7986
8095
  ...providers !== void 0 ? { providers } : {},
@@ -8000,7 +8109,7 @@ ${scopeAnswer || "(none)"}
8000
8109
  const panelExhausted = producingPanel.length > 0 && producingPanel.every(
8001
8110
  (p) => p in opts.providers || Object.keys(opts.providers).includes(p.toLowerCase())
8002
8111
  ) && producingPanel.length >= Object.keys(opts.providers).length;
8003
- auditEnvelope = await runAudit({
8112
+ auditEnvelope = await audit({
8004
8113
  output_to_audit: orchestration["final"],
8005
8114
  producing_panelists: producingPanel,
8006
8115
  ...auditRubric !== void 0 ? { rubric: auditRubric } : {},
@@ -8029,7 +8138,7 @@ ${retryConstraints}
8029
8138
  DOCUMENTS:
8030
8139
  ${documentsPayload}`
8031
8140
  };
8032
- const retryOrchestration = await runOrchestrate(
8141
+ const retryOrchestration = await orchestrate(
8033
8142
  retryOrchestrateArgs,
8034
8143
  {
8035
8144
  providers: opts.providers,
@@ -8043,7 +8152,7 @@ ${documentsPayload}`
8043
8152
  if (typeof retryOrchestration["final"] === "string" && retryOrchestration["final"]) {
8044
8153
  const retryPanel = computeProducingPanel(retryOrchestration);
8045
8154
  const retryPanelExhausted = retryPanel.length > 0 && retryPanel.length >= Object.keys(opts.providers).length;
8046
- auditEnvelope = await runAudit({
8155
+ auditEnvelope = await audit({
8047
8156
  output_to_audit: retryOrchestration["final"],
8048
8157
  producing_panelists: retryPanel,
8049
8158
  ...auditRubric !== void 0 ? { rubric: auditRubric } : {},
@@ -8118,9 +8227,28 @@ ${documentsPayload}`
8118
8227
  ["auditor", "items", "overall_score", "passed", "rubric"]
8119
8228
  ),
8120
8229
  artifacts,
8121
- warnings
8230
+ warnings,
8231
+ ...combinedUsage(subEnvelopes)
8122
8232
  };
8123
8233
  }
8234
+ function combinedUsage(envelopes) {
8235
+ const usages = [];
8236
+ const byCallTiming = [];
8237
+ let wall = 0, cpu = 0;
8238
+ for (const env of envelopes) {
8239
+ const e = env ?? {};
8240
+ const calls = e["usage"]?.["by_call"] ?? [];
8241
+ const t = e["timing"] ?? {};
8242
+ const timing = Array.isArray(t["by_call"]) ? t["by_call"] : [];
8243
+ if (!Array.isArray(calls) || calls.length === 0) continue;
8244
+ usages.push(...calls);
8245
+ if (timing.length === calls.length) byCallTiming.push(...timing);
8246
+ 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 });
8247
+ wall += Number(t["wall_ms"] ?? 0) || 0;
8248
+ cpu += Number(t["cpu_ms"] ?? 0) || 0;
8249
+ }
8250
+ return { usage: aggregateUsage(usages), timing: { wall_ms: wall, cpu_ms: cpu, by_call: byCallTiming } };
8251
+ }
8124
8252
  async function ingestDocuments(documents, sessionId, opts) {
8125
8253
  if (documents.length === 0) return [];
8126
8254
  const out = [];
@@ -11597,7 +11725,7 @@ var CHECK_INTERVAL_SECONDS = 3 * 24 * 60 * 60;
11597
11725
  var DEFAULT_PACKAGE = "crosscheck-cli";
11598
11726
  var FETCH_TIMEOUT_MS = 3e3;
11599
11727
  function engineVersion() {
11600
- return true ? "0.2.28" : "0.0.0-dev";
11728
+ return true ? "0.2.30" : "0.0.0-dev";
11601
11729
  }
11602
11730
  function defaultUpdateCachePath() {
11603
11731
  const base = process.env["CROSSCHECK_DATA_DIR"] || import_node_path12.default.join(import_node_os2.default.homedir() || import_node_os2.default.tmpdir(), ".crosscheck");
@@ -13388,6 +13516,133 @@ var ENGINE_TO_VAULT = { xai: "grok" };
13388
13516
  function vaultId(engineName) {
13389
13517
  return ENGINE_TO_VAULT[engineName] ?? engineName;
13390
13518
  }
13519
+ var ACTIVITY_TEXT_CAP = 8e3;
13520
+ var ASKED_CAP = 280;
13521
+ var VISION_PROVIDERS = ["anthropic", "openai", "gemini", "grok"];
13522
+ var NO_IMAGE_PURPOSES = /* @__PURE__ */ new Set(["early_stop", "extract", "canary", "classify"]);
13523
+ var MAX_RUN_IMAGES = 8;
13524
+ function withRunImages(args, provider, images) {
13525
+ if (!images?.length || NO_IMAGE_PURPOSES.has(args.purpose ?? "")) return args;
13526
+ const msgs = [...args.messages];
13527
+ let idx = -1;
13528
+ for (let i = msgs.length - 1; i >= 0; i--) if (msgs[i]?.role === "user") {
13529
+ idx = i;
13530
+ break;
13531
+ }
13532
+ if (idx < 0) return args;
13533
+ const m = msgs[idx];
13534
+ if (VISION_PROVIDERS.includes(provider)) {
13535
+ msgs[idx] = { ...m, images: [...m.images ?? [], ...images] };
13536
+ } else {
13537
+ const n = images.length;
13538
+ msgs[idx] = {
13539
+ ...m,
13540
+ content: `${m.content}
13541
+
13542
+ [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"}.]`
13543
+ };
13544
+ }
13545
+ return { ...args, messages: msgs };
13546
+ }
13547
+ var runContext = new import_node_async_hooks3.AsyncLocalStorage();
13548
+ var SYNTHESIS_PURPOSES = /* @__PURE__ */ new Set(["synth", "moderator", "recombine", "judge", "unify"]);
13549
+ function exemptFromSkip(ctx, provider, purpose) {
13550
+ return provider === ctx.moderator && SYNTHESIS_PURPOSES.has(purpose);
13551
+ }
13552
+ function skippedError(provider, why, limitMs) {
13553
+ return new ProviderError(
13554
+ "client",
13555
+ why === "timeout" ? `${provider}: stopped after ${Math.round((limitMs ?? 0) / 1e3)}s (your per-model time limit)` : `${provider}: stopped waiting (you skipped it)`,
13556
+ { transient: false }
13557
+ );
13558
+ }
13559
+ function lastUserText(args) {
13560
+ const msgs = args.messages;
13561
+ for (let i = msgs.length - 1; i >= 0; i--) {
13562
+ const m = msgs[i];
13563
+ if (m && m.role === "user" && typeof m.content === "string") {
13564
+ const t = m.content.replace(/\s+/g, " ").trim();
13565
+ return t.length > ASKED_CAP ? `${t.slice(0, ASKED_CAP - 1)}\u2026` : t;
13566
+ }
13567
+ }
13568
+ return "";
13569
+ }
13570
+ function withActivity(p) {
13571
+ const send = p.send.bind(p);
13572
+ return {
13573
+ name: p.name,
13574
+ model: p.model,
13575
+ ...p.fallbackModels ? { fallbackModels: p.fallbackModels } : {},
13576
+ send: async (args) => {
13577
+ const ctx = runContext.getStore();
13578
+ if (!ctx) return send(args);
13579
+ const callId = ctx.nextCallId();
13580
+ const provider = vaultId(p.name);
13581
+ const model = args.modelOverride ?? p.model;
13582
+ const purpose = args.purpose ?? "worker";
13583
+ const started = Date.now();
13584
+ const exempt = exemptFromSkip(ctx, provider, purpose);
13585
+ if (!exempt && ctx.skipped.has(provider)) throw skippedError(provider, "user");
13586
+ ctx.emit({ type: "call.start", runId: ctx.runId, at: started, callId, provider, model, purpose, asked: lastUserText(args) });
13587
+ const controller = new AbortController();
13588
+ if (args.signal) {
13589
+ if (args.signal.aborted) controller.abort(args.signal.reason);
13590
+ else args.signal.addEventListener("abort", () => controller.abort(args.signal.reason), { once: true });
13591
+ }
13592
+ let stopped;
13593
+ if (!exempt) ctx.inflight.set(callId, { provider, purpose, controller });
13594
+ const timer = !exempt && ctx.callTimeoutMs && ctx.callTimeoutMs > 0 ? setTimeout(() => {
13595
+ stopped = "timeout";
13596
+ controller.abort("timeout");
13597
+ }, ctx.callTimeoutMs) : void 0;
13598
+ controller.signal.addEventListener("abort", () => {
13599
+ if (!stopped && controller.signal.reason === "skip") stopped = "user";
13600
+ }, { once: true });
13601
+ try {
13602
+ const res = await send({ ...withRunImages(args, provider, ctx.images), signal: controller.signal });
13603
+ const text = typeof res.text === "string" ? res.text : "";
13604
+ ctx.emit({
13605
+ type: "call.done",
13606
+ runId: ctx.runId,
13607
+ at: Date.now(),
13608
+ callId,
13609
+ provider,
13610
+ model,
13611
+ purpose,
13612
+ ok: true,
13613
+ ms: Date.now() - started,
13614
+ text: text.slice(0, ACTIVITY_TEXT_CAP),
13615
+ truncated: text.length > ACTIVITY_TEXT_CAP,
13616
+ error: null,
13617
+ usage: usageOf(res)
13618
+ });
13619
+ return res;
13620
+ } catch (err) {
13621
+ const out = stopped ? skippedError(provider, stopped, ctx.callTimeoutMs) : err;
13622
+ ctx.emit({
13623
+ type: "call.done",
13624
+ runId: ctx.runId,
13625
+ at: Date.now(),
13626
+ callId,
13627
+ provider,
13628
+ model,
13629
+ purpose,
13630
+ ok: false,
13631
+ ms: Date.now() - started,
13632
+ text: "",
13633
+ truncated: false,
13634
+ error: out instanceof Error ? out.message : String(out),
13635
+ usage: null,
13636
+ ...stopped ? { stopped } : {}
13637
+ });
13638
+ throw out;
13639
+ } finally {
13640
+ if (timer) clearTimeout(timer);
13641
+ ctx.inflight.delete(callId);
13642
+ }
13643
+ }
13644
+ };
13645
+ }
13391
13646
  function usageOf(answer) {
13392
13647
  const u = answer["usage"];
13393
13648
  if (!u || typeof u !== "object") return null;
@@ -13423,6 +13678,8 @@ function bundledPricingPath() {
13423
13678
  }
13424
13679
  }
13425
13680
  var runCounter = 0;
13681
+ var callCounter = 0;
13682
+ var nextCallId = () => ++callCounter;
13426
13683
  function nextRunId() {
13427
13684
  runCounter += 1;
13428
13685
  return `run_${Date.now().toString(36)}_${runCounter}`;
@@ -13437,11 +13694,19 @@ function createEmbeddedEngine(opts) {
13437
13694
  const varName = MODEL_ENV[provider.trim().toLowerCase()];
13438
13695
  if (varName && model) env[varName] = model;
13439
13696
  }
13697
+ const superEnv = {};
13698
+ for (const [provider, model] of Object.entries(opts.superModels ?? {})) {
13699
+ const p = provider.trim().toLowerCase();
13700
+ const varName = SUPER_ENV_VARS[p === "grok" ? "xai" : p];
13701
+ if (varName && model) superEnv[varName] = model;
13702
+ }
13440
13703
  const pricingPath = [opts.pricingPath, bundledPricingPath()].find(
13441
13704
  (p) => Boolean(p) && (0, import_node_fs16.existsSync)(p)
13442
13705
  );
13443
13706
  const pricing = pricingPath ? loadPricing(pricingPath) : {};
13444
- const built = buildProviders({ env, pricing });
13707
+ const built = Object.fromEntries(
13708
+ Object.entries(buildProviders({ env, pricing })).map(([name, p]) => [name, withActivity(p)])
13709
+ );
13445
13710
  const moderator = opts.moderator ?? "anthropic";
13446
13711
  const tools = registerCoreTools({ providers: built, pricing });
13447
13712
  const providerIds = Object.keys(built).map(vaultId).sort();
@@ -13458,7 +13723,8 @@ function createEmbeddedEngine(opts) {
13458
13723
  if (!tool) return Promise.reject(new Error(`unknown tool: ${name}`));
13459
13724
  return Promise.resolve(tool.handler(args));
13460
13725
  };
13461
- const run = async (name, args, onEvent) => {
13726
+ const liveRuns = /* @__PURE__ */ new Map();
13727
+ const run = async (name, args, onEvent, runOpts = {}) => {
13462
13728
  const runId = nextRunId();
13463
13729
  const started = Date.now();
13464
13730
  const emit = (e) => {
@@ -13467,6 +13733,79 @@ function createEmbeddedEngine(opts) {
13467
13733
  } catch {
13468
13734
  }
13469
13735
  };
13736
+ const ctx = {
13737
+ runId,
13738
+ emit,
13739
+ nextCallId,
13740
+ skipped: /* @__PURE__ */ new Set(),
13741
+ inflight: /* @__PURE__ */ new Map(),
13742
+ moderator: vaultId(moderator),
13743
+ ...runOpts.callTimeoutMs && runOpts.callTimeoutMs > 0 ? { callTimeoutMs: runOpts.callTimeoutMs } : {},
13744
+ ...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) } : {}
13745
+ };
13746
+ liveRuns.set(runId, ctx);
13747
+ try {
13748
+ return await runContext.run(ctx, () => withProgress(runId, (n) => {
13749
+ if (n.params.message) emit({ type: "progress", runId, at: Date.now(), message: n.params.message });
13750
+ }, () => withSuperEnv(superEnv, () => runInner(name, args, runId, started, emit))));
13751
+ } finally {
13752
+ liveRuns.delete(runId);
13753
+ }
13754
+ };
13755
+ const skip = (runId, provider) => {
13756
+ const ctx = liveRuns.get(runId);
13757
+ if (!ctx) return 0;
13758
+ ctx.skipped.add(provider);
13759
+ let stopped = 0;
13760
+ for (const call2 of ctx.inflight.values()) {
13761
+ if (call2.provider === provider && !exemptFromSkip(ctx, call2.provider, call2.purpose)) {
13762
+ call2.controller.abort("skip");
13763
+ stopped += 1;
13764
+ }
13765
+ }
13766
+ return stopped;
13767
+ };
13768
+ const ask = async (o) => {
13769
+ const engineName = Object.keys(built).find((n) => vaultId(n) === o.provider);
13770
+ const base = engineName ? built[engineName] : void 0;
13771
+ if (!base) {
13772
+ return { ok: false, text: "", json: null, model: o.model ?? "", error: `No ${o.provider} key is configured, so it can't be asked.` };
13773
+ }
13774
+ const provider = o.model && o.model !== base.model ? retargetProvider(base, o.model) : base;
13775
+ const maxTokens = o.maxTokens ?? 8e3;
13776
+ const doAsk = async () => {
13777
+ if (o.schema) {
13778
+ const res = await requestStructured(provider, o.messages, o.schema, { maxTokens, purpose: o.purpose, maxRetries: 1 });
13779
+ return {
13780
+ ok: res.obj !== null,
13781
+ text: res.answer.response ?? "",
13782
+ json: res.obj,
13783
+ error: res.obj !== null ? null : res.answer.error ?? res.errors.join("; ") ?? "invalid reply",
13784
+ model: provider.model
13785
+ };
13786
+ }
13787
+ const a = await askOne(provider, o.messages, { maxTokens, temperature: 0.3, purpose: o.purpose });
13788
+ return { ok: !a.error, text: a.response ?? "", json: null, error: a.error ?? null, model: provider.model };
13789
+ };
13790
+ if (!o.runId || !o.onEvent) return doAsk();
13791
+ const sink = o.onEvent;
13792
+ const emit = (e) => {
13793
+ try {
13794
+ sink(e);
13795
+ } catch {
13796
+ }
13797
+ };
13798
+ const ctx = {
13799
+ runId: o.runId,
13800
+ emit,
13801
+ nextCallId,
13802
+ skipped: /* @__PURE__ */ new Set(),
13803
+ inflight: /* @__PURE__ */ new Map(),
13804
+ moderator: o.provider
13805
+ };
13806
+ return runContext.run(ctx, doAsk);
13807
+ };
13808
+ const runInner = async (name, args, runId, started, emit) => {
13470
13809
  emit({
13471
13810
  type: "run.start",
13472
13811
  runId,
@@ -13544,8 +13883,16 @@ function createEmbeddedEngine(opts) {
13544
13883
  providers: providerIds,
13545
13884
  models,
13546
13885
  listTools: () => [...tools.keys()],
13886
+ requiredArgs: (name) => {
13887
+ const tool = tools.get(name);
13888
+ if (!tool) return null;
13889
+ const req = tool.inputSchema?.required;
13890
+ return Array.isArray(req) ? req.filter((x) => typeof x === "string") : [];
13891
+ },
13547
13892
  call,
13548
13893
  run,
13894
+ skip,
13895
+ ask,
13549
13896
  close: async () => {
13550
13897
  await flush().catch(() => {
13551
13898
  });
@@ -13555,15 +13902,21 @@ function createEmbeddedEngine(opts) {
13555
13902
  var __test_internals = { usageOf, textOf, errorOf, vaultId };
13556
13903
  // Annotate the CommonJS export names for ESM import in node:
13557
13904
  0 && (module.exports = {
13905
+ ACTIVITY_TEXT_CAP,
13558
13906
  DEFAULT_EXCLUDED_PROVIDERS,
13559
13907
  DEFAULT_FALLBACKS,
13560
13908
  DEFAULT_MODELS,
13909
+ IMAGE_MEDIA_TYPES,
13910
+ MAX_RUN_IMAGES,
13911
+ SUPER_MODELS,
13912
+ VISION_PROVIDERS,
13561
13913
  __KEY_ENV,
13562
13914
  __MODEL_ENV,
13563
13915
  __test_internals,
13564
13916
  createEmbeddedEngine,
13565
13917
  isAlive,
13566
13918
  listProcesses,
13567
- processRegistryPath
13919
+ processRegistryPath,
13920
+ withRunImages
13568
13921
  });
13569
13922
  //# sourceMappingURL=embed.cjs.map