@blade-hq/agent-client 2610.0.0-beta.1 → 2610.0.1-alpha.1

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/README.md CHANGED
@@ -56,7 +56,6 @@ new BladeClient({
56
56
  baseUrl: "https://blade.example.com", // 后端地址;同域部署可传 ""
57
57
  token: "sk-blade-xxx", // 可选:PAT。不传则用 cookie 或 login()
58
58
  tokenStorage: "local", // 可选:login() 的令牌存哪("local" 默认 / "memory")
59
- streamTokens: false, // 可选:只接收完成态内容,不订阅逐 token 增量
60
59
  })
61
60
  ```
62
61
 
@@ -134,7 +133,6 @@ Solution 和 Skill 都声明为 `{ path, content }[]` 文本文件;SDK 负责
134
133
 
135
134
  ```ts
136
135
  await client.sessions.listSessions() // 会话列表
137
- await client.sessions.searchOwnedContent({ q: "项目报告" }) // 搜索自己的对话和文件名
138
136
  await client.sessions.getSession(id) // 会话详情
139
137
  await client.sessions.updateSession(id, { intent: "新标题" })
140
138
  await client.sessions.deleteSession(id)
@@ -226,18 +224,6 @@ await chat.countFiles() // 递归统计,不含目录
226
224
  await chat.downloadFile("输出/简历.md", "简历.md") // 浏览器下载
227
225
  ```
228
226
 
229
- 对符合评价条件的最新整体结果,可读取或更新当前用户的反馈:
230
-
231
- ```ts
232
- const feedback = await client.sessions.listResultFeedback(id)
233
- await client.sessions.putResultFeedback(id, assistantEntryId, {
234
- helpful: false,
235
- reason: "incomplete",
236
- })
237
- ```
238
-
239
- `ResultFeedbackReason` 是固定枚举;Server 会校验结果资格、写权限,并自行推导 Chat / 软件工厂场景和项目 ID。
240
-
241
227
  ### 模型目录
242
228
 
243
229
  ```ts
@@ -516,11 +502,11 @@ transformSlashCommand(skillId, prompt, { local: false, installed: false })
516
502
  - **SDK 身份**:`SDK_NAME`、`SDK_VERSION`
517
503
  - **声明式会话**:`SessionDefinition`、`SolutionDefinition`、`SkillDefinition`、`SessionConfig`、`TextFile`、`SessionSetupError`、`SessionSetupStage`
518
504
  - **模型目录**:`ModelsResource`、`ModelCatalog`、`ModelOption`
519
- - **会话资源(REST)**:`SessionsResource`、`CreateSessionRequest`、`ImportSessionOptions`、`AppCliDefinition`、`AppCliAttachment`、`AttachAppOptions`、`PaginatedSessionsResult`、`GlobalSearchResult`、`GlobalSearchResultItem`、`GlobalSearchConversationResult`、`GlobalSearchFileResult`、`SessionHistory`、`SessionContextStats`、`ResultFeedback`、`ResultFeedbackReason`、`ShareLinkResult`、`FileEntry`、`UploadFileEntry`、`UploadFilesOptions`、`SessionProfile`、`SessionDetail`、`SessionInfo`、`SessionStatus`、`SessionPortMapping`、`ModeId`、`TemplateId`、`PrimarySkillSnapshot`、`PrimarySkillParallelMode`
505
+ - **会话资源(REST)**:`SessionsResource`、`CreateSessionRequest`、`ImportSessionOptions`、`AppCliDefinition`、`AppCliAttachment`、`AttachAppOptions`、`PaginatedSessionsResult`、`SessionHistory`、`SessionContextStats`、`ShareLinkResult`、`FileEntry`、`UploadFileEntry`、`UploadFilesOptions`、`SessionProfile`、`SessionDetail`、`SessionInfo`、`SessionStatus`、`SessionPortMapping`、`ModeId`、`TemplateId`、`PrimarySkillSnapshot`、`PrimarySkillParallelMode`
520
506
  - **会话回放**:`ReplayState`、`ReplaySpeed`、`ReplayPreview`、`ReplaySnapshot`、`toReplaySnapshot`、`DEFAULT_REPLAY_SPEED`
