@adhdev/daemon-standalone 0.8.94 → 0.8.96

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -35477,6 +35477,125 @@ ${cleanBody}`;
35477
35477
  return { sessions: [], hasMore: false };
35478
35478
  }
35479
35479
  }
35480
+ function normalizeCanonicalHermesMessageContent(content) {
35481
+ if (typeof content === "string") return content.trim();
35482
+ if (content == null) return "";
35483
+ try {
35484
+ return JSON.stringify(content).trim();
35485
+ } catch {
35486
+ return String(content).trim();
35487
+ }
35488
+ }
35489
+ function extractCanonicalHermesMessageTimestamp(message, fallbackTs) {
35490
+ const numericTimestamp = Number(message.receivedAt || message.timestamp || message.ts || 0);
35491
+ if (Number.isFinite(numericTimestamp) && numericTimestamp > 0) return numericTimestamp;
35492
+ const stringTimestamp = typeof message.ts === "string" ? Date.parse(message.ts) : typeof message.timestamp === "string" ? Date.parse(message.timestamp) : NaN;
35493
+ if (Number.isFinite(stringTimestamp) && stringTimestamp > 0) return stringTimestamp;
35494
+ return fallbackTs;
35495
+ }
35496
+ function readExistingHermesSessionStartRecord(historySessionId) {
35497
+ try {
35498
+ const dir = path7.join(HISTORY_DIR, "hermes-cli");
35499
+ if (!fs32.existsSync(dir)) return null;
35500
+ const files = listHistoryFiles(dir, historySessionId).sort();
35501
+ for (const file2 of files) {
35502
+ const lines = fs32.readFileSync(path7.join(dir, file2), "utf-8").split("\n").filter(Boolean);
35503
+ for (const line of lines) {
35504
+ try {
35505
+ const parsed = JSON.parse(line);
35506
+ if (parsed.historySessionId !== historySessionId) continue;
35507
+ if (parsed.kind === "session_start" && parsed.role === "system") {
35508
+ return parsed;
35509
+ }
35510
+ } catch {
35511
+ }
35512
+ }
35513
+ }
35514
+ return null;
35515
+ } catch {
35516
+ return null;
35517
+ }
35518
+ }
35519
+ function rebuildHermesSavedHistoryFromCanonicalSession(historySessionId) {
35520
+ const normalizedSessionId = normalizeSavedHistorySessionId("hermes-cli", historySessionId);
35521
+ if (!normalizedSessionId) return false;
35522
+ try {
35523
+ const sessionFilePath = path7.join(os52.homedir(), ".hermes", "sessions", `session_${normalizedSessionId}.json`);
35524
+ if (!fs32.existsSync(sessionFilePath)) return false;
35525
+ const raw = JSON.parse(fs32.readFileSync(sessionFilePath, "utf-8"));
35526
+ const canonicalMessages = Array.isArray(raw.messages) ? raw.messages : [];
35527
+ const dir = path7.join(HISTORY_DIR, "hermes-cli");
35528
+ fs32.mkdirSync(dir, { recursive: true });
35529
+ const existingSessionStart = readExistingHermesSessionStartRecord(normalizedSessionId);
35530
+ const records = [];
35531
+ if (existingSessionStart) {
35532
+ records.push({
35533
+ ...existingSessionStart,
35534
+ historySessionId: normalizedSessionId
35535
+ });
35536
+ }
35537
+ let fallbackTs = Date.parse(raw.session_start || raw.last_updated || "") || Date.now();
35538
+ for (const message of canonicalMessages) {
35539
+ const role = String(message.role || "").trim();
35540
+ const content = normalizeCanonicalHermesMessageContent(message.content);
35541
+ if (!content) continue;
35542
+ const receivedAt = extractCanonicalHermesMessageTimestamp(message, fallbackTs);
35543
+ fallbackTs = receivedAt + 1;
35544
+ if (role === "user") {
35545
+ records.push({
35546
+ ts: new Date(receivedAt).toISOString(),
35547
+ receivedAt,
35548
+ role: "user",
35549
+ content,
35550
+ kind: "standard",
35551
+ agent: "hermes-cli",
35552
+ historySessionId: normalizedSessionId
35553
+ });
35554
+ continue;
35555
+ }
35556
+ if (role === "assistant") {
35557
+ records.push({
35558
+ ts: new Date(receivedAt).toISOString(),
35559
+ receivedAt,
35560
+ role: "assistant",
35561
+ content,
35562
+ kind: "standard",
35563
+ agent: "hermes-cli",
35564
+ historySessionId: normalizedSessionId
35565
+ });
35566
+ continue;
35567
+ }
35568
+ if (role === "tool") {
35569
+ records.push({
35570
+ ts: new Date(receivedAt).toISOString(),
35571
+ receivedAt,
35572
+ role: "assistant",
35573
+ content,
35574
+ kind: "tool",
35575
+ senderName: "Tool",
35576
+ agent: "hermes-cli",
35577
+ historySessionId: normalizedSessionId
35578
+ });
35579
+ }
35580
+ }
35581
+ if (records.length === 0) return false;
35582
+ const prefix = `${normalizedSessionId.replace(/[^a-zA-Z0-9_-]/g, "_")}_`;
35583
+ for (const file2 of fs32.readdirSync(dir)) {
35584
+ if (file2.startsWith(prefix) && file2.endsWith(".jsonl")) {
35585
+ fs32.unlinkSync(path7.join(dir, file2));
35586
+ }
35587
+ }
35588
+ const targetDate = new Date(records[records.length - 1].receivedAt || Date.now()).toISOString().slice(0, 10);
35589
+ const filePath = path7.join(dir, `${prefix}${targetDate}.jsonl`);
35590
+ fs32.writeFileSync(filePath, `${records.map((record2) => JSON.stringify(record2)).join("\n")}
35591
+ `, "utf-8");
35592
+ invalidatePersistedSavedHistoryIndex("hermes-cli", dir);
35593
+ savedHistorySessionCache.delete("hermes-cli");
35594
+ return true;
35595
+ } catch {
35596
+ return false;
35597
+ }
35598
+ }
35480
35599
  function isControlValue(value) {
35481
35600
  return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
35482
35601
  }
@@ -40323,6 +40442,7 @@ ${effect.notification.body || ""}`.trim();
40323
40442
  historyWriter;
