@hermespilot/link 0.7.7 → 0.7.8-beta.0

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.
@@ -6636,7 +6636,7 @@ function isConversationMissingError(error) {
6636
6636
  }
6637
6637
 
6638
6638
  // src/constants.ts
6639
- var LINK_VERSION = "0.7.7";
6639
+ var LINK_VERSION = "0.7.8-beta.0";
6640
6640
  var LINK_COMMAND = "hermeslink";
6641
6641
  var LINK_DEFAULT_PORT = 52379;
6642
6642
  var LINK_RUNTIME_DIR_NAME = ".hermeslink";
@@ -8636,6 +8636,7 @@ import { setTimeout as delay3 } from "timers/promises";
8636
8636
  import WebSocket from "ws";
8637
8637
  var CONNECT_TIMEOUT_MS = 15e3;
8638
8638
  var REQUEST_TIMEOUT_MS = 12e4;
8639
+ var USAGE_REQUEST_TIMEOUT_MS = 1e4;
8639
8640
  var PROMPT_SUBMIT_TIMEOUT_MS = 0;
8640
8641
  var READY_TIMEOUT_MS = 1e4;
8641
8642
  var BACKEND_START_TIMEOUT_MS = 45e3;
@@ -8663,12 +8664,23 @@ async function streamTuiGatewayRun(input) {
8663
8664
  profileName
8664
8665
  });
8665
8666
  await client.waitForSessionDrain(started.runtimeSessionId, input.signal);
8667
+ const usageBaseline = await client.readSessionUsage(started.runtimeSessionId).catch((error) => {
8668
+ void input.logger?.debug("tui_gateway_usage_baseline_read_failed", {
8669
+ profile: profileName,
8670
+ session_id: started.runtimeSessionId,
8671
+ error: error instanceof Error ? error.message : String(error)
8672
+ });
8673
+ return started.resumed ? null : {};
8674
+ });
8666
8675
  const events = client.submitPrompt({
8667
8676
  sessionId: started.runtimeSessionId,
8668
8677
  text: buildTuiGatewayPromptText(input),
8669
8678
  signal: input.signal
8670
8679
  });
8671
- return { started, events };
8680
+ return {
8681
+ started,
8682
+ events: normalizeTuiGatewayRunUsageDeltas(events, usageBaseline)
8683
+ };
8672
8684
  }
8673
8685
  function buildTuiGatewayPromptText(input) {
8674
8686
  return input.input;
@@ -9180,6 +9192,13 @@ var TuiGatewayClient = class {
9180
9192
  queue.closed.finally(cleanup).catch(() => void 0);
9181
9193
  return queue;
9182
9194
  }
9195
+ async readSessionUsage(sessionId) {
9196
+ return await this.request(
9197
+ "session.usage",
9198
+ { session_id: sessionId },
9199
+ USAGE_REQUEST_TIMEOUT_MS
9200
+ );
9201
+ }
9183
9202
  async interruptSession(sessionId) {
9184
9203
  const queue = new GatewayEventQueue(sessionId);
9185
9204
  this.eventQueues.add(queue);
@@ -9477,6 +9496,94 @@ var GatewayEventQueue = class {
9477
9496
  });
9478
9497
  }
9479
9498
  };
