@wibeco/bridge 0.2.3 → 0.2.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.
@@ -380,6 +380,7 @@ function toEnvelope(event, options) {
380
380
  tool_counts: event.metadata.tool_counts,
381
381
  tests_passed: event.metadata.tests_passed,
382
382
  tests_failed: event.metadata.tests_failed,
383
+ last_activity_at: event.metadata.last_activity_at,
383
384
  session_started_at: event.metadata.session_started_at,
384
385
  heartbeat_at: event.metadata.heartbeat_at,
385
386
  heartbeat_interval_ms: event.metadata.heartbeat_interval_ms,
@@ -565,6 +566,8 @@ import { join } from "path";
565
566
  var PRESENCE_HEARTBEAT_INTERVAL_MS = 45e3;
566
567
  var MAX_SESSION_DURATION_MS = 12 * 60 * 60 * 1e3;
567
568
  var MAX_SESSION_LINE_COUNT = 1e7;
569
+ var MAX_INFERRED_ACTIVITY_SECONDS = 60;
570
+ var MAX_REPORTED_ACTIVITY_SECONDS = 30 * 60;
568
571
  async function startPresenceSession(source, sessionId, cwd = process.cwd()) {
569
572
  const statePath = presenceStatePath(source, sessionId, cwd);
570
573
  await rm(statePath, { force: true });
@@ -586,7 +589,8 @@ async function startPresenceSession(source, sessionId, cwd = process.cwd()) {
586
589
  toolCounts: {},
587
590
  testsPassed: 0,
588
591
  testsFailed: 0,
589
- measuredAt: startedAt
592
+ measuredAt: startedAt,
593
+ lastActivityAt: startedAt
590
594
  };
591
595
  const metrics = metricsFromState(state, startedAt);
592
596
  if (!cliPath) return metrics;
@@ -621,10 +625,8 @@ async function updatePresenceSession(source, sessionId, event, cwd = process.cwd
621
625
  if (!state) return void 0;
622
626
  const measuredAt = (/* @__PURE__ */ new Date()).toISOString();
623
627
  const isHeartbeat = event.kind === "presence.heartbeat";
624
- if (!isHeartbeat) accrueModelTime(state, measuredAt);
625
- const model = typeof event.metadata.model === "string" ? event.metadata.model : void 0;
626
- if (model) state.model = model;
627
628
  if (!isHeartbeat) {
629
+ accrueModelActivity(state, event, measuredAt);
628
630
  state.linesAdded += safeCount(event.metadata.lines_added);
629
631
  state.linesDeleted += safeCount(event.metadata.lines_deleted);
630
632
  }
@@ -677,7 +679,6 @@ async function stopPresenceSession(source, sessionId, cwd = process.cwd()) {
677
679
  await rm(statePath, { force: true });
678
680
  if (!state) return void 0;
679
681
  const measuredAt = (/* @__PURE__ */ new Date()).toISOString();
680
- accrueModelTime(state, measuredAt);
681
682
  state.sequence += 1;
682
683
  return metricsFromState(state, measuredAt);
683
684
  }
@@ -693,7 +694,6 @@ async function runPresenceHeartbeat(statePath, expectedInstanceId, emit, interva
693
694
  await rm(statePath, { force: true });
694
695
  return;
695
696
  }
696
- accrueModelTime(state, heartbeatAt);
697
697
  state.sequence += 1;
698
698
  await writePresenceState(statePath, state);
699
699
  await emit(state.source, "heartbeat", {
@@ -731,12 +731,13 @@ async function readPresenceState(path) {
731
731
  baselineLinesAdded: optionalCount(value.baselineLinesAdded),
732
732
  baselineLinesDeleted: optionalCount(value.baselineLinesDeleted),
733
733
  paths: Array.isArray(value.paths) ? value.paths.filter((path2) => typeof path2 === "string") : [],
734
- model: typeof value.model === "string" ? value.model : void 0,
735
- modelSeconds: safeCountRecord(value.modelSeconds),
734
+ model: typeof value.model === "string" ? canonicalModelName(value.model) : void 0,
735
+ modelSeconds: canonicalModelSeconds(value.modelSeconds),
736
736
  toolCounts: safeCountRecord(value.toolCounts),
737
737
  testsPassed: safeCount(value.testsPassed),
738
738
  testsFailed: safeCount(value.testsFailed),
739
- measuredAt: typeof value.measuredAt === "string" && Number.isFinite(Date.parse(value.measuredAt)) ? value.measuredAt : value.startedAt
739
+ measuredAt: typeof value.measuredAt === "string" && Number.isFinite(Date.parse(value.measuredAt)) ? value.measuredAt : value.startedAt,
740
+ lastActivityAt: typeof value.lastActivityAt === "string" && Number.isFinite(Date.parse(value.lastActivityAt)) ? value.lastActivityAt : value.startedAt
740
741
  };
741
742
  } catch {
742
743
  return void 0;
@@ -746,17 +747,37 @@ async function writePresenceState(path, state) {
746
747
  await writeFile2(path, `${JSON.stringify(state)}
747
748
  `, { mode: 384 });
748
749
  }
749
- function accrueModelTime(state, measuredAt) {
750
- const elapsedSeconds = Math.max(
750
+ function canonicalModelName(value) {
751
+ const normalized = value.trim();
752
+ return /^(auto|default)$/i.test(normalized) ? "Auto" : normalized;
753
+ }
754
+ function canonicalModelSeconds(value) {
755
+ const canonical = {};
756
+ for (const [model, seconds] of Object.entries(safeCountRecord(value))) {
757
+ const name = canonicalModelName(model);
758
+ if (!name) continue;
759
+ canonical[name] = (canonical[name] ?? 0) + seconds;
760
+ }
761
+ return canonical;
762
+ }
763
+ function accrueModelActivity(state, event, measuredAt) {
764
+ const suppliedModel = typeof event.metadata.model === "string" ? canonicalModelName(event.metadata.model) : void 0;
765
+ if (suppliedModel) state.model = suppliedModel;
766
+ const inferredSeconds = Math.max(
751
767
  0,
752
768
  Math.floor(
753
769
  (Date.parse(measuredAt) - Date.parse(state.measuredAt || state.startedAt)) / 1e3
754
770
  )
755
771
  );
772
+ const elapsedSeconds = typeof event.durationMs === "number" && event.durationMs > 0 ? Math.min(
773
+ MAX_REPORTED_ACTIVITY_SECONDS,
774
+ Math.max(1, Math.ceil(event.durationMs / 1e3))
775
+ ) : Math.min(MAX_INFERRED_ACTIVITY_SECONDS, inferredSeconds);
756
776
  if (state.model && elapsedSeconds > 0) {
757
777
  state.modelSeconds[state.model] = (state.modelSeconds[state.model] ?? 0) + elapsedSeconds;
758
778
  }
759
779
  state.measuredAt = measuredAt;
780
+ state.lastActivityAt = measuredAt;
760
781
  }
761
782
  function metricsFromState(state, measuredAt) {
762
783
  const sessionElapsedMs = Math.max(
@@ -774,7 +795,8 @@ function metricsFromState(state, measuredAt) {
774
795
  model_seconds: state.modelSeconds,
775
796
  tool_counts: state.toolCounts,
776
797
  tests_passed: state.testsPassed,
777
- tests_failed: state.testsFailed
798
+ tests_failed: state.testsFailed,
799
+ last_activity_at: state.lastActivityAt
778
800
  };
779
801
  }
780
802
  function safeCount(value) {
@@ -17,7 +17,7 @@ import {
17
17
  startPresenceSession,
18
18
  stopPresenceSession,
19
19
  updatePresenceSession
20
- } from "./chunk-A7KGZ7NX.js";
20
+ } from "./chunk-RI4FCH2F.js";
21
21
 
22
22
  // src/cli/commands.ts
23
23
  import { access, cp, mkdir, readFile, writeFile } from "fs/promises";
package/dist/cli.js CHANGED
@@ -6,10 +6,10 @@ import {
6
6
  setupCommand,
7
7
  shareProgressCommand,
8
8
  statusCommand
9
- } from "./chunk-QDJNDFHB.js";
9
+ } from "./chunk-ZFVW6RVP.js";
10
10
  import {
11
11
  runPresenceHeartbeat
12
- } from "./chunk-A7KGZ7NX.js";
12
+ } from "./chunk-RI4FCH2F.js";
13
13
 
14
14
  // src/cli.ts
15
15
  var HELP = `wibe-bridge <command>
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  emitCommand
4
- } from "./chunk-QDJNDFHB.js";
5
- import "./chunk-A7KGZ7NX.js";
4
+ } from "./chunk-ZFVW6RVP.js";
5
+ import "./chunk-RI4FCH2F.js";
6
6
 
7
7
  // src/codex-hook.ts
8
8
  async function main() {
package/dist/index.d.ts CHANGED
@@ -268,6 +268,7 @@ interface PresenceMetrics {
268
268
  tool_counts: Record<string, number>;
269
269
  tests_passed: number;
270
270
  tests_failed: number;
271
+ last_activity_at: string;
271
272
  }
272
273
  declare function startPresenceSession(source: AgentSource, sessionId: string | undefined, cwd?: string): Promise<PresenceMetrics>;
273
274
  declare function updatePresenceSession(source: AgentSource, sessionId: string | undefined, event: CanonicalHookEvent, cwd?: string): Promise<PresenceMetrics | undefined>;
package/dist/index.js CHANGED
@@ -29,7 +29,7 @@ import {
29
29
  startPresenceSession,
30
30
  stopPresenceSession,
31
31
  updatePresenceSession
32
- } from "./chunk-A7KGZ7NX.js";
32
+ } from "./chunk-RI4FCH2F.js";
33
33
  export {
34
34
  JsonFileOfflineQueue,
35
35
  MemoryOfflineQueue,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wibeco/bridge",
3
- "version": "0.2.3",
3
+ "version": "0.2.4",
4
4
  "description": "Privacy-first live activity bridge for Cursor, Claude Code, and Codex.",
5
5
  "repository": {
6
6
  "type": "git",