40324
40443
  runtimeMessages = [];
40325
40444
  lastPersistedHistoryMessages = [];
40445
+ lastCanonicalHermesSyncMtimeMs = 0;
40326
40446
  instanceId;
40327
40447
  suppressIdleHistoryReplay = false;
40328
40448
  errorMessage = void 0;
@@ -40355,34 +40475,7 @@ ${effect.notification.body || ""}`.trim();
40355
40475
  await this.enforceFreshSessionLaunchIfNeeded();
40356
40476
  this.maybeAppendRuntimeRecoveryMessage(this.adapter.getRuntimeMetadata());
40357
40477
  if (this.providerSessionId) {
40358
- this.historyWriter.compactHistorySession(this.type, this.providerSessionId);
40359
- const restoredHistory = readChatHistory(this.type, 0, 200, this.providerSessionId);
40360
- this.historyWriter.seedSessionHistory(
40361
- this.type,
40362
- restoredHistory.messages,
40363
- this.providerSessionId,
40364
- this.instanceId
40365
- );
40366
- this.lastPersistedHistoryMessages = restoredHistory.messages.map((message) => ({
40367
- role: message.role,
40368
- content: message.content,
40369
- kind: message.kind,
40370
- senderName: message.senderName,
40371
- receivedAt: message.receivedAt
40372
- }));
40373
- this.suppressIdleHistoryReplay = restoredHistory.messages.length > 0;
40374
- if (restoredHistory.messages.length > 0) {
40375
- this.adapter.seedCommittedMessages(
40376
- restoredHistory.messages.map((message) => ({
40377
- role: message.role,
40378
- content: message.content,
40379
- timestamp: message.receivedAt,
40380
- receivedAt: message.receivedAt,
40381
- kind: message.kind,
40382
- senderName: message.senderName
40383
- }))
40384
- );
40385
- }
40478
+ this.restorePersistedHistoryFromCurrentSession();
40386
40479
  }
40387
40480
  if (this.providerSessionId && this.launchMode === "resume") {
40388
40481
  const resumedAt = Date.now();
@@ -40491,6 +40584,7 @@ ${effect.notification.body || ""}`.trim();
40491
40584
  parsedMessages = historyMessageCount > 0 ? parsedMessages.slice(-historyMessageCount) : [];
40492
40585
  }
40493
40586
  const mergedMessages = this.mergeConversationMessages(parsedMessages);
40587
+ const canonicalHermesBackedHistory = this.syncCanonicalHermesSavedHistoryIfNeeded();
40494
40588
  const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
40495
40589
  if (parsedMessages.length > 0) {
40496
40590
  const shouldSkipReplayPersist = this.suppressIdleHistoryReplay && adapterStatus.status === "idle" && parsedStatus?.status === "idle";
@@ -40508,7 +40602,7 @@ ${effect.notification.body || ""}`.trim();
40508
40602
  senderName: typeof message.senderName === "string" ? message.senderName : void 0,
40509
40603
  receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
40510
40604
  }));
40511
- if (!shouldSkipReplayPersist && normalizedMessagesToSave.length > 0) {
40605
+ if (!canonicalHermesBackedHistory && !shouldSkipReplayPersist && normalizedMessagesToSave.length > 0) {
40512
40606
  const incrementalMessages = buildIncrementalHistoryAppendMessages(this.lastPersistedHistoryMessages, normalizedMessagesToSave);
40513
40607
  this.historyWriter.appendNewMessages(
40514
40608
  this.type,
@@ -40518,7 +40612,9 @@ ${effect.notification.body || ""}`.trim();
40518
40612
  this.providerSessionId
40519
40613
  );
