@blade-hq/agent-client 2610.0.0-beta.80 → 2610.0.0-beta.82
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 +5 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +117 -20
- package/dist/index.js.map +1 -1
- package/dist/session/agent-session.d.ts +15 -1
- package/dist/session/errors.d.ts +11 -0
- package/dist/session/events.d.ts +7 -1
- package/dist/session/queue.d.ts +5 -0
- package/package.json +1 -1
- package/public-api.md +13 -2
package/README.md
CHANGED
|
@@ -478,7 +478,7 @@ await chat.refreshQueue() // 手动拉一份权威快照(首次连接与每
|
|
|
478
478
|
|
|
479
479
|
- **冲突处理**:`conflict` 表示乐观并发或状态校验失败,服务端快照已自动刷新到本地,此时保留用户草稿并说明原因即可;`ok=false` 且 `snapshot` 为 null(例如鉴权失败)时不要改动本地队列。`queueMessage` 结果未知(ack 超时)时会用同一个 `client_request_id` 重试一次,不会制造第二条。
|
|
480
480
|
- **可操作性判定**:`canEditQueuedMessage` / `canCancelQueuedMessage` / `canDeliverQueuedMessage` 只对 `pending` 返回 true;文案用 `queuedMessageStatusLabel` 与 `queuePauseReasonLabel`。
|
|
481
|
-
- **自己处理广播**:需要绕过状态机时用 `isSessionQueueSnapshot` + `shouldApplySnapshot` + `EMPTY_SESSION_QUEUE`;解析自定义 ack 用 `parseQueueAck`,返回统一的 `QueueOperationResult`(`QueueAck` 是 ack
|
|
481
|
+
- **自己处理广播**:需要绕过状态机时用 `isSessionQueueSnapshot` + `shouldApplySnapshot` + `EMPTY_SESSION_QUEUE`;解析自定义 ack 用 `parseQueueAck`,返回统一的 `QueueOperationResult`(`QueueAck` 是 ack 的线格式;`code` 是路由失败原因,供调用方决定是否重试)。
|
|
482
482
|
|
|
483
483
|
### 页面协作:让智能体和你的页面互动
|
|
484
484
|
|
|
@@ -544,9 +544,11 @@ chat.on("toolCall", (e) => console.log("调用工具", e.toolCall.name))
|
|
|
544
544
|
chat.on("toolResult", (e) => console.log("工具结果", e.toolCall.result))
|
|
545
545
|
chat.on("message", (e) => console.log("新消息", e.message))
|
|
546
546
|
chat.on("chatEnd", (e) => console.log("回复结束", e.status))
|
|
547
|
-
chat.on("error", (e) => console.error(e.message))
|
|
547
|
+
chat.on("error", (e) => console.error(e.message, e.code))
|
|
548
548
|
```
|
|
549
549
|
|
|
550
|
+
`error` 的 `message` 是可以直接展示的业务文案;`code` 是服务端给的机器可读原因(如 `owner_timeout` / `route_broken` / `owner_busy`),调用方据此决定要不要提示重试,不要解析 `message`。同一组原因也以 `AgentSessionError.code` 的形式抛出(`send()` 这类只回布尔值的入口从 `error` 事件拿),队列 API 则通过 `QueueOperationResult.code` 给出。
|
|
551
|
+
|
|
550
552
|
完整事件表见 `AgentSessionEvents` 类型定义(含 `modeChange` / `workspaceChanged` / `artifact` / `notification` / `backgroundTask` / `taskListUpdated` / `rewind` / `replayMismatch` 等)。`toolResult.source` 区分实时结果、首次连接回放和断线重连回放;`on()` 返回取消函数,handler 抛异常只告警、不影响会话。
|
|
551
553
|
|
|
552
554
|
分页响应是 `SessionTurnsPage`,其中 `nextBefore: string | null` 是唯一的“还有更早历史”真值。历史页面指令通过独立的 `HistoricalCommand` 日志恢复,不混进展示页。自定义状态容器可复用 `prependOlder`、`replaceWindow` 与 `LiveRevisionState`,但一般直接使用 `AgentSession` 即可。
|
|
@@ -739,6 +741,7 @@ HTML 一律判无效);`isInternalStatusToolUiCard` 识别内部「阶段进
|
|
|
739
741
|
- **客户端与登录**:`BladeClientOptions`、`LoginOptions`、`LoginResult`、`TokenStorageMode`、`UploadProgress`、`BladeApiError`、`AuthResource`、`ProvidersResponse`、`UserInfo`
|
|
740
742
|
- **SDK 身份**:`SDK_NAME`、`SDK_VERSION`
|
|
741
743
|
- **声明式会话**:`SessionDefinition`、`SolutionDefinition`、`SkillDefinition`、`SessionConfig`、`TextFile`、`SessionSetupError`、`SessionSetupStage`
|
|
744
|
+
- **会话错误**:`AgentSessionError`(`code` 是服务端路由失败原因,供调用方决定是否重试)
|
|
742
745
|
- **模型目录**:`ModelsResource`、`ModelCatalog`、`ModelOption`
|
|
743
746
|
- **聊天分组资源(REST)**:`ChatGroupsResource`、`ChatGroup`(含 `delete` 永久删除);`client.chatGroups`。旧名 `ChatProjectsResource`、`ChatProject`、`client.chatProjects` 与 `chat_project_id` 字段已随分组改名一并移除,接入方请改用 `chatGroups` 与 `chat_group_id`
|
|
744
747
|
- **插件目录(REST,无会话)**:`PluginsResource`、`PluginCatalogEntry`(`client.plugins`)。首页这类还没有会话的界面用它读名称、业务名与图标 token
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export type { LoadPlatformEndpointsOptions, PlatformEndpoints, PlatformServiceNa
|
|
|
9
9
|
export { SDK_NAME, SDK_VERSION } from "./version";
|
|
10
10
|
export { AgentSession } from "./session/agent-session";
|
|
11
11
|
export type { AttachAppOptions, SendOptions } from "./session/agent-session";
|
|
12
|
+
export { AgentSessionError } from "./session/errors";
|
|
12
13
|
export { SessionHub } from "./session/hub";
|
|
13
14
|
export type { SessionConnectOptions } from "./session/hub";
|
|
14
15
|
export type { AgentSessionEvents, AgentSessionEventName } from "./session/events";
|
package/dist/index.js
CHANGED
|
@@ -3591,18 +3591,37 @@ function parseQueueAck(response, fallbackSessionId) {
|
|
|
3591
3591
|
return { ok: false, conflict: false, snapshot: null, message: QUEUE_FAILURE_MESSAGE };
|
|
3592
3592
|
}
|
|
3593
3593
|
const message = typeof response.message === "string" && response.message ? response.message : null;
|
|
3594
|
+
const code = typeof response.code === "string" && response.code ? response.code : void 0;
|
|
3594
3595
|
const status = response.status;
|
|
3595
3596
|
if (status !== "ok" && status !== "conflict" && status !== "queued") {
|
|
3596
|
-
return {
|
|
3597
|
+
return {
|
|
3598
|
+
ok: false,
|
|
3599
|
+
conflict: false,
|
|
3600
|
+
snapshot: null,
|
|
3601
|
+
message: message ?? QUEUE_FAILURE_MESSAGE,
|
|
3602
|
+
...code ? { code } : {}
|
|
3603
|
+
};
|
|
3597
3604
|
}
|
|
3598
3605
|
const snapshot2 = toQueueSnapshot(response, fallbackSessionId);
|
|
3599
3606
|
if (status === "conflict") {
|
|
3600
|
-
return {
|
|
3607
|
+
return {
|
|
3608
|
+
ok: false,
|
|
3609
|
+
conflict: true,
|
|
3610
|
+
snapshot: snapshot2,
|
|
3611
|
+
message: message ?? QUEUE_FAILURE_MESSAGE,
|
|
3612
|
+
...code ? { code } : {}
|
|
3613
|
+
};
|
|
3601
3614
|
}
|
|
3602
3615
|
if (!snapshot2) {
|
|
3603
|
-
return {
|
|
3616
|
+
return {
|
|
3617
|
+
ok: false,
|
|
3618
|
+
conflict: false,
|
|
3619
|
+
snapshot: null,
|
|
3620
|
+
message: message ?? QUEUE_FAILURE_MESSAGE,
|
|
3621
|
+
...code ? { code } : {}
|
|
3622
|
+
};
|
|
3604
3623
|
}
|
|
3605
|
-
return { ok: true, conflict: false, snapshot: snapshot2, message };
|
|
3624
|
+
return { ok: true, conflict: false, snapshot: snapshot2, message, ...code ? { code } : {} };
|
|
3606
3625
|
}
|
|
3607
3626
|
function canEditQueuedMessage(item) {
|
|
3608
3627
|
return item.status === "pending";
|
|
@@ -4427,6 +4446,16 @@ function markStreamingTurns(state, turnStatus, toolCallStatus) {
|
|
|
4427
4446
|
return withTurns(state, turns);
|
|
4428
4447
|
}
|
|
4429
4448
|
|
|
4449
|
+
// src/session/errors.ts
|
|
4450
|
+
var AgentSessionError = class extends Error {
|
|
4451
|
+
name = "AgentSessionError";
|
|
4452
|
+
code;
|
|
4453
|
+
constructor(message, code) {
|
|
4454
|
+
super(message);
|
|
4455
|
+
this.code = code;
|
|
4456
|
+
}
|
|
4457
|
+
};
|
|
4458
|
+
|
|
4430
4459
|
// src/session/agent-session.ts
|
|
4431
4460
|
var OOM_MESSAGE = "\u6C99\u76D2\u5185\u5B58\u4F7F\u7528\u8D85\u51FA\u9650\u5236\uFF0C\u5DF2\u81EA\u52A8\u91CD\u542F\u3002\u5982\u679C\u7ECF\u5E38\u89E6\u53D1\uFF0C\u53EF\u4EE5\u8054\u7CFB\u7BA1\u7406\u5458\u8C03\u6574\u989D\u5EA6\u3002";
|
|
4432
4461
|
var COMMAND_RESTORE_RETRY_BASE_MS = 1e3;
|
|
@@ -4444,6 +4473,16 @@ var OOM_KEYWORDS_RE = /(?:\b(?:exit_code|ExitedWith|exited with)|退出码)\D*(?
|
|
|
4444
4473
|
function isOomText(value) {
|
|
4445
4474
|
return typeof value === "string" && OOM_KEYWORDS_RE.test(value);
|
|
4446
4475
|
}
|
|
4476
|
+
function describeSessionError(error, fallback) {
|
|
4477
|
+
if (error instanceof AgentSessionError) {
|
|
4478
|
+
return {
|
|
4479
|
+
message: error.message || fallback,
|
|
4480
|
+
...error.code ? { code: error.code } : {}
|
|
4481
|
+
};
|
|
4482
|
+
}
|
|
4483
|
+
if (error instanceof Error && error.message) return { message: error.message };
|
|
4484
|
+
return { message: fallback };
|
|
4485
|
+
}
|
|
4447
4486
|
function parseJsonRecord(value) {
|
|
4448
4487
|
if (isRecord(value)) return value;
|
|
4449
4488
|
if (typeof value !== "string") return null;
|
|
@@ -4479,11 +4518,12 @@ function isCursorInvalidError(error) {
|
|
|
4479
4518
|
return typeof error === "object" && error !== null && "status" in error && error.status === 409;
|
|
4480
4519
|
}
|
|
4481
4520
|
function queueRequestFailure(error) {
|
|
4521
|
+
const failure = error instanceof AgentSessionError ? { message: error.message, ...error.code ? { code: error.code } : {} } : { message: error instanceof Error && error.message ? error.message : "\u961F\u5217\u64CD\u4F5C\u5931\u8D25" };
|
|
4482
4522
|
return {
|
|
4483
4523
|
ok: false,
|
|
4484
4524
|
conflict: false,
|
|
4485
4525
|
snapshot: null,
|
|
4486
|
-
|
|
4526
|
+
...failure
|
|
4487
4527
|
};
|
|
4488
4528
|
}
|
|
4489
4529
|
function commandDeliveryKey(deliveryId) {
|
|
@@ -4551,6 +4591,20 @@ var AgentSession = class _AgentSession {
|
|
|
4551
4591
|
pendingReplayMode;
|
|
4552
4592
|
pendingReplayKbIds;
|
|
4553
4593
|
recentChatEndAt = 0;
|
|
4594
|
+
/**
|
|
4595
|
+
* 最近一次已经通过 `error` 事件投递过的服务端失败(`message` + `code`)。
|
|
4596
|
+
*
|
|
4597
|
+
* `chat:send` 被代理时服务端会先发 `system:error`、再用同一条失败回 ack,两条
|
|
4598
|
+
* 通道都会到达这里:前者走 `_handleSystemError`,后者走发送失败的回滚。不去重
|
|
4599
|
+
* 的话调用方会收到两次同一个 `error`(重复提示、重试逻辑跑两遍)。
|
|
4600
|
+
*
|
|
4601
|
+
* 带代际边界,只认「本次 `emitWithAck` 等待期间」投递的那一条:否则队列/停止
|
|
4602
|
+
* 失败留下的标记会一直挂着,之后一次无关的订阅失败只是文案码相同就被当成
|
|
4603
|
+
* 重复而静音。用单调递增的代际号而不是时间戳,同一毫秒内的两条也不会混淆。
|
|
4604
|
+
*/
|
|
4605
|
+
lastDeliveredSystemError = null;
|
|
4606
|
+
/** 每次投递 `system:error` 递增,用于判定某条失败是否属于本次等待。 */
|
|
4607
|
+
systemErrorGeneration = 0;
|
|
4554
4608
|
subscriptionReplaySource = null;
|
|
4555
4609
|
disposed = false;
|
|
4556
4610
|
getAppContext = null;
|
|
@@ -4965,16 +5019,19 @@ var AgentSession = class _AgentSession {
|
|
|
4965
5019
|
try {
|
|
4966
5020
|
await this.ensureJoined();
|
|
4967
5021
|
} catch (error) {
|
|
5022
|
+
const failure = describeSessionError(error, "\u4F1A\u8BDD\u8BA2\u9605\u5931\u8D25\uFF0C\u6D88\u606F\u672A\u53D1\u9001");
|
|
4968
5023
|
this.rollbackOptimisticSend(
|
|
4969
5024
|
optimisticTurnId,
|
|
4970
5025
|
askUserAnswer,
|
|
4971
5026
|
optimisticAskAnswer,
|
|
4972
5027
|
previousAskAnswer,
|
|
4973
5028
|
wasStreaming,
|
|
4974
|
-
|
|
5029
|
+
failure.message,
|
|
5030
|
+
failure.code
|
|
4975
5031
|
);
|
|
4976
5032
|
return false;
|
|
4977
5033
|
}
|
|
5034
|
+
const waitStartedAt = this.systemErrorGeneration;
|
|
4978
5035
|
try {
|
|
4979
5036
|
const response = await this.runtime.emitWithAck("chat:send", payload, 3e4);
|
|
4980
5037
|
if (response?.status === "queued") {
|
|
@@ -4993,24 +5050,28 @@ var AgentSession = class _AgentSession {
|
|
|
4993
5050
|
return true;
|
|
4994
5051
|
}
|
|
4995
5052
|
if (response?.status !== "accepted") {
|
|
4996
|
-
throw new
|
|
4997
|
-
typeof response?.message === "string" ? response.message : "\u6D88\u606F\u672A\u88AB\u670D\u52A1\u7AEF\u63A5\u53D7"
|
|
5053
|
+
throw new AgentSessionError(
|
|
5054
|
+
typeof response?.message === "string" ? response.message : "\u6D88\u606F\u672A\u88AB\u670D\u52A1\u7AEF\u63A5\u53D7",
|
|
5055
|
+
typeof response?.code === "string" ? response.code : void 0
|
|
4998
5056
|
);
|
|
4999
5057
|
}
|
|
5000
5058
|
return true;
|
|
5001
5059
|
} catch (error) {
|
|
5060
|
+
const failure = describeSessionError(error, "\u6D88\u606F\u53D1\u9001\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5");
|
|
5002
5061
|
this.rollbackOptimisticSend(
|
|
5003
5062
|
optimisticTurnId,
|
|
5004
5063
|
askUserAnswer,
|
|
5005
5064
|
optimisticAskAnswer,
|
|
5006
5065
|
previousAskAnswer,
|
|
5007
5066
|
wasStreaming,
|
|
5008
|
-
|
|
5067
|
+
failure.message,
|
|
5068
|
+
failure.code,
|
|
5069
|
+
waitStartedAt
|
|
5009
5070
|
);
|
|
5010
5071
|
return false;
|
|
5011
5072
|
}
|
|
5012
5073
|
}
|
|
5013
|
-
rollbackOptimisticSend(optimisticTurnId, askUserAnswer, optimisticAskAnswer, previousAskAnswer, wasStreaming, message) {
|
|
5074
|
+
rollbackOptimisticSend(optimisticTurnId, askUserAnswer, optimisticAskAnswer, previousAskAnswer, wasStreaming, message, code, waitStartedAt) {
|
|
5014
5075
|
this.discardOptimisticSend(
|
|
5015
5076
|
optimisticTurnId,
|
|
5016
5077
|
askUserAnswer,
|
|
@@ -5020,6 +5081,12 @@ var AgentSession = class _AgentSession {
|
|
|
5020
5081
|
this.update(
|
|
5021
5082
|
(current) => addErrorMessage(wasStreaming ? current : { ...current, isStreaming: false }, message)
|
|
5022
5083
|
);
|
|
5084
|
+
const delivered = this.lastDeliveredSystemError;
|
|
5085
|
+
if (waitStartedAt !== void 0 && delivered && delivered.generation > waitStartedAt && delivered.message === message && delivered.code === code) {
|
|
5086
|
+
this.lastDeliveredSystemError = null;
|
|
5087
|
+
return;
|
|
5088
|
+
}
|
|
5089
|
+
this.emitter.emit("error", { message, ...code ? { code } : {} });
|
|
5023
5090
|
}
|
|
5024
5091
|
/** 撤回一次乐观提交:移除乐观消息、恢复提问作答、清掉回放草稿。 */
|
|
5025
5092
|
discardOptimisticSend(optimisticTurnId, askUserAnswer, optimisticAskAnswer, previousAskAnswer) {
|
|
@@ -5284,7 +5351,12 @@ var AgentSession = class _AgentSession {
|
|
|
5284
5351
|
}
|
|
5285
5352
|
/** @internal */
|
|
5286
5353
|
_handleChatStart() {
|
|
5287
|
-
this.update((s) => ({
|
|
5354
|
+
this.update((s) => ({
|
|
5355
|
+
...s,
|
|
5356
|
+
status: "running",
|
|
5357
|
+
errorMessage: null,
|
|
5358
|
+
isStreaming: true
|
|
5359
|
+
}));
|
|
5288
5360
|
}
|
|
5289
5361
|
/** @internal */
|
|
5290
5362
|
_handleChatEnd(status) {
|
|
@@ -5292,14 +5364,31 @@ var AgentSession = class _AgentSession {
|
|
|
5292
5364
|
this.completeChat(status);
|
|
5293
5365
|
}
|
|
5294
5366
|
/** @internal */
|
|
5295
|
-
_handleSystemError(message) {
|
|
5367
|
+
_handleSystemError(message, code) {
|
|
5296
5368
|
this.flushPatches();
|
|
5297
5369
|
const finalMessage = isOomText(message) ? OOM_MESSAGE : message;
|
|
5298
5370
|
this.update(
|
|
5299
|
-
(s) => addErrorMessage(
|
|
5371
|
+
(s) => addErrorMessage(
|
|
5372
|
+
markFailed({
|
|
5373
|
+
...s,
|
|
5374
|
+
status: "failed",
|
|
5375
|
+
errorMessage: finalMessage,
|
|
5376
|
+
isStreaming: false
|
|
5377
|
+
}),
|
|
5378
|
+
finalMessage
|
|
5379
|
+
)
|
|
5300
5380
|
);
|
|
5301
5381
|
this.recentChatEndAt = Date.now();
|
|
5302
|
-
this.
|
|
5382
|
+
this.systemErrorGeneration += 1;
|
|
5383
|
+
this.lastDeliveredSystemError = {
|
|
5384
|
+
message: finalMessage,
|
|
5385
|
+
...code ? { code } : {},
|
|
5386
|
+
generation: this.systemErrorGeneration
|
|
5387
|
+
};
|
|
5388
|
+
this.emitter.emit("error", {
|
|
5389
|
+
message: finalMessage,
|
|
5390
|
+
...code ? { code } : {}
|
|
5391
|
+
});
|
|
5303
5392
|
}
|
|
5304
5393
|
/** @internal */
|
|
5305
5394
|
_handleTaskUpdated(tasks) {
|
|
@@ -5834,8 +5923,9 @@ var AgentSession = class _AgentSession {
|
|
|
5834
5923
|
5e3
|
|
5835
5924
|
).then((response) => {
|
|
5836
5925
|
if (response && response.ok === false) {
|
|
5837
|
-
throw new
|
|
5838
|
-
typeof response.message === "string" && response.message ? response.message : "Session subscription failed"
|
|
5926
|
+
throw new AgentSessionError(
|
|
5927
|
+
typeof response.message === "string" && response.message ? response.message : "Session subscription failed",
|
|
5928
|
+
typeof response.code === "string" ? response.code : void 0
|
|
5839
5929
|
);
|
|
5840
5930
|
}
|
|
5841
5931
|
this.joined = true;
|
|
@@ -6144,9 +6234,15 @@ var SessionHub = class {
|
|
|
6144
6234
|
session._handleChatEnd(data?.status ?? "completed");
|
|
6145
6235
|
}
|
|
6146
6236
|
});
|
|
6147
|
-
socket.on(
|
|
6148
|
-
|
|
6149
|
-
|
|
6237
|
+
socket.on(
|
|
6238
|
+
"system:error",
|
|
6239
|
+
(data) => {
|
|
6240
|
+
const code = data.code == null ? void 0 : String(data.code);
|
|
6241
|
+
for (const session of this.route(data.session_id)) {
|
|
6242
|
+
session._handleSystemError(data.message, code);
|
|
6243
|
+
}
|
|
6244
|
+
}
|
|
6245
|
+
);
|
|
6150
6246
|
socket.on("chat:queue:updated", (data) => {
|
|
6151
6247
|
for (const session of this.route(data?.session_id)) session._handleQueueUpdated(data);
|
|
6152
6248
|
});
|
|
@@ -6803,7 +6899,7 @@ function resolveServiceUrl(endpoints, name, path = "") {
|
|
|
6803
6899
|
|
|
6804
6900
|
// src/version.ts
|
|
6805
6901
|
var SDK_NAME = "agent-client";
|
|
6806
|
-
var SDK_VERSION = true ? "2610.0.0-beta.
|
|
6902
|
+
var SDK_VERSION = true ? "2610.0.0-beta.82" : "1.1.1";
|
|
6807
6903
|
|
|
6808
6904
|
// src/commands/protocol.ts
|
|
6809
6905
|
function isCommandEnvelope(value) {
|
|
@@ -6905,6 +7001,7 @@ var Task = type2({
|
|
|
6905
7001
|
});
|
|
6906
7002
|
export {
|
|
6907
7003
|
AgentSession,
|
|
7004
|
+
AgentSessionError,
|
|
6908
7005
|
AuthBusyReconnect,
|
|
6909
7006
|
BladeApiError,
|
|
6910
7007
|
BladeClient,
|