@adhdev/daemon-core 0.9.43 → 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.js CHANGED
@@ -985,6 +985,8 @@ function validateReadChatResultPayload(raw, source = "read_chat") {
985
985
  if (raw.summaryMetadata !== void 0) normalized.summaryMetadata = raw.summaryMetadata;
986
986
  if (Array.isArray(raw.effects)) normalized.effects = raw.effects;
987
987
  if (typeof raw.providerSessionId === "string") normalized.providerSessionId = raw.providerSessionId;
988
+ if (raw.transcriptAuthority === "provider" || raw.transcriptAuthority === "daemon") normalized.transcriptAuthority = raw.transcriptAuthority;
989
+ if (raw.coverage === "full" || raw.coverage === "tail" || raw.coverage === "current-turn") normalized.coverage = raw.coverage;
988
990
  return normalized;
989
991
  }
990
992
  var VALID_STATUSES, VALID_ROLES, VALID_BUBBLE_STATES, VALID_TURN_STATUSES;
@@ -2058,7 +2060,9 @@ var provider_cli_adapter_exports = {};
2058
2060
  __export(provider_cli_adapter_exports, {
2059
2061
  ProviderCliAdapter: () => ProviderCliAdapter,
2060
2062
  appendBoundedText: () => appendBoundedText,
2061
- normalizeCliProviderForRuntime: () => normalizeCliProviderForRuntime
2063
+ normalizeCliProviderForRuntime: () => normalizeCliProviderForRuntime,
2064
+ sanitizeCliStandardMessageContent: () => sanitizeCliStandardMessageContent,
2065
+ trimLastAssistantEchoForCliMessages: () => trimLastAssistantEchoForCliMessages
2062
2066
  });