521
507
  - **会话状态机**:`SessionHub`、`SessionState`、`SendOptions`、`ConnectionStatus`、`AskUserAnswerData`、`AgentLoopInfo`、`ActiveCompactionState`、`createInitialSessionState`、`AgentSessionEventName`
522
508
  - **页面协作**:`EmbeddedChat`、`EmbeddedChatOptions`、`CommandHandler`、`CommandEnvelope`、`InboundAction`、`InboundEnvelope`、`isCommandEnvelope`、`isInboundEnvelope`
523
- - **消息与投影协议**:`MessageContent`、`MessageContentPart`、`TextContentPart`、`ImageUrlContentPart`、`FileContentPart`、`ToolCallInfo`、`ToolBridgeContent`、`CompactionInfo`、`MemoryRefInfo`、`ArchivedFileInfo`、`ArchivedToolCallInfo`、`TurnProjection`、`ContentBlock`、`PatchEnvelope`、`MemoryRef`、`PostChatFollowup`、`FinalArtifact`、`latestPostChatFollowup`、`buildMessageContent`、`normalizeMessageContent`、`isHiddenInternalMessage`、`transformSlashCommand`、`SkillMentionAvailability`、`extractTextAttachments`、`ParsedTextAttachment`、`ParsedTextContext`
509
+ - **消息与投影协议**:`MessageContent`、`MessageContentPart`、`TextContentPart`、`ImageUrlContentPart`、`FileContentPart`、`ToolCallInfo`、`ToolBridgeContent`、`CompactionInfo`、`MemoryRefInfo`、`ArchivedFileInfo`、`ArchivedToolCallInfo`、`TurnProjection`、`ContentBlock`、`PatchEnvelope`、`MemoryRef`、`buildMessageContent`、`normalizeMessageContent`、`isHiddenInternalMessage`、`transformSlashCommand`、`SkillMentionAvailability`、`extractTextAttachments`、`ParsedTextAttachment`、`ParsedTextContext`
524
510
  - **Solution / 任务协议**:`Solution`、`SolutionAppField`、`SolutionAppState`、`SolutionAppUiConfig`、`SolutionRef`、`PublishedSolutionRef`、`ExistingSolutionRef`、`PreparedSolution`、`PreparedSolutionAsset`、`LayoutType`、`BizRole`、`TaskStatus`、`BackgroundTask`、`BackgroundTaskStopResult`
525
511
  - **Headless**:`HeadlessResource`、`RunOptions`、`RunResult`、`RunTrace`
526
- - **低层通道(apps/web 等高级集成)**:`createSocket`、`CreateSocketOptions`、`TypedSocket`、`AsrAudioPayload`、`ClientProjectionBuilder`、`RawEvent`、`acceptedPostChatFollowupCompletesLatestRun`
512
+ - **低层通道(apps/web 等高级集成)**:`createSocket`、`CreateSocketOptions`、`TypedSocket`、`AsrAudioPayload`、`ClientProjectionBuilder`、`RawEvent`
@@ -23,8 +23,6 @@ export interface BladeClientOptions {
23
23
  tokenStorage?: TokenStorageMode;
24
24
  fetchImpl?: typeof fetch;
25
25
  onRefreshSuccess?: () => void | Promise<void>;
26
- /** 是否订阅逐 token 增量,默认 true。关闭后仍接收完整消息和语义事件。 */
27
- streamTokens?: boolean;
28
26
  }
