@hermespilot/link 0.8.2 → 0.8.3

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.
@@ -5,7 +5,7 @@ import Router from "@koa/router";
5
5
  // src/conversations/conversation-service.ts
6
6
  import { EventEmitter } from "events";
7
7
  import { createHash as createHash9, randomUUID as randomUUID13 } from "crypto";
8
- import path27 from "path";
8
+ import path28 from "path";
9
9
 
10
10
  // src/database/link-database.ts
11
11
  import { mkdir } from "fs/promises";
@@ -7632,7 +7632,7 @@ async function listCronOutputFiles(profileName, jobId) {
7632
7632
  orderTimeMs: fileStat.mtimeMs
7633
7633
  });
7634
7634
  }
7635
- return files.sort((left, right) => left.orderTimeMs - right.orderTimeMs).map(({ path: path38, mtime }) => ({ path: path38, mtime }));
7635
+ return files.sort((left, right) => left.orderTimeMs - right.orderTimeMs).map(({ path: path39, mtime }) => ({ path: path39, mtime }));
7636
7636
  }
7637
7637
  function readCronOutputTimestamp(fileName) {
7638
7638
  const match = fileName.match(
@@ -7721,7 +7721,7 @@ function isConversationMissingError(error) {
7721
7721
  }
7722
7722
 
7723
7723
  // src/constants.ts
7724
- var LINK_VERSION = "0.8.2";
7724
+ var LINK_VERSION = "0.8.3";
7725
7725
  var LINK_COMMAND = "hermeslink";
7726
7726
  var LINK_DEFAULT_PORT = 52379;
7727
7727
  var LINK_RUNTIME_DIR_NAME = ".hermeslink";
@@ -21380,6 +21380,7 @@ var MESSAGE_COLUMNS = [
21380
21380
  "reasoning_details",
21381
21381
  "codex_reasoning_items"
21382
21382
  ];
21383
+ var HERMES_ROW_SESSION_POSITION = /* @__PURE__ */ Symbol("hermesRowSessionPosition");
21383
21384
  async function syncHermesSessionsIntoConversations(paths, logger, options = {}) {
21384
21385
  const maxImports = options.maxImports ?? MAX_IMPORTABLE_SESSIONS;
21385
21386
  const store = new ConversationStore(paths);
@@ -21585,7 +21586,7 @@ async function syncHermesCronSessionIntoConversations(paths, logger, input) {
21585
21586
  async function syncHermesConversationMessages(paths, logger, input) {
21586
21587
  const store = input.store ?? new ConversationStore(paths);
21587
21588
  const manifest = await store.readActiveManifest(input.conversationId);
21588
- const snapshot = await store.readSnapshot(input.conversationId);
21589
+ let snapshot = await store.readSnapshot(input.conversationId);
21589
21590
  const targets = collectHermesSessionDeleteTargets(manifest, snapshot);
21590
21591
  const result = {
21591
21592
  conversation_id: input.conversationId,
@@ -21597,8 +21598,15 @@ async function syncHermesConversationMessages(paths, logger, input) {
21597
21598
  if (targets.length === 0) {
21598
21599
  return result;
21599
21600
  }
21601
+ const duplicateCleanup = pruneStrictImportedDuplicateMessages(paths, snapshot);
21602
+ if (duplicateCleanup.removedCount > 0) {
21603
+ snapshot = duplicateCleanup.snapshot;
21604
+ result.removed_duplicate_count = duplicateCleanup.removedCount;
21605
+ result.changed = true;
21606
+ }
21600
21607
  const candidates = await collectConversationSyncCandidates(targets);
21601
21608
  const knownExactKeys = collectKnownHermesRowKeys(snapshot);
21609
+ const representedRows = collectRepresentedHermesRows(paths, snapshot);
21602
21610
  const representedMessages = collectRepresentedMessageSignatures(snapshot);
21603
21611
  const projectedMessages = [];
21604
21612
  const candidateProfiles = /* @__PURE__ */ new Map();
@@ -21608,6 +21616,12 @@ async function syncHermesConversationMessages(paths, logger, input) {
21608
21616
  if (candidateMessages.length === 0) {
21609
21617
  continue;
21610
21618
  }
21619
+ const missingCandidateMessages = candidateMessages.filter(
21620
+ (message, index) => !isRepresentedHermesRow(representedRows, message, index)
21621
+ );
21622
+ if (missingCandidateMessages.length === 0) {
21623
+ continue;
21624
+ }
21611
21625
  const profile = await resolveConversationProfileTarget(
21612
21626
  paths,
21613
21627
  candidate.profileName
@@ -21624,7 +21638,7 @@ async function syncHermesConversationMessages(paths, logger, input) {
21624
21638
  profileUid: profile.profileUid,
21625
21639
  profileDisplayName: profile.profileDisplayName,
21626
21640
  sessionId: candidate.session.id,
21627
- messages: candidateMessages
21641
+ messages: missingCandidateMessages
21628
21642
  })
21629
21643
  );
21630
21644
  } catch (error) {
@@ -21650,6 +21664,14 @@ async function syncHermesConversationMessages(paths, logger, input) {
21650
21664
  exactKeys.forEach((key) => knownExactKeys.add(key));
21651
21665
  }
21652
21666
  if (appendedMessages.length === 0) {
21667
+ if (duplicateCleanup.removedCount > 0) {
21668
+ await store.writeSnapshot(input.conversationId, snapshot);
21669
+ const currentManifest = await store.readManifest(input.conversationId);
21670
+ const stats2 = buildConversationStats(currentManifest, snapshot);
21671
+ const nextManifest2 = { ...currentManifest, stats: stats2 };
21672
+ await store.writeManifest(nextManifest2);
21673
+ await upsertConversationStats(paths, toStatsIndexRecord(nextManifest2, stats2));
21674
+ }
21653
21675
  return result;
21654
21676
  }
21655
21677
  await store.writeSnapshot(input.conversationId, {
@@ -22019,6 +22041,293 @@ function collectKnownHermesRowKeys(snapshot) {
22019
22041
  }
22020
22042
  return keys;
22021
22043
  }
22044
+ function collectRepresentedHermesRows(paths, snapshot) {
22045
+ const rows = {
22046
+ syntheticUserTexts: /* @__PURE__ */ new Set(),
22047
+ toolCallIds: /* @__PURE__ */ new Set(),
22048
+ runWindows: []
22049
+ };
22050
+ for (const run of snapshot.runs) {
22051
+ collectRunHermesMessageWindows(run).forEach(
22052
+ (window) => rows.runWindows.push(window)
22053
+ );
22054
+ const userMessage = snapshot.messages.find(
22055
+ (message) => message.id === run.trigger_message_id
22056
+ );
22057
+ if (userMessage) {
22058
+ collectSyntheticRunInputTexts(paths, userMessage).forEach(
22059
+ (text) => rows.syntheticUserTexts.add(hashText(text))
22060
+ );
22061
+ }
22062
+ const assistantMessage = snapshot.messages.find(
22063
+ (message) => message.id === run.assistant_message_id
22064
+ );
22065
+ if (assistantMessage) {
22066
+ collectAgentEventIds(assistantMessage).forEach(
22067
+ (id) => rows.toolCallIds.add(id)
22068
+ );
22069
+ }
22070
+ }
22071
+ return rows;
22072
+ }
22073
+ function pruneStrictImportedDuplicateMessages(paths, snapshot) {
22074
+ if (snapshot.runs.length === 0) {
22075
+ return { snapshot, removedCount: 0 };
22076
+ }
22077
+ const messages2 = snapshot.messages.filter(
22078
+ (message) => !isStrictImportedDuplicateRunMessage(paths, snapshot, message)
22079
+ );
22080
+ const removedCount = snapshot.messages.length - messages2.length;
22081
+ return removedCount > 0 ? { snapshot: { ...snapshot, messages: messages2 }, removedCount } : { snapshot, removedCount: 0 };
22082
+ }
22083
+ function isStrictImportedDuplicateRunMessage(paths, snapshot, message) {
22084
+ if (!isHermesImportedMessage2(message)) {
22085
+ return false;
22086
+ }
22087
+ if (snapshot.runs.some(
22088
+ (run) => run.trigger_message_id === message.id || run.assistant_message_id === message.id
22089
+ )) {
22090
+ return false;
22091
+ }
22092
+ const messageSessionIds = collectMessageHermesSessionIds(message);
22093
+ if (messageSessionIds.size === 0) {
22094
+ return false;
22095
+ }
22096
+ return snapshot.runs.some((run) => {
22097
+ if (!runSessionMatchesMessage(run, messageSessionIds)) {
22098
+ return false;
22099
+ }
22100
+ if (!isMessageInsideRunCleanupWindow(message, run)) {
22101
+ return false;
22102
+ }
22103
+ if (message.role === "user") {
22104
+ const user = snapshot.messages.find(
22105
+ (item) => item.id === run.trigger_message_id
22106
+ );
22107
+ return user ? isDuplicateImportedRunUser(paths, user, message) : false;
22108
+ }
22109
+ if (message.role === "assistant" || message.role === "tool") {
22110
+ const assistant = snapshot.messages.find(
22111
+ (item) => item.id === run.assistant_message_id
22112
+ );
22113
+ return assistant ? isDuplicateImportedRunAssistant(assistant, message) : false;
22114
+ }
22115
+ return false;
22116
+ });
22117
+ }
22118
+ function isDuplicateImportedRunUser(paths, user, imported) {
22119
+ const importedText = normalizedDuplicateText(imported);
22120
+ if (!importedText) {
22121
+ return false;
22122
+ }
22123
+ if (importedText === normalizedDuplicateText(user)) {
22124
+ return true;
22125
+ }
22126
+ return collectSyntheticRunInputTexts(paths, user).some(
22127
+ (text) => normalizedDuplicateTextValue(text) === importedText
22128
+ );
22129
+ }
22130
+ function isDuplicateImportedRunAssistant(assistant, imported) {
22131
+ const importedText = normalizedDuplicateText(imported);
22132
+ if (importedText && importedText === normalizedDuplicateText(assistant)) {
22133
+ return true;
22134
+ }
22135
+ const importedToolIds = collectAgentEventIds(imported);
22136
+ if (importedToolIds.size === 0) {
22137
+ return false;
22138
+ }
22139
+ const assistantToolIds = collectAgentEventIds(assistant);
22140
+ return [...importedToolIds].every((id) => assistantToolIds.has(id));
22141
+ }
22142
+ function collectMessageHermesSessionIds(message) {
22143
+ const sessionIds = /* @__PURE__ */ new Set();
22144
+ const hermes = toRecord12(message.hermes);
22145
+ const sessionId = readString12(hermes, "session_id");
22146
+ if (sessionId) {
22147
+ sessionIds.add(sessionId);
22148
+ }
22149
+ for (const row of readHermesRawMessageRows(message.raw)) {
22150
+ const rowSessionId = readString12(row, "session_id");
22151
+ if (rowSessionId) {
22152
+ sessionIds.add(rowSessionId);
22153
+ }
22154
+ }
22155
+ return sessionIds;
22156
+ }
22157
+ function runSessionMatchesMessage(run, messageSessionIds) {
22158
+ return collectRunHermesSessionIds(run).some(
22159
+ (sessionId) => messageSessionIds.has(sessionId)
22160
+ );
22161
+ }
22162
+ function collectRunHermesSessionIds(run) {
22163
+ return normalizeSessionIds([
22164
+ run.hermes_session_id,
22165
+ run.hermes_message_watermark?.before?.session_id,
22166
+ run.hermes_message_watermark?.after?.session_id
22167
+ ]);
22168
+ }
22169
+ function isMessageInsideRunCleanupWindow(message, run) {
22170
+ if (run.status === "queued" || run.status === "running" || run.status === "unknown") {
22171
+ return false;
22172
+ }
22173
+ const messageAt = parseIsoMillis(message.created_at);
22174
+ const startedAt = parseIsoMillis(run.started_at);
22175
+ const completedAt = run.completed_at ? parseIsoMillis(run.completed_at) : void 0;
22176
+ if (messageAt === void 0 || startedAt === void 0) {
22177
+ return false;
22178
+ }
22179
+ const lowerBound = startedAt - 10 * 60 * 1e3;
22180
+ const upperBound = (completedAt ?? startedAt) + 10 * 60 * 1e3;
22181
+ return messageAt >= lowerBound && messageAt <= upperBound;
22182
+ }
22183
+ function normalizedDuplicateText(message) {
22184
+ return normalizedDuplicateTextValue(messageText2(message));
22185
+ }
22186
+ function normalizedDuplicateTextValue(value) {
22187
+ return value.replace(/\r\n/gu, "\n").trim();
22188
+ }
22189
+ function collectRunHermesMessageWindows(run) {
22190
+ const before = normalizeWatermarkPoint(
22191
+ run.hermes_message_watermark?.before,
22192
+ run.hermes_session_id
22193
+ );
22194
+ if (!before) {
22195
+ return [];
22196
+ }
22197
+ const after = normalizeWatermarkPoint(
22198
+ run.hermes_message_watermark?.after,
22199
+ run.hermes_session_id
22200
+ );
22201
+ const sessionId = before.session_id?.trim() || run.hermes_session_id?.trim();
22202
+ if (!sessionId) {
22203
+ return [];
22204
+ }
22205
+ return [
22206
+ {
22207
+ runId: run.id,
22208
+ sessionId,
22209
+ status: run.status,
22210
+ before,
22211
+ ...after && (after.session_id ?? sessionId) === sessionId ? { after } : {},
22212
+ startedAtMs: parseIsoMillis(run.started_at),
22213
+ completedAtMs: run.completed_at ? parseIsoMillis(run.completed_at) : void 0
22214
+ }
22215
+ ];
22216
+ }
22217
+ function normalizeWatermarkPoint(point, fallbackSessionId) {
22218
+ if (!point || typeof point.message_count !== "number" || !Number.isFinite(point.message_count)) {
22219
+ return null;
22220
+ }
22221
+ const sessionId = point.session_id?.trim() || fallbackSessionId?.trim();
22222
+ return {
22223
+ source: point.source,
22224
+ ...sessionId ? { session_id: sessionId } : {},
22225
+ message_count: Math.max(0, Math.trunc(point.message_count)),
22226
+ ...typeof point.max_message_id === "number" && Number.isFinite(point.max_message_id) ? { max_message_id: point.max_message_id } : {},
22227
+ ...typeof point.max_timestamp === "number" && Number.isFinite(point.max_timestamp) ? { max_timestamp: point.max_timestamp } : {},
22228
+ captured_at: point.captured_at
22229
+ };
22230
+ }
22231
+ function collectSyntheticRunInputTexts(paths, message) {
22232
+ if (message.role !== "user") {
22233
+ return [];
22234
+ }
22235
+ const attachmentLines = message.parts.filter((part) => Boolean(part.blob)).filter((part) => !isVoicePart(part)).map((part) => {
22236
+ const label = part.filename ?? part.blob;
22237
+ const mime = part.mime ? `, ${part.mime}` : "";
22238
+ const size = part.size ? `, ${part.size} bytes` : "";
22239
+ return `- ${label}${mime}${size}: ${part.local_path ?? blobPath(paths, part.blob)}`;
22240
+ });
22241
+ if (attachmentLines.length === 0) {
22242
+ return [];
22243
+ }
22244
+ const content = messageText2(message);
22245
+ const prefix = content ? `${content}
22246
+
22247
+ ` : "";
22248
+ return [
22249
+ `${prefix}Attachments available on this computer:
22250
+ ${attachmentLines.join("\n")}`
22251
+ ];
22252
+ }
22253
+ function collectAgentEventIds(message) {
22254
+ const ids = /* @__PURE__ */ new Set();
22255
+ for (const event of message.agent_events ?? []) {
22256
+ if (event.id) {
22257
+ ids.add(event.id);
22258
+ }
22259
+ }
22260
+ for (const block of message.blocks ?? []) {
22261
+ if (block.type !== "agent_events") {
22262
+ continue;
22263
+ }
22264
+ for (const event of block.events) {
22265
+ if (event.id) {
22266
+ ids.add(event.id);
22267
+ }
22268
+ }
22269
+ }
22270
+ return ids;
22271
+ }
22272
+ function isRepresentedHermesRow(represented, row, index) {
22273
+ const role = normalizeMessageRole(row.role);
22274
+ if (represented.runWindows.some(
22275
+ (window) => isRowInsideRunWindow(window, row, role)
22276
+ )) {
22277
+ return true;
22278
+ }
22279
+ if (role === "user" && represented.syntheticUserTexts.has(hashText(normalizeContent2(row.content)))) {
22280
+ return true;
22281
+ }
22282
+ if (role === "assistant") {
22283
+ const toolCalls = readHermesToolCalls(row);
22284
+ return toolCalls.length > 0 && toolCalls.every(
22285
+ (toolCall) => toolCall.id && represented.toolCallIds.has(toolCall.id)
22286
+ );
22287
+ }
22288
+ if (role === "tool") {
22289
+ const id = readString12(row, "tool_call_id") ?? readString12(row, "tool_id") ?? readString12(row, "call_id");
22290
+ if (id) {
22291
+ return represented.toolCallIds.has(id);
22292
+ }
22293
+ const key = hermesRowKey(row, index);
22294
+ return represented.toolCallIds.has(key);
22295
+ }
22296
+ return false;
22297
+ }
22298
+ function isRowInsideRunWindow(window, row, role) {
22299
+ if (role === "system") {
22300
+ return false;
22301
+ }
22302
+ if ((readString12(row, "session_id") ?? "") !== window.sessionId) {
22303
+ return false;
22304
+ }
22305
+ const hasClosedAfter = Boolean(window.after);
22306
+ const allowOpenEnded = window.status === "running";
22307
+ const allowTerminalGrace = !hasClosedAfter && (window.status === "cancelled" || window.status === "failed") && window.completedAtMs !== void 0;
22308
+ if (!hasClosedAfter && !allowOpenEnded && !allowTerminalGrace) {
22309
+ return false;
22310
+ }
22311
+ const position = rowSessionPosition(row);
22312
+ if (window.before.source !== "none" && position !== void 0 && position > window.before.message_count && (window.after ? position <= window.after.message_count : allowOpenEnded)) {
22313
+ return true;
22314
+ }
22315
+ const rowId = readNumber3(row.id);
22316
+ if (rowId !== null && window.before.max_message_id !== void 0 && rowId > window.before.max_message_id && (window.after?.max_message_id !== void 0 ? rowId <= window.after.max_message_id : allowOpenEnded)) {
22317
+ return true;
22318
+ }
22319
+ const rowTimeMs = hermesTimestampMillis(row.timestamp);
22320
+ if (rowTimeMs === void 0) {
22321
+ return false;
22322
+ }
22323
+ const beforeTimeMs = hermesTimestampMillis(window.before.max_timestamp);
22324
+ const lowerTimeMs = beforeTimeMs ?? (window.startedAtMs ?? 0) - 5e3;
22325
+ const upperTimeMs = hermesTimestampMillis(window.after?.max_timestamp) ?? (allowTerminalGrace && window.completedAtMs !== void 0 ? window.completedAtMs + 2 * 60 * 1e3 : allowOpenEnded ? Number.POSITIVE_INFINITY : void 0);
22326
+ return upperTimeMs !== void 0 && (beforeTimeMs !== void 0 ? rowTimeMs > lowerTimeMs : rowTimeMs >= lowerTimeMs) && rowTimeMs <= upperTimeMs;
22327
+ }
22328
+ function isVoicePart(part) {
22329
+ return part.kind === "voice" || part.is_voice_note === true;
22330
+ }
22022
22331
  function collectMessageHermesRowKeys(message) {
22023
22332
  const keys = [];
22024
22333
  readHermesRawMessageRows(message.raw).forEach((row, index) => {
@@ -22072,6 +22381,21 @@ function representedMessageSignature(message) {
22072
22381
  function hashText(value) {
22073
22382
  return createHash6("sha256").update(value).digest("hex");
22074
22383
  }
22384
+ function rowSessionPosition(row) {
22385
+ const position = row[HERMES_ROW_SESSION_POSITION];
22386
+ return typeof position === "number" && Number.isFinite(position) ? position : void 0;
22387
+ }
22388
+ function hermesTimestampMillis(value) {
22389
+ const numeric = readNumber3(value);
22390
+ if (numeric === null || numeric <= 0) {
22391
+ return void 0;
22392
+ }
22393
+ return numeric > 1e10 ? numeric : numeric * 1e3;
22394
+ }
22395
+ function parseIsoMillis(value) {
22396
+ const parsed = Date.parse(value);
22397
+ return Number.isFinite(parsed) ? parsed : void 0;
22398
+ }
22075
22399
  function compareLinkMessagesByCreatedAt(left, right) {
22076
22400
  return Date.parse(left.created_at) - Date.parse(right.created_at) || left.id.localeCompare(right.id);
22077
22401
  }
@@ -23066,9 +23390,15 @@ async function readHermesSessionMessages(candidate) {
23066
23390
  readJsonlMessages(candidate.profileName, candidate.session.id)
23067
23391
  ]);
23068
23392
  const selected = jsonlMessages.length > dbMessages.length ? jsonlMessages : dbMessages;
23069
- return selected.map(
23070
- (message) => readString12(message, "session_id") ? message : { ...message, session_id: candidate.session.id }
23071
- );
23393
+ return selected.map((message, index) => {
23394
+ const normalized = readString12(message, "session_id") ? message : { ...message, session_id: candidate.session.id };
23395
+ Object.defineProperty(normalized, HERMES_ROW_SESSION_POSITION, {
23396
+ value: index + 1,
23397
+ enumerable: false,
23398
+ configurable: true
23399
+ });
23400
+ return normalized;
23401
+ });
23072
23402
  }
23073
23403
  async function readStateDbMessages(dbPath, sessionId) {
23074
23404
  if (!await isFile(dbPath)) {
@@ -24181,10 +24511,10 @@ function parseHermesApiCapabilities(payload) {
24181
24511
  sessionKeyHeader: readString14(features, "session_key_header")
24182
24512
  };
24183
24513
  }
24184
- async function callHermesApi(path38, init, options) {
24514
+ async function callHermesApi(path39, init, options) {
24185
24515
  const method = init.method ?? "GET";
24186
24516
  const startedAt = Date.now();
24187
- void options.logger?.debug("hermes_api_request_started", { method, path: path38 });
24517
+ void options.logger?.debug("hermes_api_request_started", { method, path: path39 });
24188
24518
  const availability = await ensureHermesApiServerAvailable({
24189
24519
  fetchImpl: options.fetchImpl,
24190
24520
  logger: options.logger,
@@ -24193,7 +24523,7 @@ async function callHermesApi(path38, init, options) {
24193
24523
  });
24194
24524
  let config = availability.configResult.apiServer;
24195
24525
  const fetcher = options.fetchImpl ?? fetch;
24196
- const request = () => fetchHermesApi(fetcher, config, path38, init, options);
24526
+ const request = () => fetchHermesApi(fetcher, config, path39, init, options);
24197
24527
  let response;
24198
24528
  try {
24199
24529
  response = await request();
@@ -24201,7 +24531,7 @@ async function callHermesApi(path38, init, options) {
24201
24531
  logHermesApiError(
24202
24532
  options.logger,
24203
24533
  method,
24204
- path38,
24534
+ path39,
24205
24535
  options.profileName,
24206
24536
  startedAt,
24207
24537
  error
@@ -24212,7 +24542,7 @@ async function callHermesApi(path38, init, options) {
24212
24542
  logHermesApiResponse(
24213
24543
  options.logger,
24214
24544
  method,
24215
- path38,
24545
+ path39,
24216
24546
  options.profileName,
24217
24547
  startedAt,
24218
24548
  response
@@ -24221,7 +24551,7 @@ async function callHermesApi(path38, init, options) {
24221
24551
  }
24222
24552
  void options.logger?.warn("hermes_api_request_retrying_after_401", {
24223
24553
  method,
24224
- path: path38,
24554
+ path: path39,
24225
24555
  profile: options.profileName ?? "default",
24226
24556
  port: config.port ?? null,
24227
24557
  duration_ms: Date.now() - startedAt
@@ -24240,7 +24570,7 @@ async function callHermesApi(path38, init, options) {
24240
24570
  logHermesApiError(
24241
24571
  options.logger,
24242
24572
  method,
24243
- path38,
24573
+ path39,
24244
24574
  options.profileName,
24245
24575
  startedAt,
24246
24576
  error
@@ -24250,7 +24580,7 @@ async function callHermesApi(path38, init, options) {
24250
24580
  logHermesApiResponse(
24251
24581
  options.logger,
24252
24582
  method,
24253
- path38,
24583
+ path39,
24254
24584
  options.profileName,
24255
24585
  startedAt,
24256
24586
  response
@@ -24260,7 +24590,7 @@ async function callHermesApi(path38, init, options) {
24260
24590
  }
24261
24591
  void options.logger?.warn("hermes_api_request_repairing_after_401", {
24262
24592
  method,
24263
- path: path38,
24593
+ path: path39,
24264
24594
  profile: options.profileName ?? "default",
24265
24595
  port: config.port ?? null,
24266
24596
  duration_ms: Date.now() - startedAt
@@ -24281,7 +24611,7 @@ async function callHermesApi(path38, init, options) {
24281
24611
  logHermesApiError(
24282
24612
  options.logger,
24283
24613
  method,
24284
- path38,
24614
+ path39,
24285
24615
  options.profileName,
24286
24616
  startedAt,
24287
24617
  error
@@ -24291,21 +24621,21 @@ async function callHermesApi(path38, init, options) {
24291
24621
  logHermesApiResponse(
24292
24622
  options.logger,
24293
24623
  method,
24294
- path38,
24624
+ path39,
24295
24625
  options.profileName,
24296
24626
  startedAt,
24297
24627
  response
24298
24628
  );
24299
24629
  return response;
24300
24630
  }
24301
- async function fetchHermesApi(fetcher, config, path38, init, options) {
24631
+ async function fetchHermesApi(fetcher, config, path39, init, options) {
24302
24632
  const headers = new Headers(init.headers);
24303
24633
  headers.set("accept", headers.get("accept") ?? "application/json");
24304
24634
  if (config.key) {
24305
24635
  headers.set("x-api-key", config.key);
24306
24636
  headers.set("authorization", `Bearer ${config.key}`);
24307
24637
  }
24308
- return await fetcher(`http://127.0.0.1:${config.port}${path38}`, {
24638
+ return await fetcher(`http://127.0.0.1:${config.port}${path39}`, {
24309
24639
  ...init,
24310
24640
  headers
24311
24641
  }).catch((error) => {
@@ -24314,10 +24644,10 @@ async function fetchHermesApi(fetcher, config, path38, init, options) {
24314
24644
  }
24315
24645
  void options.logger?.warn("hermes_api_server_connect_failed", {
24316
24646
  method: String(init.method ?? "GET").toUpperCase(),
24317
- path: path38,
24647
+ path: path39,
24318
24648
  profile: options.profileName ?? "default",
24319
24649
  port: config.port ?? null,
24320
- url: `http://127.0.0.1:${config.port}${path38}`,
24650
+ url: `http://127.0.0.1:${config.port}${path39}`,
24321
24651
  error: error instanceof Error ? error.message : String(error)
24322
24652
  });
24323
24653
  throw new LinkHttpError(
@@ -24327,10 +24657,10 @@ async function fetchHermesApi(fetcher, config, path38, init, options) {
24327
24657
  );
24328
24658
  });
24329
24659
  }
24330
- function logHermesApiResponse(logger, method, path38, profileName, startedAt, response) {
24660
+ function logHermesApiResponse(logger, method, path39, profileName, startedAt, response) {
24331
24661
  const fields = {
24332
24662
  method,
24333
- path: path38,
24663
+ path: path39,
24334
24664
  profile: profileName ?? "default",
24335
24665
  status: response.status,
24336
24666
  duration_ms: Date.now() - startedAt
@@ -24351,10 +24681,10 @@ async function logHermesApiFailureResponse(logger, fields, response) {
24351
24681
  ...upstreamError ? { upstream_error: upstreamError } : {}
24352
24682
  });
24353
24683
  }
24354
- function logHermesApiError(logger, method, path38, profileName, startedAt, error) {
24684
+ function logHermesApiError(logger, method, path39, profileName, startedAt, error) {
24355
24685
  void logger?.warn("hermes_api_request_failed", {
24356
24686
  method,
24357
- path: path38,
24687
+ path: path39,
24358
24688
  profile: profileName ?? "default",
24359
24689
  duration_ms: Date.now() - startedAt,
24360
24690
  ...error instanceof LinkHttpError ? { status: error.status, code: error.code } : {},
@@ -26790,6 +27120,127 @@ function isNodeError17(error, code) {
26790
27120
  return typeof error === "object" && error !== null && "code" in error && error.code === code;
26791
27121
  }
26792
27122
 
27123
+ // src/conversations/hermes-message-watermark.ts
27124
+ import { stat as stat18, readFile as readFile16 } from "fs/promises";
27125
+ import path27 from "path";
27126
+ async function readHermesMessageWatermark(input) {
27127
+ const profileName = input.profileName?.trim() || "default";
27128
+ const sessionId = input.sessionId.trim();
27129
+ const profileDir = resolveHermesProfileDir(profileName);
27130
+ const dbPath = path27.join(profileDir, "state.db");
27131
+ const [dbWatermark, jsonlWatermark] = await Promise.all([
27132
+ readStateDbMessageWatermark(dbPath, sessionId),
27133
+ readJsonlMessageWatermark(profileName, sessionId)
27134
+ ]);
27135
+ const selected = (jsonlWatermark.message_count ?? 0) > (dbWatermark.message_count ?? 0) ? jsonlWatermark : dbWatermark;
27136
+ return {
27137
+ ...selected,
27138
+ session_id: sessionId,
27139
+ captured_at: (/* @__PURE__ */ new Date()).toISOString()
27140
+ };
27141
+ }
27142
+ async function readStateDbMessageWatermark(dbPath, sessionId) {
27143
+ if (!await isFile3(dbPath)) {
27144
+ return { source: "none", message_count: 0 };
27145
+ }
27146
+ let db = null;
27147
+ try {
27148
+ db = openSqliteDatabase(dbPath, {
27149
+ readonly: true,
27150
+ timeout: 1e3
27151
+ });
27152
+ const columns = readTableColumns4(db, "messages");
27153
+ if (!columns.has("session_id")) {
27154
+ return { source: "none", message_count: 0 };
27155
+ }
27156
+ const idExpression = columns.has("id") ? "MAX(CASE WHEN typeof(id) IN ('integer', 'real') THEN id ELSE NULL END) AS max_message_id" : "NULL AS max_message_id";
27157
+ const timestampExpression = columns.has("timestamp") ? "MAX(timestamp) AS max_timestamp" : "NULL AS max_timestamp";
27158
+ const row = db.prepare(
27159
+ `
27160
+ SELECT COUNT(*) AS message_count, ${idExpression}, ${timestampExpression}
27161
+ FROM messages
27162
+ WHERE session_id = ?
27163
+ `
27164
+ ).get(sessionId);
27165
+ return {
27166
+ source: "state_db",
27167
+ message_count: readNumber5(row.message_count) ?? 0,
27168
+ ...readNumber5(row.max_message_id) !== null ? { max_message_id: readNumber5(row.max_message_id) } : {},
27169
+ ...readNumber5(row.max_timestamp) !== null ? { max_timestamp: readNumber5(row.max_timestamp) } : {}
27170
+ };
27171
+ } catch {
27172
+ return { source: "none", message_count: 0 };
27173
+ } finally {
27174
+ db?.close();
27175
+ }
27176
+ }
27177
+ async function readJsonlMessageWatermark(profileName, sessionId) {
27178
+ if (!/^[A-Za-z0-9._:-]{1,160}$/u.test(sessionId)) {
27179
+ return { source: "none", message_count: 0 };
27180
+ }
27181
+ const profileDir = resolveHermesProfileDir(profileName);
27182
+ const sessionsDir = await readHermesSessionsDir(profileName).then((value) => value.sessionsDir).catch(() => path27.join(profileDir, "sessions"));
27183
+ const transcriptPath = path27.join(sessionsDir, `${sessionId}.jsonl`);
27184
+ const raw = await readFile16(transcriptPath, "utf8").catch(() => "");
27185
+ if (!raw.trim()) {
27186
+ return { source: "none", message_count: 0 };
27187
+ }
27188
+ let messageCount = 0;
27189
+ let maxMessageId;
27190
+ let maxTimestamp;
27191
+ for (const line of raw.split(/\r?\n/u)) {
27192
+ if (!line.trim()) {
27193
+ continue;
27194
+ }
27195
+ try {
27196
+ const parsed = JSON.parse(line);
27197
+ if (!readString18(parsed, "role")) {
27198
+ continue;
27199
+ }
27200
+ messageCount += 1;
27201
+ const id = readNumber5(parsed.id);
27202
+ const timestamp = readNumber5(parsed.timestamp) ?? readNumber5(parsed.created_at) ?? readNumber5(parsed.createdAt);
27203
+ if (id !== null) {
27204
+ maxMessageId = maxMessageId === void 0 ? id : Math.max(maxMessageId, id);
27205
+ }
27206
+ if (timestamp !== null) {
27207
+ maxTimestamp = maxTimestamp === void 0 ? timestamp : Math.max(maxTimestamp, timestamp);
27208
+ }
27209
+ } catch {
27210
+ continue;
27211
+ }
27212
+ }
27213
+ return {
27214
+ source: messageCount > 0 ? "jsonl" : "none",
27215
+ message_count: messageCount,
27216
+ ...maxMessageId !== void 0 ? { max_message_id: maxMessageId } : {},
27217
+ ...maxTimestamp !== void 0 ? { max_timestamp: maxTimestamp } : {}
27218
+ };
27219
+ }
27220
+ function readTableColumns4(db, tableName) {
27221
+ try {
27222
+ const rows = db.prepare(`PRAGMA table_info(${quoteIdentifier3(tableName)})`).all();
27223
+ return new Set(
27224
+ rows.map((row) => typeof row.name === "string" ? row.name : "").filter(Boolean)
27225
+ );
27226
+ } catch {
27227
+ return /* @__PURE__ */ new Set();
27228
+ }
27229
+ }
27230
+ function quoteIdentifier3(value) {
27231
+ return `"${value.replaceAll('"', '""')}"`;
27232
+ }
27233
+ async function isFile3(filePath) {
27234
+ return stat18(filePath).then((value) => value.isFile()).catch(() => false);
27235
+ }
27236
+ function readString18(payload, key) {
27237
+ const value = payload[key];
27238
+ return typeof value === "string" && value.trim() ? value.trim() : null;
27239
+ }
27240
+ function readNumber5(value) {
27241
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
27242
+ }
27243
+
26793
27244
  // src/conversations/run-tool-event-ids.ts
26794
27245
  import { createHash as createHash7 } from "crypto";
26795
27246
  var RunToolEventIdCoalescer = class {
@@ -26883,7 +27334,7 @@ var RunToolEventIdCoalescer = class {
26883
27334
  }
26884
27335
  };
26885
27336
  function readToolEventType(event) {
26886
- const type = readString18(event.payload, "type") ?? readString18(event.payload, "event") ?? event.payloadType;
27337
+ const type = readString19(event.payload, "type") ?? readString19(event.payload, "event") ?? event.payloadType;
26887
27338
  return type.startsWith("tool.") ? type : null;
26888
27339
  }
26889
27340
  function isTerminalToolEvent(type) {
@@ -26894,14 +27345,14 @@ function hasStableToolEventId(payload) {
26894
27345
  const call = toRecord17(payload.tool_call ?? payload.toolCall);
26895
27346
  const fn = toRecord17(call.function ?? payload.function);
26896
27347
  return Boolean(
26897
- readString18(payload, "tool_call_id") ?? readString18(payload, "toolCallId") ?? readString18(payload, "tool_id") ?? readString18(payload, "call_id") ?? readString18(payload, "id") ?? readString18(tool, "id") ?? readString18(call, "id") ?? readString18(fn, "id")
27348
+ readString19(payload, "tool_call_id") ?? readString19(payload, "toolCallId") ?? readString19(payload, "tool_id") ?? readString19(payload, "call_id") ?? readString19(payload, "id") ?? readString19(tool, "id") ?? readString19(call, "id") ?? readString19(fn, "id")
26898
27349
  );
26899
27350
  }
26900
27351
  function readToolName2(payload) {
26901
27352
  const tool = toRecord17(payload.tool);
26902
27353
  const call = toRecord17(payload.tool_call ?? payload.toolCall);
26903
27354
  const fn = toRecord17(call.function ?? payload.function);
26904
- return readString18(payload, "tool_name") ?? readString18(payload, "toolName") ?? readString18(payload, "name") ?? readString18(payload, "tool") ?? readString18(tool, "name") ?? readString18(call, "name") ?? readString18(fn, "name") ?? "tool";
27355
+ return readString19(payload, "tool_name") ?? readString19(payload, "toolName") ?? readString19(payload, "name") ?? readString19(payload, "tool") ?? readString19(tool, "name") ?? readString19(call, "name") ?? readString19(fn, "name") ?? "tool";
26905
27356
  }
26906
27357
  function withGeneratedToolEventId(event, id) {
26907
27358
  return {
@@ -26958,7 +27409,7 @@ function stableStringify2(value) {
26958
27409
  function hashStableValue(value) {
26959
27410
  return createHash7("sha256").update(value).digest("hex").slice(0, 16);
26960
27411
  }
26961
- function readString18(payload, key) {
27412
+ function readString19(payload, key) {
26962
27413
  const value = payload[key];
26963
27414
  return typeof value === "string" && value.trim() ? value.trim() : null;
26964
27415
  }
@@ -26990,8 +27441,8 @@ function normalizeHermesStreamEvent(event) {
26990
27441
  };
26991
27442
  }
26992
27443
  if (event.eventName === "hermes.tool.progress") {
26993
- const toolName = readString19(event.payload, "tool") ?? readString19(event.payload, "name") ?? "tool";
26994
- const preview = readString19(event.payload, "label") ?? readString19(event.payload, "preview") ?? toolName;
27444
+ const toolName = readString20(event.payload, "tool") ?? readString20(event.payload, "name") ?? "tool";
27445
+ const preview = readString20(event.payload, "label") ?? readString20(event.payload, "preview") ?? toolName;
26995
27446
  return {
26996
27447
  ...event,
26997
27448
  payloadType: "tool.started",
@@ -27043,7 +27494,7 @@ function normalizeReasoningEvent(event) {
27043
27494
  if (type !== "tool.progress" && event.eventName !== "hermes.tool.progress") {
27044
27495
  return null;
27045
27496
  }
27046
- const toolName = readString19(event.payload, "tool_name") ?? readString19(event.payload, "tool") ?? readString19(event.payload, "name");
27497
+ const toolName = readString20(event.payload, "tool_name") ?? readString20(event.payload, "tool") ?? readString20(event.payload, "name");
27047
27498
  if (toolName !== "_thinking") {
27048
27499
  return null;
27049
27500
  }
@@ -27094,7 +27545,7 @@ function normalizeHermesResponseEvent(event) {
27094
27545
  }
27095
27546
  function normalizeResponseCreated(event) {
27096
27547
  const response = toRecord18(event.payload.response ?? event.payload);
27097
- const responseId = readString19(response, "id") ?? readString19(event.payload, "id");
27548
+ const responseId = readString20(response, "id") ?? readString20(event.payload, "id");
27098
27549
  return responseId ? {
27099
27550
  ...event,
27100
27551
  payloadType: "response.created",
@@ -27107,10 +27558,10 @@ function normalizeResponseCreated(event) {
27107
27558
  }
27108
27559
  function normalizeResponseOutputItemAdded(event) {
27109
27560
  const item = toRecord18(event.payload.item);
27110
- if (readString19(item, "type") !== "function_call") {
27561
+ if (readString20(item, "type") !== "function_call") {
27111
27562
  return null;
27112
27563
  }
27113
- const toolName = readString19(item, "name") ?? "tool";
27564
+ const toolName = readString20(item, "name") ?? "tool";
27114
27565
  const argumentsValue = parseJsonValue3(item.arguments) ?? item.arguments;
27115
27566
  return {
27116
27567
  ...event,
@@ -27120,16 +27571,16 @@ function normalizeResponseOutputItemAdded(event) {
27120
27571
  tool: toolName,
27121
27572
  tool_name: toolName,
27122
27573
  name: toolName,
27123
- tool_call_id: readString19(item, "call_id") ?? readString19(item, "id"),
27574
+ tool_call_id: readString20(item, "call_id") ?? readString20(item, "id"),
27124
27575
  arguments: argumentsValue,
27125
27576
  preview: toolName,
27126
- response_item_id: readString19(item, "id") ?? void 0
27577
+ response_item_id: readString20(item, "id") ?? void 0
27127
27578
  }
27128
27579
  };
27129
27580
  }
27130
27581
  function normalizeResponseOutputItemDone(event) {
27131
27582
  const item = toRecord18(event.payload.item);
27132
- if (readString19(item, "type") === "message") {
27583
+ if (readString20(item, "type") === "message") {
27133
27584
  const delta = extractResponseAssistantText({ output: [item] });
27134
27585
  return delta ? {
27135
27586
  ...event,
@@ -27137,7 +27588,7 @@ function normalizeResponseOutputItemDone(event) {
27137
27588
  payload: { type: "message.delta", delta }
27138
27589
  } : null;
27139
27590
  }
27140
- if (readString19(item, "type") !== "function_call_output") {
27591
+ if (readString20(item, "type") !== "function_call_output") {
27141
27592
  return null;
27142
27593
  }
27143
27594
  const output = readResponseItemOutput(item.output);
@@ -27147,12 +27598,12 @@ function normalizeResponseOutputItemDone(event) {
27147
27598
  payloadType: "tool.completed",
27148
27599
  payload: {
27149
27600
  type: "tool.completed",
27150
- tool_call_id: readString19(item, "call_id") ?? readString19(item, "id"),
27151
- status: readString19(item, "status") ?? "completed",
27601
+ tool_call_id: readString20(item, "call_id") ?? readString20(item, "id"),
27602
+ status: readString20(item, "status") ?? "completed",
27152
27603
  output,
27153
27604
  content: output,
27154
27605
  result: parsedOutput ?? output,
27155
- response_item_id: readString19(item, "id") ?? void 0
27606
+ response_item_id: readString20(item, "id") ?? void 0
27156
27607
  }
27157
27608
  };
27158
27609
  }
@@ -27163,7 +27614,7 @@ function normalizeResponseCompleted(event) {
27163
27614
  payloadType: "run.completed",
27164
27615
  payload: {
27165
27616
  type: "run.completed",
27166
- response_id: readString19(response, "id") ?? readString19(event.payload, "id"),
27617
+ response_id: readString20(response, "id") ?? readString20(event.payload, "id"),
27167
27618
  usage: toRecord18(response.usage),
27168
27619
  response
27169
27620
  }
@@ -27177,9 +27628,9 @@ function normalizeResponseFailed(event) {
27177
27628
  payloadType: "run.failed",
27178
27629
  payload: {
27179
27630
  type: "run.failed",
27180
- response_id: readString19(response, "id") ?? readString19(event.payload, "id"),
27631
+ response_id: readString20(response, "id") ?? readString20(event.payload, "id"),
27181
27632
  error: {
27182
- message: readString19(error, "message") ?? readString19(event.payload, "message") ?? "Hermes run failed"
27633
+ message: readString20(error, "message") ?? readString20(event.payload, "message") ?? "Hermes run failed"
27183
27634
  },
27184
27635
  usage: toRecord18(response.usage),
27185
27636
  response
@@ -27206,7 +27657,7 @@ function readErrorMessage4(payload) {
27206
27657
  return payload.error.trim();
27207
27658
  }
27208
27659
  const error = toRecord18(payload.error);
27209
- return readString19(error, "message") ?? readString19(payload, "message");
27660
+ return readString20(error, "message") ?? readString20(payload, "message");
27210
27661
  }
27211
27662
  function readDelta(payload) {
27212
27663
  return readText3(payload, "delta") ?? readText3(payload, "text") ?? readText3(payload, "content");
@@ -27253,7 +27704,7 @@ function readChatCompletionDelta(payload) {
27253
27704
  }
27254
27705
  function readChatCompletionFinishReason(payload) {
27255
27706
  const choice = readFirstChoice(payload);
27256
- return readString19(choice, "finish_reason") ?? readString19(choice, "finishReason");
27707
+ return readString20(choice, "finish_reason") ?? readString20(choice, "finishReason");
27257
27708
  }
27258
27709
  function readChatCompletionUsage(payload) {
27259
27710
  const usage = toRecord18(payload.usage);
@@ -27293,7 +27744,7 @@ function readAssistantTextFromChoices(payload) {
27293
27744
  return null;
27294
27745
  }
27295
27746
  const messages2 = choices.map(toRecord18).map((choice) => toRecord18(choice.message ?? choice.delta)).filter((message) => {
27296
- const role = readString19(message, "role");
27747
+ const role = readString20(message, "role");
27297
27748
  return !role || role === "assistant";
27298
27749
  }).map(readResponseMessageText).filter((text) => Boolean(text?.trim()));
27299
27750
  return messages2.length > 0 ? messages2.join("\n\n") : null;
@@ -27309,7 +27760,7 @@ function readInteger3(payload, key) {
27309
27760
  }
27310
27761
  return void 0;
27311
27762
  }
27312
- function readString19(payload, key) {
27763
+ function readString20(payload, key) {
27313
27764
  const value = payload[key];
27314
27765
  return typeof value === "string" && value.trim() ? value.trim() : null;
27315
27766
  }
@@ -27322,8 +27773,8 @@ function readResponseOutputItemText(value) {
27322
27773
  return value;
27323
27774
  }
27324
27775
  const item = toRecord18(value);
27325
- const type = readString19(item, "type");
27326
- const role = readString19(item, "role");
27776
+ const type = readString20(item, "type");
27777
+ const role = readString20(item, "role");
27327
27778
  if (type && type !== "message" && type !== "output_text" && type !== "text") {
27328
27779
  return null;
27329
27780
  }
@@ -27349,7 +27800,7 @@ function readResponseContentText(value) {
27349
27800
  return partValue;
27350
27801
  }
27351
27802
  const part = toRecord18(partValue);
27352
- const type = readString19(part, "type");
27803
+ const type = readString20(part, "type");
27353
27804
  if (type && !isVisibleResponseTextPart(type)) {
27354
27805
  return null;
27355
27806
  }
@@ -27658,6 +28109,11 @@ var ConversationRunLifecycle = class {
27658
28109
  run.profile ?? "default"
27659
28110
  );
27660
28111
  const reasoningEffort = reasoningEffortForRun(run);
28112
+ await this.recordRunHermesMessageWatermark({
28113
+ conversationId,
28114
+ runId,
28115
+ phase: "before"
28116
+ });
27661
28117
  if (backend === "tui_gateway") {
27662
28118
  const rpcRun = await streamTuiGatewayRun({
27663
28119
  input: resolvedInput,
@@ -27873,13 +28329,7 @@ var ConversationRunLifecycle = class {
27873
28329
  }
27874
28330
  } catch (error) {
27875
28331
  if (controller.signal.aborted) {
27876
- await this.deps.withConversationLock(
27877
- conversationId,
27878
- () => this.cancelRunLocked(conversationId, runId, {
27879
- abortUpstream: false,
27880
- reason: "cancelled by app"
27881
- })
27882
- );
28332
+ await this.cancelRunAfterAbort(conversationId, runId);
27883
28333
  return { shouldDrainQueue: true };
27884
28334
  }
27885
28335
  if (isTuiGatewaySessionBusyError(error)) {
@@ -28080,16 +28530,27 @@ var ConversationRunLifecycle = class {
28080
28530
  }
28081
28531
  }
28082
28532
  async cancelRun(conversationId, runId, options) {
28083
- return this.deps.withConversationLock(
28533
+ const result = await this.deps.withConversationLock(
28084
28534
  conversationId,
28085
28535
  () => this.cancelRunLocked(conversationId, runId, options)
28086
28536
  );
28537
+ await this.recordRunHermesMessageWatermark({
28538
+ conversationId,
28539
+ runId,
28540
+ phase: "after"
28541
+ });
28542
+ return result;
28087
28543
  }
28088
28544
  async failRun(conversationId, runId, message, source) {
28089
28545
  await this.refreshRunHermesCompressionTip(conversationId, runId);
28546
+ const afterWatermark = await this.readRunHermesMessageWatermark(
28547
+ conversationId,
28548
+ runId,
28549
+ "after"
28550
+ );
28090
28551
  return this.deps.withConversationLock(
28091
28552
  conversationId,
28092
- () => this.failRunLocked(conversationId, runId, message, source)
28553
+ () => this.failRunLocked(conversationId, runId, message, source, afterWatermark)
28093
28554
  );
28094
28555
  }
28095
28556
  async findConversationIdForRun(runId) {
@@ -28530,6 +28991,11 @@ var ConversationRunLifecycle = class {
28530
28991
  reason: "cancelled by app"
28531
28992
  })
28532
28993
  );
28994
+ await this.recordRunHermesMessageWatermark({
28995
+ conversationId,
28996
+ runId,
28997
+ phase: "after"
28998
+ });
28533
28999
  }
28534
29000
  async completeCancelledRun(conversationId, runId) {
28535
29001
  await this.deps.withConversationLock(
@@ -28539,6 +29005,11 @@ var ConversationRunLifecycle = class {
28539
29005
  reason: "cancelled by Hermes"
28540
29006
  })
28541
29007
  );
29008
+ await this.recordRunHermesMessageWatermark({
29009
+ conversationId,
29010
+ runId,
29011
+ phase: "after"
29012
+ });
28542
29013
  }
28543
29014
  async recoverRunTerminalEvent(input) {
28544
29015
  const deadline = Date.now() + RUN_STATUS_RECOVERY_TIMEOUT_MS;
@@ -28721,14 +29192,14 @@ var ConversationRunLifecycle = class {
28721
29192
  (message) => message.id === input.run.trigger_message_id
28722
29193
  );
28723
29194
  const prefix = guidedInterruptInputPrefix(input.run);
28724
- if (!userMessage || !userMessage.parts.some(isVoicePart)) {
29195
+ if (!userMessage || !userMessage.parts.some(isVoicePart2)) {
28725
29196
  return prefix ? `${prefix}
28726
29197
 
28727
29198
  ${input.fallbackInput}` : input.fallbackInput;
28728
29199
  }
28729
29200
  const content = messageText2(userMessage);
28730
29201
  const voiceLines = [];
28731
- for (const part of userMessage.parts.filter(isVoicePart)) {
29202
+ for (const part of userMessage.parts.filter(isVoicePart2)) {
28732
29203
  const audioPath = part.local_path ?? (part.blob ? blobPath(this.deps.paths, part.blob) : "");
28733
29204
  const result = await transcribeAudioWithHermesProfile({
28734
29205
  audioPath,
@@ -28738,7 +29209,7 @@ ${input.fallbackInput}` : input.fallbackInput;
28738
29209
  const label = part.filename ?? part.blob ?? "voice message";
28739
29210
  voiceLines.push(`- ${label}: ${result.transcript}`);
28740
29211
  }
28741
- const attachmentLines = userMessage.parts.filter((part) => Boolean(part.blob)).filter((part) => !isVoicePart(part)).map((part) => {
29212
+ const attachmentLines = userMessage.parts.filter((part) => Boolean(part.blob)).filter((part) => !isVoicePart2(part)).map((part) => {
28742
29213
  const label = part.filename ?? part.blob;
28743
29214
  const mime = part.mime ? `, ${part.mime}` : "";
28744
29215
  const size = part.size ? `, ${part.size} bytes` : "";
@@ -28824,6 +29295,47 @@ ${resolved}` : resolved;
28824
29295
  Object.assign(run, patch);
28825
29296
  await this.deps.writeSnapshot(conversationId, snapshot);
28826
29297
  }
29298
+ async recordRunHermesMessageWatermark(input) {
29299
+ const point = await this.readRunHermesMessageWatermark(
29300
+ input.conversationId,
29301
+ input.runId,
29302
+ input.phase
29303
+ );
29304
+ if (!point) {
29305
+ return;
29306
+ }
29307
+ await this.deps.withConversationLock(input.conversationId, async () => {
29308
+ const snapshot = await this.deps.readSnapshot(input.conversationId);
29309
+ const run = snapshot.runs.find((item) => item.id === input.runId);
29310
+ if (!run) {
29311
+ return;
29312
+ }
29313
+ applyRunHermesMessageWatermark(run, input.phase, point);
29314
+ await this.deps.writeSnapshot(input.conversationId, snapshot);
29315
+ });
29316
+ }
29317
+ async readRunHermesMessageWatermark(conversationId, runId, phase) {
29318
+ const snapshot = await this.deps.readSnapshot(conversationId).catch(() => null);
29319
+ const run = snapshot?.runs.find((item) => item.id === runId);
29320
+ const sessionId = run?.hermes_session_id?.trim();
29321
+ if (!run || !sessionId) {
29322
+ return null;
29323
+ }
29324
+ return await readHermesMessageWatermark({
29325
+ profileName: run.profile,
29326
+ sessionId
29327
+ }).catch((error) => {
29328
+ void this.deps.logger.debug("hermes_message_watermark_read_failed", {
29329
+ conversation_id: conversationId,
29330
+ run_id: runId,
29331
+ phase,
29332
+ profile: run.profile ?? "default",
29333
+ hermes_session_id: sessionId,
29334
+ error: error instanceof Error ? error.message : String(error)
29335
+ });
29336
+ return null;
29337
+ });
29338
+ }
28827
29339
  async updateRunUsageFromEvent(conversationId, runId, event) {
28828
29340
  const usage = readUsage(event.payload);
28829
29341
  if (!usage) {
@@ -29217,10 +29729,10 @@ ${details.join("\n")}` : localizedEmptyHermesResponseMessage(language);
29217
29729
  return goalStatus;
29218
29730
  }
29219
29731
  async persistGoalStatusUpdate(conversationId, runId, event) {
29220
- if (readString20(event.payload, "kind") !== "goal") {
29732
+ if (readString21(event.payload, "kind") !== "goal") {
29221
29733
  return null;
29222
29734
  }
29223
- const text = readString20(event.payload, "text") ?? readString20(event.payload, "message") ?? readString20(event.payload, "status") ?? "";
29735
+ const text = readString21(event.payload, "text") ?? readString21(event.payload, "message") ?? readString21(event.payload, "status") ?? "";
29224
29736
  const manifest = await this.deps.readRunnableManifest(conversationId);
29225
29737
  const snapshot = await this.deps.readSnapshot(conversationId);
29226
29738
  const run = snapshot.runs.find((item) => item.id === runId);
@@ -29407,7 +29919,7 @@ ${details.join("\n")}` : localizedEmptyHermesResponseMessage(language);
29407
29919
  }
29408
29920
  const textPart = assistant.parts.find((part) => part.type === "text");
29409
29921
  const currentText = textPart?.text ?? "";
29410
- const pendingDeliveryText = readString20(
29922
+ const pendingDeliveryText = readString21(
29411
29923
  toRecord19(assistant.hermes),
29412
29924
  "pending_media_delivery_text"
29413
29925
  );
@@ -29513,7 +30025,7 @@ ${details.join("\n")}` : localizedEmptyHermesResponseMessage(language);
29513
30025
  }
29514
30026
  reasoningDeltaSegmentId(event) {
29515
30027
  const payload = event.payload;
29516
- return readString20(payload, "segment_id") ?? readString20(payload, "segmentId") ?? readString20(payload, "id") ?? readString20(payload, "tool_call_id") ?? readString20(payload, "tool_id") ?? null;
30028
+ return readString21(payload, "segment_id") ?? readString21(payload, "segmentId") ?? readString21(payload, "id") ?? readString21(payload, "tool_call_id") ?? readString21(payload, "tool_id") ?? null;
29517
30029
  }
29518
30030
  async runRequestsAppDelivery(conversationId, runId) {
29519
30031
  const snapshot = await this.deps.readSnapshot(conversationId).catch(() => null);
@@ -29525,9 +30037,14 @@ ${details.join("\n")}` : localizedEmptyHermesResponseMessage(language);
29525
30037
  }
29526
30038
  async completeRun(conversationId, runId, source) {
29527
30039
  await this.refreshRunHermesCompressionTip(conversationId, runId);
30040
+ const afterWatermark = await this.readRunHermesMessageWatermark(
30041
+ conversationId,
30042
+ runId,
30043
+ "after"
30044
+ );
29528
30045
  return this.deps.withConversationLock(
29529
30046
  conversationId,
29530
- () => this.completeRunLocked(conversationId, runId, source)
30047
+ () => this.completeRunLocked(conversationId, runId, source, afterWatermark)
29531
30048
  );
29532
30049
  }
29533
30050
  async refreshRunHermesCompressionTip(conversationId, runId) {
@@ -29564,7 +30081,7 @@ ${details.join("\n")}` : localizedEmptyHermesResponseMessage(language);
29564
30081
  await this.rememberRunHermesSessionId(conversationId, runId, compressionTip);
29565
30082
  return { previousSessionId, nextSessionId: compressionTip };
29566
30083
  }
29567
- async completeRunLocked(conversationId, runId, source) {
30084
+ async completeRunLocked(conversationId, runId, source, afterWatermark) {
29568
30085
  let snapshot = await this.deps.readSnapshot(conversationId);
29569
30086
  let run = snapshot.runs.find((item) => item.id === runId);
29570
30087
  if (!run || run.status !== "running") {
@@ -29606,6 +30123,9 @@ ${details.join("\n")}` : localizedEmptyHermesResponseMessage(language);
29606
30123
  if (usage) {
29607
30124
  run.usage = mergeRunUsage(run.usage, usage);
29608
30125
  }
30126
+ if (afterWatermark) {
30127
+ applyRunHermesMessageWatermark(run, "after", afterWatermark);
30128
+ }
29609
30129
  const probeEvent = shouldUseHermesUsageProbe(run.hermes_backend) ? await findHermesUsageProbeEventForRun({
29610
30130
  paths: this.deps.paths,
29611
30131
  profileName: run.profile,
@@ -29754,7 +30274,7 @@ ${details.join("\n")}` : localizedEmptyHermesResponseMessage(language);
29754
30274
  await this.deps.writeManifest(nextManifest);
29755
30275
  return goal;
29756
30276
  }
29757
- async failRunLocked(conversationId, runId, message, source) {
30277
+ async failRunLocked(conversationId, runId, message, source, afterWatermark) {
29758
30278
  const snapshot = await this.deps.readSnapshot(conversationId).catch(() => null);
29759
30279
  if (!snapshot) {
29760
30280
  return;
@@ -29777,6 +30297,9 @@ ${details.join("\n")}` : localizedEmptyHermesResponseMessage(language);
29777
30297
  if (usage) {
29778
30298
  run.usage = mergeRunUsage(run.usage, usage);
29779
30299
  }
30300
+ if (afterWatermark) {
30301
+ applyRunHermesMessageWatermark(run, "after", afterWatermark);
30302
+ }
29780
30303
  const assistant = snapshot.messages.find(
29781
30304
  (item) => item.id === run.assistant_message_id
29782
30305
  );
@@ -30140,7 +30663,7 @@ ${details.join("\n")}` : localizedEmptyHermesResponseMessage(language);
30140
30663
  includeDisabled: true
30141
30664
  });
30142
30665
  return new Set(
30143
- jobs.map((job) => readString20(job, "id") ?? readString20(job, "job_id")).filter((id) => Boolean(id))
30666
+ jobs.map((job) => readString21(job, "id") ?? readString21(job, "job_id")).filter((id) => Boolean(id))
30144
30667
  );
30145
30668
  }
30146
30669
  async bindNewCronJobsCreatedByRun(input) {
@@ -30240,7 +30763,7 @@ async function readdirWithDirs(directory) {
30240
30763
  throw error;
30241
30764
  });
30242
30765
  }
30243
- function readString20(payload, key) {
30766
+ function readString21(payload, key) {
30244
30767
  const value = payload[key];
30245
30768
  return typeof value === "string" && value.trim() ? value.trim() : null;
30246
30769
  }
@@ -30331,11 +30854,11 @@ function contextCompressionGeneration(message) {
30331
30854
  return typeof generation === "number" && Number.isFinite(generation) ? Math.max(0, Math.floor(generation)) : null;
30332
30855
  }
30333
30856
  function readPreviousSessionId(payload) {
30334
- return readString20(payload, "old_session_id") ?? readString20(payload, "oldSessionId") ?? readString20(payload, "previous_session_id") ?? readString20(payload, "previousSessionId");
30857
+ return readString21(payload, "old_session_id") ?? readString21(payload, "oldSessionId") ?? readString21(payload, "previous_session_id") ?? readString21(payload, "previousSessionId");
30335
30858
  }
30336
30859
  function readNextSessionId(payload) {
30337
30860
  const info = toRecord19(payload.info);
30338
- return readString20(payload, "session_key") ?? readString20(payload, "sessionKey") ?? readString20(payload, "stored_session_id") ?? readString20(payload, "storedSessionId") ?? readString20(payload, "session_id") ?? readString20(payload, "sessionId") ?? readString20(info, "session_key") ?? readString20(info, "sessionKey");
30861
+ return readString21(payload, "session_key") ?? readString21(payload, "sessionKey") ?? readString21(payload, "stored_session_id") ?? readString21(payload, "storedSessionId") ?? readString21(payload, "session_id") ?? readString21(payload, "sessionId") ?? readString21(info, "session_key") ?? readString21(info, "sessionKey");
30339
30862
  }
30340
30863
  function eventPayloadWithLanguage(payload, language) {
30341
30864
  return { ...payload, language };
@@ -30427,13 +30950,13 @@ function isFileSearchCompletion(payloadType, payload) {
30427
30950
  const toolCall = toRecord19(payload.tool_call ?? payload.toolCall);
30428
30951
  const fn = toRecord19(toolCall.function ?? payload.function);
30429
30952
  const candidates = [
30430
- readString20(payload, "tool_name"),
30431
- readString20(payload, "toolName"),
30432
- readString20(payload, "name"),
30433
- readString20(payload, "tool"),
30434
- readString20(tool, "name"),
30435
- readString20(toolCall, "name"),
30436
- readString20(fn, "name")
30953
+ readString21(payload, "tool_name"),
30954
+ readString21(payload, "toolName"),
30955
+ readString21(payload, "name"),
30956
+ readString21(payload, "tool"),
30957
+ readString21(tool, "name"),
30958
+ readString21(toolCall, "name"),
30959
+ readString21(fn, "name")
30437
30960
  ].filter((value) => Boolean(value)).map(normalizeToolName);
30438
30961
  return candidates.some(
30439
30962
  (name) => [
@@ -30470,7 +30993,7 @@ function messageRequestsAppDelivery(text) {
30470
30993
  const hasEnglishDeliveryAction = /\b(send|share|attach|deliver|display)\b/u.test(lower) || /\bshow\s+me\b/u.test(lower);
30471
30994
  return hasEnglishDeliverable && hasEnglishDeliveryAction;
30472
30995
  }
30473
- function isVoicePart(part) {
30996
+ function isVoicePart2(part) {
30474
30997
  return part.kind === "voice" || part.is_voice_note === true;
30475
30998
  }
30476
30999
  function normalizeToolName(value) {
@@ -30773,13 +31296,13 @@ function readResponseId(payload) {
30773
31296
  return null;
30774
31297
  }
30775
31298
  const response = toRecord19(payload.response);
30776
- return readString20(payload, "response_id") ?? readString20(response, "id");
31299
+ return readString21(payload, "response_id") ?? readString21(response, "id");
30777
31300
  }
30778
31301
  function readRunId(payload) {
30779
31302
  if (!payload) {
30780
31303
  return null;
30781
31304
  }
30782
- return readString20(payload, "run_id") ?? readString20(payload, "runId");
31305
+ return readString21(payload, "run_id") ?? readString21(payload, "runId");
30783
31306
  }
30784
31307
  function isCompletedRunStatus(status) {
30785
31308
  return status === "completed" || status === "complete" || status === "succeeded" || status === "success" || status === "done";
@@ -30798,7 +31321,7 @@ function readStatusErrorMessage(value) {
30798
31321
  return value.trim();
30799
31322
  }
30800
31323
  const record = toRecord19(value);
30801
- return readString20(record, "message") ?? readString20(record, "error");
31324
+ return readString21(record, "message") ?? readString21(record, "error");
30802
31325
  }
30803
31326
  function formatUnknownErrorMessage(error) {
30804
31327
  return error instanceof Error ? error.message : String(error);
@@ -30837,6 +31360,12 @@ function sanitizeLiveSessionForEvent(liveSession) {
30837
31360
  ...liveSession.inflight ? { inflight: liveSession.inflight } : {}
30838
31361
  };
30839
31362
  }
31363
+ function applyRunHermesMessageWatermark(run, phase, point) {
31364
+ run.hermes_message_watermark = {
31365
+ ...run.hermes_message_watermark ?? {},
31366
+ [phase]: point
31367
+ };
31368
+ }
30840
31369
  function previewText2(message) {
30841
31370
  if (!message) {
30842
31371
  return null;
@@ -32561,7 +33090,7 @@ var ConversationService = class {
32561
33090
  }
32562
33091
  }
32563
33092
  hermesArchiveStateSyncMarkerPath() {
32564
- return path27.join(this.paths.indexesDir, "hermes-archive-state-sync.json");
33093
+ return path28.join(this.paths.indexesDir, "hermes-archive-state-sync.json");
32565
33094
  }
32566
33095
  prepareClearAllConversationPlan(targetStatus) {
32567
33096
  return this.maintenance.prepareClearAllConversationPlan(targetStatus);
@@ -32843,7 +33372,7 @@ function liveActivityTodoProgressForEvent(event) {
32843
33372
  if (todos) {
32844
33373
  const totalCount2 = todos.length;
32845
33374
  const doneCount2 = todos.filter((item) => {
32846
- const status = readString21(item, "status")?.toLowerCase();
33375
+ const status = readString22(item, "status")?.toLowerCase();
32847
33376
  return status === "completed" || status === "cancelled" || status === "canceled";
32848
33377
  }).length;
32849
33378
  return {
@@ -32892,11 +33421,11 @@ function liveActivityTitleFromConversationUpdate(event) {
32892
33421
  if (event.type.toLowerCase() !== "conversation.updated") {
32893
33422
  return void 0;
32894
33423
  }
32895
- const titleSource = readString21(event.payload, "title_source");
33424
+ const titleSource = readString22(event.payload, "title_source");
32896
33425
  if (titleSource === "default" || titleSource === "temporary_fallback") {
32897
33426
  return null;
32898
33427
  }
32899
- const title = readString21(event.payload, "title");
33428
+ const title = readString22(event.payload, "title");
32900
33429
  return title ? truncateLiveActivityTitle(title, 24) : null;
32901
33430
  }
32902
33431
  function liveActivityTitleFromManifest(manifest) {
@@ -32936,7 +33465,7 @@ function isConversationTitleUpdateEvent(event) {
32936
33465
  if (event.type.toLowerCase() !== "conversation.updated") {
32937
33466
  return false;
32938
33467
  }
32939
- return Boolean(readString21(event.payload, "title")?.trim());
33468
+ return Boolean(readString22(event.payload, "title")?.trim());
32940
33469
  }
32941
33470
  function resolveLiveActivityTarget(input) {
32942
33471
  if (input.run?.kind === "compression") {
@@ -32958,7 +33487,7 @@ function liveActivityPhaseForEvent(event, run, contextOperation) {
32958
33487
  }
32959
33488
  if (type === "conversation.goal.updated") {
32960
33489
  const goal = readRecord2(event.payload).goal;
32961
- const status = readString21(goal, "status");
33490
+ const status = readString22(goal, "status");
32962
33491
  return status === "paused" ? "goal_paused" : "goal_running";
32963
33492
  }
32964
33493
  if (isConversationTitleUpdateEvent(event)) {
@@ -33091,7 +33620,7 @@ function readContextCompressionOperation(payload) {
33091
33620
  if (!operation || typeof operation !== "object") {
33092
33621
  return null;
33093
33622
  }
33094
- const operationId = readString21(operation, "operation_id");
33623
+ const operationId = readString22(operation, "operation_id");
33095
33624
  if (!operationId) {
33096
33625
  return null;
33097
33626
  }
@@ -33099,19 +33628,19 @@ function readContextCompressionOperation(payload) {
33099
33628
  return {
33100
33629
  operation_id: operationId,
33101
33630
  generation: typeof record.generation === "number" ? record.generation : 0,
33102
- status: readString21(record, "status") === "completed" ? "completed" : readString21(record, "status") === "failed" ? "failed" : readString21(record, "status") === "timed_out" ? "timed_out" : readString21(record, "status") === "cancelled" ? "cancelled" : "compressing",
33103
- started_at: readString21(record, "started_at") ?? (/* @__PURE__ */ new Date()).toISOString(),
33104
- source: readString21(record, "source") === "manual" ? "manual" : "auto"
33631
+ status: readString22(record, "status") === "completed" ? "completed" : readString22(record, "status") === "failed" ? "failed" : readString22(record, "status") === "timed_out" ? "timed_out" : readString22(record, "status") === "cancelled" ? "cancelled" : "compressing",
33632
+ started_at: readString22(record, "started_at") ?? (/* @__PURE__ */ new Date()).toISOString(),
33633
+ source: readString22(record, "source") === "manual" ? "manual" : "auto"
33105
33634
  };
33106
33635
  }
33107
33636
  function readToolName3(payload) {
33108
33637
  const record = readRecord2(payload);
33109
- return readString21(record, "tool_name") ?? readString21(record, "tool") ?? readString21(record, "name") ?? readString21(readRecord2(record.tool), "name");
33638
+ return readString22(record, "tool_name") ?? readString22(record, "tool") ?? readString22(record, "name") ?? readString22(readRecord2(record.tool), "name");
33110
33639
  }
33111
33640
  function readRecord2(value) {
33112
33641
  return typeof value === "object" && value !== null && !Array.isArray(value) ? value : {};
33113
33642
  }
33114
- function readString21(value, key) {
33643
+ function readString22(value, key) {
33115
33644
  const raw = readRecord2(value)[key];
33116
33645
  return typeof raw === "string" && raw.trim() ? raw.trim() : null;
33117
33646
  }
@@ -33631,7 +34160,7 @@ async function readRawBody(request, maxBytes) {
33631
34160
  }
33632
34161
  return Buffer.concat(chunks);
33633
34162
  }
33634
- function readString22(body, key) {
34163
+ function readString23(body, key) {
33635
34164
  const value = body[key];
33636
34165
  return typeof value === "string" && value.trim() ? value.trim() : null;
33637
34166
  }
@@ -33666,7 +34195,7 @@ function readSupportedLanguage(value) {
33666
34195
  return null;
33667
34196
  }
33668
34197
  function readOptionalProfileName(body) {
33669
- return readString22(body, "profile") ?? readString22(body, "profile_name") ?? readString22(body, "profileName") ?? void 0;
34198
+ return readString23(body, "profile") ?? readString23(body, "profile_name") ?? readString23(body, "profileName") ?? void 0;
33670
34199
  }
33671
34200
  function readStringArray(body, ...keys) {
33672
34201
  for (const key of keys) {
@@ -34086,7 +34615,7 @@ function registerConversationRoutes(router, options) {
34086
34615
  const language = readPreferredLanguage(ctx);
34087
34616
  const body = await readJsonBody(ctx.req);
34088
34617
  ctx.status = 201;
34089
- const rawReasoningEffort = readString22(body, "reasoning_effort") ?? readString22(body, "reasoningEffort") ?? readString22(body, "default_reasoning_effort") ?? readString22(body, "defaultReasoningEffort");
34618
+ const rawReasoningEffort = readString23(body, "reasoning_effort") ?? readString23(body, "reasoningEffort") ?? readString23(body, "default_reasoning_effort") ?? readString23(body, "defaultReasoningEffort");
34090
34619
  const reasoningEffort = normalizeReasoningEffort(rawReasoningEffort);
34091
34620
  if (rawReasoningEffort && !reasoningEffort) {
34092
34621
  throw new LinkHttpError(
@@ -34099,15 +34628,15 @@ function registerConversationRoutes(router, options) {
34099
34628
  ok: true,
34100
34629
  conversation: localizeConversationSummary(
34101
34630
  await conversations.createConversation({
34102
- title: readString22(body, "title") ?? void 0,
34631
+ title: readString23(body, "title") ?? void 0,
34103
34632
  profileName: readOptionalProfileName(body),
34104
34633
  accountId: auth.accountId,
34105
34634
  appInstanceId: auth.appInstanceId,
34106
34635
  workspaceId: readConversationWorkspaceId(body),
34107
- modelId: readString22(body, "model_id") ?? readString22(body, "modelId") ?? readString22(body, "model") ?? void 0,
34108
- modelProvider: readString22(body, "model_provider") ?? readString22(body, "modelProvider") ?? readString22(body, "provider") ?? void 0,
34109
- modelBaseUrl: readString22(body, "model_base_url") ?? readString22(body, "modelBaseUrl") ?? readString22(body, "base_url") ?? readString22(body, "baseUrl") ?? void 0,
34110
- modelApiMode: readString22(body, "model_api_mode") ?? readString22(body, "modelApiMode") ?? readString22(body, "api_mode") ?? readString22(body, "apiMode") ?? void 0,
34636
+ modelId: readString23(body, "model_id") ?? readString23(body, "modelId") ?? readString23(body, "model") ?? void 0,
34637
+ modelProvider: readString23(body, "model_provider") ?? readString23(body, "modelProvider") ?? readString23(body, "provider") ?? void 0,
34638
+ modelBaseUrl: readString23(body, "model_base_url") ?? readString23(body, "modelBaseUrl") ?? readString23(body, "base_url") ?? readString23(body, "baseUrl") ?? void 0,
34639
+ modelApiMode: readString23(body, "model_api_mode") ?? readString23(body, "modelApiMode") ?? readString23(body, "api_mode") ?? readString23(body, "apiMode") ?? void 0,
34111
34640
  reasoningEffort
34112
34641
  }),
34113
34642
  language
@@ -34185,9 +34714,9 @@ function registerConversationRoutes(router, options) {
34185
34714
  const auth = await authenticateRequest(ctx, paths);
34186
34715
  const language = readPreferredLanguage(ctx);
34187
34716
  const body = await readJsonBody(ctx.req);
34188
- const content = readString22(body, "content") ?? readString22(body, "text") ?? readString22(body, "input") ?? "";
34717
+ const content = readString23(body, "content") ?? readString23(body, "text") ?? readString23(body, "input") ?? "";
34189
34718
  const attachments = readMessageAttachments(body.attachments ?? body.blobs);
34190
- const mode = readString22(body, "mode") ?? readString22(body, "send_mode");
34719
+ const mode = readString23(body, "mode") ?? readString23(body, "send_mode");
34191
34720
  if (mode && mode !== "message" && mode !== "goal") {
34192
34721
  throw new LinkHttpError(
34193
34722
  400,
@@ -34210,7 +34739,7 @@ function registerConversationRoutes(router, options) {
34210
34739
  conversationId: ctx.params.conversationId,
34211
34740
  content,
34212
34741
  attachments,
34213
- clientMessageId: readString22(body, "client_message_id") ?? readString22(body, "clientMessageId") ?? void 0,
34742
+ clientMessageId: readString23(body, "client_message_id") ?? readString23(body, "clientMessageId") ?? void 0,
34214
34743
  idempotencyKey: readHeader(ctx, "idempotency-key") ?? void 0,
34215
34744
  profileName: readOptionalProfileName(body),
34216
34745
  mode: mode === "goal" ? "goal" : "message",
@@ -34277,8 +34806,8 @@ function registerConversationRoutes(router, options) {
34277
34806
  ...localizeConversationResult(
34278
34807
  await conversations.startContextCompression({
34279
34808
  conversationId: ctx.params.conversationId,
34280
- focus: readString22(body, "focus") ?? readString22(body, "focus_topic") ?? readString22(body, "focusTopic") ?? void 0,
34281
- clientOperationId: readString22(body, "client_operation_id") ?? readString22(body, "clientOperationId") ?? readHeader(ctx, "idempotency-key") ?? void 0,
34809
+ focus: readString23(body, "focus") ?? readString23(body, "focus_topic") ?? readString23(body, "focusTopic") ?? void 0,
34810
+ clientOperationId: readString23(body, "client_operation_id") ?? readString23(body, "clientOperationId") ?? readHeader(ctx, "idempotency-key") ?? void 0,
34282
34811
  createUserMessage: false,
34283
34812
  accountId: auth.accountId,
34284
34813
  appInstanceId: auth.appInstanceId,
@@ -34292,11 +34821,11 @@ function registerConversationRoutes(router, options) {
34292
34821
  router.patch("/api/v1/conversations/:conversationId/model", async (ctx) => {
34293
34822
  await authenticateRequest(ctx, paths);
34294
34823
  const body = await readJsonBody(ctx.req);
34295
- const modelId = readString22(body, "model_id") ?? readString22(body, "modelId") ?? readString22(body, "model");
34296
- const modelProvider = readString22(body, "model_provider") ?? readString22(body, "modelProvider") ?? readString22(body, "provider") ?? void 0;
34297
- const modelBaseUrl = readString22(body, "model_base_url") ?? readString22(body, "modelBaseUrl") ?? readString22(body, "base_url") ?? readString22(body, "baseUrl") ?? void 0;
34298
- const modelApiMode = readString22(body, "model_api_mode") ?? readString22(body, "modelApiMode") ?? readString22(body, "api_mode") ?? readString22(body, "apiMode") ?? void 0;
34299
- const rawReasoningEffort = readString22(body, "reasoning_effort") ?? readString22(body, "reasoningEffort") ?? readString22(body, "default_reasoning_effort") ?? readString22(body, "defaultReasoningEffort");
34824
+ const modelId = readString23(body, "model_id") ?? readString23(body, "modelId") ?? readString23(body, "model");
34825
+ const modelProvider = readString23(body, "model_provider") ?? readString23(body, "modelProvider") ?? readString23(body, "provider") ?? void 0;
34826
+ const modelBaseUrl = readString23(body, "model_base_url") ?? readString23(body, "modelBaseUrl") ?? readString23(body, "base_url") ?? readString23(body, "baseUrl") ?? void 0;
34827
+ const modelApiMode = readString23(body, "model_api_mode") ?? readString23(body, "modelApiMode") ?? readString23(body, "api_mode") ?? readString23(body, "apiMode") ?? void 0;
34828
+ const rawReasoningEffort = readString23(body, "reasoning_effort") ?? readString23(body, "reasoningEffort") ?? readString23(body, "default_reasoning_effort") ?? readString23(body, "defaultReasoningEffort");
34300
34829
  const reasoningEffort = normalizeReasoningEffort(rawReasoningEffort);
34301
34830
  if (rawReasoningEffort && !reasoningEffort) {
34302
34831
  throw new LinkHttpError(
@@ -34346,7 +34875,7 @@ function registerConversationRoutes(router, options) {
34346
34875
  await authenticateRequest(ctx, paths);
34347
34876
  const language = readPreferredLanguage(ctx);
34348
34877
  const body = await readJsonBody(ctx.req);
34349
- const title = readString22(body, "title") ?? readString22(body, "name") ?? readString22(body, "display_name");
34878
+ const title = readString23(body, "title") ?? readString23(body, "name") ?? readString23(body, "display_name");
34350
34879
  if (!title) {
34351
34880
  throw new LinkHttpError(400, "title_required", "title is required");
34352
34881
  }
@@ -34538,7 +35067,7 @@ function registerConversationRoutes(router, options) {
34538
35067
  async (ctx) => {
34539
35068
  await authenticateRequest(ctx, paths);
34540
35069
  const body = await readJsonBody(ctx.req);
34541
- const scope = readString22(body, "scope") ?? "always";
35070
+ const scope = readString23(body, "scope") ?? "always";
34542
35071
  ctx.body = {
34543
35072
  ok: true,
34544
35073
  ...await conversations.resolveApproval({
@@ -34588,7 +35117,7 @@ function registerConversationRoutes(router, options) {
34588
35117
  conversationId: ctx.params.conversationId,
34589
35118
  requestId: ctx.params.requestId,
34590
35119
  kind,
34591
- answer: readString22(body, "answer") ?? void 0,
35120
+ answer: readString23(body, "answer") ?? void 0,
34592
35121
  password: readRawString(body, "password"),
34593
35122
  value: readRawString(body, "value")
34594
35123
  })
@@ -34757,10 +35286,10 @@ function readConversationWorkspaceFilter(query) {
34757
35286
  }
34758
35287
  function readConversationWorkspaceId(body) {
34759
35288
  if (Object.prototype.hasOwnProperty.call(body, "workspace_id") || Object.prototype.hasOwnProperty.call(body, "workspaceId")) {
34760
- return readString22(body, "workspace_id") ?? readString22(body, "workspaceId");
35289
+ return readString23(body, "workspace_id") ?? readString23(body, "workspaceId");
34761
35290
  }
34762
35291
  if (Object.prototype.hasOwnProperty.call(body, "workspace")) {
34763
- return readString22(body, "workspace");
35292
+ return readString23(body, "workspace");
34764
35293
  }
34765
35294
  return void 0;
34766
35295
  }
@@ -34854,7 +35383,7 @@ function resolveConversationEventCursor(input) {
34854
35383
  return Math.max(queryAfter, headerAfter);
34855
35384
  }
34856
35385
  function readConversationClearPlanTargetStatus(body) {
34857
- const raw = readString22(body, "target_status") ?? readString22(body, "targetStatus") ?? "active";
35386
+ const raw = readString23(body, "target_status") ?? readString23(body, "targetStatus") ?? "active";
34858
35387
  if (raw === "active" || raw === "archived") {
34859
35388
  return raw;
34860
35389
  }
@@ -34865,7 +35394,7 @@ function readConversationClearPlanTargetStatus(body) {
34865
35394
  );
34866
35395
  }
34867
35396
  function readInputRequestKind2(body) {
34868
- const kind = readString22(body, "kind") ?? readString22(body, "type");
35397
+ const kind = readString23(body, "kind") ?? readString23(body, "type");
34869
35398
  if (kind === "clarify" || kind === "sudo" || kind === "secret") {
34870
35399
  return kind;
34871
35400
  }
@@ -34995,11 +35524,11 @@ function isSseRequestContext(ctx) {
34995
35524
  }
34996
35525
  return isSseRequestPath(ctx.path) || isActiveSseSocket(ctx.req.socket);
34997
35526
  }
34998
- function isSseRequestPath(path38) {
34999
- if (!path38) {
35527
+ function isSseRequestPath(path39) {
35528
+ if (!path39) {
35000
35529
  return false;
35001
35530
  }
35002
- return path38 === "/api/v1/conversations/events" || path38 === "/api/v1/profile-creation/events" || path38 === "/api/v1/hermes/update/events" || path38 === "/api/v1/link/update/events" || /^\/api\/v1\/conversations\/[^/]+\/events$/u.test(path38) || /^\/api\/v1\/runs\/[^/]+\/events$/u.test(path38);
35531
+ return path39 === "/api/v1/conversations/events" || path39 === "/api/v1/profile-creation/events" || path39 === "/api/v1/hermes/update/events" || path39 === "/api/v1/link/update/events" || /^\/api\/v1\/conversations\/[^/]+\/events$/u.test(path39) || /^\/api\/v1\/runs\/[^/]+\/events$/u.test(path39);
35003
35532
  }
35004
35533
  function isExpectedClientDisconnectError2(error, options = {}) {
35005
35534
  if (!(error instanceof Error)) {
@@ -35263,7 +35792,7 @@ function toHermesCronJobInput(input) {
35263
35792
  };
35264
35793
  }
35265
35794
  async function bindAndDecorateCronJobForHermesLink(input) {
35266
- const jobId = readString22(input.job, "id") ?? readString22(input.job, "job_id");
35795
+ const jobId = readString23(input.job, "id") ?? readString23(input.job, "job_id");
35267
35796
  if (!jobId) {
35268
35797
  return input.job;
35269
35798
  }
@@ -35282,9 +35811,9 @@ async function bindAndDecorateCronJobForHermesLink(input) {
35282
35811
  }
35283
35812
  function readCronJobCreateInput(body) {
35284
35813
  const input = {};
35285
- const name = readString22(body, "name") ?? readString22(body, "title");
35286
- const prompt = readString22(body, "prompt") ?? readString22(body, "description") ?? readString22(body, "task");
35287
- const schedule = readString22(body, "schedule");
35814
+ const name = readString23(body, "name") ?? readString23(body, "title");
35815
+ const prompt = readString23(body, "prompt") ?? readString23(body, "description") ?? readString23(body, "task");
35816
+ const schedule = readString23(body, "schedule");
35288
35817
  if (!name) {
35289
35818
  throw new LinkHttpError(400, "cron_job_name_required", "name is required");
35290
35819
  }
@@ -35305,7 +35834,7 @@ function readCronJobCreateInput(body) {
35305
35834
  input.name = name;
35306
35835
  input.prompt = prompt;
35307
35836
  input.schedule = schedule;
35308
- input.deliver = readString22(body, "deliver") ?? HERMES_LINK_CRON_DELIVER;
35837
+ input.deliver = readString23(body, "deliver") ?? HERMES_LINK_CRON_DELIVER;
35309
35838
  const skills = readOptionalCronSkills(body);
35310
35839
  if (skills) {
35311
35840
  input.skills = skills;
@@ -35438,7 +35967,7 @@ import { createHash as createHash11 } from "crypto";
35438
35967
  // src/model-catalog/catalog.ts
35439
35968
  import { randomInt } from "crypto";
35440
35969
  import { mkdir as mkdir12 } from "fs/promises";
35441
- import path28 from "path";
35970
+ import path29 from "path";
35442
35971
  import { fileURLToPath } from "url";
35443
35972
  var MODEL_CATALOG_CACHE_VERSION = 1;
35444
35973
  var MODEL_CATALOG_FETCH_TIMEOUT_MS = 1e4;
@@ -35642,7 +36171,7 @@ async function readCachedCatalogFile(paths) {
35642
36171
  return cached;
35643
36172
  }
35644
36173
  async function writeCachedCatalog(paths, value) {
35645
- await mkdir12(path28.dirname(modelCatalogCachePath(paths)), {
36174
+ await mkdir12(path29.dirname(modelCatalogCachePath(paths)), {
35646
36175
  recursive: true,
35647
36176
  mode: 448
35648
36177
  });
@@ -35658,7 +36187,7 @@ async function readFallbackCatalog() {
35658
36187
  throw new Error("model capability fallback catalog was not found");
35659
36188
  }
35660
36189
  function modelCatalogCachePath(paths) {
35661
- return path28.join(paths.homeDir, "model-capabilities", "catalog-cache.json");
36190
+ return path29.join(paths.homeDir, "model-capabilities", "catalog-cache.json");
35662
36191
  }
35663
36192
  function normalizeModelCapabilityCatalog(value) {
35664
36193
  if (!value || typeof value !== "object") {
@@ -35669,7 +36198,7 @@ function normalizeModelCapabilityCatalog(value) {
35669
36198
  const models = rawModels.map(normalizeModelCapabilityEntry).filter((entry) => entry !== null);
35670
36199
  return {
35671
36200
  schemaVersion: readPositiveInteger3(record.schemaVersion) ?? 1,
35672
- updatedAt: readString23(record.updatedAt),
36201
+ updatedAt: readString24(record.updatedAt),
35673
36202
  models
35674
36203
  };
35675
36204
  }
@@ -35678,7 +36207,7 @@ function normalizeModelCapabilityEntry(value) {
35678
36207
  return null;
35679
36208
  }
35680
36209
  const record = value;
35681
- const canonicalId = readString23(record.canonicalId) ?? readString23(record.canonical_id) ?? readString23(record.id);
36210
+ const canonicalId = readString24(record.canonicalId) ?? readString24(record.canonical_id) ?? readString24(record.id);
35682
36211
  if (!canonicalId) {
35683
36212
  return null;
35684
36213
  }
@@ -35706,12 +36235,12 @@ function normalizeModelCapabilityEntry(value) {
35706
36235
  outputModalities: readStringArray2(
35707
36236
  record.outputModalities ?? record.output_modalities
35708
36237
  ),
35709
- source: readString23(record.source),
35710
- updatedAt: readString23(record.updatedAt ?? record.updated_at),
35711
- notes: readString23(record.notes)
36238
+ source: readString24(record.source),
36239
+ updatedAt: readString24(record.updatedAt ?? record.updated_at),
36240
+ notes: readString24(record.notes)
35712
36241
  };
35713
36242
  }
35714
- function readString23(value) {
36243
+ function readString24(value) {
35715
36244
  return typeof value === "string" && value.trim() ? value.trim() : null;
35716
36245
  }
35717
36246
  function readStringArray2(value) {
@@ -35721,7 +36250,7 @@ function readStringArray2(value) {
35721
36250
  const seen = /* @__PURE__ */ new Set();
35722
36251
  const values = [];
35723
36252
  for (const item of value) {
35724
- const text = readString23(item);
36253
+ const text = readString24(item);
35725
36254
  if (!text || seen.has(text)) {
35726
36255
  continue;
35727
36256
  }
@@ -35738,7 +36267,7 @@ function readPositiveInteger3(value) {
35738
36267
  return Math.floor(number);
35739
36268
  }
35740
36269
  function readReasoningSupportPolicy(value) {
35741
- const normalized = readString23(value)?.toLowerCase();
36270
+ const normalized = readString24(value)?.toLowerCase();
35742
36271
  if (!normalized || normalized === "unknown" || normalized === "auto") {
35743
36272
  return null;
35744
36273
  }
@@ -35769,7 +36298,7 @@ function readNullableBoolean(value) {
35769
36298
  if (typeof value === "boolean") {
35770
36299
  return value;
35771
36300
  }
35772
- const normalized = readString23(value)?.toLowerCase();
36301
+ const normalized = readString24(value)?.toLowerCase();
35773
36302
  if (!normalized) {
35774
36303
  return null;
35775
36304
  }
@@ -36918,8 +37447,8 @@ function normalizeUrlForIdentity(value) {
36918
37447
  return value.trim().replace(/\/+$/u, "").toLowerCase();
36919
37448
  }
36920
37449
  function readModelProviderConfigInput(body) {
36921
- const providerName = readString22(body, "display_name") ?? readString22(body, "displayName") ?? readString22(body, "provider_name") ?? readString22(body, "providerName") ?? readString22(body, "name");
36922
- const baseUrl = readString22(body, "base_url") ?? readString22(body, "baseUrl");
37450
+ const providerName = readString23(body, "display_name") ?? readString23(body, "displayName") ?? readString23(body, "provider_name") ?? readString23(body, "providerName") ?? readString23(body, "name");
37451
+ const baseUrl = readString23(body, "base_url") ?? readString23(body, "baseUrl");
36923
37452
  if (!providerName || !baseUrl) {
36924
37453
  throw new LinkHttpError(
36925
37454
  400,
@@ -36930,15 +37459,15 @@ function readModelProviderConfigInput(body) {
36930
37459
  return {
36931
37460
  providerName,
36932
37461
  baseUrl,
36933
- apiMode: readString22(body, "api_mode") ?? readString22(body, "apiMode") ?? readString22(body, "transport") ?? void 0,
36934
- keyEnv: readString22(body, "key_env") ?? readString22(body, "keyEnv") ?? void 0,
36935
- apiKey: readString22(body, "api_key") ?? readString22(body, "apiKey") ?? void 0
37462
+ apiMode: readString23(body, "api_mode") ?? readString23(body, "apiMode") ?? readString23(body, "transport") ?? void 0,
37463
+ keyEnv: readString23(body, "key_env") ?? readString23(body, "keyEnv") ?? void 0,
37464
+ apiKey: readString23(body, "api_key") ?? readString23(body, "apiKey") ?? void 0
36936
37465
  };
36937
37466
  }
36938
37467
  function readModelConfigInput(body) {
36939
- const id = readString22(body, "id") ?? readString22(body, "model_id") ?? readString22(body, "modelId");
36940
- const provider = readString22(body, "provider") ?? readString22(body, "provider_key") ?? readString22(body, "providerKey");
36941
- const baseUrl = readString22(body, "base_url") ?? readString22(body, "baseUrl");
37468
+ const id = readString23(body, "id") ?? readString23(body, "model_id") ?? readString23(body, "modelId");
37469
+ const provider = readString23(body, "provider") ?? readString23(body, "provider_key") ?? readString23(body, "providerKey");
37470
+ const baseUrl = readString23(body, "base_url") ?? readString23(body, "baseUrl");
36942
37471
  if (!id || !provider || !baseUrl) {
36943
37472
  throw new LinkHttpError(
36944
37473
  400,
@@ -36948,22 +37477,22 @@ function readModelConfigInput(body) {
36948
37477
  }
36949
37478
  return {
36950
37479
  id,
36951
- originalModelId: readString22(body, "original_model_id") ?? readString22(body, "originalModelId") ?? readString22(body, "original_id") ?? void 0,
36952
- originalProvider: readString22(body, "original_provider") ?? readString22(body, "originalProvider") ?? readString22(body, "original_provider_key") ?? readString22(body, "originalProviderKey") ?? void 0,
36953
- originalBaseUrl: readString22(body, "original_base_url") ?? readString22(body, "originalBaseUrl") ?? void 0,
36954
- originalApiMode: readString22(body, "original_api_mode") ?? readString22(body, "originalApiMode") ?? void 0,
37480
+ originalModelId: readString23(body, "original_model_id") ?? readString23(body, "originalModelId") ?? readString23(body, "original_id") ?? void 0,
37481
+ originalProvider: readString23(body, "original_provider") ?? readString23(body, "originalProvider") ?? readString23(body, "original_provider_key") ?? readString23(body, "originalProviderKey") ?? void 0,
37482
+ originalBaseUrl: readString23(body, "original_base_url") ?? readString23(body, "originalBaseUrl") ?? void 0,
37483
+ originalApiMode: readString23(body, "original_api_mode") ?? readString23(body, "originalApiMode") ?? void 0,
36955
37484
  provider,
36956
- providerName: readString22(body, "provider_name") ?? readString22(body, "providerName") ?? void 0,
37485
+ providerName: readString23(body, "provider_name") ?? readString23(body, "providerName") ?? void 0,
36957
37486
  baseUrl,
36958
- apiKey: readString22(body, "api_key") ?? readString22(body, "apiKey") ?? void 0,
36959
- apiMode: readString22(body, "api_mode") ?? readString22(body, "apiMode") ?? void 0,
37487
+ apiKey: readString23(body, "api_key") ?? readString23(body, "apiKey") ?? void 0,
37488
+ apiMode: readString23(body, "api_mode") ?? readString23(body, "apiMode") ?? void 0,
36960
37489
  contextLength: readPositiveInteger2(
36961
37490
  body.context_length ?? body.contextLength
36962
37491
  ),
36963
- keyEnv: readString22(body, "key_env") ?? readString22(body, "keyEnv") ?? void 0,
37492
+ keyEnv: readString23(body, "key_env") ?? readString23(body, "keyEnv") ?? void 0,
36964
37493
  setDefault: readBoolean4(body.set_default ?? body.setDefault),
36965
- reasoningEffort: readString22(body, "reasoning_effort") ?? readString22(body, "reasoningEffort") ?? void 0,
36966
- reasoningSupportPolicy: readString22(body, "reasoning_support_policy") ?? readString22(body, "reasoningSupportPolicy") ?? readString22(body, "reasoning_support") ?? readString22(body, "reasoningSupport") ?? void 0,
37494
+ reasoningEffort: readString23(body, "reasoning_effort") ?? readString23(body, "reasoningEffort") ?? void 0,
37495
+ reasoningSupportPolicy: readString23(body, "reasoning_support_policy") ?? readString23(body, "reasoningSupportPolicy") ?? readString23(body, "reasoning_support") ?? readString23(body, "reasoningSupport") ?? void 0,
36967
37496
  supportsVision: readNullableBoolean2(
36968
37497
  body.supports_vision ?? body.supportsVision
36969
37498
  )
@@ -36971,28 +37500,28 @@ function readModelConfigInput(body) {
36971
37500
  }
36972
37501
  function readModelDefaultsInput(body) {
36973
37502
  return {
36974
- taskModelId: readString22(body, "task_model_id") ?? readString22(body, "taskModelId") ?? readString22(body, "default_model_id") ?? readString22(body, "defaultModelId") ?? void 0,
36975
- taskModelProvider: readString22(body, "task_model_provider") ?? readString22(body, "taskModelProvider") ?? readString22(body, "default_model_provider") ?? readString22(body, "defaultModelProvider") ?? void 0,
36976
- taskModelBaseUrl: readString22(body, "task_model_base_url") ?? readString22(body, "taskModelBaseUrl") ?? readString22(body, "default_model_base_url") ?? readString22(body, "defaultModelBaseUrl") ?? void 0,
36977
- taskModelApiMode: readString22(body, "task_model_api_mode") ?? readString22(body, "taskModelApiMode") ?? readString22(body, "default_model_api_mode") ?? readString22(body, "defaultModelApiMode") ?? void 0,
36978
- compressionModelId: readString22(body, "compression_model_id") ?? readString22(body, "compressionModelId") ?? void 0,
36979
- compressionModelProvider: readString22(body, "compression_model_provider") ?? readString22(body, "compressionModelProvider") ?? void 0,
36980
- compressionModelBaseUrl: readString22(body, "compression_model_base_url") ?? readString22(body, "compressionModelBaseUrl") ?? void 0,
36981
- compressionModelApiMode: readString22(body, "compression_model_api_mode") ?? readString22(body, "compressionModelApiMode") ?? void 0,
36982
- reasoningEffort: readString22(body, "reasoning_effort") ?? readString22(body, "reasoningEffort") ?? readString22(body, "default_reasoning_effort") ?? readString22(body, "defaultReasoningEffort") ?? void 0,
36983
- imageInputMode: readString22(body, "image_input_mode") ?? readString22(body, "imageInputMode") ?? void 0
37503
+ taskModelId: readString23(body, "task_model_id") ?? readString23(body, "taskModelId") ?? readString23(body, "default_model_id") ?? readString23(body, "defaultModelId") ?? void 0,
37504
+ taskModelProvider: readString23(body, "task_model_provider") ?? readString23(body, "taskModelProvider") ?? readString23(body, "default_model_provider") ?? readString23(body, "defaultModelProvider") ?? void 0,
37505
+ taskModelBaseUrl: readString23(body, "task_model_base_url") ?? readString23(body, "taskModelBaseUrl") ?? readString23(body, "default_model_base_url") ?? readString23(body, "defaultModelBaseUrl") ?? void 0,
37506
+ taskModelApiMode: readString23(body, "task_model_api_mode") ?? readString23(body, "taskModelApiMode") ?? readString23(body, "default_model_api_mode") ?? readString23(body, "defaultModelApiMode") ?? void 0,
37507
+ compressionModelId: readString23(body, "compression_model_id") ?? readString23(body, "compressionModelId") ?? void 0,
37508
+ compressionModelProvider: readString23(body, "compression_model_provider") ?? readString23(body, "compressionModelProvider") ?? void 0,
37509
+ compressionModelBaseUrl: readString23(body, "compression_model_base_url") ?? readString23(body, "compressionModelBaseUrl") ?? void 0,
37510
+ compressionModelApiMode: readString23(body, "compression_model_api_mode") ?? readString23(body, "compressionModelApiMode") ?? void 0,
37511
+ reasoningEffort: readString23(body, "reasoning_effort") ?? readString23(body, "reasoningEffort") ?? readString23(body, "default_reasoning_effort") ?? readString23(body, "defaultReasoningEffort") ?? void 0,
37512
+ imageInputMode: readString23(body, "image_input_mode") ?? readString23(body, "imageInputMode") ?? void 0
36984
37513
  };
36985
37514
  }
36986
37515
  function readModelDeleteInput(body) {
36987
- const id = readString22(body, "model_id") ?? readString22(body, "modelId");
37516
+ const id = readString23(body, "model_id") ?? readString23(body, "modelId");
36988
37517
  if (!id) {
36989
37518
  throw new LinkHttpError(400, "model_id_required", "model_id is required");
36990
37519
  }
36991
37520
  return {
36992
37521
  id,
36993
- provider: readString22(body, "provider") ?? readString22(body, "provider_key") ?? readString22(body, "providerKey") ?? void 0,
36994
- baseUrl: readString22(body, "base_url") ?? readString22(body, "baseUrl") ?? void 0,
36995
- apiMode: readString22(body, "api_mode") ?? readString22(body, "apiMode") ?? void 0
37522
+ provider: readString23(body, "provider") ?? readString23(body, "provider_key") ?? readString23(body, "providerKey") ?? void 0,
37523
+ baseUrl: readString23(body, "base_url") ?? readString23(body, "baseUrl") ?? void 0,
37524
+ apiMode: readString23(body, "api_mode") ?? readString23(body, "apiMode") ?? void 0
36996
37525
  };
36997
37526
  }
36998
37527
  function readNullableBoolean2(value) {
@@ -37015,8 +37544,8 @@ function readNullableBoolean2(value) {
37015
37544
  return void 0;
37016
37545
  }
37017
37546
  function readModelConfigImportInput(body) {
37018
- const sourceProfileName = readString22(body, "source_profile") ?? readString22(body, "sourceProfile") ?? readString22(body, "source_profile_name") ?? readString22(body, "sourceProfileName");
37019
- const modelId = readString22(body, "model_id") ?? readString22(body, "modelId") ?? readString22(body, "id");
37547
+ const sourceProfileName = readString23(body, "source_profile") ?? readString23(body, "sourceProfile") ?? readString23(body, "source_profile_name") ?? readString23(body, "sourceProfileName");
37548
+ const modelId = readString23(body, "model_id") ?? readString23(body, "modelId") ?? readString23(body, "id");
37020
37549
  if (!sourceProfileName || !modelId) {
37021
37550
  throw new LinkHttpError(
37022
37551
  400,
@@ -37027,9 +37556,9 @@ function readModelConfigImportInput(body) {
37027
37556
  return {
37028
37557
  sourceProfileName,
37029
37558
  modelId,
37030
- provider: readString22(body, "provider") ?? readString22(body, "provider_key") ?? readString22(body, "providerKey") ?? void 0,
37031
- baseUrl: readString22(body, "base_url") ?? readString22(body, "baseUrl") ?? void 0,
37032
- apiMode: readString22(body, "api_mode") ?? readString22(body, "apiMode") ?? void 0,
37559
+ provider: readString23(body, "provider") ?? readString23(body, "provider_key") ?? readString23(body, "providerKey") ?? void 0,
37560
+ baseUrl: readString23(body, "base_url") ?? readString23(body, "baseUrl") ?? void 0,
37561
+ apiMode: readString23(body, "api_mode") ?? readString23(body, "apiMode") ?? void 0,
37033
37562
  setDefault: readBoolean4(body.set_default ?? body.setDefault)
37034
37563
  };
37035
37564
  }
@@ -37136,19 +37665,19 @@ function errorMessage3(error) {
37136
37665
  }
37137
37666
 
37138
37667
  // src/hermes/profile-identity.ts
37139
- import { readFile as readFile16, stat as stat18 } from "fs/promises";
37140
- import path29 from "path";
37668
+ import { readFile as readFile17, stat as stat19 } from "fs/promises";
37669
+ import path30 from "path";
37141
37670
  var MAX_SOUL_MD_LENGTH = 2e4;
37142
37671
  async function readHermesProfileIdentity(profileName, paths) {
37143
37672
  await assertProfileExists3(profileName, paths);
37144
37673
  const soulPath = resolveSoulPath(profileName);
37145
- const content = await readFile16(soulPath, "utf8").catch((error) => {
37674
+ const content = await readFile17(soulPath, "utf8").catch((error) => {
37146
37675
  if (isNodeError19(error, "ENOENT")) {
37147
37676
  return null;
37148
37677
  }
37149
37678
  throw error;
37150
37679
  });
37151
- const fileStat = content === null ? null : await stat18(soulPath).catch((error) => {
37680
+ const fileStat = content === null ? null : await stat19(soulPath).catch((error) => {
37152
37681
  if (isNodeError19(error, "ENOENT")) {
37153
37682
  return null;
37154
37683
  }
@@ -37194,7 +37723,7 @@ async function assertProfileExists3(profileName, paths) {
37194
37723
  }
37195
37724
  }
37196
37725
  function resolveSoulPath(profileName) {
37197
- return path29.join(resolveHermesProfileDir(profileName), "SOUL.md");
37726
+ return path30.join(resolveHermesProfileDir(profileName), "SOUL.md");
37198
37727
  }
37199
37728
  function isNodeError19(error, code) {
37200
37729
  return error instanceof Error && "code" in error && error.code === code;
@@ -37206,17 +37735,17 @@ import { EventEmitter as EventEmitter2 } from "events";
37206
37735
  import {
37207
37736
  cp,
37208
37737
  mkdir as mkdir13,
37209
- readFile as readFile18,
37738
+ readFile as readFile19,
37210
37739
  rm as rm7,
37211
- stat as stat20
37740
+ stat as stat21
37212
37741
  } from "fs/promises";
37213
- import path31 from "path";
37742
+ import path32 from "path";
37214
37743
  import YAML5 from "yaml";
37215
37744
 
37216
37745
  // src/hermes/link-skill.ts
37217
- import { readFile as readFile17, stat as stat19 } from "fs/promises";
37746
+ import { readFile as readFile18, stat as stat20 } from "fs/promises";
37218
37747
  import os7 from "os";
37219
- import path30 from "path";
37748
+ import path31 from "path";
37220
37749
  import YAML4 from "yaml";
37221
37750
  var HERMES_LINK_SKILL_ROOT_DIR = "hermes-skills";
37222
37751
  var HERMES_LINK_SKILL_DIR = "hermes-link";
@@ -37313,7 +37842,7 @@ Do not modify Hermes profiles, delete user data, edit config files, or kill proc
37313
37842
  async function ensureHermesLinkSkillInstalledForProfiles(options = {}) {
37314
37843
  const paths = options.paths ?? resolveRuntimePaths();
37315
37844
  const externalDir = resolveHermesLinkSkillExternalDir(paths);
37316
- const skillPath = path30.join(
37845
+ const skillPath = path31.join(
37317
37846
  externalDir,
37318
37847
  HERMES_LINK_SKILL_DIR,
37319
37848
  HERMES_LINK_SKILL_FILE
@@ -37395,10 +37924,10 @@ function withDefaultProfilePlaceholder2(profiles) {
37395
37924
  ];
37396
37925
  }
37397
37926
  function resolveHermesLinkSkillExternalDir(paths = resolveRuntimePaths()) {
37398
- return path30.join(paths.homeDir, HERMES_LINK_SKILL_ROOT_DIR);
37927
+ return path31.join(paths.homeDir, HERMES_LINK_SKILL_ROOT_DIR);
37399
37928
  }
37400
37929
  async function writeHermesLinkSkill(skillPath) {
37401
- const existing = await readFile17(skillPath, "utf8").catch((error) => {
37930
+ const existing = await readFile18(skillPath, "utf8").catch((error) => {
37402
37931
  if (isNodeError20(error, "ENOENT")) {
37403
37932
  return null;
37404
37933
  }
@@ -37456,7 +37985,7 @@ async function ensureProfileUsesExternalSkillDir(profile, externalDir) {
37456
37985
  };
37457
37986
  }
37458
37987
  async function readHermesConfigDocument3(configPath) {
37459
- const existingRaw = await readFile17(configPath, "utf8").catch(
37988
+ const existingRaw = await readFile18(configPath, "utf8").catch(
37460
37989
  (error) => {
37461
37990
  if (isNodeError20(error, "ENOENT")) {
37462
37991
  return null;
@@ -37490,11 +38019,11 @@ function appendExternalDir(current, externalDir, hermesHome) {
37490
38019
  const seen = new Set(
37491
38020
  entries.map((entry) => resolveExternalDirEntry(entry, hermesHome))
37492
38021
  );
37493
- const normalizedExternalDir = path30.resolve(externalDir);
38022
+ const normalizedExternalDir = path31.resolve(externalDir);
37494
38023
  return seen.has(normalizedExternalDir) ? entries : [...entries, normalizedExternalDir];
37495
38024
  }
37496
38025
  function externalDirsInclude(current, externalDir, hermesHome) {
37497
- const normalizedExternalDir = path30.resolve(externalDir);
38026
+ const normalizedExternalDir = path31.resolve(externalDir);
37498
38027
  return readExternalDirEntries(current).some(
37499
38028
  (entry) => resolveExternalDirEntry(entry, hermesHome) === normalizedExternalDir
37500
38029
  );
@@ -37505,14 +38034,14 @@ function readExternalDirEntries(value) {
37505
38034
  }
37506
38035
  function resolveExternalDirEntry(entry, hermesHome) {
37507
38036
  const expanded = expandHome(expandEnvVars(entry));
37508
- return path30.resolve(path30.isAbsolute(expanded) ? expanded : path30.join(hermesHome, expanded));
38037
+ return path31.resolve(path31.isAbsolute(expanded) ? expanded : path31.join(hermesHome, expanded));
37509
38038
  }
37510
38039
  function expandHome(value) {
37511
38040
  if (value === "~") {
37512
38041
  return os7.homedir();
37513
38042
  }
37514
- if (value.startsWith(`~${path30.sep}`) || value.startsWith("~/")) {
37515
- return path30.join(os7.homedir(), value.slice(2));
38043
+ if (value.startsWith(`~${path31.sep}`) || value.startsWith("~/")) {
38044
+ return path31.join(os7.homedir(), value.slice(2));
37516
38045
  }
37517
38046
  return value;
37518
38047
  }
@@ -37523,7 +38052,7 @@ function expandEnvVars(value) {
37523
38052
  );
37524
38053
  }
37525
38054
  async function pathIsDirectory2(filePath) {
37526
- return stat19(filePath).then((value) => value.isDirectory()).catch((error) => {
38055
+ return stat20(filePath).then((value) => value.isDirectory()).catch((error) => {
37527
38056
  if (isNodeError20(error, "ENOENT")) {
37528
38057
  return false;
37529
38058
  }
@@ -38064,8 +38593,8 @@ function collectEnvKeys(value, keys = /* @__PURE__ */ new Set()) {
38064
38593
  return keys;
38065
38594
  }
38066
38595
  async function writeEnvValues(profileName, values) {
38067
- const envPath = path31.join(resolveHermesProfileDir(profileName), ".env");
38068
- const existingRaw = await readFile18(envPath, "utf8").catch((error) => {
38596
+ const envPath = path32.join(resolveHermesProfileDir(profileName), ".env");
38597
+ const existingRaw = await readFile19(envPath, "utf8").catch((error) => {
38069
38598
  if (isNodeError21(error, "ENOENT")) {
38070
38599
  return "";
38071
38600
  }
@@ -38101,8 +38630,8 @@ async function writeEnvValues(profileName, values) {
38101
38630
  await atomicWriteFilePreservingMetadata(envPath, nextRaw);
38102
38631
  }
38103
38632
  async function copySkills(sourceProfile, targetProfile) {
38104
- const sourceSkills = path31.join(resolveHermesProfileDir(sourceProfile), "skills");
38105
- const targetSkills = path31.join(resolveHermesProfileDir(targetProfile), "skills");
38633
+ const sourceSkills = path32.join(resolveHermesProfileDir(sourceProfile), "skills");
38634
+ const targetSkills = path32.join(resolveHermesProfileDir(targetProfile), "skills");
38106
38635
  if (!await pathExists2(sourceSkills)) {
38107
38636
  return;
38108
38637
  }
@@ -38125,7 +38654,7 @@ function copyProperty(source, target, key) {
38125
38654
  }
38126
38655
  }
38127
38656
  async function readYamlConfig(configPath) {
38128
- const existingRaw = await readFile18(configPath, "utf8").catch(
38657
+ const existingRaw = await readFile19(configPath, "utf8").catch(
38129
38658
  (error) => {
38130
38659
  if (isNodeError21(error, "ENOENT")) {
38131
38660
  return null;
@@ -38188,7 +38717,7 @@ async function writeProfileCreationState(paths, state) {
38188
38717
  await writeJsonFile(profileCreationStatePath(paths), state);
38189
38718
  }
38190
38719
  async function readProfileCreationLogLines(paths) {
38191
- const raw = await readFile18(profileCreationLogPath(paths), "utf8").catch(() => "");
38720
+ const raw = await readFile19(profileCreationLogPath(paths), "utf8").catch(() => "");
38192
38721
  if (!raw.trim()) {
38193
38722
  return [];
38194
38723
  }
@@ -38197,10 +38726,10 @@ async function readProfileCreationLogLines(paths) {
38197
38726
  );
38198
38727
  }
38199
38728
  function profileCreationStatePath(paths) {
38200
- return path31.join(paths.runDir, "profile-create-state.json");
38729
+ return path32.join(paths.runDir, "profile-create-state.json");
38201
38730
  }
38202
38731
  function profileCreationLogPath(paths) {
38203
- return path31.join(paths.logsDir, PROFILE_CREATE_LOG_FILE);
38732
+ return path32.join(paths.logsDir, PROFILE_CREATE_LOG_FILE);
38204
38733
  }
38205
38734
  async function clearProfileCreationLogFiles(paths) {
38206
38735
  const primary = profileCreationLogPath(paths);
@@ -38213,7 +38742,7 @@ async function clearProfileCreationLogFiles(paths) {
38213
38742
  ]);
38214
38743
  }
38215
38744
  async function pathExists2(targetPath) {
38216
- return await stat20(targetPath).then(() => true).catch((error) => {
38745
+ return await stat21(targetPath).then(() => true).catch((error) => {
38217
38746
  if (isNodeError21(error, "ENOENT")) {
38218
38747
  return false;
38219
38748
  }
@@ -38346,16 +38875,16 @@ function readProfilePermissionsInput(body) {
38346
38875
  const approvals = readOptionalObject(body, "approvals");
38347
38876
  if (approvals) {
38348
38877
  input.approvals = {
38349
- mode: readString22(approvals, "mode") ?? readString22(approvals, "approval_mode") ?? readString22(approvals, "approvalMode") ?? void 0,
38878
+ mode: readString23(approvals, "mode") ?? readString23(approvals, "approval_mode") ?? readString23(approvals, "approvalMode") ?? void 0,
38350
38879
  timeout: readPositiveInteger2(approvals.timeout),
38351
- cronMode: readString22(approvals, "cron_mode") ?? readString22(approvals, "cronMode") ?? void 0
38880
+ cronMode: readString23(approvals, "cron_mode") ?? readString23(approvals, "cronMode") ?? void 0
38352
38881
  };
38353
38882
  }
38354
38883
  const terminal = readOptionalObject(body, "terminal");
38355
38884
  if (terminal) {
38356
38885
  input.terminal = {
38357
- backend: readString22(terminal, "backend") ?? void 0,
38358
- cwd: readString22(terminal, "cwd") ?? void 0,
38886
+ backend: readString23(terminal, "backend") ?? void 0,
38887
+ cwd: readString23(terminal, "cwd") ?? void 0,
38359
38888
  containerCpu: readPositiveInteger2(
38360
38889
  terminal.container_cpu ?? terminal.containerCpu
38361
38890
  ),
@@ -38486,10 +39015,10 @@ function toProfileToolConfigHttpError(error) {
38486
39015
  import {
38487
39016
  access as access3,
38488
39017
  readdir as readdir10,
38489
- readFile as readFile19,
38490
- stat as stat21
39018
+ readFile as readFile20,
39019
+ stat as stat22
38491
39020
  } from "fs/promises";
38492
- import path32 from "path";
39021
+ import path33 from "path";
38493
39022
  import YAML6 from "yaml";
38494
39023
  var ENTRY_DELIMITER = "\n\xA7\n";
38495
39024
  var DEFAULT_MEMORY_LIMIT = 2200;
@@ -38686,9 +39215,9 @@ async function testHindsightProviderSettings(profileName, patch) {
38686
39215
  const mode = normalizeHindsightMode(
38687
39216
  patch.mode ?? config.mode ?? env.HINDSIGHT_MODE
38688
39217
  );
38689
- const apiUrl = readString24(patch.apiUrl) ?? readString24(config.api_url) ?? env.HINDSIGHT_API_URL ?? (mode === "cloud" ? HINDSIGHT_DEFAULT_API_URL : HINDSIGHT_DEFAULT_LOCAL_URL);
38690
- const bankId = readString24(patch.bankId) ?? readString24(config.bank_id) ?? "hermes";
38691
- const apiKey = readString24(patch.apiKey) ?? env.HINDSIGHT_API_KEY ?? readString24(config.apiKey) ?? readString24(config.api_key);
39218
+ const apiUrl = readString25(patch.apiUrl) ?? readString25(config.api_url) ?? env.HINDSIGHT_API_URL ?? (mode === "cloud" ? HINDSIGHT_DEFAULT_API_URL : HINDSIGHT_DEFAULT_LOCAL_URL);
39219
+ const bankId = readString25(patch.bankId) ?? readString25(config.bank_id) ?? "hermes";
39220
+ const apiKey = readString25(patch.apiKey) ?? env.HINDSIGHT_API_KEY ?? readString25(config.apiKey) ?? readString25(config.api_key);
38692
39221
  const baseUrl = normalizeHttpUrl2(apiUrl);
38693
39222
  if (!baseUrl) {
38694
39223
  return {
@@ -38820,7 +39349,7 @@ async function saveProviderSettings(profileName, provider, patch) {
38820
39349
  });
38821
39350
  await patchJsonProviderConfig(
38822
39351
  profileName,
38823
- path32.join("hindsight", "config.json"),
39352
+ path33.join("hindsight", "config.json"),
38824
39353
  {
38825
39354
  mode: patch.mode,
38826
39355
  api_url: patch.apiUrl,
@@ -38968,7 +39497,7 @@ function normalizeCustomProviderId(provider) {
38968
39497
  }
38969
39498
  async function patchHermesMemoryProvider(profileName, provider) {
38970
39499
  const configPath = resolveHermesConfigPath(profileName);
38971
- const existingRaw = await readFile19(configPath, "utf8").catch(
39500
+ const existingRaw = await readFile20(configPath, "utf8").catch(
38972
39501
  (error) => {
38973
39502
  if (isNodeError22(error, "ENOENT")) {
38974
39503
  return null;
@@ -38992,7 +39521,7 @@ async function patchHermesMemoryProvider(profileName, provider) {
38992
39521
  }
38993
39522
  async function patchHermesMemoryLimits(profileName, patch) {
38994
39523
  const configPath = resolveHermesConfigPath(profileName);
38995
- const existingRaw = await readFile19(configPath, "utf8").catch(
39524
+ const existingRaw = await readFile20(configPath, "utf8").catch(
38996
39525
  (error) => {
38997
39526
  if (isNodeError22(error, "ENOENT")) {
38998
39527
  return null;
@@ -39023,12 +39552,12 @@ async function patchHermesMemoryLimits(profileName, patch) {
39023
39552
  await atomicWriteFilePreservingMetadata(configPath, document.toString());
39024
39553
  }
39025
39554
  function resolveMemoryDir(profileName) {
39026
- return path32.join(resolveHermesProfileDir(profileName), "memories");
39555
+ return path33.join(resolveHermesProfileDir(profileName), "memories");
39027
39556
  }
39028
39557
  async function readMemoryStore(profileName, target, limits) {
39029
39558
  const filePath = memoryFilePath(profileName, target);
39030
39559
  const entries = await readMemoryEntries(filePath);
39031
- const fileStat = await stat21(filePath).catch((error) => {
39560
+ const fileStat = await stat22(filePath).catch((error) => {
39032
39561
  if (isNodeError22(error, "ENOENT")) {
39033
39562
  return null;
39034
39563
  }
@@ -39057,7 +39586,7 @@ async function readMemoryStore(profileName, target, limits) {
39057
39586
  };
39058
39587
  }
39059
39588
  async function readMemoryEntries(filePath) {
39060
- const raw = await readFile19(filePath, "utf8").catch((error) => {
39589
+ const raw = await readFile20(filePath, "utf8").catch((error) => {
39061
39590
  if (isNodeError22(error, "ENOENT")) {
39062
39591
  return "";
39063
39592
  }
@@ -39084,7 +39613,7 @@ async function writeMemoryEntries(profileName, target, entries) {
39084
39613
  );
39085
39614
  }
39086
39615
  function memoryFilePath(profileName, target) {
39087
- return path32.join(
39616
+ return path33.join(
39088
39617
  resolveMemoryDir(profileName),
39089
39618
  target === "user" ? "USER.md" : "MEMORY.md"
39090
39619
  );
@@ -39144,7 +39673,7 @@ async function readCustomProviderSetupSummary(profileName) {
39144
39673
  configurable: true,
39145
39674
  configured: true,
39146
39675
  configurationIssue: null,
39147
- providerConfigPath: path32.join(
39676
+ providerConfigPath: path33.join(
39148
39677
  resolveHermesProfileDir(profileName),
39149
39678
  "<provider>.json"
39150
39679
  ),
@@ -39222,7 +39751,7 @@ async function readProviderConfigurationStatus(profileName, provider) {
39222
39751
  const config2 = await readJsonObject(
39223
39752
  memoryProviderConfigPath(profileName, "honcho") ?? ""
39224
39753
  );
39225
- return isConfiguredEnvValue(env.HONCHO_API_KEY) || isConfiguredEnvValue(readString24(config2.apiKey)) || isConfiguredEnvValue(readString24(config2.api_key)) || isConfiguredEnvValue(readString24(config2.baseUrl)) ? { configured: true, issue: null } : {
39754
+ return isConfiguredEnvValue(env.HONCHO_API_KEY) || isConfiguredEnvValue(readString25(config2.apiKey)) || isConfiguredEnvValue(readString25(config2.api_key)) || isConfiguredEnvValue(readString25(config2.baseUrl)) ? { configured: true, issue: null } : {
39226
39755
  configured: false,
39227
39756
  issue: "Honcho \u9700\u8981\u5148\u586B\u5199 API Key\uFF0C\u6216\u5728 honcho.json \u914D\u7F6E self-hosted baseUrl\u3002"
39228
39757
  };
@@ -39231,7 +39760,7 @@ async function readProviderConfigurationStatus(profileName, provider) {
39231
39760
  const config2 = await readJsonObject(
39232
39761
  memoryProviderConfigPath(profileName, "mem0") ?? ""
39233
39762
  );
39234
- return isConfiguredEnvValue(env.MEM0_API_KEY) || isConfiguredEnvValue(readString24(config2.api_key)) ? { configured: true, issue: null } : {
39763
+ return isConfiguredEnvValue(env.MEM0_API_KEY) || isConfiguredEnvValue(readString25(config2.api_key)) ? { configured: true, issue: null } : {
39235
39764
  configured: false,
39236
39765
  issue: "Mem0 \u9700\u8981\u5148\u5728\u672C\u9875\u586B\u5199 API Key\uFF0CLink \u4F1A\u5199\u5165\u5F53\u524D Profile \u7684 .env\u3002"
39237
39766
  };
@@ -39273,7 +39802,7 @@ async function readProviderConfigurationStatus(profileName, provider) {
39273
39802
  memoryProviderConfigPath(profileName, provider) ?? ""
39274
39803
  );
39275
39804
  const mode = normalizeHindsightMode(config.mode ?? env.HINDSIGHT_MODE);
39276
- const apiKey = readString24(config.apiKey) ?? readString24(config.api_key) ?? env.HINDSIGHT_API_KEY;
39805
+ const apiKey = readString25(config.apiKey) ?? readString25(config.api_key) ?? env.HINDSIGHT_API_KEY;
39277
39806
  if (mode === "cloud") {
39278
39807
  return isConfiguredEnvValue(apiKey) ? { configured: true, issue: null } : {
39279
39808
  configured: false,
@@ -39281,15 +39810,15 @@ async function readProviderConfigurationStatus(profileName, provider) {
39281
39810
  };
39282
39811
  }
39283
39812
  if (mode === "local_external") {
39284
- const apiUrl = readString24(config.api_url) ?? env.HINDSIGHT_API_URL ?? HINDSIGHT_DEFAULT_LOCAL_URL;
39813
+ const apiUrl = readString25(config.api_url) ?? env.HINDSIGHT_API_URL ?? HINDSIGHT_DEFAULT_LOCAL_URL;
39285
39814
  return isConfiguredEnvValue(apiUrl) ? { configured: true, issue: null } : {
39286
39815
  configured: false,
39287
39816
  issue: "Hindsight local_external \u9700\u8981\u914D\u7F6E\u53EF\u8BBF\u95EE\u7684 API URL\u3002"
39288
39817
  };
39289
39818
  }
39290
39819
  if (mode === "local_embedded") {
39291
- const llmProvider = readString24(config.llm_provider) ?? "openai";
39292
- const llmModel = readString24(config.llm_model);
39820
+ const llmProvider = readString25(config.llm_provider) ?? "openai";
39821
+ const llmModel = readString25(config.llm_model);
39293
39822
  if (!llmModel) {
39294
39823
  return {
39295
39824
  configured: false,
@@ -39297,7 +39826,7 @@ async function readProviderConfigurationStatus(profileName, provider) {
39297
39826
  };
39298
39827
  }
39299
39828
  if (llmProvider === "openai_compatible" && !isConfiguredEnvValue(
39300
- readString24(config.llm_base_url) ?? env.HINDSIGHT_API_LLM_BASE_URL
39829
+ readString25(config.llm_base_url) ?? env.HINDSIGHT_API_LLM_BASE_URL
39301
39830
  )) {
39302
39831
  return {
39303
39832
  configured: false,
@@ -39305,7 +39834,7 @@ async function readProviderConfigurationStatus(profileName, provider) {
39305
39834
  };
39306
39835
  }
39307
39836
  if (!["ollama", "lmstudio", "openai_compatible"].includes(llmProvider) && !isConfiguredEnvValue(
39308
- readString24(config.llmApiKey) ?? readString24(config.llm_api_key) ?? env.HINDSIGHT_LLM_API_KEY
39837
+ readString25(config.llmApiKey) ?? readString25(config.llm_api_key) ?? env.HINDSIGHT_LLM_API_KEY
39309
39838
  )) {
39310
39839
  return {
39311
39840
  configured: false,
@@ -39361,8 +39890,8 @@ async function readProviderSettings(profileName, provider) {
39361
39890
  secretSetting(
39362
39891
  "apiKey",
39363
39892
  "API Key",
39364
- env.HONCHO_API_KEY ?? readString24(config.apiKey) ?? readString24(config.api_key),
39365
- isConfiguredEnvValue(env.HONCHO_API_KEY) || isConfiguredEnvValue(readString24(config.apiKey)) || isConfiguredEnvValue(readString24(config.api_key))
39893
+ env.HONCHO_API_KEY ?? readString25(config.apiKey) ?? readString25(config.api_key),
39894
+ isConfiguredEnvValue(env.HONCHO_API_KEY) || isConfiguredEnvValue(readString25(config.apiKey)) || isConfiguredEnvValue(readString25(config.api_key))
39366
39895
  ),
39367
39896
  stringSetting("workspace", "Workspace", config.workspace ?? "hermes"),
39368
39897
  stringSetting("peerName", "\u7528\u6237 Peer", config.peerName ?? ""),
@@ -39404,8 +39933,8 @@ async function readProviderSettings(profileName, provider) {
39404
39933
  secretSetting(
39405
39934
  "apiKey",
39406
39935
  "API Key",
39407
- env.MEM0_API_KEY ?? readString24(config.apiKey) ?? readString24(config.api_key),
39408
- isConfiguredEnvValue(env.MEM0_API_KEY) || isConfiguredEnvValue(readString24(config.apiKey)) || isConfiguredEnvValue(readString24(config.api_key))
39936
+ env.MEM0_API_KEY ?? readString25(config.apiKey) ?? readString25(config.api_key),
39937
+ isConfiguredEnvValue(env.MEM0_API_KEY) || isConfiguredEnvValue(readString25(config.apiKey)) || isConfiguredEnvValue(readString25(config.api_key))
39409
39938
  ),
39410
39939
  stringSetting("userId", "User ID", config.user_id ?? "hermes-user"),
39411
39940
  stringSetting("agentId", "Agent ID", config.agent_id ?? "hermes"),
@@ -39490,8 +40019,8 @@ async function readProviderSettings(profileName, provider) {
39490
40019
  secretSetting(
39491
40020
  "apiKey",
39492
40021
  "Hindsight API Key",
39493
- env.HINDSIGHT_API_KEY ?? readString24(config.apiKey) ?? readString24(config.api_key),
39494
- isConfiguredEnvValue(env.HINDSIGHT_API_KEY) || isConfiguredEnvValue(readString24(config.apiKey)) || isConfiguredEnvValue(readString24(config.api_key))
40022
+ env.HINDSIGHT_API_KEY ?? readString25(config.apiKey) ?? readString25(config.api_key),
40023
+ isConfiguredEnvValue(env.HINDSIGHT_API_KEY) || isConfiguredEnvValue(readString25(config.apiKey)) || isConfiguredEnvValue(readString25(config.api_key))
39495
40024
  ),
39496
40025
  stringSetting(
39497
40026
  "bankId",
@@ -39513,8 +40042,8 @@ async function readProviderSettings(profileName, provider) {
39513
40042
  secretSetting(
39514
40043
  "llmApiKey",
39515
40044
  "LLM API Key",
39516
- env.HINDSIGHT_LLM_API_KEY ?? readString24(config.llmApiKey) ?? readString24(config.llm_api_key),
39517
- isConfiguredEnvValue(env.HINDSIGHT_LLM_API_KEY) || isConfiguredEnvValue(readString24(config.llmApiKey)) || isConfiguredEnvValue(readString24(config.llm_api_key))
40045
+ env.HINDSIGHT_LLM_API_KEY ?? readString25(config.llmApiKey) ?? readString25(config.llm_api_key),
40046
+ isConfiguredEnvValue(env.HINDSIGHT_LLM_API_KEY) || isConfiguredEnvValue(readString25(config.llmApiKey)) || isConfiguredEnvValue(readString25(config.llm_api_key))
39518
40047
  ),
39519
40048
  booleanSetting("autoRecall", "\u81EA\u52A8\u56DE\u5FC6", config.auto_recall ?? true),
39520
40049
  booleanSetting("autoRetain", "\u81EA\u52A8\u6C89\u6DC0", config.auto_retain ?? true),
@@ -39538,7 +40067,7 @@ async function readProviderSettings(profileName, provider) {
39538
40067
  stringSetting(
39539
40068
  "dbPath",
39540
40069
  "SQLite \u6570\u636E\u5E93\u8DEF\u5F84",
39541
- config.db_path ?? path32.join(resolveHermesProfileDir(profileName), "memory_store.db")
40070
+ config.db_path ?? path33.join(resolveHermesProfileDir(profileName), "memory_store.db")
39542
40071
  ),
39543
40072
  booleanSetting("autoExtract", "\u4F1A\u8BDD\u7ED3\u675F\u81EA\u52A8\u62BD\u53D6", config.auto_extract ?? false),
39544
40073
  numberSetting("defaultTrust", "\u9ED8\u8BA4\u4FE1\u4EFB\u5206", config.default_trust ?? 0.5),
@@ -39574,7 +40103,7 @@ async function readProviderSettings(profileName, provider) {
39574
40103
  stringSetting(
39575
40104
  "workingDirectory",
39576
40105
  "\u5DE5\u4F5C\u76EE\u5F55",
39577
- path32.join(resolveHermesProfileDir(profileName), "byterover"),
40106
+ path33.join(resolveHermesProfileDir(profileName), "byterover"),
39578
40107
  false
39579
40108
  )
39580
40109
  ];
@@ -39583,16 +40112,16 @@ async function readProviderSettings(profileName, provider) {
39583
40112
  }
39584
40113
  function memoryProviderConfigPath(profileName, provider) {
39585
40114
  if (provider === "honcho") {
39586
- return path32.join(resolveHermesProfileDir(profileName), "honcho.json");
40115
+ return path33.join(resolveHermesProfileDir(profileName), "honcho.json");
39587
40116
  }
39588
40117
  if (provider === "mem0") {
39589
- return path32.join(resolveHermesProfileDir(profileName), "mem0.json");
40118
+ return path33.join(resolveHermesProfileDir(profileName), "mem0.json");
39590
40119
  }
39591
40120
  if (provider === "supermemory") {
39592
- return path32.join(resolveHermesProfileDir(profileName), "supermemory.json");
40121
+ return path33.join(resolveHermesProfileDir(profileName), "supermemory.json");
39593
40122
  }
39594
40123
  if (provider === "hindsight") {
39595
- return path32.join(
40124
+ return path33.join(
39596
40125
  resolveHermesProfileDir(profileName),
39597
40126
  "hindsight",
39598
40127
  "config.json"
@@ -39601,19 +40130,19 @@ function memoryProviderConfigPath(profileName, provider) {
39601
40130
  return null;
39602
40131
  }
39603
40132
  function customProviderConfigPath(profileName, provider) {
39604
- return path32.join(
40133
+ return path33.join(
39605
40134
  resolveHermesProfileDir(profileName),
39606
40135
  `${normalizeCustomProviderId(provider)}.json`
39607
40136
  );
39608
40137
  }
39609
40138
  function customProviderRegistryPath(profileName) {
39610
- return path32.join(
40139
+ return path33.join(
39611
40140
  resolveHermesProfileDir(profileName),
39612
40141
  CUSTOM_PROVIDER_REGISTRY_FILE
39613
40142
  );
39614
40143
  }
39615
40144
  async function readCustomProviderRegistry(profileName) {
39616
- const raw = await readFile19(customProviderRegistryPath(profileName), "utf8").catch(
40145
+ const raw = await readFile20(customProviderRegistryPath(profileName), "utf8").catch(
39617
40146
  (error) => {
39618
40147
  if (isNodeError22(error, "ENOENT")) {
39619
40148
  return "";
@@ -39633,11 +40162,11 @@ async function readCustomProviderRegistry(profileName) {
39633
40162
  return { id: id2, label: id2, description: "\u81EA\u5B9A\u4E49 memory provider\u3002" };
39634
40163
  }
39635
40164
  const record = toRecord22(item);
39636
- const id = normalizeCustomProviderId(readString24(record.id) ?? "");
40165
+ const id = normalizeCustomProviderId(readString25(record.id) ?? "");
39637
40166
  return {
39638
40167
  id,
39639
- label: readString24(record.label) ?? id,
39640
- description: readString24(record.description) ?? "\u81EA\u5B9A\u4E49 memory provider\u3002"
40168
+ label: readString25(record.label) ?? id,
40169
+ description: readString25(record.description) ?? "\u81EA\u5B9A\u4E49 memory provider\u3002"
39641
40170
  };
39642
40171
  }).filter((item) => item.id);
39643
40172
  } catch {
@@ -39659,7 +40188,7 @@ async function saveCustomProviderRegistryEntry(profileName, provider) {
39659
40188
  );
39660
40189
  }
39661
40190
  async function discoverUserMemoryProviderDescriptors(profileName) {
39662
- const pluginsDir = path32.join(resolveHermesProfileDir(profileName), "plugins");
40191
+ const pluginsDir = path33.join(resolveHermesProfileDir(profileName), "plugins");
39663
40192
  const entries = await readdir10(pluginsDir, { withFileTypes: true }).catch(
39664
40193
  (error) => {
39665
40194
  if (isNodeError22(error, "ENOENT")) {
@@ -39679,21 +40208,21 @@ async function discoverUserMemoryProviderDescriptors(profileName) {
39679
40208
  } catch {
39680
40209
  continue;
39681
40210
  }
39682
- const providerDir = path32.join(pluginsDir, entry.name);
40211
+ const providerDir = path33.join(pluginsDir, entry.name);
39683
40212
  if (!await isMemoryProviderPluginDir(providerDir)) {
39684
40213
  continue;
39685
40214
  }
39686
40215
  const meta = await readPluginMetadata(providerDir);
39687
40216
  descriptors.push({
39688
40217
  id: providerId,
39689
- label: readString24(meta.name) ?? providerId,
39690
- description: readString24(meta.description) ?? "\u81EA\u5B9A\u4E49 memory provider\u3002"
40218
+ label: readString25(meta.name) ?? providerId,
40219
+ description: readString25(meta.description) ?? "\u81EA\u5B9A\u4E49 memory provider\u3002"
39691
40220
  });
39692
40221
  }
39693
40222
  return descriptors;
39694
40223
  }
39695
40224
  async function isUserMemoryProviderInstalled(profileName, provider) {
39696
- const providerDir = path32.join(
40225
+ const providerDir = path33.join(
39697
40226
  resolveHermesProfileDir(profileName),
39698
40227
  "plugins",
39699
40228
  normalizeCustomProviderId(provider)
@@ -39701,7 +40230,7 @@ async function isUserMemoryProviderInstalled(profileName, provider) {
39701
40230
  return isMemoryProviderPluginDir(providerDir);
39702
40231
  }
39703
40232
  async function isMemoryProviderPluginDir(providerDir) {
39704
- const source = await readFile19(path32.join(providerDir, "__init__.py"), "utf8").catch(
40233
+ const source = await readFile20(path33.join(providerDir, "__init__.py"), "utf8").catch(
39705
40234
  (error) => {
39706
40235
  if (isNodeError22(error, "ENOENT")) {
39707
40236
  return "";
@@ -39713,7 +40242,7 @@ async function isMemoryProviderPluginDir(providerDir) {
39713
40242
  return sample.includes("register_memory_provider") || sample.includes("MemoryProvider");
39714
40243
  }
39715
40244
  async function readPluginMetadata(providerDir) {
39716
- const raw = await readFile19(path32.join(providerDir, "plugin.yaml"), "utf8").catch(
40245
+ const raw = await readFile20(path33.join(providerDir, "plugin.yaml"), "utf8").catch(
39717
40246
  (error) => {
39718
40247
  if (isNodeError22(error, "ENOENT")) {
39719
40248
  return "";
@@ -39725,10 +40254,10 @@ async function readPluginMetadata(providerDir) {
39725
40254
  }
39726
40255
  async function resolveByteRoverCli() {
39727
40256
  const candidates = [
39728
- ...(process.env.PATH ?? "").split(path32.delimiter).filter(Boolean).map((dir) => path32.join(dir, "brv")),
39729
- path32.join(process.env.HOME ?? "", ".brv-cli", "bin", "brv"),
40257
+ ...(process.env.PATH ?? "").split(path33.delimiter).filter(Boolean).map((dir) => path33.join(dir, "brv")),
40258
+ path33.join(process.env.HOME ?? "", ".brv-cli", "bin", "brv"),
39730
40259
  "/usr/local/bin/brv",
39731
- path32.join(process.env.HOME ?? "", ".npm-global", "bin", "brv")
40260
+ path33.join(process.env.HOME ?? "", ".npm-global", "bin", "brv")
39732
40261
  ].filter(Boolean);
39733
40262
  for (const candidate of candidates) {
39734
40263
  const found = await access3(candidate).then(() => true).catch(() => false);
@@ -39739,7 +40268,7 @@ async function resolveByteRoverCli() {
39739
40268
  return null;
39740
40269
  }
39741
40270
  async function readHolographicProviderConfig(profileName) {
39742
- const raw = await readFile19(resolveHermesConfigPath(profileName), "utf8").catch(
40271
+ const raw = await readFile20(resolveHermesConfigPath(profileName), "utf8").catch(
39743
40272
  (error) => {
39744
40273
  if (isNodeError22(error, "ENOENT")) {
39745
40274
  return "";
@@ -39753,7 +40282,7 @@ async function readHolographicProviderConfig(profileName) {
39753
40282
  }
39754
40283
  async function patchHolographicProviderConfig(profileName, patch) {
39755
40284
  const configPath = resolveHermesConfigPath(profileName);
39756
- const existingRaw = await readFile19(configPath, "utf8").catch(
40285
+ const existingRaw = await readFile20(configPath, "utf8").catch(
39757
40286
  (error) => {
39758
40287
  if (isNodeError22(error, "ENOENT")) {
39759
40288
  return null;
@@ -39789,8 +40318,8 @@ async function patchHermesMemoryEnv(profileName, patch) {
39789
40318
  if (entries.length === 0) {
39790
40319
  return;
39791
40320
  }
39792
- const envPath = path32.join(resolveHermesProfileDir(profileName), ".env");
39793
- const existingRaw = await readFile19(envPath, "utf8").catch((error) => {
40321
+ const envPath = path33.join(resolveHermesProfileDir(profileName), ".env");
40322
+ const existingRaw = await readFile20(envPath, "utf8").catch((error) => {
39794
40323
  if (isNodeError22(error, "ENOENT")) {
39795
40324
  return "";
39796
40325
  }
@@ -39849,7 +40378,7 @@ function isMemoryEnvKeyWritable(key) {
39849
40378
  ].includes(key);
39850
40379
  }
39851
40380
  function normalizeHindsightMode(value) {
39852
- const mode = readString24(value) ?? "cloud";
40381
+ const mode = readString25(value) ?? "cloud";
39853
40382
  return mode === "local" ? "local_embedded" : mode;
39854
40383
  }
39855
40384
  function normalizeHttpUrl2(value) {
@@ -39918,31 +40447,31 @@ function parseJsonObject2(text) {
39918
40447
  }
39919
40448
  }
39920
40449
  function readHindsightError(json) {
39921
- const detail = readString24(json.detail) ?? readString24(json.error);
40450
+ const detail = readString25(json.detail) ?? readString25(json.error);
39922
40451
  return detail ? `\uFF1A${detail}` : "";
39923
40452
  }
39924
40453
  function hindsightSemanticIssue(pathName, json) {
39925
40454
  if (pathName === "/health") {
39926
- const status = readString24(json.status);
40455
+ const status = readString25(json.status);
39927
40456
  return status && ["healthy", "ok"].includes(status.toLowerCase()) ? null : `\u5065\u5EB7\u72B6\u6001\u5F02\u5E38\uFF1A${status ?? "unknown"}`;
39928
40457
  }
39929
40458
  return null;
39930
40459
  }
39931
40460
  function summarizeHindsightProbe(pathName, json) {
39932
40461
  if (pathName === "/health") {
39933
- const status = readString24(json.status) ?? "ok";
39934
- const database = readString24(json.database);
40462
+ const status = readString25(json.status) ?? "ok";
40463
+ const database = readString25(json.database);
39935
40464
  return database ? `${status}, database ${database}` : status;
39936
40465
  }
39937
40466
  if (pathName === "/version") {
39938
- const version = readString24(json.api_version);
40467
+ const version = readString25(json.api_version);
39939
40468
  return version ? `API ${version}` : "version endpoint reachable";
39940
40469
  }
39941
- const bankId = readString24(json.bank_id);
40470
+ const bankId = readString25(json.bank_id);
39942
40471
  return bankId ? `bank ${bankId} reachable` : "bank config reachable";
39943
40472
  }
39944
40473
  async function readActiveMemoryProvider(profileName) {
39945
- const raw = await readFile19(
40474
+ const raw = await readFile20(
39946
40475
  resolveHermesConfigPath(profileName),
39947
40476
  "utf8"
39948
40477
  ).catch((error) => {
@@ -39953,14 +40482,14 @@ async function readActiveMemoryProvider(profileName) {
39953
40482
  });
39954
40483
  const config = raw ? toRecord22(YAML6.parse(raw)) : {};
39955
40484
  const memory = toRecord22(config.memory);
39956
- const provider = readString24(memory.provider);
40485
+ const provider = readString25(memory.provider);
39957
40486
  if (!provider || provider === "built-in" || provider === "builtin" || provider === "built_in") {
39958
40487
  return null;
39959
40488
  }
39960
40489
  return provider;
39961
40490
  }
39962
40491
  async function patchJsonProviderConfig(profileName, relativePath, patch) {
39963
- const configPath = path32.join(
40492
+ const configPath = path33.join(
39964
40493
  resolveHermesProfileDir(profileName),
39965
40494
  relativePath
39966
40495
  );
@@ -39978,7 +40507,7 @@ async function patchJsonProviderConfig(profileName, relativePath, patch) {
39978
40507
  );
39979
40508
  }
39980
40509
  async function readJsonObject(filePath) {
39981
- const raw = await readFile19(filePath, "utf8").catch((error) => {
40510
+ const raw = await readFile20(filePath, "utf8").catch((error) => {
39982
40511
  if (isNodeError22(error, "ENOENT")) {
39983
40512
  return "{}";
39984
40513
  }
@@ -39989,7 +40518,7 @@ async function readJsonObject(filePath) {
39989
40518
  } catch {
39990
40519
  throw new HermesMemoryError(
39991
40520
  "memory_provider_config_invalid",
39992
- `${path32.basename(filePath)} \u4E0D\u662F\u6709\u6548\u7684 JSON \u914D\u7F6E\u6587\u4EF6\u3002`
40521
+ `${path33.basename(filePath)} \u4E0D\u662F\u6709\u6548\u7684 JSON \u914D\u7F6E\u6587\u4EF6\u3002`
39993
40522
  );
39994
40523
  }
39995
40524
  }
@@ -40010,7 +40539,7 @@ function stringSetting(key, label, value, editable = true) {
40010
40539
  return {
40011
40540
  key,
40012
40541
  label,
40013
- value: readString24(value) ?? "",
40542
+ value: readString25(value) ?? "",
40014
40543
  editable,
40015
40544
  kind: "string"
40016
40545
  };
@@ -40022,7 +40551,7 @@ function secretSetting(key, label, value, configured) {
40022
40551
  value: "",
40023
40552
  editable: true,
40024
40553
  kind: "secret",
40025
- configured: configured || isConfiguredEnvValue(readString24(value))
40554
+ configured: configured || isConfiguredEnvValue(readString25(value))
40026
40555
  };
40027
40556
  }
40028
40557
  function textSetting(key, label, value, editable = true) {
@@ -40035,11 +40564,11 @@ function textSetting(key, label, value, editable = true) {
40035
40564
  };
40036
40565
  }
40037
40566
  function selectSetting(key, label, value, options, editable = true) {
40038
- const stringValue = readString24(value) ?? options[0] ?? null;
40567
+ const stringValue = readString25(value) ?? options[0] ?? null;
40039
40568
  return { key, label, value: stringValue, editable, kind: "select", options };
40040
40569
  }
40041
40570
  async function readMemoryLimits(profileName) {
40042
- const raw = await readFile19(
40571
+ const raw = await readFile20(
40043
40572
  resolveHermesConfigPath(profileName),
40044
40573
  "utf8"
40045
40574
  ).catch((error) => {
@@ -40108,7 +40637,7 @@ function hashString(value) {
40108
40637
  function toRecord22(value) {
40109
40638
  return typeof value === "object" && value !== null && !Array.isArray(value) ? value : {};
40110
40639
  }
40111
- function readString24(value) {
40640
+ function readString25(value) {
40112
40641
  return typeof value === "string" && value.trim() ? value.trim() : null;
40113
40642
  }
40114
40643
  function readPositiveInteger4(value) {
@@ -40267,7 +40796,7 @@ function registerProfileMemoryRoutes(router, options) {
40267
40796
  );
40268
40797
  }
40269
40798
  function readMemoryTarget(body) {
40270
- const raw = readString22(body, "target");
40799
+ const raw = readString23(body, "target");
40271
40800
  if (raw === "memory" || raw === "user") {
40272
40801
  return raw;
40273
40802
  }
@@ -40278,7 +40807,7 @@ function readMemoryTarget(body) {
40278
40807
  );
40279
40808
  }
40280
40809
  function readMemoryResetTarget(body) {
40281
- const raw = readString22(body, "target") ?? "all";
40810
+ const raw = readString23(body, "target") ?? "all";
40282
40811
  if (raw === "all" || raw === "memory" || raw === "user") {
40283
40812
  return raw;
40284
40813
  }
@@ -40289,7 +40818,7 @@ function readMemoryResetTarget(body) {
40289
40818
  );
40290
40819
  }
40291
40820
  function readRequiredMemoryContent(body) {
40292
- const content = readString22(body, "content") ?? readString22(body, "text");
40821
+ const content = readString23(body, "content") ?? readString23(body, "text");
40293
40822
  if (!content) {
40294
40823
  throw new LinkHttpError(
40295
40824
  400,
@@ -40300,7 +40829,7 @@ function readRequiredMemoryContent(body) {
40300
40829
  return content;
40301
40830
  }
40302
40831
  function readRequiredMemoryMatch(body) {
40303
- const oldText = readString22(body, "old_text") ?? readString22(body, "oldText") ?? readString22(body, "match");
40832
+ const oldText = readString23(body, "old_text") ?? readString23(body, "oldText") ?? readString23(body, "match");
40304
40833
  if (!oldText) {
40305
40834
  throw new LinkHttpError(
40306
40835
  400,
@@ -40311,7 +40840,7 @@ function readRequiredMemoryMatch(body) {
40311
40840
  return oldText;
40312
40841
  }
40313
40842
  function readRequiredMemoryProvider(body) {
40314
- const provider = readString22(body, "provider") ?? readString22(body, "provider_id") ?? readString22(body, "providerId");
40843
+ const provider = readString23(body, "provider") ?? readString23(body, "provider_id") ?? readString23(body, "providerId");
40315
40844
  if (!provider) {
40316
40845
  throw new LinkHttpError(
40317
40846
  400,
@@ -40341,7 +40870,7 @@ function readMemorySettingsPatch(body, options = {}) {
40341
40870
  input.userCharLimit = userCharLimit;
40342
40871
  }
40343
40872
  }
40344
- const mode = readString22(body, "mode");
40873
+ const mode = readString23(body, "mode");
40345
40874
  if (mode) {
40346
40875
  input.mode = mode;
40347
40876
  }
@@ -40357,7 +40886,7 @@ function readMemorySettingsPatch(body, options = {}) {
40357
40886
  if (bankId !== void 0) {
40358
40887
  input.bankId = bankId;
40359
40888
  }
40360
- const llmProvider = readString22(body, "llm_provider") ?? readString22(body, "llmProvider");
40889
+ const llmProvider = readString23(body, "llm_provider") ?? readString23(body, "llmProvider");
40361
40890
  if (llmProvider) {
40362
40891
  input.llmProvider = llmProvider;
40363
40892
  }
@@ -40393,11 +40922,11 @@ function readMemorySettingsPatch(body, options = {}) {
40393
40922
  if (autoRetain !== void 0) {
40394
40923
  input.autoRetain = autoRetain;
40395
40924
  }
40396
- const memoryMode = readString22(body, "memory_mode") ?? readString22(body, "memoryMode");
40925
+ const memoryMode = readString23(body, "memory_mode") ?? readString23(body, "memoryMode");
40397
40926
  if (memoryMode) {
40398
40927
  input.memoryMode = memoryMode;
40399
40928
  }
40400
- const recallBudget = readString22(body, "recall_budget") ?? readString22(body, "recallBudget");
40929
+ const recallBudget = readString23(body, "recall_budget") ?? readString23(body, "recallBudget");
40401
40930
  if (recallBudget) {
40402
40931
  input.recallBudget = recallBudget;
40403
40932
  }
@@ -40413,11 +40942,11 @@ function readMemorySettingsPatch(body, options = {}) {
40413
40942
  if (profileFrequency !== void 0) {
40414
40943
  input.profileFrequency = profileFrequency;
40415
40944
  }
40416
- const captureMode = readString22(body, "capture_mode") ?? readString22(body, "captureMode");
40945
+ const captureMode = readString23(body, "capture_mode") ?? readString23(body, "captureMode");
40417
40946
  if (captureMode) {
40418
40947
  input.captureMode = captureMode;
40419
40948
  }
40420
- const searchMode = readString22(body, "search_mode") ?? readString22(body, "searchMode");
40949
+ const searchMode = readString23(body, "search_mode") ?? readString23(body, "searchMode");
40421
40950
  if (searchMode) {
40422
40951
  input.searchMode = searchMode;
40423
40952
  }
@@ -40451,11 +40980,11 @@ function readMemorySettingsPatch(body, options = {}) {
40451
40980
  if (aiPeer !== void 0) {
40452
40981
  input.aiPeer = aiPeer;
40453
40982
  }
40454
- const recallMode = readString22(body, "recall_mode") ?? readString22(body, "recallMode");
40983
+ const recallMode = readString23(body, "recall_mode") ?? readString23(body, "recallMode");
40455
40984
  if (recallMode) {
40456
40985
  input.recallMode = recallMode;
40457
40986
  }
40458
- const writeFrequency = readString22(body, "write_frequency") ?? readString22(body, "writeFrequency");
40987
+ const writeFrequency = readString23(body, "write_frequency") ?? readString23(body, "writeFrequency");
40459
40988
  if (writeFrequency) {
40460
40989
  input.writeFrequency = writeFrequency;
40461
40990
  }
@@ -40463,7 +40992,7 @@ function readMemorySettingsPatch(body, options = {}) {
40463
40992
  if (saveMessages !== void 0) {
40464
40993
  input.saveMessages = saveMessages;
40465
40994
  }
40466
- const sessionStrategy = readString22(body, "session_strategy") ?? readString22(body, "sessionStrategy");
40995
+ const sessionStrategy = readString23(body, "session_strategy") ?? readString23(body, "sessionStrategy");
40467
40996
  if (sessionStrategy) {
40468
40997
  input.sessionStrategy = sessionStrategy;
40469
40998
  }
@@ -40612,8 +41141,8 @@ function toMemoryHttpError(error) {
40612
41141
  }
40613
41142
 
40614
41143
  // src/hermes/skills.ts
40615
- import { readFile as readFile20, readdir as readdir11 } from "fs/promises";
40616
- import path33 from "path";
41144
+ import { readFile as readFile21, readdir as readdir11 } from "fs/promises";
41145
+ import path34 from "path";
40617
41146
  import YAML7 from "yaml";
40618
41147
  var HermesSkillNotFoundError = class extends Error {
40619
41148
  constructor(skillName) {
@@ -40627,7 +41156,7 @@ var EXCLUDED_SKILL_DIRS = /* @__PURE__ */ new Set([".git", ".github", ".hub"]);
40627
41156
  async function listHermesProfileSkills(profileName, paths = resolveRuntimePaths()) {
40628
41157
  const profile = await readExistingProfile(profileName, paths);
40629
41158
  const profileDir = resolveHermesProfileDir(profile.name);
40630
- const skillsRoot = path33.join(profileDir, "skills");
41159
+ const skillsRoot = path34.join(profileDir, "skills");
40631
41160
  const [skillFiles, disabled, provenance] = await Promise.all([
40632
41161
  findSkillFiles(skillsRoot),
40633
41162
  readDisabledSkillNames(resolveHermesConfigPath(profile.name)),
@@ -40718,7 +41247,7 @@ async function collectSkillFiles(directory, results) {
40718
41247
  if (EXCLUDED_SKILL_DIRS.has(entry.name)) {
40719
41248
  continue;
40720
41249
  }
40721
- const entryPath = path33.join(directory, entry.name);
41250
+ const entryPath = path34.join(directory, entry.name);
40722
41251
  if (entry.isDirectory()) {
40723
41252
  await collectSkillFiles(entryPath, results);
40724
41253
  continue;
@@ -40729,7 +41258,7 @@ async function collectSkillFiles(directory, results) {
40729
41258
  }
40730
41259
  }
40731
41260
  async function readSkillMetadata(input) {
40732
- const raw = await readFile20(input.skillFile, "utf8").catch(
41261
+ const raw = await readFile21(input.skillFile, "utf8").catch(
40733
41262
  (error) => {
40734
41263
  if (isNodeError23(error, "ENOENT") || isNodeError23(error, "EACCES")) {
40735
41264
  return null;
@@ -40740,16 +41269,16 @@ async function readSkillMetadata(input) {
40740
41269
  if (raw === null) {
40741
41270
  return null;
40742
41271
  }
40743
- const skillDir = path33.dirname(input.skillFile);
41272
+ const skillDir = path34.dirname(input.skillFile);
40744
41273
  const { frontmatter, body } = parseSkillDocument(raw.slice(0, 4e3));
40745
41274
  const name = normalizeSkillName(
40746
- readString25(frontmatter.name) ?? path33.basename(skillDir)
41275
+ readString26(frontmatter.name) ?? path34.basename(skillDir)
40747
41276
  );
40748
41277
  if (!name) {
40749
41278
  return null;
40750
41279
  }
40751
41280
  const description = normalizeDescription(
40752
- readString25(frontmatter.description) ?? firstBodyDescription(body)
41281
+ readString26(frontmatter.description) ?? firstBodyDescription(body)
40753
41282
  );
40754
41283
  const provenance = input.provenance.get(name) ?? {
40755
41284
  source: "local",
@@ -40762,7 +41291,7 @@ async function readSkillMetadata(input) {
40762
41291
  enabled: !input.disabled.has(name),
40763
41292
  source: provenance.source,
40764
41293
  trust: provenance.trust,
40765
- relativePath: path33.relative(input.skillsRoot, skillDir)
41294
+ relativePath: path34.relative(input.skillsRoot, skillDir)
40766
41295
  };
40767
41296
  }
40768
41297
  function parseSkillDocument(raw) {
@@ -40783,8 +41312,8 @@ function parseSkillDocument(raw) {
40783
41312
  }
40784
41313
  }
40785
41314
  function categoryFromPath(skillsRoot, skillFile) {
40786
- const relative = path33.relative(skillsRoot, skillFile);
40787
- const parts = relative.split(path33.sep).filter(Boolean);
41315
+ const relative = path34.relative(skillsRoot, skillFile);
41316
+ const parts = relative.split(path34.sep).filter(Boolean);
40788
41317
  return parts.length >= 3 ? parts[0] : null;
40789
41318
  }
40790
41319
  function firstBodyDescription(body) {
@@ -40807,7 +41336,7 @@ function normalizeDescription(value) {
40807
41336
  return `${description.slice(0, MAX_DESCRIPTION_LENGTH - 3)}...`;
40808
41337
  }
40809
41338
  async function readDisabledSkillNames(configPath) {
40810
- const raw = await readFile20(configPath, "utf8").catch((error) => {
41339
+ const raw = await readFile21(configPath, "utf8").catch((error) => {
40811
41340
  if (isNodeError23(error, "ENOENT")) {
40812
41341
  return "";
40813
41342
  }
@@ -40831,7 +41360,7 @@ async function readSkillProvenance(root) {
40831
41360
  return provenance;
40832
41361
  }
40833
41362
  async function readBundledSkillNames(root) {
40834
- const raw = await readFile20(path33.join(root, ".bundled_manifest"), "utf8").catch(
41363
+ const raw = await readFile21(path34.join(root, ".bundled_manifest"), "utf8").catch(
40835
41364
  (error) => {
40836
41365
  if (isNodeError23(error, "ENOENT")) {
40837
41366
  return "";
@@ -40854,7 +41383,7 @@ async function readBundledSkillNames(root) {
40854
41383
  return names;
40855
41384
  }
40856
41385
  async function readHubInstalledSkills(root) {
40857
- const raw = await readFile20(path33.join(root, ".hub", "lock.json"), "utf8").catch(
41386
+ const raw = await readFile21(path34.join(root, ".hub", "lock.json"), "utf8").catch(
40858
41387
  (error) => {
40859
41388
  if (isNodeError23(error, "ENOENT")) {
40860
41389
  return "";
@@ -40876,8 +41405,8 @@ async function readHubInstalledSkills(root) {
40876
41405
  for (const [name, rawEntry] of Object.entries(installed2)) {
40877
41406
  const entry = toRecord23(rawEntry);
40878
41407
  result.set(normalizeSkillName(name), {
40879
- source: readString25(entry.source) ?? "hub",
40880
- trust: readString25(entry.trust_level) ?? null
41408
+ source: readString26(entry.source) ?? "hub",
41409
+ trust: readString26(entry.trust_level) ?? null
40881
41410
  });
40882
41411
  }
40883
41412
  return result;
@@ -40926,7 +41455,7 @@ function compareCategoryNames(left, right) {
40926
41455
  return left.localeCompare(right);
40927
41456
  }
40928
41457
  async function readHermesConfigDocument4(configPath) {
40929
- const existingRaw = await readFile20(configPath, "utf8").catch(
41458
+ const existingRaw = await readFile21(configPath, "utf8").catch(
40930
41459
  (error) => {
40931
41460
  if (isNodeError23(error, "ENOENT")) {
40932
41461
  return null;
@@ -40961,7 +41490,7 @@ function readStringList6(value) {
40961
41490
  }
40962
41491
  return value.filter((item) => typeof item === "string").map((item) => item.trim()).filter(Boolean);
40963
41492
  }
40964
- function readString25(value) {
41493
+ function readString26(value) {
40965
41494
  return typeof value === "string" && value.trim() ? value.trim() : null;
40966
41495
  }
40967
41496
  function toRecord23(value) {
@@ -41333,7 +41862,7 @@ function registerRunRoutes(router, options) {
41333
41862
  await authenticateRequest(ctx, paths);
41334
41863
  const language = readPreferredLanguage(ctx);
41335
41864
  const body = await readJsonBody(ctx.req);
41336
- const input = readString22(body, "input");
41865
+ const input = readString23(body, "input");
41337
41866
  if (!input) {
41338
41867
  throw new LinkHttpError(400, "run_input_required", "input is required");
41339
41868
  }
@@ -41341,12 +41870,12 @@ function registerRunRoutes(router, options) {
41341
41870
  ctx.body = await createHermesRun(
41342
41871
  {
41343
41872
  input,
41344
- instructions: readString22(body, "instructions") ?? void 0,
41873
+ instructions: readString23(body, "instructions") ?? void 0,
41345
41874
  conversation_history: readConversationHistory(
41346
41875
  body.conversation_history ?? body.conversationHistory
41347
41876
  ),
41348
- session_id: readString22(body, "session_id") ?? readString22(body, "sessionId") ?? void 0,
41349
- session_key: readString22(body, "session_key") ?? readString22(body, "sessionKey") ?? void 0
41877
+ session_id: readString23(body, "session_id") ?? readString23(body, "sessionId") ?? void 0,
41878
+ session_key: readString23(body, "session_key") ?? readString23(body, "sessionKey") ?? void 0
41350
41879
  },
41351
41880
  { logger, profileName: readOptionalProfileName(body), language }
41352
41881
  );
@@ -41521,8 +42050,8 @@ function readModelList(payload) {
41521
42050
  // src/hermes/updates.ts
41522
42051
  import { EventEmitter as EventEmitter3 } from "events";
41523
42052
  import { spawn as spawn4 } from "child_process";
41524
- import { mkdir as mkdir14, readFile as readFile21, rm as rm8 } from "fs/promises";
41525
- import path34 from "path";
42053
+ import { mkdir as mkdir14, readFile as readFile22, rm as rm8 } from "fs/promises";
42054
+ import path35 from "path";
41526
42055
  var SERVER_HERMES_RELEASES_LATEST_PATH = "/api/v1/hermes-agent/releases/latest";
41527
42056
  var RELEASE_CACHE_TTL_MS = 6 * 60 * 60 * 1e3;
41528
42057
  var RELEASE_FETCH_TIMEOUT_MS = 5e3;
@@ -41759,20 +42288,20 @@ function normalizeServerReleaseSnapshot(payload) {
41759
42288
  const remote = toNullableRecord(snapshot.remote);
41760
42289
  return {
41761
42290
  remote: remote ? normalizeServerRelease(remote) : null,
41762
- cacheState: readString26(snapshot, "cache_state") ?? readString26(snapshot, "cacheState"),
41763
- issue: readString26(snapshot, "issue")
42291
+ cacheState: readString27(snapshot, "cache_state") ?? readString27(snapshot, "cacheState"),
42292
+ issue: readString27(snapshot, "issue")
41764
42293
  };
41765
42294
  }
41766
42295
  function normalizeServerRelease(payload) {
41767
- const tag = readString26(payload, "tag");
41768
- const name = readString26(payload, "name");
42296
+ const tag = readString27(payload, "tag");
42297
+ const name = readString27(payload, "name");
41769
42298
  return {
41770
- version: readString26(payload, "version") ?? extractSemver(name) ?? extractTagSemver(tag),
42299
+ version: readString27(payload, "version") ?? extractSemver(name) ?? extractTagSemver(tag),
41771
42300
  tag,
41772
42301
  name,
41773
- releaseUrl: readString26(payload, "releaseUrl") ?? readString26(payload, "release_url"),
41774
- publishedAt: readString26(payload, "publishedAt") ?? readString26(payload, "published_at"),
41775
- fetchedAt: readString26(payload, "fetchedAt") ?? readString26(payload, "fetched_at") ?? (/* @__PURE__ */ new Date()).toISOString()
42302
+ releaseUrl: readString27(payload, "releaseUrl") ?? readString27(payload, "release_url"),
42303
+ publishedAt: readString27(payload, "publishedAt") ?? readString27(payload, "published_at"),
42304
+ fetchedAt: readString27(payload, "fetchedAt") ?? readString27(payload, "fetched_at") ?? (/* @__PURE__ */ new Date()).toISOString()
41776
42305
  };
41777
42306
  }
41778
42307
  async function readReleaseCache(paths) {
@@ -41791,7 +42320,7 @@ async function writeUpdateState(paths, state) {
41791
42320
  await writeJsonFile(updateStatePath(paths), state);
41792
42321
  }
41793
42322
  async function readUpdateLogLines(paths) {
41794
- const raw = await readFile21(updateLogPath(paths), "utf8").catch(() => "");
42323
+ const raw = await readFile22(updateLogPath(paths), "utf8").catch(() => "");
41795
42324
  if (!raw.trim()) {
41796
42325
  return [];
41797
42326
  }
@@ -41800,13 +42329,13 @@ async function readUpdateLogLines(paths) {
41800
42329
  );
41801
42330
  }
41802
42331
  function releaseCachePath(paths) {
41803
- return path34.join(paths.indexesDir, "hermes-release-check.json");
42332
+ return path35.join(paths.indexesDir, "hermes-release-check.json");
41804
42333
  }
41805
42334
  function updateStatePath(paths) {
41806
- return path34.join(paths.runDir, "hermes-update-state.json");
42335
+ return path35.join(paths.runDir, "hermes-update-state.json");
41807
42336
  }
41808
42337
  function updateLogPath(paths) {
41809
- return path34.join(paths.logsDir, UPDATE_LOG_FILE);
42338
+ return path35.join(paths.logsDir, UPDATE_LOG_FILE);
41810
42339
  }
41811
42340
  async function clearUpdateLogFiles(paths) {
41812
42341
  const primary = updateLogPath(paths);
@@ -41898,7 +42427,7 @@ function isRecentRunningState2(state) {
41898
42427
  const startedAt = Date.parse(state.started_at);
41899
42428
  return Number.isFinite(startedAt) && Date.now() - startedAt < 3e4;
41900
42429
  }
41901
- function readString26(payload, key) {
42430
+ function readString27(payload, key) {
41902
42431
  const value = payload[key];
41903
42432
  return typeof value === "string" && value.trim() ? value.trim() : null;
41904
42433
  }
@@ -41906,13 +42435,13 @@ function readString26(payload, key) {
41906
42435
  // src/link/updates.ts
41907
42436
  import { spawn as spawn6 } from "child_process";
41908
42437
  import { EventEmitter as EventEmitter4 } from "events";
41909
- import { mkdir as mkdir17, readFile as readFile23, rm as rm11 } from "fs/promises";
41910
- import path36 from "path";
42438
+ import { mkdir as mkdir17, readFile as readFile24, rm as rm11 } from "fs/promises";
42439
+ import path37 from "path";
41911
42440
 
41912
42441
  // src/daemon/process.ts
41913
42442
  import { spawn as spawn5 } from "child_process";
41914
- import { mkdir as mkdir16, readFile as readFile22, rm as rm10, writeFile as writeFile4 } from "fs/promises";
41915
- import path35 from "path";
42443
+ import { mkdir as mkdir16, readFile as readFile23, rm as rm10, writeFile as writeFile4 } from "fs/promises";
42444
+ import path36 from "path";
41916
42445
 
41917
42446
  // src/daemon/service.ts
41918
42447
  import { createServer } from "http";
@@ -43940,7 +44469,7 @@ async function runDaemonSupervisor(paths = resolveRuntimePaths()) {
43940
44469
  await mkdir16(paths.logsDir, { recursive: true, mode: 448 });
43941
44470
  const log = createRotatingTextLogWriter({
43942
44471
  paths,
43943
- fileName: path35.basename(daemonLogFile(paths))
44472
+ fileName: path36.basename(daemonLogFile(paths))
43944
44473
  });
43945
44474
  const scriptPath = currentCliScriptPath();
43946
44475
  const write = (chunk) => {
@@ -44120,7 +44649,7 @@ function currentCliScriptPath() {
44120
44649
  return process.argv[1];
44121
44650
  }
44122
44651
  async function readPid(filePath) {
44123
- const raw = await readFile22(filePath, "utf8").catch(() => null);
44652
+ const raw = await readFile23(filePath, "utf8").catch(() => null);
44124
44653
  if (!raw) {
44125
44654
  return null;
44126
44655
  }
@@ -44239,7 +44768,7 @@ function terminateChild(child, previousForceKillTimer) {
44239
44768
  }
44240
44769
  }
44241
44770
  function supervisorStopIntentPath(paths) {
44242
- return path35.join(paths.runDir, "supervisor-stop-intent.json");
44771
+ return path36.join(paths.runDir, "supervisor-stop-intent.json");
44243
44772
  }
44244
44773
  async function writeSupervisorStopIntent(paths, pid) {
44245
44774
  await mkdir16(paths.runDir, { recursive: true, mode: 448 });
@@ -44252,7 +44781,7 @@ async function writeSupervisorStopIntent(paths, pid) {
44252
44781
  }
44253
44782
  async function consumeSupervisorStopIntent(paths, pid) {
44254
44783
  const filePath = supervisorStopIntentPath(paths);
44255
- const raw = await readFile22(filePath, "utf8").catch(() => null);
44784
+ const raw = await readFile23(filePath, "utf8").catch(() => null);
44256
44785
  if (!raw) {
44257
44786
  return false;
44258
44787
  }
@@ -44270,7 +44799,7 @@ async function consumeSupervisorStopIntent(paths, pid) {
44270
44799
  }
44271
44800
  async function clearExpiredSupervisorStopIntent(paths) {
44272
44801
  const filePath = supervisorStopIntentPath(paths);
44273
- const raw = await readFile22(filePath, "utf8").catch(() => null);
44802
+ const raw = await readFile23(filePath, "utf8").catch(() => null);
44274
44803
  if (!raw) {
44275
44804
  return;
44276
44805
  }
@@ -44719,16 +45248,16 @@ function normalizeServerSnapshot(payload) {
44719
45248
  if (!policy) {
44720
45249
  return {
44721
45250
  remote: null,
44722
- issue: readString27(snapshot, "issue")
45251
+ issue: readString28(snapshot, "issue")
44723
45252
  };
44724
45253
  }
44725
45254
  const release = toNullableRecord2(snapshot.release);
44726
- const currentVersion = readString27(policy, "current_version") ?? readString27(policy, "currentVersion");
44727
- const minSafeVersion = readString27(policy, "min_safe_version") ?? readString27(policy, "minSafeVersion");
45255
+ const currentVersion = readString28(policy, "current_version") ?? readString28(policy, "currentVersion");
45256
+ const minSafeVersion = readString28(policy, "min_safe_version") ?? readString28(policy, "minSafeVersion");
44728
45257
  if (!currentVersion) {
44729
45258
  return {
44730
45259
  remote: null,
44731
- issue: readString27(snapshot, "issue")
45260
+ issue: readString28(snapshot, "issue")
44732
45261
  };
44733
45262
  }
44734
45263
  return {
@@ -44736,10 +45265,10 @@ function normalizeServerSnapshot(payload) {
44736
45265
  current_version: currentVersion,
44737
45266
  min_safe_version: minSafeVersion,
44738
45267
  target_version: currentVersion,
44739
- release_url: release ? readString27(release, "release_url") ?? readString27(release, "releaseUrl") : null,
44740
- published_at: release ? readString27(release, "published_at") ?? readString27(release, "publishedAt") : null
45268
+ release_url: release ? readString28(release, "release_url") ?? readString28(release, "releaseUrl") : null,
45269
+ published_at: release ? readString28(release, "published_at") ?? readString28(release, "publishedAt") : null
44741
45270
  },
44742
- issue: readString27(snapshot, "issue")
45271
+ issue: readString28(snapshot, "issue")
44743
45272
  };
44744
45273
  }
44745
45274
  async function fetchCurrentLinkReleaseFromServer(options, fetcher, channel) {
@@ -44802,7 +45331,7 @@ async function buildOfficialInstallCommand(options, targetVersion) {
44802
45331
  };
44803
45332
  }
44804
45333
  function buildUnixInstallCommand(installerUrl) {
44805
- const nodeBinDir = path36.dirname(process.execPath);
45334
+ const nodeBinDir = path37.dirname(process.execPath);
44806
45335
  const fetchScript = [
44807
45336
  quoteShellToken(process.execPath),
44808
45337
  "--input-type=module",
@@ -45063,7 +45592,7 @@ async function writeUpdateState2(paths, state) {
45063
45592
  await writeJsonFile(updateStatePath2(paths), state);
45064
45593
  }
45065
45594
  async function readUpdateLogLines2(paths) {
45066
- const raw = await readFile23(updateLogPath2(paths), "utf8").catch(() => "");
45595
+ const raw = await readFile24(updateLogPath2(paths), "utf8").catch(() => "");
45067
45596
  if (!raw.trim()) {
45068
45597
  return [];
45069
45598
  }
@@ -45072,10 +45601,10 @@ async function readUpdateLogLines2(paths) {
45072
45601
  );
45073
45602
  }
45074
45603
  function updateStatePath2(paths) {
45075
- return path36.join(paths.runDir, "link-update-state.json");
45604
+ return path37.join(paths.runDir, "link-update-state.json");
45076
45605
  }
45077
45606
  function updateLogPath2(paths) {
45078
- return path36.join(paths.logsDir, UPDATE_LOG_FILE2);
45607
+ return path37.join(paths.logsDir, UPDATE_LOG_FILE2);
45079
45608
  }
45080
45609
  async function clearUpdateLogFiles2(paths) {
45081
45610
  const primary = updateLogPath2(paths);
@@ -45153,13 +45682,13 @@ function toRecord26(value) {
45153
45682
  function toNullableRecord2(value) {
45154
45683
  return typeof value === "object" && value !== null ? value : null;
45155
45684
  }
45156
- function readString27(payload, key) {
45685
+ function readString28(payload, key) {
45157
45686
  const value = payload[key];
45158
45687
  return typeof value === "string" && value.trim() ? value.trim() : null;
45159
45688
  }
45160
45689
 
45161
45690
  // src/pairing/pairing.ts
45162
- import path37 from "path";
45691
+ import path38 from "path";
45163
45692
  import { rm as rm12 } from "fs/promises";
45164
45693
 
45165
45694
  // src/relay/bootstrap.ts
@@ -45499,10 +46028,10 @@ async function loadRequiredIdentity2(paths) {
45499
46028
  }
45500
46029
  return identity;
45501
46030
  }
45502
- async function postServerJson(serverBaseUrl, path38, body, options) {
46031
+ async function postServerJson(serverBaseUrl, path39, body, options) {
45503
46032
  let response;
45504
46033
  try {
45505
- response = await fetch(`${serverBaseUrl.replace(/\/+$/u, "")}${path38}`, {
46034
+ response = await fetch(`${serverBaseUrl.replace(/\/+$/u, "")}${path39}`, {
45506
46035
  method: "POST",
45507
46036
  headers: {
45508
46037
  accept: "application/json",
@@ -45550,10 +46079,10 @@ function pairingErrorSnapshot(stage, error) {
45550
46079
  occurred_at: (/* @__PURE__ */ new Date()).toISOString()
45551
46080
  };
45552
46081
  }
45553
- async function patchServerJson(serverBaseUrl, path38, token, body, options) {
46082
+ async function patchServerJson(serverBaseUrl, path39, token, body, options) {
45554
46083
  let response;
45555
46084
  try {
45556
- response = await fetch(`${serverBaseUrl.replace(/\/+$/u, "")}${path38}`, {
46085
+ response = await fetch(`${serverBaseUrl.replace(/\/+$/u, "")}${path39}`, {
45557
46086
  method: "PATCH",
45558
46087
  headers: {
45559
46088
  accept: "application/json",
@@ -45601,10 +46130,10 @@ function createPairingNetworkError(input) {
45601
46130
  );
45602
46131
  }
45603
46132
  function pairingClaimPath(sessionId, paths) {
45604
- return path37.join(paths.pairingDir, `${Buffer.from(sessionId).toString("base64url")}.claimed.json`);
46133
+ return path38.join(paths.pairingDir, `${Buffer.from(sessionId).toString("base64url")}.claimed.json`);
45605
46134
  }
45606
46135
  function pairingSessionPath(sessionId, paths) {
45607
- return path37.join(paths.pairingDir, `${Buffer.from(sessionId).toString("base64url")}.json`);
46136
+ return path38.join(paths.pairingDir, `${Buffer.from(sessionId).toString("base64url")}.json`);
45608
46137
  }
45609
46138
  function qrPreferredUrls(routes) {
45610
46139
  return routes.preferredUrls.filter((url) => !url.includes("/api/v1/relay/links/")).slice(0, 1);
@@ -45707,8 +46236,8 @@ function registerSystemRoutes(router, options) {
45707
46236
  });
45708
46237
  router.post("/api/v1/pairing/claim", async (ctx) => {
45709
46238
  const body = await readJsonBody(ctx.req);
45710
- const sessionId = readString22(body, "session_id") ?? readString22(body, "sessionId");
45711
- const claimToken = readString22(body, "claim_token") ?? readString22(body, "claimToken");
46239
+ const sessionId = readString23(body, "session_id") ?? readString23(body, "sessionId");
46240
+ const claimToken = readString23(body, "claim_token") ?? readString23(body, "claimToken");
45712
46241
  if (!sessionId || !claimToken) {
45713
46242
  throw new LinkHttpError(
45714
46243
  400,
@@ -45719,10 +46248,10 @@ function registerSystemRoutes(router, options) {
45719
46248
  const claimed = await claimPairing({
45720
46249
  sessionId,
45721
46250
  claimToken,
45722
- deviceLabel: readString22(body, "device_label") ?? readString22(body, "deviceLabel") ?? "HermesPilot App",
45723
- devicePlatform: readString22(body, "device_platform") ?? readString22(body, "devicePlatform") ?? "unknown",
45724
- deviceModel: readString22(body, "device_model") ?? readString22(body, "deviceModel"),
45725
- appInstanceId: readString22(body, "app_instance_id") ?? readString22(body, "appInstanceId"),
46251
+ deviceLabel: readString23(body, "device_label") ?? readString23(body, "deviceLabel") ?? "HermesPilot App",
46252
+ devicePlatform: readString23(body, "device_platform") ?? readString23(body, "devicePlatform") ?? "unknown",
46253
+ deviceModel: readString23(body, "device_model") ?? readString23(body, "deviceModel"),
46254
+ appInstanceId: readString23(body, "app_instance_id") ?? readString23(body, "appInstanceId"),
45726
46255
  paths
45727
46256
  });
45728
46257
  ctx.body = claimed;
@@ -45802,9 +46331,9 @@ function registerSystemRoutes(router, options) {
45802
46331
  const body = await readJsonBody(ctx.req);
45803
46332
  const session = await createDeviceSession(
45804
46333
  {
45805
- label: readString22(body, "device_label") ?? readString22(body, "deviceLabel") ?? "HermesPilot App",
45806
- platform: readString22(body, "device_platform") ?? readString22(body, "devicePlatform") ?? "unknown",
45807
- model: readString22(body, "device_model") ?? readString22(body, "deviceModel"),
46334
+ label: readString23(body, "device_label") ?? readString23(body, "deviceLabel") ?? "HermesPilot App",
46335
+ platform: readString23(body, "device_platform") ?? readString23(body, "devicePlatform") ?? "unknown",
46336
+ model: readString23(body, "device_model") ?? readString23(body, "deviceModel"),
45808
46337
  appInstanceId: auth.appInstanceId
45809
46338
  },
45810
46339
  paths
@@ -45833,7 +46362,7 @@ function registerSystemRoutes(router, options) {
45833
46362
  });
45834
46363
  router.post("/api/v1/auth/refresh", async (ctx) => {
45835
46364
  const body = await readJsonBody(ctx.req);
45836
- const refreshToken = readString22(body, "refresh_token") ?? readString22(body, "refreshToken");
46365
+ const refreshToken = readString23(body, "refresh_token") ?? readString23(body, "refreshToken");
45837
46366
  if (!refreshToken) {
45838
46367
  throw new LinkHttpError(
45839
46368
  400,
@@ -45844,10 +46373,10 @@ function registerSystemRoutes(router, options) {
45844
46373
  const session = await refreshDeviceSession(
45845
46374
  refreshToken,
45846
46375
  {
45847
- appInstanceId: readString22(body, "app_instance_id") ?? readString22(body, "appInstanceId"),
45848
- label: readString22(body, "device_label") ?? readString22(body, "deviceLabel"),
45849
- platform: readString22(body, "device_platform") ?? readString22(body, "devicePlatform"),
45850
- model: readString22(body, "device_model") ?? readString22(body, "deviceModel")
46376
+ appInstanceId: readString23(body, "app_instance_id") ?? readString23(body, "appInstanceId"),
46377
+ label: readString23(body, "device_label") ?? readString23(body, "deviceLabel"),
46378
+ platform: readString23(body, "device_platform") ?? readString23(body, "devicePlatform"),
46379
+ model: readString23(body, "device_model") ?? readString23(body, "deviceModel")
45851
46380
  },
45852
46381
  paths
45853
46382
  );
@@ -45866,7 +46395,7 @@ function registerSystemRoutes(router, options) {
45866
46395
  });
45867
46396
  router.post("/api/v1/auth/logout", async (ctx) => {
45868
46397
  const body = await readJsonBody(ctx.req);
45869
- const refreshToken = readString22(body, "refresh_token") ?? readString22(body, "refreshToken");
46398
+ const refreshToken = readString23(body, "refresh_token") ?? readString23(body, "refreshToken");
45870
46399
  if (refreshToken) {
45871
46400
  await revokeDeviceRefreshToken(refreshToken, paths);
45872
46401
  }
@@ -46107,7 +46636,7 @@ function registerSystemRoutes(router, options) {
46107
46636
  router.patch("/api/v1/devices/:deviceId", async (ctx) => {
46108
46637
  const auth = await authenticateRequest(ctx, paths);
46109
46638
  const body = await readJsonBody(ctx.req);
46110
- const label = readString22(body, "label") ?? readString22(body, "device_label");
46639
+ const label = readString23(body, "label") ?? readString23(body, "device_label");
46111
46640
  if (!label) {
46112
46641
  throw new LinkHttpError(
46113
46642
  400,
@@ -46151,7 +46680,7 @@ function isActiveCronJob(job) {
46151
46680
  if (!enabled) {
46152
46681
  return false;
46153
46682
  }
46154
- const state = readString22(job, "state")?.toLowerCase();
46683
+ const state = readString23(job, "state")?.toLowerCase();
46155
46684
  return !["paused", "disabled", "completed", "deleted"].includes(state ?? "");
46156
46685
  }
46157
46686
  function filterLogsWithinHours(logs, hours, now = Date.now()) {
@@ -46195,8 +46724,8 @@ function registerWorkspaceRoutes(router, options) {
46195
46724
  ctx.body = {
46196
46725
  ok: true,
46197
46726
  workspace: await conversations.createWorkspace({
46198
- name: readString22(body, "name") ?? "",
46199
- icon: readString22(body, "icon") ?? void 0
46727
+ name: readString23(body, "name") ?? "",
46728
+ icon: readString23(body, "icon") ?? void 0
46200
46729
  })
46201
46730
  };
46202
46731
  });
@@ -46206,8 +46735,8 @@ function registerWorkspaceRoutes(router, options) {
46206
46735
  ctx.body = {
46207
46736
  ok: true,
46208
46737
  workspace: await conversations.renameWorkspace(ctx.params.workspaceId, {
46209
- name: readString22(body, "name") ?? "",
46210
- icon: readString22(body, "icon") ?? void 0
46738
+ name: readString23(body, "name") ?? "",
46739
+ icon: readString23(body, "icon") ?? void 0
46211
46740
  })
46212
46741
  };
46213
46742
  });
@@ -46290,8 +46819,8 @@ function registerLinkUpdateRoutes(router, options) {
46290
46819
  ctx.body = await startLinkUpdate({
46291
46820
  paths,
46292
46821
  logger,
46293
- channel: readString22(body, "channel"),
46294
- targetVersion: readString22(body, "target_version") ?? readString22(body, "targetVersion")
46822
+ channel: readString23(body, "channel"),
46823
+ targetVersion: readString23(body, "target_version") ?? readString23(body, "targetVersion")
46295
46824
  });
46296
46825
  });
46297
46826
  router.get("/api/v1/link/update/events", async (ctx) => {
@@ -46321,7 +46850,7 @@ import QRCode from "qrcode";
46321
46850
  function registerPairingRoutes(router, options) {
46322
46851
  const { paths } = options;
46323
46852
  router.get("/pair", async (ctx) => {
46324
- const sessionId = readString22(ctx.query, "session_id");
46853
+ const sessionId = readString23(ctx.query, "session_id");
46325
46854
  if (!sessionId) {
46326
46855
  throw new LinkHttpError(400, "pairing_session_required", "session_id is required");
46327
46856
  }
@@ -46346,7 +46875,7 @@ function registerPairingRoutes(router, options) {
46346
46875
  ctx.body = page;
46347
46876
  });
46348
46877
  router.get("/api/v1/pairing/session", async (ctx) => {
46349
- const sessionId = readString22(ctx.query, "session_id");
46878
+ const sessionId = readString23(ctx.query, "session_id");
46350
46879
  if (!sessionId) {
46351
46880
  throw new LinkHttpError(400, "pairing_session_required", "session_id is required");
46352
46881
  }
@@ -46816,7 +47345,7 @@ function registerInternalRoutes(router, options) {
46816
47345
  router.post("/internal/deliver", async (ctx) => {
46817
47346
  assertLoopbackRequest(ctx.req);
46818
47347
  const body = await readJsonBody(ctx.req);
46819
- const stagingDir = readString22(body, "staging_dir") ?? readString22(body, "stagingDir");
47348
+ const stagingDir = readString23(body, "staging_dir") ?? readString23(body, "stagingDir");
46820
47349
  if (!stagingDir) {
46821
47350
  throw new LinkHttpError(
46822
47351
  400,
@@ -46835,9 +47364,9 @@ function registerInternalRoutes(router, options) {
46835
47364
  ctx.body = {
46836
47365
  ok: true,
46837
47366
  ...await options.conversations.deliverFilesFromTool({
46838
- profile: readString22(body, "profile") ?? readString22(body, "profile_name") ?? readString22(body, "profileName") ?? void 0,
46839
- taskId: readString22(body, "task_id") ?? readString22(body, "taskId") ?? void 0,
46840
- sessionId: readString22(body, "session_id") ?? readString22(body, "sessionId") ?? void 0,
47367
+ profile: readString23(body, "profile") ?? readString23(body, "profile_name") ?? readString23(body, "profileName") ?? void 0,
47368
+ taskId: readString23(body, "task_id") ?? readString23(body, "taskId") ?? void 0,
47369
+ sessionId: readString23(body, "session_id") ?? readString23(body, "sessionId") ?? void 0,
46841
47370
  files: body.files ?? body.file ?? body.path
46842
47371
  })
46843
47372
  };
@@ -46898,9 +47427,9 @@ function registerLiveActivityRoutes(router, options) {
46898
47427
  const auth = await authenticateRequest(ctx, paths);
46899
47428
  const body = await readJsonBody(ctx.req);
46900
47429
  const targetKind = readTargetKind(body);
46901
- const runId = normalizePattern(readString22(body, "run_id") ?? readString22(body, "runId"), RUN_ID_PATTERN);
47430
+ const runId = normalizePattern(readString23(body, "run_id") ?? readString23(body, "runId"), RUN_ID_PATTERN);
46902
47431
  const operationId = normalizePattern(
46903
- readString22(body, "operation_id") ?? readString22(body, "operationId"),
47432
+ readString23(body, "operation_id") ?? readString23(body, "operationId"),
46904
47433
  OPERATION_ID_PATTERN
46905
47434
  );
46906
47435
  if (targetKind === "run" && !runId) {
@@ -46946,7 +47475,7 @@ function registerLiveActivityRoutes(router, options) {
46946
47475
  });
46947
47476
  }
46948
47477
  function readTargetKind(body) {
46949
- const value = readString22(body, "target_kind") ?? readString22(body, "targetKind");
47478
+ const value = readString23(body, "target_kind") ?? readString23(body, "targetKind");
46950
47479
  return readTargetKindValue(value);
46951
47480
  }
46952
47481
  function readTargetKindValue(value) {
@@ -46968,21 +47497,21 @@ function readQueryValue(query, key) {
46968
47497
  return readQueryString(query[key]) ?? null;
46969
47498
  }
46970
47499
  function readApnsEnvironment(body) {
46971
- const value = readString22(body, "apns_environment") ?? readString22(body, "apnsEnvironment");
47500
+ const value = readString23(body, "apns_environment") ?? readString23(body, "apnsEnvironment");
46972
47501
  if (value === "sandbox" || value === "production") {
46973
47502
  return value;
46974
47503
  }
46975
47504
  throw new LinkHttpError(400, "apns_environment_invalid", "apns_environment must be sandbox or production");
46976
47505
  }
46977
47506
  function readLanguage2(body) {
46978
- const value = readString22(body, "language") ?? readString22(body, "preferred_language") ?? readString22(body, "preferredLanguage");
47507
+ const value = readString23(body, "language") ?? readString23(body, "preferred_language") ?? readString23(body, "preferredLanguage");
46979
47508
  if (!value) {
46980
47509
  return null;
46981
47510
  }
46982
47511
  return value.toLowerCase().startsWith("zh") ? "zh" : "en";
46983
47512
  }
46984
47513
  function readPrivacyLevel(body) {
46985
- const value = readString22(body, "privacy_level") ?? readString22(body, "privacyLevel");
47514
+ const value = readString23(body, "privacy_level") ?? readString23(body, "privacyLevel");
46986
47515
  if (value === "minimal" || value === "detailed") {
46987
47516
  return value;
46988
47517
  }
@@ -46990,7 +47519,7 @@ function readPrivacyLevel(body) {
46990
47519
  }
46991
47520
  function readRequiredString(body, keys, code) {
46992
47521
  for (const key of keys) {
46993
- const value = readString22(body, key);
47522
+ const value = readString23(body, key);
46994
47523
  if (value) {
46995
47524
  return value;
46996
47525
  }
@@ -47006,7 +47535,7 @@ function readRequiredPattern(body, keys, pattern, code) {
47006
47535
  }
47007
47536
  function readOptionalString2(body, keys, maxLength) {
47008
47537
  for (const key of keys) {
47009
- const value = readString22(body, key);
47538
+ const value = readString23(body, key);
47010
47539
  if (value) {
47011
47540
  return value.slice(0, maxLength);
47012
47541
  }
@@ -47018,7 +47547,7 @@ function normalizePattern(value, pattern) {
47018
47547
  }
47019
47548
  function readIso(body, keys) {
47020
47549
  for (const key of keys) {
47021
- const value = readString22(body, key);
47550
+ const value = readString23(body, key);
47022
47551
  if (!value) {
47023
47552
  continue;
47024
47553
  }