2063
2067
  function normalizeComparableTranscriptText(value) {
2064
2068
  return sanitizeTerminalText(String(value || "")).replace(/\s+/g, " ").trim();
@@ -2098,7 +2102,76 @@ function appendBoundedText(current, chunk, maxChars) {
2098
2102
  if (current.length <= keepFromCurrent) return current + chunk;
2099
2103
  return current.slice(-keepFromCurrent) + chunk;
2100
2104
  }
2101
- var os10, ProviderCliAdapter;
2105
+ function isLikelyCommittedActivityPrefixContinuation(line) {
2106
+ const trimmed = String(line || "").trim();
2107
+ if (!trimmed) return false;
2108
+ if (COMMITTED_ACTIVITY_PREFIX_BLOCK_RE.test(trimmed)) return false;
2109
+ if (/\s/.test(trimmed)) return false;
2110
+ if (/[가-힣]/.test(trimmed)) return false;
2111
+ if (trimmed.length > 96) return false;
2112
+ return /^[A-Za-z0-9_./:@+%=-]+$/.test(trimmed);
2113
+ }
2114
+ function parseCommittedActivityPrefixBlock(lines, index) {
2115
+ const first = String(lines[index] || "").trim();
2116
+ if (!COMMITTED_ACTIVITY_PREFIX_BLOCK_RE.test(first)) return null;
2117
+ const parts = [first];
2118
+ let nextIndex = index + 1;
2119
+ while (nextIndex < lines.length && isLikelyCommittedActivityPrefixContinuation(lines[nextIndex])) {
2120
+ parts.push(String(lines[nextIndex] || "").trim());
2121
+ nextIndex += 1;
2122
+ }
2123
+ return { label: parts.join(""), nextIndex };
2124
+ }
2125
+ function sanitizeCliStandardMessageContent(content) {
2126
+ const source = String(content || "").trim();
2127
+ if (!source) return "";
2128
+ const lines = source.split(/\r?\n/);
2129
+ if (lines.length < 4) return source;
2130
+ const counts = /* @__PURE__ */ new Map();
2131
+ for (let index = 0; index < lines.length; index += 1) {
2132
+ const block = parseCommittedActivityPrefixBlock(lines, index);
2133
+ if (!block) continue;
2134
+ counts.set(block.label, (counts.get(block.label) || 0) + 1);
2135
+ index = block.nextIndex - 1;
2136
+ }
2137
+ const repeatedLabels = new Set(
2138
+ Array.from(counts.entries()).filter(([, count]) => count >= 3).map(([label]) => label)
2139
+ );
2140
+ if (repeatedLabels.size === 0) return source;
2141
+ const stripped = [];
2142
+ let removed = 0;
2143
+ for (let index = 0; index < lines.length; index += 1) {
2144
+ const block = parseCommittedActivityPrefixBlock(lines, index);
2145
+ if (block && repeatedLabels.has(block.label)) {
2146
+ removed += 1;
2147
+ index = block.nextIndex - 1;
2148
+ continue;
2149
+ }
2150
+ stripped.push(lines[index]);
2151
+ }
2152
+ const next = stripped.join("\n").replace(/\n{3,}/g, "\n\n").trim();
2153
+ return removed >= 3 && next.length >= 80 ? next : source;
2154
+ }
2155
+ function sanitizeCommittedMessageForDisplay(message) {
2156
+ if (!message || message.role !== "assistant" || (message.kind || "standard") !== "standard") return message;
2157
+ const content = sanitizeCliStandardMessageContent(message.content);
2158
+ if (content === message.content) return message;
2159
+ return { ...message, content };
2160
+ }
2161
+ function trimLastAssistantEchoForCliMessages(messages, prompt) {
2162
+ if (!prompt) return;
2163
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
2164
+ const message = messages[index];
2165
+ if (!message || message.role !== "assistant" || typeof message.content !== "string") continue;
2166
+ if ((message.kind || "standard") !== "standard") continue;
2167
+ message.content = trimPromptEchoPrefix(message.content, prompt);
2168
+ if (!message.content.trim()) {
2169
+ messages.splice(index, 1);
2170
+ }
2171
+ return;
2172
+ }
2173
+ }
2174
+ var os10, COMMITTED_ACTIVITY_PREFIX_BLOCK_RE, ProviderCliAdapter;
2102
2175
  var init_provider_cli_adapter = __esm({
2103
2176
  "src/cli-adapters/provider-cli-adapter.ts"() {
2104
2177
  "use strict";
@@ -2114,6 +2187,7 @@ var init_provider_cli_adapter = __esm({
2114
2187
  init_provider_cli_config();
2115
2188
  init_provider_cli_runtime();
2116
2189
  init_provider_cli_shared();
2190
+ COMMITTED_ACTIVITY_PREFIX_BLOCK_RE = /^(?:📖|💻|🔎|📚|📋|✏️|📝|🔧|🛠️|⚙️)\s+(.+)$/;
2117
2191
  ProviderCliAdapter = class _ProviderCliAdapter {
2118
2192
  constructor(provider, workingDir, extraArgs = [], transportFactory = new NodePtyTransportFactory()) {
2119
2193
  this.extraArgs = extraArgs;
@@ -2294,7 +2368,14 @@ var init_provider_cli_adapter = __esm({
2294
2368
  }
2295
2369
  return null;
2296
2370
  }
2371
+ providerOwnsTranscript() {
2372
+ return this.provider.transcriptAuthority === "provider";
2373
+ }
2374
+ shouldUseFullProviderTranscriptContext() {
2375
+ return this.providerOwnsTranscript() && this.provider.transcriptContext === "full";
2376
+ }
2297
2377
  selectParseBaseMessages(baseMessages) {
2378
+ if (this.shouldUseFullProviderTranscriptContext()) return baseMessages;
2298
2379
  if (baseMessages.length <= _ProviderCliAdapter.PARSE_MESSAGE_TAIL_LIMIT) return baseMessages;
2299
2380
  return baseMessages.slice(-_ProviderCliAdapter.PARSE_MESSAGE_TAIL_LIMIT);
2300
2381
  }
@@ -2325,7 +2406,10 @@ var init_provider_cli_adapter = __esm({
2325
2406
  const tailFirst = parseBaseMessages[0];
2326
2407
  if (tailFirst && this.messagesComparable(parsedFirst, tailFirst)) {
2327
2408
  const prefixLength = fullBaseMessages.length - parseBaseMessages.length;
2328
- return [...fullBaseMessages.slice(0, prefixLength), ...parsedMessages];
2409
+ const prefix = fullBaseMessages.slice(0, prefixLength);
2410
+ const shouldSanitizePrefix = !!this.currentTurnScope || this.currentStatus !== "idle" || !!this.activeModal;
2411
+ const nextPrefix = shouldSanitizePrefix ? prefix.map((message) => sanitizeCommittedMessageForDisplay(message)) : prefix;
2412
+ return [...nextPrefix, ...parsedMessages];
2329
2413
  }
2330
2414
  return [...fullBaseMessages, ...parsedMessages];
2331
2415
  }
@@ -2774,9 +2858,7 @@ var init_provider_cli_adapter = __esm({
2774
2858
  );
2775
2859
  }
2776
2860
  trimLastAssistantEcho(messages, prompt) {
2777
- if (!prompt) return;
2778
- const last = [...messages].reverse().find((m) => m.role === "assistant" && typeof m.content === "string");
2779
- if (last) last.content = trimPromptEchoPrefix(last.content, prompt);
2861
+ trimLastAssistantEchoForCliMessages(messages, prompt);
2780
2862
  }
2781
2863
  clearAllTimers() {
2782
2864
  if (this.responseTimeout) {
@@ -3524,10 +3606,12 @@ var init_provider_cli_adapter = __esm({
3524
3606
  }
3525
3607
  buildCommittedChatMessages() {
3526
3608
  return this.committedMessages.map((message, index) => {
3527
- const contentValue = message.content;
3609
+ const rawContentValue = message.content;
3610
+ const rawContent = typeof rawContentValue === "string" ? rawContentValue : String(rawContentValue || "");
3611
+ const content = message.role === "assistant" && (message.kind || "standard") === "standard" ? sanitizeCliStandardMessageContent(rawContent) : rawContent;
3528
3612
  return buildChatMessage({
3529
3613
  role: message.role,
3530
- content: typeof contentValue === "string" ? contentValue : String(contentValue || ""),
3614
+ content,
3531
3615
  timestamp: message.timestamp,
3532
3616
  kind: message.kind,
3533
3617
  meta: message.meta,
@@ -3628,7 +3712,8 @@ var init_provider_cli_adapter = __esm({
3628
3712
  title: parsed.title || this.cliName,
3629
3713
  messages: hydratedMessages,
3630
3714
  activeModal: parsed.activeModal ?? this.activeModal,
3631
- providerSessionId: typeof parsed.providerSessionId === "string" ? parsed.providerSessionId : void 0
3715
+ providerSessionId: typeof parsed.providerSessionId === "string" ? parsed.providerSessionId : void 0,
3716
+ ...this.providerOwnsTranscript() ? { transcriptAuthority: "provider", coverage: this.shouldUseFullProviderTranscriptContext() ? "full" : "tail" } : {}
3632
3717
  };
3633
3718
  } else {
3634
3719
  const messages = [...this.committedMessages];
@@ -7962,6 +8047,27 @@ var ChatHistoryWriter = class {
7962
8047
  return name.replace(/[^a-zA-Z0-9_-]/g, "_");
7963
8048
  }
7964
8049
  };
8050
+ function pageHistoryRecords(agentType, records, offset = 0, limit = 30, excludeRecentCount = 0, historyBehavior) {
8051
+ const allMessages = records.map((message) => sanitizeHistoryMessage(agentType, message)).filter(Boolean);
8052
+ allMessages.sort((a, b) => a.receivedAt - b.receivedAt);
8053
+ const chronological = [];
8054
+ let lastTurn = null;
8055
+ for (const message of allMessages) {
8056
+ const previous = chronological[chronological.length - 1];
8057
+ if (isAdjacentHistoryDuplicate(agentType, previous, message)) continue;
8058
+ if (message.role !== "system" && isAdjacentHistoryDuplicate(agentType, lastTurn, message)) continue;
8059
+ chronological.push(message);
8060
+ if (message.role !== "system") lastTurn = message;
8061
+ }
8062
+ const collapsed = collapseReplayAssistantTurns(chronological, historyBehavior);
8063
+ const boundedLimit = Math.max(1, limit);
8064
+ const boundedOffset = Math.max(0, offset);
8065
+ const boundedExclude = Math.max(0, Math.min(excludeRecentCount, collapsed.length));
8066
+ const endExclusive = Math.max(0, collapsed.length - boundedExclude - boundedOffset);
8067
+ const startInclusive = Math.max(0, endExclusive - boundedLimit);
8068
+ const sliced = collapsed.slice(startInclusive, endExclusive);
8069
+ return { messages: sliced, hasMore: startInclusive > 0 };
8070
+ }
7965
8071
  function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0, historyBehavior) {
7966
8072
  try {
7967
8073
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
@@ -7987,25 +8093,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, ex
7987
8093
  }
7988
8094
  }
7989
8095
  }
7990
- allMessages.sort((a, b) => a.receivedAt - b.receivedAt);
7991
- const chronological = [];
7992
- let lastTurn = null;
7993
- for (const message of allMessages) {
7994
- const previous = chronological[chronological.length - 1];
7995
- if (isAdjacentHistoryDuplicate(agentType, previous, message)) continue;
7996
- if (message.role !== "system" && isAdjacentHistoryDuplicate(agentType, lastTurn, message)) continue;
7997
- chronological.push(message);
7998
- if (message.role !== "system") lastTurn = message;
7999
- }
8000
- const collapsed = collapseReplayAssistantTurns(chronological, historyBehavior);
8001
- const boundedLimit = Math.max(1, limit);
8002
- const boundedOffset = Math.max(0, offset);
8003
- const boundedExclude = Math.max(0, Math.min(excludeRecentCount, collapsed.length));
8004
- const endExclusive = Math.max(0, collapsed.length - boundedExclude - boundedOffset);
8005
- const startInclusive = Math.max(0, endExclusive - boundedLimit);
8006
- const sliced = collapsed.slice(startInclusive, endExclusive);
8007
- const hasMore = startInclusive > 0;
8008
- return { messages: sliced, hasMore };
8096
+ return pageHistoryRecords(agentType, allMessages, offset, limit, excludeRecentCount, historyBehavior);
8009
8097
  } catch {
8010
8098
  return { messages: [], hasMore: false };
8011
8099
  }
@@ -8140,6 +8228,52 @@ function rewriteCanonicalSavedHistory(agentType, historySessionId, records) {
8140
8228
  return false;
8141
8229
  }
8142
8230
  }
8231
+ function buildHermesNativeHistoryRecords(historySessionId) {
8232
+ const normalizedSessionId = normalizeSavedHistorySessionId(historySessionId);
8233
+ if (!normalizedSessionId) return null;
8234
+ try {
8235
+ const sessionFilePath = path7.join(os5.homedir(), ".hermes", "sessions", `session_${normalizedSessionId}.json`);
8236
+ if (!fs3.existsSync(sessionFilePath)) return null;
8237
+ const raw = JSON.parse(fs3.readFileSync(sessionFilePath, "utf-8"));
8238
+ const canonicalMessages = Array.isArray(raw.messages) ? raw.messages : [];
8239
+ const records = [];
8240
+ let fallbackTs = Date.parse(raw.session_start || raw.last_updated || "") || Date.now();
8241
+ for (const message of canonicalMessages) {
8242
+ const role = String(message.role || "").trim();
8243
+ const content = normalizeCanonicalHermesMessageContent(message.content);
8244
+ if (!content) continue;
8245
+ const receivedAt = extractCanonicalHermesMessageTimestamp(message, fallbackTs);
8246
+ fallbackTs = receivedAt + 1;
8247
+ if (role === "user" || role === "assistant") {
8248
+ records.push({
8249
+ ts: new Date(receivedAt).toISOString(),
8250
+ receivedAt,
8251
+ role,
8252
+ content,
8253
+ kind: "standard",
8254
+ agent: "hermes-cli",
8255
+ historySessionId: normalizedSessionId
8256
+ });
8257
+ continue;
8258
+ }
8259
+ if (role === "tool") {
8260
+ records.push({
8261
+ ts: new Date(receivedAt).toISOString(),
8262
+ receivedAt,
8263
+ role: "assistant",
8264
+ content,
8265
+ kind: "tool",
8266
+ senderName: "Tool",
8267
+ agent: "hermes-cli",
8268
+ historySessionId: normalizedSessionId
8269
+ });
8270
+ }
8271
+ }
8272
+ return records;
8273
+ } catch {
8274
+ return null;
8275
+ }
8276
+ }
8143
8277
  function rebuildHermesSavedHistoryFromCanonicalSession(historySessionId) {
8144
8278
  const normalizedSessionId = normalizeSavedHistorySessionId(historySessionId);
8145
8279
  if (!normalizedSessionId) return false;
@@ -8289,6 +8423,77 @@ function extractClaudeUserContentParts(content) {
8289
8423
  }
8290
8424
  return parts;
8291
8425
  }
8426
+ function buildClaudeNativeHistoryRecords(historySessionId, workspace) {
8427
+ const normalizedSessionId = normalizeSavedHistorySessionId(historySessionId);
8428
+ if (!normalizedSessionId) return null;
8429
+ try {
8430
+ const transcriptPath = resolveClaudeProjectTranscriptPath(normalizedSessionId, workspace);
8431
+ if (!transcriptPath) return null;
8432
+ const lines = fs3.readFileSync(transcriptPath, "utf-8").split("\n").filter(Boolean);
8433
+ const records = [];
8434
+ let fallbackTs = Date.now();
8435
+ for (const line of lines) {
8436
+ let parsed = null;
8437
+ try {
8438
+ parsed = JSON.parse(line);
8439
+ } catch {
8440
+ parsed = null;
8441
+ }
8442
+ if (!parsed) continue;
8443
+ const parsedSessionId = String(parsed.sessionId || "").trim();
8444
+ if (parsedSessionId && parsedSessionId !== normalizedSessionId) continue;
8445
+ const receivedAt = extractTimestampValue(parsed.timestamp) || fallbackTs;
8446
+ fallbackTs = receivedAt + 1;
8447
+ const parsedWorkspace = String(parsed.cwd || workspace || "").trim();
8448
+ if (records.length === 0 && parsedWorkspace) {
8449
+ records.push({
8450
+ ts: new Date(receivedAt).toISOString(),
8451
+ receivedAt,
8452
+ role: "system",
8453
+ kind: "session_start",
8454
+ content: parsedWorkspace,
8455
+ agent: "claude-cli",
8456
+ historySessionId: normalizedSessionId,
8457
+ workspace: parsedWorkspace
8458
+ });
8459
+ }
8460
+ const type = String(parsed.type || "").trim();
8461
+ const message = parsed.message && typeof parsed.message === "object" ? parsed.message : null;
8462
+ if (type === "user" && message) {
8463
+ for (const part of extractClaudeUserContentParts(message.content)) {
8464
+ records.push({
8465
+ ts: new Date(receivedAt).toISOString(),
8466
+ receivedAt,
8467
+ role: part.role,
8468
+ content: part.content,
8469
+ kind: part.kind,
8470
+ senderName: part.senderName,
8471
+ agent: "claude-cli",
8472
+ historySessionId: normalizedSessionId
8473
+ });
8474
+ }
8475
+ continue;
8476
+ }
8477
+ if (type === "assistant" && message) {
8478
+ for (const part of extractClaudeAssistantContentParts(message.content)) {
8479
+ records.push({
8480
+ ts: new Date(receivedAt).toISOString(),
8481
+ receivedAt,
8482
+ role: "assistant",
8483
+ content: part.content,
8484
+ kind: part.kind,
8485
+ senderName: part.senderName,
8486
+ agent: "claude-cli",
8487
+ historySessionId: normalizedSessionId
8488
+ });
8489
+ }
8490
+ }
8491
+ }
8492
+ return records;
8493
+ } catch {
8494
+ return null;
8495
+ }
8496
+ }
8292
8497
  function rebuildClaudeSavedHistoryFromNativeProject(historySessionId, workspace) {
8293
8498
  const normalizedSessionId = normalizeSavedHistorySessionId(historySessionId);
8294
8499
  if (!normalizedSessionId) return false;
@@ -8367,6 +8572,352 @@ function rebuildClaudeSavedHistoryFromNativeProject(historySessionId, workspace)
8367
8572
  return false;
8368
8573
  }
8369
8574
  }
8575
+ function isUuidLikeSessionId(sessionId) {
8576
+ return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(sessionId);
8577
+ }
8578
+ function readCodexSessionMeta(filePath) {
8579
+ try {
8580
+ const firstLine = fs3.readFileSync(filePath, "utf-8").split("\n").find(Boolean);
8581
+ if (!firstLine) return null;
8582
+ const parsed = JSON.parse(firstLine);
8583
+ if (String(parsed.type || "") !== "session_meta") return null;
8584
+ const payload = parsed.payload && typeof parsed.payload === "object" ? parsed.payload : null;
8585
+ return payload;
8586
+ } catch {
8587
+ return null;
8588
+ }
8589
+ }
8590
+ function resolveCodexSessionTranscriptPath(historySessionId, workspace) {
8591
+ const normalizedSessionId = normalizeSavedHistorySessionId(historySessionId);
8592
+ if (!normalizedSessionId || !isUuidLikeSessionId(normalizedSessionId)) return null;
8593
+ const sessionsDir = path7.join(os5.homedir(), ".codex", "sessions");
8594
+ if (!fs3.existsSync(sessionsDir)) return null;
8595
+ const normalizedWorkspace = typeof workspace === "string" ? workspace.trim() : "";
8596
+ const candidates = [];
8597
+ const stack = [sessionsDir];
8598
+ while (stack.length > 0) {
8599
+ const current = stack.pop();
8600
+ if (!current) continue;
8601
+ let entries = [];
8602
+ try {
8603
+ entries = fs3.readdirSync(current, { withFileTypes: true });
8604
+ } catch {
8605
+ continue;
8606
+ }
8607
+ for (const entry of entries) {
8608
+ const entryPath = path7.join(current, entry.name);
8609
+ if (entry.isDirectory()) {
8610
+ stack.push(entryPath);
8611
+ continue;
8612
+ }
8613
+ if (!entry.isFile() || !entry.name.endsWith(".jsonl") || !entry.name.includes(normalizedSessionId)) continue;
8614
+ const meta = readCodexSessionMeta(entryPath);
8615
+ const metaSessionId = String(meta?.id || "").trim();
8616
+ if (metaSessionId && metaSessionId !== normalizedSessionId) continue;
8617
+ const metaWorkspace = String(meta?.cwd || "").trim();
8618
+ let mtimeMs = 0;
8619
+ try {
8620
+ mtimeMs = fs3.statSync(entryPath).mtimeMs;
8621
+ } catch {
8622
+ }
8623
+ candidates.push({
8624
+ path: entryPath,
8625
+ mtimeMs,
8626
+ workspaceMatches: !!normalizedWorkspace && metaWorkspace === normalizedWorkspace,
8627
+ metaMatches: metaSessionId === normalizedSessionId
8628
+ });
8629
+ }
8630
+ }
8631
+ candidates.sort((a, b) => Number(b.workspaceMatches) - Number(a.workspaceMatches) || Number(b.metaMatches) - Number(a.metaMatches) || b.mtimeMs - a.mtimeMs);
8632
+ return candidates[0]?.path || null;
8633
+ }
8634
+ function flattenCodexContent(content) {
8635
+ if (typeof content === "string") return content.trim();
8636
+ if (content == null) return "";
8637
+ if (Array.isArray(content)) {
8638
+ return content.map((entry) => flattenCodexContent(entry)).filter(Boolean).join("\n").trim();
8639
+ }
8640
+ if (typeof content === "object") {
8641
+ const record = content;
8642
+ if (typeof record.text === "string") return record.text.trim();
8643
+ if (typeof record.content === "string" || Array.isArray(record.content)) return flattenCodexContent(record.content);
8644
+ if (typeof record.output === "string") return record.output.trim();
8645
+ if (typeof record.message === "string") return record.message.trim();
8646
+ }
8647
+ return "";
8648
+ }
8649
+ function summarizeCodexToolCall(payload) {
8650
+ const name = String(payload.name || payload.type || "tool").trim() || "tool";
8651
+ const rawArguments = payload.arguments ?? payload.input;
8652
+ let argumentValue = "";
8653
+ if (typeof rawArguments === "string") {
8654
+ const trimmed = rawArguments.trim();
8655
+ try {
8656
+ const parsed = JSON.parse(trimmed);
8657
+ argumentValue = summarizeCodexToolArguments(parsed);
8658
+ } catch {
8659
+ argumentValue = trimmed;
8660
+ }
8661
+ } else {
8662
+ argumentValue = summarizeCodexToolArguments(rawArguments);
8663
+ }
8664
+ return argumentValue ? `${name}: ${argumentValue}` : name;
8665
+ }
8666
+ function summarizeCodexToolArguments(value) {
8667
+ if (typeof value === "string") return value.trim();
8668
+ if (Array.isArray(value)) return value.map((entry) => String(entry)).join(" ").trim();
8669
+ if (!value || typeof value !== "object") return "";
8670
+ const record = value;
8671
+ const direct = record.command || record.cmd || record.query || record.path || record.prompt;
8672
+ if (typeof direct === "string") return direct.trim();
8673
+ if (Array.isArray(direct)) return direct.map((entry) => String(entry)).join(" ").trim();
8674
+ try {
8675
+ return JSON.stringify(record).trim();
8676
+ } catch {
8677
+ return "";
8678
+ }
8679
+ }
8680
+ function codexToolOutputContent(payload) {
8681
+ const output = payload.output ?? payload.result ?? payload.content;
8682
+ const text = flattenCodexContent(output);
8683
+ if (text) return text;
8684
+ if (output && typeof output === "object") {
8685
+ try {
8686
+ return JSON.stringify(output).trim();
8687
+ } catch {
8688
+ return "";
8689
+ }
8690
+ }
8691
+ return "";
8692
+ }
8693
+ function buildCodexNativeHistoryRecords(historySessionId, workspace) {
8694
+ const normalizedSessionId = normalizeSavedHistorySessionId(historySessionId);
8695
+ if (!normalizedSessionId || !isUuidLikeSessionId(normalizedSessionId)) return null;
8696
+ try {
8697
+ const transcriptPath = resolveCodexSessionTranscriptPath(normalizedSessionId, workspace);
8698
+ if (!transcriptPath) return null;
8699
+ const lines = fs3.readFileSync(transcriptPath, "utf-8").split("\n").filter(Boolean);
8700
+ const records = [];
8701
+ let fallbackTs = Date.now();
8702
+ for (const line of lines) {
8703
+ let parsed = null;
8704
+ try {
8705
+ parsed = JSON.parse(line);
8706
+ } catch {
8707
+ parsed = null;
8708
+ }
8709
+ if (!parsed) continue;
8710
+ const receivedAt = extractTimestampValue(parsed.timestamp) || fallbackTs;
8711
+ fallbackTs = receivedAt + 1;
8712
+ const type = String(parsed.type || "").trim();
8713
+ const payload = parsed.payload && typeof parsed.payload === "object" ? parsed.payload : null;
8714
+ if (!payload) continue;
8715
+ if (type === "session_meta") {
8716
+ const parsedSessionId = String(payload.id || "").trim();
8717
+ if (parsedSessionId && parsedSessionId !== normalizedSessionId) return null;
8718
+ const parsedWorkspace = String(payload.cwd || workspace || "").trim();
8719
+ if (records.length === 0 && parsedWorkspace) {
8720
+ records.push({
8721
+ ts: new Date(receivedAt).toISOString(),
8722
+ receivedAt,
8723
+ role: "system",
8724
+ kind: "session_start",
8725
+ content: parsedWorkspace,
8726
+ agent: "codex-cli",
8727
+ historySessionId: normalizedSessionId,
8728
+ workspace: parsedWorkspace
8729
+ });
8730
+ }
8731
+ continue;
8732
+ }
8733
+ if (type !== "response_item") continue;
8734
+ const payloadType = String(payload.type || "").trim();
8735
+ if (payloadType === "message") {
8736
+ const role = String(payload.role || "").trim();
8737
+ if (role !== "user" && role !== "assistant") continue;
8738
+ const content = flattenCodexContent(payload.content);
8739
+ if (!content) continue;
8740
+ records.push({
8741
+ ts: new Date(receivedAt).toISOString(),
8742
+ receivedAt,
8743
+ role,
8744
+ content,
8745
+ kind: "standard",
8746
+ agent: "codex-cli",
8747
+ historySessionId: normalizedSessionId
8748
+ });
8749
+ continue;
8750
+ }
8751
+ if (payloadType === "function_call" || payloadType === "custom_tool_call") {
8752
+ const content = summarizeCodexToolCall(payload);
8753
+ if (!content) continue;
8754
+ records.push({
8755
+ ts: new Date(receivedAt).toISOString(),
8756
+ receivedAt,
8757
+ role: "assistant",
8758
+ content,
8759
+ kind: "tool",
8760
+ senderName: "Tool",
8761
+ agent: "codex-cli",
8762
+ historySessionId: normalizedSessionId
8763
+ });
8764
+ continue;
8765
+ }
8766
+ if (payloadType === "function_call_output" || payloadType === "custom_tool_call_output") {
8767
+ const content = codexToolOutputContent(payload);
8768
+ if (!content) continue;
8769
+ records.push({
8770
+ ts: new Date(receivedAt).toISOString(),
8771
+ receivedAt,
8772
+ role: "assistant",
8773
+ content,
8774
+ kind: "tool",
8775
+ senderName: "Tool",
8776
+ agent: "codex-cli",
8777
+ historySessionId: normalizedSessionId
8778
+ });
8779
+ }
8780
+ }
8781
+ return records;
8782
+ } catch {
8783
+ return null;
8784
+ }
8785
+ }
8786
+ function rebuildCodexSavedHistoryFromNativeSession(historySessionId, workspace) {
8787
+ const normalizedSessionId = normalizeSavedHistorySessionId(historySessionId);
8788
+ if (!normalizedSessionId || !isUuidLikeSessionId(normalizedSessionId)) return false;
8789
+ const records = buildCodexNativeHistoryRecords(normalizedSessionId, workspace);
8790
+ if (!records || records.length === 0) return false;
8791
+ const existingSessionStart = readExistingSessionStartRecord("codex-cli", normalizedSessionId);
8792
+ const recordsToWrite = existingSessionStart && records[0]?.kind !== "session_start" ? [{ ...existingSessionStart, historySessionId: normalizedSessionId }, ...records] : records;
8793
+ return rewriteCanonicalSavedHistory("codex-cli", normalizedSessionId, recordsToWrite);
8794
+ }
8795
+ function isNativeSourceCanonicalHistory(canonicalHistory) {
8796
+ if (!canonicalHistory) return false;
8797
+ if (canonicalHistory.mode === "disabled") return false;
8798
+ if (canonicalHistory.mode === "materialized-mirror") return false;
8799
+ return true;
8800
+ }
8801
+ function buildNativeHistoryRecords(canonicalHistory, historySessionId, workspace) {
8802
+ const normalizedSessionId = normalizeSavedHistorySessionId(historySessionId || "");
8803
+ if (!canonicalHistory || !normalizedSessionId || !isNativeSourceCanonicalHistory(canonicalHistory)) return null;
8804
+ if (canonicalHistory.format === "hermes-json") return buildHermesNativeHistoryRecords(normalizedSessionId);
8805
+ if (canonicalHistory.format === "claude-jsonl") return buildClaudeNativeHistoryRecords(normalizedSessionId, workspace);
8806
+ if (canonicalHistory.format === "codex-jsonl") return buildCodexNativeHistoryRecords(normalizedSessionId, workspace);
8807
+ return null;
8808
+ }
8809
+ function readProviderChatHistory(agentType, options = {}) {
8810
+ if (isNativeSourceCanonicalHistory(options.canonicalHistory) && options.historySessionId) {
8811
+ const records = buildNativeHistoryRecords(options.canonicalHistory, options.historySessionId, options.workspace);
8812
+ if (!records) return { messages: [], hasMore: false, source: "native-unavailable" };
8813
+ return {
8814
+ ...pageHistoryRecords(agentType, records, options.offset || 0, options.limit || 30, options.excludeRecentCount || 0, options.historyBehavior),
8815
+ source: "provider-native"
8816
+ };
8817
+ }
8818
+ return {
8819
+ ...readChatHistory(agentType, options.offset || 0, options.limit || 30, options.historySessionId, options.excludeRecentCount || 0, options.historyBehavior),
8820
+ source: "adhdev-mirror"
8821
+ };
8822
+ }
8823
+ function buildNativeSessionSummary(agentType, historySessionId, records, sourcePath) {
8824
+ const visible = pageHistoryRecords(agentType, records, 0, Number.MAX_SAFE_INTEGER).messages;
8825
+ if (visible.length === 0) return null;
8826
+ let sourceMtimeMs = 0;
8827
+ try {
8828
+ sourceMtimeMs = fs3.statSync(sourcePath).mtimeMs;
8829
+ } catch {
8830
+ }
8831
+ const firstMessageAt = visible[0]?.receivedAt || sourceMtimeMs || Date.now();
8832
+ const lastMessageAt = visible[visible.length - 1]?.receivedAt || firstMessageAt;
8833
+ const lastNonSystem = [...visible].reverse().find((message) => message.role !== "system") || visible[visible.length - 1];
8834
+ const firstSystem = visible.find((message) => message.kind === "session_start");
8835
+ return {
8836
+ historySessionId,
8837
+ sessionTitle: lastNonSystem?.content,
8838
+ messageCount: visible.length,
8839
+ firstMessageAt,
8840
+ lastMessageAt,
8841
+ preview: lastNonSystem?.content,
8842
+ workspace: firstSystem?.workspace || (firstSystem?.kind === "session_start" ? firstSystem.content : void 0),
8843
+ source: "provider-native",
8844
+ sourcePath,
8845
+ sourceMtimeMs
8846
+ };
8847
+ }
8848
+ function listFilesRecursive(root, predicate) {
8849
+ if (!fs3.existsSync(root)) return [];
8850
+ const results = [];
8851
+ const stack = [root];
8852
+ while (stack.length > 0) {
8853
+ const current = stack.pop();
8854
+ if (!current) continue;
8855
+ let entries = [];
8856
+ try {
8857
+ entries = fs3.readdirSync(current, { withFileTypes: true });
8858
+ } catch {
8859
+ continue;
8860
+ }
8861
+ for (const entry of entries) {
8862
+ const entryPath = path7.join(current, entry.name);
8863
+ if (entry.isDirectory()) {
8864
+ stack.push(entryPath);
8865
+ continue;
8866
+ }
8867
+ if (predicate(entryPath, entry)) results.push(entryPath);
8868
+ }
8869
+ }
8870
+ return results;
8871
+ }
8872
+ function collectNativeHistorySessionSummaries(agentType, canonicalHistory) {
8873
+ const summaries = [];
8874
+ if (canonicalHistory.format === "hermes-json") {
8875
+ const root = path7.join(os5.homedir(), ".hermes", "sessions");
8876
+ for (const filePath of listFilesRecursive(root, (_entryPath, entry) => entry.isFile() && /^session_.+\.json$/.test(entry.name))) {
8877
+ const fileName = path7.basename(filePath);
8878
+ const historySessionId = fileName.replace(/^session_/, "").replace(/\.json$/, "");
8879
+ const records = buildHermesNativeHistoryRecords(historySessionId);
8880
+ const summary = records ? buildNativeSessionSummary(agentType, historySessionId, records, filePath) : null;
8881
+ if (summary) summaries.push(summary);
8882
+ }
8883
+ } else if (canonicalHistory.format === "claude-jsonl") {
8884
+ const root = path7.join(os5.homedir(), ".claude", "projects");
8885
+ for (const filePath of listFilesRecursive(root, (_entryPath, entry) => entry.isFile() && entry.name.endsWith(".jsonl"))) {
8886
+ const historySessionId = path7.basename(filePath, ".jsonl");
8887
+ const records = buildClaudeNativeHistoryRecords(historySessionId);
8888
+ const summary = records ? buildNativeSessionSummary(agentType, historySessionId, records, filePath) : null;
8889
+ if (summary) summaries.push(summary);
8890
+ }
8891
+ } else if (canonicalHistory.format === "codex-jsonl") {
8892
+ const root = path7.join(os5.homedir(), ".codex", "sessions");
8893
+ const uuidPattern = /([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/i;
8894
+ for (const filePath of listFilesRecursive(root, (_entryPath, entry) => entry.isFile() && entry.name.endsWith(".jsonl"))) {
8895
+ const meta = readCodexSessionMeta(filePath);
8896
+ const historySessionId = String(meta?.id || path7.basename(filePath).match(uuidPattern)?.[1] || "").trim();
8897
+ if (!historySessionId) continue;
8898
+ const records = buildCodexNativeHistoryRecords(historySessionId, String(meta?.cwd || "").trim() || void 0);
8899
+ const summary = records ? buildNativeSessionSummary(agentType, historySessionId, records, filePath) : null;
8900
+ if (summary) summaries.push(summary);
8901
+ }
8902
+ }
8903
+ return sortSavedHistorySessionSummaries(summaries);
8904
+ }
8905
+ function listProviderHistorySessions(agentType, options = {}) {
8906
+ if (isNativeSourceCanonicalHistory(options.canonicalHistory)) {
8907
+ const offset = Math.max(0, options.offset || 0);
8908
+ const limit = Math.max(1, options.limit || 30);
8909
+ const summaries = collectNativeHistorySessionSummaries(agentType, options.canonicalHistory);
8910
+ return {
8911
+ sessions: summaries.slice(offset, offset + limit),
8912
+ hasMore: offset + limit < summaries.length,
8913
+ source: "provider-native"
8914
+ };
8915
+ }
8916
+ return {
8917
+ ...listSavedHistorySessions(agentType, { offset: options.offset, limit: options.limit }, options.historyBehavior),
8918
+ source: "adhdev-mirror"
8919
+ };
8920
+ }
8370
8921
 
8371
8922
  // src/providers/provider-patch-state.ts
8372
8923
  function isControlValue(value) {
@@ -10980,7 +11531,16 @@ async function handleChatHistory(h, args) {
10980
11531
  const visibleCount = Array.isArray(status?.messages) ? status.messages.length : 0;
10981
11532
  if (visibleCount > excludeRecentCount) excludeRecentCount = visibleCount;
10982
11533
  }
10983
- const result = readChatHistory(agentStr, offset || 0, limit || 30, historySessionId, excludeRecentCount);
11534
+ const workspace = typeof args?.workspace === "string" ? args.workspace : typeof h.currentSession?.workspace === "string" ? h.currentSession.workspace : void 0;
11535
+ const result = readProviderChatHistory(agentStr, {
11536
+ canonicalHistory: provider?.canonicalHistory,
11537
+ historySessionId,
11538
+ workspace,
11539
+ offset: offset || 0,
11540
+ limit: limit || 30,
11541
+ excludeRecentCount,
11542
+ historyBehavior: provider?.historyBehavior
11543
+ });
10984
11544
  return { success: true, ...result, agent: agentStr };
10985
11545
  } catch (e) {
10986
11546
  return { success: false, error: e.message };
@@ -11005,7 +11565,8 @@ async function handleReadChat(h, args) {
11005
11565
  }
11006
11566
  const parsedRecord = parsedStatus && typeof parsedStatus === "object" ? parsedStatus : null;
11007
11567
  const adapterStatus = adapter.getStatus();
11008
- const shouldPreferAdapterMessages = Array.isArray(adapterStatus.messages) && adapterStatus.messages.length > 0 && Array.isArray(parsedRecord?.messages) && adapterStatus.messages.length > parsedRecord.messages.length;
11568
+ const parsedIsProviderAuthoritative = parsedRecord?.transcriptAuthority === "provider" || parsedRecord?.coverage === "full";
11569
+ const shouldPreferAdapterMessages = !parsedIsProviderAuthoritative && Array.isArray(adapterStatus.messages) && adapterStatus.messages.length > 0 && Array.isArray(parsedRecord?.messages) && adapterStatus.messages.length > parsedRecord.messages.length;
11009
11570
  const parsedShowsApproval = hasNonEmptyModalButtons(parsedRecord?.activeModal) && parsedRecord?.status === "waiting_approval";
11010
11571
  const status = parsedRecord ? {
11011
11572
  ...parsedRecord,
@@ -11015,6 +11576,8 @@ async function handleReadChat(h, args) {
11015
11576
  } : adapterStatus;
11016
11577
  const title = typeof parsedRecord?.title === "string" ? parsedRecord.title : void 0;
11017
11578
  const providerSessionId = typeof parsedRecord?.providerSessionId === "string" ? parsedRecord.providerSessionId : void 0;
11579
+ const transcriptAuthority = parsedRecord?.transcriptAuthority === "provider" || parsedRecord?.transcriptAuthority === "daemon" ? parsedRecord.transcriptAuthority : void 0;
11580
+ const coverage = parsedRecord?.coverage === "full" || parsedRecord?.coverage === "tail" || parsedRecord?.coverage === "current-turn" ? parsedRecord.coverage : void 0;
11018
11581
  if (status) {
11019
11582
  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}`);
11020
11583
  return buildReadChatCommandResult({
@@ -11033,7 +11596,9 @@ async function handleReadChat(h, args) {
11033
11596
  returnedMsgCount: Array.isArray(status.messages) ? status.messages.length : 0
11034
11597
  },
11035
11598
  ...title ? { title } : {},
11036
- ...providerSessionId ? { providerSessionId } : {}
11599
+ ...providerSessionId ? { providerSessionId } : {},
11600
+ ...transcriptAuthority ? { transcriptAuthority } : {},
11601
+ ...coverage ? { coverage } : {}
11037
11602
  }, args);
11038
11603
  }
11039
11604
  }
@@ -13453,6 +14018,8 @@ var CliProviderInstance = class {
13453
14018
  lastCanonicalHermesWatchPath = void 0;
13454
14019
  lastCanonicalClaudeRebuildMtimeMs = 0;
13455
14020
  lastCanonicalClaudeCheckAt = 0;
14021
+ lastCanonicalCodexRebuildMtimeMs = 0;
14022
+ lastCanonicalCodexCheckAt = 0;
13456
14023
  cachedSqliteDb = null;
13457
14024
  cachedSqliteDbPath = null;
13458
14025
  cachedSqliteDbMissingUntil = 0;
@@ -14152,6 +14719,25 @@ ${effect.notification.body || ""}`.trim();
14152
14719
  if (!this.providerSessionId) return false;
14153
14720
  const canonicalHistory = this.provider.canonicalHistory;
14154
14721
  if (!canonicalHistory) return false;
14722
+ if (isNativeSourceCanonicalHistory(canonicalHistory)) {
14723
+ const restoredHistory = readProviderChatHistory(this.type, {
14724
+ canonicalHistory,
14725
+ historySessionId: this.providerSessionId,
14726
+ workspace: this.workingDir,
14727
+ offset: 0,
14728
+ limit: Number.MAX_SAFE_INTEGER,
14729
+ historyBehavior: this.provider.historyBehavior
14730
+ });
14731
+ if (restoredHistory.source !== "provider-native") return false;
14732
+ this.lastPersistedHistoryMessages = restoredHistory.messages.map((message) => ({
14733
+ role: message.role,
14734
+ content: message.content,
14735
+ kind: message.kind,
14736
+ senderName: message.senderName,
14737
+ receivedAt: message.receivedAt
14738
+ }));
14739
+ return true;
14740
+ }
14155
14741
  try {
14156
14742
  let rebuilt = false;
14157
14743
  if (canonicalHistory.format === "hermes-json") {
@@ -14185,6 +14771,23 @@ ${effect.notification.body || ""}`.trim();
14185
14771
  if (transcriptMtime > 0 && transcriptMtime <= this.lastCanonicalClaudeRebuildMtimeMs) return true;
14186
14772
  rebuilt = rebuildClaudeSavedHistoryFromNativeProject(this.providerSessionId, this.workingDir);
14187
14773
  if (rebuilt) this.lastCanonicalClaudeRebuildMtimeMs = transcriptMtime || Date.now();
14774
+ } else if (canonicalHistory.format === "codex-jsonl") {
14775
+ const now = Date.now();
14776
+ if (now - this.lastCanonicalCodexCheckAt < 2e3 && this.lastCanonicalCodexRebuildMtimeMs !== 0) {
14777
+ return true;
14778
+ }
14779
+ this.lastCanonicalCodexCheckAt = now;
14780
+ const transcriptFile = resolveCodexSessionTranscriptPath(this.providerSessionId, this.workingDir);
14781
+ let transcriptMtime = 0;
14782
+ if (transcriptFile) {
14783
+ try {
14784
+ transcriptMtime = fs5.statSync(transcriptFile).mtimeMs;
14785
+ } catch {
14786
+ }
14787
+ }
14788
+ if (transcriptMtime > 0 && transcriptMtime <= this.lastCanonicalCodexRebuildMtimeMs) return true;
14789
+ rebuilt = rebuildCodexSavedHistoryFromNativeSession(this.providerSessionId, this.workingDir);
14790
+ if (rebuilt) this.lastCanonicalCodexRebuildMtimeMs = transcriptMtime || Date.now();
14188
14791
  }
14189
14792
  if (!rebuilt) return false;
14190
14793
  const restoredHistory = readChatHistory(this.type, 0, Number.MAX_SAFE_INTEGER, this.providerSessionId, 0, this.provider.historyBehavior);
@@ -14203,8 +14806,17 @@ ${effect.notification.body || ""}`.trim();
14203
14806
  restorePersistedHistoryFromCurrentSession() {
14204
14807
  if (!this.providerSessionId) return;
14205
14808
  this.syncCanonicalSavedHistoryIfNeeded();
14206
- this.historyWriter.compactHistorySession(this.type, this.providerSessionId, this.provider.historyBehavior);
14207
- const restoredHistory = readChatHistory(this.type, 0, Number.MAX_SAFE_INTEGER, this.providerSessionId, 0, this.provider.historyBehavior);
14809
+ const restoredHistory = isNativeSourceCanonicalHistory(this.provider.canonicalHistory) ? readProviderChatHistory(this.type, {
14810
+ canonicalHistory: this.provider.canonicalHistory,
14811
+ historySessionId: this.providerSessionId,
14812
+ workspace: this.workingDir,
14813
+ offset: 0,
14814
+ limit: Number.MAX_SAFE_INTEGER,
14815
+ historyBehavior: this.provider.historyBehavior
14816
+ }) : (() => {
14817
+ this.historyWriter.compactHistorySession(this.type, this.providerSessionId, this.provider.historyBehavior);
14818
+ return readChatHistory(this.type, 0, Number.MAX_SAFE_INTEGER, this.providerSessionId, 0, this.provider.historyBehavior);
14819
+ })();
14208
14820
  this.historyWriter.seedSessionHistory(
14209
14821
  this.type,
14210
14822
  restoredHistory.messages,
@@ -17934,6 +18546,38 @@ var ProviderLoader = class _ProviderLoader {
17934
18546
  }
17935
18547
  };
17936
18548
 
18549
+ // src/launch/macos-app-process.ts
18550
+ function normalizeMacAppPath(appPath) {
18551
+ const trimmed = String(appPath || "").trim();
18552
+ if (!trimmed) return null;
18553
+ return trimmed.replace(/\/+$/, "");
18554
+ }
18555
+ function parsePsLine(line) {
18556
+ const match = line.match(/^\s*(\d+)\s+(.+)$/);
18557
+ if (!match) return null;
18558
+ const pid = Number.parseInt(match[1], 10);
18559
+ if (!Number.isFinite(pid)) return null;
18560
+ return { pid, args: match[2] };
18561
+ }
18562
+ function isMacAppProcessArgs(args, appPath) {
18563
+ const normalized = normalizeMacAppPath(appPath);
18564
+ if (!normalized) return false;
18565
+ return String(args || "").startsWith(`${normalized}/`);
18566
+ }
18567
+ function findMacAppProcessPids(psOutput, appPaths) {
18568
+ const normalizedPaths = appPaths.map(normalizeMacAppPath).filter((value) => !!value);
18569
+ if (normalizedPaths.length === 0) return [];
18570
+ const pids = [];
18571
+ for (const line of String(psOutput || "").split(/\r?\n/)) {
18572
+ const parsed = parsePsLine(line);
18573
+ if (!parsed) continue;
18574
+ if (normalizedPaths.some((appPath) => isMacAppProcessArgs(parsed.args, appPath))) {
18575
+ pids.push(parsed.pid);
18576
+ }
18577
+ }
18578
+ return pids;
18579
+ }
18580
+
17937
18581
  // src/launch.ts
17938
18582
  var _providerLoader = null;
17939
18583
  function getProviderLoader() {
@@ -17970,6 +18614,35 @@ function getCdpStartupTimeoutMs(ideId) {
17970
18614
  function escapeForAppleScript(value) {
17971
18615
  return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
17972
18616
  }
18617
+ function getIdePathCandidates(ideId) {
18618
+ return getProviderLoader().getIdePathCandidates(ideId);
18619
+ }
18620
+ function getMacAppProcessPids(ideId) {
18621
+ const appPaths = getIdePathCandidates(ideId);
18622
+ if (appPaths.length === 0) return [];
18623
+ try {
18624
+ const output = (0, import_child_process7.execSync)("ps axww -o pid=,args=", {
18625
+ encoding: "utf-8",
18626
+ timeout: 3e3,
18627
+ stdio: ["pipe", "pipe", "pipe"]
18628
+ });
18629
+ return findMacAppProcessPids(output, appPaths);
18630
+ } catch {
18631
+ return [];
18632
+ }
18633
+ }
18634
+ function killMacAppPathProcesses(ideId, signal) {
18635
+ const pids = getMacAppProcessPids(ideId);
18636
+ let signalled = false;
18637
+ for (const pid of pids) {
18638
+ try {
18639
+ process.kill(pid, signal);
18640
+ signalled = true;
18641
+ } catch {
18642
+ }
18643
+ }
18644
+ return signalled;
18645
+ }
17973
18646
  async function findFreePort(ports) {
17974
18647
  for (const port2 of ports) {
17975
18648
  const free = await checkPortFree(port2);
@@ -18031,6 +18704,7 @@ async function killIdeProcess(ideId) {
18031
18704
  } catch {
18032
18705
  }
18033
18706
  }
18707
+ killMacAppPathProcesses(ideId, "SIGTERM");
18034
18708
  } else if (plat === "win32" && winProcesses) {
18035
18709
  for (const proc of winProcesses) {
18036
18710
  try {
@@ -18060,6 +18734,7 @@ async function killIdeProcess(ideId) {
18060
18734
  (0, import_child_process7.execSync)(`pkill -9 -x "${appName}" 2>/dev/null`, { timeout: 5e3 });
18061
18735
  } catch {
18062
18736
  }
18737
+ killMacAppPathProcesses(ideId, "SIGKILL");
18063
18738
  } else if (plat === "win32" && winProcesses) {
18064
18739
  for (const proc of winProcesses) {
18065
18740
  try {
@@ -18079,14 +18754,16 @@ function isIdeRunning(ideId) {
18079
18754
  try {
18080
18755
  if (plat === "darwin") {
18081
18756
  const appName = getMacAppIdentifiers()[ideId];
18082
- if (!appName) return false;
18757
+ if (!appName) return getMacAppProcessPids(ideId).length > 0;
18083
18758
  try {
18084
18759
  const result = (0, import_child_process7.execSync)(`pgrep -x "${appName}" 2>/dev/null`, {
18085
18760
  encoding: "utf-8",
18086
18761
  timeout: 3e3
18087
18762
  });
18088
- return result.trim().length > 0;
18763
+ if (result.trim().length > 0) return true;
18089
18764
  } catch {
18765
+ }
18766
+ try {
18090
18767
  const result = (0, import_child_process7.execSync)(
18091
18768
  `osascript -e 'tell application "System Events" to count (every process whose name is "${escapeForAppleScript(appName)}")'`,
18092
18769
  {
@@ -18095,8 +18772,10 @@ function isIdeRunning(ideId) {
18095
18772
  stdio: ["pipe", "pipe", "pipe"]
18096
18773
  }
18097
18774
  );
18098
- return Number.parseInt(result.trim() || "0", 10) > 0;
18775
+ if (Number.parseInt(result.trim() || "0", 10) > 0) return true;
18776
+ } catch {
18099
18777
  }
18778
+ return getMacAppProcessPids(ideId).length > 0;
18100
18779
  } else if (plat === "win32") {
18101
18780
  const winProcesses = getWinProcessNames()[ideId];
18102
18781
  if (!winProcesses) return false;
@@ -19463,13 +20142,18 @@ var DaemonCommandRouter = class {
19463
20142
  const wantsAll = args?.all === true;
19464
20143
  const offset = wantsAll ? 0 : Math.max(0, Number(args?.offset) || 0);
19465
20144
  const limit = wantsAll ? Number.MAX_SAFE_INTEGER : Math.max(1, Math.min(100, Number(args?.limit) || 30));
19466
- const { sessions: historySessions, hasMore } = listSavedHistorySessions(providerType, { offset, limit });
20145
+ const providerMeta = this.deps.providerLoader.getMeta(providerType);
20146
+ const { sessions: historySessions, hasMore, source } = listProviderHistorySessions(providerType, {
20147
+ canonicalHistory: providerMeta?.canonicalHistory,
20148
+ offset,
20149
+ limit,
20150
+ historyBehavior: providerMeta?.historyBehavior
20151
+ });
19467
20152
  const state = loadState();
19468
20153
  const savedSessions = getSavedProviderSessions(state, { providerType, kind });
19469
20154
  const recentSessions = getRecentActivity(state, 200).filter((entry) => entry.providerType === providerType && entry.kind === kind && entry.providerSessionId);
19470
20155
  const savedSessionById = new Map(savedSessions.map((entry) => [entry.providerSessionId, entry]));
19471
20156
  const recentSessionById = new Map(recentSessions.map((entry) => [entry.providerSessionId, entry]));
19472
- const providerMeta = this.deps.providerLoader.getMeta(providerType);
19473
20157
  const canResumeById = supportsExplicitSessionResume(providerMeta?.resume);
19474
20158
  return {
19475
20159
  success: true,
@@ -19492,7 +20176,8 @@ var DaemonCommandRouter = class {
19492
20176
  canResume: !!(saved?.workspace || recent?.workspace || session.workspace) && canResumeById
19493
20177
  };
19494
20178
  }),
19495
- hasMore
20179
+ hasMore,
20180
+ source
19496
20181
  };
19497
20182
  }
19498
20183
  // ─── restart_session: IDE / CLI / ACP unified ───