@adhdev/daemon-core 0.9.44 → 0.9.45

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
@@ -980,6 +980,8 @@ function validateReadChatResultPayload(raw, source = "read_chat") {
980
980
  if (raw.summaryMetadata !== void 0) normalized.summaryMetadata = raw.summaryMetadata;
981
981
  if (Array.isArray(raw.effects)) normalized.effects = raw.effects;
982
982
  if (typeof raw.providerSessionId === "string") normalized.providerSessionId = raw.providerSessionId;
983
+ if (raw.transcriptAuthority === "provider" || raw.transcriptAuthority === "daemon") normalized.transcriptAuthority = raw.transcriptAuthority;
984
+ if (raw.coverage === "full" || raw.coverage === "tail" || raw.coverage === "current-turn") normalized.coverage = raw.coverage;
983
985
  return normalized;
984
986
  }
985
987
  var VALID_STATUSES, VALID_ROLES, VALID_BUBBLE_STATES, VALID_TURN_STATUSES;
@@ -2056,7 +2058,8 @@ __export(provider_cli_adapter_exports, {
2056
2058
  ProviderCliAdapter: () => ProviderCliAdapter,
2057
2059
  appendBoundedText: () => appendBoundedText,
2058
2060
  normalizeCliProviderForRuntime: () => normalizeCliProviderForRuntime,
2059
- sanitizeCliStandardMessageContent: () => sanitizeCliStandardMessageContent
2061
+ sanitizeCliStandardMessageContent: () => sanitizeCliStandardMessageContent,
2062
+ trimLastAssistantEchoForCliMessages: () => trimLastAssistantEchoForCliMessages
2060
2063
  });
2061
2064
  import * as os10 from "os";
2062
2065
  function normalizeComparableTranscriptText(value) {
@@ -2153,6 +2156,19 @@ function sanitizeCommittedMessageForDisplay(message) {
2153
2156
  if (content === message.content) return message;
2154
2157
  return { ...message, content };
2155
2158
  }
2159
+ function trimLastAssistantEchoForCliMessages(messages, prompt) {
2160
+ if (!prompt) return;
2161
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
2162
+ const message = messages[index];
2163
+ if (!message || message.role !== "assistant" || typeof message.content !== "string") continue;
2164
+ if ((message.kind || "standard") !== "standard") continue;
2165
+ message.content = trimPromptEchoPrefix(message.content, prompt);
2166
+ if (!message.content.trim()) {
2167
+ messages.splice(index, 1);
2168
+ }
2169
+ return;
2170
+ }
2171
+ }
2156
2172
  var COMMITTED_ACTIVITY_PREFIX_BLOCK_RE, ProviderCliAdapter;
