@adhdev/daemon-core 0.8.98 → 0.8.100

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.
@@ -103,4 +103,5 @@ export declare function listSavedHistorySessions(agentType: string, options?: {
103
103
  hasMore: boolean;
104
104
  };
105
105
  export declare function rebuildHermesSavedHistoryFromCanonicalSession(historySessionId: string): boolean;
106
+ export declare function rebuildClaudeSavedHistoryFromNativeProject(historySessionId: string, workspace?: string): boolean;
106
107
  export {};
package/dist/index.js CHANGED
@@ -4582,6 +4582,7 @@ init_config();
4582
4582
 
4583
4583
  // src/providers/provider-session-id.ts
4584
4584
  var HERMES_SESSION_ID_RE = /^\d{8}_\d{6}_[a-z0-9]+$/i;
4585
+ var CLAUDE_SESSION_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
4585
4586
  function normalizeProviderSessionId(providerType, providerSessionId) {
4586
4587
  const normalizedProviderType = typeof providerType === "string" ? providerType.trim() : "";
4587
4588
  const normalizedId = typeof providerSessionId === "string" ? providerSessionId.trim() : "";
@@ -4591,6 +4592,9 @@ function normalizeProviderSessionId(providerType, providerSessionId) {
4591
4592
  if (normalizedProviderType === "hermes-cli" && !HERMES_SESSION_ID_RE.test(normalizedId)) {
4592
4593
  return "";
4593
4594
  }
4595
+ if (normalizedProviderType === "claude-cli" && !CLAUDE_SESSION_ID_RE.test(normalizedId)) {
4596
+ return "";
4597
+ }
4594
4598
  return normalizedId;
4595
4599
  }
4596
4600
  function isLegacyVolatileSessionReadKey(key) {
@@ -7712,9 +7716,16 @@ function extractCanonicalHermesMessageTimestamp(message, fallbackTs) {
7712
7716
  if (Number.isFinite(stringTimestamp) && stringTimestamp > 0) return stringTimestamp;
7713
7717
  return fallbackTs;
7714
7718
  }
7715
- function readExistingHermesSessionStartRecord(historySessionId) {
7719
+ function extractTimestampValue(value) {
7720
+ const numericTimestamp = Number(value || 0);
7721
+ if (Number.isFinite(numericTimestamp) && numericTimestamp > 0) return numericTimestamp;
7722
+ const stringTimestamp = typeof value === "string" ? Date.parse(value) : NaN;
7723
+ if (Number.isFinite(stringTimestamp) && stringTimestamp > 0) return stringTimestamp;
7724
+ return 0;
7725
+ }
7726
+ function readExistingSessionStartRecord(agentType, historySessionId) {
7716
7727
  try {
7717
- const dir = path7.join(HISTORY_DIR, "hermes-cli");
7728
+ const dir = path7.join(HISTORY_DIR, agentType);
7718
7729
  if (!fs3.existsSync(dir)) return null;
7719
7730
  const files = listHistoryFiles(dir, historySessionId).sort();
7720
7731
  for (const file of files) {
@@ -7735,6 +7746,28 @@ function readExistingHermesSessionStartRecord(historySessionId) {
7735
7746
  return null;
7736
7747
  }
7737
7748
  }
7749
+ function rewriteCanonicalSavedHistory(agentType, historySessionId, records) {
7750
+ if (records.length === 0) return false;
7751
+ try {
7752
+ const dir = path7.join(HISTORY_DIR, agentType);
7753
+ fs3.mkdirSync(dir, { recursive: true });
7754
+ const prefix = `${historySessionId.replace(/[^a-zA-Z0-9_-]/g, "_")}_`;
7755
+ for (const file of fs3.readdirSync(dir)) {
7756
+ if (file.startsWith(prefix) && file.endsWith(".jsonl")) {
7757
+ fs3.unlinkSync(path7.join(dir, file));
7758
+ }
7759
+ }
7760
+ const targetDate = new Date(records[records.length - 1].receivedAt || Date.now()).toISOString().slice(0, 10);
7761
+ const filePath = path7.join(dir, `${prefix}${targetDate}.jsonl`);
7762
+ fs3.writeFileSync(filePath, `${records.map((record) => JSON.stringify(record)).join("\n")}
7763
+ `, "utf-8");
7764
+ invalidatePersistedSavedHistoryIndex(agentType, dir);
7765
+ savedHistorySessionCache.delete(agentType.replace(/[^a-zA-Z0-9_-]/g, "_"));
7766
+ return true;
7767
+ } catch {
7768
+ return false;
7769
+ }
7770
+ }
7738
7771
  function rebuildHermesSavedHistoryFromCanonicalSession(historySessionId) {
7739
7772
  const normalizedSessionId = normalizeSavedHistorySessionId("hermes-cli", historySessionId);
7740
7773
  if (!normalizedSessionId) return false;
@@ -7745,7 +7778,7 @@ function rebuildHermesSavedHistoryFromCanonicalSession(historySessionId) {
7745
7778
  const canonicalMessages = Array.isArray(raw.messages) ? raw.messages : [];
7746
7779
  const dir = path7.join(HISTORY_DIR, "hermes-cli");
7747
7780
  fs3.mkdirSync(dir, { recursive: true });
7748
- const existingSessionStart = readExistingHermesSessionStartRecord(normalizedSessionId);
7781
+ const existingSessionStart = readExistingSessionStartRecord("hermes-cli", normalizedSessionId);
7749
7782
  const records = [];
7750
7783
  if (existingSessionStart) {
7751
7784
  records.push({
@@ -7797,20 +7830,167 @@ function rebuildHermesSavedHistoryFromCanonicalSession(historySessionId) {
7797
7830
  });
7798
7831
  }
7799
7832
  }
7800
- if (records.length === 0) return false;
7801
- const prefix = `${normalizedSessionId.replace(/[^a-zA-Z0-9_-]/g, "_")}_`;
7802
- for (const file of fs3.readdirSync(dir)) {
7803
- if (file.startsWith(prefix) && file.endsWith(".jsonl")) {
7804
- fs3.unlinkSync(path7.join(dir, file));
7833
+ return rewriteCanonicalSavedHistory("hermes-cli", normalizedSessionId, records);
7834
+ } catch {
7835
+ return false;
7836
+ }
7837
+ }
7838
+ function resolveClaudeProjectTranscriptPath(historySessionId, workspace) {
7839
+ const claudeProjectsDir = path7.join(os5.homedir(), ".claude", "projects");
7840
+ if (!fs3.existsSync(claudeProjectsDir)) return null;
7841
+ const normalizedWorkspace = typeof workspace === "string" ? workspace.trim() : "";
7842
+ if (normalizedWorkspace) {
7843
+ const directPath = path7.join(claudeProjectsDir, normalizedWorkspace.replace(/[\\/]/g, "-"), `${historySessionId}.jsonl`);
7844
+ if (fs3.existsSync(directPath)) return directPath;
7845
+ }
7846
+ const stack = [claudeProjectsDir];
7847
+ while (stack.length > 0) {
7848
+ const current = stack.pop();
7849
+ if (!current) continue;
7850
+ for (const entry of fs3.readdirSync(current, { withFileTypes: true })) {
7851
+ const entryPath = path7.join(current, entry.name);
7852
+ if (entry.isDirectory()) {
7853
+ stack.push(entryPath);
7854
+ continue;
7855
+ }
7856
+ if (entry.isFile() && entry.name === `${historySessionId}.jsonl`) {
7857
+ return entryPath;
7805
7858
  }
7806
7859
  }
7807
- const targetDate = new Date(records[records.length - 1].receivedAt || Date.now()).toISOString().slice(0, 10);
7808
- const filePath = path7.join(dir, `${prefix}${targetDate}.jsonl`);
7809
- fs3.writeFileSync(filePath, `${records.map((record) => JSON.stringify(record)).join("\n")}
7810
- `, "utf-8");
7811
- invalidatePersistedSavedHistoryIndex("hermes-cli", dir);
7812
- savedHistorySessionCache.delete("hermes-cli");
7813
- return true;
7860
+ }
7861
+ return null;
7862
+ }
7863
+ function extractClaudeAssistantContentParts(content) {
7864
+ if (typeof content === "string") {
7865
+ const trimmed = content.trim();
7866
+ return trimmed ? [{ content: trimmed, kind: "standard", role: "assistant" }] : [];
7867
+ }
7868
+ if (!Array.isArray(content)) return [];
7869
+ const parts = [];
7870
+ for (const block of content) {
7871
+ if (!block || typeof block !== "object") continue;
7872
+ const record = block;
7873
+ const type = String(record.type || "").trim();
7874
+ if (type === "text") {
7875
+ const text = String(record.text || "").trim();
7876
+ if (text) parts.push({ content: text, kind: "standard", role: "assistant" });
7877
+ continue;
7878
+ }
7879
+ if (type === "tool_use") {
7880
+ const name = String(record.name || "").trim() || "Tool";
7881
+ const input = record.input && typeof record.input === "object" ? record.input : null;
7882
+ const command = input ? String(input.command || "").trim() : "";
7883
+ const summary = command ? `${name}: ${command}` : name;
7884
+ if (summary) parts.push({ content: summary, kind: "tool", senderName: "Tool", role: "assistant" });
7885
+ }
7886
+ }
7887
+ return parts;
7888
+ }
7889
+ function extractClaudeUserContentParts(content) {
7890
+ if (typeof content === "string") {
7891
+ const trimmed = content.trim();
7892
+ return trimmed ? [{ role: "user", content: trimmed, kind: "standard" }] : [];
7893
+ }
7894
+ if (!Array.isArray(content)) return [];
7895
+ const parts = [];
7896
+ for (const block of content) {
7897
+ if (!block || typeof block !== "object") continue;
7898
+ const record = block;
7899
+ const type = String(record.type || "").trim();
7900
+ if (type === "text") {
7901
+ const text = String(record.text || "").trim();
7902
+ if (text) parts.push({ role: "user", content: text, kind: "standard" });
7903
+ continue;
7904
+ }
7905
+ if (type === "tool_result") {
7906
+ const rawContent = record.content;
7907
+ const text = typeof rawContent === "string" ? rawContent.trim() : Array.isArray(rawContent) ? rawContent.map((entry) => {
7908
+ if (typeof entry === "string") return entry.trim();
7909
+ if (!entry || typeof entry !== "object") return "";
7910
+ const nested = entry;
7911
+ if (typeof nested.text === "string") return nested.text.trim();
7912
+ if (typeof nested.content === "string") return nested.content.trim();
7913
+ return "";
7914
+ }).filter(Boolean).join("\n") : "";
7915
+ if (text) parts.push({ role: "assistant", content: text, kind: "tool", senderName: "Tool" });
7916
+ }
7917
+ }
7918
+ return parts;
7919
+ }
7920
+ function rebuildClaudeSavedHistoryFromNativeProject(historySessionId, workspace) {
7921
+ const normalizedSessionId = normalizeSavedHistorySessionId("claude-cli", historySessionId);
7922
+ if (!normalizedSessionId) return false;
7923
+ try {
7924
+ const transcriptPath = resolveClaudeProjectTranscriptPath(normalizedSessionId, workspace);
7925
+ if (!transcriptPath) return false;
7926
+ const lines = fs3.readFileSync(transcriptPath, "utf-8").split("\n").filter(Boolean);
7927
+ const records = [];
7928
+ const existingSessionStart = readExistingSessionStartRecord("claude-cli", normalizedSessionId);
7929
+ if (existingSessionStart) {
7930
+ records.push({
7931
+ ...existingSessionStart,
7932
+ historySessionId: normalizedSessionId
7933
+ });
7934
+ }
7935
+ let fallbackTs = Date.now();
7936
+ for (const line of lines) {
7937
+ let parsed = null;
7938
+ try {
7939
+ parsed = JSON.parse(line);
7940
+ } catch {
7941
+ parsed = null;
7942
+ }
7943
+ if (!parsed) continue;
7944
+ const parsedSessionId = String(parsed.sessionId || "").trim();
7945
+ if (parsedSessionId && parsedSessionId !== normalizedSessionId) continue;
7946
+ const receivedAt = extractTimestampValue(parsed.timestamp) || fallbackTs;
7947
+ fallbackTs = receivedAt + 1;
7948
+ const parsedWorkspace = String(parsed.cwd || workspace || "").trim();
7949
+ if (records.length === 0 && parsedWorkspace) {
7950
+ records.push({
7951
+ ts: new Date(receivedAt).toISOString(),
7952
+ receivedAt,
7953
+ role: "system",
7954
+ kind: "session_start",
7955
+ content: parsedWorkspace,
7956
+ agent: "claude-cli",
7957
+ historySessionId: normalizedSessionId,
7958
+ workspace: parsedWorkspace
7959
+ });
7960
+ }
7961
+ const type = String(parsed.type || "").trim();
7962
+ const message = parsed.message && typeof parsed.message === "object" ? parsed.message : null;
7963
+ if (type === "user" && message) {
7964
+ for (const part of extractClaudeUserContentParts(message.content)) {
7965
+ records.push({
7966
+ ts: new Date(receivedAt).toISOString(),
7967
+ receivedAt,
7968
+ role: part.role,
7969
+ content: part.content,
7970
+ kind: part.kind,
7971
+ senderName: part.senderName,
7972
+ agent: "claude-cli",
7973
+ historySessionId: normalizedSessionId
7974
+ });
7975
+ }
7976
+ continue;
7977
+ }
7978
+ if (type === "assistant" && message) {
7979
+ for (const part of extractClaudeAssistantContentParts(message.content)) {
7980
+ records.push({
7981
+ ts: new Date(receivedAt).toISOString(),
7982
+ receivedAt,
7983
+ role: "assistant",
7984
+ content: part.content,
7985
+ kind: part.kind,
7986
+ senderName: part.senderName,
7987
+ agent: "claude-cli",
7988
+ historySessionId: normalizedSessionId
7989
+ });
7990
+ }
7991
+ }
7992
+ }
7993
+ return rewriteCanonicalSavedHistory("claude-cli", normalizedSessionId, records);
7814
7994
  } catch {
7815
7995
  return false;
7816
7996
  }
@@ -12869,7 +13049,7 @@ var CliProviderInstance = class {
12869
13049
  parsedMessages = historyMessageCount > 0 ? parsedMessages.slice(-historyMessageCount) : [];
12870
13050
  }
12871
13051
  const mergedMessages = this.mergeConversationMessages(parsedMessages);
12872
- const canonicalHermesBackedHistory = this.syncCanonicalHermesSavedHistoryIfNeeded();
13052
+ const canonicalBackedHistory = this.syncCanonicalSavedHistoryIfNeeded();
12873
13053
  const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
12874
13054
  if (parsedMessages.length > 0) {
12875
13055
  const shouldSkipReplayPersist = this.suppressIdleHistoryReplay && adapterStatus.status === "idle" && parsedStatus?.status === "idle";
@@ -12887,7 +13067,7 @@ var CliProviderInstance = class {
12887
13067
  senderName: typeof message.senderName === "string" ? message.senderName : void 0,
12888
13068
  receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
12889
13069
  }));
12890
- if (!canonicalHermesBackedHistory && !shouldSkipReplayPersist && normalizedMessagesToSave.length > 0) {
13070
+ if (!canonicalBackedHistory && !shouldSkipReplayPersist && normalizedMessagesToSave.length > 0) {
12891
13071
  const incrementalMessages = buildIncrementalHistoryAppendMessages(this.lastPersistedHistoryMessages, normalizedMessagesToSave);
12892
13072
  this.historyWriter.appendNewMessages(
12893
13073
  this.type,
@@ -12897,7 +13077,7 @@ var CliProviderInstance = class {
12897
13077
  this.providerSessionId
12898
13078
  );
12899
13079
  }
12900
- if (!canonicalHermesBackedHistory) {
13080
+ if (!canonicalBackedHistory) {
12901
13081
  this.lastPersistedHistoryMessages = normalizedMessagesToSave;
12902
13082
  }
12903
13083
  }
@@ -13252,7 +13432,14 @@ ${effect.notification.body || ""}`.trim();
13252
13432
  return this.provider.name;
13253
13433
  }
13254
13434
  shouldAutoApprove() {
13255
- return this.settings.autoApprove !== false;
13435
+ if (typeof this.settings.autoApprove === "boolean") {
13436
+ return this.settings.autoApprove;
13437
+ }
13438
+ const providerDefault = this.provider.settings?.autoApprove?.default;
13439
+ if (typeof providerDefault === "boolean") {
13440
+ return providerDefault;
13441
+ }
13442
+ return false;
13256
13443
  }
13257
13444
  recordAutoApproval(modalMessage, buttonLabel, now = Date.now()) {
13258
13445
  this.appendRuntimeSystemMessage(
@@ -13374,32 +13561,52 @@ ${effect.notification.body || ""}`.trim();
13374
13561
  });
13375
13562
  LOG.info("CLI", `[${this.type}] discovered provider session id: ${nextSessionId}`);
13376
13563
  }
13377
- syncCanonicalHermesSavedHistoryIfNeeded() {
13378
- if (this.type !== "hermes-cli" || !this.providerSessionId) return false;
13379
- try {
13380
- const canonicalPath = path11.join(os11.homedir(), ".hermes", "sessions", `session_${this.providerSessionId}.json`);
13381
- if (!fs5.existsSync(canonicalPath)) return false;
13382
- const stat = fs5.statSync(canonicalPath);
13383
- if (stat.mtimeMs <= this.lastCanonicalHermesSyncMtimeMs) return true;
13384
- const rebuilt = rebuildHermesSavedHistoryFromCanonicalSession(this.providerSessionId);
13385
- if (!rebuilt) return false;
13386
- this.lastCanonicalHermesSyncMtimeMs = stat.mtimeMs;
13387
- const restoredHistory = readChatHistory(this.type, 0, Number.MAX_SAFE_INTEGER, this.providerSessionId);
13388
- this.lastPersistedHistoryMessages = restoredHistory.messages.map((message) => ({
13389
- role: message.role,
13390
- content: message.content,
13391
- kind: message.kind,
13392
- senderName: message.senderName,
13393
- receivedAt: message.receivedAt
13394
- }));
13395
- return true;
13396
- } catch {
13397
- return false;
13564
+ syncCanonicalSavedHistoryIfNeeded() {
13565
+ if (!this.providerSessionId) return false;
13566
+ if (this.type === "hermes-cli") {
13567
+ try {
13568
+ const canonicalPath = path11.join(os11.homedir(), ".hermes", "sessions", `session_${this.providerSessionId}.json`);
13569
+ if (!fs5.existsSync(canonicalPath)) return false;
13570
+ const stat = fs5.statSync(canonicalPath);
13571
+ if (stat.mtimeMs <= this.lastCanonicalHermesSyncMtimeMs) return true;
13572
+ const rebuilt = rebuildHermesSavedHistoryFromCanonicalSession(this.providerSessionId);
13573
+ if (!rebuilt) return false;
13574
+ this.lastCanonicalHermesSyncMtimeMs = stat.mtimeMs;
13575
+ const restoredHistory = readChatHistory(this.type, 0, Number.MAX_SAFE_INTEGER, this.providerSessionId);
13576
+ this.lastPersistedHistoryMessages = restoredHistory.messages.map((message) => ({
13577
+ role: message.role,
13578
+ content: message.content,
13579
+ kind: message.kind,
13580
+ senderName: message.senderName,
13581
+ receivedAt: message.receivedAt
13582
+ }));
13583
+ return true;
13584
+ } catch {
13585
+ return false;
13586
+ }
13398
13587
  }
13588
+ if (this.type === "claude-cli") {
13589
+ try {
13590
+ const rebuilt = rebuildClaudeSavedHistoryFromNativeProject(this.providerSessionId, this.workingDir);
13591
+ if (!rebuilt) return false;
13592
+ const restoredHistory = readChatHistory(this.type, 0, Number.MAX_SAFE_INTEGER, this.providerSessionId);
13593
+ this.lastPersistedHistoryMessages = restoredHistory.messages.map((message) => ({
13594
+ role: message.role,
13595
+ content: message.content,
13596
+ kind: message.kind,
13597
+ senderName: message.senderName,
13598
+ receivedAt: message.receivedAt
13599
+ }));
13600
+ return true;
13601
+ } catch {
13602
+ return false;
13603
+ }
13604
+ }
13605
+ return false;
13399
13606
  }
13400
13607
  restorePersistedHistoryFromCurrentSession() {
13401
13608
  if (!this.providerSessionId) return;
13402
- this.syncCanonicalHermesSavedHistoryIfNeeded();
13609
+ this.syncCanonicalSavedHistoryIfNeeded();
13403
13610
  this.historyWriter.compactHistorySession(this.type, this.providerSessionId);
13404
13611
  const restoredHistory = readChatHistory(this.type, 0, Number.MAX_SAFE_INTEGER, this.providerSessionId);
13405
13612
  this.historyWriter.seedSessionHistory(
@@ -18974,9 +19181,12 @@ function prepareSessionChatTailUpdate(input) {
18974
19181
  }
18975
19182
  function prepareSessionModalUpdate(input) {
18976
19183
  const { modalMessage, modalButtons } = normalizeSessionModalFields(input.activeModal);
19184
+ const status = normalizeManagedStatus(input.status, {
19185
+ activeModal: modalButtons.length > 0 ? { buttons: modalButtons } : null
19186
+ });
18977
19187
  const deliverySignature = buildSessionModalDeliverySignature({
18978
19188
  sessionId: input.sessionId,
18979
- status: input.status,
19189
+ status,
18980
19190
  ...input.title ? { title: input.title } : {},
18981
19191
  ...modalMessage ? { modalMessage } : {},
18982
19192
  ...modalButtons.length > 0 ? { modalButtons } : {}
@@ -18996,7 +19206,7 @@ function prepareSessionModalUpdate(input) {
18996
19206
  topic: "session.modal",
18997
19207
  key: input.key,
18998
19208
  sessionId: input.sessionId,
18999
- status: input.status,
19209
+ status,
19000
19210
  ...input.title ? { title: input.title } : {},
19001
19211
  ...modalMessage ? { modalMessage } : {},
19002
19212
  ...modalButtons.length > 0 ? { modalButtons } : {},