@blade-hq/agent-client 2608.0.5-beta.0 → 2608.0.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.
package/dist/index.js CHANGED
@@ -2,9 +2,6 @@
2
2
  function isAuthCallbackMessage(value) {
3
3
  return typeof value === "object" && value !== null && value.type === "blade-agent:sdk-auth";
4
4
  }
5
- var AUTH_ERROR_HINTS = {
6
- pat_unavailable: "\u6CA1\u80FD\u4E3A\u4F60\u51C6\u5907\u8BBF\u95EE\u51ED\u636E\u3002\u8BF7\u9000\u51FA\u540E\u91CD\u65B0\u767B\u5F55 Blade \u518D\u8BD5\u4E00\u6B21\uFF1B\u82E5\u4ECD\u7136\u5931\u8D25\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u3002"
7
- };
8
5
  function randomState() {
9
6
  const bytes = new Uint8Array(24);
10
7
  crypto.getRandomValues(bytes);
@@ -82,22 +79,18 @@ async function loginWithPopup(client, options = {}) {
82
79
  if (event.data.state !== state) return;
83
80
  const message = event.data;
84
81
  stopCloseWatch();
85
- const closePopup = () => {
86
- try {
87
- popup.close();
88
- } catch {
89
- }
90
- };
82
+ try {
83
+ popup.close();
84
+ } catch {
85
+ }
91
86
  if (message.status === "denied") {
92
- closePopup();
93
87
  settle(() => reject(new Error("\u4F60\u53D6\u6D88\u4E86\u6388\u6743\uFF0C\u672A\u5B8C\u6210\u767B\u5F55\u3002")));
94
88
  return;
95
89
  }
96
90
  if (message.status !== "success" || !message.code) {
97
- settle(() => reject(new Error(AUTH_ERROR_HINTS[message.error ?? ""] ?? message.error ?? "\u767B\u5F55\u5931\u8D25\uFF0C\u672A\u53D6\u5F97\u6388\u6743\u7801\u3002")));
91
+ settle(() => reject(new Error(message.error || "\u767B\u5F55\u5931\u8D25\uFF0C\u672A\u53D6\u5F97\u6388\u6743\u7801\u3002")));
98
92
  return;
99
93
  }
100
- closePopup();
101
94
  client.json("POST", "/api/auth/sdk/token", {
102
95
  code: message.code,
103
96
  state,
@@ -181,24 +174,6 @@ var AuthResource = class {
181
174
  login(options) {
182
175
  return this.client.login(options);
183
176
  }
184
- /**
185
- * 用一次性 code 换 PAT。给**服务端**用:浏览器把 code 交给你自己的后端,
186
- * 后端换到的 PAT 不进浏览器。浏览器里直接用 `login()` 就够了。
187
- *
188
- * 服务端调用时会自己补上 `Origin` 头(浏览器会自动带,服务端不会,缺了
189
- * 后端报 `missing_request_origin`)。
190
- */
191
- exchangeCode(params) {
192
- return this.client.jsonFromInit("/api/auth/sdk/token", {
193
- method: "POST",
194
- headers: { Origin: params.clientOrigin },
195
- body: JSON.stringify({
196
- code: params.code,
197
- state: params.state,
198
- client_origin: params.clientOrigin
199
- })
200
- });
201
- }
202
177
  /** 清除 login() 存储的令牌。 */
203
178
  logoutToken() {
204
179
  this.client.logoutToken();
@@ -350,11 +325,7 @@ var HeadlessResource = class {
350
325
  socket.on("chat:start", onChatStart);
351
326
  socket.on("chat:end", onChatEnd);
352
327
  socket.on("system:error", onSystemError);
353
- socket.emit("session:subscribe", {
354
- session_id,
355
- event_format: "raw",
356
- stream_tokens: this.client.options.streamTokens !== false
357
- });
328
+ socket.emit("session:subscribe", { session_id, event_format: "raw" });
358
329
  socket.emit(
359
330
  "chat:send",
360
331
  {
@@ -436,47 +407,6 @@ var ModelsResource = class {
436
407
  }
437
408
  };
438
409
 
439
- // src/schemas/session.ts
440
- import { type } from "arktype";
441
- var SessionStatus = type(
442
- "'created' | 'running' | 'completed' | 'failed' | 'interrupted' | 'waiting_for_input'"
443
- );
444
- var DEFAULT_REPLAY_SPEED = 5;
445
- var SessionInfo = type({
446
- id: "string",
447
- intent: "string",
448
- status: SessionStatus,
449
- created_at: "string",
450
- updated_at: "string",
451
- "shared?": "boolean",
452
- "memory_enabled?": "boolean",
453
- "is_persistent?": "boolean",
454
- "is_headless?": "boolean",
455
- "viewer_role?": "'owner' | 'viewer'",
456
- "template_id?": "string | null",
457
- "model?": "string | null",
458
- "enable_thinking?": "boolean | null",
459
- "solution_id?": "string | null",
460
- "solution_ref?": "unknown",
461
- "biz_role_id?": "string | null",
462
- "solution?": "unknown",
463
- "plan_summary?": "string | null",
464
- "primary_skill_id?": "string | null",
465
- // ship-attack v2:后端 engine.set_bound_skill 写入的"绑定 skill id"。
466
- // 未绑定 / 非 ship-attack session 为 null。
467
- "bound_skill_id?": "string | null",
468
- "replay_state?": "unknown",
469
- "is_pinned?": "boolean",
470
- "pinned_at?": "string | null",
471
- "is_example?": "boolean",
472
- "ports?": "unknown",
473
- "disable_tools?": "string[]",
474
- "runtime_type?": "string | null",
475
- "daemon_id?": "string | null",
476
- "workspace_path?": "string | null",
477
- "match?": "unknown"
478
- });
479
-
480
410
  // src/session/definition.ts
481
411
  var SessionSetupError = class extends Error {
482
412
  constructor(message, stage, sessionId, options) {
@@ -897,28 +827,6 @@ function sourceLoopFor(loopId, loopDescriptions) {
897
827
  if (!description) return null;
898
828
  return { loop_name: loopId, description };
899
829
  }
900
- var MAX_FINAL_ARTIFACTS = 20;
901
- function normalizeFinalArtifacts(raw) {
902
- if (!Array.isArray(raw)) return [];
903
- const artifacts = [];
904
- const seen = /* @__PURE__ */ new Set();
905
- for (const item of raw) {
906
- if (typeof item !== "object" || item === null) continue;
907
- const record = item;
908
- const target = String(record.target ?? "").trim();
909
- if (!target || seen.has(target)) continue;
910
- const isLink = /^https?:\/\//i.test(target);
911
- if (!isLink && target.split("/").includes("..")) continue;
912
- seen.add(target);
913
- artifacts.push({
914
- kind: isLink ? "link" : "file",
915
- target,
916
- label: String(record.label ?? "").trim()
917
- });
918
- if (artifacts.length === MAX_FINAL_ARTIFACTS) break;
919
- }
920
- return artifacts;
921
- }
922
830
  function normalizePostChatFollowup(data, assistantEntryId) {
923
831
  const raw = data.suggestions;
924
832
  const suggestions = [];
@@ -930,17 +838,11 @@ function normalizePostChatFollowup(data, assistantEntryId) {
930
838
  }
931
839
  }
932
840
  const recaption = String(data.recaption ?? "");
933
- const finalArtifacts = normalizeFinalArtifacts(data.final_artifacts);
934
- const feedbackEligible = data.feedback_eligible === true;
935
- if (suggestions.length === 0 && !recaption && finalArtifacts.length === 0 && !feedbackEligible)
936
- return null;
841
+ if (suggestions.length === 0 && !recaption) return null;
937
842
  return {
938
843
  assistant_entry_id: assistantEntryId,
939
844
  recaption,
940
- suggestions: suggestions.slice(0, 3),
941
- final_artifacts: finalArtifacts,
942
- feedback_eligible: feedbackEligible,
943
- feedback_scope: "latest_result"
845
+ suggestions: suggestions.slice(0, 3)
944
846
  };
945
847
  }
946
848
  function normalizeChildPause(pausePayload) {
@@ -1024,60 +926,11 @@ function toolStatusFromResult(result) {
1024
926
  }
1025
927
 
1026
928
  // src/shared/projection/builder.ts
1027
- function hasChatRunEvent(events) {
1028
- return events.some(
1029
- (event) => event.type !== "session:post_chat_followup" && !event.type.startsWith("compaction:")
1030
- );
1031
- }
1032
- function acceptedPostChatFollowupCompletesLatestRun(events, updates) {
1033
- const acceptedAssistantEntryIds = new Set(
1034
- updates.flatMap((update) => {
1035
- if (update.kind !== "upsert") return [];
1036
- const followup = update.turn.post_chat_followup;
1037
- return followup?.assistant_entry_id ? [followup.assistant_entry_id] : [];
1038
- })
1039
- );
1040
- for (let index = events.length - 1; index >= 0; index -= 1) {
1041
- const event = events[index];
1042
- if (event?.type !== "session:post_chat_followup") continue;
1043
- const assistantEntryId = String(event.payload.assistant_entry_id ?? "");
1044
- return acceptedAssistantEntryIds.has(assistantEntryId) && !hasChatRunEvent(events.slice(index + 1));
1045
- }
1046
- return false;
1047
- }
1048
929
  function isConversationTurn(turn) {
1049
930
  return (turn.role === "user" || turn.role === "assistant") && (turn.kind ?? "message") === "message" && !turn.blocks.some(
1050
931
  (block) => block.type === "mode_change" || block.type === "plan_status" || block.type === "ask_user_answer"
1051
932
  );
1052
933
  }
1053
- function completedResponseText(content) {
1054
- if (typeof content === "string") return content;
1055
- if (!Array.isArray(content)) return content == null ? "" : String(content);
1056
- return content.filter(
1057
- (part) => typeof part === "object" && part !== null && !Array.isArray(part)
1058
- ).filter((part) => part.type === "text").map((part) => String(part.text ?? "")).join("");
1059
- }
1060
- function replaceTextContent(state, content) {
1061
- if (state.blocks.some((block) => block.type === "text")) return;
1062
- const replacement = { type: "text", content };
1063
- const blocks = [];
1064
- let inserted = false;
1065
- for (const block of state.blocks) {
1066
- if (block.type === "text") {
1067
- if (content && !inserted) {
1068
- blocks.push(replacement);
1069
- inserted = true;
1070
- }
1071
- continue;
1072
- }
1073
- blocks.push(block);
1074
- }
1075
- if (content && !inserted) {
1076
- const toolIndex = blocks.findIndex((block) => block.type === "tool_use");
1077
- blocks.splice(toolIndex < 0 ? blocks.length : toolIndex, 0, replacement);
1078
- }
1079
- state.blocks = blocks;
1080
- }
1081
934
  var ClientProjectionBuilder = class {
1082
935
  activeTurns = /* @__PURE__ */ new Map();
1083
936
  lastTurnIds = /* @__PURE__ */ new Map();
@@ -1160,9 +1013,6 @@ var ClientProjectionBuilder = class {
1160
1013
  return this.onDelta(state, "thinking", "", String(payload.content ?? ""));
1161
1014
  case "llm:content:delta":
1162
1015
  return this.onDelta(state, "text", "", String(payload.content ?? ""));
1163
- case "llm:content:complete":
1164
- replaceTextContent(state, String(payload.content ?? ""));
1165
- return this.syncPatch(state);
1166
1016
  case "llm:tool_call:created":
1167
1017
  return this.onToolCallCreated(state, payload);
1168
1018
  case "llm:response:done":
@@ -1452,9 +1302,6 @@ var ClientProjectionBuilder = class {
1452
1302
  if (typeof payload.usage === "object" && payload.usage !== null) {
1453
1303
  state.usage = { ...payload.usage };
1454
1304
  }
1455
- if ("content" in payload) {
1456
- replaceTextContent(state, completedResponseText(payload.content));
1457
- }
1458
1305
  const toolCalls = payload.tool_calls;
1459
1306
  if (Array.isArray(toolCalls)) {
1460
1307
  for (const raw of toolCalls) {
@@ -2258,11 +2105,6 @@ var SessionsResource = class {
2258
2105
  listSessionsWithSkillData() {
2259
2106
  return this.client.json("GET", "/api/sessions/with-skill-data");
2260
2107
  }
2261
- searchOwnedContent(params) {
2262
- const searchParams = new URLSearchParams({ q: params.q.trim() });
2263
- if (params.limit !== void 0) searchParams.set("limit", String(params.limit));
2264
- return this.client.json("GET", `/api/search?${searchParams.toString()}`);
2265
- }
2266
2108
  createSession(intent, template_id, primary_skill_id) {
2267
2109
  return this.createSessionWithRequest({ intent, template_id, primary_skill_id });
2268
2110
  }
@@ -2288,16 +2130,12 @@ var SessionsResource = class {
2288
2130
  pinSession(sessionId, pinned) {
2289
2131
  return this.client.json("PATCH", `/api/sessions/${sessionId}/pin`, { pinned });
2290
2132
  }
2291
- startReplaySession(sourceSessionId, speed = DEFAULT_REPLAY_SPEED) {
2133
+ startReplaySession(sourceSessionId, speed = 5) {
2292
2134
  return this.client.json("POST", `/api/sessions/${sourceSessionId}/replay`, { speed });
2293
2135
  }
2294
2136
  updateReplaySession(sessionId, payload) {
2295
2137
  return this.client.json("PATCH", `/api/sessions/${sessionId}/replay`, payload);
2296
2138
  }
2297
- /** 查询会话能否作为回放来源;不支持时 reason 可直接展示,用来提前禁用入口。 */
2298
- getReplayPreview(sessionId) {
2299
- return this.client.json("GET", `/api/sessions/${sessionId}/replay/preview`);
2300
- }
2301
2139
  updateSharing(sessionId, shared) {
2302
2140
  return this.client.json("PATCH", `/api/sessions/${sessionId}/sharing`, { shared });
2303
2141
  }
@@ -2329,16 +2167,6 @@ var SessionsResource = class {
2329
2167
  );
2330
2168
  return projectHistory(entries);
2331
2169
  }
2332
- listResultFeedback(sessionId) {
2333
- return this.client.json("GET", `/api/sessions/${encodeURIComponent(sessionId)}/feedback`);
2334
- }
2335
- putResultFeedback(sessionId, assistantEntryId, feedback) {
2336
- return this.client.json(
2337
- "PUT",
2338
- `/api/sessions/${encodeURIComponent(sessionId)}/turns/${encodeURIComponent(assistantEntryId)}/feedback`,
2339
- feedback
2340
- );
2341
- }
2342
2170
  getSessionContextStats(sessionId, init) {
2343
2171
  return this.client.jsonFromInit(`/api/sessions/${sessionId}/context-stats`, init);
2344
2172
  }
@@ -2761,15 +2589,10 @@ function contentPreview(content, maxLen = 80) {
2761
2589
  const text = getTextContent(content).trim();
2762
2590
  return text.length > maxLen ? `${text.slice(0, maxLen)}\u2026` : text;
2763
2591
  }
2764
- function transformSlashCommand(skillName, rawInput, { local = true, installed = true } = {}) {
2592
+ function transformSlashCommand(skillName, rawInput) {
2765
2593
  const prompt = rawInput.replace(`<skill>${skillName}</skill>`, "").trim();
2766
- if (local) {
2767
- return prompt ? `\u8BF7\u4F7F\u7528 ${skillName} skill \u5B8C\u6210\u4EFB\u52A1
2594
+ return prompt ? `\u8BF7\u4F7F\u7528 ${skillName} skill \u5B8C\u6210\u4EFB\u52A1
2768
2595
  ${prompt}` : `\u8BF7\u4F7F\u7528 ${skillName} skill \u5B8C\u6210\u4EFB\u52A1`;
2769
- }
2770
- const steps = installed ? `\u8BF7\u5148\u8FD0\u884C blade hub skill use ${skillName} \u52A0\u8F7D\u6280\u80FD` : `\u8BE5\u6280\u80FD\u5C1A\u672A\u5B89\u88C5\u3002\u8BF7\u5148\u8FD0\u884C blade hub skill install ${skillName} \u5B89\u88C5\uFF0C\u518D\u8FD0\u884C blade hub skill use ${skillName} \u52A0\u8F7D`;
2771
- return prompt ? `${steps}\uFF0C\u7136\u540E\u5B8C\u6210\u4EFB\u52A1\uFF1A
2772
- ${prompt}` : `${steps}\uFF0C\u7136\u540E\u4F7F\u7528\u5B83\u5B8C\u6210\u4EFB\u52A1`;
2773
2596
  }
2774
2597
  var ATTACHMENT_TAG_RE = /\[附件:\s*([^\]]+)\](?:[ \t]*已上传到工作区路径:[ \t]*([^\r\n]+))?/g;
2775
2598
  var CONTEXT_PART_RE = /^\[上下文:\s*([^\]]+)\]\n([\s\S]*)$/;
@@ -2855,14 +2678,6 @@ function groupMessagesByLoop(messages) {
2855
2678
  }
2856
2679
 
2857
2680
  // src/session/state.ts
2858
- function toReplaySnapshot(raw) {
2859
- if (!raw || !raw.status) return null;
2860
- return {
2861
- isReplay: raw.status === "replay",
2862
- speed: raw.speed ?? 1,
2863
- sourceSessionId: raw.source_session_id ?? null
2864
- };
2865
- }
2866
2681
  function createInitialSessionState(sessionId) {
2867
2682
  return {
2868
2683
  sessionId,
@@ -2875,9 +2690,7 @@ function createInitialSessionState(sessionId) {
2875
2690
  errorMessage: null,
2876
2691
  askAnswers: {},
2877
2692
  agentLoops: {},
2878
- activeCompaction: null,
2879
- replay: null,
2880
- viewerRole: null
2693
+ activeCompaction: null
2881
2694
  };
2882
2695
  }
2883
2696
  function parseAgentDescription(argumentsJson) {
@@ -3307,7 +3120,7 @@ function extractTerminalChatEndStatus(events) {
3307
3120
  }
3308
3121
  return null;
3309
3122
  }
3310
- function hasChatRunEvent2(events) {
3123
+ function hasChatRunEvent(events) {
3311
3124
  return events.some(
3312
3125
  (event) => event.type !== "session:post_chat_followup" && !event.type.startsWith("compaction:")
3313
3126
  );
@@ -3328,11 +3141,6 @@ var AgentSession = class _AgentSession {
3328
3141
  patchFlushCancel = null;
3329
3142
  joined = false;
3330
3143
  joinPending = null;
3331
- // 回放控制请求排成一条队列。连着点"5x"再点"退出回放"时,并发发出去的两个
3332
- // 请求响应可能乱序回来,晚到的旧值会把已经退出的会话又显示成回放中;用
3333
- // 序号丢弃过期响应又会在失败时留下中间态。串行执行就没有这些情况:每个
3334
- // 响应都是当时最新的,失败也只影响自己。
3335
- replayQueue = Promise.resolve();
3336
3144
  pendingReplayMessage = null;
3337
3145
  pendingReplayMode;
3338
3146
  recentChatEndAt = 0;
@@ -3359,15 +3167,10 @@ var AgentSession = class _AgentSession {
3359
3167
  const session = new _AgentSession(
3360
3168
  sessionId,
3361
3169
  {
3362
- streamTokens: false,
3363
3170
  emitEvent: readonlyError,
3364
3171
  emitWithAck: async () => readonlyError(),
3365
3172
  ensureConnected: readonlyError,
3366
3173
  fetchTurns: async () => turns,
3367
- // 静态历史没有回放身份可言,给个空详情即可,不要抛错——_bootstrap
3368
- // 不会跑到这里,但保持只读语义一致。
3369
- fetchSessionInfo: async () => ({ replay_state: null }),
3370
- updateReplay: async () => readonlyError(),
3371
3174
  listDir: async () => readonlyError(),
3372
3175
  countFiles: async () => readonlyError(),
3373
3176
  downloadFile: async () => readonlyError(),
@@ -3659,13 +3462,10 @@ var AgentSession = class _AgentSession {
3659
3462
  this.joinPending = null;
3660
3463
  try {
3661
3464
  await this.ensureJoined();
3662
- await Promise.all([
3663
- this.syncTurnsFromHistory({
3664
- clearOnEmpty: true,
3665
- preserveChangesSince: turnsBeforeRejoin
3666
- }),
3667
- this.syncReplayFromSession()
3668
- ]);
3465
+ await this.syncTurnsFromHistory({
3466
+ clearOnEmpty: true,
3467
+ preserveChangesSince: turnsBeforeRejoin
3468
+ });
3669
3469
  } catch {
3670
3470
  }
3671
3471
  }
@@ -3673,40 +3473,6 @@ var AgentSession = class _AgentSession {
3673
3473
  async _bootstrap() {
3674
3474
  await this.syncTurnsFromHistory({ suppressErrors: false });
3675
3475
  await this.ensureJoined();
3676
- await this.syncReplayFromSession();
3677
- }
3678
- /** 改回放是 owner 专属(服务端 PATCH 走 _get_owned_session)。 */
3679
- get canControlReplay() {
3680
- return this.state.viewerRole !== "viewer";
3681
- }
3682
- /** 拉一次会话详情,填回放状态和只读身份;失败按非回放会话处理,不挡启动。 */
3683
- async syncReplayFromSession() {
3684
- try {
3685
- const info = await this.runtime.fetchSessionInfo(this.sessionId);
3686
- const replay = toReplaySnapshot(info.replay_state);
3687
- const viewerRole = info.viewer_role ?? null;
3688
- this.update((s) => ({ ...s, replay, viewerRole }));
3689
- } catch {
3690
- }
3691
- }
3692
- /** 调整回放倍速;不是回放会话、或只读身份时什么都不做。 */
3693
- async setReplaySpeed(speed) {
3694
- if (!this.state.replay?.isReplay || !this.canControlReplay) return;
3695
- await this.applyReplayControl({ speed });
3696
- }
3697
- /** 退出回放,之后的对话交给真实模型运行;不是回放会话、或只读身份时什么都不做。 */
3698
- async exitReplay() {
3699
- if (!this.state.replay?.isReplay || !this.canControlReplay) return;
3700
- await this.applyReplayControl({ status: "autonomous" });
3701
- }
3702
- /** 把一次回放控制请求排进队列;前一个完成后才发出,响应直接安装。 */
3703
- applyReplayControl(payload) {
3704
- const run = this.replayQueue.then(async () => {
3705
- const result = await this.runtime.updateReplay(this.sessionId, payload);
3706
- this.update((s) => ({ ...s, replay: toReplaySnapshot(result) }));
3707
- });
3708
- this.replayQueue = run.catch(() => void 0);
3709
- return run;
3710
3476
  }
3711
3477
  /** @internal */
3712
3478
  _handleTurnStart(turn) {
@@ -3733,7 +3499,7 @@ var AgentSession = class _AgentSession {
3733
3499
  _handleTurnEvents(events) {
3734
3500
  if (!events.length) return;
3735
3501
  const terminalChatEndStatus = extractTerminalChatEndStatus(events);
3736
- if (!terminalChatEndStatus && hasChatRunEvent2(events)) {
3502
+ if (!terminalChatEndStatus && hasChatRunEvent(events)) {
3737
3503
  this.markRunningIfIdle();
3738
3504
  }
3739
3505
  if (this.state.turns.length) {
@@ -3747,8 +3513,8 @@ var AgentSession = class _AgentSession {
3747
3513
  this.emitter.emit("workspaceChanged", {});
3748
3514
  }
3749
3515
  }
3750
- if (terminalChatEndStatus || acceptedPostChatFollowupCompletesLatestRun(events, updates)) {
3751
- this.completeChat(terminalChatEndStatus ?? "completed");
3516
+ if (terminalChatEndStatus) {
3517
+ this.finishStreaming(terminalChatEndStatus);
3752
3518
  }
3753
3519
  }
3754
3520
  /** @internal */
@@ -3758,7 +3524,10 @@ var AgentSession = class _AgentSession {
3758
3524
  /** @internal */
3759
3525
  _handleChatEnd(status) {
3760
3526
  this.flushPatches();
3761
- this.completeChat(status);
3527
+ this.finishStreaming(status);
3528
+ this.recentChatEndAt = Date.now();
3529
+ void this.syncTurnsFromHistory();
3530
+ this.emitter.emit("chatEnd", { status });
3762
3531
  }
3763
3532
  /** @internal */
3764
3533
  _handleSystemError(message) {
@@ -3783,10 +3552,6 @@ var AgentSession = class _AgentSession {
3783
3552
  if (data.status) {
3784
3553
  this.update((s) => ({ ...s, status: data.status ?? s.status }));
3785
3554
  }
3786
- if (data.replay_state !== void 0) {
3787
- const replay = toReplaySnapshot(data.replay_state);
3788
- this.update((s) => ({ ...s, replay }));
3789
- }
3790
3555
  this.emitter.emit("sessionUpdated", {
3791
3556
  intent: data.intent,
3792
3557
  status: data.status,
@@ -3902,12 +3667,6 @@ var AgentSession = class _AgentSession {
3902
3667
  return next;
3903
3668
  });
3904
3669
  }
3905
- completeChat(status) {
3906
- this.finishStreaming(status);
3907
- this.recentChatEndAt = Date.now();
3908
- void this.syncTurnsFromHistory();
3909
- this.emitter.emit("chatEnd", { status });
3910
- }
3911
3670
  applyTurn(turn) {
3912
3671
  this.flushPatches();
3913
3672
  const previous = this.state;
@@ -4090,12 +3849,7 @@ var AgentSession = class _AgentSession {
4090
3849
  if (this.joinPending) return this.joinPending;
4091
3850
  const join = this.runtime.emitWithAck(
4092
3851
  "session:subscribe",
4093
- {
4094
- session_id: this.sessionId,
4095
- event_format: "raw",
4096
- resume: true,
4097
- stream_tokens: this.runtime.streamTokens
4098
- },
3852
+ { session_id: this.sessionId, event_format: "raw", resume: true },
4099
3853
  5e3
4100
3854
  ).then((response) => {
4101
3855
  if (response && response.ok === false) {
@@ -4231,7 +3985,6 @@ var SessionHub = class {
4231
3985
  }
4232
3986
  runtimeFor() {
4233
3987
  return {
4234
- streamTokens: this.client.options?.streamTokens !== false,
4235
3988
  emitEvent: (event, data) => {
4236
3989
  ;
4237
3990
  this.client.socket().emit(event, data);
@@ -4248,8 +4001,6 @@ var SessionHub = class {
4248
4001
  }),
4249
4002
  ensureConnected: () => this.ensureConnected(),
4250
4003
  fetchTurns: (sessionId) => this.client.sessions.getSessionTurns(sessionId),
4251
- fetchSessionInfo: (sessionId) => this.client.sessions.getSession(sessionId),
4252
- updateReplay: (sessionId, payload) => this.client.sessions.updateReplaySession(sessionId, payload).then((result) => result.replay_state ?? null),
4253
4004
  listDir: (sessionId, dirPath) => this.client.sessions.listDir(sessionId, dirPath),
4254
4005
  countFiles: (sessionId, dirPath) => this.client.sessions.countFiles(sessionId, dirPath),
4255
4006
  downloadFile: (sessionId, filePath, downloadName) => this.client.sessions.downloadFile(sessionId, filePath, downloadName),
@@ -4471,7 +4222,7 @@ function resolveAuthToken(options) {
4471
4222
 
4472
4223
  // src/version.ts
4473
4224
  var SDK_NAME = "agent-client";
4474
- var SDK_VERSION = true ? "2608.0.5-beta.0" : "1.1.1";
4225
+ var SDK_VERSION = true ? "2608.0.5" : "1.1.1";
4475
4226
 
4476
4227
  // src/socket.ts
4477
4228
  function withSdkIdentity(auth) {
@@ -4923,18 +4674,45 @@ function connectEmbedded(options) {
4923
4674
  };
4924
4675
  }
4925
4676
 
4926
- // src/schemas/projection-utils.ts
4927
- function latestPostChatFollowup(turns) {
4928
- for (let index = turns.length - 1; index >= 0; index -= 1) {
4929
- const turn = turns[index];
4930
- if (turn.loop_id === "root" && (turn.role === "user" || turn.role === "assistant") && (turn.kind ?? "message") === "message" && !turn.blocks.some(
4931
- (block) => ["mode_change", "plan_status", "ask_user_answer"].includes(block.type)
4932
- )) {
4933
- return turn.role === "assistant" ? turn.post_chat_followup ?? null : null;
4934
- }
4935
- }
4936
- return null;
4937
- }
4677
+ // src/schemas/session.ts
4678
+ import { type } from "arktype";
4679
+ var SessionStatus = type(
4680
+ "'created' | 'running' | 'completed' | 'failed' | 'interrupted' | 'waiting_for_input'"
4681
+ );
4682
+ var SessionInfo = type({
4683
+ id: "string",
4684
+ intent: "string",
4685
+ status: SessionStatus,
4686
+ created_at: "string",
4687
+ updated_at: "string",
4688
+ "shared?": "boolean",
4689
+ "memory_enabled?": "boolean",
4690
+ "is_persistent?": "boolean",
4691
+ "is_headless?": "boolean",
4692
+ "viewer_role?": "'owner' | 'viewer'",
4693
+ "template_id?": "string | null",
4694
+ "model?": "string | null",
4695
+ "enable_thinking?": "boolean | null",
4696
+ "solution_id?": "string | null",
4697
+ "solution_ref?": "unknown",
4698
+ "biz_role_id?": "string | null",
4699
+ "solution?": "unknown",
4700
+ "plan_summary?": "string | null",
4701
+ "primary_skill_id?": "string | null",
4702
+ // ship-attack v2:后端 engine.set_bound_skill 写入的"绑定 skill id"。
4703
+ // 未绑定 / 非 ship-attack session 为 null。
4704
+ "bound_skill_id?": "string | null",
4705
+ "replay_state?": "unknown",
4706
+ "is_pinned?": "boolean",
4707
+ "pinned_at?": "string | null",
4708
+ "is_example?": "boolean",
4709
+ "ports?": "unknown",
4710
+ "disable_tools?": "string[]",
4711
+ "runtime_type?": "string | null",
4712
+ "daemon_id?": "string | null",
4713
+ "workspace_path?": "string | null",
4714
+ "match?": "unknown"
4715
+ });
4938
4716
 
4939
4717
  // src/schemas/solution.ts
4940
4718
  var LayoutType = /* @__PURE__ */ ((LayoutType2) => {
@@ -4967,7 +4745,6 @@ export {
4967
4745
  BladeApiError,
4968
4746
  BladeClient,
4969
4747
  ClientProjectionBuilder,
4970
- DEFAULT_REPLAY_SPEED,
4971
4748
  LayoutType,
4972
4749
  ModelsResource,
4973
4750
  SDK_NAME,
@@ -4978,7 +4755,6 @@ export {
4978
4755
  SessionStatus,
4979
4756
  Task,
4980
4757
  TaskStatus,
4981
- acceptedPostChatFollowupCompletesLatestRun,
4982
4758
  buildMessageContent,
4983
4759
  connectEmbedded,
4984
4760
  contentPreview,
@@ -4992,9 +4768,7 @@ export {
4992
4768
  isCommandEnvelope,
4993
4769
  isHiddenInternalMessage,
4994
4770
  isInboundEnvelope,
4995
- latestPostChatFollowup,
4996
4771
  normalizeMessageContent,
4997
- toReplaySnapshot,
4998
4772
  transformSlashCommand
4999
4773
  };
5000
4774
  //# sourceMappingURL=index.js.map