2157
2173
  var init_provider_cli_adapter = __esm({
2158
2174
  "src/cli-adapters/provider-cli-adapter.ts"() {
@@ -2349,7 +2365,14 @@ var init_provider_cli_adapter = __esm({
2349
2365
  }
2350
2366
  return null;
2351
2367
  }
2368
+ providerOwnsTranscript() {
2369
+ return this.provider.transcriptAuthority === "provider";
2370
+ }
2371
+ shouldUseFullProviderTranscriptContext() {
2372
+ return this.providerOwnsTranscript() && this.provider.transcriptContext === "full";
2373
+ }
2352
2374
  selectParseBaseMessages(baseMessages) {
2375
+ if (this.shouldUseFullProviderTranscriptContext()) return baseMessages;
2353
2376
  if (baseMessages.length <= _ProviderCliAdapter.PARSE_MESSAGE_TAIL_LIMIT) return baseMessages;
2354
2377
  return baseMessages.slice(-_ProviderCliAdapter.PARSE_MESSAGE_TAIL_LIMIT);
2355
2378
  }
@@ -2832,9 +2855,7 @@ var init_provider_cli_adapter = __esm({
2832
2855
  );
2833
2856
  }
2834
2857
  trimLastAssistantEcho(messages, prompt) {
2835
- if (!prompt) return;
2836
- const last = [...messages].reverse().find((m) => m.role === "assistant" && typeof m.content === "string");
2837
- if (last) last.content = trimPromptEchoPrefix(last.content, prompt);
2858
+ trimLastAssistantEchoForCliMessages(messages, prompt);
2838
2859
  }
2839
2860
  clearAllTimers() {
2840
2861
  if (this.responseTimeout) {
@@ -3688,7 +3709,8 @@ var init_provider_cli_adapter = __esm({
3688
3709
  title: parsed.title || this.cliName,
3689
3710
  messages: hydratedMessages,
3690
3711
  activeModal: parsed.activeModal ?? this.activeModal,
3691
- providerSessionId: typeof parsed.providerSessionId === "string" ? parsed.providerSessionId : void 0
3712
+ providerSessionId: typeof parsed.providerSessionId === "string" ? parsed.providerSessionId : void 0,
3713
+ ...this.providerOwnsTranscript() ? { transcriptAuthority: "provider", coverage: this.shouldUseFullProviderTranscriptContext() ? "full" : "tail" } : {}
3692
3714
  };
3693
3715
  } else {
3694
3716
  const messages = [...this.committedMessages];
@@ -7872,6 +7894,27 @@ var ChatHistoryWriter = class {
7872
7894
  return name.replace(/[^a-zA-Z0-9_-]/g, "_");
7873
7895
  }
7874
7896
  };
7897
+ function pageHistoryRecords(agentType, records, offset = 0, limit = 30, excludeRecentCount = 0, historyBehavior) {
7898
+ const allMessages = records.map((message) => sanitizeHistoryMessage(agentType, message)).filter(Boolean);
7899
+ allMessages.sort((a, b) => a.receivedAt - b.receivedAt);
7900
+ const chronological = [];
7901
+ let lastTurn = null;
7902
+ for (const message of allMessages) {
7903
+ const previous = chronological[chronological.length - 1];
7904
+ if (isAdjacentHistoryDuplicate(agentType, previous, message)) continue;
7905
+ if (message.role !== "system" && isAdjacentHistoryDuplicate(agentType, lastTurn, message)) continue;
7906
+ chronological.push(message);
7907
+ if (message.role !== "system") lastTurn = message;
7908
+ }
7909
+ const collapsed = collapseReplayAssistantTurns(chronological, historyBehavior);
7910
+ const boundedLimit = Math.max(1, limit);
7911
+ const boundedOffset = Math.max(0, offset);
7912
+ const boundedExclude = Math.max(0, Math.min(excludeRecentCount, collapsed.length));
7913
+ const endExclusive = Math.max(0, collapsed.length - boundedExclude - boundedOffset);
7914
+ const startInclusive = Math.max(0, endExclusive - boundedLimit);
7915
+ const sliced = collapsed.slice(startInclusive, endExclusive);
7916
+ return { messages: sliced, hasMore: startInclusive > 0 };
7917
+ }
7875
7918
  function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0, historyBehavior) {
7876
7919
  try {
7877
7920
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
@@ -7897,25 +7940,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, ex
7897
7940
  }
7898
7941
  }
7899
7942
  }
7900
- allMessages.sort((a, b) => a.receivedAt - b.receivedAt);
7901
- const chronological = [];
7902
- let lastTurn = null;
7903
- for (const message of allMessages) {
7904
- const previous = chronological[chronological.length - 1];
7905
- if (isAdjacentHistoryDuplicate(agentType, previous, message)) continue;
7906
- if (message.role !== "system" && isAdjacentHistoryDuplicate(agentType, lastTurn, message)) continue;
7907
- chronological.push(message);
7908
- if (message.role !== "system") lastTurn = message;
7909
- }
7910
- const collapsed = collapseReplayAssistantTurns(chronological, historyBehavior);
7911
- const boundedLimit = Math.max(1, limit);
7912
- const boundedOffset = Math.max(0, offset);
7913
- const boundedExclude = Math.max(0, Math.min(excludeRecentCount, collapsed.length));
7914
- const endExclusive = Math.max(0, collapsed.length - boundedExclude - boundedOffset);
7915
- const startInclusive = Math.max(0, endExclusive - boundedLimit);
7916
- const sliced = collapsed.slice(startInclusive, endExclusive);
7917
- const hasMore = startInclusive > 0;
7918
- return { messages: sliced, hasMore };
7943
+ return pageHistoryRecords(agentType, allMessages, offset, limit, excludeRecentCount, historyBehavior);
7919
7944
  } catch {
7920
7945
  return { messages: [], hasMore: false };
7921
7946
  }
@@ -8050,6 +8075,52 @@ function rewriteCanonicalSavedHistory(agentType, historySessionId, records) {
8050
8075
  return false;
8051
8076
  }
8052
8077
  }
8078
+ function buildHermesNativeHistoryRecords(historySessionId) {
8079
+ const normalizedSessionId = normalizeSavedHistorySessionId(historySessionId);
8080
+ if (!normalizedSessionId) return null;
8081
+ try {
8082
+ const sessionFilePath = path7.join(os5.homedir(), ".hermes", "sessions", `session_${normalizedSessionId}.json`);
8083
+ if (!fs3.existsSync(sessionFilePath)) return null;
8084
+ const raw = JSON.parse(fs3.readFileSync(sessionFilePath, "utf-8"));
8085
+ const canonicalMessages = Array.isArray(raw.messages) ? raw.messages : [];
8086
+ const records = [];
8087
+ let fallbackTs = Date.parse(raw.session_start || raw.last_updated || "") || Date.now();
8088
+ for (const message of canonicalMessages) {
8089
+ const role = String(message.role || "").trim();
8090
+ const content = normalizeCanonicalHermesMessageContent(message.content);
8091
+ if (!content) continue;
8092
+ const receivedAt = extractCanonicalHermesMessageTimestamp(message, fallbackTs);
8093
+ fallbackTs = receivedAt + 1;
8094
+ if (role === "user" || role === "assistant") {
8095
+ records.push({
8096
+ ts: new Date(receivedAt).toISOString(),
8097
+ receivedAt,
8098
+ role,
8099
+ content,
8100
+ kind: "standard",
8101
+ agent: "hermes-cli",
8102
+ historySessionId: normalizedSessionId
8103
+ });
8104
+ continue;
8105
+ }
8106
+ if (role === "tool") {
8107
+ records.push({
8108
+ ts: new Date(receivedAt).toISOString(),
8109
+ receivedAt,
8110
+ role: "assistant",
8111
+ content,
8112
+ kind: "tool",
8113
+ senderName: "Tool",
8114
+ agent: "hermes-cli",
8115
+ historySessionId: normalizedSessionId
8116
+ });
8117
+ }
8118
+ }
8119
+ return records;
8120
+ } catch {
8121
+ return null;
8122
+ }
8123
+ }
8053
8124
  function rebuildHermesSavedHistoryFromCanonicalSession(historySessionId) {
8054
8125
  const normalizedSessionId = normalizeSavedHistorySessionId(historySessionId);
8055
8126
  if (!normalizedSessionId) return false;
@@ -8199,6 +8270,77 @@ function extractClaudeUserContentParts(content) {
8199
8270
  }
8200
8271
  return parts;
8201
8272
  }
8273
+ function buildClaudeNativeHistoryRecords(historySessionId, workspace) {
8274
+ const normalizedSessionId = normalizeSavedHistorySessionId(historySessionId);
8275
+ if (!normalizedSessionId) return null;
8276
+ try {
8277
+ const transcriptPath = resolveClaudeProjectTranscriptPath(normalizedSessionId, workspace);
8278
+ if (!transcriptPath) return null;
8279
+ const lines = fs3.readFileSync(transcriptPath, "utf-8").split("\n").filter(Boolean);
8280
+ const records = [];
8281
+ let fallbackTs = Date.now();
8282
+ for (const line of lines) {
8283
+ let parsed = null;
8284
+ try {
8285
+ parsed = JSON.parse(line);
8286
+ } catch {
8287
+ parsed = null;
8288
+ }
8289
+ if (!parsed) continue;
8290
+ const parsedSessionId = String(parsed.sessionId || "").trim();
8291
+ if (parsedSessionId && parsedSessionId !== normalizedSessionId) continue;
8292
+ const receivedAt = extractTimestampValue(parsed.timestamp) || fallbackTs;
8293
+ fallbackTs = receivedAt + 1;
8294
+ const parsedWorkspace = String(parsed.cwd || workspace || "").trim();
8295
+ if (records.length === 0 && parsedWorkspace) {
8296
+ records.push({
8297
+ ts: new Date(receivedAt).toISOString(),
8298
+ receivedAt,
8299
+ role: "system",
8300
+ kind: "session_start",
8301
+ content: parsedWorkspace,
8302
+ agent: "claude-cli",
8303
+ historySessionId: normalizedSessionId,
8304
+ workspace: parsedWorkspace
8305
+ });
8306
+ }
8307
+ const type = String(parsed.type || "").trim();
8308
+ const message = parsed.message && typeof parsed.message === "object" ? parsed.message : null;
8309
+ if (type === "user" && message) {
8310
+ for (const part of extractClaudeUserContentParts(message.content)) {
8311
+ records.push({
8312
+ ts: new Date(receivedAt).toISOString(),
8313
+ receivedAt,
8314
+ role: part.role,
8315
+ content: part.content,
8316
+ kind: part.kind,
8317
+ senderName: part.senderName,
8318
+ agent: "claude-cli",
8319
+ historySessionId: normalizedSessionId
8320
+ });
8321
+ }
8322
+ continue;
8323
+ }
8324
+ if (type === "assistant" && message) {
8325
+ for (const part of extractClaudeAssistantContentParts(message.content)) {
8326
+ records.push({
8327
+ ts: new Date(receivedAt).toISOString(),
8328
+ receivedAt,
8329
+ role: "assistant",
8330
+ content: part.content,
8331
+ kind: part.kind,
8332
+ senderName: part.senderName,
8333
+ agent: "claude-cli",
8334
+ historySessionId: normalizedSessionId
8335
+ });
8336
+ }
8337
+ }
8338
+ }
8339
+ return records;
8340
+ } catch {
8341
+ return null;
8342
+ }
8343
+ }
8202
8344
  function rebuildClaudeSavedHistoryFromNativeProject(historySessionId, workspace) {
8203
8345
  const normalizedSessionId = normalizeSavedHistorySessionId(historySessionId);
8204
8346
  if (!normalizedSessionId) return false;
@@ -8277,6 +8419,352 @@ function rebuildClaudeSavedHistoryFromNativeProject(historySessionId, workspace)
8277
8419
  return false;
8278
8420
  }
8279
8421
  }
