@hermespilot/link 0.6.3 → 0.6.4

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.
@@ -4891,7 +4891,7 @@ import os2 from "os";
4891
4891
  import path5 from "path";
4892
4892
 
4893
4893
  // src/constants.ts
4894
- var LINK_VERSION = "0.6.3";
4894
+ var LINK_VERSION = "0.6.4";
4895
4895
  var LINK_COMMAND = "hermeslink";
4896
4896
  var LINK_DEFAULT_PORT = 52379;
4897
4897
  var LINK_RUNTIME_DIR_NAME = ".hermeslink";
@@ -14880,6 +14880,17 @@ async function buildRunTranscriptEvents(input) {
14880
14880
  }
14881
14881
  return events;
14882
14882
  }
14883
+ async function readRunFinalAssistantText(input) {
14884
+ const sessionId = input.hermesSessionId.trim();
14885
+ if (!sessionId) {
14886
+ return null;
14887
+ }
14888
+ const profileName = isValidProfileName3(input.profileName) ? input.profileName : "default";
14889
+ const rows = await readHermesTranscriptRows(profileName, sessionId);
14890
+ const lowerBoundSeconds = runStartedLowerBoundSeconds(input.runStartedAt);
14891
+ const assistantRows = rows.filter((row) => isRunRow(row, lowerBoundSeconds)).filter((row) => normalizeRole(row.role) === "assistant").map((row) => normalizeContent3(row.content).trim()).filter(Boolean);
14892
+ return assistantRows.at(-1) ?? null;
14893
+ }
14883
14894
  async function readHermesTranscriptRows(profileName, sessionId) {
14884
14895
  const profileDir = resolveHermesProfileDir(profileName);
14885
14896
  const dbPath = path19.join(profileDir, "state.db");
@@ -15786,6 +15797,9 @@ function toRecord12(value) {
15786
15797
  var RUN_STATUS_RECOVERY_TIMEOUT_MS = 10 * 60 * 1e3;
15787
15798
  var RUN_STATUS_RECOVERY_INITIAL_DELAY_MS = 500;
15788
15799
  var RUN_STATUS_RECOVERY_MAX_DELAY_MS = 2500;
15800
+ var RESPONSE_TRANSCRIPT_RECOVERY_TIMEOUT_MS = 3e4;
15801
+ var RESPONSE_TRANSCRIPT_RECOVERY_INITIAL_DELAY_MS = 750;
15802
+ var RESPONSE_TRANSCRIPT_RECOVERY_MAX_DELAY_MS = 2500;
15789
15803
  var ConversationRunLifecycle = class {
15790
15804
  constructor(deps) {
15791
15805
  this.deps = deps;
@@ -16163,10 +16177,31 @@ var ConversationRunLifecycle = class {
16163
16177
  await this.cancelRunAfterAbort(input.conversationId, input.runId);
16164
16178
  return;
16165
16179
  }
16166
- const hasAssistantOutput = await this.runHasAssistantOutput(
16180
+ let hasAssistantOutput = await this.runHasAssistantOutput(
16167
16181
  input.conversationId,
16168
16182
  input.runId
16169
16183
  );
16184
+ if (input.backend === "responses" && !hasAssistantOutput) {
16185
+ const recoveredEvent2 = await this.recoverResponseRunFromHermesTranscript({
16186
+ conversationId: input.conversationId,
16187
+ runId: input.runId,
16188
+ profileName: input.profileName,
16189
+ signal: input.controller.signal
16190
+ });
16191
+ if (recoveredEvent2) {
16192
+ await this.completeRun(input.conversationId, input.runId, recoveredEvent2);
16193
+ this.deps.scheduleTitleRefresh(input.conversationId);
16194
+ return;
16195
+ }
16196
+ if (input.controller.signal.aborted) {
16197
+ await this.cancelRunAfterAbort(input.conversationId, input.runId);
16198
+ return;
16199
+ }
16200
+ hasAssistantOutput = await this.runHasAssistantOutput(
16201
+ input.conversationId,
16202
+ input.runId
16203
+ );
16204
+ }
16170
16205
  if (input.backend === "responses" && !streamError && hasAssistantOutput) {
16171
16206
  await this.completeRun(input.conversationId, input.runId);
16172
16207
  } else {
@@ -16440,6 +16475,65 @@ var ConversationRunLifecycle = class {
16440
16475
  await this.persistHermesEvent(input.conversationId, input.runId, event);
16441
16476
  }
16442
16477
  }
16478
+ async recoverResponseRunFromHermesTranscript(input) {
16479
+ const deadline = Date.now() + RESPONSE_TRANSCRIPT_RECOVERY_TIMEOUT_MS;
16480
+ let delayMs = RESPONSE_TRANSCRIPT_RECOVERY_INITIAL_DELAY_MS;
16481
+ await this.deps.logger.warn("hermes_response_transcript_recovery_started", {
16482
+ conversation_id: input.conversationId,
16483
+ run_id: input.runId,
16484
+ timeout_ms: RESPONSE_TRANSCRIPT_RECOVERY_TIMEOUT_MS
16485
+ });
16486
+ while (!input.signal.aborted && Date.now() < deadline) {
16487
+ if (!await this.deps.isConversationRunnable(input.conversationId)) {
16488
+ return null;
16489
+ }
16490
+ const snapshot = await this.deps.readSnapshot(input.conversationId).catch(() => null);
16491
+ const run = snapshot?.runs.find((item) => item.id === input.runId);
16492
+ if (!run || run.status !== "running") {
16493
+ return null;
16494
+ }
16495
+ const recoveredText = await readRunFinalAssistantText({
16496
+ profileName: input.profileName,
16497
+ hermesSessionId: run.hermes_session_id,
16498
+ runStartedAt: run.started_at
16499
+ }).catch(async (error) => {
16500
+ await this.deps.logger.warn(
16501
+ "hermes_response_transcript_recovery_read_failed",
16502
+ {
16503
+ conversation_id: input.conversationId,
16504
+ run_id: input.runId,
16505
+ hermes_session_id: run.hermes_session_id,
16506
+ error: error instanceof Error ? error.message : String(error)
16507
+ }
16508
+ );
16509
+ return null;
16510
+ });
16511
+ if (recoveredText?.trim()) {
16512
+ const deltaEvent = transcriptRecoveryDeltaEvent(
16513
+ run.hermes_session_id,
16514
+ recoveredText
16515
+ );
16516
+ await this.persistHermesEvent(
16517
+ input.conversationId,
16518
+ input.runId,
16519
+ deltaEvent
16520
+ );
16521
+ await this.deps.logger.info("hermes_response_transcript_recovered", {
16522
+ conversation_id: input.conversationId,
16523
+ run_id: input.runId,
16524
+ hermes_session_id: run.hermes_session_id,
16525
+ content_length: recoveredText.length
16526
+ });
16527
+ return transcriptRecoveryCompletedEvent(run.hermes_session_id);
16528
+ }
16529
+ await sleep(Math.min(delayMs, deadline - Date.now()), input.signal);
16530
+ delayMs = Math.min(
16531
+ RESPONSE_TRANSCRIPT_RECOVERY_MAX_DELAY_MS,
16532
+ delayMs + 500
16533
+ );
16534
+ }
16535
+ return null;
16536
+ }
16443
16537
  async resolveRunInput(input) {
16444
16538
  const userMessage = input.snapshot.messages.find(
16445
16539
  (message) => message.id === input.run.trigger_message_id
@@ -17374,6 +17468,39 @@ function normalizeRunProfileForCompare(profileName) {
17374
17468
  return null;
17375
17469
  }
17376
17470
  }
17471
+ function transcriptRecoveryDeltaEvent(hermesSessionId, text) {
17472
+ return {
17473
+ eventName: "message.delta",
17474
+ payloadType: "message.delta",
17475
+ payload: {
17476
+ type: "message.delta",
17477
+ delta: text,
17478
+ recovered_from: "hermes_transcript",
17479
+ hermes_session_id: hermesSessionId
17480
+ },
17481
+ rawPayload: {
17482
+ format: "hermes-transcript-recovery",
17483
+ hermes_session_id: hermesSessionId,
17484
+ content: text
17485
+ }
17486
+ };
17487
+ }
17488
+ function transcriptRecoveryCompletedEvent(hermesSessionId) {
17489
+ return {
17490
+ eventName: "run.completed",
17491
+ payloadType: "run.completed",
17492
+ payload: {
17493
+ type: "run.completed",
17494
+ recovered_from: "hermes_transcript",
17495
+ hermes_session_id: hermesSessionId
17496
+ },
17497
+ rawPayload: {
17498
+ format: "hermes-transcript-recovery",
17499
+ hermes_session_id: hermesSessionId,
17500
+ type: "run.completed"
17501
+ }
17502
+ };
17503
+ }
17377
17504
  function readResponseId(payload) {
17378
17505
  if (!payload) {
17379
17506
  return null;
package/dist/cli/index.js CHANGED
@@ -44,7 +44,7 @@ import {
44
44
  startDaemonProcess,
45
45
  startLinkService,
46
46
  stopDaemonProcess
47
- } from "../chunk-PCJGVIKH.js";
47
+ } from "../chunk-FCCY3M5Z.js";
48
48
 
49
49
  // src/cli/index.ts
50
50
  import { Command } from "commander";
package/dist/http/app.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createApp
3
- } from "../chunk-PCJGVIKH.js";
3
+ } from "../chunk-FCCY3M5Z.js";
4
4
  export {
5
5
  createApp
6
6
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hermespilot/link",
3
- "version": "0.6.3",
3
+ "version": "0.6.4",
4
4
  "private": false,
5
5
  "description": "Hermes Link companion service and CLI for connecting hermes-agent through HermesPilot",
6
6
  "license": "MIT",