@adhdev/daemon-core 0.9.44 → 0.9.46

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -980,6 +980,8 @@ function validateReadChatResultPayload(raw, source = "read_chat") {
980
980
  if (raw.summaryMetadata !== void 0) normalized.summaryMetadata = raw.summaryMetadata;
981
981
  if (Array.isArray(raw.effects)) normalized.effects = raw.effects;
982
982
  if (typeof raw.providerSessionId === "string") normalized.providerSessionId = raw.providerSessionId;
983
+ if (raw.transcriptAuthority === "provider" || raw.transcriptAuthority === "daemon") normalized.transcriptAuthority = raw.transcriptAuthority;
984
+ if (raw.coverage === "full" || raw.coverage === "tail" || raw.coverage === "current-turn") normalized.coverage = raw.coverage;
983
985
  return normalized;
984
986
  }
985
987
  var VALID_STATUSES, VALID_ROLES, VALID_BUBBLE_STATES, VALID_TURN_STATUSES;
@@ -2056,7 +2058,8 @@ __export(provider_cli_adapter_exports, {
2056
2058
  ProviderCliAdapter: () => ProviderCliAdapter,
2057
2059
  appendBoundedText: () => appendBoundedText,
2058
2060
  normalizeCliProviderForRuntime: () => normalizeCliProviderForRuntime,
2059
- sanitizeCliStandardMessageContent: () => sanitizeCliStandardMessageContent
2061
+ sanitizeCliStandardMessageContent: () => sanitizeCliStandardMessageContent,
2062
+ trimLastAssistantEchoForCliMessages: () => trimLastAssistantEchoForCliMessages
2060
2063
  });
2061
2064
  import * as os10 from "os";
2062
2065
  function normalizeComparableTranscriptText(value) {
@@ -2153,6 +2156,19 @@ function sanitizeCommittedMessageForDisplay(message) {
2153
2156
  if (content === message.content) return message;
2154
2157
  return { ...message, content };
2155
2158
  }
2159
+ function trimLastAssistantEchoForCliMessages(messages, prompt) {
2160
+ if (!prompt) return;
2161
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
2162
+ const message = messages[index];
2163
+ if (!message || message.role !== "assistant" || typeof message.content !== "string") continue;
2164
+ if ((message.kind || "standard") !== "standard") continue;
2165
+ message.content = trimPromptEchoPrefix(message.content, prompt);
2166
+ if (!message.content.trim()) {
2167
+ messages.splice(index, 1);
2168
+ }
2169
+ return;
2170
+ }
2171
+ }
2156
2172
  var COMMITTED_ACTIVITY_PREFIX_BLOCK_RE, ProviderCliAdapter;
2157
2173
  var init_provider_cli_adapter = __esm({
2158
2174
  "src/cli-adapters/provider-cli-adapter.ts"() {
@@ -2349,7 +2365,14 @@ var init_provider_cli_adapter = __esm({
2349
2365
  }
2350
2366
  return null;
2351
2367
  }
2368
+ providerOwnsTranscript() {
2369
+ return this.provider.transcriptAuthority === "provider";
2370
+ }
2371
+ shouldUseFullProviderTranscriptContext() {
2372
+ return this.providerOwnsTranscript() && this.provider.transcriptContext === "full";
2373
+ }
2352
2374
  selectParseBaseMessages(baseMessages) {
2375
+ if (this.shouldUseFullProviderTranscriptContext()) return baseMessages;
2353
2376
  if (baseMessages.length <= _ProviderCliAdapter.PARSE_MESSAGE_TAIL_LIMIT) return baseMessages;
2354
2377
  return baseMessages.slice(-_ProviderCliAdapter.PARSE_MESSAGE_TAIL_LIMIT);
2355
2378
  }
@@ -2832,9 +2855,7 @@ var init_provider_cli_adapter = __esm({
2832
2855
  );
2833
2856
  }
2834
2857
  trimLastAssistantEcho(messages, prompt) {
2835
- if (!prompt) return;
2836
- const last = [...messages].reverse().find((m) => m.role === "assistant" && typeof m.content === "string");
2837
- if (last) last.content = trimPromptEchoPrefix(last.content, prompt);
2858
+ trimLastAssistantEchoForCliMessages(messages, prompt);
2838
2859
  }
2839
2860
  clearAllTimers() {
2840
2861
  if (this.responseTimeout) {
@@ -3688,7 +3709,8 @@ var init_provider_cli_adapter = __esm({
3688
3709
  title: parsed.title || this.cliName,
3689
3710
  messages: hydratedMessages,
3690
3711
  activeModal: parsed.activeModal ?? this.activeModal,
3691
- providerSessionId: typeof parsed.providerSessionId === "string" ? parsed.providerSessionId : void 0
3712
+ providerSessionId: typeof parsed.providerSessionId === "string" ? parsed.providerSessionId : void 0,
3713
+ ...this.providerOwnsTranscript() ? { transcriptAuthority: "provider", coverage: this.shouldUseFullProviderTranscriptContext() ? "full" : "tail" } : {}
3692
3714
  };
3693
3715
  } else {
3694
3716
  const messages = [...this.committedMessages];
@@ -7872,6 +7894,27 @@ var ChatHistoryWriter = class {
7872
7894
  return name.replace(/[^a-zA-Z0-9_-]/g, "_");
7873
7895
  }
7874
7896
  };
7897
+ function pageHistoryRecords(agentType, records, offset = 0, limit = 30, excludeRecentCount = 0, historyBehavior) {
7898
+ const allMessages = records.map((message) => sanitizeHistoryMessage(agentType, message)).filter(Boolean);
7899
+ allMessages.sort((a, b) => a.receivedAt - b.receivedAt);
7900
+ const chronological = [];
7901
+ let lastTurn = null;
7902
+ for (const message of allMessages) {
7903
+ const previous = chronological[chronological.length - 1];
7904
+ if (isAdjacentHistoryDuplicate(agentType, previous, message)) continue;
7905
+ if (message.role !== "system" && isAdjacentHistoryDuplicate(agentType, lastTurn, message)) continue;
7906
+ chronological.push(message);
7907
+ if (message.role !== "system") lastTurn = message;
7908
+ }
7909
+ const collapsed = collapseReplayAssistantTurns(chronological, historyBehavior);
7910
+ const boundedLimit = Math.max(1, limit);
7911
+ const boundedOffset = Math.max(0, offset);
7912
+ const boundedExclude = Math.max(0, Math.min(excludeRecentCount, collapsed.length));
7913
+ const endExclusive = Math.max(0, collapsed.length - boundedExclude - boundedOffset);
7914
+ const startInclusive = Math.max(0, endExclusive - boundedLimit);
7915
+ const sliced = collapsed.slice(startInclusive, endExclusive);
7916
+ return { messages: sliced, hasMore: startInclusive > 0 };
7917
+ }
7875
7918
  function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0, historyBehavior) {
7876
7919
  try {
7877
7920
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
@@ -7897,25 +7940,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, ex
7897
7940
  }
7898
7941
  }
7899
7942
  }
7900
- allMessages.sort((a, b) => a.receivedAt - b.receivedAt);
7901
- const chronological = [];
7902
- let lastTurn = null;
7903
- for (const message of allMessages) {
7904
- const previous = chronological[chronological.length - 1];
7905
- if (isAdjacentHistoryDuplicate(agentType, previous, message)) continue;
7906
- if (message.role !== "system" && isAdjacentHistoryDuplicate(agentType, lastTurn, message)) continue;
7907
- chronological.push(message);
7908
- if (message.role !== "system") lastTurn = message;
7909
- }
7910
- const collapsed = collapseReplayAssistantTurns(chronological, historyBehavior);
7911
- const boundedLimit = Math.max(1, limit);
7912
- const boundedOffset = Math.max(0, offset);
7913
- const boundedExclude = Math.max(0, Math.min(excludeRecentCount, collapsed.length));
7914
- const endExclusive = Math.max(0, collapsed.length - boundedExclude - boundedOffset);
7915
- const startInclusive = Math.max(0, endExclusive - boundedLimit);
7916
- const sliced = collapsed.slice(startInclusive, endExclusive);
7917
- const hasMore = startInclusive > 0;
7918
- return { messages: sliced, hasMore };
7943
+ return pageHistoryRecords(agentType, allMessages, offset, limit, excludeRecentCount, historyBehavior);
7919
7944
  } catch {
7920
7945
  return { messages: [], hasMore: false };
7921
7946
  }
@@ -7982,29 +8007,6 @@ function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
7982
8007
  return { sessions: [], hasMore: false };
7983
8008
  }
7984
8009
  }
