@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.
package/dist/index.mjs CHANGED
@@ -4431,6 +4431,7 @@ import { join as join3 } from "path";
4431
4431
 
4432
4432
  // src/providers/provider-session-id.ts
4433
4433
  var HERMES_SESSION_ID_RE = /^\d{8}_\d{6}_[a-z0-9]+$/i;
4434
+ 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;
4434
4435
  function normalizeProviderSessionId(providerType, providerSessionId) {
4435
4436
  const normalizedProviderType = typeof providerType === "string" ? providerType.trim() : "";
4436
4437
  const normalizedId = typeof providerSessionId === "string" ? providerSessionId.trim() : "";
@@ -4440,6 +4441,9 @@ function normalizeProviderSessionId(providerType, providerSessionId) {
4440
4441
  if (normalizedProviderType === "hermes-cli" && !HERMES_SESSION_ID_RE.test(normalizedId)) {
4441
4442
  return "";
4442
4443
  }
4444
+ if (normalizedProviderType === "claude-cli" && !CLAUDE_SESSION_ID_RE.test(normalizedId)) {
4445
+ return "";
4446
+ }
4443
4447
  return normalizedId;
4444
4448
  }
4445
4449
  function isLegacyVolatileSessionReadKey(key) {
@@ -7561,9 +7565,16 @@ function extractCanonicalHermesMessageTimestamp(message, fallbackTs) {
7561
7565
  if (Number.isFinite(stringTimestamp) && stringTimestamp > 0) return stringTimestamp;
7562
7566
  return fallbackTs;
7563
7567
  }
7564
- function readExistingHermesSessionStartRecord(historySessionId) {
7568
+ function extractTimestampValue(value) {
7569
+ const numericTimestamp = Number(value || 0);
7570
+ if (Number.isFinite(numericTimestamp) && numericTimestamp > 0) return numericTimestamp;
7571
+ const stringTimestamp = typeof value === "string" ? Date.parse(value) : NaN;
7572
+ if (Number.isFinite(stringTimestamp) && stringTimestamp > 0) return stringTimestamp;
7573
+ return 0;
7574
+ }
7575
+ function readExistingSessionStartRecord(agentType, historySessionId) {
7565
7576
  try {
7566
- const dir = path7.join(HISTORY_DIR, "hermes-cli");
7577
+ const dir = path7.join(HISTORY_DIR, agentType);
7567
7578
  if (!fs3.existsSync(dir)) return null;
7568
7579
  const files = listHistoryFiles(dir, historySessionId).sort();
7569
7580
  for (const file of files) {
@@ -7584,6 +7595,28 @@ function readExistingHermesSessionStartRecord(historySessionId) {
7584
7595
  return null;
7585
7596
  }
7586
7597
  }
7598
+ function rewriteCanonicalSavedHistory(agentType, historySessionId, records) {
7599
+ if (records.length === 0) return false;
7600
+ try {
7601
+ const dir = path7.join(HISTORY_DIR, agentType);
7602
+ fs3.mkdirSync(dir, { recursive: true });
7603
+ const prefix = `${historySessionId.replace(/[^a-zA-Z0-9_-]/g, "_")}_`;
7604
+ for (const file of fs3.readdirSync(dir)) {
7605
+ if (file.startsWith(prefix) && file.endsWith(".jsonl")) {
7606
+ fs3.unlinkSync(path7.join(dir, file));
7607
+ }
7608
+ }
7609
+ const targetDate = new Date(records[records.length - 1].receivedAt || Date.now()).toISOString().slice(0, 10);
7610
+ const filePath = path7.join(dir, `${prefix}${targetDate}.jsonl`);
7611
+ fs3.writeFileSync(filePath, `${records.map((record) => JSON.stringify(record)).join("\n")}
7612
+ `, "utf-8");
7613
+ invalidatePersistedSavedHistoryIndex(agentType, dir);
7614
+ savedHistorySessionCache.delete(agentType.replace(/[^a-zA-Z0-9_-]/g, "_"));
7615
+ return true;
7616
+ } catch {
7617
+ return false;
7618
+ }
7619
+ }
7587
7620
  function rebuildHermesSavedHistoryFromCanonicalSession(historySessionId) {
7588
7621
  const normalizedSessionId = normalizeSavedHistorySessionId("hermes-cli", historySessionId);
7589
7622
  if (!normalizedSessionId) return false;
@@ -7594,7 +7627,7 @@ function rebuildHermesSavedHistoryFromCanonicalSession(historySessionId) {
7594
7627
  const canonicalMessages = Array.isArray(raw.messages) ? raw.messages : [];
7595
7628
  const dir = path7.join(HISTORY_DIR, "hermes-cli");
7596
7629
  fs3.mkdirSync(dir, { recursive: true });
7597
- const existingSessionStart = readExistingHermesSessionStartRecord(normalizedSessionId);
7630
+ const existingSessionStart = readExistingSessionStartRecord("hermes-cli", normalizedSessionId);
7598
7631
  const records = [];
7599
7632
  if (existingSessionStart) {
7600
7633
  records.push({
@@ -7646,20 +7679,167 @@ function rebuildHermesSavedHistoryFromCanonicalSession(historySessionId) {
7646
7679
  });
7647
7680
  }
7648
7681
  }
7649
- if (records.length === 0) return false;
7650
- const prefix = `${normalizedSessionId.replace(/[^a-zA-Z0-9_-]/g, "_")}_`;
7651
- for (const file of fs3.readdirSync(dir)) {
7652
- if (file.startsWith(prefix) && file.endsWith(".jsonl")) {
7653
- fs3.unlinkSync(path7.join(dir, file));
7682
+ return rewriteCanonicalSavedHistory("hermes-cli", normalizedSessionId, records);
7683
+ } catch {
7684
+ return false;
7685
+ }
7686
+ }
7687
+ function resolveClaudeProjectTranscriptPath(historySessionId, workspace) {
7688
+ const claudeProjectsDir = path7.join(os5.homedir(), ".claude", "projects");
7689
+ if (!fs3.existsSync(claudeProjectsDir)) return null;
7690
+ const normalizedWorkspace = typeof workspace === "string" ? workspace.trim() : "";
7691
+ if (normalizedWorkspace) {
7692
+ const directPath = path7.join(claudeProjectsDir, normalizedWorkspace.replace(/[\\/]/g, "-"), `${historySessionId}.jsonl`);
7693
+ if (fs3.existsSync(directPath)) return directPath;
7694
+ }
7695
+ const stack = [claudeProjectsDir];
7696
+ while (stack.length > 0) {
7697
+ const current = stack.pop();
7698
+ if (!current) continue;
7699
+ for (const entry of fs3.readdirSync(current, { withFileTypes: true })) {
7700
+ const entryPath = path7.join(current, entry.name);
7701
+ if (entry.isDirectory()) {
7702
+ stack.push(entryPath);
7703
+ continue;
7704
+ }
7705
+ if (entry.isFile() && entry.name === `${historySessionId}.jsonl`) {
7706
+ return entryPath;
7654
7707
  }
7655
7708
  }
7656
- const targetDate = new Date(records[records.length - 1].receivedAt || Date.now()).toISOString().slice(0, 10);
7657
- const filePath = path7.join(dir, `${prefix}${targetDate}.jsonl`);
7658
- fs3.writeFileSync(filePath, `${records.map((record) => JSON.stringify(record)).join("\n")}
7659
- `, "utf-8");
7660
- invalidatePersistedSavedHistoryIndex("hermes-cli", dir);
7661
- savedHistorySessionCache.delete("hermes-cli");
7662
- return true;
7709
+ }
7710
+ return null;
7711
+ }
7712
+ function extractClaudeAssistantContentParts(content) {
7713
+ if (typeof content === "string") {
7714
+ const trimmed = content.trim();
7715
+ return trimmed ? [{ content: trimmed, kind: "standard", role: "assistant" }] : [];
7716
+ }
7717
+ if (!Array.isArray(content)) return [];
7718
+ const parts = [];
7719
+ for (const block of content) {
7720
+ if (!block || typeof block !== "object") continue;
7721
+ const record = block;
7722
+ const type = String(record.type || "").trim();
7723
+ if (type === "text") {
7724
+ const text = String(record.text || "").trim();
7725
+ if (text) parts.push({ content: text, kind: "standard", role: "assistant" });
7726
+ continue;
7727
+ }
7728
+ if (type === "tool_use") {
7729
+ const name = String(record.name || "").trim() || "Tool";
7730
+ const input = record.input && typeof record.input === "object" ? record.input : null;
7731
+ const command = input ? String(input.command || "").trim() : "";
7732
+ const summary = command ? `${name}: ${command}` : name;
7733
+ if (summary) parts.push({ content: summary, kind: "tool", senderName: "Tool", role: "assistant" });
7734
+ }
7735
+ }
7736
+ return parts;
7737
+ }
7738
+ function extractClaudeUserContentParts(content) {
7739
+ if (typeof content === "string") {
7740
+ const trimmed = content.trim();
7741
+ return trimmed ? [{ role: "user", content: trimmed, kind: "standard" }] : [];
7742
+ }
7743
+ if (!Array.isArray(content)) return [];
7744
+ const parts = [];
7745
+ for (const block of content) {
7746
+ if (!block || typeof block !== "object") continue;
7747
+ const record = block;
7748
+ const type = String(record.type || "").trim();
7749
+ if (type === "text") {
7750
+ const text = String(record.text || "").trim();
7751
+ if (text) parts.push({ role: "user", content: text, kind: "standard" });
7752
+ continue;
7753
+ }
7754
+ if (type === "tool_result") {
7755
+ const rawContent = record.content;
7756
+ const text = typeof rawContent === "string" ? rawContent.trim() : Array.isArray(rawContent) ? rawContent.map((entry) => {
7757
+ if (typeof entry === "string") return entry.trim();
7758
+ if (!entry || typeof entry !== "object") return "";
7759
+ const nested = entry;
7760
+ if (typeof nested.text === "string") return nested.text.trim();
7761
+ if (typeof nested.content === "string") return nested.content.trim();
7762
+ return "";
7763
+ }).filter(Boolean).join("\n") : "";
7764
+ if (text) parts.push({ role: "assistant", content: text, kind: "tool", senderName: "Tool" });
7765
+ }
7766
+ }
7767
+ return parts;
7768
+ }
7769
+ function rebuildClaudeSavedHistoryFromNativeProject(historySessionId, workspace) {
7770
+ const normalizedSessionId = normalizeSavedHistorySessionId("claude-cli", historySessionId);
7771
+ if (!normalizedSessionId) return false;
7772
+ try {
7773
+ const transcriptPath = resolveClaudeProjectTranscriptPath(normalizedSessionId, workspace);
7774
+ if (!transcriptPath) return false;
7775
+ const lines = fs3.readFileSync(transcriptPath, "utf-8").split("\n").filter(Boolean);
7776
+ const records = [];
7777
+ const existingSessionStart = readExistingSessionStartRecord("claude-cli", normalizedSessionId);
7778
+ if (existingSessionStart) {
7779
+ records.push({
7780
+ ...existingSessionStart,
7781
+ historySessionId: normalizedSessionId
7782
+ });
7783
+ }
7784
+ let fallbackTs = Date.now();
7785
+ for (const line of lines) {
7786
+ let parsed = null;
7787
+ try {
7788
+ parsed = JSON.parse(line);
7789
+ } catch {
7790
+ parsed = null;
7791
+ }
7792
+ if (!parsed) continue;
7793
+ const parsedSessionId = String(parsed.sessionId || "").trim();
7794
+ if (parsedSessionId && parsedSessionId !== normalizedSessionId) continue;
7795
+ const receivedAt = extractTimestampValue(parsed.timestamp) || fallbackTs;
7796
+ fallbackTs = receivedAt + 1;
7797
+ const parsedWorkspace = String(parsed.cwd || workspace || "").trim();
7798
+ if (records.length === 0 && parsedWorkspace) {
7799
+ records.push({
7800
+ ts: new Date(receivedAt).toISOString(),
7801
+ receivedAt,
7802
+ role: "system",
7803
+ kind: "session_start",
7804
+ content: parsedWorkspace,
7805
+ agent: "claude-cli",
7806
+ historySessionId: normalizedSessionId,
7807
+ workspace: parsedWorkspace
7808
+ });
7809
+ }
7810
+ const type = String(parsed.type || "").trim();
7811
+ const message = parsed.message && typeof parsed.message === "object" ? parsed.message : null;
7812
+ if (type === "user" && message) {
7813
+ for (const part of extractClaudeUserContentParts(message.content)) {
7814
+ records.push({
7815
+ ts: new Date(receivedAt).toISOString(),
7816
+ receivedAt,
7817
+ role: part.role,
7818
+ content: part.content,
7819
+ kind: part.kind,
7820
+ senderName: part.senderName,
7821
+ agent: "claude-cli",
7822
+ historySessionId: normalizedSessionId
7823
+ });
7824
+ }
7825
+ continue;
7826
+ }
7827
+ if (type === "assistant" && message) {
7828
+ for (const part of extractClaudeAssistantContentParts(message.content)) {
7829
+ records.push({
7830
+ ts: new Date(receivedAt).toISOString(),
7831
+ receivedAt,
7832
+ role: "assistant",
7833
+ content: part.content,
7834
+ kind: part.kind,
7835
+ senderName: part.senderName,
7836
+ agent: "claude-cli",
7837
+ historySessionId: normalizedSessionId
7838
+ });
7839
+ }
7840
+ }
7841
+ }
7842
+ return rewriteCanonicalSavedHistory("claude-cli", normalizedSessionId, records);
7663
7843
  } catch {
7664
7844
  return false;
7665
7845
  }
@@ -12718,7 +12898,7 @@ var CliProviderInstance = class {
12718
12898
  parsedMessages = historyMessageCount > 0 ? parsedMessages.slice(-historyMessageCount) : [];
12719
12899
  }
12720
12900
  const mergedMessages = this.mergeConversationMessages(parsedMessages);
12721
- const canonicalHermesBackedHistory = this.syncCanonicalHermesSavedHistoryIfNeeded();
12901
+ const canonicalBackedHistory = this.syncCanonicalSavedHistoryIfNeeded();
12722
12902
  const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
12723
12903
  if (parsedMessages.length > 0) {
12724
12904
  const shouldSkipReplayPersist = this.suppressIdleHistoryReplay && adapterStatus.status === "idle" && parsedStatus?.status === "idle";
@@ -12736,7 +12916,7 @@ var CliProviderInstance = class {
12736
12916
  senderName: typeof message.senderName === "string" ? message.senderName : void 0,
12737
12917
  receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
12738
12918
  }));
12739
- if (!canonicalHermesBackedHistory && !shouldSkipReplayPersist && normalizedMessagesToSave.length > 0) {
12919
+ if (!canonicalBackedHistory && !shouldSkipReplayPersist && normalizedMessagesToSave.length > 0) {
12740
12920
  const incrementalMessages = buildIncrementalHistoryAppendMessages(this.lastPersistedHistoryMessages, normalizedMessagesToSave);
12741
12921
  this.historyWriter.appendNewMessages(
12742
12922
  this.type,
@@ -12746,7 +12926,7 @@ var CliProviderInstance = class {
12746
12926
  this.providerSessionId
12747
12927
  );
12748
12928
  }
12749
- if (!canonicalHermesBackedHistory) {
12929
+ if (!canonicalBackedHistory) {
12750
12930
  this.lastPersistedHistoryMessages = normalizedMessagesToSave;
12751
12931
  }
12752
12932
  }
@@ -13101,7 +13281,14 @@ ${effect.notification.body || ""}`.trim();
13101
13281
  return this.provider.name;
13102
13282
  }
13103
13283
  shouldAutoApprove() {
13104
- return this.settings.autoApprove !== false;
13284
+ if (typeof this.settings.autoApprove === "boolean") {
13285
+ return this.settings.autoApprove;
13286
+ }
13287
+ const providerDefault = this.provider.settings?.autoApprove?.default;
13288
+ if (typeof providerDefault === "boolean") {
13289
+ return providerDefault;
13290
+ }
13291
+ return false;
13105
13292
  }
13106
13293
  recordAutoApproval(modalMessage, buttonLabel, now = Date.now()) {
13107
13294
  this.appendRuntimeSystemMessage(
@@ -13223,32 +13410,52 @@ ${effect.notification.body || ""}`.trim();
13223
13410
  });
13224
13411
  LOG.info("CLI", `[${this.type}] discovered provider session id: ${nextSessionId}`);
13225
13412
  }
13226
- syncCanonicalHermesSavedHistoryIfNeeded() {
13227
- if (this.type !== "hermes-cli" || !this.providerSessionId) return false;
13228
- try {
13229
- const canonicalPath = path11.join(os11.homedir(), ".hermes", "sessions", `session_${this.providerSessionId}.json`);
13230
- if (!fs5.existsSync(canonicalPath)) return false;
13231
- const stat = fs5.statSync(canonicalPath);
13232
- if (stat.mtimeMs <= this.lastCanonicalHermesSyncMtimeMs) return true;
13233
- const rebuilt = rebuildHermesSavedHistoryFromCanonicalSession(this.providerSessionId);
13234
- if (!rebuilt) return false;
13235
- this.lastCanonicalHermesSyncMtimeMs = stat.mtimeMs;
13236
- const restoredHistory = readChatHistory(this.type, 0, Number.MAX_SAFE_INTEGER, this.providerSessionId);
13237
- this.lastPersistedHistoryMessages = restoredHistory.messages.map((message) => ({
13238
- role: message.role,
13239
- content: message.content,
13240
- kind: message.kind,
13241
- senderName: message.senderName,
13242
- receivedAt: message.receivedAt
13243
- }));
13244
- return true;
13245
- } catch {
13246
- return false;
13413
+ syncCanonicalSavedHistoryIfNeeded() {
13414
+ if (!this.providerSessionId) return false;
13415
+ if (this.type === "hermes-cli") {
13416
+ try {
13417
+ const canonicalPath = path11.join(os11.homedir(), ".hermes", "sessions", `session_${this.providerSessionId}.json`);
13418
+ if (!fs5.existsSync(canonicalPath)) return false;
13419
+ const stat = fs5.statSync(canonicalPath);
13420
+ if (stat.mtimeMs <= this.lastCanonicalHermesSyncMtimeMs) return true;
13421
+ const rebuilt = rebuildHermesSavedHistoryFromCanonicalSession(this.providerSessionId);
13422
+ if (!rebuilt) return false;
13423
+ this.lastCanonicalHermesSyncMtimeMs = stat.mtimeMs;
13424
+ const restoredHistory = readChatHistory(this.type, 0, Number.MAX_SAFE_INTEGER, this.providerSessionId);
13425
+ this.lastPersistedHistoryMessages = restoredHistory.messages.map((message) => ({
13426
+ role: message.role,
13427
+ content: message.content,
13428
+ kind: message.kind,
13429
+ senderName: message.senderName,
13430
+ receivedAt: message.receivedAt
13431
+ }));
13432
+ return true;
13433
+ } catch {
13434
+ return false;
13435
+ }
13247
13436
  }
13437
+ if (this.type === "claude-cli") {
13438
+ try {
13439
+ const rebuilt = rebuildClaudeSavedHistoryFromNativeProject(this.providerSessionId, this.workingDir);
13440
+ if (!rebuilt) return false;
13441
+ const restoredHistory = readChatHistory(this.type, 0, Number.MAX_SAFE_INTEGER, this.providerSessionId);
13442
+ this.lastPersistedHistoryMessages = restoredHistory.messages.map((message) => ({
13443
+ role: message.role,
13444
+ content: message.content,
13445
+ kind: message.kind,
13446
+ senderName: message.senderName,
13447
+ receivedAt: message.receivedAt
13448
+ }));
13449
+ return true;
13450
+ } catch {
13451
+ return false;
13452
+ }
13453
+ }
13454
+ return false;
13248
13455
  }
13249
13456
  restorePersistedHistoryFromCurrentSession() {
13250
13457
  if (!this.providerSessionId) return;
13251
- this.syncCanonicalHermesSavedHistoryIfNeeded();
13458
+ this.syncCanonicalSavedHistoryIfNeeded();
13252
13459
  this.historyWriter.compactHistorySession(this.type, this.providerSessionId);
13253
13460
  const restoredHistory = readChatHistory(this.type, 0, Number.MAX_SAFE_INTEGER, this.providerSessionId);
13254
13461
  this.historyWriter.seedSessionHistory(
@@ -18828,9 +19035,12 @@ function prepareSessionChatTailUpdate(input) {
18828
19035
  }
18829
19036
  function prepareSessionModalUpdate(input) {
18830
19037
  const { modalMessage, modalButtons } = normalizeSessionModalFields(input.activeModal);
19038
+ const status = normalizeManagedStatus(input.status, {
19039
+ activeModal: modalButtons.length > 0 ? { buttons: modalButtons } : null
19040
+ });
18831
19041
  const deliverySignature = buildSessionModalDeliverySignature({
18832
19042
  sessionId: input.sessionId,
18833
- status: input.status,
19043
+ status,
18834
19044
  ...input.title ? { title: input.title } : {},
18835
19045
  ...modalMessage ? { modalMessage } : {},
18836
19046
  ...modalButtons.length > 0 ? { modalButtons } : {}
@@ -18850,7 +19060,7 @@ function prepareSessionModalUpdate(input) {
18850
19060
  topic: "session.modal",
18851
19061
  key: input.key,
18852
19062
  sessionId: input.sessionId,
18853
- status: input.status,
19063
+ status,
18854
19064
  ...input.title ? { title: input.title } : {},
18855
19065
  ...modalMessage ? { modalMessage } : {},
18856
19066
  ...modalButtons.length > 0 ? { modalButtons } : {},