zidane 7.0.20 → 7.0.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/dist/acp-cli.js +2 -2
  2. package/dist/acp.d.ts +1 -1
  3. package/dist/agent.d.ts +1 -1
  4. package/dist/{anthropic-DATE-m9f.js → anthropic-BSbDiW0J.js} +34 -4
  5. package/dist/anthropic-BSbDiW0J.js.map +1 -0
  6. package/dist/{approvals-CzrFKdu-.js → approvals-Deg8JhMI.js} +209 -67
  7. package/dist/approvals-Deg8JhMI.js.map +1 -0
  8. package/dist/{auth-DD4KYv1w.js → auth-Nq-tSMb9.js} +52 -34
  9. package/dist/{auth-DD4KYv1w.js.map → auth-Nq-tSMb9.js.map} +1 -1
  10. package/dist/chat/pure.d.ts +3 -3
  11. package/dist/chat.d.ts +5 -5
  12. package/dist/chat.js +2 -2
  13. package/dist/contexts/daytona.d.ts +1 -1
  14. package/dist/contexts/e2b.d.ts +1 -1
  15. package/dist/daemon-cli.js +1 -1
  16. package/dist/eval.d.ts +1 -1
  17. package/dist/extensions.d.ts +1 -1
  18. package/dist/headless.d.ts +1 -1
  19. package/dist/{index-CvGkUoNk.d.ts → index-C4mY0oKE.d.ts} +3 -21
  20. package/dist/index-C4mY0oKE.d.ts.map +1 -0
  21. package/dist/{index-CGjexO2a.d.ts → index-DQn4tuAA.d.ts} +7 -5
  22. package/dist/index-DQn4tuAA.d.ts.map +1 -0
  23. package/dist/index.d.ts +1 -1
  24. package/dist/index.js +3 -3
  25. package/dist/{ipc-gce-02nV.js → ipc-DlfrDGKv.js} +2 -2
  26. package/dist/{ipc-gce-02nV.js.map → ipc-DlfrDGKv.js.map} +1 -1
  27. package/dist/ipc.d.ts +5 -5
  28. package/dist/ipc.d.ts.map +1 -1
  29. package/dist/ipc.js +3 -3
  30. package/dist/mcp.d.ts +1 -1
  31. package/dist/{oauth-D-LZ4ic-.js → oauth-CmtlmCzi.js} +142 -210
  32. package/dist/oauth-CmtlmCzi.js.map +1 -0
  33. package/dist/output/stream-json.d.ts +1 -1
  34. package/dist/output/terminal.d.ts +1 -1
  35. package/dist/plugins.d.ts +1 -1
  36. package/dist/presets.d.ts +1 -1
  37. package/dist/providers/anthropic.d.ts +1 -1
  38. package/dist/providers/anthropic.js +1 -1
  39. package/dist/providers/arcee.d.ts +1 -1
  40. package/dist/providers/baseten.d.ts +1 -1
  41. package/dist/providers/cerebras.d.ts +1 -1
  42. package/dist/providers/local.d.ts +1 -1
  43. package/dist/providers/openai-compat.d.ts +1 -1
  44. package/dist/providers/openai.d.ts +1 -1
  45. package/dist/providers/openai.js +1 -1
  46. package/dist/providers/openrouter.d.ts +1 -1
  47. package/dist/providers/xai.d.ts +1 -1
  48. package/dist/providers/xai.js +1 -1
  49. package/dist/{providers-Bjdvmpfu.js → providers-ZucqgwU7.js} +2 -2
  50. package/dist/{providers-Bjdvmpfu.js.map → providers-ZucqgwU7.js.map} +1 -1
  51. package/dist/providers.d.ts +1 -1
  52. package/dist/providers.js +3 -3
  53. package/dist/restate.d.ts +1 -1
  54. package/dist/{server-C3FOQvIu.js → server-DW-sKF3g.js} +19 -6
  55. package/dist/server-DW-sKF3g.js.map +1 -0
  56. package/dist/session/sqlite.d.ts +1 -1
  57. package/dist/session.d.ts +1 -1
  58. package/dist/skills.d.ts +1 -1
  59. package/dist/{tool-formatters-BTNnkola.d.ts → tool-formatters-GZHxP824.d.ts} +2 -2
  60. package/dist/{tool-formatters-BTNnkola.d.ts.map → tool-formatters-GZHxP824.d.ts.map} +1 -1
  61. package/dist/tools/fetch-url.d.ts +1 -1
  62. package/dist/tools/web-search.d.ts +1 -1
  63. package/dist/tools.d.ts +1 -1
  64. package/dist/{transcript-anchors-DzY3KZ54.d.ts → transcript-anchors-CY50AXdF.d.ts} +2 -2
  65. package/dist/{transcript-anchors-DzY3KZ54.d.ts.map → transcript-anchors-CY50AXdF.d.ts.map} +1 -1
  66. package/dist/tui.d.ts +3 -3
  67. package/dist/tui.d.ts.map +1 -1
  68. package/dist/tui.js +506 -379
  69. package/dist/tui.js.map +1 -1
  70. package/dist/{turn-operations-DRED3NeH.d.ts → turn-operations-CAmNETlu.d.ts} +3 -3
  71. package/dist/{turn-operations-DRED3NeH.d.ts.map → turn-operations-CAmNETlu.d.ts.map} +1 -1
  72. package/dist/types.d.ts +1 -1
  73. package/docs/CHAT.md +8 -0
  74. package/docs/IPC.md +4 -2
  75. package/package.json +1 -1
  76. package/dist/anthropic-DATE-m9f.js.map +0 -1
  77. package/dist/approvals-CzrFKdu-.js.map +0 -1
  78. package/dist/index-CGjexO2a.d.ts.map +0 -1
  79. package/dist/index-CvGkUoNk.d.ts.map +0 -1
  80. package/dist/oauth-D-LZ4ic-.js.map +0 -1
  81. package/dist/server-C3FOQvIu.js.map +0 -1
