@vibedeckx/linux-x64 0.3.4 → 0.3.5

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.
Files changed (2) hide show
  1. package/dist/bin.js +109 -43
  2. package/package.json +1 -1
package/dist/bin.js CHANGED
@@ -205180,6 +205180,13 @@ function findTurnOpeningUserEntry(entries, beforeIndex) {
205180
205180
  }
205181
205181
  return opening;
205182
205182
  }
205183
+ function findLatestUserEntry(entries) {
205184
+ for (let i = entries.length - 1; i >= 0; i--) {
205185
+ const entry = entries[i];
205186
+ if (entry?.type === "user") return entry;
205187
+ }
205188
+ return void 0;
205189
+ }
205183
205190
  function resolveNotificationDisposition(openingUserEntry) {
205184
205191
  if (openingUserEntry?.type !== "user") return "result";
205185
205192
  if (openingUserEntry.notificationDisposition) return openingUserEntry.notificationDisposition;
@@ -228169,6 +228176,10 @@ var AgentSessionManager = class {
228169
228176
  if (event.type === "turn_started" || event.type === "text" || event.type === "thinking" || event.type === "tool_use" || event.type === "tool_result" || event.type === "approval_request") {
228170
228177
  this.applyCompletionTimerAction(session, session.completion.noteTurnActivity());
228171
228178
  }
228179
+ if (session.turnOpenSince === null && (event.type === "turn_started" || event.type === "text" || event.type === "thinking" || event.type === "tool_use" || event.type === "tool_result" || event.type === "approval_request")) {
228180
+ session.turnOpenSince = timestamp;
228181
+ session.turnDisposition = resolveNotificationDisposition(findLatestUserEntry(session.store.entries));
228182
+ }
228172
228183
  if (session.status !== "running" && (event.type === "text" || event.type === "thinking" || event.type === "tool_use" || event.type === "tool_result" || event.type === "approval_request")) {
228173
228184
  session.status = "running";
228174
228185
  if (!session.skipDb) await this.storage.agentSessions.updateStatus(sessionId, "running");
@@ -230244,6 +230255,26 @@ function tryParseWsMessage(raw) {
230244
230255
  return void 0;
230245
230256
  }
230246
230257
  }
230258
+ function isEntryPatchFrame(parsed) {
230259
+ if (!parsed || !("JsonPatch" in parsed)) return false;
230260
+ const ops = parsed.JsonPatch;
230261
+ if (!Array.isArray(ops)) return false;
230262
+ return ops.some((op) => typeof op?.path === "string" && op.path.startsWith("/entries/"));
230263
+ }
230264
+ function entryPatchFrames(messages) {
230265
+ const frames = [];
230266
+ for (const raw of messages) {
230267
+ if (isEntryPatchFrame(tryParseWsMessage(raw))) frames.push(raw);
230268
+ }
230269
+ return frames;
230270
+ }
230271
+ function isSequencePrefix(cached2, replay) {
230272
+ if (cached2.length > replay.length) return false;
230273
+ for (let i = 0; i < cached2.length; i++) {
230274
+ if (cached2[i] !== replay[i]) return false;
230275
+ }
230276
+ return true;
230277
+ }
230247
230278
  async function persistRemoteSessionActivityFrame(storage, sessionId, remoteInfo, parsed, activityAt = Date.now()) {
230248
230279
  const projectId = projectIdFromRemoteSessionId(sessionId, remoteInfo);
230249
230280
  const statusEvent = statusEventFromRemotePatch(parsed, sessionId, remoteInfo);
@@ -230307,6 +230338,7 @@ function connectPersistentRemoteWs(sessionId, remoteInfo, cache2, reverseConnect
230307
230338
  const raw = data.toString();
230308
230339
  const parsed = tryParseWsMessage(raw);
230309
230340
  if (!parsed) return;
230341
+ if ("keepalive" in parsed) return;
230310
230342
  const kind = "JsonPatch" in parsed ? "JsonPatch" : "finished" in parsed ? "finished" : "taskCompleted" in parsed ? "taskCompleted" : "workflowRunUpdated" in parsed ? "workflowRunUpdated" : "processAlive" in parsed ? "processAlive" : "branchActivity" in parsed ? "branchActivity" : "Ready" in parsed ? "Ready" : "error" in parsed ? "error" : "other";
230311
230343
  if (kind === "JsonPatch") {
230312
230344
  const ops = parsed.JsonPatch;
@@ -230454,23 +230486,18 @@ function connectPersistentRemoteWs(sessionId, remoteInfo, cache2, reverseConnect
230454
230486
  if ("Ready" in parsed) {
230455
230487
  syncing = false;
230456
230488
  const currentEntry = cache2.get(sessionId);
230457
- const cachedMsgCount = currentEntry.messages.length;
230458
- if (replayBuffer.length > cachedMsgCount) {
230459
- const delta = replayBuffer.slice(cachedMsgCount);
230460
- console.log(`[AgentWS] Sync delta: ${delta.length} new msgs for ${sessionId}`);
230489
+ const cachedSeq = entryPatchFrames(currentEntry.messages);
230490
+ const extendsCache = isSequencePrefix(cachedSeq, replayBuffer);
230491
+ if (extendsCache && replayBuffer.length > cachedSeq.length) {
230492
+ const delta = replayBuffer.slice(cachedSeq.length);
230493
+ console.log(`[AgentWS] Sync delta: ${delta.length} new entry patches for ${sessionId} (remote=${replayBuffer.length}, cached=${cachedSeq.length})`);
230461
230494
  for (const msg of delta) {
230462
- const p2 = tryParseWsMessage(msg);
230463
- cache2.appendMessage(sessionId, msg, !!(p2 && "JsonPatch" in p2));
230495
+ cache2.appendMessage(sessionId, msg, true);
230464
230496
  cache2.broadcast(sessionId, msg);
230465
230497
  }
230466
- } else if (replayBuffer.length < cachedMsgCount) {
230467
- console.log(`[AgentWS] Sync stale cache for ${sessionId}: remote=${replayBuffer.length}, cached=${cachedMsgCount}`);
230468
- let newPatchCount = 0;
230469
- for (const msg of replayBuffer) {
230470
- const p2 = tryParseWsMessage(msg);
230471
- if (p2 && "JsonPatch" in p2) newPatchCount++;
230472
- }
230473
- cache2.replaceAll(sessionId, [...replayBuffer], newPatchCount);
230498
+ } else if (!extendsCache) {
230499
+ console.log(`[AgentWS] Sync replace for ${sessionId}: remote=${replayBuffer.length}, cached=${cachedSeq.length} (sequence diverged or shrank)`);
230500
+ cache2.replaceAll(sessionId, [...replayBuffer], replayBuffer.length);
230474
230501
  const clearPatch = {
230475
230502
  JsonPatch: [{
230476
230503
  op: "replace",
@@ -230488,12 +230515,15 @@ function connectPersistentRemoteWs(sessionId, remoteInfo, cache2, reverseConnect
230488
230515
  remoteWs.on("message", handleLiveMessage);
230489
230516
  return;
230490
230517
  }
230491
- if ("JsonPatch" in parsed || "taskCompleted" in parsed || "error" in parsed) {
230518
+ if (isEntryPatchFrame(parsed)) {
230492
230519
  replayBuffer.push(raw);
230520
+ return;
230493
230521
  }
230494
230522
  if ("finished" in parsed) {
230495
230523
  cache2.setFinished(sessionId);
230524
+ return;
230496
230525
  }
230526
+ handleLiveMessage(data);
230497
230527
  });
230498
230528
  }
230499
230529
  remoteWs.on("error", (error48) => {
@@ -245476,6 +245506,7 @@ function attachRemoteProcessStream(fastify2, processId, send, onTerminal) {
245476
245506
  } catch {
245477
245507
  }
245478
245508
  if (!parsed) return;
245509
+ if ("keepalive" in parsed) return;
245479
245510
  send(parsed);
245480
245511
  if (parsed.type === "finished" || parsed.type === "error") terminalSignalSent = true;
245481
245512
  if (parsed.type === "finished" || parsed.type === "error") {
@@ -245630,6 +245661,47 @@ async function userOwnsSession(fastify2, sessionId, userId) {
245630
245661
  return !!await fastify2.storage.projects.getById(session.project_id, userId);
245631
245662
  }
245632
245663
 
245664
+ // src/utils/ws-heartbeat.ts
245665
+ var DEFAULT_INTERVAL_MS = 3e4;
245666
+ function attachWsHeartbeat(socket, { label, intervalMs = DEFAULT_INTERVAL_MS, keepalive = false }) {
245667
+ let awaitingPong = false;
245668
+ const markAlive = () => {
245669
+ awaitingPong = false;
245670
+ };
245671
+ socket.on("pong", markAlive);
245672
+ socket.on("message", markAlive);
245673
+ const timer = setInterval(() => {
245674
+ if (socket.readyState !== wrapper_default.OPEN) return;
245675
+ if (awaitingPong) {
245676
+ console.log(`[WsHeartbeat] ${label}: no pong within ${intervalMs * 2}ms \u2014 terminating dead socket`);
245677
+ try {
245678
+ socket.terminate();
245679
+ } catch {
245680
+ }
245681
+ return;
245682
+ }
245683
+ awaitingPong = true;
245684
+ try {
245685
+ socket.ping();
245686
+ } catch {
245687
+ }
245688
+ if (keepalive) {
245689
+ try {
245690
+ socket.send(JSON.stringify({ keepalive: Date.now() }));
245691
+ } catch {
245692
+ }
245693
+ }
245694
+ }, intervalMs);
245695
+ let cleaned = false;
245696
+ return () => {
245697
+ if (cleaned) return;
245698
+ cleaned = true;
245699
+ clearInterval(timer);
245700
+ socket.off("pong", markAlive);
245701
+ socket.off("message", markAlive);
245702
+ };
245703
+ }
245704
+
245633
245705
  // src/routes/websocket-routes.ts
245634
245706
  var routes24 = async (fastify2) => {
245635
245707
  fastify2.reverseConnectManager.setStatusChangeHandler((remoteServerId, status) => {
@@ -245688,10 +245760,14 @@ var routes24 = async (fastify2) => {
245688
245760
  }
245689
245761
  return;
245690
245762
  }
245763
+ const stopHeartbeat = attachWsHeartbeat(socket, {
245764
+ label: `ProjectChatWS thread=${req.params.threadId}`
245765
+ });
245691
245766
  let cleaned = false;
245692
245767
  const cleanup = () => {
245693
245768
  if (cleaned) return;
245694
245769
  cleaned = true;
245770
+ stopHeartbeat();
245695
245771
  unsubscribe();
245696
245772
  };
245697
245773
  socket.on("close", cleanup);
@@ -245723,11 +245799,9 @@ var routes24 = async (fastify2) => {
245723
245799
  return;
245724
245800
  }
245725
245801
  console.log(`[WebSocket] Client connected for process ${processId}`);
245726
- const pingInterval = setInterval(() => {
245727
- if (socket.readyState === wrapper_default.OPEN) {
245728
- socket.ping();
245729
- }
245730
- }, 3e4);
245802
+ const stopHeartbeat = attachWsHeartbeat(socket, {
245803
+ label: `ExecutorWS process=${processId}`
245804
+ });
245731
245805
  const send = (msg) => {
245732
245806
  try {
245733
245807
  socket.send(JSON.stringify(msg));
@@ -245753,7 +245827,7 @@ var routes24 = async (fastify2) => {
245753
245827
  });
245754
245828
  socket.on("close", () => {
245755
245829
  console.log(`[WebSocket] Client disconnected from process ${processId}`);
245756
- clearInterval(pingInterval);
245830
+ stopHeartbeat();
245757
245831
  handle.cleanup();
245758
245832
  });
245759
245833
  }
@@ -245769,11 +245843,7 @@ var routes24 = async (fastify2) => {
245769
245843
  return;
245770
245844
  }
245771
245845
  console.log(`[ExecutorMux] Client connected`);
245772
- const pingInterval = setInterval(() => {
245773
- if (socket.readyState === wrapper_default.OPEN) {
245774
- socket.ping();
245775
- }
245776
- }, 3e4);
245846
+ const stopHeartbeat = attachWsHeartbeat(socket, { label: "ExecutorMux" });
245777
245847
  const subs = /* @__PURE__ */ new Map();
245778
245848
  const handleInputMap = /* @__PURE__ */ new Map();
245779
245849
  const subscribeProcess = async (processId) => {
@@ -245832,7 +245902,7 @@ var routes24 = async (fastify2) => {
245832
245902
  });
245833
245903
  socket.on("close", () => {
245834
245904
  console.log(`[ExecutorMux] Client disconnected; cleaning ${subs.size} subscriptions`);
245835
- clearInterval(pingInterval);
245905
+ stopHeartbeat();
245836
245906
  for (const cleanup of subs.values()) cleanup();
245837
245907
  subs.clear();
245838
245908
  handleInputMap.clear();
@@ -245876,15 +245946,15 @@ var routes24 = async (fastify2) => {
245876
245946
  return;
245877
245947
  }
245878
245948
  console.log(`[AgentWS] Client connected for session ${sessionId}`);
245879
- const pingInterval = setInterval(() => {
245880
- if (socket.readyState === wrapper_default.OPEN) {
245881
- socket.ping();
245882
- }
245883
- }, 3e4);
245949
+ const stopHeartbeat = attachWsHeartbeat(socket, {
245950
+ label: `AgentWS session=${sessionId}`,
245951
+ keepalive: true
245952
+ });
245884
245953
  if (sessionId.startsWith("remote-")) {
245885
245954
  const remoteInfo = fastify2.remoteSessionMap.get(sessionId);
245886
245955
  if (!remoteInfo) {
245887
245956
  console.log(`[AgentWS] Remote session ${sessionId} not found in map`);
245957
+ stopHeartbeat();
245888
245958
  socket.send(JSON.stringify({ type: "error", message: "Remote session not found" }));
245889
245959
  socket.close();
245890
245960
  return;
@@ -245911,7 +245981,7 @@ var routes24 = async (fastify2) => {
245911
245981
  }
245912
245982
  cache2.addSubscriber(sessionId, socket);
245913
245983
  socket.on("close", () => {
245914
- clearInterval(pingInterval);
245984
+ stopHeartbeat();
245915
245985
  cache2.removeSubscriber(sessionId, socket);
245916
245986
  });
245917
245987
  return;
@@ -245952,7 +246022,7 @@ var routes24 = async (fastify2) => {
245952
246022
  });
245953
246023
  socket.on("close", () => {
245954
246024
  console.log(`[AgentWS] Client disconnected from remote session ${sessionId}`);
245955
- clearInterval(pingInterval);
246025
+ stopHeartbeat();
245956
246026
  cache2.removeSubscriber(sessionId, socket);
245957
246027
  });
245958
246028
  return;
@@ -245960,7 +246030,7 @@ var routes24 = async (fastify2) => {
245960
246030
  const unsubscribe = fastify2.agentSessionManager.subscribe(sessionId, socket);
245961
246031
  if (!unsubscribe) {
245962
246032
  console.log(`[AgentWS] Session ${sessionId} not found`);
245963
- clearInterval(pingInterval);
246033
+ stopHeartbeat();
245964
246034
  socket.send(JSON.stringify({ error: "Session not found" }));
245965
246035
  socket.close();
245966
246036
  return;
@@ -245979,7 +246049,7 @@ var routes24 = async (fastify2) => {
245979
246049
  });
245980
246050
  socket.on("close", () => {
245981
246051
  console.log(`[AgentWS] Client disconnected from session ${sessionId}`);
245982
- clearInterval(pingInterval);
246052
+ stopHeartbeat();
245983
246053
  unsubscribe?.();
245984
246054
  });
245985
246055
  }
@@ -246035,15 +246105,11 @@ var routes24 = async (fastify2) => {
246035
246105
  }
246036
246106
  }
246037
246107
  console.log(`[ChatWS] Client connected for session ${sessionId}`);
246038
- const pingInterval = setInterval(() => {
246039
- if (socket.readyState === wrapper_default.OPEN) {
246040
- socket.ping();
246041
- }
246042
- }, 3e4);
246108
+ const stopHeartbeat = attachWsHeartbeat(socket, { label: `ChatWS session=${sessionId}` });
246043
246109
  const unsubscribe = fastify2.chatSessionManager.subscribe(sessionId, socket);
246044
246110
  if (!unsubscribe) {
246045
246111
  console.log(`[ChatWS] Session ${sessionId} not found`);
246046
- clearInterval(pingInterval);
246112
+ stopHeartbeat();
246047
246113
  socket.send(JSON.stringify({ error: "Session not found" }));
246048
246114
  socket.close();
246049
246115
  return;
@@ -246063,7 +246129,7 @@ var routes24 = async (fastify2) => {
246063
246129
  });
246064
246130
  socket.on("close", () => {
246065
246131
  console.log(`[ChatWS] Client disconnected from session ${sessionId}`);
246066
- clearInterval(pingInterval);
246132
+ stopHeartbeat();
246067
246133
  unsubscribe?.();
246068
246134
  });
246069
246135
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibedeckx/linux-x64",
3
- "version": "0.3.4",
3
+ "version": "0.3.5",
4
4
  "description": "Vibedeckx platform binaries for Linux x64",
5
5
  "os": [
6
6
  "linux"