7985
- function normalizeCanonicalHermesMessageContent(content) {
7986
- if (typeof content === "string") return content.trim();
7987
- if (content == null) return "";
7988
- try {
7989
- return JSON.stringify(content).trim();
7990
- } catch {
7991
- return String(content).trim();
7992
- }
7993
- }
7994
- function extractCanonicalHermesMessageTimestamp(message, fallbackTs) {
7995
- const numericTimestamp = Number(message.receivedAt || message.timestamp || message.ts || 0);
7996
- if (Number.isFinite(numericTimestamp) && numericTimestamp > 0) return numericTimestamp;
7997
- const stringTimestamp = typeof message.ts === "string" ? Date.parse(message.ts) : typeof message.timestamp === "string" ? Date.parse(message.timestamp) : NaN;
7998
- if (Number.isFinite(stringTimestamp) && stringTimestamp > 0) return stringTimestamp;
7999
- return fallbackTs;
8000
- }
8001
- function extractTimestampValue(value) {
8002
- const numericTimestamp = Number(value || 0);
8003
- if (Number.isFinite(numericTimestamp) && numericTimestamp > 0) return numericTimestamp;
8004
- const stringTimestamp = typeof value === "string" ? Date.parse(value) : NaN;
8005
- if (Number.isFinite(stringTimestamp) && stringTimestamp > 0) return stringTimestamp;
8006
- return 0;
8007
- }
8008
8010
  function readExistingSessionStartRecord(agentType, historySessionId) {
8009
8011
  try {
8010
8012
  const dir = path7.join(HISTORY_DIR, agentType);
@@ -8050,232 +8052,193 @@ function rewriteCanonicalSavedHistory(agentType, historySessionId, records) {
8050
8052
  return false;
8051
8053
  }
8052
8054
  }
8053
- function rebuildHermesSavedHistoryFromCanonicalSession(historySessionId) {
8055
+ function getNativeHistoryScriptName(canonicalHistory, key) {
8056
+ const configured = canonicalHistory?.scripts?.[key];
8057
+ if (typeof configured === "string" && configured.trim()) return configured.trim();
8058
+ return key === "readSession" ? "readNativeHistory" : "listNativeHistory";
8059
+ }
8060
+ function getProviderNativeHistoryScript(scripts, canonicalHistory, key) {
8061
+ if (!canonicalHistory?.scripts) return null;
8062
+ const fn = scripts?.[getNativeHistoryScriptName(canonicalHistory, key)];
8063
+ return typeof fn === "function" ? fn : null;
8064
+ }
8065
+ function normalizeProviderNativeHistoryRecords(agentType, historySessionId, records) {
8066
+ if (!Array.isArray(records)) return [];
8067
+ const normalizedSessionId = normalizeSavedHistorySessionId(historySessionId);
8068
+ return records.map((record) => sanitizeHistoryMessage(agentType, {
8069
+ ts: typeof record?.ts === "string" ? record.ts : new Date(Number(record?.receivedAt) || Date.now()).toISOString(),
8070
+ receivedAt: Number(record?.receivedAt) || Date.parse(record?.ts || "") || Date.now(),
8071
+ role: record?.role,
8072
+ content: String(record?.content || ""),
8073
+ kind: record?.kind || (record?.role === "system" ? "session_start" : "standard"),
8074
+ senderName: record?.senderName,
8075
+ agent: agentType,
8076
+ instanceId: record?.instanceId,
8077
+ historySessionId: normalizeSavedHistorySessionId(record?.historySessionId || normalizedSessionId),
8078
+ sessionTitle: record?.sessionTitle,
8079
+ workspace: record?.workspace
8080
+ })).filter(Boolean);
8081
+ }
8082
+ function callProviderNativeHistoryRead(agentType, canonicalHistory, scripts, historySessionId, workspace) {
8083
+ const fn = getProviderNativeHistoryScript(scripts, canonicalHistory, "readSession");
8084
+ if (!fn) return null;
8085
+ const result = fn({
8086
+ agentType,
8087
+ sessionId: historySessionId,
8088
+ historySessionId,
8089
+ workspace,
8090
+ format: canonicalHistory?.format,
8091
+ watchPath: canonicalHistory?.watchPath,
8092
+ args: { sessionId: historySessionId, historySessionId, workspace }
8093
+ });
8094
+ if (!result || typeof result !== "object") return null;
8095
+ const records = normalizeProviderNativeHistoryRecords(agentType, historySessionId, result.messages || result.records);
8096
+ if (records.length === 0) return null;
8097
+ return {
8098
+ records,
8099
+ sourcePath: typeof result.sourcePath === "string" ? result.sourcePath : "",
8100
+ sourceMtimeMs: Number(result.sourceMtimeMs) || 0
8101
+ };
8102
+ }
8103
+ function buildNativeHistoryReadResult(agentType, canonicalHistory, scripts, historySessionId, workspace) {
8104
+ const normalizedSessionId = normalizeSavedHistorySessionId(historySessionId || "");
8105
+ if (!canonicalHistory || !normalizedSessionId || !isNativeSourceCanonicalHistory(canonicalHistory)) return null;
8106
+ return callProviderNativeHistoryRead(agentType, canonicalHistory, scripts, normalizedSessionId, workspace);
8107
+ }
8108
+ function materializeNativeHistoryToMirror(agentType, canonicalHistory, historySessionId, workspace, scripts) {
8054
8109
  const normalizedSessionId = normalizeSavedHistorySessionId(historySessionId);
8055
8110
  if (!normalizedSessionId) return false;
8111
+ const nativeResult = callProviderNativeHistoryRead(agentType, canonicalHistory, scripts, normalizedSessionId, workspace);
8112
+ const nativeRecords = nativeResult?.records || [];
8113
+ if (nativeRecords.length === 0) return false;
8114
+ const normalizedRecords = nativeRecords.map((record) => ({
8115
+ ...record,
8116
+ agent: agentType,
8117
+ historySessionId: normalizedSessionId
8118
+ }));
8119
+ const existingSessionStart = readExistingSessionStartRecord(agentType, normalizedSessionId);
8120
+ const records = existingSessionStart && normalizedRecords[0]?.kind !== "session_start" ? [{ ...existingSessionStart, historySessionId: normalizedSessionId, agent: agentType }, ...normalizedRecords] : normalizedRecords;
8121
+ return rewriteCanonicalSavedHistory(agentType, normalizedSessionId, records);
8122
+ }
8123
+ function materializeProviderNativeHistory(agentType, canonicalHistory, historySessionId, workspace, scripts) {
8124
+ if (!canonicalHistory || canonicalHistory.mode !== "materialized-mirror") return false;
8125
+ return materializeNativeHistoryToMirror(agentType, canonicalHistory, historySessionId, workspace, scripts);
8126
+ }
8127
+ function isNativeSourceCanonicalHistory(canonicalHistory) {
8128
+ if (!canonicalHistory) return false;
8129
+ if (canonicalHistory.mode === "disabled") return false;
8130
+ if (canonicalHistory.mode === "materialized-mirror") return false;
8131
+ return true;
8132
+ }
8133
+ function readProviderChatHistory(agentType, options = {}) {
8134
+ if (isNativeSourceCanonicalHistory(options.canonicalHistory) && options.historySessionId) {
8135
+ const nativeResult = buildNativeHistoryReadResult(agentType, options.canonicalHistory, options.scripts, options.historySessionId, options.workspace);
8136
+ if (!nativeResult) return { messages: [], hasMore: false, source: "native-unavailable" };
8137
+ return {
8138
+ ...pageHistoryRecords(agentType, nativeResult.records, options.offset || 0, options.limit || 30, options.excludeRecentCount || 0, options.historyBehavior),
8139
+ source: "provider-native",
8140
+ sourcePath: nativeResult.sourcePath,
8141
+ sourceMtimeMs: nativeResult.sourceMtimeMs
8142
+ };
8143
+ }
8144
+ return {
8145
+ ...readChatHistory(agentType, options.offset || 0, options.limit || 30, options.historySessionId, options.excludeRecentCount || 0, options.historyBehavior),
8146
+ source: "adhdev-mirror"
8147
+ };
8148
+ }
8149
+ function buildNativeSessionSummary(agentType, historySessionId, records, sourcePath) {
8150
+ const visible = pageHistoryRecords(agentType, records, 0, Number.MAX_SAFE_INTEGER).messages;
8151
+ if (visible.length === 0) return null;
8152
+ let sourceMtimeMs = 0;
8056
8153
  try {
8057
- const sessionFilePath = path7.join(os5.homedir(), ".hermes", "sessions", `session_${normalizedSessionId}.json`);
8058
- if (!fs3.existsSync(sessionFilePath)) return false;
8059
- const raw = JSON.parse(fs3.readFileSync(sessionFilePath, "utf-8"));
8060
- const canonicalMessages = Array.isArray(raw.messages) ? raw.messages : [];
8061
- const dir = path7.join(HISTORY_DIR, "hermes-cli");
8062
- fs3.mkdirSync(dir, { recursive: true });
8063
- const existingSessionStart = readExistingSessionStartRecord("hermes-cli", normalizedSessionId);
8064
- const records = [];
8065
- if (existingSessionStart) {
8066
- records.push({
8067
- ...existingSessionStart,
8068
- historySessionId: normalizedSessionId
8069
- });
8070
- }
8071
- let fallbackTs = Date.parse(raw.session_start || raw.last_updated || "") || Date.now();
8072
- for (const message of canonicalMessages) {
8073
- const role = String(message.role || "").trim();
8074
- const content = normalizeCanonicalHermesMessageContent(message.content);
8075
- if (!content) continue;
8076
- const receivedAt = extractCanonicalHermesMessageTimestamp(message, fallbackTs);
8077
- fallbackTs = receivedAt + 1;
8078
- if (role === "user") {
8079
- records.push({
8080
- ts: new Date(receivedAt).toISOString(),
8081
- receivedAt,
8082
- role: "user",
8083
- content,
8084
- kind: "standard",
8085
- agent: "hermes-cli",
8086
- historySessionId: normalizedSessionId
8087
- });
8088
- continue;
8089
- }
8090
- if (role === "assistant") {
8091
- records.push({
8092
- ts: new Date(receivedAt).toISOString(),
8093
- receivedAt,
8094
- role: "assistant",
8095
- content,
8096
- kind: "standard",
8097
- agent: "hermes-cli",
8098
- historySessionId: normalizedSessionId
8099
- });
8100
- continue;
8101
- }
8102
- if (role === "tool") {
8103
- records.push({
8104
- ts: new Date(receivedAt).toISOString(),
8105
- receivedAt,
8106
- role: "assistant",
8107
- content,
8108
- kind: "tool",
8109
- senderName: "Tool",
8110
- agent: "hermes-cli",
8111
- historySessionId: normalizedSessionId
8112
- });
8113
- }
8114
- }
8115
- return rewriteCanonicalSavedHistory("hermes-cli", normalizedSessionId, records);
8154
+ sourceMtimeMs = fs3.statSync(sourcePath).mtimeMs;
8116
8155
  } catch {
8117
- return false;
8118
8156
  }
8157
+ const firstMessageAt = visible[0]?.receivedAt || sourceMtimeMs || Date.now();
8158
+ const lastMessageAt = visible[visible.length - 1]?.receivedAt || firstMessageAt;
8159
+ const lastNonSystem = [...visible].reverse().find((message) => message.role !== "system") || visible[visible.length - 1];
8160
+ const firstSystem = visible.find((message) => message.kind === "session_start");
8161
+ return {
8162
+ historySessionId,
8163
+ sessionTitle: lastNonSystem?.content,
8164
+ messageCount: visible.length,
8165
+ firstMessageAt,
8166
+ lastMessageAt,
8167
+ preview: lastNonSystem?.content,
8168
+ workspace: firstSystem?.workspace || (firstSystem?.kind === "session_start" ? firstSystem.content : void 0),
8169
+ source: "provider-native",
8170
+ sourcePath,
8171
+ sourceMtimeMs
8172
+ };
8119
8173
  }
8120
- function resolveClaudeProjectTranscriptPath(historySessionId, workspace) {
8121
- const claudeProjectsDir = path7.join(os5.homedir(), ".claude", "projects");
8122
- if (!fs3.existsSync(claudeProjectsDir)) return null;
8123
- const normalizedWorkspace = typeof workspace === "string" ? workspace.trim() : "";
8124
- if (normalizedWorkspace) {
8125
- const directPath = path7.join(claudeProjectsDir, normalizedWorkspace.replace(/[\\/]/g, "-"), `${historySessionId}.jsonl`);
8126
- if (fs3.existsSync(directPath)) return directPath;
8127
- }
8128
- const stack = [claudeProjectsDir];
8129
- while (stack.length > 0) {
8130
- const current = stack.pop();
8131
- if (!current) continue;
8132
- for (const entry of fs3.readdirSync(current, { withFileTypes: true })) {
8133
- const entryPath = path7.join(current, entry.name);
8134
- if (entry.isDirectory()) {
8135
- stack.push(entryPath);
8136
- continue;
8137
- }
8138
- if (entry.isFile() && entry.name === `${historySessionId}.jsonl`) {
8139
- return entryPath;
8140
- }
8141
- }
8142
- }
8143
- return null;
8174
+ function normalizeProviderNativeHistorySessionSummary(agentType, item) {
8175
+ const historySessionId = normalizeSavedHistorySessionId(item?.historySessionId || item?.sessionId || "");
8176
+ if (!historySessionId) return null;
8177
+ const sourcePath = typeof item?.sourcePath === "string" ? item.sourcePath : "";
8178
+ const sourceMtimeMs = Number(item?.sourceMtimeMs) || 0;
8179
+ const firstMessageAt = Number(item?.firstMessageAt) || sourceMtimeMs || Date.now();
8180
+ const lastMessageAt = Number(item?.lastMessageAt) || firstMessageAt;
8181
+ const messageCount = Math.max(0, Number(item?.messageCount) || 0);
8182
+ return {
8183
+ historySessionId,
8184
+ sessionTitle: typeof item?.sessionTitle === "string" ? item.sessionTitle : void 0,
8185
+ messageCount,
8186
+ firstMessageAt,
8187
+ lastMessageAt,
8188
+ preview: typeof item?.preview === "string" ? item.preview : void 0,
8189
+ workspace: typeof item?.workspace === "string" ? item.workspace : void 0,
8190
+ source: "provider-native",
8191
+ sourcePath,
8192
+ sourceMtimeMs
8193
+ };
8144
8194
  }
8145
- function extractClaudeAssistantContentParts(content) {
8146
- if (typeof content === "string") {
8147
- const trimmed = content.trim();
8148
- return trimmed ? [{ content: trimmed, kind: "standard", role: "assistant" }] : [];
8149
- }
8150
- if (!Array.isArray(content)) return [];
8151
- const parts = [];
8152
- for (const block of content) {
8153
- if (!block || typeof block !== "object") continue;
8154
- const record = block;
8155
- const type = String(record.type || "").trim();
8156
- if (type === "text") {
8157
- const text = String(record.text || "").trim();
8158
- if (text) parts.push({ content: text, kind: "standard", role: "assistant" });
8195
+ function collectProviderScriptNativeHistorySessionSummaries(agentType, canonicalHistory, scripts) {
8196
+ const fn = getProviderNativeHistoryScript(scripts, canonicalHistory, "listSessions");
8197
+ if (!fn) return null;
8198
+ const result = fn({
8199
+ agentType,
8200
+ format: canonicalHistory.format,
8201
+ watchPath: canonicalHistory.watchPath,
8202
+ args: {}
8203
+ });
8204
+ if (!result || typeof result !== "object") return [];
8205
+ const sessions = Array.isArray(result.sessions) ? result.sessions : [];
8206
+ const summaries = [];
8207
+ for (const item of sessions) {
8208
+ if (Array.isArray(item?.messages || item?.records)) {
8209
+ const historySessionId = normalizeSavedHistorySessionId(item?.historySessionId || item?.sessionId || "");
8210
+ if (!historySessionId) continue;
8211
+ const records = normalizeProviderNativeHistoryRecords(agentType, historySessionId, item.messages || item.records);
8212
+ const summary2 = buildNativeSessionSummary(agentType, historySessionId, records, typeof item?.sourcePath === "string" ? item.sourcePath : "");
8213
+ if (summary2) {
8214
+ if (Number(item?.sourceMtimeMs)) summary2.sourceMtimeMs = Number(item.sourceMtimeMs);
8215
+ summaries.push(summary2);
8216
+ }
8159
8217
  continue;
8160
8218
  }
8161
- if (type === "tool_use") {
8162
- const name = String(record.name || "").trim() || "Tool";
8163
- const input = record.input && typeof record.input === "object" ? record.input : null;
8164
- const command = input ? String(input.command || "").trim() : "";
8165
- const summary = command ? `${name}: ${command}` : name;
8166
- if (summary) parts.push({ content: summary, kind: "tool", senderName: "Tool", role: "assistant" });
8167
- }
8219
+ const summary = normalizeProviderNativeHistorySessionSummary(agentType, item);
8220
+ if (summary) summaries.push(summary);
8168
8221
  }
8169
- return parts;
8222
+ return sortSavedHistorySessionSummaries(summaries);
8170
8223
  }
8171
- function extractClaudeUserContentParts(content) {
8172
- if (typeof content === "string") {
8173
- const trimmed = content.trim();
8174
- return trimmed ? [{ role: "user", content: trimmed, kind: "standard" }] : [];
8175
- }
8176
- if (!Array.isArray(content)) return [];
8177
- const parts = [];
8178
- for (const block of content) {
8179
- if (!block || typeof block !== "object") continue;
8180
- const record = block;
8181
- const type = String(record.type || "").trim();
8182
- if (type === "text") {
8183
- const text = String(record.text || "").trim();
8184
- if (text) parts.push({ role: "user", content: text, kind: "standard" });
8185
- continue;
8186
- }
8187
- if (type === "tool_result") {
8188
- const rawContent = record.content;
8189
- const text = typeof rawContent === "string" ? rawContent.trim() : Array.isArray(rawContent) ? rawContent.map((entry) => {
8190
- if (typeof entry === "string") return entry.trim();
8191
- if (!entry || typeof entry !== "object") return "";
8192
- const nested = entry;
8193
- if (typeof nested.text === "string") return nested.text.trim();
8194
- if (typeof nested.content === "string") return nested.content.trim();
8195
- return "";
8196
- }).filter(Boolean).join("\n") : "";
8197
- if (text) parts.push({ role: "assistant", content: text, kind: "tool", senderName: "Tool" });
8198
- }
8199
- }
8200
- return parts;
8224
+ function collectNativeHistorySessionSummaries(agentType, canonicalHistory, scripts) {
8225
+ return collectProviderScriptNativeHistorySessionSummaries(agentType, canonicalHistory, scripts) || [];
8201
8226
  }
8202
- function rebuildClaudeSavedHistoryFromNativeProject(historySessionId, workspace) {
8203
- const normalizedSessionId = normalizeSavedHistorySessionId(historySessionId);
8204
- if (!normalizedSessionId) return false;
8205
- try {
8206
- const transcriptPath = resolveClaudeProjectTranscriptPath(normalizedSessionId, workspace);
8207
- if (!transcriptPath) return false;
8208
- const lines = fs3.readFileSync(transcriptPath, "utf-8").split("\n").filter(Boolean);
8209
- const records = [];
8210
- const existingSessionStart = readExistingSessionStartRecord("claude-cli", normalizedSessionId);
8211
- if (existingSessionStart) {
8212
- records.push({
8213
- ...existingSessionStart,
8214
- historySessionId: normalizedSessionId
8215
- });
8216
- }
8217
- let fallbackTs = Date.now();
8218
- for (const line of lines) {
8219
- let parsed = null;
8220
- try {
8221
- parsed = JSON.parse(line);
8222
- } catch {
8223
- parsed = null;
8224
- }
8225
- if (!parsed) continue;
8226
- const parsedSessionId = String(parsed.sessionId || "").trim();
8227
- if (parsedSessionId && parsedSessionId !== normalizedSessionId) continue;
8228
- const receivedAt = extractTimestampValue(parsed.timestamp) || fallbackTs;
8229
- fallbackTs = receivedAt + 1;
8230
- const parsedWorkspace = String(parsed.cwd || workspace || "").trim();
8231
- if (records.length === 0 && parsedWorkspace) {
8232
- records.push({
8233
- ts: new Date(receivedAt).toISOString(),
8234
- receivedAt,
8235
- role: "system",
8236
- kind: "session_start",
8237
- content: parsedWorkspace,
8238
- agent: "claude-cli",
8239
- historySessionId: normalizedSessionId,
8240
- workspace: parsedWorkspace
8241
- });
8242
- }
8243
- const type = String(parsed.type || "").trim();
8244
- const message = parsed.message && typeof parsed.message === "object" ? parsed.message : null;
8245
- if (type === "user" && message) {
8246
- for (const part of extractClaudeUserContentParts(message.content)) {
8247
- records.push({
8248
- ts: new Date(receivedAt).toISOString(),
8249
- receivedAt,
8250
- role: part.role,
8251
- content: part.content,
8252
- kind: part.kind,
8253
- senderName: part.senderName,
8254
- agent: "claude-cli",
8255
- historySessionId: normalizedSessionId
8256
- });
8257
- }
8258
- continue;
8259
- }
8260
- if (type === "assistant" && message) {
8261
- for (const part of extractClaudeAssistantContentParts(message.content)) {
8262
- records.push({
8263
- ts: new Date(receivedAt).toISOString(),
8264
- receivedAt,
8265
- role: "assistant",
8266
- content: part.content,
8267
- kind: part.kind,
8268
- senderName: part.senderName,
8269
- agent: "claude-cli",
8270
- historySessionId: normalizedSessionId
8271
- });
8272
- }
8273
- }
8274
- }
8275
- return rewriteCanonicalSavedHistory("claude-cli", normalizedSessionId, records);
8276
- } catch {
8277
- return false;
8227
+ function listProviderHistorySessions(agentType, options = {}) {
8228
+ if (isNativeSourceCanonicalHistory(options.canonicalHistory)) {
8229
+ const offset = Math.max(0, options.offset || 0);
8230
+ const limit = Math.max(1, options.limit || 30);
8231
+ const summaries = collectNativeHistorySessionSummaries(agentType, options.canonicalHistory, options.scripts);
8232
+ return {
8233
+ sessions: summaries.slice(offset, offset + limit),
8234
+ hasMore: offset + limit < summaries.length,
8235
+ source: "provider-native"
8236
+ };
8278
8237
  }
8238
+ return {
8239
+ ...listSavedHistorySessions(agentType, { offset: options.offset, limit: options.limit }, options.historyBehavior),
8240
+ source: "adhdev-mirror"
8241
+ };
8279
8242
  }
8280
8243
 
8281
8244
  // src/providers/provider-patch-state.ts
@@ -10890,7 +10853,17 @@ async function handleChatHistory(h, args) {
10890
10853
  const visibleCount = Array.isArray(status?.messages) ? status.messages.length : 0;
10891
10854
  if (visibleCount > excludeRecentCount) excludeRecentCount = visibleCount;
10892
10855
  }
10893
- const result = readChatHistory(agentStr, offset || 0, limit || 30, historySessionId, excludeRecentCount);
10856
+ const workspace = typeof args?.workspace === "string" ? args.workspace : typeof h.currentSession?.workspace === "string" ? h.currentSession.workspace : void 0;
10857
+ const result = readProviderChatHistory(agentStr, {
10858
+ canonicalHistory: provider?.canonicalHistory,
10859
+ historySessionId,
10860
+ workspace,
10861
+ offset: offset || 0,
10862
+ limit: limit || 30,
10863
+ excludeRecentCount,
10864
+ historyBehavior: provider?.historyBehavior,
10865
+ scripts: provider?.scripts
10866
+ });
10894
10867
  return { success: true, ...result, agent: agentStr };
10895
10868
  } catch (e) {
10896
10869
  return { success: false, error: e.message };
@@ -10915,7 +10888,8 @@ async function handleReadChat(h, args) {
10915
10888
  }
10916
10889
  const parsedRecord = parsedStatus && typeof parsedStatus === "object" ? parsedStatus : null;
10917
10890
  const adapterStatus = adapter.getStatus();
10918
- const shouldPreferAdapterMessages = Array.isArray(adapterStatus.messages) && adapterStatus.messages.length > 0 && Array.isArray(parsedRecord?.messages) && adapterStatus.messages.length > parsedRecord.messages.length;
10891
+ const parsedIsProviderAuthoritative = parsedRecord?.transcriptAuthority === "provider" || parsedRecord?.coverage === "full";
10892
+ const shouldPreferAdapterMessages = !parsedIsProviderAuthoritative && Array.isArray(adapterStatus.messages) && adapterStatus.messages.length > 0 && Array.isArray(parsedRecord?.messages) && adapterStatus.messages.length > parsedRecord.messages.length;
10919
10893
  const parsedShowsApproval = hasNonEmptyModalButtons(parsedRecord?.activeModal) && parsedRecord?.status === "waiting_approval";
10920
10894
  const status = parsedRecord ? {
10921
10895
  ...parsedRecord,
@@ -10925,6 +10899,8 @@ async function handleReadChat(h, args) {
10925
10899
  } : adapterStatus;
10926
10900
  const title = typeof parsedRecord?.title === "string" ? parsedRecord.title : void 0;
10927
10901
  const providerSessionId = typeof parsedRecord?.providerSessionId === "string" ? parsedRecord.providerSessionId : void 0;
10902
+ const transcriptAuthority = parsedRecord?.transcriptAuthority === "provider" || parsedRecord?.transcriptAuthority === "daemon" ? parsedRecord.transcriptAuthority : void 0;
10903
+ const coverage = parsedRecord?.coverage === "full" || parsedRecord?.coverage === "tail" || parsedRecord?.coverage === "current-turn" ? parsedRecord.coverage : void 0;
10928
10904
  if (status) {
10929
10905
  LOG.debug("Command", `[read_chat] cli-like resolved provider=${adapter.cliType} target=${String(args?.targetSessionId || "")} adapterStatus=${String(adapterStatus.status || "")} parsedStatus=${String(parsedRecord?.status || "")} shouldPreferAdapterMessages=${String(shouldPreferAdapterMessages)} adapterMsgCount=${Array.isArray(adapterStatus.messages) ? adapterStatus.messages.length : 0} parsedMsgCount=${Array.isArray(parsedRecord?.messages) ? parsedRecord.messages.length : 0} returnedMsgCount=${Array.isArray(status.messages) ? status.messages.length : 0}`);
10930
10906
  return buildReadChatCommandResult({
@@ -10943,7 +10919,9 @@ async function handleReadChat(h, args) {
10943
10919
  returnedMsgCount: Array.isArray(status.messages) ? status.messages.length : 0
10944
10920
  },
10945
10921
  ...title ? { title } : {},
10946
- ...providerSessionId ? { providerSessionId } : {}
10922
+ ...providerSessionId ? { providerSessionId } : {},
10923
+ ...transcriptAuthority ? { transcriptAuthority } : {},
10924
+ ...coverage ? { coverage } : {}
10947
10925
  }, args);
10948
10926
  }
10949
10927
  }
@@ -13358,11 +13336,8 @@ var CliProviderInstance = class {
13358
13336
  historyWriter;
13359
13337
  runtimeMessages = [];
13360
13338
  lastPersistedHistoryMessages = [];
13361
- lastCanonicalHermesSyncMtimeMs = 0;
13362
- lastCanonicalHermesExistCheckAt = 0;
13363
- lastCanonicalHermesWatchPath = void 0;
13364
- lastCanonicalClaudeRebuildMtimeMs = 0;
13365
- lastCanonicalClaudeCheckAt = 0;
13339
+ lastNativeSourceCanonicalCheckAt = 0;
13340
+ lastNativeSourceCanonicalCacheKey = void 0;
13366
13341
  cachedSqliteDb = null;
13367
13342
  cachedSqliteDbPath = null;
13368
13343
  cachedSqliteDbMissingUntil = 0;
@@ -14062,41 +14037,45 @@ ${effect.notification.body || ""}`.trim();
14062
14037
  if (!this.providerSessionId) return false;
14063
14038
  const canonicalHistory = this.provider.canonicalHistory;
14064
14039
  if (!canonicalHistory) return false;
14040
+ if (isNativeSourceCanonicalHistory(canonicalHistory)) {
14041
+ const cacheKey = [this.type, this.providerSessionId, this.workingDir].join("\0");
14042
+ const now = Date.now();
14043
+ if (cacheKey === this.lastNativeSourceCanonicalCacheKey && now - this.lastNativeSourceCanonicalCheckAt < 2e3) {
14044
+ return true;
14045
+ }
14046
+ this.lastNativeSourceCanonicalCacheKey = cacheKey;
14047
+ this.lastNativeSourceCanonicalCheckAt = now;
14048
+ const restoredHistory = readProviderChatHistory(this.type, {
14049
+ canonicalHistory,
14050
+ historySessionId: this.providerSessionId,
14051
+ workspace: this.workingDir,
14052
+ offset: 0,
14053
+ limit: Number.MAX_SAFE_INTEGER,
14054
+ historyBehavior: this.provider.historyBehavior,
14055
+ scripts: this.provider.scripts
14056
+ });
14057
+ if (restoredHistory.source === "provider-native") {
14058
+ this.lastPersistedHistoryMessages = restoredHistory.messages.map((message) => ({
14059
+ role: message.role,
14060
+ content: message.content,
14061
+ kind: message.kind,
14062
+ senderName: message.senderName,
14063
+ receivedAt: message.receivedAt
14064
+ }));
14065
+ }
14066
+ return true;
14067
+ }
14065
14068
  try {
14066
- let rebuilt = false;
14067
- if (canonicalHistory.format === "hermes-json") {
14068
- const watchPath = canonicalHistory.watchPath.replace(/^~/, os11.homedir()).replace("{{sessionId}}", this.providerSessionId);
14069
- const now = Date.now();
14070
- if (watchPath !== this.lastCanonicalHermesWatchPath || now - this.lastCanonicalHermesExistCheckAt >= 2e3) {
14071
- this.lastCanonicalHermesWatchPath = watchPath;
14072
- this.lastCanonicalHermesExistCheckAt = now;
14073
- if (!fs5.existsSync(watchPath)) return false;
14074
- } else if (this.lastCanonicalHermesSyncMtimeMs === 0) {
14075
- if (!fs5.existsSync(watchPath)) return false;
14076
- }
14077
- const stat = fs5.statSync(watchPath);
14078
- if (stat.mtimeMs <= this.lastCanonicalHermesSyncMtimeMs) return true;
14079
- rebuilt = rebuildHermesSavedHistoryFromCanonicalSession(this.providerSessionId);
14080
- if (rebuilt) this.lastCanonicalHermesSyncMtimeMs = stat.mtimeMs;
14081
- } else if (canonicalHistory.format === "claude-jsonl") {
14082
- const now = Date.now();
14083
- if (now - this.lastCanonicalClaudeCheckAt < 2e3 && this.lastCanonicalClaudeRebuildMtimeMs !== 0) {
14084
- return true;
14085
- }
14086
- this.lastCanonicalClaudeCheckAt = now;
14087
- const claudeProjectsDir = path11.join(os11.homedir(), ".claude", "projects");
14088
- const workspaceSegment = typeof this.workingDir === "string" ? this.workingDir.replace(/[\\/]/g, "-").replace(/^-+/, "") : "";
14089
- const transcriptFile = path11.join(claudeProjectsDir, workspaceSegment, `${this.providerSessionId}.jsonl`);
14090
- let transcriptMtime = 0;
14091
- try {
14092
- transcriptMtime = fs5.statSync(transcriptFile).mtimeMs;
14093
- } catch {
14094
- }
14095
- if (transcriptMtime > 0 && transcriptMtime <= this.lastCanonicalClaudeRebuildMtimeMs) return true;
14096
- rebuilt = rebuildClaudeSavedHistoryFromNativeProject(this.providerSessionId, this.workingDir);
14097
- if (rebuilt) this.lastCanonicalClaudeRebuildMtimeMs = transcriptMtime || Date.now();
14069
+ const cacheKey = [this.type, this.providerSessionId, this.workingDir, canonicalHistory.mode || "materialized-mirror"].join("\0");
14070
+ const now = Date.now();
14071
+ if (cacheKey === this.lastNativeSourceCanonicalCacheKey && now - this.lastNativeSourceCanonicalCheckAt < 2e3) {
14072
+ return true;
14073
+ }
14074
+ this.lastNativeSourceCanonicalCacheKey = cacheKey;
14075
+ this.lastNativeSourceCanonicalCheckAt = now;
14076
+ if (!materializeProviderNativeHistory(this.type, canonicalHistory, this.providerSessionId, this.workingDir, this.provider.scripts)) {
14077
+ return false;
14098
14078
  }
14099
- if (!rebuilt) return false;
14100
14079
  const restoredHistory = readChatHistory(this.type, 0, Number.MAX_SAFE_INTEGER, this.providerSessionId, 0, this.provider.historyBehavior);
14101
14080
  this.lastPersistedHistoryMessages = restoredHistory.messages.map((message) => ({
14102
14081
  role: message.role,
@@ -14113,8 +14092,18 @@ ${effect.notification.body || ""}`.trim();
14113
14092
  restorePersistedHistoryFromCurrentSession() {
14114
14093
  if (!this.providerSessionId) return;
14115
14094
  this.syncCanonicalSavedHistoryIfNeeded();
14116
- this.historyWriter.compactHistorySession(this.type, this.providerSessionId, this.provider.historyBehavior);
14117
- const restoredHistory = readChatHistory(this.type, 0, Number.MAX_SAFE_INTEGER, this.providerSessionId, 0, this.provider.historyBehavior);
14095
+ const restoredHistory = isNativeSourceCanonicalHistory(this.provider.canonicalHistory) ? readProviderChatHistory(this.type, {
14096
+ canonicalHistory: this.provider.canonicalHistory,
14097
+ historySessionId: this.providerSessionId,
14098
+ workspace: this.workingDir,
14099
+ offset: 0,
14100
+ limit: Number.MAX_SAFE_INTEGER,
14101
+ historyBehavior: this.provider.historyBehavior,
14102
+ scripts: this.provider.scripts
14103
+ }) : (() => {
14104
+ this.historyWriter.compactHistorySession(this.type, this.providerSessionId, this.provider.historyBehavior);
14105
+ return readChatHistory(this.type, 0, Number.MAX_SAFE_INTEGER, this.providerSessionId, 0, this.provider.historyBehavior);
14106
+ })();
14118
14107
  this.historyWriter.seedSessionHistory(
14119
14108
  this.type,
14120
14109
  restoredHistory.messages,
@@ -16250,6 +16239,7 @@ function validateProviderDefinition(raw) {
16250
16239
  warnings.push("Extension providers should have extensionId");
16251
16240
  }
16252
16241
  validateCapabilities(provider, controls, errors);
16242
+ validateCanonicalHistory(provider.canonicalHistory, errors);
16253
16243
  for (const control of controls) {
16254
16244
  validateControl(control, errors);
16255
16245
  }
@@ -16307,6 +16297,39 @@ function validateCapabilities(provider, controls, errors) {
16307
16297
  errors.push("providers declaring controls must set capabilities.controls.typedResults=true");
16308
16298
  }
16309
16299
  }
16300
+ function validateCanonicalHistory(raw, errors) {
16301
+ if (raw === void 0) return;
16302
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
16303
+ errors.push("canonicalHistory must be an object");
16304
+ return;
16305
+ }
16306
+ const canonicalHistory = raw;
16307
+ const format = canonicalHistory.format;
16308
+ if (format !== void 0 && (typeof format !== "string" || !format.trim())) {
16309
+ errors.push("canonicalHistory.format must be a non-empty string when provided");
16310
+ }
16311
+ const watchPath = canonicalHistory.watchPath;
16312
+ if (watchPath !== void 0 && (typeof watchPath !== "string" || !watchPath.trim())) {
16313
+ errors.push("canonicalHistory.watchPath must be a non-empty string when provided");
16314
+ }
16315
+ const mode = canonicalHistory.mode;
16316
+ if (mode !== void 0 && !["native-source", "materialized-mirror", "disabled"].includes(String(mode))) {
16317
+ errors.push("canonicalHistory.mode must be one of: native-source, materialized-mirror, disabled");
16318
+ }
16319
+ const scripts = canonicalHistory.scripts;
16320
+ if (scripts === void 0) return;
16321
+ if (!scripts || typeof scripts !== "object" || Array.isArray(scripts)) {
16322
+ errors.push("canonicalHistory.scripts must be an object");
16323
+ return;
16324
+ }
16325
+ const scriptConfig = scripts;
16326
+ for (const key of ["readSession", "listSessions"]) {
16327
+ const value = scriptConfig[key];
16328
+ if (typeof value !== "string" || !value.trim()) {
16329
+ errors.push(`canonicalHistory.scripts.${key} must be a non-empty string`);
16330
+ }
16331
+ }
16332
+ }
16310
16333
  function validateControl(control, errors) {
16311
16334
  if (!control || typeof control !== "object") {
16312
16335
  errors.push("controls: each control must be an object");
@@ -17849,6 +17872,38 @@ var ProviderLoader = class _ProviderLoader {
17849
17872
  }
17850
17873
  };
17851
17874
 
17875
+ // src/launch/macos-app-process.ts
17876
+ function normalizeMacAppPath(appPath) {
17877
+ const trimmed = String(appPath || "").trim();
17878
+ if (!trimmed) return null;
17879
+ return trimmed.replace(/\/+$/, "");
17880
+ }
17881
+ function parsePsLine(line) {
17882
+ const match = line.match(/^\s*(\d+)\s+(.+)$/);
17883
+ if (!match) return null;
17884
+ const pid = Number.parseInt(match[1], 10);
17885
+ if (!Number.isFinite(pid)) return null;
17886
+ return { pid, args: match[2] };
17887
+ }
17888
+ function isMacAppProcessArgs(args, appPath) {
17889
+ const normalized = normalizeMacAppPath(appPath);
17890
+ if (!normalized) return false;
17891
+ return String(args || "").startsWith(`${normalized}/`);
17892
+ }
17893
+ function findMacAppProcessPids(psOutput, appPaths) {
17894
+ const normalizedPaths = appPaths.map(normalizeMacAppPath).filter((value) => !!value);
17895
+ if (normalizedPaths.length === 0) return [];
17896
+ const pids = [];
17897
+ for (const line of String(psOutput || "").split(/\r?\n/)) {
17898
+ const parsed = parsePsLine(line);
17899
+ if (!parsed) continue;
17900
+ if (normalizedPaths.some((appPath) => isMacAppProcessArgs(parsed.args, appPath))) {
17901
+ pids.push(parsed.pid);
17902
+ }
17903
+ }
17904
+ return pids;
17905
+ }
17906
+
17852
17907
  // src/launch.ts
17853
17908
  var _providerLoader = null;
17854
17909
  function getProviderLoader() {
@@ -17885,6 +17940,35 @@ function getCdpStartupTimeoutMs(ideId) {
17885
17940
  function escapeForAppleScript(value) {
17886
17941
  return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
17887
17942
  }
17943
+ function getIdePathCandidates(ideId) {
17944
+ return getProviderLoader().getIdePathCandidates(ideId);
17945
+ }
17946
+ function getMacAppProcessPids(ideId) {
17947
+ const appPaths = getIdePathCandidates(ideId);
17948
+ if (appPaths.length === 0) return [];
17949
+ try {
17950
+ const output = execSync4("ps axww -o pid=,args=", {
17951
+ encoding: "utf-8",
17952
+ timeout: 3e3,
17953
+ stdio: ["pipe", "pipe", "pipe"]
17954
+ });
17955
+ return findMacAppProcessPids(output, appPaths);
17956
+ } catch {
17957
+ return [];
17958
+ }
17959
+ }
17960
+ function killMacAppPathProcesses(ideId, signal) {
17961
+ const pids = getMacAppProcessPids(ideId);
17962
+ let signalled = false;
17963
+ for (const pid of pids) {
17964
+ try {
17965
+ process.kill(pid, signal);
17966
+ signalled = true;
17967
+ } catch {
17968
+ }
17969
+ }
17970
+ return signalled;
17971
+ }
17888
17972
  async function findFreePort(ports) {
17889
17973
  for (const port2 of ports) {
17890
17974
  const free = await checkPortFree(port2);
@@ -17946,6 +18030,7 @@ async function killIdeProcess(ideId) {
17946
18030
  } catch {
17947
18031
  }
17948
18032
  }
18033
+ killMacAppPathProcesses(ideId, "SIGTERM");
17949
18034
  } else if (plat === "win32" && winProcesses) {
17950
18035
  for (const proc of winProcesses) {
17951
18036
  try {
@@ -17975,6 +18060,7 @@ async function killIdeProcess(ideId) {
17975
18060
  execSync4(`pkill -9 -x "${appName}" 2>/dev/null`, { timeout: 5e3 });
17976
18061
  } catch {
17977
18062
  }
18063
+ killMacAppPathProcesses(ideId, "SIGKILL");
17978
18064
  } else if (plat === "win32" && winProcesses) {
17979
18065
  for (const proc of winProcesses) {
17980
18066
  try {
@@ -17994,14 +18080,16 @@ function isIdeRunning(ideId) {
17994
18080
  try {
17995
18081
  if (plat === "darwin") {
17996
18082
  const appName = getMacAppIdentifiers()[ideId];
17997
- if (!appName) return false;
18083
+ if (!appName) return getMacAppProcessPids(ideId).length > 0;
17998
18084
  try {
17999
18085
  const result = execSync4(`pgrep -x "${appName}" 2>/dev/null`, {
18000
18086
  encoding: "utf-8",
18001
18087
  timeout: 3e3
18002
18088
  });
18003
- return result.trim().length > 0;
18089
+ if (result.trim().length > 0) return true;
18004
18090
  } catch {
18091
+ }
18092
+ try {
18005
18093
  const result = execSync4(
18006
18094
  `osascript -e 'tell application "System Events" to count (every process whose name is "${escapeForAppleScript(appName)}")'`,
18007
18095
  {
@@ -18010,8 +18098,10 @@ function isIdeRunning(ideId) {
18010
18098
  stdio: ["pipe", "pipe", "pipe"]
18011
18099
  }
18012
18100
  );
18013
- return Number.parseInt(result.trim() || "0", 10) > 0;
18101
+ if (Number.parseInt(result.trim() || "0", 10) > 0) return true;
18102
+ } catch {
18014
18103
  }
18104
+ return getMacAppProcessPids(ideId).length > 0;
18015
18105
  } else if (plat === "win32") {
18016
18106
  const winProcesses = getWinProcessNames()[ideId];
18017
18107
  if (!winProcesses) return false;
@@ -19378,13 +19468,19 @@ var DaemonCommandRouter = class {
19378
19468
  const wantsAll = args?.all === true;
19379
19469
  const offset = wantsAll ? 0 : Math.max(0, Number(args?.offset) || 0);
19380
19470
  const limit = wantsAll ? Number.MAX_SAFE_INTEGER : Math.max(1, Math.min(100, Number(args?.limit) || 30));
19381
- const { sessions: historySessions, hasMore } = listSavedHistorySessions(providerType, { offset, limit });
19471
+ const providerMeta = this.deps.providerLoader.getMeta(providerType);
19472
+ const { sessions: historySessions, hasMore, source } = listProviderHistorySessions(providerType, {
19473
+ canonicalHistory: providerMeta?.canonicalHistory,
19474
+ offset,
19475
+ limit,
19476
+ historyBehavior: providerMeta?.historyBehavior,
19477
+ scripts: providerMeta?.scripts
19478
+ });
19382
19479
  const state = loadState();
19383
19480
  const savedSessions = getSavedProviderSessions(state, { providerType, kind });
19384
19481
  const recentSessions = getRecentActivity(state, 200).filter((entry) => entry.providerType === providerType && entry.kind === kind && entry.providerSessionId);
19385
19482
  const savedSessionById = new Map(savedSessions.map((entry) => [entry.providerSessionId, entry]));
19386
19483
  const recentSessionById = new Map(recentSessions.map((entry) => [entry.providerSessionId, entry]));
19387
- const providerMeta = this.deps.providerLoader.getMeta(providerType);
19388
19484
  const canResumeById = supportsExplicitSessionResume(providerMeta?.resume);
19389
19485
  return {
19390
19486
  success: true,
@@ -19404,10 +19500,14 @@ var DaemonCommandRouter = class {
19404
19500
  messageCount: session.messageCount,
19405
19501
  firstMessageAt: session.firstMessageAt,
19406
19502
  lastMessageAt: session.lastMessageAt,
19407
- canResume: !!(saved?.workspace || recent?.workspace || session.workspace) && canResumeById
19503
+ canResume: !!(saved?.workspace || recent?.workspace || session.workspace) && canResumeById,
19504
+ historySource: session.source,
19505
+ sourcePath: session.sourcePath,
19506
+ sourceMtimeMs: session.sourceMtimeMs
19408
19507
  };
19409
19508
  }),
19410
- hasMore
19509
+ hasMore,
19510
+ source
19411
19511
  };
19412
19512
  }
19413
19513
  // ─── restart_session: IDE / CLI / ACP unified ───