@blade-hq/agent-kit 0.5.16 → 0.5.19

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.
@@ -1491,13 +1491,14 @@ function extractAskAnswers(turns) {
1491
1491
  }
1492
1492
  return answers;
1493
1493
  }
1494
- function registerCreatedSessionState(set, session, mode = DEFAULT_SESSION_MODE) {
1494
+ function registerCreatedSessionState(set, session, mode = DEFAULT_SESSION_MODE, options = {}) {
1495
+ const fresh = options.fresh ?? true;
1495
1496
  useChatStore.getState().setTurns(session.id, []);
1496
1497
  useTaskStore.getState().setTasks(session.id, []);
1497
1498
  set((state) => ({
1498
1499
  sessions: [session, ...state.sessions.filter((item) => item.id !== session.id)],
1499
1500
  modes: { ...state.modes, [session.id]: state.modes[session.id] ?? mode },
1500
- _freshSessions: new Set(state._freshSessions).add(session.id)
1501
+ _freshSessions: fresh ? new Set(state._freshSessions).add(session.id) : new Set([...state._freshSessions].filter((id) => id !== session.id))
1501
1502
  }));
1502
1503
  }
1503
1504
  async function revalidateViewerSessions(existingSessions) {
@@ -1599,8 +1600,8 @@ var useSessionStore = create5()((set, get) => ({
1599
1600
  });
1600
1601
  return session_id;
1601
1602
  },
1602
- registerCreatedSession: (session, mode = DEFAULT_SESSION_MODE) => {
1603
- registerCreatedSessionState(set, session, mode);
1603
+ registerCreatedSession: (session, mode = DEFAULT_SESSION_MODE, options = {}) => {
1604
+ registerCreatedSessionState(set, session, mode, options);
1604
1605
  },
1605
1606
  upsertSession: (session) => {
1606
1607
  set((state) => ({
@@ -2270,6 +2271,9 @@ var AgentSocket = class {
2270
2271
  pendingReplayModes = /* @__PURE__ */ new Map();
2271
2272
  oomNotifiedKeys = /* @__PURE__ */ new Set();
2272
2273
  pendingTurnPatches = /* @__PURE__ */ new Map();
2274
+ joinedSessions = /* @__PURE__ */ new Set();
2275
+ requestedJoins = /* @__PURE__ */ new Set();
2276
+ pendingJoins = /* @__PURE__ */ new Map();
2273
2277
  patchFlushHandle = null;
2274
2278
  patchFlushCancel = null;
2275
2279
  _ensureConnected() {
@@ -2392,6 +2396,7 @@ var AgentSocket = class {
2392
2396
  }
2393
2397
  useChatStore.getState().setStreaming(sessionId, false);
2394
2398
  invalidateContextStats(sessionId);
2399
+ void this._syncSessionTurnsFromHistory(sessionId);
2395
2400
  useRuntimeStore.getState().addEvent(sessionId, {
2396
2401
  type: "chat:end",
2397
2402
  title: status === "paused" ? "Waiting for input" : status === "interrupted" ? "\u8FD0\u884C\u5DF2\u4E2D\u65AD" : status === "failed" ? "Run failed" : "Run completed",
@@ -2578,10 +2583,13 @@ var AgentSocket = class {
2578
2583
  this.socket.on("connect", () => {
2579
2584
  useConnectionStore.getState().markConnected();
2580
2585
  console.log("[agent-socket] connected, id:", this.socket.id);
2586
+ this.joinedSessions.clear();
2587
+ this.requestedJoins.clear();
2588
+ this.pendingJoins.clear();
2581
2589
  const sessionId = this.subscribedSession;
2582
2590
  if (sessionId) {
2583
2591
  useSessionStore.getState().setActiveSession(sessionId);
2584
- this.socket.emit("session:subscribe", { session_id: sessionId });
2592
+ void this._ensureJoined(sessionId);
2585
2593
  }
2586
2594
  });
2587
2595
  this.socket.on("connect_error", (err) => {
@@ -2687,6 +2695,14 @@ var AgentSocket = class {
2687
2695
  detail: OOM_MESSAGE
2688
2696
  });
2689
2697
  }
2698
+ async _syncSessionTurnsFromHistory(sessionId) {
2699
+ try {
2700
+ const turns = await this.client.sessions.getSessionTurns(sessionId);
2701
+ if (turns.length === 0) return;
2702
+ useChatStore.getState().setTurns(sessionId, turns);
2703
+ } catch {
2704
+ }
2705
+ }
2690
2706
  _applySystemNotification(sessionId, loopId, notification) {
2691
2707
  const notificationType = notification.notification_type ?? "system_notification";
2692
2708
  const title = notification.title ?? notificationType;
@@ -2728,7 +2744,7 @@ var AgentSocket = class {
2728
2744
  useUiStore.getState().clearArtifacts();
2729
2745
  useCardStateStore.getState().clearAllStates();
2730
2746
  }
2731
- this.socket.emit("session:subscribe", { session_id: sessionId });
2747
+ void this._ensureJoined(sessionId);
2732
2748
  }
2733
2749
  unsubscribe() {
2734
2750
  const previousSessionId = this.subscribedSession;
@@ -2736,6 +2752,9 @@ var AgentSocket = class {
2736
2752
  this.socket.emit("session:unsubscribe", { session_id: previousSessionId });
2737
2753
  useUiBridgeStore.getState().clearSession(previousSessionId);
2738
2754
  this.subscribedSession = null;
2755
+ this.requestedJoins.delete(previousSessionId);
2756
+ this.joinedSessions.delete(previousSessionId);
2757
+ this.pendingJoins.delete(previousSessionId);
2739
2758
  }
2740
2759
  this.previewArtifactsByToolCall.clear();
2741
2760
  }
@@ -2749,7 +2768,44 @@ var AgentSocket = class {
2749
2768
  * 幂等:后端 session:subscribe handler 只做 enter_room,重复 emit 无副作用。
2750
2769
  */
2751
2770
  attachSession(sessionId) {
2752
- this.socket.emit("session:subscribe", { session_id: sessionId });
2771
+ void this._ensureJoined(sessionId);
2772
+ }
2773
+ _ensureJoined(sessionId) {
2774
+ if (this.joinedSessions.has(sessionId)) {
2775
+ return Promise.resolve();
2776
+ }
2777
+ this.requestedJoins.add(sessionId);
2778
+ const pending = this.pendingJoins.get(sessionId);
2779
+ if (pending) {
2780
+ return pending;
2781
+ }
2782
+ const join = new Promise((resolve, reject) => {
2783
+ this.socket.timeout(5e3).emit(
2784
+ "session:subscribe",
2785
+ { session_id: sessionId },
2786
+ (err, response) => {
2787
+ if (err) {
2788
+ reject(err);
2789
+ return;
2790
+ }
2791
+ if (response && response.ok === false) {
2792
+ reject(new Error(response.message || "Session subscription failed"));
2793
+ return;
2794
+ }
2795
+ if (this.requestedJoins.has(sessionId)) {
2796
+ this.joinedSessions.add(sessionId);
2797
+ }
2798
+ resolve();
2799
+ }
2800
+ );
2801
+ }).finally(() => {
2802
+ this.pendingJoins.delete(sessionId);
2803
+ });
2804
+ this.pendingJoins.set(sessionId, join);
2805
+ return join;
2806
+ }
2807
+ _shouldWaitForJoinBeforeSend(sessionId) {
2808
+ return this.subscribedSession === sessionId || this.joinedSessions.has(sessionId) || this.pendingJoins.has(sessionId) || this.requestedJoins.has(sessionId);
2753
2809
  }
2754
2810
  send(sessionId, message, mode, askuserAnswer, extras) {
2755
2811
  this._ensureConnected();
@@ -2781,7 +2837,7 @@ var AgentSocket = class {
2781
2837
  this.pendingReplayMessages.set(sessionId, message);
2782
2838
  this.pendingReplayModes.set(sessionId, mode);
2783
2839
  }
2784
- this.socket.emit("chat:send", {
2840
+ const payload = {
2785
2841
  session_id: sessionId,
2786
2842
  message,
2787
2843
  mode,
@@ -2789,7 +2845,19 @@ var AgentSocket = class {
2789
2845
  model: extras?.model,
2790
2846
  whatif: extras?.whatif,
2791
2847
  replay_decision: extras?.replay_decision
2792
- });
2848
+ };
2849
+ const sendPayload = () => {
2850
+ this.socket.emit("chat:send", payload);
2851
+ };
2852
+ if (this._shouldWaitForJoinBeforeSend(sessionId)) {
2853
+ void this._ensureJoined(sessionId).then(sendPayload).catch((error) => {
2854
+ useChatStore.getState().setStreaming(sessionId, false);
2855
+ useSessionStore.getState().updateSessionStatus(sessionId, "failed");
2856
+ useChatStore.getState().addErrorMessage(sessionId, error.message || "\u4F1A\u8BDD\u8BA2\u9605\u5931\u8D25\uFF0C\u6D88\u606F\u672A\u53D1\u9001");
2857
+ });
2858
+ } else {
2859
+ sendPayload();
2860
+ }
2793
2861
  const skillId = extractSkillIdForAnalytics(message);
2794
2862
  trackEvent("message_sent", {
2795
2863
  session_id: sessionId,
@@ -3073,4 +3141,4 @@ export {
3073
3141
  bootstrapBladeClient,
3074
3142
  getBootstrappedClient
3075
3143
  };
3076
- //# sourceMappingURL=chunk-CZYQQABG.js.map
3144
+ //# sourceMappingURL=chunk-SPHQXYME.js.map