40520
40614
  }
40521
- this.lastPersistedHistoryMessages = normalizedMessagesToSave;
40615
+ if (!canonicalHermesBackedHistory) {
40616
+ this.lastPersistedHistoryMessages = normalizedMessagesToSave;
40617
+ }
40522
40618
  }
40523
40619
  this.applyProviderResponse(parsedStatus, { phase: "immediate" });
40524
40620
  const surface = resolveProviderStateSurface({
@@ -40975,6 +41071,7 @@ ${effect.notification.body || ""}`.trim();
40975
41071
  this.providerSessionId = nextSessionId;
40976
41072
  this.historyWriter.promoteHistorySession(this.type, previousHistorySessionId, nextSessionId);
40977
41073
  this.historyWriter.writeSessionStart(this.type, nextSessionId, this.workingDir, this.instanceId);
41074
+ this.restorePersistedHistoryFromCurrentSession();
40978
41075
  this.adapter.updateRuntimeMeta({ providerSessionId: nextSessionId });
40979
41076
  this.onProviderSessionResolved?.({
40980
41077
  instanceId: this.instanceId,
@@ -40986,6 +41083,61 @@ ${effect.notification.body || ""}`.trim();
40986
41083
  });
40987
41084
  LOG2.info("CLI", `[${this.type}] discovered provider session id: ${nextSessionId}`);
40988
41085
  }
41086
+ syncCanonicalHermesSavedHistoryIfNeeded() {
41087
+ if (this.type !== "hermes-cli" || !this.providerSessionId) return false;
41088
+ try {
41089
+ const canonicalPath = path11.join(os11.homedir(), ".hermes", "sessions", `session_${this.providerSessionId}.json`);
41090
+ if (!fs52.existsSync(canonicalPath)) return false;
41091
+ const stat4 = fs52.statSync(canonicalPath);
41092
+ if (stat4.mtimeMs <= this.lastCanonicalHermesSyncMtimeMs) return true;
41093
+ const rebuilt = rebuildHermesSavedHistoryFromCanonicalSession(this.providerSessionId);
41094
+ if (!rebuilt) return false;
41095
+ this.lastCanonicalHermesSyncMtimeMs = stat4.mtimeMs;
41096
+ const restoredHistory = readChatHistory(this.type, 0, Number.MAX_SAFE_INTEGER, this.providerSessionId);
41097
+ this.lastPersistedHistoryMessages = restoredHistory.messages.map((message) => ({
41098
+ role: message.role,
41099
+ content: message.content,
41100
+ kind: message.kind,
41101
+ senderName: message.senderName,
41102
+ receivedAt: message.receivedAt
41103
+ }));
41104
+ return true;
41105
+ } catch {
41106
+ return false;
41107
+ }
41108
+ }
41109
+ restorePersistedHistoryFromCurrentSession() {
41110
+ if (!this.providerSessionId) return;
41111
+ this.syncCanonicalHermesSavedHistoryIfNeeded();
41112
+ this.historyWriter.compactHistorySession(this.type, this.providerSessionId);
41113
+ const restoredHistory = readChatHistory(this.type, 0, Number.MAX_SAFE_INTEGER, this.providerSessionId);
41114
+ this.historyWriter.seedSessionHistory(
41115
+ this.type,
41116
+ restoredHistory.messages,
41117
+ this.providerSessionId,
41118
+ this.instanceId
41119
+ );
41120
+ this.lastPersistedHistoryMessages = restoredHistory.messages.map((message) => ({
41121
+ role: message.role,
41122
+ content: message.content,
41123
+ kind: message.kind,
41124
+ senderName: message.senderName,
41125
+ receivedAt: message.receivedAt
41126
+ }));
41127
+ this.suppressIdleHistoryReplay = restoredHistory.messages.length > 0;
41128
+ if (restoredHistory.messages.length > 0) {
41129
+ this.adapter.seedCommittedMessages(
41130
+ restoredHistory.messages.map((message) => ({
41131
+ role: message.role,
41132
+ content: message.content,
41133
+ timestamp: message.receivedAt,
41134
+ receivedAt: message.receivedAt,
41135
+ kind: message.kind,
41136
+ senderName: message.senderName
41137
+ }))
41138
+ );
41139
+ }
41140
+ }
40989
41141
  getProbeDirectories() {
40990
41142
  const dirs = /* @__PURE__ */ new Set();
40991
41143
  const addDir = (value) => {