@adhdev/daemon-standalone 0.8.25 → 0.8.27

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.js CHANGED
@@ -28512,18 +28512,18 @@ var require_dist2 = __commonJS({
28512
28512
  };
28513
28513
  }
28514
28514
  });
28515
- var import_session_host_core2;
28515
+ var import_session_host_core3;
28516
28516
  var init_spawn_env = __esm2({
28517
28517
  "src/cli-adapters/spawn-env.ts"() {
28518
28518
  "use strict";
28519
- import_session_host_core2 = require_dist();
28519
+ import_session_host_core3 = require_dist();
28520
28520
  }
28521
28521
  });
28522
28522
  function loadNodePty() {
28523
28523
  if (cachedPty !== void 0) return cachedPty;
28524
28524
  try {
28525
28525
  cachedPty = require("node-pty");
28526
- (0, import_session_host_core2.ensureNodePtySpawnHelperPermissions)();
28526
+ (0, import_session_host_core3.ensureNodePtySpawnHelperPermissions)();
28527
28527
  } catch {
28528
28528
  cachedPty = null;
28529
28529
  }
@@ -28830,7 +28830,7 @@ var require_dist2 = __commonJS({
28830
28830
  init_terminal_screen();
28831
28831
  init_pty_transport();
28832
28832
  init_spawn_env();
28833
- buildCliSpawnEnv = import_session_host_core2.sanitizeSpawnEnv;
28833
+ buildCliSpawnEnv = import_session_host_core3.sanitizeSpawnEnv;
28834
28834
  ProviderCliAdapter = class _ProviderCliAdapter {
28835
28835
  constructor(provider, workingDir, extraArgs = [], transportFactory = new NodePtyTransportFactory()) {
28836
28836
  this.extraArgs = extraArgs;
@@ -32969,6 +32969,7 @@ ${data.message || ""}`.trim();
32969
32969
  currentStatus = "idle";
32970
32970
  agentStreams = [];
32971
32971
  messages = [];
32972
+ prevMessageHashes = /* @__PURE__ */ new Map();
32972
32973
  activeModal = null;
32973
32974
  currentModel = "";
32974
32975
  currentMode = "";
@@ -33034,7 +33035,7 @@ ${data.message || ""}`.trim();
33034
33035
  onEvent(event, data) {
33035
33036
  if (event === "stream_update") {
33036
33037
  if (data?.streams) this.agentStreams = data.streams;
33037
- if (data?.messages) this.messages = data.messages;
33038
+ if (data?.messages) this.messages = this.assignReceivedAt(data.messages);
33038
33039
  if (data?.activeModal !== void 0) this.activeModal = data.activeModal;
33039
33040
  if (data?.model) this.currentModel = data.model;
33040
33041
  if (data?.mode) this.currentMode = data.mode;
@@ -33060,6 +33061,7 @@ ${data.message || ""}`.trim();
33060
33061
  dispose() {
33061
33062
  this.agentStreams = [];
33062
33063
  this.messages = [];
33064
+ this.prevMessageHashes.clear();
33063
33065
  this.monitor.reset();
33064
33066
  this.appliedEffectKeys.clear();
33065
33067
  this.runtimeMessages = [];
@@ -33215,6 +33217,23 @@ ${data.message || ""}`.trim();
33215
33217
  this.chatId || this.instanceId
33216
33218
  );
33217
33219
  }
33220
+ /**
33221
+ * Assign stable receivedAt to extension messages.
33222
+ * Same pattern as IdeProviderInstance.readChat() prevByHash —
33223
+ * preserves first-seen timestamp across polling cycles.
33224
+ */
33225
+ assignReceivedAt(messages) {
33226
+ const now = Date.now();
33227
+ const nextHashes = /* @__PURE__ */ new Map();
33228
+ for (const msg of messages) {
33229
+ const hash2 = `${msg.role}:${(msg.content || "").slice(0, 100)}`;
33230
+ const prevTime = this.prevMessageHashes.get(hash2);
33231
+ msg.receivedAt = prevTime || now;
33232
+ nextHashes.set(hash2, msg.receivedAt);
33233
+ }
33234
+ this.prevMessageHashes = nextHashes;
33235
+ return messages;
33236
+ }
33218
33237
  mergeConversationMessages(messages) {
33219
33238
  if (this.runtimeMessages.length === 0) return messages;
33220
33239
  return [...messages, ...this.runtimeMessages.map((entry) => entry.message)].map((message, index) => ({ message, index })).sort((a, b2) => {
@@ -33271,6 +33290,7 @@ ${effect.notification.body || ""}`.trim();
33271
33290
  }
33272
33291
  this.agentStreams = [];
33273
33292
  this.messages = [];
33293
+ this.prevMessageHashes.clear();
33274
33294
  this.activeModal = null;
33275
33295
  this.currentModel = "";
33276
33296
  this.currentMode = "";
@@ -34246,16 +34266,28 @@ ${effect.notification.body || ""}`.trim();
34246
34266
  if (!message || typeof message !== "object") return message;
34247
34267
  return trimStructuredStrings(message, stringLimit);
34248
34268
  }
34269
+ function normalizeMessageTime(message) {
34270
+ if (!message || typeof message !== "object") return message;
34271
+ const msg = message;
34272
+ if (msg.receivedAt == null) {
34273
+ const fallback = msg.timestamp ?? msg.createdAt;
34274
+ if (fallback != null) {
34275
+ const ts22 = typeof fallback === "string" ? Date.parse(fallback) : Number(fallback);
34276
+ if (Number.isFinite(ts22) && ts22 > 0) msg.receivedAt = ts22;
34277
+ }
34278
+ }
34279
+ return msg;
34280
+ }
34249
34281
  function trimMessagesForStatus(messages) {
34250
34282
  if (!Array.isArray(messages) || messages.length === 0) return [];
34251
34283
  const recent = messages.slice(-STATUS_ACTIVE_CHAT_MESSAGE_LIMIT);
34252
34284
  const kept = [];
34253
34285
  let totalBytes = 0;
34254
34286
  for (let i = recent.length - 1; i >= 0; i -= 1) {
34255
- let normalized = trimMessageForStatus(recent[i], STATUS_ACTIVE_CHAT_STRING_LIMIT);
34287
+ let normalized = normalizeMessageTime(trimMessageForStatus(recent[i], STATUS_ACTIVE_CHAT_STRING_LIMIT));
34256
34288
  let size = estimateBytes(normalized);
34257
34289
  if (size > STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT) {
34258
- normalized = trimMessageForStatus(recent[i], STATUS_ACTIVE_CHAT_FALLBACK_STRING_LIMIT);
34290
+ normalized = normalizeMessageTime(trimMessageForStatus(recent[i], STATUS_ACTIVE_CHAT_FALLBACK_STRING_LIMIT));
34259
34291
  size = estimateBytes(normalized);
34260
34292
  }
34261
34293
  if (kept.length > 0 && totalBytes + size > STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT) {
@@ -34870,7 +34902,7 @@ ${effect.notification.body || ""}`.trim();
34870
34902
  if (isExtensionTransport(transport)) {
34871
34903
  _log(`Extension: ${provider?.type || "unknown_extension"}`);
34872
34904
  try {
34873
- const evalResult = await h.evaluateProviderScript("sendMessage", { MESSAGE: text }, 3e4);
34905
+ const evalResult = await h.evaluateProviderScript("sendMessage", { message: text }, 3e4);
34874
34906
  if (evalResult?.result) {
34875
34907
  const parsed = parseMaybeJson(evalResult.result);
34876
34908
  if (didProviderConfirmSend(parsed)) {
@@ -34901,7 +34933,7 @@ ${effect.notification.body || ""}`.trim();
34901
34933
  return { success: false, error: `CDP for ${managerKey || "unknown"} not connected` };
34902
34934
  }
34903
34935
  _log(`Targeting IDE: ${getCurrentManagerKey(h)}`);
34904
- const sendScript = h.getProviderScript("sendMessage", { MESSAGE: text });
34936
+ const sendScript = h.getProviderScript("sendMessage", { message: text });
34905
34937
  if (sendScript) {
34906
34938
  try {
34907
34939
  const result = await targetCdp.evaluate(sendScript, 3e4);
@@ -36295,9 +36327,26 @@ ${effect.notification.body || ""}`.trim();
36295
36327
  if (provider?.scripts) {
36296
36328
  const fn2 = provider.scripts[scriptName];
36297
36329
  if (typeof fn2 === "function") {
36298
- const firstVal = params ? Object.values(params)[0] : void 0;
36299
- const script = firstVal ? fn2(firstVal) : fn2();
36300
- if (script) return script;
36330
+ if (params && Object.keys(params).length > 0) {
36331
+ const firstVal = Object.values(params)[0];
36332
+ if (scriptName === "sendMessage" && typeof firstVal === "string") {
36333
+ const legacyScript = fn2(firstVal);
36334
+ if (legacyScript) return legacyScript;
36335
+ }
36336
+ const script = fn2(params);
36337
+ if (script) {
36338
+ const likelyLegacyObjectLeak = typeof script === "string" && script.includes("[object Object]") && typeof firstVal === "string";
36339
+ if (!likelyLegacyObjectLeak) return script;
36340
+ }
36341
+ if (firstVal !== void 0) {
36342
+ const legacyScript = fn2(firstVal);
36343
+ if (legacyScript) return legacyScript;
36344
+ }
36345
+ if (script) return script;
36346
+ } else {
36347
+ const script = fn2();
36348
+ if (script) return script;
36349
+ }
36301
36350
  }
36302
36351
  }
36303
36352
  return null;
@@ -36754,6 +36803,7 @@ ${effect.notification.body || ""}`.trim();
36754
36803
  this.detectStatusTransition();
36755
36804
  });
36756
36805
  await this.adapter.spawn();
36806
+ this.maybeAppendRuntimeRecoveryMessage(this.adapter.getRuntimeMetadata());
36757
36807
  if (this.providerSessionId) {
36758
36808
  const restoredHistory = readChatHistory(this.type, 0, 200, this.providerSessionId);
36759
36809
  if (restoredHistory.messages.length > 0) {
@@ -36848,6 +36898,7 @@ ${effect.notification.body || ""}`.trim();
36848
36898
  this.promoteProviderSessionId(parsedProviderSessionId);
36849
36899
  }
36850
36900
  const runtime = this.adapter.getRuntimeMetadata();
36901
+ this.maybeAppendRuntimeRecoveryMessage(runtime);
36851
36902
  const parsedMessages = Array.isArray(parsedStatus?.messages) ? parsedStatus.messages : [];
36852
36903
  const controlValues = extractProviderControlValues(this.provider.controls, parsedStatus);
36853
36904
  if (controlValues) {
@@ -37174,6 +37225,28 @@ ${effect.notification.body || ""}`.trim();
37174
37225
  const pad = (value) => String(value).padStart(2, "0");
37175
37226
  return `${date5.getFullYear()}-${pad(date5.getMonth() + 1)}-${pad(date5.getDate())} ${pad(date5.getHours())}:${pad(date5.getMinutes())}:${pad(date5.getSeconds())}`;
37176
37227
  }
37228
+ maybeAppendRuntimeRecoveryMessage(runtime) {
37229
+ if (!runtime?.restoredFromStorage || !runtime.runtimeId) return;
37230
+ const recoveryState = String(runtime.recoveryState || "").trim();
37231
+ if (!recoveryState) return;
37232
+ let content = "";
37233
+ if (recoveryState === "auto_resumed") {
37234
+ content = "Session host restored this CLI after restart and reattached it from a saved snapshot.";
37235
+ } else if (recoveryState === "resume_failed") {
37236
+ const errorSuffix = runtime.recoveryError ? ` Resume failed: ${runtime.recoveryError}` : "";
37237
+ content = `Session host found this CLI after restart, but automatic resume failed.${errorSuffix}`;
37238
+ } else if (recoveryState === "host_restart_interrupted") {
37239
+ content = "Session host found this CLI in interrupted state after restart and is attempting to resume it.";
37240
+ } else if (recoveryState === "orphan_snapshot") {
37241
+ content = "Session host restored the last snapshot for this CLI, but the original runtime was not resumed automatically.";
37242
+ } else {
37243
+ content = `Session host restored this CLI after restart (${recoveryState}).`;
37244
+ }
37245
+ this.appendRuntimeSystemMessage(
37246
+ content,
37247
+ `runtime_recovery:${runtime.runtimeId}:${recoveryState}`
37248
+ );
37249
+ }
37177
37250
  appendRuntimeSystemMessage(content, dedupKey, receivedAt = Date.now()) {
37178
37251
  const normalizedContent = String(content || "").trim();
37179
37252
  if (!normalizedContent) return;
@@ -40440,17 +40513,17 @@ Run 'adhdev doctor' for detailed diagnostics.`
40440
40513
  function getSessionMessageUpdatedAt(session) {
40441
40514
  const lastMessage = session.activeChat?.messages?.at?.(-1);
40442
40515
  if (!lastMessage) return 0;
40443
- return parseMessageTime(lastMessage.timestamp) || parseMessageTime(lastMessage.receivedAt) || parseMessageTime(lastMessage.createdAt) || 0;
40516
+ return parseMessageTime(lastMessage.receivedAt) || 0;
40444
40517
  }
40445
40518
  function getSessionCompletionMarker(session) {
40446
40519
  const lastMessage = session.activeChat?.messages?.at?.(-1);
40447
40520
  if (!lastMessage) return "";
40448
40521
  const role = typeof lastMessage.role === "string" ? lastMessage.role : "";
40449
- if (role === "user" || role === "human") return "";
40522
+ if (role === "user" || role === "human" || role === "system") return "";
40450
40523
  if (typeof lastMessage._turnKey === "string" && lastMessage._turnKey) return `turn:${lastMessage._turnKey}`;
40451
40524
  if (typeof lastMessage.id === "string" && lastMessage.id) return `id:${lastMessage.id}`;
40452
40525
  if (typeof lastMessage.index === "number" && Number.isFinite(lastMessage.index)) return `idx:${lastMessage.index}`;
40453
- const timestamp = parseMessageTime(lastMessage.timestamp) || parseMessageTime(lastMessage.receivedAt) || parseMessageTime(lastMessage.createdAt);
40526
+ const timestamp = parseMessageTime(lastMessage.receivedAt);
40454
40527
  return timestamp > 0 ? `ts:${timestamp}` : "";
40455
40528
  }
40456
40529
  function getSessionLastUsedAt(session) {
@@ -40467,7 +40540,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
40467
40540
  if (status === "generating" || status === "starting") {
40468
40541
  return { unread: false, inboxBucket: "working" };
40469
40542
  }
40470
- const unread = completionMarker ? completionMarker !== seenCompletionMarker : hasContentChange && lastUsedAt > lastSeenAt && lastRole !== "user" && lastRole !== "human";
40543
+ const unread = completionMarker ? completionMarker !== seenCompletionMarker : hasContentChange && lastUsedAt > lastSeenAt && lastRole !== "user" && lastRole !== "human" && lastRole !== "system";
40471
40544
  return { unread, inboxBucket: unread ? "task_complete" : "idle" };
40472
40545
  }
40473
40546
  function buildRecentLaunches(recentActivity) {
@@ -40748,6 +40821,25 @@ Run 'adhdev doctor' for detailed diagnostics.`
40748
40821
  "change_model"
40749
40822
  ];
40750
40823
  var READ_DEBUG_ENABLED2 = process.argv.includes("--dev") || process.env.ADHDEV_READ_DEBUG === "1";
40824
+ function toHostedCliRuntimeDescriptor(record2) {
40825
+ if (!record2 || typeof record2 !== "object") return null;
40826
+ const runtimeId = typeof record2.sessionId === "string" ? record2.sessionId : "";
40827
+ const cliType = typeof record2.providerType === "string" ? record2.providerType : "";
40828
+ const workspace = typeof record2.workspace === "string" ? record2.workspace : "";
40829
+ if (!runtimeId || !cliType || !workspace) return null;
40830
+ return {
40831
+ runtimeId,
40832
+ runtimeKey: typeof record2.runtimeKey === "string" ? record2.runtimeKey : void 0,
40833
+ displayName: typeof record2.displayName === "string" ? record2.displayName : void 0,
40834
+ workspaceLabel: typeof record2.workspaceLabel === "string" ? record2.workspaceLabel : void 0,
40835
+ lifecycle: typeof record2.lifecycle === "string" ? record2.lifecycle : void 0,
40836
+ recoveryState: typeof record2.meta?.runtimeRecoveryState === "string" ? String(record2.meta.runtimeRecoveryState) : null,
40837
+ cliType,
40838
+ workspace,
40839
+ cliArgs: Array.isArray(record2.meta?.cliArgs) ? record2.meta.cliArgs : [],
40840
+ providerSessionId: typeof record2.meta?.providerSessionId === "string" ? String(record2.meta.providerSessionId) : void 0
40841
+ };
40842
+ }
40751
40843
  var DaemonCommandRouter = class {
40752
40844
  deps;
40753
40845
  constructor(deps) {
@@ -40821,6 +40913,90 @@ Run 'adhdev doctor' for detailed diagnostics.`
40821
40913
  return { success: false, error: e.message };
40822
40914
  }
40823
40915
  }
40916
+ case "session_host_get_diagnostics": {
40917
+ if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
40918
+ const diagnostics = await this.deps.sessionHostControl.getDiagnostics({
40919
+ includeSessions: args?.includeSessions !== false,
40920
+ limit: Number(args?.limit) || void 0
40921
+ });
40922
+ return { success: true, diagnostics };
40923
+ }
40924
+ case "session_host_list_sessions": {
40925
+ if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
40926
+ const sessions = await this.deps.sessionHostControl.listSessions();
40927
+ return { success: true, sessions };
40928
+ }
40929
+ case "session_host_stop_session": {
40930
+ if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
40931
+ const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
40932
+ if (!sessionId) return { success: false, error: "sessionId required" };
40933
+ const record2 = await this.deps.sessionHostControl.stopSession(sessionId);
40934
+ return { success: true, record: record2 };
40935
+ }
40936
+ case "session_host_resume_session": {
40937
+ if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
40938
+ const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
40939
+ if (!sessionId) return { success: false, error: "sessionId required" };
40940
+ const record2 = await this.deps.sessionHostControl.resumeSession(sessionId);
40941
+ const hosted = toHostedCliRuntimeDescriptor(record2);
40942
+ if (hosted) {
40943
+ await this.deps.cliManager.restoreHostedSessions([hosted]);
40944
+ }
40945
+ return { success: true, record: record2 };
40946
+ }
40947
+ case "session_host_restart_session": {
40948
+ if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
40949
+ const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
40950
+ if (!sessionId) return { success: false, error: "sessionId required" };
40951
+ const record2 = await this.deps.sessionHostControl.restartSession(sessionId);
40952
+ const hosted = toHostedCliRuntimeDescriptor(record2);
40953
+ if (hosted) {
40954
+ await this.deps.cliManager.restoreHostedSessions([hosted]);
40955
+ }
40956
+ return { success: true, record: record2 };
40957
+ }
40958
+ case "session_host_send_signal": {
40959
+ if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
40960
+ const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
40961
+ const signal = typeof args?.signal === "string" ? args.signal : "";
40962
+ if (!sessionId) return { success: false, error: "sessionId required" };
40963
+ if (!signal) return { success: false, error: "signal required" };
40964
+ const record2 = await this.deps.sessionHostControl.sendSignal(sessionId, signal);
40965
+ return { success: true, record: record2 };
40966
+ }
40967
+ case "session_host_force_detach_client": {
40968
+ if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
40969
+ const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
40970
+ const clientId = typeof args?.clientId === "string" ? args.clientId : "";
40971
+ if (!sessionId) return { success: false, error: "sessionId required" };
40972
+ if (!clientId) return { success: false, error: "clientId required" };
40973
+ const record2 = await this.deps.sessionHostControl.forceDetachClient(sessionId, clientId);
40974
+ return { success: true, record: record2 };
40975
+ }
40976
+ case "session_host_acquire_write": {
40977
+ if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
40978
+ const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
40979
+ const clientId = typeof args?.clientId === "string" ? args.clientId : "";
40980
+ const ownerType = args?.ownerType === "agent" ? "agent" : "user";
40981
+ if (!sessionId) return { success: false, error: "sessionId required" };
40982
+ if (!clientId) return { success: false, error: "clientId required" };
40983
+ const record2 = await this.deps.sessionHostControl.acquireWrite({
40984
+ sessionId,
40985
+ clientId,
40986
+ ownerType,
40987
+ force: args?.force !== false
40988
+ });
40989
+ return { success: true, record: record2 };
40990
+ }
40991
+ case "session_host_release_write": {
40992
+ if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
40993
+ const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
40994
+ const clientId = typeof args?.clientId === "string" ? args.clientId : "";
40995
+ if (!sessionId) return { success: false, error: "sessionId required" };
40996
+ if (!clientId) return { success: false, error: "clientId required" };
40997
+ const record2 = await this.deps.sessionHostControl.releaseWrite({ sessionId, clientId });
40998
+ return { success: true, record: record2 };
40999
+ }
40824
41000
  case "list_saved_sessions": {
40825
41001
  const providerType = typeof args?.providerType === "string" ? args.providerType.trim() : typeof args?.agentType === "string" ? args.agentType.trim() : "";
40826
41002
  const kind = args?.kind === "acp" ? "acp" : "cli";
@@ -41341,6 +41517,14 @@ Run 'adhdev doctor' for detailed diagnostics.`
41341
41517
  hasScript(name) {
41342
41518
  return typeof this.provider.scripts?.[name] === "function";
41343
41519
  }
41520
+ parseMaybeJson(raw) {
41521
+ if (typeof raw !== "string") return raw;
41522
+ try {
41523
+ return JSON.parse(raw);
41524
+ } catch {
41525
+ return raw;
41526
+ }
41527
+ }
41344
41528
  summarizeRaw(raw) {
41345
41529
  try {
41346
41530
  if (typeof raw === "string") return raw.replace(/\s+/g, " ").trim().slice(0, 240);
@@ -41401,12 +41585,30 @@ Run 'adhdev doctor' for detailed diagnostics.`
41401
41585
  }
41402
41586
  }
41403
41587
  async sendMessage(evaluate, text) {
41404
- const script = this.callScript("sendMessage", text);
41588
+ const params = { message: text };
41589
+ const script = this.callScript("sendMessage", params) || this.callScript("sendMessage", text);
41405
41590
  if (!script) throw new Error(`[${this.agentName}] sendMessage script not available`);
41406
41591
  const result = await evaluate(script);
41407
41592
  if (result && typeof result === "string" && result.startsWith("error:")) {
41408
41593
  throw new Error(`[${this.agentName}] sendMessage failed: ${result}`);
41409
41594
  }
41595
+ const parsed = this.parseMaybeJson(result);
41596
+ if (parsed === true) return;
41597
+ if (typeof parsed === "string") {
41598
+ const normalized = parsed.trim().toLowerCase();
41599
+ if (normalized === "ok" || normalized === "sent" || normalized === "success" || normalized === "true") {
41600
+ return;
41601
+ }
41602
+ }
41603
+ if (parsed && typeof parsed === "object") {
41604
+ if (parsed.sent === true || parsed.success === true || parsed.ok === true || parsed.submitted === true || parsed.dispatched === true) {
41605
+ return;
41606
+ }
41607
+ if (typeof parsed.error === "string" && parsed.error.trim()) {
41608
+ throw new Error(`[${this.agentName}] sendMessage failed: ${parsed.error}`);
41609
+ }
41610
+ }
41611
+ throw new Error(`[${this.agentName}] sendMessage was not confirmed`);
41410
41612
  }
41411
41613
  async resolveAction(evaluate, action, button) {
41412
41614
  const script = this.callScript("resolveAction", { action, button });
@@ -47629,6 +47831,7 @@ data: ${JSON.stringify(msg.data)}
47629
47831
  }
47630
47832
  }
47631
47833
  handleEvent(event) {
47834
+ if (!("sessionId" in event)) return;
47632
47835
  if (event.sessionId !== this.options.runtimeId) return;
47633
47836
  if ((event.type === "session_started" || event.type === "session_resumed") && typeof event.pid === "number") {
47634
47837
  this.currentPid = event.pid;
@@ -47704,7 +47907,10 @@ data: ${JSON.stringify(msg.data)}
47704
47907
  clientId: client.clientId,
47705
47908
  type: client.type,
47706
47909
  readOnly: client.readOnly
47707
- }))
47910
+ })),
47911
+ restoredFromStorage: record2.meta?.restoredFromStorage === true,
47912
+ recoveryState: typeof record2.meta?.runtimeRecoveryState === "string" ? String(record2.meta.runtimeRecoveryState) : null,
47913
+ recoveryError: typeof record2.meta?.runtimeRecoveryError === "string" ? String(record2.meta.runtimeRecoveryError) : null
47708
47914
  };
47709
47915
  }
47710
47916
  enqueue(action) {
@@ -47740,11 +47946,11 @@ data: ${JSON.stringify(msg.data)}
47740
47946
  });
47741
47947
  }
47742
47948
  };
47743
- var import_session_host_core3 = require_dist();
47949
+ var import_session_host_core32 = require_dist();
47744
47950
  var STARTUP_TIMEOUT_MS = 8e3;
47745
47951
  var STARTUP_POLL_MS = 200;
47746
47952
  async function canConnect(endpoint) {
47747
- const client = new import_session_host_core3.SessionHostClient({ endpoint });
47953
+ const client = new import_session_host_core32.SessionHostClient({ endpoint });
47748
47954
  try {
47749
47955
  await client.connect();
47750
47956
  await client.close();
@@ -47762,14 +47968,14 @@ data: ${JSON.stringify(msg.data)}
47762
47968
  throw new Error(`Session host did not become ready within ${timeoutMs}ms`);
47763
47969
  }
47764
47970
  async function ensureSessionHostReady2(options) {
47765
- const endpoint = (0, import_session_host_core3.getDefaultSessionHostEndpoint)(options.appName || "adhdev");
47971
+ const endpoint = (0, import_session_host_core32.getDefaultSessionHostEndpoint)(options.appName || "adhdev");
47766
47972
  if (await canConnect(endpoint)) return endpoint;
47767
47973
  options.spawnHost();
47768
47974
  await waitForReady(endpoint, options.timeoutMs);
47769
47975
  return endpoint;
47770
47976
  }
47771
47977
  async function listHostedCliRuntimes2(endpoint) {
47772
- const client = new import_session_host_core3.SessionHostClient({ endpoint });
47978
+ const client = new import_session_host_core32.SessionHostClient({ endpoint });
47773
47979
  try {
47774
47980
  const response = await client.request({
47775
47981
  type: "list_sessions",
@@ -48140,6 +48346,7 @@ data: ${JSON.stringify(msg.data)}
48140
48346
  onIdeConnected: () => poller?.start(),
48141
48347
  onStatusChange: config2.onStatusChange,
48142
48348
  onPostChatCommand: config2.onPostChatCommand,
48349
+ sessionHostControl: config2.sessionHostControl,
48143
48350
  getCdpLogFn: config2.getCdpLogFn || ((ideType) => LOG2.forComponent(`CDP:${ideType}`).asLogFn())
48144
48351
  });
48145
48352
  poller = new AgentStreamPoller({
@@ -48514,6 +48721,58 @@ var SessionHostClient = class {
48514
48721
  }
48515
48722
  };
48516
48723
 
48724
+ // src/session-host-control.ts
48725
+ var StandaloneSessionHostControlPlane = class {
48726
+ constructor(getEndpoint) {
48727
+ this.getEndpoint = getEndpoint;
48728
+ }
48729
+ async getDiagnostics(payload = {}) {
48730
+ return this.request("get_host_diagnostics", payload);
48731
+ }
48732
+ async listSessions() {
48733
+ return this.request("list_sessions", {});
48734
+ }
48735
+ async stopSession(sessionId) {
48736
+ return this.request("stop_session", { sessionId });
48737
+ }
48738
+ async resumeSession(sessionId) {
48739
+ return this.request("resume_session", { sessionId });
48740
+ }
48741
+ async restartSession(sessionId) {
48742
+ return this.request("restart_session", { sessionId });
48743
+ }
48744
+ async sendSignal(sessionId, signal) {
48745
+ return this.request("send_signal", { sessionId, signal });
48746
+ }
48747
+ async forceDetachClient(sessionId, clientId) {
48748
+ return this.request("force_detach_client", { sessionId, clientId });
48749
+ }
48750
+ async acquireWrite(payload) {
48751
+ return this.request("acquire_write", payload);
48752
+ }
48753
+ async releaseWrite(payload) {
48754
+ return this.request("release_write", payload);
48755
+ }
48756
+ async request(type, payload) {
48757
+ const endpoint = await this.getEndpoint();
48758
+ const client = new SessionHostClient({ endpoint });
48759
+ try {
48760
+ await client.connect();
48761
+ const response = await client.request({
48762
+ type,
48763
+ payload
48764
+ });
48765
+ if (!response.success) {
48766
+ throw new Error(response.error || `Session host request failed: ${type}`);
48767
+ }
48768
+ return response.result ?? null;
48769
+ } finally {
48770
+ await client.close().catch(() => {
48771
+ });
48772
+ }
48773
+ }
48774
+ };
48775
+
48517
48776
  // ../terminal-mux-control/dist/chunk-7RNMRPVZ.mjs
48518
48777
  var import_os = __toESM(require("os"), 1);
48519
48778
  var import_path = __toESM(require("path"), 1);
@@ -48773,6 +49032,9 @@ var StandaloneServer = class {
48773
49032
  const host = options.host || "127.0.0.1";
48774
49033
  const sessionHostEndpoint = await ensureSessionHostReady();
48775
49034
  this.sessionHostEndpoint = sessionHostEndpoint;
49035
+ const sessionHostControl = new StandaloneSessionHostControlPlane(
49036
+ async () => this.ensureActiveSessionHostEndpoint()
49037
+ );
48776
49038
  this.authToken = options.token || process.env.ADHDEV_TOKEN || null;
48777
49039
  this.components = await (0, import_daemon_core2.initDaemonComponents)({
48778
49040
  cliManagerDeps: {
@@ -48811,6 +49073,7 @@ var StandaloneServer = class {
48811
49073
  listHostedCliRuntimes: async () => listHostedCliRuntimes(sessionHostEndpoint)
48812
49074
  },
48813
49075
  onStatusChange: () => this.scheduleBroadcastStatus(),
49076
+ sessionHostControl,
48814
49077
  onStreamsUpdated: (ideType, streams) => {
48815
49078
  if (!this.components) return;
48816
49079
  (0, import_daemon_core2.forwardAgentStreamsToIdeInstance)(this.components.instanceManager, ideType, streams);
@@ -49149,6 +49412,7 @@ var StandaloneServer = class {
49149
49412
  `);
49150
49413
  }
49151
49414
  const writeEvent = (event) => {
49415
+ if (!("sessionId" in event)) return;
49152
49416
  if (event.sessionId !== sessionId) return;
49153
49417
  if (!this.isCliSession(sessionId)) return;
49154
49418
  res.write(`event: ${event.type}
@@ -49301,7 +49565,7 @@ var StandaloneServer = class {
49301
49565
  return { success: false, error: "command type required" };
49302
49566
  }
49303
49567
  const result = await this.components.router.execute(type, args, "standalone");
49304
- if (type.startsWith("workspace_")) this.scheduleBroadcastStatus();
49568
+ if (type.startsWith("workspace_") || type.startsWith("session_host_")) this.scheduleBroadcastStatus();
49305
49569
  return result;
49306
49570
  }
49307
49571
  scheduleBroadcastStatus() {