@blade-hq/agent-client 1.2.1-alpha.4 → 1.2.1-beta.10
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 +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +197 -41
- package/dist/index.js.map +1 -1
- package/dist/resources/sessions.d.ts +2 -5
- package/dist/schemas/background.d.ts +18 -3
- package/dist/session/agent-session.d.ts +4 -10
- package/dist/session/events.d.ts +8 -1
- package/dist/shared/projection/builder.d.ts +1 -0
- package/dist/types/socket-events.d.ts +13 -1
- package/package.json +1 -1
- package/public-api.md +15 -7
package/README.md
CHANGED
|
@@ -182,7 +182,7 @@ const unsubscribe = chat.subscribe(() => rerender(chat.getState()))
|
|
|
182
182
|
### 动作
|
|
183
183
|
|
|
184
184
|
```ts
|
|
185
|
-
await chat.send("你好")
|
|
185
|
+
const accepted = await chat.send("你好") // 服务端接受后为 true;拒绝时为 false
|
|
186
186
|
await chat.send("换个方案", { mode: "planning" }) // 指定模式/模型等选项
|
|
187
187
|
chat.append("补充:预算不超过 5 万") // 智能体运行中追加说明
|
|
188
188
|
await chat.stop() // 停止当前回复
|
|
@@ -389,6 +389,6 @@ function Message({ message }: { message: ChatMessage }) {
|
|
|
389
389
|
- **会话状态机**:`SessionHub`、`SessionState`、`SendOptions`、`ConnectionStatus`、`AskUserAnswerData`、`AgentLoopInfo`、`ActiveCompactionState`、`createInitialSessionState`、`AgentSessionEventName`
|
|
390
390
|
- **页面协作**:`EmbeddedChat`、`EmbeddedChatOptions`、`CommandHandler`、`CommandEnvelope`、`InboundAction`、`InboundEnvelope`、`isCommandEnvelope`、`isInboundEnvelope`
|
|
391
391
|
- **消息与投影协议**:`MessageContent`、`MessageContentPart`、`TextContentPart`、`ImageUrlContentPart`、`FileContentPart`、`ToolCallInfo`、`ToolBridgeContent`、`CompactionInfo`、`MemoryRefInfo`、`ArchivedFileInfo`、`ArchivedToolCallInfo`、`TurnProjection`、`ContentBlock`、`PatchEnvelope`、`MemoryRef`、`buildMessageContent`、`normalizeMessageContent`、`isHiddenInternalMessage`、`transformSlashCommand`、`extractTextAttachments`、`ParsedTextAttachment`、`ParsedTextContext`
|
|
392
|
-
- **Solution / 任务协议**:`Solution`、`SolutionAppField`、`SolutionAppState`、`SolutionAppUiConfig`、`SolutionRef`、`PublishedSolutionRef`、`ExistingSolutionRef`、`PreparedSolution`、`PreparedSolutionAsset`、`LayoutType`、`BizRole`、`TaskStatus`、`BackgroundTask`
|
|
392
|
+
- **Solution / 任务协议**:`Solution`、`SolutionAppField`、`SolutionAppState`、`SolutionAppUiConfig`、`SolutionRef`、`PublishedSolutionRef`、`ExistingSolutionRef`、`PreparedSolution`、`PreparedSolutionAsset`、`LayoutType`、`BizRole`、`TaskStatus`、`BackgroundTask`、`BackgroundTaskStopResult`
|
|
393
393
|
- **Headless**:`HeadlessResource`、`RunOptions`、`RunResult`、`RunTrace`
|
|
394
394
|
- **低层通道(apps/web 等高级集成)**:`createSocket`、`CreateSocketOptions`、`TypedSocket`、`AsrAudioPayload`、`ClientProjectionBuilder`、`RawEvent`
|
package/dist/index.d.ts
CHANGED
|
@@ -31,7 +31,7 @@ export type { ModeId, PrimarySkillParallelMode, PrimarySkillSnapshot, SessionDet
|
|
|
31
31
|
export { LayoutType } from "./schemas/solution";
|
|
32
32
|
export type { BizRole, Solution, SolutionAppField, SolutionAppState, SolutionAppUiConfig, } from "./schemas/solution";
|
|
33
33
|
export { Task, TaskStatus } from "./schemas/task";
|
|
34
|
-
export type { BackgroundTask } from "./schemas/background";
|
|
34
|
+
export type { BackgroundTask, BackgroundTaskStopResult } from "./schemas/background";
|
|
35
35
|
export { ClientProjectionBuilder } from "./shared/projection";
|
|
36
36
|
export type { RawEvent } from "./shared/projection";
|
|
37
37
|
export { createSocket } from "./socket";
|
package/dist/index.js
CHANGED
|
@@ -45,8 +45,8 @@ async function loginWithPopup(client, options = {}) {
|
|
|
45
45
|
authorizeUrl.searchParams.set("client_origin", clientOrigin);
|
|
46
46
|
authorizeUrl.searchParams.set("state", state);
|
|
47
47
|
const popup = window.open(
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
"about:blank",
|
|
49
|
+
`blade-sdk-login-${state}`,
|
|
50
50
|
`popup=yes,width=${width},height=${height},left=${left},top=${top}`
|
|
51
51
|
);
|
|
52
52
|
if (!popup) {
|
|
@@ -69,6 +69,7 @@ async function loginWithPopup(client, options = {}) {
|
|
|
69
69
|
};
|
|
70
70
|
const onMessage = (event) => {
|
|
71
71
|
if (event.origin !== expectedOrigin) return;
|
|
72
|
+
if (event.source !== popup) return;
|
|
72
73
|
if (!isAuthCallbackMessage(event.data)) return;
|
|
73
74
|
if (event.data.state !== state) return;
|
|
74
75
|
const message = event.data;
|
|
@@ -107,6 +108,7 @@ async function loginWithPopup(client, options = {}) {
|
|
|
107
108
|
settle(() => reject(new Error("\u767B\u5F55\u8D85\u65F6\uFF0C\u8BF7\u91CD\u8BD5\u3002")));
|
|
108
109
|
}, timeoutMs);
|
|
109
110
|
window.addEventListener("message", onMessage);
|
|
111
|
+
popup.location.replace(authorizeUrl.toString());
|
|
110
112
|
});
|
|
111
113
|
}
|
|
112
114
|
|
|
@@ -319,13 +321,22 @@ var HeadlessResource = class {
|
|
|
319
321
|
socket.on("chat:end", onChatEnd);
|
|
320
322
|
socket.on("system:error", onSystemError);
|
|
321
323
|
socket.emit("session:subscribe", { session_id, event_format: "raw" });
|
|
322
|
-
socket.emit(
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
324
|
+
socket.emit(
|
|
325
|
+
"chat:send",
|
|
326
|
+
{
|
|
327
|
+
session_id,
|
|
328
|
+
message: prompt,
|
|
329
|
+
headless: true,
|
|
330
|
+
output_schema: options.schema ?? null,
|
|
331
|
+
model: options.model ?? null
|
|
332
|
+
},
|
|
333
|
+
(response) => {
|
|
334
|
+
if (response.status === "accepted") return;
|
|
335
|
+
rejectAfterChatEnd(
|
|
336
|
+
new HeadlessError(response.message ?? "headless run was not accepted", response)
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
);
|
|
329
340
|
});
|
|
330
341
|
}
|
|
331
342
|
};
|
|
@@ -905,6 +916,7 @@ var ClientProjectionBuilder = class {
|
|
|
905
916
|
pendingChildPauses = /* @__PURE__ */ new Map();
|
|
906
917
|
pendingMemoryRefs = /* @__PURE__ */ new Map();
|
|
907
918
|
activeCompactions = /* @__PURE__ */ new Map();
|
|
919
|
+
failedCompactions = /* @__PURE__ */ new Map();
|
|
908
920
|
seq = 0;
|
|
909
921
|
syntheticCounter = 0;
|
|
910
922
|
displayNameResolver;
|
|
@@ -968,6 +980,12 @@ var ClientProjectionBuilder = class {
|
|
|
968
980
|
return null;
|
|
969
981
|
}
|
|
970
982
|
switch (event.type) {
|
|
983
|
+
case "llm:stream:reset":
|
|
984
|
+
state.blocks = [];
|
|
985
|
+
state.toolCalls = [];
|
|
986
|
+
state.usage = null;
|
|
987
|
+
state.responseDone = false;
|
|
988
|
+
return this.syncPatch(state);
|
|
971
989
|
case "llm:thinking:delta":
|
|
972
990
|
return this.onDelta(state, "thinking", "", String(payload.content ?? ""));
|
|
973
991
|
case "llm:content:delta":
|
|
@@ -1004,6 +1022,7 @@ var ClientProjectionBuilder = class {
|
|
|
1004
1022
|
this.pendingChildPauses.clear();
|
|
1005
1023
|
this.pendingMemoryRefs.clear();
|
|
1006
1024
|
this.activeCompactions.clear();
|
|
1025
|
+
this.failedCompactions.clear();
|
|
1007
1026
|
this.seq = 0;
|
|
1008
1027
|
this.syntheticCounter = 0;
|
|
1009
1028
|
}
|
|
@@ -1476,7 +1495,7 @@ var ClientProjectionBuilder = class {
|
|
|
1476
1495
|
onCompaction(eventType, loopId, payload) {
|
|
1477
1496
|
const compactionId = String(payload.compaction_id ?? "");
|
|
1478
1497
|
if (!compactionId) return null;
|
|
1479
|
-
|
|
1498
|
+
let current = {
|
|
1480
1499
|
...this.activeCompactions.get(compactionId) ?? {},
|
|
1481
1500
|
...payload,
|
|
1482
1501
|
loop_id: loopId
|
|
@@ -1486,6 +1505,7 @@ var ClientProjectionBuilder = class {
|
|
|
1486
1505
|
case "compaction:start":
|
|
1487
1506
|
status = "streaming";
|
|
1488
1507
|
this.activeCompactions.set(compactionId, current);
|
|
1508
|
+
this.failedCompactions.delete(compactionId);
|
|
1489
1509
|
break;
|
|
1490
1510
|
case "compaction:end":
|
|
1491
1511
|
status = "completed";
|
|
@@ -1498,11 +1518,17 @@ var ClientProjectionBuilder = class {
|
|
|
1498
1518
|
case "compaction:error":
|
|
1499
1519
|
status = "failed";
|
|
1500
1520
|
this.activeCompactions.delete(compactionId);
|
|
1521
|
+
this.failedCompactions.set(compactionId, { ...current });
|
|
1501
1522
|
break;
|
|
1502
1523
|
default:
|
|
1503
1524
|
status = "streaming";
|
|
1504
1525
|
this.activeCompactions.set(compactionId, current);
|
|
1505
1526
|
}
|
|
1527
|
+
const failed = this.failedCompactions.get(compactionId);
|
|
1528
|
+
if (failed && status !== "failed") {
|
|
1529
|
+
current = { ...failed, ...current };
|
|
1530
|
+
status = "failed";
|
|
1531
|
+
}
|
|
1506
1532
|
const turn = buildCompactionTurn(this.nextSeq(), compactionId, loopId, status, current);
|
|
1507
1533
|
return [{ kind: "upsert", turn }];
|
|
1508
1534
|
}
|
|
@@ -3037,6 +3063,11 @@ function extractTerminalChatEndStatus(events) {
|
|
|
3037
3063
|
}
|
|
3038
3064
|
return null;
|
|
3039
3065
|
}
|
|
3066
|
+
function hasChatRunEvent(events) {
|
|
3067
|
+
return events.some(
|
|
3068
|
+
(event) => event.type !== "session:post_chat_followup" && !event.type.startsWith("compaction:")
|
|
3069
|
+
);
|
|
3070
|
+
}
|
|
3040
3071
|
function isUiMetaLike(value) {
|
|
3041
3072
|
return isRecord5(value) && ("resourceHTML" in value || "resourceUri" in value || "resourceURI" in value);
|
|
3042
3073
|
}
|
|
@@ -3059,6 +3090,7 @@ var AgentSession = class _AgentSession {
|
|
|
3059
3090
|
disposed = false;
|
|
3060
3091
|
getAppContext = null;
|
|
3061
3092
|
sendPending = false;
|
|
3093
|
+
manualCompactionPending = false;
|
|
3062
3094
|
deliveredCommandKeys = /* @__PURE__ */ new Set();
|
|
3063
3095
|
deliveredToolPreviews = /* @__PURE__ */ new Map();
|
|
3064
3096
|
oomNotifiedKeys = /* @__PURE__ */ new Set();
|
|
@@ -3153,22 +3185,26 @@ var AgentSession = class _AgentSession {
|
|
|
3153
3185
|
/** 发送一条消息。字符串或多模态内容均可。 */
|
|
3154
3186
|
async send(content, options = {}) {
|
|
3155
3187
|
this.runtime.ensureConnected();
|
|
3156
|
-
if (this.state.isStreaming || this.sendPending) {
|
|
3157
|
-
this.update(
|
|
3158
|
-
|
|
3188
|
+
if (this.state.isStreaming || this.state.activeCompaction || this.sendPending || this.manualCompactionPending) {
|
|
3189
|
+
this.update(
|
|
3190
|
+
(s) => addErrorMessage(s, "\u5F53\u524D\u56DE\u590D\u5C1A\u672A\u7ED3\u675F\u6216\u5BF9\u8BDD\u6B63\u5728\u6574\u7406\uFF0C\u8BF7\u7A0D\u540E\u518D\u53D1\u9001\u3002")
|
|
3191
|
+
);
|
|
3192
|
+
return false;
|
|
3159
3193
|
}
|
|
3160
3194
|
this.sendPending = true;
|
|
3161
3195
|
try {
|
|
3162
|
-
await this.sendUnlocked(content, options);
|
|
3196
|
+
return await this.sendUnlocked(content, options);
|
|
3163
3197
|
} finally {
|
|
3164
3198
|
this.sendPending = false;
|
|
3165
3199
|
}
|
|
3166
3200
|
}
|
|
3167
3201
|
async sendUnlocked(content, options) {
|
|
3168
3202
|
await this.ensureIdleBeforeSend();
|
|
3169
|
-
if (this.state.isStreaming) {
|
|
3170
|
-
this.update(
|
|
3171
|
-
|
|
3203
|
+
if (this.state.isStreaming || this.state.activeCompaction || this.manualCompactionPending) {
|
|
3204
|
+
this.update(
|
|
3205
|
+
(s) => addErrorMessage(s, "\u5F53\u524D\u56DE\u590D\u5C1A\u672A\u7ED3\u675F\u6216\u5BF9\u8BDD\u6B63\u5728\u6574\u7406\uFF0C\u8BF7\u7A0D\u540E\u518D\u53D1\u9001\u3002")
|
|
3206
|
+
);
|
|
3207
|
+
return false;
|
|
3172
3208
|
}
|
|
3173
3209
|
let appContext;
|
|
3174
3210
|
if (this.getAppContext) {
|
|
@@ -3189,19 +3225,28 @@ var AgentSession = class _AgentSession {
|
|
|
3189
3225
|
} catch (error) {
|
|
3190
3226
|
const message = error instanceof Error && error.message ? `\u8BFB\u53D6\u5E94\u7528\u4E0A\u4E0B\u6587\u5931\u8D25\uFF1A${error.message}` : "\u8BFB\u53D6\u5E94\u7528\u4E0A\u4E0B\u6587\u5931\u8D25\uFF0C\u6D88\u606F\u672A\u53D1\u9001";
|
|
3191
3227
|
this.update((s) => addErrorMessage(s, message));
|
|
3192
|
-
return;
|
|
3228
|
+
return false;
|
|
3193
3229
|
}
|
|
3194
3230
|
}
|
|
3195
3231
|
const askUserAnswer = options.askUserAnswer;
|
|
3232
|
+
let optimisticTurnId = null;
|
|
3233
|
+
let optimisticAskAnswer;
|
|
3234
|
+
let previousAskAnswer;
|
|
3196
3235
|
if (!(askUserAnswer && typeof askUserAnswer.tool_call_id === "string")) {
|
|
3197
|
-
this.update((
|
|
3236
|
+
this.update((state) => {
|
|
3237
|
+
const next = addUserMessage(state, content);
|
|
3238
|
+
optimisticTurnId = next.turns.at(-1)?.turn_id ?? null;
|
|
3239
|
+
return next;
|
|
3240
|
+
});
|
|
3198
3241
|
}
|
|
3199
3242
|
this.update((s) => ({ ...s, isStreaming: true }));
|
|
3200
3243
|
if (askUserAnswer && typeof askUserAnswer.tool_call_id === "string") {
|
|
3201
3244
|
const { tool_call_id, ...rest } = askUserAnswer;
|
|
3245
|
+
previousAskAnswer = this.state.askAnswers[tool_call_id];
|
|
3246
|
+
optimisticAskAnswer = rest;
|
|
3202
3247
|
this.update((s) => ({
|
|
3203
3248
|
...s,
|
|
3204
|
-
askAnswers: { ...s.askAnswers, [tool_call_id]:
|
|
3249
|
+
askAnswers: { ...s.askAnswers, [tool_call_id]: optimisticAskAnswer }
|
|
3205
3250
|
}));
|
|
3206
3251
|
}
|
|
3207
3252
|
if (!options.replayDecision) {
|
|
@@ -3222,15 +3267,54 @@ var AgentSession = class _AgentSession {
|
|
|
3222
3267
|
try {
|
|
3223
3268
|
await this.ensureJoined();
|
|
3224
3269
|
} catch (error) {
|
|
3225
|
-
this.
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3270
|
+
this.rollbackOptimisticSend(
|
|
3271
|
+
optimisticTurnId,
|
|
3272
|
+
askUserAnswer,
|
|
3273
|
+
optimisticAskAnswer,
|
|
3274
|
+
previousAskAnswer,
|
|
3275
|
+
error instanceof Error && error.message ? error.message : "\u4F1A\u8BDD\u8BA2\u9605\u5931\u8D25\uFF0C\u6D88\u606F\u672A\u53D1\u9001"
|
|
3230
3276
|
);
|
|
3231
|
-
return;
|
|
3277
|
+
return false;
|
|
3278
|
+
}
|
|
3279
|
+
try {
|
|
3280
|
+
const response = await this.runtime.emitWithAck("chat:send", payload, 3e4);
|
|
3281
|
+
if (response?.status !== "accepted") {
|
|
3282
|
+
throw new Error(
|
|
3283
|
+
typeof response?.message === "string" ? response.message : "\u6D88\u606F\u672A\u88AB\u670D\u52A1\u7AEF\u63A5\u53D7"
|
|
3284
|
+
);
|
|
3285
|
+
}
|
|
3286
|
+
return true;
|
|
3287
|
+
} catch (error) {
|
|
3288
|
+
this.rollbackOptimisticSend(
|
|
3289
|
+
optimisticTurnId,
|
|
3290
|
+
askUserAnswer,
|
|
3291
|
+
optimisticAskAnswer,
|
|
3292
|
+
previousAskAnswer,
|
|
3293
|
+
error instanceof Error && error.message ? error.message : "\u6D88\u606F\u53D1\u9001\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5"
|
|
3294
|
+
);
|
|
3295
|
+
return false;
|
|
3232
3296
|
}
|
|
3233
|
-
|
|
3297
|
+
}
|
|
3298
|
+
rollbackOptimisticSend(optimisticTurnId, askUserAnswer, optimisticAskAnswer, previousAskAnswer, message) {
|
|
3299
|
+
this.pendingReplayMessage = null;
|
|
3300
|
+
this.pendingReplayMode = void 0;
|
|
3301
|
+
this.update((current) => {
|
|
3302
|
+
let next = optimisticTurnId ? withTurns(
|
|
3303
|
+
current,
|
|
3304
|
+
current.turns.filter((turn) => turn.turn_id !== optimisticTurnId)
|
|
3305
|
+
) : current;
|
|
3306
|
+
const toolCallId = askUserAnswer && typeof askUserAnswer.tool_call_id === "string" ? askUserAnswer.tool_call_id : null;
|
|
3307
|
+
if (toolCallId && next.askAnswers[toolCallId] === optimisticAskAnswer) {
|
|
3308
|
+
const askAnswers = { ...next.askAnswers };
|
|
3309
|
+
if (previousAskAnswer === void 0) {
|
|
3310
|
+
delete askAnswers[toolCallId];
|
|
3311
|
+
} else {
|
|
3312
|
+
askAnswers[toolCallId] = previousAskAnswer;
|
|
3313
|
+
}
|
|
3314
|
+
next = { ...next, askAnswers };
|
|
3315
|
+
}
|
|
3316
|
+
return addErrorMessage({ ...next, isStreaming: false }, message);
|
|
3317
|
+
});
|
|
3234
3318
|
}
|
|
3235
3319
|
/** 智能体运行期间追加补充说明(不打断当前回复)。 */
|
|
3236
3320
|
append(text) {
|
|
@@ -3244,7 +3328,28 @@ var AgentSession = class _AgentSession {
|
|
|
3244
3328
|
}
|
|
3245
3329
|
/** 手动触发上下文压缩。 */
|
|
3246
3330
|
compact() {
|
|
3247
|
-
|
|
3331
|
+
if (this.state.isStreaming || this.state.activeCompaction || this.manualCompactionPending) {
|
|
3332
|
+
return Promise.resolve({
|
|
3333
|
+
status: "error",
|
|
3334
|
+
message: "\u5F53\u524D\u56DE\u590D\u5C1A\u672A\u7ED3\u675F\u6216\u5BF9\u8BDD\u6B63\u5728\u6574\u7406\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5\u3002"
|
|
3335
|
+
});
|
|
3336
|
+
}
|
|
3337
|
+
this.manualCompactionPending = true;
|
|
3338
|
+
this.update((state) => ({
|
|
3339
|
+
...state,
|
|
3340
|
+
activeCompaction: {
|
|
3341
|
+
turn_id: "pending-manual-compaction",
|
|
3342
|
+
compaction_id: "pending-manual-compaction",
|
|
3343
|
+
status: "streaming",
|
|
3344
|
+
trigger: "manual"
|
|
3345
|
+
}
|
|
3346
|
+
}));
|
|
3347
|
+
return this.runtime.emitWithAck("chat:compact", { session_id: this.sessionId }, 3e4).then((response) => response ?? {}).finally(() => {
|
|
3348
|
+
this.manualCompactionPending = false;
|
|
3349
|
+
if (this.state.activeCompaction?.compaction_id === "pending-manual-compaction") {
|
|
3350
|
+
this.update((state) => ({ ...state, activeCompaction: null }));
|
|
3351
|
+
}
|
|
3352
|
+
});
|
|
3248
3353
|
}
|
|
3249
3354
|
/**
|
|
3250
3355
|
* 把一段业务数据作为附件放进聊天输入框(比如地图上选中的点位)。
|
|
@@ -3334,10 +3439,7 @@ var AgentSession = class _AgentSession {
|
|
|
3334
3439
|
_handleTurnEvents(events) {
|
|
3335
3440
|
if (!events.length) return;
|
|
3336
3441
|
const terminalChatEndStatus = extractTerminalChatEndStatus(events);
|
|
3337
|
-
|
|
3338
|
-
(event) => event.type === "session:post_chat_followup"
|
|
3339
|
-
);
|
|
3340
|
-
if (!terminalChatEndStatus && !followupOnly) {
|
|
3442
|
+
if (!terminalChatEndStatus && hasChatRunEvent(events)) {
|
|
3341
3443
|
this.markRunningIfIdle();
|
|
3342
3444
|
}
|
|
3343
3445
|
if (this.state.turns.length) {
|
|
@@ -3411,11 +3513,30 @@ var AgentSession = class _AgentSession {
|
|
|
3411
3513
|
this.pendingReplayMessage = null;
|
|
3412
3514
|
this.pendingReplayMode = void 0;
|
|
3413
3515
|
const respond = (decision) => {
|
|
3414
|
-
this.runtime.
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3516
|
+
void this.runtime.emitWithAck(
|
|
3517
|
+
"chat:send",
|
|
3518
|
+
{
|
|
3519
|
+
session_id: this.sessionId,
|
|
3520
|
+
message,
|
|
3521
|
+
mode,
|
|
3522
|
+
replay_decision: decision
|
|
3523
|
+
},
|
|
3524
|
+
3e4
|
|
3525
|
+
).then((response) => {
|
|
3526
|
+
if (response?.status === "accepted") return;
|
|
3527
|
+
this.update(
|
|
3528
|
+
(state) => addErrorMessage(
|
|
3529
|
+
{ ...state, isStreaming: false },
|
|
3530
|
+
typeof response?.message === "string" ? response.message : "\u6D88\u606F\u672A\u88AB\u670D\u52A1\u7AEF\u63A5\u53D7"
|
|
3531
|
+
)
|
|
3532
|
+
);
|
|
3533
|
+
}).catch((error) => {
|
|
3534
|
+
this.update(
|
|
3535
|
+
(state) => addErrorMessage(
|
|
3536
|
+
{ ...state, isStreaming: false },
|
|
3537
|
+
error instanceof Error && error.message ? error.message : "\u6D88\u606F\u53D1\u9001\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5"
|
|
3538
|
+
)
|
|
3539
|
+
);
|
|
3419
3540
|
});
|
|
3420
3541
|
};
|
|
3421
3542
|
const handled = this.emitter.emitFirst("replayMismatch", {
|
|
@@ -3697,6 +3818,18 @@ var AgentSession = class _AgentSession {
|
|
|
3697
3818
|
};
|
|
3698
3819
|
|
|
3699
3820
|
// src/session/hub.ts
|
|
3821
|
+
var BACKGROUND_STATUSES = [
|
|
3822
|
+
"starting",
|
|
3823
|
+
"running",
|
|
3824
|
+
"cancelling",
|
|
3825
|
+
"succeeded",
|
|
3826
|
+
"failed",
|
|
3827
|
+
"cancelled",
|
|
3828
|
+
"lost"
|
|
3829
|
+
];
|
|
3830
|
+
function normalizeBackgroundStatus(value) {
|
|
3831
|
+
return BACKGROUND_STATUSES.includes(value) ? value : "running";
|
|
3832
|
+
}
|
|
3700
3833
|
var SessionHub = class {
|
|
3701
3834
|
client;
|
|
3702
3835
|
sessions = /* @__PURE__ */ new Map();
|
|
@@ -3951,7 +4084,11 @@ var SessionHub = class {
|
|
|
3951
4084
|
id: taskId,
|
|
3952
4085
|
command: typeof task.command === "string" ? task.command : "",
|
|
3953
4086
|
description: typeof task.description === "string" ? task.description : void 0,
|
|
3954
|
-
|
|
4087
|
+
// Pass the server's status through unchanged. Collapsing it here
|
|
4088
|
+
// made subscribers see a successful-looking "done" for tasks the
|
|
4089
|
+
// REST API correctly reported as cancelled or lost.
|
|
4090
|
+
status: normalizeBackgroundStatus(task.status),
|
|
4091
|
+
failureReason: typeof task.failure_reason === "string" ? task.failure_reason : void 0,
|
|
3955
4092
|
exitCode: typeof task.exit_code === "number" || task.exit_code === null ? task.exit_code : void 0,
|
|
3956
4093
|
elapsedSeconds: typeof task.elapsed_seconds === "number" ? task.elapsed_seconds : 0,
|
|
3957
4094
|
output: Array.isArray(task.output_preview) && task.output_preview.length > 0 ? task.output_preview.join("\n") : void 0
|
|
@@ -3994,7 +4131,7 @@ function resolveAuthToken(options) {
|
|
|
3994
4131
|
|
|
3995
4132
|
// src/version.ts
|
|
3996
4133
|
var SDK_NAME = "agent-client";
|
|
3997
|
-
var SDK_VERSION = true ? "1.2.1-
|
|
4134
|
+
var SDK_VERSION = true ? "1.2.1-beta.10" : "1.1.1";
|
|
3998
4135
|
|
|
3999
4136
|
// src/socket.ts
|
|
4000
4137
|
function withSdkIdentity(auth) {
|
|
@@ -4342,12 +4479,31 @@ function resolveTokenOption(tokenOption) {
|
|
|
4342
4479
|
const token = typeof tokenOption === "function" ? tokenOption() : tokenOption;
|
|
4343
4480
|
return token ? token : null;
|
|
4344
4481
|
}
|
|
4482
|
+
var SANDBOX_ONLY_HOST = "host.docker.internal";
|
|
4345
4483
|
function normalizeBaseUrl(baseUrl) {
|
|
4346
4484
|
const normalized = baseUrl.trim().replace(/\/+$/, "");
|
|
4347
|
-
if (
|
|
4485
|
+
if (typeof window === "undefined") {
|
|
4348
4486
|
return normalized;
|
|
4349
4487
|
}
|
|
4350
|
-
|
|
4488
|
+
if (!normalized) {
|
|
4489
|
+
return window.location.origin;
|
|
4490
|
+
}
|
|
4491
|
+
assertBrowserReachable(normalized);
|
|
4492
|
+
return normalized;
|
|
4493
|
+
}
|
|
4494
|
+
function assertBrowserReachable(baseUrl) {
|
|
4495
|
+
let hostname;
|
|
4496
|
+
try {
|
|
4497
|
+
hostname = new URL(baseUrl, window.location.href).hostname;
|
|
4498
|
+
} catch {
|
|
4499
|
+
return;
|
|
4500
|
+
}
|
|
4501
|
+
if (hostname !== SANDBOX_ONLY_HOST) {
|
|
4502
|
+
return;
|
|
4503
|
+
}
|
|
4504
|
+
throw new Error(
|
|
4505
|
+
`Blade Agent \u5730\u5740 ${baseUrl} \u53EA\u6709\u6C99\u76D2\u5185\u90E8\u89E3\u6790\u5F97\u5230\uFF0C\u6D4F\u89C8\u5668\u6253\u4E0D\u5F00\u3002\u8BF7\u628A\u5B83\u6539\u6210\u7528\u6237\u6D4F\u89C8\u5668\u80FD\u8BBF\u95EE\u7684\u5730\u5740\uFF08\u901A\u5E38\u662F\u8BBF\u95EE\u8FD9\u4E2A\u5E94\u7528\u65F6\u7528\u7684\u4E3B\u673A\u540D + Blade Server \u7AEF\u53E3\uFF09\u3002`
|
|
4506
|
+
);
|
|
4351
4507
|
}
|
|
4352
4508
|
function isFormData(value) {
|
|
4353
4509
|
return typeof FormData !== "undefined" && value instanceof FormData;
|