@blade-hq/agent-kit 1.0.16 → 1.0.18

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.
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  apiFetchResponse,
3
3
  getAuthedUrl
4
- } from "./chunk-QEYZZDLM.js";
4
+ } from "./chunk-TLB4ORQT.js";
5
5
 
6
6
  // src/react/lib/session-file-preview.ts
7
7
  var IMAGE_EXTS = /* @__PURE__ */ new Set(["png", "jpg", "jpeg", "gif", "svg", "webp", "ico", "bmp"]);
@@ -117,4 +117,4 @@ export {
117
117
  resolveTextPreviewType,
118
118
  resolveSessionFilePreviewTarget
119
119
  };
120
- //# sourceMappingURL=chunk-U4KVB5OB.js.map
120
+ //# sourceMappingURL=chunk-MKZ4VTJ2.js.map
@@ -3389,6 +3389,21 @@ function isGisGoalListPayload(value) {
3389
3389
  function isGisResourceListPayload(value) {
3390
3390
  return isRecord4(value) && Array.isArray(value.resources);
3391
3391
  }
3392
+ function sessionStatusFromChatEnd(status) {
3393
+ if (status === "paused") return "waiting_for_input";
3394
+ if (status === "interrupted") return "interrupted";
3395
+ if (status === "failed") return "failed";
3396
+ return "completed";
3397
+ }
3398
+ function extractTerminalChatEndStatus(events) {
3399
+ for (let i = events.length - 1; i >= 0; i--) {
3400
+ const event = events[i];
3401
+ if (event?.type !== "chat:end") continue;
3402
+ const status = event.payload?.status;
3403
+ return typeof status === "string" ? status : "completed";
3404
+ }
3405
+ return null;
3406
+ }
3392
3407
  function isGisTargetListPayload(value) {
3393
3408
  return isRecord4(value) && Array.isArray(value.targets);
3394
3409
  }
@@ -3439,6 +3454,7 @@ var AgentSocket = class {
3439
3454
  joinedSessions = /* @__PURE__ */ new Set();
3440
3455
  requestedJoins = /* @__PURE__ */ new Set();
3441
3456
  pendingJoins = /* @__PURE__ */ new Map();
3457
+ recentChatEndAt = /* @__PURE__ */ new Map();
3442
3458
  boardProjectRefCounts = /* @__PURE__ */ new Map();
3443
3459
  patchFlushHandle = null;
3444
3460
  patchFlushCancel = null;
@@ -3552,7 +3568,8 @@ var AgentSocket = class {
3552
3568
  s.on("turn:events", (data) => {
3553
3569
  const sessionId = this._resolveSessionId(data);
3554
3570
  if (!sessionId || !data.events?.length) return;
3555
- if (!useChatStore.getState().isStreaming[sessionId]) {
3571
+ const terminalChatEndStatus = extractTerminalChatEndStatus(data.events);
3572
+ if (!terminalChatEndStatus && !useChatStore.getState().isStreaming[sessionId]) {
3556
3573
  useSessionStore.getState().updateSessionStatus(sessionId, "running");
3557
3574
  useChatStore.getState().setStreaming(sessionId, true);
3558
3575
  }
@@ -3575,6 +3592,16 @@ var AgentSocket = class {
3575
3592
  notifyWorkspaceFilesChanged(sessionId);
3576
3593
  }
3577
3594
  }
3595
+ if (terminalChatEndStatus) {
3596
+ useSessionStore.getState().updateSessionStatus(sessionId, sessionStatusFromChatEnd(terminalChatEndStatus));
3597
+ if (terminalChatEndStatus === "interrupted") {
3598
+ useChatStore.getState().markInterrupted(sessionId);
3599
+ } else if (terminalChatEndStatus === "failed") {
3600
+ useChatStore.getState().markFailed(sessionId);
3601
+ }
3602
+ useChatStore.getState().setStreaming(sessionId, false);
3603
+ invalidateContextStats(sessionId);
3604
+ }
3578
3605
  });
3579
3606
  s.on("chat:start", (data) => {
3580
3607
  const sessionId = this._resolveSessionId(data);
@@ -3588,16 +3615,14 @@ var AgentSocket = class {
3588
3615
  if (sessionId) {
3589
3616
  this._flushPendingTurnPatches(sessionId);
3590
3617
  const status = data?.status ?? "completed";
3591
- useSessionStore.getState().updateSessionStatus(
3592
- sessionId,
3593
- status === "paused" ? "waiting_for_input" : status === "interrupted" ? "interrupted" : status === "failed" ? "failed" : "completed"
3594
- );
3618
+ useSessionStore.getState().updateSessionStatus(sessionId, sessionStatusFromChatEnd(status));
3595
3619
  if (status === "interrupted") {
3596
3620
  useChatStore.getState().markInterrupted(sessionId);
3597
3621
  } else if (status === "failed") {
3598
3622
  useChatStore.getState().markFailed(sessionId);
3599
3623
  }
3600
3624
  useChatStore.getState().setStreaming(sessionId, false);
3625
+ this.recentChatEndAt.set(sessionId, Date.now());
3601
3626
  invalidateContextStats(sessionId);
3602
3627
  void this._syncSessionTurnsFromHistory(sessionId);
3603
3628
  useRuntimeStore.getState().addEvent(sessionId, {
@@ -3623,6 +3648,7 @@ var AgentSocket = class {
3623
3648
  useSessionStore.getState().setErrorMessage(sessionId, message);
3624
3649
  useChatStore.getState().markFailed(sessionId);
3625
3650
  useChatStore.getState().setStreaming(sessionId, false);
3651
+ this.recentChatEndAt.set(sessionId, Date.now());
3626
3652
  useRuntimeStore.getState().addEvent(sessionId, {
3627
3653
  type: "system:error",
3628
3654
  title: "Runtime error",
@@ -4136,8 +4162,17 @@ var AgentSocket = class {
4136
4162
  _shouldWaitForJoinBeforeSend(sessionId) {
4137
4163
  return this.subscribedSession === sessionId || this.joinedSessions.has(sessionId) || this.pendingJoins.has(sessionId) || this.requestedJoins.has(sessionId);
4138
4164
  }
4139
- send(sessionId, message, mode, askuserAnswer, extras) {
4165
+ async send(sessionId, message, mode, askuserAnswer, extras) {
4140
4166
  this._ensureConnected();
4167
+ if (useChatStore.getState().isStreaming[sessionId]) {
4168
+ useChatStore.getState().addErrorMessage(sessionId, "\u5F53\u524D\u56DE\u590D\u5C1A\u672A\u7ED3\u675F\uFF0C\u8BF7\u7A0D\u540E\u518D\u53D1\u9001\u3002");
4169
+ return;
4170
+ }
4171
+ await this._ensureSessionIdleBeforeSend(sessionId);
4172
+ if (useChatStore.getState().isStreaming[sessionId]) {
4173
+ useChatStore.getState().addErrorMessage(sessionId, "\u5F53\u524D\u56DE\u590D\u5C1A\u672A\u7ED3\u675F\uFF0C\u8BF7\u7A0D\u540E\u518D\u53D1\u9001\u3002");
4174
+ return;
4175
+ }
4141
4176
  if (!(askuserAnswer && typeof askuserAnswer.tool_call_id === "string")) {
4142
4177
  useChatStore.getState().addUserMessage(sessionId, message);
4143
4178
  }
@@ -4194,6 +4229,24 @@ var AgentSocket = class {
4194
4229
  });
4195
4230
  }
4196
4231
  }
4232
+ async _ensureSessionIdleBeforeSend(sessionId) {
4233
+ const lastEndedAt = this.recentChatEndAt.get(sessionId) ?? 0;
4234
+ if (Date.now() - lastEndedAt > 3e3) {
4235
+ return;
4236
+ }
4237
+ const deadline = Date.now() + 3e3;
4238
+ while (Date.now() < deadline) {
4239
+ const response = await this.stop(sessionId);
4240
+ const status = String(response.status ?? "");
4241
+ if (status === "idle" || status === "done" || status === "interrupted") {
4242
+ return;
4243
+ }
4244
+ if (status !== "stopping") {
4245
+ return;
4246
+ }
4247
+ await new Promise((resolve) => globalThis.setTimeout(resolve, 150));
4248
+ }
4249
+ }
4197
4250
  /**
4198
4251
  * 在 agent loop 运行期间追加补充消息。
4199
4252
  * 消息会在下一轮 LLM 调用前以 user-supplement 形式注入。
@@ -4482,4 +4535,4 @@ export {
4482
4535
  bootstrapBladeClient,
4483
4536
  getBootstrappedClient
4484
4537
  };
4485
- //# sourceMappingURL=chunk-QEYZZDLM.js.map
4538
+ //# sourceMappingURL=chunk-TLB4ORQT.js.map