@agentproto/runtime 2.3.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -2573,7 +2573,7 @@ function resolveAuthSpec(input) {
2573
2573
  }
2574
2574
  if (!provider) return void 0;
2575
2575
  const sub = input.descriptor.authSubscription;
2576
- const supportsSub = sub !== void 0 && (gatewayRoute === void 0 || isNativeGatewayPreset);
2576
+ const supportsSub = (sub !== void 0 || input.descriptor.modelDerivedApiKey === true) && (gatewayRoute === void 0 || isNativeGatewayPreset);
2577
2577
  const enforce = input.descriptor.authEnforce ?? "when-configured";
2578
2578
  const external = supportsSub && sub?.external === true;
2579
2579
  const subCredAvailable = input.subscriptionCredential !== void 0 || external && input.externalSubscriptionVerified === true;
@@ -2605,7 +2605,7 @@ function resolveAuthSpec(input) {
2605
2605
  credentialSource = subCredAvailable ? "cli-local-login" : "none";
2606
2606
  externalCredential = true;
2607
2607
  } else if (mode === "subscription") {
2608
- setEnv = sub.setEnv;
2608
+ setEnv = sub?.setEnv ?? apiKeyEnv;
2609
2609
  credential = input.subscriptionCredential;
2610
2610
  credentialSource = credential !== void 0 ? input.subscriptionCredentialSource ?? "explicit-config" : "none";
2611
2611
  } else {
@@ -3679,7 +3679,8 @@ function resolveModelId(id) {
3679
3679
  }
3680
3680
  function methodsForDirect(descriptor) {
3681
3681
  const methods = [];
3682
- if (descriptor?.authSubscription) methods.push("oauth-bearer");
3682
+ if (descriptor?.authSubscription || descriptor?.modelDerivedApiKey)
3683
+ methods.push("oauth-bearer");
3683
3684
  if (descriptor?.provider || descriptor?.modelDerivedApiKey) methods.push("api-key");
3684
3685
  return methods;
3685
3686
  }
@@ -7505,6 +7506,8 @@ function toSessionSummary(desc) {
7505
7506
  lastOutputAt: desc.lastOutputAt,
7506
7507
  lastActivityAt: desc.lastActivityAt,
7507
7508
  processAlive: desc.processAlive,
7509
+ watchers: desc.watchers,
7510
+ childrenBusy: desc.childrenBusy,
7508
7511
  label: desc.label,
7509
7512
  title: desc.title,
7510
7513
  renamedByUser: desc.renamedByUser,
@@ -7532,6 +7535,7 @@ function toSessionSummary(desc) {
7532
7535
  turnsCompleted: desc.turnsCompleted,
7533
7536
  busy: desc.busy,
7534
7537
  blockedOn: desc.blockedOn,
7538
+ stalledSinceMs: desc.stalledSinceMs,
7535
7539
  origin: desc.origin,
7536
7540
  parentSessionId: desc.parentSessionId,
7537
7541
  depth: desc.depth,
@@ -7659,6 +7663,28 @@ function createSessionsRegistry(opts) {
7659
7663
  const sessionEvents = opts?.sessionEvents;
7660
7664
  const resolveAgentAdapter = opts?.resolveAgentAdapter;
7661
7665
  const sessions = /* @__PURE__ */ new Map();
7666
+ const watchersById = /* @__PURE__ */ new Map();
7667
+ const stampWatchers = (desc) => {
7668
+ desc.watchers = watchersById.get(desc.id) ?? 0;
7669
+ };
7670
+ const childrenBusyCounts = () => {
7671
+ const all = Array.from(sessions.values());
7672
+ const parentOf = new Map(all.map((s) => [s.desc.id, s.desc.parentSessionId]));
7673
+ const counts = /* @__PURE__ */ new Map();
7674
+ for (const s of all) {
7675
+ const d = s.desc;
7676
+ const midTurn = d.busy === true && (d.status === "running" || d.status === "starting");
7677
+ if (!midTurn) continue;
7678
+ const seen = /* @__PURE__ */ new Set([d.id]);
7679
+ let pid = d.parentSessionId;
7680
+ while (pid && !seen.has(pid)) {
7681
+ seen.add(pid);
7682
+ counts.set(pid, (counts.get(pid) ?? 0) + 1);
7683
+ pid = parentOf.get(pid);
7684
+ }
7685
+ }
7686
+ return counts;
7687
+ };
7662
7688
  const pendingPermissions = /* @__PURE__ */ new Map();
7663
7689
  let persistTimer = null;
7664
7690
  let nextSubId = 1;
@@ -7722,6 +7748,17 @@ function createSessionsRegistry(opts) {
7722
7748
  ...rt.desc.endedReason ? { reason: rt.desc.endedReason } : {}
7723
7749
  });
7724
7750
  };
7751
+ const clearStalledFlag = (rt) => {
7752
+ if (rt.desc.stalledSinceMs === void 0) return;
7753
+ rt.desc.stalledSinceMs = void 0;
7754
+ schedulePersist();
7755
+ sessionEvents?.emit({
7756
+ type: "session:stall-cleared",
7757
+ sessionId: rt.desc.id,
7758
+ ...rt.desc.label ? { label: rt.desc.label } : {},
7759
+ ts: (/* @__PURE__ */ new Date()).toISOString()
7760
+ });
7761
+ };
7725
7762
  const refreshAwaitingPermission = (rt) => {
7726
7763
  let has = false;
7727
7764
  for (const p of pendingPermissions.values()) {
@@ -8503,6 +8540,7 @@ ${message}`;
8503
8540
  rt.desc.awaitingInput = false;
8504
8541
  rt.desc.awaitingQuestion = void 0;
8505
8542
  releaseBlockedOn(rt.desc);
8543
+ clearStalledFlag(rt);
8506
8544
  let turnCompleted = false;
8507
8545
  let sawTurnEnd = false;
8508
8546
  let abnormalReason;
@@ -8560,6 +8598,7 @@ ${message}`;
8560
8598
  rt.desc.busy = false;
8561
8599
  rt.emitter.emit("busy", false);
8562
8600
  releaseBlockedOn(rt.desc);
8601
+ clearStalledFlag(rt);
8563
8602
  if (pendingToolCallIds.size > 0) {
8564
8603
  for (const toolCallId of pendingToolCallIds) {
8565
8604
  const synthetic = {
@@ -9501,13 +9540,17 @@ ${message}`;
9501
9540
  const rt = sessions.get(id);
9502
9541
  if (!rt) return;
9503
9542
  rt.desc.lastActivityAt = (/* @__PURE__ */ new Date()).toISOString();
9543
+ clearStalledFlag(rt);
9504
9544
  schedulePersist();
9505
9545
  },
9506
9546
  list(opts2) {
9507
9547
  const includeArchived = opts2?.includeArchived ?? false;
9548
+ const childrenBusy = childrenBusyCounts();
9508
9549
  return Array.from(sessions.values()).map((s) => s.desc).filter((desc) => includeArchived || !desc.archived).sort((a, b) => b.startedAt.localeCompare(a.startedAt)).map((desc) => {
9509
9550
  stampProcessAlive(desc);
9510
9551
  stampInterrupted(desc);
9552
+ stampWatchers(desc);
9553
+ desc.childrenBusy = childrenBusy.get(desc.id) ?? 0;
9511
9554
  return desc;
9512
9555
  });
9513
9556
  },
@@ -9515,11 +9558,14 @@ ${message}`;
9515
9558
  const includeArchived = opts2?.includeArchived ?? false;
9516
9559
  const limit = Math.max(1, Math.min(200, opts2?.limit ?? 50));
9517
9560
  const offset = Math.max(0, opts2?.offset ?? 0);
9561
+ const childrenBusy = childrenBusyCounts();
9518
9562
  const all = Array.from(sessions.values()).map((s) => s.desc).filter((desc) => includeArchived || !desc.archived).sort((a, b) => b.startedAt.localeCompare(a.startedAt));
9519
9563
  const slice = all.slice(offset, offset + limit);
9520
9564
  const summaries = slice.map((desc) => {
9521
9565
  stampProcessAlive(desc);
9522
9566
  stampInterrupted(desc);
9567
+ stampWatchers(desc);
9568
+ desc.childrenBusy = childrenBusy.get(desc.id) ?? 0;
9523
9569
  return toSessionSummary(desc);
9524
9570
  });
9525
9571
  return { summaries, total: all.length };
@@ -9529,9 +9575,19 @@ ${message}`;
9529
9575
  if (desc) {
9530
9576
  stampProcessAlive(desc);
9531
9577
  stampInterrupted(desc);
9578
+ stampWatchers(desc);
9579
+ desc.childrenBusy = childrenBusyCounts().get(desc.id) ?? 0;
9532
9580
  }
9533
9581
  return desc;
9534
9582
  },
9583
+ incWatchers(id) {
9584
+ watchersById.set(id, (watchersById.get(id) ?? 0) + 1);
9585
+ },
9586
+ decWatchers(id) {
9587
+ const next = (watchersById.get(id) ?? 0) - 1;
9588
+ if (next > 0) watchersById.set(id, next);
9589
+ else watchersById.delete(id);
9590
+ },
9535
9591
  attach(id, onLine) {
9536
9592
  const rt = sessions.get(id);
9537
9593
  if (!rt) return null;
@@ -9698,6 +9754,30 @@ ${message}`;
9698
9754
  emitExited(rt);
9699
9755
  return true;
9700
9756
  },
9757
+ markStalled(id, stalledSinceMs) {
9758
+ const rt = sessions.get(id);
9759
+ if (!rt) return false;
9760
+ if (rt.desc.kind !== "agent-cli" || rt.desc.status !== "running") return false;
9761
+ if (rt.desc.busy !== true || rt.desc.blockedOn !== void 0) return false;
9762
+ if (rt.desc.stalledSinceMs !== void 0) return false;
9763
+ rt.desc.stalledSinceMs = stalledSinceMs;
9764
+ schedulePersist();
9765
+ sessionEvents?.emit({
9766
+ type: "session:stalled",
9767
+ sessionId: rt.desc.id,
9768
+ stalledSinceMs,
9769
+ ...rt.desc.label ? { label: rt.desc.label } : {},
9770
+ ts: (/* @__PURE__ */ new Date()).toISOString()
9771
+ });
9772
+ return true;
9773
+ },
9774
+ clearStalled(id) {
9775
+ const rt = sessions.get(id);
9776
+ if (!rt) return false;
9777
+ const wasFlagged = rt.desc.stalledSinceMs !== void 0;
9778
+ clearStalledFlag(rt);
9779
+ return wasFlagged;
9780
+ },
9701
9781
  isResuming(id) {
9702
9782
  return !!sessions.get(id)?.resumePromise;
9703
9783
  },
@@ -11008,6 +11088,7 @@ function registerAgentTools(server, opts) {
11008
11088
  buildOrchestratorMcp,
11009
11089
  callerScope,
11010
11090
  callerSessionId,
11091
+ mcpBridgeOrigin,
11011
11092
  webhookNotifier,
11012
11093
  daemonMcpUrl,
11013
11094
  loadRoleRegistry: loadRoleRegistry2,
@@ -11285,6 +11366,12 @@ function registerAgentTools(server, opts) {
11285
11366
  {
11286
11367
  ...spawnInput,
11287
11368
  adapter,
11369
+ // Auto-stamp the source channel (#session-visibility): when the
11370
+ // caller didn't pass an explicit `origin`, fall back to the connecting
11371
+ // client's `?origin=` label so a bridge-client spawn (cowork/vscode/
11372
+ // codex) is attributed instead of landing as a bare root. An explicit
11373
+ // `input.origin` (already in `spawnInput`) always wins.
11374
+ ...!spawnInput.origin && mcpBridgeOrigin ? { origin: mcpBridgeOrigin } : {},
11288
11375
  // The trusted caller id (from `?callerSessionId=`) becomes the
11289
11376
  // implicit auto-parent — attach-by-default without the caller
11290
11377
  // passing its own id. An explicit `parentSessionId` still outranks
@@ -12531,6 +12618,15 @@ async function restartAgentSession(registry, resolveAgentAdapter, prev, opts = {
12531
12618
  ...accessProfileEcho ? { accessProfile: accessProfileEcho } : {},
12532
12619
  ...effMode ? { mode: effMode } : {},
12533
12620
  ...resolved.commandPreview ? { commandPreview: resolved.commandPreview } : {},
12621
+ // Lineage carry-forward (#session-visibility). A restart is a NEW
12622
+ // descriptor, but it is the same logical session continued — so its
12623
+ // origin (which channel spawned it: cowork/vscode/codex/cron) and its
12624
+ // parent/depth must survive, exactly as continue-fresh already carries
12625
+ // them (session-continue-fresh.ts). Dropping them here is what left a
12626
+ // restarted session a bare top-level root with no source trace.
12627
+ ...prev.origin ? { origin: prev.origin } : {},
12628
+ ...prev.parentSessionId ? { parentSessionId: prev.parentSessionId } : {},
12629
+ ...prev.depth !== void 0 ? { depth: prev.depth } : {},
12534
12630
  // Verifiability echo (never the credential) — see the auth
12535
12631
  // resolution block above. Absent when no credential resolved,
12536
12632
  // same as session-spawn.ts.
@@ -14106,6 +14202,13 @@ function registerSessionTools(rawServer, opts) {
14106
14202
  rows: input.rows ?? 24,
14107
14203
  ...prev.name ? { name: prev.name } : {},
14108
14204
  ...prev.label ? { label: prev.label } : {},
14205
+ // Lineage carry-forward (#session-visibility) — same reasoning as
14206
+ // the agent branch in session-restart-core.ts: a restart keeps the
14207
+ // logical session's origin/parent/depth rather than resetting it to
14208
+ // a bare root.
14209
+ ...prev.origin ? { origin: prev.origin } : {},
14210
+ ...prev.parentSessionId ? { parentSessionId: prev.parentSessionId } : {},
14211
+ ...prev.depth !== void 0 ? { depth: prev.depth } : {},
14109
14212
  resumedFrom: prev.id,
14110
14213
  resumeVia: describeResumePath(augmented)
14111
14214
  });
@@ -19676,11 +19779,13 @@ async function monitorSessionWait(opts) {
19676
19779
  return new Promise((resolve22) => {
19677
19780
  const unsubs = [];
19678
19781
  let settled = false;
19782
+ for (const id of resolvedIds) registry.incWatchers(id);
19679
19783
  const finish = (result) => {
19680
19784
  if (settled) return;
19681
19785
  settled = true;
19682
19786
  clearTimeout(timer);
19683
19787
  for (const u of unsubs) u();
19788
+ for (const id of resolvedIds) registry.decWatchers(id);
19684
19789
  resolve22(result);
19685
19790
  };
19686
19791
  const relevantTypes = targetEvent === "any" ? ["session:turn-end", "session:awaiting-input", "session:exited"] : targetEvent === "turn-end" ? ["session:turn-end", "session:awaiting-input"] : targetEvent === "awaiting-input" ? ["session:awaiting-input"] : ["session:exited"];
@@ -21039,11 +21144,18 @@ async function startHttpServer(opts) {
21039
21144
  const raw = new URLSearchParams(url.slice(qIdx + 1)).get("callerSessionId");
21040
21145
  return raw && raw.length > 0 ? raw : void 0;
21041
21146
  }
21147
+ function parseOriginQuery(url) {
21148
+ const qIdx = url.indexOf("?");
21149
+ if (qIdx === -1) return void 0;
21150
+ const raw = new URLSearchParams(url.slice(qIdx + 1)).get("origin");
21151
+ return raw && raw.length > 0 ? raw : void 0;
21152
+ }
21042
21153
  async function handleMcp(req, res) {
21043
21154
  if (!authorizeMcp(req, res)) return;
21044
21155
  const denyTools = parseDenyToolsQuery(req.url ?? "");
21045
21156
  const callerSessionId = parseCallerSessionIdQuery(req.url ?? "");
21046
- const server2 = await opts.mcpServerFactory(denyTools, callerSessionId);
21157
+ const origin = parseOriginQuery(req.url ?? "");
21158
+ const server2 = await opts.mcpServerFactory(denyTools, callerSessionId, origin);
21047
21159
  await serveMcp(req, res, server2);
21048
21160
  }
21049
21161
  async function handleOrchestratorMcp(req, res) {
@@ -21093,7 +21205,8 @@ async function startHttpServer(opts) {
21093
21205
  resumeSessionsOnBoot: opts.meta.resumeSessionsOnBoot === true,
21094
21206
  idleReapAfterMs: opts.meta.idleReapAfterMs ?? 0,
21095
21207
  crashDetectIntervalMs: opts.meta.crashDetectIntervalMs ?? 0,
21096
- restartSweepIntervalMs: opts.meta.restartSweepIntervalMs ?? 0
21208
+ restartSweepIntervalMs: opts.meta.restartSweepIntervalMs ?? 0,
21209
+ turnStallAfterMs: opts.meta.turnStallAfterMs ?? 0
21097
21210
  })
21098
21211
  );
21099
21212
  }
@@ -24539,6 +24652,49 @@ function runCrashDetectPass(opts) {
24539
24652
  return summary;
24540
24653
  }
24541
24654
 
24655
+ // src/stall-watchdog.ts
24656
+ function lastActivityMsOf(desc) {
24657
+ const tsStr = desc.lastActivityAt ?? desc.startedAt;
24658
+ const ts = tsStr ? Date.parse(tsStr) : Number.NaN;
24659
+ return Number.isFinite(ts) ? ts : null;
24660
+ }
24661
+ function isStallCandidate(desc, nowMs, thresholdMs) {
24662
+ if (desc.kind !== "agent-cli") return false;
24663
+ if (desc.status !== "running") return false;
24664
+ if (desc.busy !== true) return false;
24665
+ if (desc.blockedOn !== void 0) return false;
24666
+ if (desc.stalledSinceMs !== void 0) return false;
24667
+ const lastMs = lastActivityMsOf(desc);
24668
+ if (lastMs === null) return false;
24669
+ return nowMs - lastMs > thresholdMs;
24670
+ }
24671
+ function runStallWatchdogPass(opts) {
24672
+ const { registry, isServed } = opts;
24673
+ const thresholdMs = opts.turnStallAfterMs;
24674
+ if (!thresholdMs || thresholdMs <= 0) {
24675
+ return { enabled: false, candidates: 0, stalled: 0, ids: [] };
24676
+ }
24677
+ const nowMs = opts.now ? opts.now() : Date.now();
24678
+ const all = registry.list({ includeArchived: true });
24679
+ const candidates = all.filter(
24680
+ (d) => (isServed?.(d) ?? true) && isStallCandidate(d, nowMs, thresholdMs)
24681
+ );
24682
+ const summary = {
24683
+ enabled: true,
24684
+ candidates: candidates.length,
24685
+ stalled: 0,
24686
+ ids: []
24687
+ };
24688
+ for (const d of candidates) {
24689
+ const lastMs = lastActivityMsOf(d) ?? nowMs;
24690
+ if (registry.markStalled(d.id, lastMs)) {
24691
+ summary.stalled++;
24692
+ summary.ids.push(d.id);
24693
+ }
24694
+ }
24695
+ return summary;
24696
+ }
24697
+
24542
24698
  // src/restart-scheduler.ts
24543
24699
  function isEligibleForRestart(desc) {
24544
24700
  const policy = desc.restartPolicy;
@@ -25638,6 +25794,13 @@ function createAppRegistry(opts) {
25638
25794
  listApps() {
25639
25795
  return [...state.apps];
25640
25796
  },
25797
+ removeApp(appId) {
25798
+ const idx = state.apps.findIndex((a) => a.appId === appId);
25799
+ if (idx === -1) return void 0;
25800
+ const [removed] = state.apps.splice(idx, 1);
25801
+ persist();
25802
+ return removed;
25803
+ },
25641
25804
  createRun(input) {
25642
25805
  const run = {
25643
25806
  appRunId: `apprun_${randomUUID()}`,
@@ -25694,6 +25857,31 @@ function createAppRegistry(opts) {
25694
25857
  }
25695
25858
  };
25696
25859
  }
25860
+ var EMPTY_CATALOG = { apps: [] };
25861
+ function defaultAppCatalogPath() {
25862
+ return join(homedir(), ".agentproto", "app-catalog.json");
25863
+ }
25864
+ async function loadAppCatalogFile(path) {
25865
+ const catalogPath = path ?? defaultAppCatalogPath();
25866
+ let raw;
25867
+ try {
25868
+ raw = await readFile(catalogPath, "utf8");
25869
+ } catch {
25870
+ return EMPTY_CATALOG;
25871
+ }
25872
+ try {
25873
+ const parsed = JSON.parse(raw);
25874
+ if (!Array.isArray(parsed.apps)) return EMPTY_CATALOG;
25875
+ const apps = parsed.apps.filter((e) => {
25876
+ if (typeof e !== "object" || e === null) return false;
25877
+ const rec = e;
25878
+ return typeof rec.appId === "string" && typeof rec.dir === "string";
25879
+ });
25880
+ return { apps };
25881
+ } catch {
25882
+ return EMPTY_CATALOG;
25883
+ }
25884
+ }
25697
25885
 
25698
25886
  // src/app-tools.ts
25699
25887
  var DEFAULT_AGENT_ADAPTER = "mastra-agent";
@@ -25726,7 +25914,12 @@ async function readAppRefs(dir) {
25726
25914
  const toRefs = (v) => Array.isArray(v) ? v.filter(
25727
25915
  (e) => typeof e === "object" && e !== null && typeof e.id === "string" && typeof e.path === "string"
25728
25916
  ).map((e) => ({ id: e.id, path: resolveRef(dir, e.path) })) : [];
25729
- return { agents: toRefs(data.agents), workflows: toRefs(data.workflows) };
25917
+ let ui;
25918
+ if (typeof data.ui === "object" && data.ui !== null && typeof data.ui.path === "string") {
25919
+ const uiData = data.ui;
25920
+ ui = { ...uiData, path: resolveRef(dir, uiData.path) };
25921
+ }
25922
+ return { agents: toRefs(data.agents), workflows: toRefs(data.workflows), ...ui ? { ui } : {} };
25730
25923
  }
25731
25924
  async function performInstall(dir, appRegistry, listRegisteredToolIds, resolveAgentAdapter) {
25732
25925
  let handle;
@@ -25764,20 +25957,31 @@ async function performInstall(dir, appRegistry, listRegisteredToolIds, resolveAg
25764
25957
  const unvalidatedAgentTools = [
25765
25958
  ...new Set(handle.agents.flatMap((e) => (e.agent.tools ?? []).map(refIdOf)))
25766
25959
  ];
25960
+ const ui = refs.ui ? {
25961
+ path: refs.ui.path,
25962
+ ...handle.ui?.title !== void 0 ? { title: handle.ui.title } : {},
25963
+ ...handle.ui?.description !== void 0 ? { description: handle.ui.description } : {},
25964
+ ...handle.ui?.tools !== void 0 ? { tools: handle.ui.tools } : {},
25965
+ ...handle.ui?.csp !== void 0 ? { csp: handle.ui.csp } : {}
25966
+ } : void 0;
25767
25967
  const record2 = appRegistry.upsertApp({
25768
25968
  appId: handle.id,
25769
25969
  dir,
25770
25970
  ...handle.version ? { version: handle.version } : {},
25771
25971
  ...handle.name ? { name: handle.name } : {},
25972
+ ...handle.description ? { description: handle.description } : {},
25772
25973
  agents: refs.agents,
25773
25974
  workflows: refs.workflows,
25774
25975
  unvalidatedAgentTools,
25775
- ...handle.requires ? { requires: handle.requires } : {}
25976
+ ...handle.requires ? { requires: handle.requires } : {},
25977
+ ...ui ? { ui } : {},
25978
+ ...handle.artifacts ? { artifacts: handle.artifacts } : {},
25979
+ ...handle.dev ? { dev: handle.dev } : {}
25776
25980
  });
25777
25981
  return { ok: true, record: record2 };
25778
25982
  }
25779
25983
  function registerAppTools(server, opts) {
25780
- const { registry, resolveAgentAdapter, listRegisteredToolIds, workflowRunner } = opts;
25984
+ const { registry, resolveAgentAdapter, listRegisteredToolIds, workflowRunner, dispatchTool, callImportedTool } = opts;
25781
25985
  const appRegistry = opts.appRegistry ?? createAppRegistry({
25782
25986
  ...opts.persistPath !== void 0 ? { persistPath: opts.persistPath } : {},
25783
25987
  ...opts.persist !== void 0 ? { persist: opts.persist } : {}
@@ -26026,6 +26230,167 @@ function registerAppTools(server, opts) {
26026
26230
  return textResult(result);
26027
26231
  }
26028
26232
  );
26233
+ server.tool(
26234
+ "app_tool_call",
26235
+ "Call one of an installed app's UI-exposed tools \u2014 the allowlist set at `defineApp({ ui: { tools: [...] } })` time (`app_install`'s `record.ui.tools`). A tool id prefixed `imported:<alias>/<toolName>` dispatches through an imported MCP server (same proxy `mcp_imported_call` uses); every other id dispatches through the daemon's own registered tools (same reach-in routine/cron `target.tool` dispatch uses).",
26236
+ {
26237
+ appId: z.string(),
26238
+ tool: z.string().describe("A tool id from the app's `ui.tools` allowlist."),
26239
+ args: z.record(z.string(), z.unknown()).optional().describe("Tool arguments. Default: empty object.")
26240
+ },
26241
+ async (input) => {
26242
+ const installed = appRegistry.getApp(input.appId);
26243
+ if (!installed || !installed.ui) {
26244
+ return errorResult(`app_tool_call: app "${input.appId}" is not installed or has no UI.`);
26245
+ }
26246
+ const allowlist = installed.ui.tools ?? [];
26247
+ if (!allowlist.includes(input.tool)) {
26248
+ return errorResult(
26249
+ `app_tool_call: tool "${input.tool}" is not in app "${input.appId}"'s ui.tools allowlist: ${allowlist.length > 0 ? allowlist.join(", ") : "(empty)"}`
26250
+ );
26251
+ }
26252
+ const args = input.args ?? {};
26253
+ try {
26254
+ if (input.tool.startsWith("imported:")) {
26255
+ if (!callImportedTool) return notEnabled("app_tool_call");
26256
+ const rest = input.tool.slice("imported:".length);
26257
+ const slash = rest.indexOf("/");
26258
+ if (slash === -1) {
26259
+ return errorResult(
26260
+ `app_tool_call: malformed imported tool id "${input.tool}" \u2014 expected "imported:<alias>/<toolName>".`
26261
+ );
26262
+ }
26263
+ const result2 = await callImportedTool(rest.slice(0, slash), rest.slice(slash + 1), args);
26264
+ return textResult(result2);
26265
+ }
26266
+ if (!dispatchTool) return notEnabled("app_tool_call");
26267
+ const result = await dispatchTool(input.tool, args);
26268
+ return textResult(result);
26269
+ } catch (err) {
26270
+ return errorResult(`app_tool_call: ${err instanceof Error ? err.message : String(err)}`);
26271
+ }
26272
+ }
26273
+ );
26274
+ server.tool(
26275
+ "app_uninstall",
26276
+ "Remove an installed app's record. Refuses if the app is applied to any scope (unapply first via app_unapply) or has a running app_run (stop it first via app_stop).",
26277
+ { appId: z.string() },
26278
+ async (input) => {
26279
+ const applied = appRegistry.listApplied().filter((m) => m.appId === input.appId);
26280
+ if (applied.length > 0) {
26281
+ return errorResult(
26282
+ `app_uninstall: app "${input.appId}" is applied to scope(s) ${applied.map((m) => m.scopeId).join(", ")} \u2014 unapply from scopes first.`
26283
+ );
26284
+ }
26285
+ const runningRuns = appRegistry.listRuns().filter((r) => r.appId === input.appId && r.status === "running");
26286
+ if (runningRuns.length > 0) {
26287
+ return errorResult(
26288
+ `app_uninstall: app "${input.appId}" has running app_run(s) ${runningRuns.map((r) => r.appRunId).join(", ")} \u2014 stop app runs first.`
26289
+ );
26290
+ }
26291
+ const removed = appRegistry.removeApp(input.appId);
26292
+ if (!removed) {
26293
+ return errorResult(`app_uninstall: no installed app "${input.appId}".`);
26294
+ }
26295
+ return textResult({ appId: removed.appId });
26296
+ }
26297
+ );
26298
+ server.tool(
26299
+ "app_catalog",
26300
+ "List browsable apps from the catalog file (default `~/.agentproto/app-catalog.json`, tolerates a missing file), merged with installed-app status \u2014 every entry reports `installed` and `hasUi`. Installed apps absent from the catalog file are included too.",
26301
+ {
26302
+ scopeId: z.string().optional().describe("Reserved for future scope-aware filtering. Currently unused.")
26303
+ },
26304
+ async () => {
26305
+ const catalog = await loadAppCatalogFile(opts.catalogPath);
26306
+ const installedApps = appRegistry.listApps();
26307
+ const installedById = new Map(installedApps.map((a) => [a.appId, a]));
26308
+ const seen = /* @__PURE__ */ new Set();
26309
+ const entries = catalog.apps.map((entry) => {
26310
+ const installed = installedById.get(entry.appId);
26311
+ seen.add(entry.appId);
26312
+ const name = entry.name ?? installed?.name;
26313
+ const description = entry.description ?? installed?.description;
26314
+ return {
26315
+ appId: entry.appId,
26316
+ ...name ? { name } : {},
26317
+ ...description ? { description } : {},
26318
+ dir: entry.dir,
26319
+ ...entry.category ? { category: entry.category } : {},
26320
+ installed: installed !== void 0,
26321
+ hasUi: installed?.ui !== void 0
26322
+ };
26323
+ });
26324
+ for (const app of installedApps) {
26325
+ if (seen.has(app.appId)) continue;
26326
+ entries.push({
26327
+ appId: app.appId,
26328
+ ...app.name ? { name: app.name } : {},
26329
+ ...app.description ? { description: app.description } : {},
26330
+ dir: app.dir,
26331
+ installed: true,
26332
+ hasUi: app.ui !== void 0
26333
+ });
26334
+ }
26335
+ return textResult(entries);
26336
+ }
26337
+ );
26338
+ }
26339
+ function appUiToolId(appId) {
26340
+ const slug = appId.replace(/^@[^/]+\//, "").replace(/[^a-z0-9]/g, "_");
26341
+ return `app_ui_${slug}`;
26342
+ }
26343
+ function createUiHtmlCache() {
26344
+ const cache = /* @__PURE__ */ new Map();
26345
+ return {
26346
+ async get(path, version) {
26347
+ const cached = cache.get(path);
26348
+ if (cached && cached.version === version) return cached.html;
26349
+ const html = await readFile(path, "utf8");
26350
+ cache.set(path, { version, html });
26351
+ return html;
26352
+ }
26353
+ };
26354
+ }
26355
+ async function makeInstalledAppUiApps(appRegistry, cache, existingToolNames) {
26356
+ const apps = [];
26357
+ const seen = new Set(existingToolNames);
26358
+ for (const app of appRegistry.listApps()) {
26359
+ const ui = app.ui;
26360
+ if (!ui) continue;
26361
+ const toolId = appUiToolId(app.appId);
26362
+ if (seen.has(toolId)) {
26363
+ console.warn(
26364
+ `[app-ui-apps] skipping UI panel for app "${app.appId}": tool id "${toolId}" collides with an existing tool or another installed app's panel.`
26365
+ );
26366
+ continue;
26367
+ }
26368
+ let html;
26369
+ try {
26370
+ html = await cache.get(ui.path, app.updatedAt);
26371
+ } catch (err) {
26372
+ console.warn(
26373
+ `[app-ui-apps] skipping UI panel for app "${app.appId}": could not read "${ui.path}": ${err instanceof Error ? err.message : String(err)}`
26374
+ );
26375
+ continue;
26376
+ }
26377
+ seen.add(toolId);
26378
+ apps.push({
26379
+ id: toolId,
26380
+ title: ui.title ?? app.name ?? app.appId,
26381
+ ...ui.description ? { description: ui.description } : {},
26382
+ inputSchema: z.object({}),
26383
+ execute: async () => ({ appId: app.appId, tools: ui.tools ?? [] }),
26384
+ html,
26385
+ ...ui.csp ? {
26386
+ csp: {
26387
+ ...ui.csp.connectDomains ? { connectDomains: [...ui.csp.connectDomains] } : {},
26388
+ ...ui.csp.resourceDomains ? { resourceDomains: [...ui.csp.resourceDomains] } : {}
26389
+ }
26390
+ } : {}
26391
+ });
26392
+ }
26393
+ return apps;
26029
26394
  }
26030
26395
  function createSessionEventBus() {
26031
26396
  const ee = new EventEmitter();
@@ -29211,7 +29576,8 @@ function registerDaemonHealthTools(server, opts) {
29211
29576
  resumeSessionsOnBoot: opts.resumeSessionsOnBoot,
29212
29577
  idleReapAfterMs: opts.idleReapAfterMs,
29213
29578
  crashDetectIntervalMs: opts.crashDetectIntervalMs ?? 0,
29214
- restartSweepIntervalMs: opts.restartSweepIntervalMs ?? 0
29579
+ restartSweepIntervalMs: opts.restartSweepIntervalMs ?? 0,
29580
+ turnStallAfterMs: opts.turnStallAfterMs ?? 0
29215
29581
  });
29216
29582
  }
29217
29583
  );
@@ -31356,6 +31722,7 @@ async function isAgentCliAuthConfigured(slug, descriptor, model) {
31356
31722
 
31357
31723
  // src/index.ts
31358
31724
  var DEFAULT_CRASH_DETECT_INTERVAL_MS = 3e4;
31725
+ var DEFAULT_TURN_STALL_AFTER_MS = 5 * 6e4;
31359
31726
  var DEFAULT_ALWAYS_ON_TOOLS = [
31360
31727
  "daemon_health",
31361
31728
  "agent_start",
@@ -31366,7 +31733,8 @@ var DEFAULT_ALWAYS_ON_TOOLS = [
31366
31733
  "session_monitor",
31367
31734
  "session_events_poll",
31368
31735
  "permissions_list",
31369
- "permissions_respond"
31736
+ "permissions_respond",
31737
+ "app_tool_call"
31370
31738
  ];
31371
31739
  async function createGateway(opts) {
31372
31740
  const startedAt = Date.now();
@@ -31374,6 +31742,7 @@ async function createGateway(opts) {
31374
31742
  const idleReapAfterMs = typeof opts.idleReapAfterMs === "number" && opts.idleReapAfterMs > 0 ? opts.idleReapAfterMs : 0;
31375
31743
  const crashDetectIntervalMs = typeof opts.crashDetectIntervalMs === "number" ? opts.crashDetectIntervalMs > 0 ? opts.crashDetectIntervalMs : 0 : DEFAULT_CRASH_DETECT_INTERVAL_MS;
31376
31744
  const restartSweepIntervalMs = typeof opts.restartSweepIntervalMs === "number" && opts.restartSweepIntervalMs > 0 ? opts.restartSweepIntervalMs : 0;
31745
+ const turnStallAfterMs = typeof opts.turnStallAfterMs === "number" ? opts.turnStallAfterMs > 0 ? opts.turnStallAfterMs : 0 : DEFAULT_TURN_STALL_AFTER_MS;
31377
31746
  const workspace = resolve(opts.workspace);
31378
31747
  if (!existsSync(workspace)) {
31379
31748
  throw new Error(`runtime: workspace dir does not exist: ${workspace}`);
@@ -31550,7 +31919,8 @@ async function createGateway(opts) {
31550
31919
  cronScheduler,
31551
31920
  dispatchTool
31552
31921
  });
31553
- const appRegistry = createAppRegistry();
31922
+ const appRegistry = createAppRegistry({ persist });
31923
+ const appUiHtmlCache = createUiHtmlCache();
31554
31924
  const workflowRunner = opts.resolveAgentAdapter ? createWorkflowRunner({
31555
31925
  registry: sessions,
31556
31926
  sessionEvents,
@@ -31671,7 +32041,7 @@ async function createGateway(opts) {
31671
32041
  ...opts.listAgentAdapters ? { listAgentAdapters: opts.listAgentAdapters } : {},
31672
32042
  ...opts.listHarnessCapabilities ? { listHarnessCapabilities: opts.listHarnessCapabilities } : {}
31673
32043
  });
31674
- const mcpServerFactory = async (denyTools, callerSessionId) => {
32044
+ const mcpServerFactory = async (denyTools, callerSessionId, origin) => {
31675
32045
  const { server: rawServer } = await createMcpServer({
31676
32046
  specs: opts.specs,
31677
32047
  workspace,
@@ -31690,7 +32060,8 @@ async function createGateway(opts) {
31690
32060
  resumeSessionsOnBoot: opts.resumeSessionsOnBoot === true,
31691
32061
  idleReapAfterMs,
31692
32062
  crashDetectIntervalMs,
31693
- restartSweepIntervalMs
32063
+ restartSweepIntervalMs,
32064
+ turnStallAfterMs
31694
32065
  });
31695
32066
  registerCommandTools(server, {
31696
32067
  workspace,
@@ -31714,6 +32085,9 @@ async function createGateway(opts) {
31714
32085
  // a spawn made by an agent session attaches under it by default (see
31715
32086
  // spawn-attach.ts). Absent on a human/root `/mcp` call → no auto-parent.
31716
32087
  ...callerSessionId ? { callerSessionId } : {},
32088
+ // `?origin=` query (#session-visibility) — the connecting client's source
32089
+ // label, used as the default origin for a spawn that doesn't set its own.
32090
+ ...origin ? { mcpBridgeOrigin: origin } : {},
31717
32091
  webhookNotifier,
31718
32092
  daemonMcpUrl,
31719
32093
  resolveSandboxProvider: resolveSandboxProviderResolved,
@@ -31753,6 +32127,16 @@ async function createGateway(opts) {
31753
32127
  registry: sessions,
31754
32128
  listRegisteredToolIds,
31755
32129
  appRegistry,
32130
+ dispatchTool,
32131
+ // Same proxy `mcp_imported_call` (session-tools.ts) dispatches
32132
+ // through — unwraps `{ok,result}|{ok:false,error}` into a plain
32133
+ // return-or-throw for `app_tool_call`'s `imported:<alias>/<toolName>`
32134
+ // ids.
32135
+ callImportedTool: async (alias, tool, args) => {
32136
+ const out = await mcpProxy.callTool(alias, tool, args);
32137
+ if (!out.ok) throw new Error(`app_tool_call: imported "${alias}".${tool}: ${out.error}`);
32138
+ return out.result;
32139
+ },
31756
32140
  ...opts.resolveAgentAdapter ? { resolveAgentAdapter: opts.resolveAgentAdapter } : {},
31757
32141
  ...workflowRunner ? { workflowRunner } : {}
31758
32142
  });
@@ -31764,7 +32148,7 @@ async function createGateway(opts) {
31764
32148
  }
31765
32149
  return rows;
31766
32150
  };
31767
- registerMcpApps(server, [
32151
+ const builtinPanelApps = [
31768
32152
  makeSessionsPanelApp({ listSessions: listSessionsFiltered }),
31769
32153
  makeAgentsOverviewApp({ listSessions: listSessionsFiltered }),
31770
32154
  makeBureauSessionsApp({ listSessions: listSessionsFiltered }),
@@ -31814,7 +32198,13 @@ async function createGateway(opts) {
31814
32198
  }
31815
32199
  })
31816
32200
  ] : []
31817
- ]);
32201
+ ];
32202
+ const installedAppUiApps = await makeInstalledAppUiApps(
32203
+ appRegistry,
32204
+ appUiHtmlCache,
32205
+ new Set(builtinPanelApps.map((app) => app.id))
32206
+ );
32207
+ registerMcpApps(server, [...builtinPanelApps, ...installedAppUiApps]);
31818
32208
  registerSummarizeSessionTool(server, {
31819
32209
  getSession: (id) => sessions.get(id),
31820
32210
  tailLines: (id, lastN) => {
@@ -31967,7 +32357,8 @@ async function createGateway(opts) {
31967
32357
  resumeSessionsOnBoot: opts.resumeSessionsOnBoot === true,
31968
32358
  idleReapAfterMs,
31969
32359
  crashDetectIntervalMs,
31970
- restartSweepIntervalMs
32360
+ restartSweepIntervalMs,
32361
+ turnStallAfterMs
31971
32362
  },
31972
32363
  cronScheduler,
31973
32364
  routineRegistrar
@@ -32012,6 +32403,27 @@ async function createGateway(opts) {
32012
32403
  }, crashDetectIntervalMs);
32013
32404
  crashDetectTimer.unref?.();
32014
32405
  }
32406
+ let turnStallTimer = null;
32407
+ if (turnStallAfterMs > 0) {
32408
+ const rawInterval = process.env.AGENTPROTO_TURN_STALL_INTERVAL_MS;
32409
+ const parsedInterval = rawInterval ? Number.parseInt(rawInterval, 10) : NaN;
32410
+ const intervalMs = Number.isFinite(parsedInterval) && parsedInterval > 0 ? parsedInterval : Math.min(turnStallAfterMs, 6e4);
32411
+ turnStallTimer = setInterval(() => {
32412
+ try {
32413
+ const summary = runStallWatchdogPass({ registry: sessions, turnStallAfterMs });
32414
+ if (summary.stalled > 0) {
32415
+ console.log(
32416
+ `[stall-watchdog] flagged ${summary.stalled}/${summary.candidates} stalled agent session(s): ${summary.ids.join(", ")}`
32417
+ );
32418
+ }
32419
+ } catch (err) {
32420
+ console.warn(
32421
+ `[stall-watchdog] sweep failed: ${err instanceof Error ? err.message : String(err)}`
32422
+ );
32423
+ }
32424
+ }, intervalMs);
32425
+ turnStallTimer.unref?.();
32426
+ }
32015
32427
  let restartSweepTimer = null;
32016
32428
  if (restartSweepIntervalMs > 0) {
32017
32429
  restartSweepTimer = setInterval(() => {
@@ -32072,6 +32484,7 @@ async function createGateway(opts) {
32072
32484
  heartbeat.stop();
32073
32485
  if (idleReapTimer) clearInterval(idleReapTimer);
32074
32486
  if (crashDetectTimer) clearInterval(crashDetectTimer);
32487
+ if (turnStallTimer) clearInterval(turnStallTimer);
32075
32488
  if (restartSweepTimer) clearInterval(restartSweepTimer);
32076
32489
  restartScheduler.dispose();
32077
32490
  inboundWatcher?.shutdown();
@@ -32131,6 +32544,6 @@ var export_providersPath = providers_store_exports.providersPath;
32131
32544
  var export_removeProviderKey = providers_store_exports.removeProviderKey;
32132
32545
  var export_setProviderKey = providers_store_exports.setProviderKey;
32133
32546
 
32134
- export { AnthropicRemainingQuotaReader, AuthResolutionError, BUCKETS_ROOT, CLAUDE_CODE_OAUTH_SOURCE, DEFAULT_BUCKET, DEFAULT_ORCHESTRATOR_TOOLS, DEFAULT_WORKTREE_ISOLATION, INBOUND_PROVIDERS, LEGACY_SESSIONS_FILE, PAIRINGS_VERSION, POSTURE_NATIVE_ALIASES, POSTURE_PREAMBLES, export_PROVIDER_ENV_VARS as PROVIDER_ENV_VARS, ResumeDisabledError, SESSION_ID_ENV, SubscriptionSourceError, TASK_STATUSES, WORKSPACE_SLUG_ENV, WORKTREE_ISOLATION_ENV, activityCounts, appendConversationRecord, attachSandbox, bucketDir, bucketSessionsFile, bucketTranscriptDir, buildCatalogModels, buildCatalogProviderModels, buildMcpConfigSnippet, buildRouteAwareLaunchConfig, canonicalForModeId, claudeProjectSlug, composeMode, composeSessionObservers, conversationIndexPath, createActivityProjector, createFileStepCache, createGateway, createInboundEndpointStore, createOrchestratorInjector, createOrchestratorMcpServerFactory, createPairingRegistry, createPrProvenanceReconciler, createReconnectLogGate, createScopeTokenRegistry, createSupervisorTaskGateRunner, createTaskLedger, createWorkspaceFs, credentialFingerprint, daemonRegistryDir, decideWorktreeIsolation, declaredPresetToProviderPreset, decomposeMode, deleteUserPreset, deriveSessionUsage, enrichRollupWithProviderQuota, enrichWithRemainingQuota, evaluateCostBudget, fileConversationStore, filterActivities, findConversationRecord, findNativeMode, formatToolCall, formatToolResult, getMcpCredentialDeps, export_getProviderKey as getProviderKey, getUserPreset, export_injectProviderKeysIntoEnv as injectProviderKeysIntoEnv, isAgentCliAuthConfigured, isClosedTaskStatus, isSafeBucketSlug, isTerminalActivityState, listBuckets, listPresets, listUserPresets, export_loadProviders as loadProviders, loadQuotaStore, loadUserPresets, loadWorktreeIsolation, locateConversationByNativePath, locateConversationBySessionId, makeBrowserAdapterLister, migrateLegacySessionsFile, migrationMarkerPath, monitorPolicyWait, monitorSessionWait, narrowOrchestratorTools, normalizeInbound, normalizeModeId, normalizeSkillsOption, normalizeWorktreeField, parseAnthropicRateLimitHeaders, parseDuration, parseTaskStatus, parseWindow, parseWorktreeIsolationMode, policyToActivities, policyWatchesSession, prToActivities, projectSessionUsage, export_providerEnvVar as providerEnvVar, export_providersPath as providersPath, readConversationIndex, readDaemonRegistry, readProfileQuota, readRegisteredSlugs, readRuntimeMeta, readUsageSnapshots, reapOrphanedDescendants, recordProfileQuota, registerBuiltinRoutes, registerPairingTools, registerSandboxAttachTool, export_removeProviderKey as removeProviderKey, resolveAuthSpec, resolveBucketSlug, resolveNativeLink, resolvePosture, resolveSpawnDefaults, resolveSubscriptionCredential, rollupUsage, runCrashDetectPass, runEagerResumePass, runIdleReapPass, saveUserPreset, setMcpCredentialDeps, export_setProviderKey as setProviderKey, sweepStaleDaemonRegistry, sweepStaleRuntimeMetas, toWorktreeStatusView, turnToActivities, unlinkDaemonRegistryEntry, unlinkRuntimeMeta, userPresetsPath, verifyInboundSignature, workflowToActivities, writeDaemonRegistryEntry };
32547
+ export { AnthropicRemainingQuotaReader, AuthResolutionError, BUCKETS_ROOT, CLAUDE_CODE_OAUTH_SOURCE, DEFAULT_BUCKET, DEFAULT_ORCHESTRATOR_TOOLS, DEFAULT_WORKTREE_ISOLATION, INBOUND_PROVIDERS, LEGACY_SESSIONS_FILE, PAIRINGS_VERSION, POSTURE_NATIVE_ALIASES, POSTURE_PREAMBLES, export_PROVIDER_ENV_VARS as PROVIDER_ENV_VARS, ResumeDisabledError, SESSION_ID_ENV, SubscriptionSourceError, TASK_STATUSES, WORKSPACE_SLUG_ENV, WORKTREE_ISOLATION_ENV, activityCounts, appendConversationRecord, attachSandbox, bucketDir, bucketSessionsFile, bucketTranscriptDir, buildCatalogModels, buildCatalogProviderModels, buildMcpConfigSnippet, buildRouteAwareLaunchConfig, canonicalForModeId, claudeProjectSlug, composeMode, composeSessionObservers, conversationIndexPath, createActivityProjector, createFileStepCache, createGateway, createInboundEndpointStore, createOrchestratorInjector, createOrchestratorMcpServerFactory, createPairingRegistry, createPrProvenanceReconciler, createReconnectLogGate, createScopeTokenRegistry, createSupervisorTaskGateRunner, createTaskLedger, createWorkspaceFs, credentialFingerprint, daemonRegistryDir, decideWorktreeIsolation, declaredPresetToProviderPreset, decomposeMode, deleteUserPreset, deriveSessionUsage, enrichRollupWithProviderQuota, enrichWithRemainingQuota, evaluateCostBudget, fileConversationStore, filterActivities, findConversationRecord, findNativeMode, formatToolCall, formatToolResult, getMcpCredentialDeps, export_getProviderKey as getProviderKey, getUserPreset, export_injectProviderKeysIntoEnv as injectProviderKeysIntoEnv, isAgentCliAuthConfigured, isClosedTaskStatus, isSafeBucketSlug, isTerminalActivityState, listBuckets, listPresets, listUserPresets, export_loadProviders as loadProviders, loadQuotaStore, loadUserPresets, loadWorktreeIsolation, locateConversationByNativePath, locateConversationBySessionId, makeBrowserAdapterLister, migrateLegacySessionsFile, migrationMarkerPath, monitorPolicyWait, monitorSessionWait, narrowOrchestratorTools, normalizeInbound, normalizeModeId, normalizeSkillsOption, normalizeWorktreeField, parseAnthropicRateLimitHeaders, parseDuration, parseTaskStatus, parseWindow, parseWorktreeIsolationMode, policyToActivities, policyWatchesSession, prToActivities, projectSessionUsage, export_providerEnvVar as providerEnvVar, export_providersPath as providersPath, readConversationIndex, readDaemonRegistry, readProfileQuota, readRegisteredSlugs, readRuntimeMeta, readUsageSnapshots, reapOrphanedDescendants, recordProfileQuota, registerBuiltinRoutes, registerPairingTools, registerSandboxAttachTool, export_removeProviderKey as removeProviderKey, resolveAuthSpec, resolveBucketSlug, resolveNativeLink, resolvePosture, resolveSpawnDefaults, resolveSubscriptionCredential, rollupUsage, runCrashDetectPass, runEagerResumePass, runIdleReapPass, runStallWatchdogPass, saveUserPreset, setMcpCredentialDeps, export_setProviderKey as setProviderKey, sweepStaleDaemonRegistry, sweepStaleRuntimeMetas, toWorktreeStatusView, turnToActivities, unlinkDaemonRegistryEntry, unlinkRuntimeMeta, userPresetsPath, verifyInboundSignature, workflowToActivities, writeDaemonRegistryEntry };
32135
32548
  //# sourceMappingURL=index.mjs.map
32136
32549
  //# sourceMappingURL=index.mjs.map