@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.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;
@@ -2055,7 +2057,9 @@ var provider_cli_adapter_exports = {};
2055
2057
  __export(provider_cli_adapter_exports, {
2056
2058
  ProviderCliAdapter: () => ProviderCliAdapter,
2057
2059
  appendBoundedText: () => appendBoundedText,
2058
- normalizeCliProviderForRuntime: () => normalizeCliProviderForRuntime
2060
+ normalizeCliProviderForRuntime: () => normalizeCliProviderForRuntime,
2061
+ sanitizeCliStandardMessageContent: () => sanitizeCliStandardMessageContent,
2062
+ trimLastAssistantEchoForCliMessages: () => trimLastAssistantEchoForCliMessages
2059
2063
  });
2060
2064
  import * as os10 from "os";
2061
2065
  function normalizeComparableTranscriptText(value) {
@@ -2096,7 +2100,76 @@ function appendBoundedText(current, chunk, maxChars) {
2096
2100
  if (current.length <= keepFromCurrent) return current + chunk;
2097
2101
  return current.slice(-keepFromCurrent) + chunk;
2098
2102
  }
2099
- var ProviderCliAdapter;
2103
+ function isLikelyCommittedActivityPrefixContinuation(line) {
2104
+ const trimmed = String(line || "").trim();
2105
+ if (!trimmed) return false;
2106
+ if (COMMITTED_ACTIVITY_PREFIX_BLOCK_RE.test(trimmed)) return false;
2107
+ if (/\s/.test(trimmed)) return false;
2108
+ if (/[가-힣]/.test(trimmed)) return false;
2109
+ if (trimmed.length > 96) return false;
2110
+ return /^[A-Za-z0-9_./:@+%=-]+$/.test(trimmed);
2111
+ }
2112
+ function parseCommittedActivityPrefixBlock(lines, index) {
2113
+ const first = String(lines[index] || "").trim();
2114
+ if (!COMMITTED_ACTIVITY_PREFIX_BLOCK_RE.test(first)) return null;
2115
+ const parts = [first];
2116
+ let nextIndex = index + 1;
2117
+ while (nextIndex < lines.length && isLikelyCommittedActivityPrefixContinuation(lines[nextIndex])) {
2118
+ parts.push(String(lines[nextIndex] || "").trim());
2119
+ nextIndex += 1;
2120
+ }
2121
+ return { label: parts.join(""), nextIndex };
2122
+ }
2123
+ function sanitizeCliStandardMessageContent(content) {
2124
+ const source = String(content || "").trim();
2125
+ if (!source) return "";
2126
+ const lines = source.split(/\r?\n/);
2127
+ if (lines.length < 4) return source;
2128
+ const counts = /* @__PURE__ */ new Map();
2129
+ for (let index = 0; index < lines.length; index += 1) {
2130
+ const block = parseCommittedActivityPrefixBlock(lines, index);
2131
+ if (!block) continue;
2132
+ counts.set(block.label, (counts.get(block.label) || 0) + 1);
2133
+ index = block.nextIndex - 1;
2134
+ }
2135
+ const repeatedLabels = new Set(
2136
+ Array.from(counts.entries()).filter(([, count]) => count >= 3).map(([label]) => label)
2137
+ );
2138
+ if (repeatedLabels.size === 0) return source;
2139
+ const stripped = [];
2140
+ let removed = 0;
2141
+ for (let index = 0; index < lines.length; index += 1) {
2142
+ const block = parseCommittedActivityPrefixBlock(lines, index);
2143
+ if (block && repeatedLabels.has(block.label)) {
2144
+ removed += 1;
2145
+ index = block.nextIndex - 1;
2146
+ continue;
2147
+ }
2148
+ stripped.push(lines[index]);
2149
+ }
2150
+ const next = stripped.join("\n").replace(/\n{3,}/g, "\n\n").trim();
2151
+ return removed >= 3 && next.length >= 80 ? next : source;
2152
+ }
2153
+ function sanitizeCommittedMessageForDisplay(message) {
2154
+ if (!message || message.role !== "assistant" || (message.kind || "standard") !== "standard") return message;
2155
+ const content = sanitizeCliStandardMessageContent(message.content);
2156
+ if (content === message.content) return message;
2157
+ return { ...message, content };
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
+ }
2172
+ var COMMITTED_ACTIVITY_PREFIX_BLOCK_RE, ProviderCliAdapter;
2100
2173
  var init_provider_cli_adapter = __esm({
2101
2174
  "src/cli-adapters/provider-cli-adapter.ts"() {
2102
2175
  "use strict";
@@ -2111,6 +2184,7 @@ var init_provider_cli_adapter = __esm({
2111
2184
  init_provider_cli_config();
2112
2185
  init_provider_cli_runtime();
2113
2186
  init_provider_cli_shared();
2187
+ COMMITTED_ACTIVITY_PREFIX_BLOCK_RE = /^(?:📖|💻|🔎|📚|📋|✏️|📝|🔧|🛠️|⚙️)\s+(.+)$/;
2114
2188
  ProviderCliAdapter = class _ProviderCliAdapter {
2115
2189
  constructor(provider, workingDir, extraArgs = [], transportFactory = new NodePtyTransportFactory()) {
2116
2190
  this.extraArgs = extraArgs;
@@ -2291,7 +2365,14 @@ var init_provider_cli_adapter = __esm({
2291
2365
  }
2292
2366
  return null;
2293
2367
  }
2368
+ providerOwnsTranscript() {
2369
+ return this.provider.transcriptAuthority === "provider";
2370
+ }
2371
+ shouldUseFullProviderTranscriptContext() {
2372
+ return this.providerOwnsTranscript() && this.provider.transcriptContext === "full";
2373
+ }
2294
2374
  selectParseBaseMessages(baseMessages) {
2375
+ if (this.shouldUseFullProviderTranscriptContext()) return baseMessages;
2295
2376
  if (baseMessages.length <= _ProviderCliAdapter.PARSE_MESSAGE_TAIL_LIMIT) return baseMessages;
2296
2377
  return baseMessages.slice(-_ProviderCliAdapter.PARSE_MESSAGE_TAIL_LIMIT);
2297
2378
  }
@@ -2322,7 +2403,10 @@ var init_provider_cli_adapter = __esm({
2322
2403
  const tailFirst = parseBaseMessages[0];
2323
2404
  if (tailFirst && this.messagesComparable(parsedFirst, tailFirst)) {
2324
2405
  const prefixLength = fullBaseMessages.length - parseBaseMessages.length;
2325
- return [...fullBaseMessages.slice(0, prefixLength), ...parsedMessages];
2406
+ const prefix = fullBaseMessages.slice(0, prefixLength);
2407
+ const shouldSanitizePrefix = !!this.currentTurnScope || this.currentStatus !== "idle" || !!this.activeModal;
2408
+ const nextPrefix = shouldSanitizePrefix ? prefix.map((message) => sanitizeCommittedMessageForDisplay(message)) : prefix;
2409
+ return [...nextPrefix, ...parsedMessages];
2326
2410
  }
2327
2411
  return [...fullBaseMessages, ...parsedMessages];
2328
2412
  }
@@ -2771,9 +2855,7 @@ var init_provider_cli_adapter = __esm({
2771
2855
  );
2772
2856
  }
2773
2857
  trimLastAssistantEcho(messages, prompt) {
2774
- if (!prompt) return;
2775
- const last = [...messages].reverse().find((m) => m.role === "assistant" && typeof m.content === "string");
2776
- if (last) last.content = trimPromptEchoPrefix(last.content, prompt);
2858
+ trimLastAssistantEchoForCliMessages(messages, prompt);
2777
2859
  }
2778
2860
  clearAllTimers() {
2779
2861
  if (this.responseTimeout) {
@@ -3521,10 +3603,12 @@ var init_provider_cli_adapter = __esm({
3521
3603
  }
3522
3604
  buildCommittedChatMessages() {
3523
3605
  return this.committedMessages.map((message, index) => {
3524
- const contentValue = message.content;
3606
+ const rawContentValue = message.content;
3607
+ const rawContent = typeof rawContentValue === "string" ? rawContentValue : String(rawContentValue || "");
3608
+ const content = message.role === "assistant" && (message.kind || "standard") === "standard" ? sanitizeCliStandardMessageContent(rawContent) : rawContent;
3525
3609
  return buildChatMessage({
3526
3610
  role: message.role,
3527
- content: typeof contentValue === "string" ? contentValue : String(contentValue || ""),
3611
+ content,
3528
3612
  timestamp: message.timestamp,
3529
3613
  kind: message.kind,
3530
3614
  meta: message.meta,
@@ -3625,7 +3709,8 @@ var init_provider_cli_adapter = __esm({
3625
3709
  title: parsed.title || this.cliName,
3626
3710
  messages: hydratedMessages,
3627
3711
  activeModal: parsed.activeModal ?? this.activeModal,
3628
- 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" } : {}
3629
3714
  };
3630
3715
  } else {
3631
3716
  const messages = [...this.committedMessages];
@@ -7809,6 +7894,27 @@ var ChatHistoryWriter = class {
7809
7894
  return name.replace(/[^a-zA-Z0-9_-]/g, "_");
7810
7895
  }
7811
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
+ }
7812
7918
  function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0, historyBehavior) {
7813
7919
  try {
7814
7920
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
@@ -7834,25 +7940,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, ex
7834
7940
  }
7835
7941
  }
7836
7942
  }
7837
- allMessages.sort((a, b) => a.receivedAt - b.receivedAt);
7838
- const chronological = [];
7839
- let lastTurn = null;
7840
- for (const message of allMessages) {
7841
- const previous = chronological[chronological.length - 1];
7842
- if (isAdjacentHistoryDuplicate(agentType, previous, message)) continue;
7843
- if (message.role !== "system" && isAdjacentHistoryDuplicate(agentType, lastTurn, message)) continue;
7844
- chronological.push(message);
7845
- if (message.role !== "system") lastTurn = message;
7846
- }
7847
- const collapsed = collapseReplayAssistantTurns(chronological, historyBehavior);
7848
- const boundedLimit = Math.max(1, limit);
7849
- const boundedOffset = Math.max(0, offset);
7850
- const boundedExclude = Math.max(0, Math.min(excludeRecentCount, collapsed.length));
7851
- const endExclusive = Math.max(0, collapsed.length - boundedExclude - boundedOffset);
7852
- const startInclusive = Math.max(0, endExclusive - boundedLimit);
7853
- const sliced = collapsed.slice(startInclusive, endExclusive);
7854
- const hasMore = startInclusive > 0;
7855
- return { messages: sliced, hasMore };
7943
+ return pageHistoryRecords(agentType, allMessages, offset, limit, excludeRecentCount, historyBehavior);
7856
7944
  } catch {
7857
7945
  return { messages: [], hasMore: false };
7858
7946
  }
@@ -7987,6 +8075,52 @@ function rewriteCanonicalSavedHistory(agentType, historySessionId, records) {
7987
8075
  return false;
7988
8076
  }
7989
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
+ }
7990
8124
  function rebuildHermesSavedHistoryFromCanonicalSession(historySessionId) {
7991
8125
  const normalizedSessionId = normalizeSavedHistorySessionId(historySessionId);
7992
8126
  if (!normalizedSessionId) return false;
@@ -8136,6 +8270,77 @@ function extractClaudeUserContentParts(content) {
8136
8270
  }
8137
8271
  return parts;
8138
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
+ }
8139
8344
  function rebuildClaudeSavedHistoryFromNativeProject(historySessionId, workspace) {
8140
8345
  const normalizedSessionId = normalizeSavedHistorySessionId(historySessionId);
8141
8346
  if (!normalizedSessionId) return false;
@@ -8214,6 +8419,352 @@ function rebuildClaudeSavedHistoryFromNativeProject(historySessionId, workspace)
8214
8419
  return false;
8215
8420
  }
8216
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
+ }
8217
8768
 
8218
8769
  // src/providers/provider-patch-state.ts
8219
8770
  function isControlValue(value) {
@@ -10827,7 +11378,16 @@ async function handleChatHistory(h, args) {
10827
11378
  const visibleCount = Array.isArray(status?.messages) ? status.messages.length : 0;
10828
11379
  if (visibleCount > excludeRecentCount) excludeRecentCount = visibleCount;
10829
11380
  }
10830
- 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
+ });
10831
11391
  return { success: true, ...result, agent: agentStr };
10832
11392
  } catch (e) {
10833
11393
  return { success: false, error: e.message };
@@ -10852,7 +11412,8 @@ async function handleReadChat(h, args) {
10852
11412
  }
10853
11413
  const parsedRecord = parsedStatus && typeof parsedStatus === "object" ? parsedStatus : null;
10854
11414
  const adapterStatus = adapter.getStatus();
10855
- 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;
10856
11417
  const parsedShowsApproval = hasNonEmptyModalButtons(parsedRecord?.activeModal) && parsedRecord?.status === "waiting_approval";
10857
11418
  const status = parsedRecord ? {
10858
11419
  ...parsedRecord,
@@ -10862,6 +11423,8 @@ async function handleReadChat(h, args) {
10862
11423
  } : adapterStatus;
10863
11424
  const title = typeof parsedRecord?.title === "string" ? parsedRecord.title : void 0;
10864
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;
10865
11428
  if (status) {
10866
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}`);
10867
11430
  return buildReadChatCommandResult({
@@ -10880,7 +11443,9 @@ async function handleReadChat(h, args) {
10880
11443
  returnedMsgCount: Array.isArray(status.messages) ? status.messages.length : 0
10881
11444
  },
10882
11445
  ...title ? { title } : {},
10883
- ...providerSessionId ? { providerSessionId } : {}
11446
+ ...providerSessionId ? { providerSessionId } : {},
11447
+ ...transcriptAuthority ? { transcriptAuthority } : {},
11448
+ ...coverage ? { coverage } : {}
10884
11449
  }, args);
10885
11450
  }
10886
11451
  }
@@ -13300,6 +13865,8 @@ var CliProviderInstance = class {
13300
13865
  lastCanonicalHermesWatchPath = void 0;
13301
13866
  lastCanonicalClaudeRebuildMtimeMs = 0;
13302
13867
  lastCanonicalClaudeCheckAt = 0;
13868
+ lastCanonicalCodexRebuildMtimeMs = 0;
13869
+ lastCanonicalCodexCheckAt = 0;
13303
13870
  cachedSqliteDb = null;
13304
13871
  cachedSqliteDbPath = null;
13305
13872
  cachedSqliteDbMissingUntil = 0;
@@ -13999,6 +14566,25 @@ ${effect.notification.body || ""}`.trim();
13999
14566
  if (!this.providerSessionId) return false;
14000
14567
  const canonicalHistory = this.provider.canonicalHistory;
14001
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
+ }
14002
14588
  try {
14003
14589
  let rebuilt = false;
14004
14590
  if (canonicalHistory.format === "hermes-json") {
@@ -14032,6 +14618,23 @@ ${effect.notification.body || ""}`.trim();
14032
14618
  if (transcriptMtime > 0 && transcriptMtime <= this.lastCanonicalClaudeRebuildMtimeMs) return true;
14033
14619
  rebuilt = rebuildClaudeSavedHistoryFromNativeProject(this.providerSessionId, this.workingDir);
14034
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();
14035
14638
  }
14036
14639
  if (!rebuilt) return false;
14037
14640
  const restoredHistory = readChatHistory(this.type, 0, Number.MAX_SAFE_INTEGER, this.providerSessionId, 0, this.provider.historyBehavior);
@@ -14050,8 +14653,17 @@ ${effect.notification.body || ""}`.trim();
14050
14653
  restorePersistedHistoryFromCurrentSession() {
14051
14654
  if (!this.providerSessionId) return;
14052
14655
  this.syncCanonicalSavedHistoryIfNeeded();
14053
- this.historyWriter.compactHistorySession(this.type, this.providerSessionId, this.provider.historyBehavior);
14054
- 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
+ })();
14055
14667
  this.historyWriter.seedSessionHistory(
14056
14668
  this.type,
14057
14669
  restoredHistory.messages,
@@ -17786,6 +18398,38 @@ var ProviderLoader = class _ProviderLoader {
17786
18398
  }
17787
18399
  };
17788
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
+
17789
18433
  // src/launch.ts
17790
18434
  var _providerLoader = null;
17791
18435
  function getProviderLoader() {
@@ -17822,6 +18466,35 @@ function getCdpStartupTimeoutMs(ideId) {
17822
18466
  function escapeForAppleScript(value) {
17823
18467
  return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
17824
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
+ }
17825
18498
  async function findFreePort(ports) {
17826
18499
  for (const port2 of ports) {
17827
18500
  const free = await checkPortFree(port2);
@@ -17883,6 +18556,7 @@ async function killIdeProcess(ideId) {
17883
18556
  } catch {
17884
18557
  }
17885
18558
  }
18559
+ killMacAppPathProcesses(ideId, "SIGTERM");
17886
18560
  } else if (plat === "win32" && winProcesses) {
17887
18561
  for (const proc of winProcesses) {
17888
18562
  try {
@@ -17912,6 +18586,7 @@ async function killIdeProcess(ideId) {
17912
18586
  execSync4(`pkill -9 -x "${appName}" 2>/dev/null`, { timeout: 5e3 });
17913
18587
  } catch {
17914
18588
  }
18589
+ killMacAppPathProcesses(ideId, "SIGKILL");
17915
18590
  } else if (plat === "win32" && winProcesses) {
17916
18591
  for (const proc of winProcesses) {
17917
18592
  try {
@@ -17931,14 +18606,16 @@ function isIdeRunning(ideId) {
17931
18606
  try {
17932
18607
  if (plat === "darwin") {
17933
18608
  const appName = getMacAppIdentifiers()[ideId];
17934
- if (!appName) return false;
18609
+ if (!appName) return getMacAppProcessPids(ideId).length > 0;
17935
18610
  try {
17936
18611
  const result = execSync4(`pgrep -x "${appName}" 2>/dev/null`, {
17937
18612
  encoding: "utf-8",
17938
18613
  timeout: 3e3
17939
18614
  });
17940
- return result.trim().length > 0;
18615
+ if (result.trim().length > 0) return true;
17941
18616
  } catch {
18617
+ }
18618
+ try {
17942
18619
  const result = execSync4(
17943
18620
  `osascript -e 'tell application "System Events" to count (every process whose name is "${escapeForAppleScript(appName)}")'`,
17944
18621
  {
@@ -17947,8 +18624,10 @@ function isIdeRunning(ideId) {
17947
18624
  stdio: ["pipe", "pipe", "pipe"]
17948
18625
  }
17949
18626
  );
17950
- return Number.parseInt(result.trim() || "0", 10) > 0;
18627
+ if (Number.parseInt(result.trim() || "0", 10) > 0) return true;
18628
+ } catch {
17951
18629
  }
18630
+ return getMacAppProcessPids(ideId).length > 0;
17952
18631
  } else if (plat === "win32") {
17953
18632
  const winProcesses = getWinProcessNames()[ideId];
17954
18633
  if (!winProcesses) return false;
@@ -19315,13 +19994,18 @@ var DaemonCommandRouter = class {
19315
19994
  const wantsAll = args?.all === true;
19316
19995
  const offset = wantsAll ? 0 : Math.max(0, Number(args?.offset) || 0);
19317
19996
  const limit = wantsAll ? Number.MAX_SAFE_INTEGER : Math.max(1, Math.min(100, Number(args?.limit) || 30));
19318
- 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
+ });
19319
20004
  const state = loadState();
19320
20005
  const savedSessions = getSavedProviderSessions(state, { providerType, kind });
19321
20006
  const recentSessions = getRecentActivity(state, 200).filter((entry) => entry.providerType === providerType && entry.kind === kind && entry.providerSessionId);
19322
20007
  const savedSessionById = new Map(savedSessions.map((entry) => [entry.providerSessionId, entry]));
19323
20008
  const recentSessionById = new Map(recentSessions.map((entry) => [entry.providerSessionId, entry]));
19324
- const providerMeta = this.deps.providerLoader.getMeta(providerType);
19325
20009
  const canResumeById = supportsExplicitSessionResume(providerMeta?.resume);
19326
20010
  return {
19327
20011
  success: true,
@@ -19344,7 +20028,8 @@ var DaemonCommandRouter = class {
19344
20028
  canResume: !!(saved?.workspace || recent?.workspace || session.workspace) && canResumeById
19345
20029
  };
19346
20030
  }),
19347
- hasMore
20031
+ hasMore,
20032
+ source
19348
20033
  };
19349
20034
  }
19350
20035
  // ─── restart_session: IDE / CLI / ACP unified ───