@@ -18,7 +18,7 @@ import { i as findActiveTriggers, n as collectReferences, o as mergeSuggestions,
18
18
  import { r as fetchUrl } from "./fetch-url-ma-5_p0p.js";
19
19
  import { webSearch } from "./tools/web-search.js";
20
20
  import { A as chunkMarkdownForRender, At as MAIN_SESSION_TITLE, Bt as renderSessionEventXml, Ft as artifactsFromTurns, It as isMainSession, J as filterChainFallbacks, Lt as orchestratedBy, Nt as SESSION_ROLE_KEY, Pt as WORKER_REPORT_FRAGMENT, Qt as formatRunReceiptLine, Rt as parseSessionEventXml, St as promptTurnRefs, U as buildRunModel, Ut as sessionEventLabel, _n as mergeApprovalAndBodyOutcomes, bn as rewriteMultiEditHeader, dn as previewEditPayload, et as restoreChainFallbacks, hn as buildEditOutcomesAnnotation, jt as ORCHESTRATED_BY_KEY, kt as MAIN_PLAYBOOK_FRAGMENT, ln as extractEditPayload, m as ownerOf, nn as runReceiptFromRun, tn as hasRunReceipt, u as capTranscriptEvents, vn as parseEditOutcomesFromResult, wn as chatReferenceTokensFromText, xn as stripEditOutcomesAnnotation, yn as resolveApprovalForPayload, zt as renderProjectsBriefing } from "./turn-operations-BgqpLlOG.js";
21
- import { T as restoreModelOptions, b as modelSupportsReasoning, d as BUILTIN_PROVIDERS, f as anthropicDescriptor, g as getContextWindow, h as enabledModelOptions, i as readCredentials, m as credKeyOf, n as applyApiKeyEnv, r as credentialsPath, t as detectAuth, x as modelsForDescriptor } from "./auth-DD4KYv1w.js";
21
+ import { T as restoreModelOptions, b as modelSupportsReasoning, d as BUILTIN_PROVIDERS, f as anthropicDescriptor, g as getContextWindow, h as enabledModelOptions, i as readCredentials, m as credKeyOf, n as applyApiKeyEnv, r as credentialsPath, t as detectAuth, x as modelsForDescriptor } from "./auth-Nq-tSMb9.js";
22
22
  import { basename, delimiter, dirname, isAbsolute, join, posix, relative, resolve, sep } from "node:path";
23
23
  import { Buffer } from "node:buffer";
24
24
  import { chmodSync, closeSync, cpSync, createReadStream, createWriteStream, existsSync, mkdirSync, mkdtempSync, openSync, readFileSync, readSync, readdirSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
@@ -9137,14 +9137,23 @@ const RUN_HEARTBEAT_MS = 60 * 1e3;
9137
9137
  function startRunHeartbeat(opts) {
9138
9138
  const enabled = opts.env.multiProcess === true || opts.env.readSettings().useDaemon === true;
9139
9139
  let lastBeat = Promise.resolve();
9140
+ let beatInFlight = false;
9141
+ let ending;
9140
9142
  const timer = enabled ? setInterval(() => {
9141
- if (opts.isRunning()) lastBeat = opts.env.store.updateStatus(opts.sessionId, "running").catch(() => void 0);
9143
+ if (!ending && !beatInFlight && opts.isRunning()) {
9144
+ beatInFlight = true;
9145
+ lastBeat = opts.env.store.updateStatus(opts.sessionId, "running").catch(() => void 0).finally(() => {
9146
+ beatInFlight = false;
9147
+ });
9148
+ }
9142
9149
  }, RUN_HEARTBEAT_MS) : void 0;
9143
9150
  return { end(settledStatus) {
9144
- if (timer) clearInterval(timer);
9145
- return lastBeat.then(async () => {
9151
+ if (ending) return ending;
9152
+ if (timer !== void 0) clearInterval(timer);
9153
+ ending = lastBeat.then(async () => {
9146
9154
  if (enabled && settledStatus && settledStatus !== "running") await opts.env.store.updateStatus(opts.sessionId, settledStatus);
9147
9155
  }).catch(() => void 0);
9156
+ return ending;
9148
9157
  } };
9149
9158
  }
9150
9159
  /**
@@ -10783,7 +10792,28 @@ function resultToText(result) {
10783
10792
  function createChatHost(env) {
10784
10793
  const debugStream = env.debugStream ?? process.env.ZIDANE_IPC_DEBUG_STREAM === "1";
10785
10794
  let orchestrationRef;
10795
+ const dispatchSignals = /* @__PURE__ */ new Map();
10786
10796
  const broadcast = (signal) => {
10797
+ if (signal.kind === "run:start" || signal.kind === "run:end") {
10798
+ const dispatch = dispatchSignals.get(signal.sessionId);
10799
+ if (dispatch) {
10800
+ if (signal.kind === "run:end") {
10801
+ dispatch.end = signal;
10802
+ return;
10803
+ }
10804
+ const previous = dispatch.end;
10805
+ dispatch.end = void 0;
10806
+ if (previous) {
10807
+ dispatchSignals.delete(signal.sessionId);
10808
+ try {
10809
+ broadcast(previous);
10810
+ } finally {
10811
+ dispatchSignals.set(signal.sessionId, dispatch);
10812
+ }
10813
+ }
10814
+ dispatch.runId = signal.runId;
10815
+ }
10816
+ }
10787
10817
  if (debugStream) {
10788
10818
  const preview = signal.kind === "event" && signal.event.kind === "markdown" ? `markdown:"${signal.event.text.slice(0, 30)}${signal.event.text.length > 30 ? "…" : ""}"` : signal.kind === "event" ? `event:${signal.event.kind}${signal.event.kind === "tool" || signal.event.kind === "tool-result" ? `(${signal.event.tool})` : ""}` : signal.kind;
10789
10819
  console.log(`[ipc-host] → ${preview}`);
@@ -10827,12 +10857,20 @@ function createChatHost(env) {
10827
10857
  steer: steerSession,
10828
10858
  interrupt: interruptSession,
10829
10859
  liveSession: (sessionId) => active.get(sessionId)?.agent.session ?? void 0,
10830
- isRunning: (sessionId) => active.get(sessionId)?.agent.isRunning === true,
10860
+ isRunning: isSessionBusy,
10831
10861
  createSession: createSessionInStore$1
10832
10862
  });
10833
10863
  orchestrationRef = orchestration;
10834
10864
  const commands = createCommandModule({
10835
- env,
10865
+ env: {
10866
+ ...env,
10867
+ runtimeConfig: async (cwd) => {
10868
+ const generation = assertDispatchOpen();
10869
+ const config = await env.runtimeConfig(cwd);
10870
+ assertDispatchOpen(generation);
10871
+ return config;
10872
+ }
10873
+ },
10836
10874
  broadcast,
10837
10875
  ensureAgent,
10838
10876
  buildProvider,
@@ -10857,6 +10895,22 @@ function createChatHost(env) {
10857
10895
  * pre-invalidation config.
10858
10896
  */
10859
10897
  let teardownGeneration = 0;
10898
+ const dispatches = /* @__PURE__ */ new Map();
10899
+ const lifecycleWork = /* @__PURE__ */ new Set();
10900
+ let closed = false;
10901
+ let drainPromise;
10902
+ function trackWork(work) {
10903
+ lifecycleWork.add(work);
10904
+ work.finally(() => lifecycleWork.delete(work)).catch(() => void 0);
10905
+ return work;
10906
+ }
10907
+ function assertDispatchOpen(generation = teardownGeneration) {
10908
+ if (closed || generation !== teardownGeneration) throw new Error("Chat host was shut down. Retry with an active host.");
10909
+ return generation;
10910
+ }
10911
+ function isSessionBusy(sessionId) {
10912
+ return dispatches.has(sessionId) || active.get(sessionId)?.agent.isRunning === true;
10913
+ }
10860
10914
  /**
10861
10915
  * The per-run receipt (`run-summary`) for the run that just ended, read off
10862
10916
  * the session's latest TOP-LEVEL run record. Emitted BEFORE `run:end` so it
@@ -10939,11 +10993,11 @@ function createChatHost(env) {
10939
10993
  run.commandAbort?.abort();
10940
10994
  run.compactionController?.abort();
10941
10995
  run.controller.abort();
10942
- run.warnLog?.close().catch(() => void 0);
10996
+ if (run.warnLog) trackWork(run.warnLog.close()).catch(() => void 0);
10943
10997
  run.ledger.clear();
10944
10998
  run.work.clear();
10945
10999
  if (opts?.broadcastWork !== false) broadcastWorkSnapshot(run);
10946
- run.agent.destroy().catch(() => void 0);
11000
+ trackWork(run.agent.destroy()).catch(() => void 0);
10947
11001
  }
10948
11002
  /** Tear down a built-but-never-activated (or stale) run. */
10949
11003
  function discardRun(run) {
@@ -10954,7 +11008,7 @@ function createChatHost(env) {
10954
11008
  active.delete(sessionId);
10955
11009
  }
10956
11010
  function pruneIdleAgents() {
10957
- const idle = [...active.entries()].filter(([, entry]) => !entry.agent.isRunning && !entry.compacting && entry.commandAbort === void 0 && entry.work.size === 0).sort((a, b) => a[1].lastUsedAt - b[1].lastUsedAt);
11011
+ const idle = [...active.entries()].filter(([sessionId, entry]) => !isSessionBusy(sessionId) && !entry.compacting && entry.commandAbort === void 0 && entry.work.size === 0).sort((a, b) => a[1].lastUsedAt - b[1].lastUsedAt);
10958
11012
  const overflow = active.size - MAX_IDLE_ACTIVE_AGENTS;
10959
11013
  if (overflow <= 0) return;
10960
11014
  for (const [sessionId, entry] of idle.slice(0, overflow)) {
@@ -11054,6 +11108,7 @@ function createChatHost(env) {
11054
11108
  };
11055
11109
  }
11056
11110
  async function ensureAgent(sessionId) {
11111
+ assertDispatchOpen();
11057
11112
  const existing = active.get(sessionId);
11058
11113
  if (existing) {
11059
11114
  existing.lastUsedAt = Date.now();
@@ -11072,6 +11127,7 @@ function createChatHost(env) {
11072
11127
  return run;
11073
11128
  });
11074
11129
  pendingBuilds.set(sessionId, build);
11130
+ trackWork(build);
11075
11131
  build.catch(() => void 0).finally(() => {
11076
11132
  if (pendingBuilds.get(sessionId) === build) pendingBuilds.delete(sessionId);
11077
11133
  });
@@ -12127,13 +12183,78 @@ function createChatHost(env) {
12127
12183
  return !(internal?.ownMarkerExempt !== false && ownRunEnded !== void 0 && persisted.updatedAt <= ownRunEnded + 2e3);
12128
12184
  }
12129
12185
  async function sendPrompt(opts, internal) {
12186
+ assertDispatchOpen();
12187
+ if (isSessionBusy(opts.sessionId)) throw new Error(`Session "${opts.sessionId}" already has a run in flight. Use steer/followUp (or pushQueued) to feed the active run.`);
12188
+ const generation = teardownGeneration;
12189
+ const finished = Promise.withResolvers();
12190
+ dispatches.set(opts.sessionId, finished.promise);
12191
+ let settlement;
12192
+ let accepted = false;
12193
+ const signals = { runId: randomUUID() };
12194
+ dispatchSignals.set(opts.sessionId, signals);
12195
+ let outcome = { ok: true };
12196
+ const release = () => {
12197
+ if (dispatches.get(opts.sessionId) === finished.promise) dispatches.delete(opts.sessionId);
12198
+ dispatchSignals.delete(opts.sessionId);
12199
+ try {
12200
+ broadcast({
12201
+ kind: "run:end",
12202
+ sessionId: opts.sessionId,
12203
+ runId: signals.runId,
12204
+ ...signals.end ?? outcome,
12205
+ ...!outcome.ok ? outcome : {}
12206
+ });
12207
+ } finally {
12208
+ finished.resolve();
12209
+ }
12210
+ };
12211
+ try {
12212
+ const result = await preparePrompt(opts, internal, (completion) => {
12213
+ settlement = completion;
12214
+ });
12215
+ if (!signals.end) signals.runId = result.runId;
12216
+ accepted = true;
12217
+ return result;
12218
+ } catch (err) {
12219
+ outcome = {
12220
+ ok: false,
12221
+ error: err instanceof Error ? err.message : String(err)
12222
+ };
12223
+ throw err;
12224
+ } finally {
12225
+ const drain = () => {
12226
+ if (!closed && generation === teardownGeneration) drainQueue(opts.sessionId);
12227
+ };
12228
+ if (settlement) settlement.catch((err) => {
12229
+ outcome = {
12230
+ ok: false,
12231
+ error: err instanceof Error ? err.message : String(err)
12232
+ };
12233
+ }).finally(release).then(drain).catch(() => void 0);
12234
+ else {
12235
+ release();
12236
+ if (accepted) setTimeout(drain, 0);
12237
+ }
12238
+ }
12239
+ }
12240
+ async function preparePrompt(opts, internal, trackSettlement) {
12241
+ const generation = teardownGeneration;
12130
12242
  const settings = env.readSettings();
12131
12243
  const run = await ensureAgent(opts.sessionId);
12244
+ assertDispatchOpen(generation);
12132
12245
  if (run.agent.isRunning) throw new Error(`Session "${opts.sessionId}" already has a run in flight. Use steer/followUp (or pushQueued) to feed the active run.`);
12133
- if (await foreignRunActive(opts.sessionId, run, internal)) throw new Error(`Session "${opts.sessionId}" is running in another process (an in-process zidane window?). Wait for that run to finish or interrupt it there.`);
12246
+ if (await foreignRunActive(opts.sessionId, run, internal)) {
12247
+ internal?.onForeignRun?.();
12248
+ throw new Error(`Session "${opts.sessionId}" is running in another process (an in-process zidane window?). Wait for that run to finish or interrupt it there.`);
12249
+ }
12134
12250
  if (!opts.wake) suppressedWake.delete(opts.sessionId);
12251
+ assertDispatchOpen(generation);
12135
12252
  const commandResult = await commands.runSlashCommand(opts);
12136
- if (commandResult.ran) return { runId: commandResult.runId ?? randomUUID() };
12253
+ assertDispatchOpen(generation);
12254
+ if (commandResult.ran) {
12255
+ internal?.onCommand?.();
12256
+ return { runId: commandResult.runId ?? randomUUID() };
12257
+ }
12137
12258
  if (opts.asCommand !== void 0) throw new Error(`unknown command: /${opts.asCommand}. This session's extensions do not provide it (different working directory, or the extension is not installed for it).`);
12138
12259
  if (!opts.wake) broadcast({
12139
12260
  kind: "event",
@@ -12186,12 +12307,6 @@ function createChatHost(env) {
12186
12307
  const enabled = enabledModelOptions(data?.metadata?.modelOptions);
12187
12308
  modelOptions = restoreModelOptions(descriptor, modelId, { [modelId]: enabled });
12188
12309
  } catch {}
12189
- broadcast({
12190
- kind: "run:start",
12191
- sessionId: opts.sessionId,
12192
- runId
12193
- });
12194
- broadcastTodosSnapshot(run);
12195
12310
  const promptValue = opts.attachments && opts.attachments.length > 0 ? [...opts.prompt.length > 0 ? [{
12196
12311
  type: "text",
12197
12312
  text: opts.prompt
@@ -12209,6 +12324,7 @@ function createChatHost(env) {
12209
12324
  })] : opts.prompt;
12210
12325
  const autoCompactDescriptor = BUILTIN_PROVIDERS[run.providerKey] ?? BUILTIN_PROVIDERS.anthropic;
12211
12326
  const sendRuntime = await env.runtimeConfig(run.cwd);
12327
+ assertDispatchOpen(generation);
12212
12328
  const summarizer = resolveCompactionSummarizer(settings.compactionModel, (key) => buildProvider(sendRuntime.providers, key), {
12213
12329
  providerKey: run.providerKey,
12214
12330
  model: modelOverride ?? run.model
@@ -12246,34 +12362,45 @@ function createChatHost(env) {
12246
12362
  ...thinking ? { thinking } : {},
12247
12363
  ...modelOptions ? { modelOptions } : {}
12248
12364
  });
12249
- (env.hostRuntime ? env.hostRuntime.runWith(sessionHostRuntime(run, env, { appendNote: (blocks) => appendNoteTurn(run, blocks) }), runAgent) : runAgent()).then(() => {
12250
- broadcastRunReceipt(run);
12251
- broadcast({
12252
- kind: "run:end",
12253
- sessionId: opts.sessionId,
12254
- runId,
12255
- ok: true
12256
- });
12257
- broadcastTodosSnapshot(run);
12258
- }).catch((err) => {
12259
- broadcastRunReceipt(run);
12365
+ broadcast({
12366
+ kind: "run:start",
12367
+ sessionId: opts.sessionId,
12368
+ runId
12369
+ });
12370
+ broadcastTodosSnapshot(run);
12371
+ const scopedRun = Promise.resolve().then(() => {
12372
+ assertDispatchOpen(generation);
12373
+ return env.hostRuntime ? env.hostRuntime.runWith(sessionHostRuntime(run, env, { appendNote: (blocks) => appendNoteTurn(run, blocks) }), runAgent) : runAgent();
12374
+ });
12375
+ let outcome = { ok: true };
12376
+ trackSettlement(scopedRun.catch((err) => {
12377
+ outcome = {
12378
+ ok: false,
12379
+ error: err instanceof Error ? err.message : String(err)
12380
+ };
12381
+ }).then(async () => {
12382
+ run.lastRunEndedAt = Date.now();
12383
+ const settle = heartbeat.end(run.agent.session?.status);
12384
+ try {
12385
+ try {
12386
+ broadcastRunReceipt(run);
12387
+ } finally {
12388
+ run.chatReferenceTokens.current = [];
12389
+ run.lastUsedAt = Date.now();
12390
+ if (pendingDispose.delete(opts.sessionId)) rebuildAgentOnly(opts.sessionId);
12391
+ pruneIdleAgents();
12392
+ }
12393
+ } finally {
12394
+ await settle;
12395
+ }
12260
12396
  broadcast({
12261
12397
  kind: "run:end",
12262
12398
  sessionId: opts.sessionId,
12263
12399
  runId,
12264
- ok: false,
12265
- error: err.message
12400
+ ...outcome
12266
12401
  });
12267
12402
  broadcastTodosSnapshot(run);
12268
- }).finally(() => {
12269
- run.lastRunEndedAt = Date.now();
12270
- const settle = heartbeat.end(run.agent.session?.status);
12271
- run.chatReferenceTokens.current = [];
12272
- run.lastUsedAt = Date.now();
12273
- if (pendingDispose.delete(opts.sessionId)) rebuildAgentOnly(opts.sessionId);
12274
- pruneIdleAgents();
12275
- settle.then(() => drainQueue(opts.sessionId));
12276
- });
12403
+ }));
12277
12404
  return { runId };
12278
12405
  }
12279
12406
  /**
@@ -12296,7 +12423,7 @@ function createChatHost(env) {
12296
12423
  * via `pendingAgentRebuildRef`).
12297
12424
  */
12298
12425
  function disposeAgentForRebuild(sessionId) {
12299
- if (active.get(sessionId)?.agent.isRunning === true) pendingDispose.add(sessionId);
12426
+ if (isSessionBusy(sessionId)) pendingDispose.add(sessionId);
12300
12427
  else rebuildAgentOnly(sessionId);
12301
12428
  }
12302
12429
  const queues = /* @__PURE__ */ new Map();
@@ -12339,7 +12466,7 @@ function createChatHost(env) {
12339
12466
  */
12340
12467
  function maybeWake(sessionId) {
12341
12468
  const entry = active.get(sessionId);
12342
- if (!entry || entry.agent.isRunning || !entry.agent.hasPendingTaskNotifications) return;
12469
+ if (closed || !entry || isSessionBusy(sessionId) || !entry.agent.hasPendingTaskNotifications) return;
12343
12470
  wakeRun(sessionId).catch(() => void 0);
12344
12471
  }
12345
12472
  /**
@@ -12357,7 +12484,7 @@ function createChatHost(env) {
12357
12484
  * because in both cases the turns it appended are already durable.
12358
12485
  */
12359
12486
  async function wakeRun(sessionId) {
12360
- if (suppressedWake.has(sessionId)) return;
12487
+ if (closed || suppressedWake.has(sessionId)) return;
12361
12488
  if ((queues.get(sessionId)?.length ?? 0) > 0) return;
12362
12489
  await sendPrompt({
12363
12490
  sessionId,
@@ -12366,13 +12493,13 @@ function createChatHost(env) {
12366
12493
  }, { ownMarkerExempt: false });
12367
12494
  }
12368
12495
  function drainQueue(sessionId, attempt = 0) {
12369
- if (draining.has(sessionId)) return;
12496
+ if (closed || draining.has(sessionId)) return;
12370
12497
  const queue = queues.get(sessionId);
12371
12498
  if (!queue || queue.length === 0) {
12372
12499
  maybeWake(sessionId);
12373
12500
  return;
12374
12501
  }
12375
- if (active.get(sessionId)?.agent.isRunning === true) {
12502
+ if (isSessionBusy(sessionId)) {
12376
12503
  if (attempt < 100) setTimeout(drainQueue, 25, sessionId, attempt + 1);
12377
12504
  return;
12378
12505
  }
@@ -12405,7 +12532,7 @@ function createChatHost(env) {
12405
12532
  draining.delete(sessionId);
12406
12533
  });
12407
12534
  }
12408
- return {
12535
+ const host = {
12409
12536
  interactions,
12410
12537
  approvals,
12411
12538
  sendPrompt,
@@ -12418,6 +12545,7 @@ function createChatHost(env) {
12418
12545
  if (entry?.agent.followUp(message)) entry.pendingInjections.push(message);
12419
12546
  },
12420
12547
  async pushQueued(sessionId, message, activatedSkills) {
12548
+ assertDispatchOpen();
12421
12549
  const entry = active.get(sessionId);
12422
12550
  if (entry?.agent.isRunning === true) {
12423
12551
  if (entry.agent.steer(message)) entry.pendingInjections.push(message);
@@ -12434,41 +12562,38 @@ function createChatHost(env) {
12434
12562
  broadcastQueue(sessionId);
12435
12563
  return { delivered: "queued" };
12436
12564
  };
12437
- if (await foreignRunActive(sessionId, await ensureAgent(sessionId))) return parkQueued();
12438
- try {
12439
- if ((await commands.runSlashCommand({
12440
- sessionId,
12441
- prompt: message
12442
- })).ran) return { delivered: "command" };
12443
- } catch (err) {
12444
- if (active.get(sessionId)?.agent.isRunning !== true) throw err;
12445
- return parkQueued();
12446
- }
12565
+ if (isSessionBusy(sessionId)) return parkQueued();
12566
+ let command = false;
12567
+ let foreign = false;
12447
12568
  try {
12448
12569
  await sendPrompt({
12449
12570
  sessionId,
12450
12571
  prompt: message,
12451
12572
  ...activatedSkills ? { activatedSkills } : {}
12573
+ }, {
12574
+ onCommand: () => {
12575
+ command = true;
12576
+ },
12577
+ onForeignRun: () => {
12578
+ foreign = true;
12579
+ }
12452
12580
  });
12453
- return { delivered: "send" };
12581
+ return { delivered: command ? "command" : "send" };
12454
12582
  } catch (err) {
12455
- const live = active.get(sessionId);
12456
- if (live?.agent.isRunning === true) {
12457
- if (live.agent.steer(message)) live.pendingInjections.push(message);
12458
- return { delivered: "steer" };
12459
- }
12583
+ assertDispatchOpen();
12584
+ if (foreign || isSessionBusy(sessionId)) return parkQueued();
12460
12585
  throw err;
12461
12586
  }
12462
12587
  },
12463
12588
  isSessionRunning(sessionId) {
12464
12589
  const entry = active.get(sessionId);
12465
12590
  if (entry) entry.lastUsedAt = Date.now();
12466
- return entry?.agent.isRunning === true;
12591
+ return isSessionBusy(sessionId);
12467
12592
  },
12468
12593
  listLiveSessions() {
12469
- return [...active.entries()].map(([sessionId, entry]) => ({
12594
+ return [.../* @__PURE__ */ new Set([...active.keys(), ...dispatches.keys()])].map((sessionId) => ({
12470
12595
  sessionId,
12471
- running: entry.agent.isRunning
12596
+ running: isSessionBusy(sessionId)
12472
12597
  }));
12473
12598
  },
12474
12599
  getLiveTurns(sessionId) {
@@ -12478,6 +12603,7 @@ function createChatHost(env) {
12478
12603
  return active.get(sessionId)?.agent.session ?? null;
12479
12604
  },
12480
12605
  async queueAdd(sessionId, text, activatedSkills, attachments, asCommand) {
12606
+ assertDispatchOpen();
12481
12607
  const enqueue = () => {
12482
12608
  const queue = queues.get(sessionId) ?? [];
12483
12609
  queue.push({
@@ -12491,7 +12617,7 @@ function createChatHost(env) {
12491
12617
  broadcastQueue(sessionId);
12492
12618
  return { delivered: "queued" };
12493
12619
  };
12494
- if (active.get(sessionId)?.agent.isRunning === true) return enqueue();
12620
+ if (isSessionBusy(sessionId)) return enqueue();
12495
12621
  try {
12496
12622
  await sendPrompt({
12497
12623
  sessionId,
@@ -12502,7 +12628,8 @@ function createChatHost(env) {
12502
12628
  });
12503
12629
  return { delivered: "sent" };
12504
12630
  } catch (err) {
12505
- if (active.get(sessionId)?.agent.isRunning === true) return enqueue();
12631
+ assertDispatchOpen();
12632
+ if (isSessionBusy(sessionId)) return enqueue();
12506
12633
  throw err;
12507
12634
  }
12508
12635
  },
@@ -12532,6 +12659,7 @@ function createChatHost(env) {
12532
12659
  return active.get(sessionId)?.systemMd ?? null;
12533
12660
  },
12534
12661
  async queuePushNow(sessionId, id) {
12662
+ assertDispatchOpen();
12535
12663
  const queue = queues.get(sessionId);
12536
12664
  const entry = queue?.find((item) => item.id === id);
12537
12665
  if (!queue || !entry) return { delivered: "missing" };
@@ -12560,6 +12688,7 @@ function createChatHost(env) {
12560
12688
  return { delivered: "send" };
12561
12689
  },
12562
12690
  hasActiveWork() {
12691
+ if (dispatches.size > 0 || lifecycleWork.size > 0) return true;
12563
12692
  for (const entry of active.values()) if (entry.agent.isRunning || entry.compacting || entry.commandAbort !== void 0 || entry.work.size > 0) return true;
12564
12693
  return false;
12565
12694
  },
@@ -12778,6 +12907,18 @@ function createChatHost(env) {
12778
12907
  * that invalidates the runtime config) so active runs, in-flight
12779
12908
  * compactions, and pending HITL promises all unwind cleanly.
12780
12909
  */
12910
+ drain() {
12911
+ if (!drainPromise) {
12912
+ closed = true;
12913
+ const compactions = [...active.values()].flatMap((entry) => entry.compacting ? [entry.compacting] : []);
12914
+ host.shutdown();
12915
+ drainPromise = (async () => {
12916
+ await Promise.allSettled(compactions);
12917
+ while (dispatches.size > 0 || lifecycleWork.size > 0) await Promise.allSettled([...dispatches.values(), ...lifecycleWork]);
12918
+ })();
12919
+ }
12920
+ return drainPromise;
12921
+ },
12781
12922
  shutdown() {
12782
12923
  suppressedWake.clear();
12783
12924
  pluginCatalogCache.clear();
@@ -12795,6 +12936,7 @@ function createChatHost(env) {
12795
12936
  active.clear();
12796
12937
  }
12797
12938
  };
12939
+ return host;
12798
12940
  }
12799
12941
  //#endregion
12800
12942
  //#region src/chat/interactions.tsx
@@ -16471,4 +16613,4 @@ function createApprovalHub(options) {
16471
16613
  //#endregion
16472
16614
  export { supportsOAuth as $, tryOpenBrowser as $n, INTERACTION_GUIDANCE_NO_PROMPTS as $r, runCompaction as $t, useSafeModeQueue as A, createDiscoverySlot as An, DEFAULT_MAX_TODO_ITEMS as Ar, makeRequestInteraction as At, USAGE_CACHE_TTL_MS as B, scoreArtifacts as Bn, isTodoTool as Br, readFileSafe as Bt, resolveSessionExportTarget as C, sumRunCosts as Ci, GRUVBOX_LIGHT as Cn, DEFAULT_AGENT_ID as Cr, InteractionsProvider as Ct, scopeCwd as D, updateToolEventOutcomes as Di, CATPPUCCIN_MOCHA as Dn, accentColor as Dr, createInteractionTools as Dt, resolveSessionCwd as E, toolResultText as Ei, CATPPUCCIN_MACCHIATO as En, PLAN_AGENT as Er, createAutomaticInteractionResponse as Et, matchesSafelistEntry as F, useConfig as Fn, TODO_WRITE_COUNTS_METADATA_KEY as Fr, STALE_RUN_MARKER_MS as Ft, usageChecksOptedOut as G, mcpsWritePath as Gn, setTodosForRun as Gr, modelChainMetadata as Gt, fetchAllProviderUsage as H, countClaudeSessionFiles as Hn, pruneTodosByRun as Hr, serializePreview as Ht, projectsFilePath as I, resolveConfig as In, applyTodosSnapshot as Ir, createChatHost as It, fetchOAuthRedirect as J, buildMcpServers as Jn, ACTIONS_WITH_CARE_DOCTRINE as Jr, buildPluginContributions as Jt, usageSourceFor as K, removeMcpServer as Kn, todoProgressLabel as Kr, sessionModelFallbacks as Kt, readProjects as L, resolveStoragePaths as Ln, createTodoTools as Lr, toTodosSnapshot as Lt, addToSafelist as M, useDiscovery as Mn, TODOS_METADATA_KEY as Mr, serializeInteractionResponse as Mt, getSafelist as N, useDiscoveryOptional as Nn, TODOWRITE_TOOL as Nr, useInteractionsActions as Nt, SafeModeProvider as O, usageByModel as Oi, parseEditorCommand as On, resolveAgentId as Or, isInteractionTool as Ot, isOnSafelist as P, ConfigProvider as Pn, TODO_STATUS_GLYPHS as Pr, useInteractionsQueue as Pt, runOAuthLogin as Q, parseMcpsFile as Qn, INTERACTION_GUIDANCE as Qr, EditOutcomeLedger as Qt, suggestSafelistEntries as R, ARTIFACTS_COMPLETION_PROVIDER_ID as Rn, getArchivedTodosForRun as Rr, createInteractionHub as Rt, renderSession as S, stripSpawnTokensLine as Si, GRUVBOX_DARK as Sn, BUILTIN_AGENTS as Sr, HOST_INTERACTION_ID_PREFIX as St, folderlessCwd as T, toolCallPreview as Ti, CATPPUCCIN_LATTE as Tn, DEFAULT_PERSIST_EXCLUDE_TOOLS as Tr, buildResumedToolResultsTurn as Tt, fetchProviderUsage as U, hasClaudeCodeSetup as Un, sanitizeTodoItems as Ur, createBuiltinCommands as Ut, clearProviderUsageCache as V, useCompletion as Vn, pickActiveRunId as Vr, resolveCwdPath as Vt, providerUsageSupported as W, importFromClaudeCode as Wn, selectActiveTodos as Wr, createMainSession as Wt, redirectUriFromAuthUrl as X, defaultMcpsConfigPaths as Xn, DOING_TASKS_DOCTRINE as Xr, parsePluginScanPathEnv as Xt, normalizeRedirectPaste as Y, dedupMcpServersByName as Yn, COMMUNICATION_DOCTRINE as Yr, discoverProjectPlugins as Yt, oauthUsesManualCodePaste as Z, discoverProjectMcps as Zn, IDENTITY_PREFIX as Zr, attachMcpWarnLog as Zt, buildSpawnEndEvent as _, loadState as _i, BUILTIN_THEMES as _n, groupArtifacts as _r, useMcpAuthState as _t, renderActiveTodoAnchor as a, buildPlanSystem as ai, shortChord as an, runUpdateCommand as ar, subscribeMcpToolsCache as at, defaultSkillScanPaths as b, saveState as bi, resolveTheme as bn, renderAgentsMdBlock as br, ASK_USER_TOOL as bt, useSelectStyle as c, createChatTurnsReadTool as ci, DEFAULT_SETTINGS as cn, checkTarballAvailable as cr, useMcpToolToggleSet as ct, useTheme as d, createStateStore as di, SETTINGS_INPUTS as dn, detectPackageManager as dr, parentServerName as dt, PLAN_MODE_DOCTRINE as ei, EMPTY_HINTS as en, tryRevealPath as er, clearMcpToolsCache as et, discoverSystemMd as f, deriveSessionTitle as fi, SETTINGS_TOGGLES as fn, parseSemver as fr, createFileMcpCredentialStore as ft, useStreamBuffer as g, listSessionMeta as gi, useSettings as gn, chatAutoCompactBehavior as gr, useMcpAuthDispatch as gt, userSystemMdPath as h, lastContextSizeFromTurns as hi, enforceSettingsInvariants as hn, resolvePlatformPackage as hr, McpAuthProvider as ht, createActiveTodoAnchorHooks as i, buildBuildSystem as ii, buildHints as in, useUpdateCheck as ir, saveMcpToolsCache as it, IMPLICITLY_SAFE_TOOLS as j, DiscoveryProvider as jn, TODOREAD_TOOL as jr, pendingInteractionsFromTurns as jt, useSafeModeActions as k, quoteForShell as kn, singleAgentRegistry as kr, isModelInteraction as kt, useSurfaces as l, DEFAULT_SESSION_TITLE as li, SETTINGS_CATEGORIES as ln, compareSemver as lr, buildVisibleMcpRows as lt, userScopeOverridesLoad as m, getSessionMeta as mi, clampFps as mn, performSelfUpdate as mr, patchMcpCredential as mt, createMemoryApprovalsStore as n, SUBAGENT_GUIDANCE as ni, hintsLength as nn, bootTick as nr, mcpToolsCachePath as nt, ThemeProvider as o, envSection as oi, listProjectFiles as on, findInstalledCompanion as or, buildToolToggle as ot, renderSystemMdSeed as p, eventsFromTurns as pi, SettingsProvider as pn, performInPlaceSelfUpdate as pr, mcpCredentialsPath as pt, formatPathForCwd as q, upsertMcpServer as qn, useActiveTodos as qr, runEndNotice as qt, computeTurnAnchors as r, TOKEN_DISCIPLINE_DOCTRINE as ri, truncateTrailing as rn, buildUpdateHint as rr, refreshMcpToolsCatalog as rt, useColors as s, chatReferenceTokensForPrompt as si, useEnabledToggleSet as sn, checkForUpdate as sr, useMcpToolToggleMap as st, createApprovalHub as t, PLAN_MODE_DOCTRINE_NO_PROMPTS as ti, clipHintsToWidth as tn, bootProfileEnabled as tr, loadMcpToolsCache as tt, useSyntaxStyles as u, compactSummaryEvent as ui, SETTINGS_CHOICES as un, detectLibc as ur, indexOfServerRow as ut, buildSpawnStartEvent as v, marginTopFor as vi, DEFAULT_THEME as vn, summarizeArtifactCounts as vr, getMcpAuthStatus as vt, writeSessionExport as w, titleFromTurns as wi, CATPPUCCIN_FRAPPE as wn, DEFAULT_BUDGET_EXCLUDE_TOOLS as wr, PRESENT_PLAN_TOOL as wt, discoverProjectSkills as x, serverToolResultSummary as xi, VAPORWAVE_THEME as xn, BUILD_AGENT as xr, AUTOMATIC_INTERACTION_INSTRUCTION as xt, buildSkillsConfig as y, noticeTurnContent as yi, resolveChipColor as yn, discoverAgentsMd as yr, reduceMcpAuth as yt, writeProjects as z, createArtifactsCompletionProvider as zn, getTodosForRun as zr, extractEditPayloadForGate as zt };
16473
16615
 
16474
- //# sourceMappingURL=approvals-CzrFKdu-.js.map
16616
+ //# sourceMappingURL=approvals-Deg8JhMI.js.map