9499
+ async function* normalizeTuiGatewayRunUsageDeltas(events, baseline) {
9500
+ for await (const event of events) {
9501
+ yield normalizeTuiGatewayRunUsageDelta(event, baseline);
9502
+ }
9503
+ }
9504
+ function normalizeTuiGatewayRunUsageDelta(event, baseline) {
9505
+ if (baseline === null || event.payloadType !== "run.completed" && event.payloadType !== "run.failed" && event.payloadType !== "run.cancelled") {
9506
+ return event;
9507
+ }
9508
+ const usage = normalizeTuiGatewayUsageDelta(event.payload.usage, baseline);
9509
+ if (!usage) {
9510
+ return event;
9511
+ }
9512
+ return {
9513
+ ...event,
9514
+ payload: {
9515
+ ...event.payload,
9516
+ usage
9517
+ }
9518
+ };
9519
+ }
9520
+ function normalizeTuiGatewayUsageDelta(usageValue, baseline) {
9521
+ const usage = toRecord3(usageValue);
9522
+ if (Object.keys(usage).length === 0) {
9523
+ return null;
9524
+ }
9525
+ const inputTokens = usageDelta(usage, baseline, [
9526
+ "input",
9527
+ "input_tokens",
9528
+ "prompt",
9529
+ "prompt_tokens"
9530
+ ]);
9531
+ const outputTokens = usageDelta(usage, baseline, [
9532
+ "output",
9533
+ "output_tokens",
9534
+ "completion",
9535
+ "completion_tokens"
9536
+ ]);
9537
+ const totalTokens = totalUsageDelta(
9538
+ usage,
9539
+ baseline,
9540
+ inputTokens,
9541
+ outputTokens
9542
+ );
9543
+ const contextTokens = readNumber2(usage, "context_used") ?? readNumber2(usage, "context_tokens") ?? readNumber2(usage, "current_context_tokens") ?? readNumber2(usage, "last_prompt_tokens");
9544
+ const contextWindow = readNumber2(usage, "context_max") ?? readNumber2(usage, "context_window") ?? readNumber2(usage, "context_length");
9545
+ const usagePercent = readNumber2(usage, "context_percent") ?? readNumber2(usage, "usage_percent");
9546
+ if (inputTokens === void 0 && outputTokens === void 0 && totalTokens === void 0 && contextTokens === void 0) {
9547
+ return null;
9548
+ }
9549
+ return {
9550
+ ...usage,
9551
+ ...inputTokens !== void 0 ? { input_tokens: inputTokens } : {},
9552
+ ...outputTokens !== void 0 ? { output_tokens: outputTokens } : {},
9553
+ ...totalTokens !== void 0 ? { total_tokens: totalTokens } : {},
9554
+ ...contextTokens !== void 0 ? { context_tokens: contextTokens } : {},
9555
+ ...contextWindow !== void 0 ? { context_window: contextWindow } : {},
9556
+ ...usagePercent !== void 0 ? { usage_percent: usagePercent } : {}
9557
+ };
9558
+ }
9559
+ function usageDelta(current, baseline, keys) {
9560
+ const currentValue = readFirstNumber(current, keys);
9561
+ if (currentValue === void 0) {
9562
+ return void 0;
9563
+ }
9564
+ const baselineValue = readFirstNumber(baseline, keys) ?? 0;
9565
+ return Math.max(0, currentValue - baselineValue);
9566
+ }
9567
+ function totalUsageDelta(current, baseline, inputTokens, outputTokens) {
9568
+ const currentTotal = readFirstNumber(current, ["total", "total_tokens"]);
9569
+ const baselineTotal = readFirstNumber(baseline, ["total", "total_tokens"]);
9570
+ if (currentTotal !== void 0 && (baselineTotal !== void 0 || Object.keys(baseline).length === 0)) {
9571
+ return Math.max(0, currentTotal - (baselineTotal ?? 0));
9572
+ }
9573
+ if (inputTokens !== void 0 || outputTokens !== void 0) {
9574
+ return (inputTokens ?? 0) + (outputTokens ?? 0);
9575
+ }
9576
+ return void 0;
9577
+ }
9578
+ function readFirstNumber(payload, keys) {
9579
+ for (const key of keys) {
9580
+ const value = readNumber2(payload, key);
9581
+ if (value !== void 0) {
9582
+ return value;
9583
+ }
9584
+ }
9585
+ return void 0;
9586
+ }
9480
9587
  function normalizeGatewayEvent(event) {
9481
9588
  const payload = toRecord3(event.payload);
9482
9589
  const base = {
@@ -9762,7 +9869,14 @@ function readString5(payload, key) {
9762
9869
  }
9763
9870
  function readNumber2(payload, key) {
9764
9871
  const value = payload[key];
9765
- return typeof value === "number" && Number.isFinite(value) ? value : null;
9872
+ if (typeof value === "number" && Number.isFinite(value)) {
9873
+ return Math.max(0, Math.floor(value));
9874
+ }
9875
+ if (typeof value === "string" && value.trim()) {
9876
+ const parsed = Number.parseInt(value.replaceAll(",", ""), 10);
9877
+ return Number.isFinite(parsed) ? Math.max(0, parsed) : void 0;
9878
+ }
9879
+ return void 0;
9766
9880
  }
9767
9881
  function readText(payload, key) {
9768
9882
  const value = payload[key];
@@ -9996,6 +10110,25 @@ function latestUsageRun(snapshot) {
9996
10110
  }
9997
10111
  return void 0;
9998
10112
  }
10113
+ function latestContextUsageRun(snapshot) {
10114
+ let latestEstimatedRun;
10115
+ let latestUsageRun2;
10116
+ for (const run of [...snapshot.runs].reverse()) {
10117
+ if (!isAgentRun(run) || !run.usage) {
10118
+ continue;
10119
+ }
10120
+ latestUsageRun2 ??= run;
10121
+ if (run.usage.context_tokens === void 0) {
10122
+ continue;
10123
+ }
10124
+ if (run.usage.context_source === "estimated") {
10125
+ latestEstimatedRun ??= run;
10126
+ continue;
10127
+ }
10128
+ return run;
10129
+ }
10130
+ return latestEstimatedRun ?? latestUsageRun2;
10131
+ }
9999
10132
  function latestRuntimeRun(snapshot) {
10000
10133
  for (const run of [...snapshot.runs].reverse()) {
10001
10134
  if (isAgentRun(run) && (run.model || run.profile_uid || run.profile_name_snapshot || run.profile || run.usage)) {
@@ -10991,7 +11124,7 @@ async function readConversationProfileSummary(paths, manifest) {
10991
11124
  }
10992
11125
  async function buildConversationRuntimeMetadata(paths, manifest, snapshot) {
10993
11126
  const current = await readCurrentConversationRuntime(paths, manifest);
10994
- const usageRun = latestUsageRun(snapshot);
11127
+ const usageRun = latestContextUsageRun(snapshot);
10995
11128
  const profileUid = current.profileUid;
10996
11129
  const profileName = current.profileName;
10997
11130
  const profilePresentation = {
@@ -23489,7 +23622,7 @@ ${details.join("\n")}` : localizedEmptyHermesResponseMessage(language);
23489
23622
  payload: { message: assistant }
23490
23623
  });
23491
23624
  }
23492
- const contextUsage = contextUsagePayload(run);
23625
+ const contextUsage = contextUsagePayloadForSnapshot(snapshot);
23493
23626
  await this.deps.appendEvent(conversationId, {
23494
23627
  type: "run.completed",
23495
23628
  message_id: assistant?.id,
@@ -23557,7 +23690,7 @@ ${details.join("\n")}` : localizedEmptyHermesResponseMessage(language);
23557
23690
  assistant?.id,
23558
23691
  expiredApprovals
23559
23692
  );
23560
- const contextUsage = contextUsagePayload(run);
23693
+ const contextUsage = contextUsagePayloadForSnapshot(snapshot);
23561
23694
  await this.deps.appendEvent(conversationId, {
23562
23695
  type: "run.failed",
23563
23696
  message_id: assistant?.id,
@@ -23760,11 +23893,16 @@ ${details.join("\n")}` : localizedEmptyHermesResponseMessage(language);
23760
23893
  payload: { message: assistant, cancelled: true }
23761
23894
  });
23762
23895
  }
23896
+ const contextUsage = contextUsagePayloadForSnapshot(snapshot);
23763
23897
  const event = await this.deps.appendEvent(conversationId, {
23764
23898
  type: "run.cancelled",
23765
23899
  message_id: assistant?.id,
23766
23900
  run_id: runId,
23767
- payload: { run, reason: options.reason }
23901
+ payload: {
23902
+ run,
23903
+ reason: options.reason,
23904
+ ...contextUsage ? { context: contextUsage } : {}
23905
+ }
23768
23906
  });
23769
23907
  await this.deps.persistConversationStats(conversationId, snapshot);
23770
23908
  void this.deps.logger.info("conversation_run_cancelled", {
@@ -24126,6 +24264,10 @@ function appendAgentEventBlock2(message, event, updatedAt) {
24126
24264
  }
24127
24265
  message.blocks = blocks;
24128
24266
  }
24267
+ function contextUsagePayloadForSnapshot(snapshot) {
24268
+ const run = latestContextUsageRun(snapshot);
24269
+ return run ? contextUsagePayload(run) : null;
24270
+ }
24129
24271
  function contextUsagePayload(run) {
24130
24272
  const usage = run.usage;
24131
24273
  const runtimeContext = resolveRuntimeContextUsage({
package/dist/cli/index.js CHANGED
@@ -54,7 +54,7 @@ import {
54
54
  stopDaemonProcess,
55
55
  summarizeUsageProbeEnsure,
56
56
  translate
57
- } from "../chunk-JQYZZDVU.js";
57
+ } from "../chunk-A3USRRZU.js";
58
58
 
59
59
  // src/cli/index.ts
60
60
  import { Command } from "commander";
package/dist/http/app.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createApp
3
- } from "../chunk-JQYZZDVU.js";
3
+ } from "../chunk-A3USRRZU.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.7.7",
3
+ "version": "0.7.8-beta.0",
4
4
  "private": false,
5
5
  "description": "Hermes Link companion service and CLI for connecting hermes-agent through HermesPilot",
6
6
  "license": "MIT",