@parhelia/core 0.1.12737 → 0.1.12741

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.
@@ -1022,12 +1022,16 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
1022
1022
  }
1023
1023
  return getAgentRunMessageAgentId(message.payload) === normalizedAgentId;
1024
1024
  })
1025
- .slice(-8)
1025
+ .slice(0, 8)
1026
+ .reverse()
1026
1027
  .map((message) => ({
1027
1028
  timestamp: message.timestamp,
1029
+ direction: message.direction ?? "incoming",
1028
1030
  type: message.type,
1029
- seq: getAgentRunMessageSeq(message.payload),
1030
- detail: getAgentRunMessageDetail(message.type, message.payload),
1031
+ seq: message.seq ?? getAgentRunMessageSeq(message.payload),
1032
+ detail: message.detail ?? getAgentRunMessageDetail(message.type, message.payload),
1033
+ rawMessage: message.rawMessage,
1034
+ payloadBytes: message.payloadBytes ?? null,
1031
1035
  }));
1032
1036
  }, [currentAgentId, editContext?.webSocketMessages]);
1033
1037
  const appendToolUiEvent = useCallback((type, detail, seq) => {
@@ -1834,6 +1838,8 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
1834
1838
  const lastSeqRef = useRef(0);
1835
1839
  const subscribedAgentIdRef = useRef(null);
1836
1840
  const reconcileServerStateInFlightRef = useRef(false);
1841
+ const streamRecoveryInFlightRef = useRef(false);
1842
+ const lastStreamRecoveryAtRef = useRef(0);
1837
1843
  const toolCallFirstSeenAtRef = useRef({});
1838
1844
  const pendingToolCompletionTimersRef = useRef({});
1839
1845
  // Cache mode/model/profile changes made while the agent is still "new" (not yet persisted)
@@ -3961,10 +3967,12 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
3961
3967
  if (subscribedAgentIdRef.current) {
3962
3968
  const socket = globalThis.editorSocket;
3963
3969
  if (socket && socket.readyState === WebSocket.OPEN) {
3964
- socket.send(JSON.stringify({
3970
+ const payload = {
3965
3971
  type: "agent:unsubscribe",
3966
3972
  agentId: subscribedAgentIdRef.current,
3967
- }));
3973
+ };
3974
+ console.debug("[AgentWebSocket] sent", payload);
3975
+ socket.send(JSON.stringify(payload));
3968
3976
  }
3969
3977
  subscribedAgentIdRef.current = null;
3970
3978
  }
@@ -3973,10 +3981,12 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
3973
3981
  // Send subscription message to server
3974
3982
  const socket = globalThis.editorSocket;
3975
3983
  if (socket && socket.readyState === WebSocket.OPEN) {
3976
- socket.send(JSON.stringify({
3984
+ const payload = {
3977
3985
  type: "agent:subscribe",
3978
3986
  agentId: agentStub.id,
3979
- }));
3987
+ };
3988
+ console.debug("[AgentWebSocket] sent", payload);
3989
+ socket.send(JSON.stringify(payload));
3980
3990
  }
3981
3991
  // Use the addSocketMessageListener helper from editContext
3982
3992
  // Wrap the handler in a stable function that uses the ref
@@ -4021,10 +4031,12 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
4021
4031
  if (socket &&
4022
4032
  socket.readyState === WebSocket.OPEN &&
4023
4033
  subscribedAgentIdRef.current) {
4024
- socket.send(JSON.stringify({
4034
+ const payload = {
4025
4035
  type: "agent:unsubscribe",
4026
4036
  agentId: subscribedAgentIdRef.current,
4027
- }));
4037
+ };
4038
+ console.debug("[AgentWebSocket] sent", payload);
4039
+ socket.send(JSON.stringify(payload));
4028
4040
  }
4029
4041
  unsubscribe();
4030
4042
  subscribedAgentIdRef.current = null;
@@ -5502,10 +5514,58 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
5502
5514
  settleCompletedRun(normalizeServerExecutionStatus(serverStatus) === "cancelled"
5503
5515
  ? "cancelled"
5504
5516
  : "completed");
5517
+ return;
5518
+ }
5519
+ const serverLastSeq = diagnostics.currentSession?.lastDelivery?.lastSeq ??
5520
+ diagnostics.transport?.lastSeq ??
5521
+ null;
5522
+ const serverLastSuccessAt = diagnostics.currentSession?.lastDelivery?.lastSuccessAt ??
5523
+ diagnostics.transport?.lastBroadcastAt ??
5524
+ diagnostics.transport?.lastProducedAt ??
5525
+ null;
5526
+ const serverLastSuccessTime = serverLastSuccessAt
5527
+ ? Date.parse(serverLastSuccessAt)
5528
+ : Number.NaN;
5529
+ const now = Date.now();
5530
+ const serverDeliveryOldEnough = Number.isFinite(serverLastSuccessTime) &&
5531
+ now - serverLastSuccessTime > 8_000;
5532
+ const recoveryCooldownElapsed = now - lastStreamRecoveryAtRef.current > 30_000;
5533
+ const localLastSeq = lastSeqRef.current;
5534
+ if (diagnostics.currentSession?.isConnected &&
5535
+ diagnostics.currentSession?.isSubscribed &&
5536
+ typeof serverLastSeq === "number" &&
5537
+ serverLastSeq > localLastSeq &&
5538
+ serverDeliveryOldEnough &&
5539
+ recoveryCooldownElapsed &&
5540
+ !streamRecoveryInFlightRef.current) {
5541
+ streamRecoveryInFlightRef.current = true;
5542
+ lastStreamRecoveryAtRef.current = now;
5543
+ appendToolUiEvent("ui:stream-recovery", `server seq ${serverLastSeq} is ahead of local seq ${localLastSeq}; reconnecting socket`, serverLastSeq);
5544
+ try {
5545
+ await loadAgent();
5546
+ }
5547
+ catch (loadError) {
5548
+ console.warn("[AgentTerminal] Failed to reload agent during stream recovery", loadError);
5549
+ }
5550
+ try {
5551
+ const socket = globalThis.editorSocket;
5552
+ if (socket && socket.readyState === WebSocket.OPEN) {
5553
+ socket.close(4000, "agent-stream-lag");
5554
+ }
5555
+ }
5556
+ catch (socketError) {
5557
+ console.warn("[AgentTerminal] Failed to reconnect stale agent stream socket", socketError);
5558
+ }
5559
+ finally {
5560
+ window.setTimeout(() => {
5561
+ streamRecoveryInFlightRef.current = false;
5562
+ }, 5_000);
5563
+ }
5505
5564
  }
5506
5565
  }
5507
5566
  catch (error) {
5508
5567
  console.warn("[AgentTerminal] Failed to reconcile agent run status", error);
5568
+ streamRecoveryInFlightRef.current = false;
5509
5569
  }
5510
5570
  };
5511
5571
  // Avoid racing a freshly submitted run before the backend has registered it.
@@ -5522,6 +5582,8 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
5522
5582
  editContext?.socketConnectionVersion,
5523
5583
  isActive,
5524
5584
  isExecuting,
5585
+ appendToolUiEvent,
5586
+ loadAgent,
5525
5587
  settleCompletedRun,
5526
5588
  ]);
5527
5589
  const showInitialThinkingSplash = messages.length === 0 &&