29
27
  export declare class BladeClient {
30
28
  private refreshPromise;
package/dist/index.d.ts CHANGED
@@ -21,12 +21,11 @@ export type { HeadlessResource } from "./resources/headless";
21
21
  export { ModelsResource } from "./resources/models";
22
22
  export type { ModelCatalog, ModelOption } from "./resources/models";
23
23
  export type { SessionsResource } from "./resources/sessions";
24
- export type { CreateSessionRequest, AppCliAttachment, AppCliDefinition, FileEntry, ImportSessionOptions, PaginatedSessionsResult, GlobalSearchConversationResult, GlobalSearchFileResult, GlobalSearchResult, GlobalSearchResultItem, ResultFeedback, ResultFeedbackReason, SessionContextStats, SessionHistory, ShareLinkResult, UploadFileEntry, UploadFilesOptions, } from "./resources/sessions";
24
+ export type { CreateSessionRequest, AppCliAttachment, AppCliDefinition, FileEntry, ImportSessionOptions, PaginatedSessionsResult, SessionContextStats, SessionHistory, ShareLinkResult, UploadFileEntry, UploadFilesOptions, } from "./resources/sessions";
25
25
  export type { ArchivedFileInfo, ArchivedToolCallInfo, ChatMessage, CompactionInfo, FileContentPart, ImageUrlContentPart, MemoryRefInfo, MessageContent, MessageContentPart, TextContentPart, ToolBridgeContent, ToolCallInfo, } from "./schemas/message";
26
26
  export { buildMessageContent, contentPreview, extractTextAttachments, getFileParts, getImageParts, getTextContent, groupMessagesByLoop, isHiddenInternalMessage, normalizeMessageContent, transformSlashCommand, } from "./schemas/message-utils";
27
27
  export type { ParsedTextAttachment, ParsedTextContext, SkillMentionAvailability, } from "./schemas/message-utils";
28
- export type { ContentBlock, FinalArtifact, MemoryRef, PatchEnvelope, PostChatFollowup, TurnProjection, } from "./schemas/projection";
29
- export { latestPostChatFollowup } from "./schemas/projection-utils";
28
+ export type { ContentBlock, MemoryRef, PatchEnvelope, TurnProjection } from "./schemas/projection";
30
29
  export { DEFAULT_REPLAY_SPEED } from "./schemas/session";
31
30
  export { SessionInfo, SessionStatus } from "./schemas/session";
32
31
  export type { ModeId, PrimarySkillParallelMode, PrimarySkillSnapshot, ReplayPreview, ReplaySpeed, ReplayState, SessionDetail, SessionPortMapping, PublishedSolutionRef, TemplateId, } from "./schemas/session";
@@ -34,7 +33,7 @@ export { LayoutType } from "./schemas/solution";
34
33
  export type { BizRole, Solution, SolutionAppField, SolutionAppState, SolutionAppUiConfig, } from "./schemas/solution";
35
34
  export { Task, TaskStatus } from "./schemas/task";
36
35
  export type { BackgroundTask, BackgroundTaskStopResult } from "./schemas/background";
37
- export { acceptedPostChatFollowupCompletesLatestRun, ClientProjectionBuilder } from "./shared/projection";
36
+ export { ClientProjectionBuilder } from "./shared/projection";
38
37
  export type { RawEvent } from "./shared/projection";
39
38
  export { createSocket } from "./socket";
40
39
  export type { CreateSocketOptions, TypedSocket } from "./socket";
package/dist/index.js CHANGED
@@ -350,11 +350,7 @@ var HeadlessResource = class {
350
350
  socket.on("chat:start", onChatStart);
351
351
  socket.on("chat:end", onChatEnd);
352
352
  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
- });
353
+ socket.emit("session:subscribe", { session_id, event_format: "raw" });
358
354
  socket.emit(
359
355
  "chat:send",
360
356
  {
@@ -897,7 +893,7 @@ function sourceLoopFor(loopId, loopDescriptions) {
897
893
  if (!description) return null;
898
894
  return { loop_name: loopId, description };
899
895
  }
900
- var MAX_FINAL_ARTIFACTS = 20;
896
+ var MAX_FINAL_ARTIFACTS = 3;
901
897
  function normalizeFinalArtifacts(raw) {
902
898
  if (!Array.isArray(raw)) return [];
903
899
  const artifacts = [];
@@ -931,16 +927,12 @@ function normalizePostChatFollowup(data, assistantEntryId) {
931
927
  }
932
928
  const recaption = String(data.recaption ?? "");
933
929
  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;
930
+ if (suggestions.length === 0 && !recaption && finalArtifacts.length === 0) return null;
937
931
  return {
938
932
  assistant_entry_id: assistantEntryId,
939
933
  recaption,
940
934
  suggestions: suggestions.slice(0, 3),
941
- final_artifacts: finalArtifacts,
942
- feedback_eligible: feedbackEligible,
943
- feedback_scope: "latest_result"
935
+ final_artifacts: finalArtifacts
944
936
  };
945
937
  }
946
938
  function normalizeChildPause(pausePayload) {
@@ -1024,60 +1016,11 @@ function toolStatusFromResult(result) {
1024
1016
  }
1025
1017
 
1026
1018
  // 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
1019
  function isConversationTurn(turn) {
1049
1020
  return (turn.role === "user" || turn.role === "assistant") && (turn.kind ?? "message") === "message" && !turn.blocks.some(
1050
1021
  (block) => block.type === "mode_change" || block.type === "plan_status" || block.type === "ask_user_answer"
1051
1022
  );
1052
1023
  }
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
1024
  var ClientProjectionBuilder = class {
1082
1025
  activeTurns = /* @__PURE__ */ new Map();
1083
1026
  lastTurnIds = /* @__PURE__ */ new Map();
@@ -1160,9 +1103,6 @@ var ClientProjectionBuilder = class {
1160
1103
  return this.onDelta(state, "thinking", "", String(payload.content ?? ""));
1161
1104
  case "llm:content:delta":
1162
1105
  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
1106
  case "llm:tool_call:created":
1167
1107
  return this.onToolCallCreated(state, payload);
1168
1108
  case "llm:response:done":
@@ -1452,9 +1392,6 @@ var ClientProjectionBuilder = class {
1452
1392
  if (typeof payload.usage === "object" && payload.usage !== null) {
1453
1393
  state.usage = { ...payload.usage };
1454
1394
  }
1455
- if ("content" in payload) {
1456
- replaceTextContent(state, completedResponseText(payload.content));
1457
- }
1458
1395
  const toolCalls = payload.tool_calls;
1459
1396
  if (Array.isArray(toolCalls)) {
1460
1397
  for (const raw of toolCalls) {
@@ -2258,11 +2195,6 @@ var SessionsResource = class {
2258
2195
  listSessionsWithSkillData() {
2259
2196
  return this.client.json("GET", "/api/sessions/with-skill-data");
2260
2197
  }
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
2198
  createSession(intent, template_id, primary_skill_id) {
2267
2199
  return this.createSessionWithRequest({ intent, template_id, primary_skill_id });
2268
2200
  }
@@ -2329,16 +2261,6 @@ var SessionsResource = class {
2329
2261
  );
2330
2262
  return projectHistory(entries);
2331
2263
  }
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
2264
  getSessionContextStats(sessionId, init) {
2343
2265
  return this.client.jsonFromInit(`/api/sessions/${sessionId}/context-stats`, init);
2344
2266
  }
@@ -3307,7 +3229,7 @@ function extractTerminalChatEndStatus(events) {
3307
3229
  }
3308
3230
  return null;
3309
3231
  }
3310
- function hasChatRunEvent2(events) {
3232
+ function hasChatRunEvent(events) {
3311
3233
  return events.some(
3312
3234
  (event) => event.type !== "session:post_chat_followup" && !event.type.startsWith("compaction:")
3313
3235
  );
@@ -3359,7 +3281,6 @@ var AgentSession = class _AgentSession {
3359
3281
  const session = new _AgentSession(
3360
3282
  sessionId,
3361
3283
  {
3362
- streamTokens: false,
3363
3284
  emitEvent: readonlyError,
3364
3285
  emitWithAck: async () => readonlyError(),
3365
3286
  ensureConnected: readonlyError,
@@ -3733,7 +3654,7 @@ var AgentSession = class _AgentSession {
3733
3654
  _handleTurnEvents(events) {
3734
3655
  if (!events.length) return;
3735
3656
  const terminalChatEndStatus = extractTerminalChatEndStatus(events);
3736
- if (!terminalChatEndStatus && hasChatRunEvent2(events)) {
3657
+ if (!terminalChatEndStatus && hasChatRunEvent(events)) {
3737
3658
  this.markRunningIfIdle();
3738
3659
  }
3739
3660
  if (this.state.turns.length) {
@@ -3747,8 +3668,8 @@ var AgentSession = class _AgentSession {
3747
3668
  this.emitter.emit("workspaceChanged", {});
3748
3669
  }
3749
3670
  }
3750
- if (terminalChatEndStatus || acceptedPostChatFollowupCompletesLatestRun(events, updates)) {
3751
- this.completeChat(terminalChatEndStatus ?? "completed");
3671
+ if (terminalChatEndStatus) {
3672
+ this.finishStreaming(terminalChatEndStatus);
3752
3673
  }
3753
3674
  }
3754
3675
  /** @internal */
@@ -3758,7 +3679,10 @@ var AgentSession = class _AgentSession {
3758
3679
  /** @internal */
3759
3680
  _handleChatEnd(status) {
3760
3681
  this.flushPatches();
3761
- this.completeChat(status);
3682
+ this.finishStreaming(status);
3683
+ this.recentChatEndAt = Date.now();
3684
+ void this.syncTurnsFromHistory();
3685
+ this.emitter.emit("chatEnd", { status });
3762
3686
  }
3763
3687
  /** @internal */
3764
3688
  _handleSystemError(message) {
@@ -3902,12 +3826,6 @@ var AgentSession = class _AgentSession {
3902
3826
  return next;
3903
3827
  });
3904
3828
  }
3905
- completeChat(status) {
3906
- this.finishStreaming(status);
3907
- this.recentChatEndAt = Date.now();
3908
- void this.syncTurnsFromHistory();
3909
- this.emitter.emit("chatEnd", { status });
3910
- }
3911
3829
  applyTurn(turn) {
3912
3830
  this.flushPatches();
3913
3831
  const previous = this.state;
@@ -4090,12 +4008,7 @@ var AgentSession = class _AgentSession {
4090
4008
  if (this.joinPending) return this.joinPending;
4091
4009
  const join = this.runtime.emitWithAck(
4092
4010
  "session:subscribe",
4093
- {
4094
- session_id: this.sessionId,
4095
- event_format: "raw",
4096
- resume: true,
4097
- stream_tokens: this.runtime.streamTokens
4098
- },
4011
+ { session_id: this.sessionId, event_format: "raw", resume: true },
4099
4012
  5e3
4100
4013
  ).then((response) => {
4101
4014
  if (response && response.ok === false) {
@@ -4231,7 +4144,6 @@ var SessionHub = class {
4231
4144
  }
4232
4145
  runtimeFor() {
4233
4146
  return {
4234
- streamTokens: this.client.options?.streamTokens !== false,
4235
4147
  emitEvent: (event, data) => {
4236
4148
  ;
4237
4149
  this.client.socket().emit(event, data);
@@ -4471,7 +4383,7 @@ function resolveAuthToken(options) {
4471
4383
 
4472
4384
  // src/version.ts
4473
4385
  var SDK_NAME = "agent-client";
4474
- var SDK_VERSION = true ? "2610.0.0-beta.1" : "1.1.1";
4386
+ var SDK_VERSION = true ? "2610.0.1-alpha.1" : "1.1.1";
4475
4387
 
4476
4388
  // src/socket.ts
4477
4389
  function withSdkIdentity(auth) {
@@ -4923,19 +4835,6 @@ function connectEmbedded(options) {
4923
4835
  };
4924
4836
  }
4925
4837
 
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
- }
4938
-
4939
4838
  // src/schemas/solution.ts
4940
4839
  var LayoutType = /* @__PURE__ */ ((LayoutType2) => {
4941
4840
  LayoutType2["Default"] = "default";
@@ -4978,7 +4877,6 @@ export {
4978
4877
  SessionStatus,
4979
4878
  Task,
4980
4879
  TaskStatus,
4981
- acceptedPostChatFollowupCompletesLatestRun,
4982
4880
  buildMessageContent,
4983
4881
  connectEmbedded,
4984
4882
  contentPreview,
@@ -4992,7 +4890,6 @@ export {
4992
4890
  isCommandEnvelope,
4993
4891
  isHiddenInternalMessage,
4994
4892
  isInboundEnvelope,
4995
- latestPostChatFollowup,
4996
4893
  normalizeMessageContent,
4997
4894
  toReplaySnapshot,
4998
4895
  transformSlashCommand