8422
+ function isUuidLikeSessionId(sessionId) {
8423
+ return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(sessionId);
8424
+ }
8425
+ function readCodexSessionMeta(filePath) {
8426
+ try {
8427
+ const firstLine = fs3.readFileSync(filePath, "utf-8").split("\n").find(Boolean);
8428
+ if (!firstLine) return null;
8429
+ const parsed = JSON.parse(firstLine);
8430
+ if (String(parsed.type || "") !== "session_meta") return null;
8431
+ const payload = parsed.payload && typeof parsed.payload === "object" ? parsed.payload : null;
8432
+ return payload;
8433
+ } catch {
8434
+ return null;
8435
+ }
8436
+ }
8437
+ function resolveCodexSessionTranscriptPath(historySessionId, workspace) {
8438
+ const normalizedSessionId = normalizeSavedHistorySessionId(historySessionId);
8439
+ if (!normalizedSessionId || !isUuidLikeSessionId(normalizedSessionId)) return null;
8440
+ const sessionsDir = path7.join(os5.homedir(), ".codex", "sessions");
8441
+ if (!fs3.existsSync(sessionsDir)) return null;
8442
+ const normalizedWorkspace = typeof workspace === "string" ? workspace.trim() : "";
8443
+ const candidates = [];
8444
+ const stack = [sessionsDir];
8445
+ while (stack.length > 0) {
8446
+ const current = stack.pop();
8447
+ if (!current) continue;
8448
+ let entries = [];
8449
+ try {
8450
+ entries = fs3.readdirSync(current, { withFileTypes: true });
8451
+ } catch {
8452
+ continue;
8453
+ }
8454
+ for (const entry of entries) {
8455
+ const entryPath = path7.join(current, entry.name);
8456
+ if (entry.isDirectory()) {
8457
+ stack.push(entryPath);
8458
+ continue;
8459
+ }
8460
+ if (!entry.isFile() || !entry.name.endsWith(".jsonl") || !entry.name.includes(normalizedSessionId)) continue;
8461
+ const meta = readCodexSessionMeta(entryPath);
8462
+ const metaSessionId = String(meta?.id || "").trim();
8463
+ if (metaSessionId && metaSessionId !== normalizedSessionId) continue;
8464
+ const metaWorkspace = String(meta?.cwd || "").trim();
8465
+ let mtimeMs = 0;
8466
+ try {
8467
+ mtimeMs = fs3.statSync(entryPath).mtimeMs;
8468
+ } catch {
8469
+ }
8470
+ candidates.push({
8471
+ path: entryPath,
8472
+ mtimeMs,
8473
+ workspaceMatches: !!normalizedWorkspace && metaWorkspace === normalizedWorkspace,
8474
+ metaMatches: metaSessionId === normalizedSessionId
8475
+ });
8476
+ }
8477
+ }
8478
+ candidates.sort((a, b) => Number(b.workspaceMatches) - Number(a.workspaceMatches) || Number(b.metaMatches) - Number(a.metaMatches) || b.mtimeMs - a.mtimeMs);
8479
+ return candidates[0]?.path || null;
8480
+ }
8481
+ function flattenCodexContent(content) {
8482
+ if (typeof content === "string") return content.trim();
8483
+ if (content == null) return "";
8484
+ if (Array.isArray(content)) {
8485
+ return content.map((entry) => flattenCodexContent(entry)).filter(Boolean).join("\n").trim();
8486
+ }
8487
+ if (typeof content === "object") {
8488
+ const record = content;
8489
+ if (typeof record.text === "string") return record.text.trim();
8490
+ if (typeof record.content === "string" || Array.isArray(record.content)) return flattenCodexContent(record.content);
8491
+ if (typeof record.output === "string") return record.output.trim();
8492
+ if (typeof record.message === "string") return record.message.trim();
8493
+ }
8494
+ return "";
8495
+ }
8496
+ function summarizeCodexToolCall(payload) {
8497
+ const name = String(payload.name || payload.type || "tool").trim() || "tool";
8498
+ const rawArguments = payload.arguments ?? payload.input;
8499
+ let argumentValue = "";
8500
+ if (typeof rawArguments === "string") {
8501
+ const trimmed = rawArguments.trim();
8502
+ try {
8503
+ const parsed = JSON.parse(trimmed);
8504
+ argumentValue = summarizeCodexToolArguments(parsed);
8505
+ } catch {
8506
+ argumentValue = trimmed;
8507
+ }
8508
+ } else {
8509
+ argumentValue = summarizeCodexToolArguments(rawArguments);
8510
+ }
8511
+ return argumentValue ? `${name}: ${argumentValue}` : name;
8512
+ }
8513
+ function summarizeCodexToolArguments(value) {
8514
+ if (typeof value === "string") return value.trim();
8515
+ if (Array.isArray(value)) return value.map((entry) => String(entry)).join(" ").trim();
8516
+ if (!value || typeof value !== "object") return "";
8517
+ const record = value;
8518
+ const direct = record.command || record.cmd || record.query || record.path || record.prompt;
8519
+ if (typeof direct === "string") return direct.trim();
8520
+ if (Array.isArray(direct)) return direct.map((entry) => String(entry)).join(" ").trim();
8521
+ try {
8522
+ return JSON.stringify(record).trim();
8523
+ } catch {
8524
+ return "";
8525
+ }
8526
+ }
8527
+ function codexToolOutputContent(payload) {
8528
+ const output = payload.output ?? payload.result ?? payload.content;
8529
+ const text = flattenCodexContent(output);
8530
+ if (text) return text;
8531
+ if (output && typeof output === "object") {
8532
+ try {
8533
+ return JSON.stringify(output).trim();
8534
+ } catch {
8535
+ return "";
8536
+ }
8537
+ }
8538
+ return "";
8539
+ }
8540
+ function buildCodexNativeHistoryRecords(historySessionId, workspace) {
8541
+ const normalizedSessionId = normalizeSavedHistorySessionId(historySessionId);
8542
+ if (!normalizedSessionId || !isUuidLikeSessionId(normalizedSessionId)) return null;
8543
+ try {
8544
+ const transcriptPath = resolveCodexSessionTranscriptPath(normalizedSessionId, workspace);
8545
+ if (!transcriptPath) return null;
8546
+ const lines = fs3.readFileSync(transcriptPath, "utf-8").split("\n").filter(Boolean);
8547
+ const records = [];
8548
+ let fallbackTs = Date.now();
8549
+ for (const line of lines) {
8550
+ let parsed = null;
8551
+ try {
8552
+ parsed = JSON.parse(line);
8553
+ } catch {
8554
+ parsed = null;
8555
+ }
8556
+ if (!parsed) continue;
8557
+ const receivedAt = extractTimestampValue(parsed.timestamp) || fallbackTs;
8558
+ fallbackTs = receivedAt + 1;
8559
+ const type = String(parsed.type || "").trim();
8560
+ const payload = parsed.payload && typeof parsed.payload === "object" ? parsed.payload : null;
8561
+ if (!payload) continue;
8562
+ if (type === "session_meta") {
8563
+ const parsedSessionId = String(payload.id || "").trim();
8564
+ if (parsedSessionId && parsedSessionId !== normalizedSessionId) return null;
8565
+ const parsedWorkspace = String(payload.cwd || workspace || "").trim();
8566
+ if (records.length === 0 && parsedWorkspace) {
8567
+ records.push({
8568
+ ts: new Date(receivedAt).toISOString(),
8569
+ receivedAt,
8570
+ role: "system",
8571
+ kind: "session_start",
8572
+ content: parsedWorkspace,
8573
+ agent: "codex-cli",
8574
+ historySessionId: normalizedSessionId,
8575
+ workspace: parsedWorkspace
8576
+ });
8577
+ }
8578
+ continue;
8579
+ }
8580
+ if (type !== "response_item") continue;
8581
+ const payloadType = String(payload.type || "").trim();
8582
+ if (payloadType === "message") {
8583
+ const role = String(payload.role || "").trim();
8584
+ if (role !== "user" && role !== "assistant") continue;
8585
+ const content = flattenCodexContent(payload.content);
8586
+ if (!content) continue;
8587
+ records.push({
8588
+ ts: new Date(receivedAt).toISOString(),
8589
+ receivedAt,
8590
+ role,
8591
+ content,
8592
+ kind: "standard",
8593
+ agent: "codex-cli",
8594
+ historySessionId: normalizedSessionId
8595
+ });
8596
+ continue;
8597
+ }
8598
+ if (payloadType === "function_call" || payloadType === "custom_tool_call") {
8599
+ const content = summarizeCodexToolCall(payload);
8600
+ if (!content) continue;
8601
+ records.push({
8602
+ ts: new Date(receivedAt).toISOString(),
8603
+ receivedAt,
8604
+ role: "assistant",
8605
+ content,
8606
+ kind: "tool",
8607
+ senderName: "Tool",
8608
+ agent: "codex-cli",
8609
+ historySessionId: normalizedSessionId
8610
+ });
8611
+ continue;
8612
+ }
8613
+ if (payloadType === "function_call_output" || payloadType === "custom_tool_call_output") {
8614
+ const content = codexToolOutputContent(payload);
8615
+ if (!content) continue;
8616
+ records.push({
8617
+ ts: new Date(receivedAt).toISOString(),
8618
+ receivedAt,
8619
+ role: "assistant",
8620
+ content,
8621
+ kind: "tool",
8622
+ senderName: "Tool",
8623
+ agent: "codex-cli",
8624
+ historySessionId: normalizedSessionId
8625
+ });
8626
+ }
8627
+ }
8628
+ return records;
8629
+ } catch {
8630
+ return null;
8631
+ }
8632
+ }
8633
+ function rebuildCodexSavedHistoryFromNativeSession(historySessionId, workspace) {
8634
+ const normalizedSessionId = normalizeSavedHistorySessionId(historySessionId);
8635
+ if (!normalizedSessionId || !isUuidLikeSessionId(normalizedSessionId)) return false;
8636
+ const records = buildCodexNativeHistoryRecords(normalizedSessionId, workspace);
8637
+ if (!records || records.length === 0) return false;
8638
+ const existingSessionStart = readExistingSessionStartRecord("codex-cli", normalizedSessionId);
8639
+ const recordsToWrite = existingSessionStart && records[0]?.kind !== "session_start" ? [{ ...existingSessionStart, historySessionId: normalizedSessionId }, ...records] : records;
8640
+ return rewriteCanonicalSavedHistory("codex-cli", normalizedSessionId, recordsToWrite);
8641
+ }
8642
+ function isNativeSourceCanonicalHistory(canonicalHistory) {
8643
+ if (!canonicalHistory) return false;
8644
+ if (canonicalHistory.mode === "disabled") return false;
8645
+ if (canonicalHistory.mode === "materialized-mirror") return false;
8646
+ return true;
8647
+ }
8648
+ function buildNativeHistoryRecords(canonicalHistory, historySessionId, workspace) {
8649
+ const normalizedSessionId = normalizeSavedHistorySessionId(historySessionId || "");
8650
+ if (!canonicalHistory || !normalizedSessionId || !isNativeSourceCanonicalHistory(canonicalHistory)) return null;
8651
+ if (canonicalHistory.format === "hermes-json") return buildHermesNativeHistoryRecords(normalizedSessionId);
8652
+ if (canonicalHistory.format === "claude-jsonl") return buildClaudeNativeHistoryRecords(normalizedSessionId, workspace);
8653
+ if (canonicalHistory.format === "codex-jsonl") return buildCodexNativeHistoryRecords(normalizedSessionId, workspace);
8654
+ return null;
8655
+ }
8656
+ function readProviderChatHistory(agentType, options = {}) {
8657
+ if (isNativeSourceCanonicalHistory(options.canonicalHistory) && options.historySessionId) {
8658
+ const records = buildNativeHistoryRecords(options.canonicalHistory, options.historySessionId, options.workspace);
8659
+ if (!records) return { messages: [], hasMore: false, source: "native-unavailable" };
8660
+ return {
8661
+ ...pageHistoryRecords(agentType, records, options.offset || 0, options.limit || 30, options.excludeRecentCount || 0, options.historyBehavior),
8662
+ source: "provider-native"
8663
+ };
8664
+ }
8665
+ return {
8666
+ ...readChatHistory(agentType, options.offset || 0, options.limit || 30, options.historySessionId, options.excludeRecentCount || 0, options.historyBehavior),
8667
+ source: "adhdev-mirror"
8668
+ };
8669
+ }
8670
+ function buildNativeSessionSummary(agentType, historySessionId, records, sourcePath) {
8671
+ const visible = pageHistoryRecords(agentType, records, 0, Number.MAX_SAFE_INTEGER).messages;
8672
+ if (visible.length === 0) return null;
8673
+ let sourceMtimeMs = 0;
8674
+ try {
8675
+ sourceMtimeMs = fs3.statSync(sourcePath).mtimeMs;
8676
+ } catch {
8677
+ }
8678
+ const firstMessageAt = visible[0]?.receivedAt || sourceMtimeMs || Date.now();
8679
+ const lastMessageAt = visible[visible.length - 1]?.receivedAt || firstMessageAt;
8680
+ const lastNonSystem = [...visible].reverse().find((message) => message.role !== "system") || visible[visible.length - 1];
8681
+ const firstSystem = visible.find((message) => message.kind === "session_start");
8682
+ return {
8683
+ historySessionId,
8684
+ sessionTitle: lastNonSystem?.content,
8685
+ messageCount: visible.length,
8686
+ firstMessageAt,
8687
+ lastMessageAt,
8688
+ preview: lastNonSystem?.content,
8689
+ workspace: firstSystem?.workspace || (firstSystem?.kind === "session_start" ? firstSystem.content : void 0),
8690
+ source: "provider-native",
8691
+ sourcePath,
8692
+ sourceMtimeMs
8693
+ };
8694
+ }
8695
+ function listFilesRecursive(root, predicate) {
8696
+ if (!fs3.existsSync(root)) return [];
8697
+ const results = [];
8698
+ const stack = [root];
8699
+ while (stack.length > 0) {
8700
+ const current = stack.pop();
8701
+ if (!current) continue;
8702
+ let entries = [];
8703
+ try {
8704
+ entries = fs3.readdirSync(current, { withFileTypes: true });
8705
+ } catch {
8706
+ continue;
8707
+ }
8708
+ for (const entry of entries) {
8709
+ const entryPath = path7.join(current, entry.name);
8710
+ if (entry.isDirectory()) {
8711
+ stack.push(entryPath);
8712
+ continue;
8713
+ }
8714
+ if (predicate(entryPath, entry)) results.push(entryPath);
8715
+ }
8716
+ }
8717
+ return results;
8718
+ }
8719
+ function collectNativeHistorySessionSummaries(agentType, canonicalHistory) {
8720
+ const summaries = [];
8721
+ if (canonicalHistory.format === "hermes-json") {
8722
+ const root = path7.join(os5.homedir(), ".hermes", "sessions");
8723
+ for (const filePath of listFilesRecursive(root, (_entryPath, entry) => entry.isFile() && /^session_.+\.json$/.test(entry.name))) {
8724
+ const fileName = path7.basename(filePath);
8725
+ const historySessionId = fileName.replace(/^session_/, "").replace(/\.json$/, "");
8726
+ const records = buildHermesNativeHistoryRecords(historySessionId);
8727
+ const summary = records ? buildNativeSessionSummary(agentType, historySessionId, records, filePath) : null;
8728
+ if (summary) summaries.push(summary);
8729
+ }
8730
+ } else if (canonicalHistory.format === "claude-jsonl") {
8731
+ const root = path7.join(os5.homedir(), ".claude", "projects");
8732
+ for (const filePath of listFilesRecursive(root, (_entryPath, entry) => entry.isFile() && entry.name.endsWith(".jsonl"))) {
8733
+ const historySessionId = path7.basename(filePath, ".jsonl");
8734
+ const records = buildClaudeNativeHistoryRecords(historySessionId);
8735
+ const summary = records ? buildNativeSessionSummary(agentType, historySessionId, records, filePath) : null;
8736
+ if (summary) summaries.push(summary);
8737
+ }
8738
+ } else if (canonicalHistory.format === "codex-jsonl") {
8739
+ const root = path7.join(os5.homedir(), ".codex", "sessions");
8740
+ const uuidPattern = /([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/i;
8741
+ for (const filePath of listFilesRecursive(root, (_entryPath, entry) => entry.isFile() && entry.name.endsWith(".jsonl"))) {
8742
+ const meta = readCodexSessionMeta(filePath);
8743
+ const historySessionId = String(meta?.id || path7.basename(filePath).match(uuidPattern)?.[1] || "").trim();
8744
+ if (!historySessionId) continue;
8745
+ const records = buildCodexNativeHistoryRecords(historySessionId, String(meta?.cwd || "").trim() || void 0);
8746
+ const summary = records ? buildNativeSessionSummary(agentType, historySessionId, records, filePath) : null;
8747
+ if (summary) summaries.push(summary);
8748
+ }
8749
+ }
8750
+ return sortSavedHistorySessionSummaries(summaries);
8751
+ }
8752
+ function listProviderHistorySessions(agentType, options = {}) {
8753
+ if (isNativeSourceCanonicalHistory(options.canonicalHistory)) {
8754
+ const offset = Math.max(0, options.offset || 0);
8755
+ const limit = Math.max(1, options.limit || 30);
8756
+ const summaries = collectNativeHistorySessionSummaries(agentType, options.canonicalHistory);
8757
+ return {
8758
+ sessions: summaries.slice(offset, offset + limit),
8759
+ hasMore: offset + limit < summaries.length,
8760
+ source: "provider-native"
8761
+ };
8762
+ }
8763
+ return {
8764
+ ...listSavedHistorySessions(agentType, { offset: options.offset, limit: options.limit }, options.historyBehavior),
8765
+ source: "adhdev-mirror"
8766
+ };
8767
+ }
8280
8768
 
8281
8769
  // src/providers/provider-patch-state.ts
8282
8770
  function isControlValue(value) {
@@ -10890,7 +11378,16 @@ async function handleChatHistory(h, args) {
10890
11378
  const visibleCount = Array.isArray(status?.messages) ? status.messages.length : 0;
10891
11379
  if (visibleCount > excludeRecentCount) excludeRecentCount = visibleCount;
10892
11380
  }
10893
- const result = readChatHistory(agentStr, offset || 0, limit || 30, historySessionId, excludeRecentCount);
11381
+ const workspace = typeof args?.workspace === "string" ? args.workspace : typeof h.currentSession?.workspace === "string" ? h.currentSession.workspace : void 0;
11382
+ const result = readProviderChatHistory(agentStr, {
11383
+ canonicalHistory: provider?.canonicalHistory,
11384
+ historySessionId,
11385
+ workspace,
11386
+ offset: offset || 0,
11387
+ limit: limit || 30,
11388
+ excludeRecentCount,
11389
+ historyBehavior: provider?.historyBehavior
11390
+ });
10894
11391
  return { success: true, ...result, agent: agentStr };
10895
11392
  } catch (e) {
10896
11393
  return { success: false, error: e.message };
@@ -10915,7 +11412,8 @@ async function handleReadChat(h, args) {
10915
11412
  }
10916
11413
  const parsedRecord = parsedStatus && typeof parsedStatus === "object" ? parsedStatus : null;
10917
11414
  const adapterStatus = adapter.getStatus();
10918
- const shouldPreferAdapterMessages = Array.isArray(adapterStatus.messages) && adapterStatus.messages.length > 0 && Array.isArray(parsedRecord?.messages) && adapterStatus.messages.length > parsedRecord.messages.length;
11415
+ const parsedIsProviderAuthoritative = parsedRecord?.transcriptAuthority === "provider" || parsedRecord?.coverage === "full";
11416
+ const shouldPreferAdapterMessages = !parsedIsProviderAuthoritative && Array.isArray(adapterStatus.messages) && adapterStatus.messages.length > 0 && Array.isArray(parsedRecord?.messages) && adapterStatus.messages.length > parsedRecord.messages.length;
10919
11417
  const parsedShowsApproval = hasNonEmptyModalButtons(parsedRecord?.activeModal) && parsedRecord?.status === "waiting_approval";
10920
11418
  const status = parsedRecord ? {
10921
11419
  ...parsedRecord,
@@ -10925,6 +11423,8 @@ async function handleReadChat(h, args) {
10925
11423
  } : adapterStatus;
10926
11424
  const title = typeof parsedRecord?.title === "string" ? parsedRecord.title : void 0;
10927
11425
  const providerSessionId = typeof parsedRecord?.providerSessionId === "string" ? parsedRecord.providerSessionId : void 0;
11426
+ const transcriptAuthority = parsedRecord?.transcriptAuthority === "provider" || parsedRecord?.transcriptAuthority === "daemon" ? parsedRecord.transcriptAuthority : void 0;
11427
+ const coverage = parsedRecord?.coverage === "full" || parsedRecord?.coverage === "tail" || parsedRecord?.coverage === "current-turn" ? parsedRecord.coverage : void 0;
10928
11428
  if (status) {
10929
11429
  LOG.debug("Command", `[read_chat] cli-like resolved provider=${adapter.cliType} target=${String(args?.targetSessionId || "")} adapterStatus=${String(adapterStatus.status || "")} parsedStatus=${String(parsedRecord?.status || "")} shouldPreferAdapterMessages=${String(shouldPreferAdapterMessages)} adapterMsgCount=${Array.isArray(adapterStatus.messages) ? adapterStatus.messages.length : 0} parsedMsgCount=${Array.isArray(parsedRecord?.messages) ? parsedRecord.messages.length : 0} returnedMsgCount=${Array.isArray(status.messages) ? status.messages.length : 0}`);
10930
11430
  return buildReadChatCommandResult({
@@ -10943,7 +11443,9 @@ async function handleReadChat(h, args) {
10943
11443
  returnedMsgCount: Array.isArray(status.messages) ? status.messages.length : 0
10944
11444
  },
10945
11445
  ...title ? { title } : {},
10946
- ...providerSessionId ? { providerSessionId } : {}
11446
+ ...providerSessionId ? { providerSessionId } : {},
11447
+ ...transcriptAuthority ? { transcriptAuthority } : {},
11448
+ ...coverage ? { coverage } : {}
10947
11449
  }, args);
10948
11450
  }
10949
11451
  }
@@ -13363,6 +13865,8 @@ var CliProviderInstance = class {
13363
13865
  lastCanonicalHermesWatchPath = void 0;
13364
13866
  lastCanonicalClaudeRebuildMtimeMs = 0;
13365
13867
  lastCanonicalClaudeCheckAt = 0;
13868
+ lastCanonicalCodexRebuildMtimeMs = 0;
13869
+ lastCanonicalCodexCheckAt = 0;
13366
13870
  cachedSqliteDb = null;
13367
13871
  cachedSqliteDbPath = null;
13368
13872
  cachedSqliteDbMissingUntil = 0;
@@ -14062,6 +14566,25 @@ ${effect.notification.body || ""}`.trim();
14062
14566
  if (!this.providerSessionId) return false;
14063
14567
  const canonicalHistory = this.provider.canonicalHistory;
14064
14568
  if (!canonicalHistory) return false;
14569
+ if (isNativeSourceCanonicalHistory(canonicalHistory)) {
14570
+ const restoredHistory = readProviderChatHistory(this.type, {
14571
+ canonicalHistory,
14572
+ historySessionId: this.providerSessionId,
14573
+ workspace: this.workingDir,
14574
+ offset: 0,
14575
+ limit: Number.MAX_SAFE_INTEGER,
14576
+ historyBehavior: this.provider.historyBehavior
14577
+ });
14578
+ if (restoredHistory.source !== "provider-native") return false;
14579
+ this.lastPersistedHistoryMessages = restoredHistory.messages.map((message) => ({
14580
+ role: message.role,
14581
+ content: message.content,
14582
+ kind: message.kind,
14583
+ senderName: message.senderName,
14584
+ receivedAt: message.receivedAt
14585
+ }));
14586
+ return true;
14587
+ }
14065
14588
  try {
14066
14589
  let rebuilt = false;
14067
14590
  if (canonicalHistory.format === "hermes-json") {
@@ -14095,6 +14618,23 @@ ${effect.notification.body || ""}`.trim();
14095
14618
  if (transcriptMtime > 0 && transcriptMtime <= this.lastCanonicalClaudeRebuildMtimeMs) return true;
14096
14619
  rebuilt = rebuildClaudeSavedHistoryFromNativeProject(this.providerSessionId, this.workingDir);
14097
14620
  if (rebuilt) this.lastCanonicalClaudeRebuildMtimeMs = transcriptMtime || Date.now();
14621
+ } else if (canonicalHistory.format === "codex-jsonl") {
14622
+ const now = Date.now();
14623
+ if (now - this.lastCanonicalCodexCheckAt < 2e3 && this.lastCanonicalCodexRebuildMtimeMs !== 0) {
14624
+ return true;
14625
+ }
14626
+ this.lastCanonicalCodexCheckAt = now;
14627
+ const transcriptFile = resolveCodexSessionTranscriptPath(this.providerSessionId, this.workingDir);
14628
+ let transcriptMtime = 0;
14629
+ if (transcriptFile) {
14630
+ try {
14631
+ transcriptMtime = fs5.statSync(transcriptFile).mtimeMs;
14632
+ } catch {
14633
+ }
14634
+ }
14635
+ if (transcriptMtime > 0 && transcriptMtime <= this.lastCanonicalCodexRebuildMtimeMs) return true;
14636
+ rebuilt = rebuildCodexSavedHistoryFromNativeSession(this.providerSessionId, this.workingDir);
14637
+ if (rebuilt) this.lastCanonicalCodexRebuildMtimeMs = transcriptMtime || Date.now();
14098
14638
  }
14099
14639
  if (!rebuilt) return false;
14100
14640
  const restoredHistory = readChatHistory(this.type, 0, Number.MAX_SAFE_INTEGER, this.providerSessionId, 0, this.provider.historyBehavior);
@@ -14113,8 +14653,17 @@ ${effect.notification.body || ""}`.trim();
14113
14653
  restorePersistedHistoryFromCurrentSession() {
14114
14654
  if (!this.providerSessionId) return;
14115
14655
  this.syncCanonicalSavedHistoryIfNeeded();
14116
- this.historyWriter.compactHistorySession(this.type, this.providerSessionId, this.provider.historyBehavior);
14117
- const restoredHistory = readChatHistory(this.type, 0, Number.MAX_SAFE_INTEGER, this.providerSessionId, 0, this.provider.historyBehavior);
14656
+ const restoredHistory = isNativeSourceCanonicalHistory(this.provider.canonicalHistory) ? readProviderChatHistory(this.type, {
14657
+ canonicalHistory: this.provider.canonicalHistory,
14658
+ historySessionId: this.providerSessionId,
14659
+ workspace: this.workingDir,
14660
+ offset: 0,
14661
+ limit: Number.MAX_SAFE_INTEGER,
14662
+ historyBehavior: this.provider.historyBehavior
14663
+ }) : (() => {
14664
+ this.historyWriter.compactHistorySession(this.type, this.providerSessionId, this.provider.historyBehavior);
14665
+ return readChatHistory(this.type, 0, Number.MAX_SAFE_INTEGER, this.providerSessionId, 0, this.provider.historyBehavior);
14666
+ })();
14118
14667
  this.historyWriter.seedSessionHistory(
14119
14668
  this.type,
14120
14669
  restoredHistory.messages,
@@ -17849,6 +18398,38 @@ var ProviderLoader = class _ProviderLoader {
17849
18398
  }
17850
18399
  };
17851
18400
 
18401
+ // src/launch/macos-app-process.ts
18402
+ function normalizeMacAppPath(appPath) {
18403
+ const trimmed = String(appPath || "").trim();
18404
+ if (!trimmed) return null;
18405
+ return trimmed.replace(/\/+$/, "");
18406
+ }
18407
+ function parsePsLine(line) {
18408
+ const match = line.match(/^\s*(\d+)\s+(.+)$/);
18409
+ if (!match) return null;
18410
+ const pid = Number.parseInt(match[1], 10);
18411
+ if (!Number.isFinite(pid)) return null;
18412
+ return { pid, args: match[2] };
18413
+ }
18414
+ function isMacAppProcessArgs(args, appPath) {
18415
+ const normalized = normalizeMacAppPath(appPath);
18416
+ if (!normalized) return false;
18417
+ return String(args || "").startsWith(`${normalized}/`);
18418
+ }
18419
+ function findMacAppProcessPids(psOutput, appPaths) {
18420
+ const normalizedPaths = appPaths.map(normalizeMacAppPath).filter((value) => !!value);
18421
+ if (normalizedPaths.length === 0) return [];
18422
+ const pids = [];
18423
+ for (const line of String(psOutput || "").split(/\r?\n/)) {
18424
+ const parsed = parsePsLine(line);
18425
+ if (!parsed) continue;
18426
+ if (normalizedPaths.some((appPath) => isMacAppProcessArgs(parsed.args, appPath))) {
18427
+ pids.push(parsed.pid);
18428
+ }
18429
+ }
18430
+ return pids;
18431
+ }
18432
+
17852
18433
  // src/launch.ts
17853
18434
  var _providerLoader = null;
17854
18435
  function getProviderLoader() {
@@ -17885,6 +18466,35 @@ function getCdpStartupTimeoutMs(ideId) {
17885
18466
  function escapeForAppleScript(value) {
17886
18467
  return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
17887
18468
  }
18469
+ function getIdePathCandidates(ideId) {
18470
+ return getProviderLoader().getIdePathCandidates(ideId);
18471
+ }
18472
+ function getMacAppProcessPids(ideId) {
18473
+ const appPaths = getIdePathCandidates(ideId);
18474
+ if (appPaths.length === 0) return [];
18475
+ try {
18476
+ const output = execSync4("ps axww -o pid=,args=", {
18477
+ encoding: "utf-8",
18478
+ timeout: 3e3,
18479
+ stdio: ["pipe", "pipe", "pipe"]
18480
+ });
18481
+ return findMacAppProcessPids(output, appPaths);
18482
+ } catch {
18483
+ return [];
18484
+ }
18485
+ }
18486
+ function killMacAppPathProcesses(ideId, signal) {
18487
+ const pids = getMacAppProcessPids(ideId);
18488
+ let signalled = false;
18489
+ for (const pid of pids) {
18490
+ try {
18491
+ process.kill(pid, signal);
18492
+ signalled = true;
18493
+ } catch {
18494
+ }
18495
+ }
18496
+ return signalled;
18497
+ }
17888
18498
  async function findFreePort(ports) {
17889
18499
  for (const port2 of ports) {
17890
18500
  const free = await checkPortFree(port2);
@@ -17946,6 +18556,7 @@ async function killIdeProcess(ideId) {
17946
18556
  } catch {
17947
18557
  }
17948
18558
  }
18559
+ killMacAppPathProcesses(ideId, "SIGTERM");
17949
18560
  } else if (plat === "win32" && winProcesses) {
17950
18561
  for (const proc of winProcesses) {
17951
18562
  try {
@@ -17975,6 +18586,7 @@ async function killIdeProcess(ideId) {
17975
18586
  execSync4(`pkill -9 -x "${appName}" 2>/dev/null`, { timeout: 5e3 });
17976
18587
  } catch {
17977
18588
  }
18589
+ killMacAppPathProcesses(ideId, "SIGKILL");
17978
18590
  } else if (plat === "win32" && winProcesses) {
17979
18591
  for (const proc of winProcesses) {
17980
18592
  try {
@@ -17994,14 +18606,16 @@ function isIdeRunning(ideId) {
17994
18606
  try {
17995
18607
  if (plat === "darwin") {
17996
18608
  const appName = getMacAppIdentifiers()[ideId];
17997
- if (!appName) return false;
18609
+ if (!appName) return getMacAppProcessPids(ideId).length > 0;
17998
18610
  try {
17999
18611
  const result = execSync4(`pgrep -x "${appName}" 2>/dev/null`, {
18000
18612
  encoding: "utf-8",
18001
18613
  timeout: 3e3
18002
18614
  });
18003
- return result.trim().length > 0;
18615
+ if (result.trim().length > 0) return true;
18004
18616
  } catch {
18617
+ }
18618
+ try {
18005
18619
  const result = execSync4(
18006
18620
  `osascript -e 'tell application "System Events" to count (every process whose name is "${escapeForAppleScript(appName)}")'`,
18007
18621
  {
@@ -18010,8 +18624,10 @@ function isIdeRunning(ideId) {
18010
18624
  stdio: ["pipe", "pipe", "pipe"]
18011
18625
  }
18012
18626
  );
18013
- return Number.parseInt(result.trim() || "0", 10) > 0;
18627
+ if (Number.parseInt(result.trim() || "0", 10) > 0) return true;
18628
+ } catch {
18014
18629
  }
18630
+ return getMacAppProcessPids(ideId).length > 0;
18015
18631
  } else if (plat === "win32") {
18016
18632
  const winProcesses = getWinProcessNames()[ideId];
18017
18633
  if (!winProcesses) return false;
@@ -19378,13 +19994,18 @@ var DaemonCommandRouter = class {
19378
19994
  const wantsAll = args?.all === true;
19379
19995
  const offset = wantsAll ? 0 : Math.max(0, Number(args?.offset) || 0);
19380
19996
  const limit = wantsAll ? Number.MAX_SAFE_INTEGER : Math.max(1, Math.min(100, Number(args?.limit) || 30));
19381
- const { sessions: historySessions, hasMore } = listSavedHistorySessions(providerType, { offset, limit });
19997
+ const providerMeta = this.deps.providerLoader.getMeta(providerType);
19998
+ const { sessions: historySessions, hasMore, source } = listProviderHistorySessions(providerType, {
19999
+ canonicalHistory: providerMeta?.canonicalHistory,
20000
+ offset,
20001
+ limit,
20002
+ historyBehavior: providerMeta?.historyBehavior
20003
+ });
19382
20004
  const state = loadState();
19383
20005
  const savedSessions = getSavedProviderSessions(state, { providerType, kind });
19384
20006
  const recentSessions = getRecentActivity(state, 200).filter((entry) => entry.providerType === providerType && entry.kind === kind && entry.providerSessionId);
19385
20007
  const savedSessionById = new Map(savedSessions.map((entry) => [entry.providerSessionId, entry]));
19386
20008
  const recentSessionById = new Map(recentSessions.map((entry) => [entry.providerSessionId, entry]));
19387
- const providerMeta = this.deps.providerLoader.getMeta(providerType);
19388
20009
  const canResumeById = supportsExplicitSessionResume(providerMeta?.resume);
19389
20010
  return {
19390
20011
  success: true,
@@ -19407,7 +20028,8 @@ var DaemonCommandRouter = class {
19407
20028
  canResume: !!(saved?.workspace || recent?.workspace || session.workspace) && canResumeById
19408
20029
  };
19409
20030
  }),
19410
- hasMore
20031
+ hasMore,
20032
+ source
19411
20033
  };
19412
20034
  }
19413
20035
  // ─── restart_session: IDE / CLI / ACP unified ───