@blade-hq/agent-client 2610.0.1 → 2612.0.0-beta.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 +38 -142
- package/dist/chunk-U2VELZGU.js +7607 -0
- package/dist/chunk-U2VELZGU.js.map +1 -0
- package/dist/embed/mount-renderer.d.ts +50 -0
- package/dist/index.d.ts +16 -59
- package/dist/index.js +22 -7115
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +55 -0
- package/dist/internal.js +340 -0
- package/dist/internal.js.map +1 -0
- package/dist/schemas/projection.d.ts +3 -0
- package/dist/schemas/solution.d.ts +0 -4
- package/dist/session/agent-session.d.ts +82 -12
- package/dist/session/events.d.ts +15 -1
- package/dist/session/hub.d.ts +88 -2
- package/dist/session/state.d.ts +37 -0
- package/dist/session/workflow.d.ts +57 -0
- package/dist/shared/oom.d.ts +5 -0
- package/dist/shared/projection/builder.d.ts +4 -0
- package/dist/shared/projection/helpers.d.ts +3 -0
- package/dist/types/socket-events.d.ts +6 -0
- package/package.json +5 -1
- package/public-api.md +163 -1494
- package/dist/commands/embedded.d.ts +0 -32
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export * from "./index";
|
|
2
|
+
export { isEntryGoneError } from "./resources/sessions";
|
|
3
|
+
export { PollingBackoff } from "./polling-backoff";
|
|
4
|
+
export { EMPTY_PLATFORM_ENDPOINTS, loadPlatformEndpoints, resolveServiceUrl, } from "./platform-endpoints";
|
|
5
|
+
export type { LoadPlatformEndpointsOptions, PlatformEndpoints, PlatformServiceName, } from "./platform-endpoints";
|
|
6
|
+
export { SessionHub } from "./session/hub";
|
|
7
|
+
export type { SessionConnectOptions, SessionHubEvents, SessionHubOptions } from "./session/hub";
|
|
8
|
+
export { sessionStatusFromChatEnd } from "./session/agent-session";
|
|
9
|
+
export type { ChatEndPayload, SessionDetailSnapshot } from "./session/agent-session";
|
|
10
|
+
export { isWorkflowRunToolName, workflowEntriesFromOutput, workflowNameFromArguments, } from "./session/workflow";
|
|
11
|
+
export { isMcpAppData } from "./schemas/mcp-app";
|
|
12
|
+
export type { McpAppArchive, McpAppContextState, McpAppContextUpdate, McpAppData, } from "./schemas/mcp-app";
|
|
13
|
+
export { applyTurnPatch, createInitialSessionState, parentForkToolCallIdFromTurn, upsertTurn, withTurns, reconcileHistoricalUserTurns, reconcileOptimisticUserTurns, toReplaySnapshot, } from "./session/state";
|
|
14
|
+
export { EMPTY_SESSION_QUEUE, canCancelQueuedMessage, canDeliverQueuedMessage, canEditQueuedMessage, isSessionQueueSnapshot, parseQueueAck, queuePauseReasonLabel, queuedMessageStatusLabel, shouldApplySnapshot, } from "./session/queue";
|
|
15
|
+
export type { QueueAck } from "./session/queue";
|
|
16
|
+
export { prependOlder, replaceWindow } from "./session/history-page";
|
|
17
|
+
export type { LiveRevisionState } from "./session/history-page";
|
|
18
|
+
export type { CommandEnvelope, InboundAction, InboundEnvelope } from "./commands/protocol";
|
|
19
|
+
export { isCommandEnvelope, isInboundEnvelope } from "./commands/protocol";
|
|
20
|
+
export { canToggleComputer, computerDaemonVersion, computerOS, computerPlatformLabel, computerState, sortComputers, } from "./resources/computers";
|
|
21
|
+
export type { AccountComputerList, ComputerOS, ComputerState, SessionComputerList, } from "./resources/computers";
|
|
22
|
+
export { ModelsResource } from "./resources/models";
|
|
23
|
+
export { ComputersResource } from "./resources/computers";
|
|
24
|
+
export type { SessionPlugin, SessionPluginActivation } from "./resources/sessions";
|
|
25
|
+
export type { SessionPluginConfigError, SessionPluginConfigSet, SessionPluginConfigState, SessionPluginConfigStateName, SessionPluginConfigSummary, SessionPluginConfigUpdate, } from "./resources/sessions";
|
|
26
|
+
export { ChatGroupsResource } from "./resources/chat-groups";
|
|
27
|
+
export type { ChatGroup } from "./resources/chat-groups";
|
|
28
|
+
export { PluginsResource } from "./resources/plugins";
|
|
29
|
+
export type { PluginCatalogEntry } from "./resources/plugins";
|
|
30
|
+
export type { SiteVisitsResource, SiteVisitsSummary } from "./resources/site-visits";
|
|
31
|
+
export type { GlobalSearchConversationResult, GlobalSearchFileResult, GlobalSearchResult, GlobalSearchResultItem, HistoricalCommand, ImportSessionOptions, ResultFeedback, ResultFeedbackReason, SessionContextStats, SessionHistory, SessionTurnIndex, SessionTurnIndexItem, ShareLinkResult, } from "./resources/sessions";
|
|
32
|
+
export type { ArchivedFileInfo, ArchivedToolCallInfo, CompactionInfo, ToolBridgeContent, } from "./schemas/message";
|
|
33
|
+
export { inferToolStatus } from "./schemas/message";
|
|
34
|
+
export type { ChatEnd, ContentDelta, LlmResponseDone, SessionStatusEvent, SystemError, ToolCallArgumentsDelta, ToolCallCreated, ToolResultDelta, ToolResultDone, } from "./schemas/event";
|
|
35
|
+
export { buildMessageContent, extractTextAttachments, isBackgroundWakeMessage, isHiddenInternalMessage, normalizeMessageContent, } from "./schemas/message-utils";
|
|
36
|
+
export type { ParsedTextAttachment, ParsedTextContext } from "./schemas/message-utils";
|
|
37
|
+
export { contextProjectionData, getContextDisplayState, getContextGroupDisplayState, groupAdjacentContextRuns, } from "./schemas/context";
|
|
38
|
+
export type { ContextAction, ContextDisplayState, ContextGroupDisplayState, ContextProjectionData, ContextProjectionFields, ContextSourceInfo, } from "./schemas/context";
|
|
39
|
+
export type { ContentBlock, FinalArtifact, MemoryRef, PatchEnvelope, PendingQuestionRef, PostChatFollowup, RunTiming, ToolCallProjection, TurnProjection, } from "./schemas/projection";
|
|
40
|
+
export { latestPostChatFollowup } from "./schemas/projection-utils";
|
|
41
|
+
export { buildToolUiCardKey, collectInlineToolUiCards, collectPreviewToolUiCards, isAppDevToolUiCard, isInternalStatusToolUiCard, isToolUiCard, resolveToolUiCardContent, } from "./shared/tool-ui-card";
|
|
42
|
+
export type { InlineToolUiCardEntry, PreviewToolUiCardEntry, ToolUiCard, ToolUiCardContentType, } from "./shared/tool-ui-card";
|
|
43
|
+
export type { ModeId, PrimarySkillParallelMode, PrimarySkillSnapshot, PrimarySkillStageSpec, PrimarySkillStepSpec, PublishedSolutionRef, ReplayPreview, SessionPortMapping, SessionSearchMatch, SkillEditorTemplateId, TemplateId, } from "./schemas/session";
|
|
44
|
+
export { LayoutType } from "./schemas/solution";
|
|
45
|
+
export type { BizRole, Solution, SolutionAppField, SolutionAppState, SolutionAppUiConfig, } from "./schemas/solution";
|
|
46
|
+
export { Task, TaskStatus } from "./schemas/task";
|
|
47
|
+
export type { BackgroundTask, BackgroundTaskStopResult } from "./schemas/background";
|
|
48
|
+
export type * from "./types/sdk-profile";
|
|
49
|
+
export { acceptedPostChatFollowupCompletesLatestRun, acknowledgeTurnEvents, ClientProjectionBuilder, hasChatRunEvent, } from "./shared/projection";
|
|
50
|
+
export type { RawEvent } from "./shared/projection";
|
|
51
|
+
export { AuthBusyReconnect, authBusyRetryDelayMs } from "./shared/auth-busy";
|
|
52
|
+
export { isOomText, OOM_MESSAGE } from "./shared/oom";
|
|
53
|
+
export { createSocket } from "./socket";
|
|
54
|
+
export type { CreateSocketOptions, TypedSocket } from "./socket";
|
|
55
|
+
export type { AsrAudioPayload } from "./types/socket-events";
|
package/dist/internal.js
ADDED
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AgentSession,
|
|
3
|
+
AgentSessionError,
|
|
4
|
+
AuthBusyReconnect,
|
|
5
|
+
BladeApiError,
|
|
6
|
+
BladeClient,
|
|
7
|
+
ChatGroupsResource,
|
|
8
|
+
ClientProjectionBuilder,
|
|
9
|
+
ComputersResource,
|
|
10
|
+
DEFAULT_REPLAY_SPEED,
|
|
11
|
+
EMPTY_SESSION_QUEUE,
|
|
12
|
+
ModelsResource,
|
|
13
|
+
OOM_MESSAGE,
|
|
14
|
+
PluginsResource,
|
|
15
|
+
SDK_NAME,
|
|
16
|
+
SDK_VERSION,
|
|
17
|
+
SessionHub,
|
|
18
|
+
SessionInfo,
|
|
19
|
+
SessionSetupError,
|
|
20
|
+
SessionStatus,
|
|
21
|
+
acceptedPostChatFollowupCompletesLatestRun,
|
|
22
|
+
acknowledgeTurnEvents,
|
|
23
|
+
applyTurnPatch,
|
|
24
|
+
authBusyRetryDelayMs,
|
|
25
|
+
buildMessageContent,
|
|
26
|
+
buildToolUiCardKey,
|
|
27
|
+
canCancelQueuedMessage,
|
|
28
|
+
canDeliverQueuedMessage,
|
|
29
|
+
canEditQueuedMessage,
|
|
30
|
+
canToggleComputer,
|
|
31
|
+
chatErrorForDisplay,
|
|
32
|
+
collectInlineToolUiCards,
|
|
33
|
+
collectPreviewToolUiCards,
|
|
34
|
+
computerDaemonVersion,
|
|
35
|
+
computerOS,
|
|
36
|
+
computerPlatformLabel,
|
|
37
|
+
computerState,
|
|
38
|
+
contentPreview,
|
|
39
|
+
contextProjectionData,
|
|
40
|
+
createInitialSessionState,
|
|
41
|
+
createSocket,
|
|
42
|
+
extractTextAttachments,
|
|
43
|
+
getContextDisplayState,
|
|
44
|
+
getContextGroupDisplayState,
|
|
45
|
+
getFileParts,
|
|
46
|
+
getImageParts,
|
|
47
|
+
getTextContent,
|
|
48
|
+
groupAdjacentContextRuns,
|
|
49
|
+
groupMessagesByLoop,
|
|
50
|
+
hasChatRunEvent,
|
|
51
|
+
inferToolStatus,
|
|
52
|
+
isAppDevToolUiCard,
|
|
53
|
+
isBackgroundWakeMessage,
|
|
54
|
+
isEntryGoneError,
|
|
55
|
+
isHiddenInternalMessage,
|
|
56
|
+
isInternalStatusToolUiCard,
|
|
57
|
+
isMcpAppData,
|
|
58
|
+
isOomText,
|
|
59
|
+
isRecord,
|
|
60
|
+
isSessionQueueSnapshot,
|
|
61
|
+
isToolUiCard,
|
|
62
|
+
isWorkflowRunToolName,
|
|
63
|
+
normalizeMessageContent,
|
|
64
|
+
parentForkToolCallIdFromTurn,
|
|
65
|
+
parseQueueAck,
|
|
66
|
+
prependOlder,
|
|
67
|
+
queuePauseReasonLabel,
|
|
68
|
+
queuedMessageStatusLabel,
|
|
69
|
+
reconcileHistoricalUserTurns,
|
|
70
|
+
reconcileOptimisticUserTurns,
|
|
71
|
+
replaceWindow,
|
|
72
|
+
resolveToolUiCardContent,
|
|
73
|
+
sessionStatusFromChatEnd,
|
|
74
|
+
shouldApplySnapshot,
|
|
75
|
+
sortComputers,
|
|
76
|
+
toReplaySnapshot,
|
|
77
|
+
transformSlashCommand,
|
|
78
|
+
upsertTurn,
|
|
79
|
+
userFacingErrorText,
|
|
80
|
+
withTurns,
|
|
81
|
+
workflowEntriesFromOutput,
|
|
82
|
+
workflowNameFromArguments
|
|
83
|
+
} from "./chunk-U2VELZGU.js";
|
|
84
|
+
|
|
85
|
+
// src/polling-backoff.ts
|
|
86
|
+
var MAX_BACKOFF_MS = 6e4;
|
|
87
|
+
var MAX_TIMER_MS = 2147483647;
|
|
88
|
+
var PollingBackoff = class {
|
|
89
|
+
constructor(intervalMs) {
|
|
90
|
+
this.intervalMs = intervalMs;
|
|
91
|
+
if (!Number.isFinite(intervalMs) || intervalMs <= 0 || intervalMs > MAX_BACKOFF_MS) {
|
|
92
|
+
throw new RangeError("Polling interval must be between 0 and 60000 ms");
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
intervalMs;
|
|
96
|
+
failures = 0;
|
|
97
|
+
nextAt = 0;
|
|
98
|
+
reset() {
|
|
99
|
+
this.failures = 0;
|
|
100
|
+
this.nextAt = 0;
|
|
101
|
+
}
|
|
102
|
+
failed(error) {
|
|
103
|
+
if (error instanceof Error && error.name === "AbortError" || error instanceof BladeApiError && error.status < 500 && error.status !== 408 && error.status !== 429) {
|
|
104
|
+
this.nextAt = false;
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
this.failures = Math.min(this.failures + 1, 10);
|
|
108
|
+
const ceiling = Math.min(MAX_BACKOFF_MS, this.intervalMs * 2 ** this.failures);
|
|
109
|
+
const backoff = Math.max(this.intervalMs, ceiling * (0.5 + Math.random() * 0.5));
|
|
110
|
+
const header = error instanceof BladeApiError ? error.response.headers.get("Retry-After")?.trim() : void 0;
|
|
111
|
+
const retryAfter = header ? /^\d+$/.test(header) ? Number(header) * 1e3 : Date.parse(header) - Date.now() : 0;
|
|
112
|
+
const delay = Math.max(backoff, Number.isNaN(retryAfter) ? 0 : retryAfter);
|
|
113
|
+
this.nextAt = delay > MAX_TIMER_MS ? false : Date.now() + delay;
|
|
114
|
+
}
|
|
115
|
+
/** Zero means ready, false means stop, otherwise wait at least this many ms. */
|
|
116
|
+
waitMs() {
|
|
117
|
+
return this.nextAt === false ? false : Math.max(0, this.nextAt - Date.now());
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
// src/platform-endpoints.ts
|
|
122
|
+
var PLATFORM_SERVICE_NAMES = [
|
|
123
|
+
"os",
|
|
124
|
+
"hub",
|
|
125
|
+
"agent",
|
|
126
|
+
"oauth",
|
|
127
|
+
"llmGateway",
|
|
128
|
+
"gitea",
|
|
129
|
+
"tile"
|
|
130
|
+
];
|
|
131
|
+
var EMPTY_PLATFORM_ENDPOINTS = Object.freeze({
|
|
132
|
+
services: Object.freeze({})
|
|
133
|
+
});
|
|
134
|
+
function defaultDocumentBaseUrl() {
|
|
135
|
+
if (typeof document === "undefined") return void 0;
|
|
136
|
+
if (document.querySelector("base[href]")) return document.baseURI;
|
|
137
|
+
if (typeof location !== "undefined" && location.origin) return `${location.origin}/`;
|
|
138
|
+
return document.baseURI;
|
|
139
|
+
}
|
|
140
|
+
function normalizeServiceUrl(value) {
|
|
141
|
+
if (typeof value !== "string" || !value.trim()) return null;
|
|
142
|
+
if (value.includes("?") || value.includes("#")) return null;
|
|
143
|
+
try {
|
|
144
|
+
const url = new URL(value.trim());
|
|
145
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") return null;
|
|
146
|
+
if (url.username || url.password || url.search || url.hash) return null;
|
|
147
|
+
return url.toString().replace(/\/$/, "");
|
|
148
|
+
} catch {
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
function parsePlatformEndpoints(value) {
|
|
153
|
+
if (!isRecord(value) || !isRecord(value.services)) return null;
|
|
154
|
+
const services = {};
|
|
155
|
+
for (const name of PLATFORM_SERVICE_NAMES) {
|
|
156
|
+
if (!(name in value.services)) continue;
|
|
157
|
+
const url = normalizeServiceUrl(value.services[name]);
|
|
158
|
+
if (!url) return null;
|
|
159
|
+
if (name === "agent" && new URL(url).pathname !== "/") return null;
|
|
160
|
+
services[name] = url;
|
|
161
|
+
}
|
|
162
|
+
return { services };
|
|
163
|
+
}
|
|
164
|
+
async function loadPlatformEndpoints(options = {}) {
|
|
165
|
+
const fetchImpl = options.fetchImpl ?? globalThis.fetch;
|
|
166
|
+
const baseUrl = options.baseUrl ?? defaultDocumentBaseUrl();
|
|
167
|
+
if (!fetchImpl || !baseUrl) return EMPTY_PLATFORM_ENDPOINTS;
|
|
168
|
+
const controller = new AbortController();
|
|
169
|
+
const timeout = globalThis.setTimeout(() => controller.abort(), options.timeoutMs ?? 3e3);
|
|
170
|
+
try {
|
|
171
|
+
const response = await fetchImpl(new URL("config.json", baseUrl), {
|
|
172
|
+
cache: "no-store",
|
|
173
|
+
credentials: "same-origin",
|
|
174
|
+
headers: { Accept: "application/json" },
|
|
175
|
+
signal: controller.signal
|
|
176
|
+
});
|
|
177
|
+
if (!response.ok) return EMPTY_PLATFORM_ENDPOINTS;
|
|
178
|
+
return parsePlatformEndpoints(await response.json()) ?? EMPTY_PLATFORM_ENDPOINTS;
|
|
179
|
+
} catch {
|
|
180
|
+
return EMPTY_PLATFORM_ENDPOINTS;
|
|
181
|
+
} finally {
|
|
182
|
+
globalThis.clearTimeout(timeout);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
function resolveServiceUrl(endpoints, name, path = "") {
|
|
186
|
+
const baseUrl = endpoints.services[name];
|
|
187
|
+
if (!baseUrl) return null;
|
|
188
|
+
if (!path) return baseUrl;
|
|
189
|
+
const pathReference = path.trimStart();
|
|
190
|
+
if (path.includes("\\") || pathReference.startsWith("//") || /^[a-z][a-z0-9+.-]*:/i.test(pathReference)) {
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
const base = new URL(`${baseUrl}/`);
|
|
194
|
+
const target = new URL(path.replace(/^\/+/, ""), base);
|
|
195
|
+
if (target.origin !== base.origin || !target.pathname.startsWith(base.pathname)) {
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
return target.toString();
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// src/commands/protocol.ts
|
|
202
|
+
function isCommandEnvelope(value) {
|
|
203
|
+
if (typeof value !== "object" || value === null) return false;
|
|
204
|
+
const record = value;
|
|
205
|
+
return record.__bladeBridge === true && record.direction === "agent-to-host" && typeof record.action === "string";
|
|
206
|
+
}
|
|
207
|
+
function isInboundEnvelope(value) {
|
|
208
|
+
if (typeof value !== "object" || value === null) return false;
|
|
209
|
+
const record = value;
|
|
210
|
+
return record.__bladeBridge === true && record.direction === "host-to-agent" && (record.action === "addContext" || record.action === "appendInput" || record.action === "sendMessage");
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// src/schemas/projection-utils.ts
|
|
214
|
+
function latestPostChatFollowup(turns) {
|
|
215
|
+
for (let index = turns.length - 1; index >= 0; index -= 1) {
|
|
216
|
+
const turn = turns[index];
|
|
217
|
+
if (turn.loop_id === "root" && (turn.role === "user" || turn.role === "assistant") && (turn.kind ?? "message") === "message" && !turn.blocks.some(
|
|
218
|
+
(block) => ["mode_change", "plan_status", "ask_user_answer"].includes(block.type)
|
|
219
|
+
)) {
|
|
220
|
+
return turn.role === "assistant" ? turn.post_chat_followup ?? null : null;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// src/schemas/solution.ts
|
|
227
|
+
var LayoutType = /* @__PURE__ */ ((LayoutType2) => {
|
|
228
|
+
LayoutType2["Default"] = "default";
|
|
229
|
+
LayoutType2["SkillEditor"] = "skill-editor";
|
|
230
|
+
LayoutType2["SolutionEditor"] = "solution-editor";
|
|
231
|
+
LayoutType2["SolutionApp"] = "solution-app";
|
|
232
|
+
LayoutType2["Custom"] = "custom";
|
|
233
|
+
return LayoutType2;
|
|
234
|
+
})(LayoutType || {});
|
|
235
|
+
|
|
236
|
+
// src/schemas/task.ts
|
|
237
|
+
import { type } from "arktype";
|
|
238
|
+
var TaskStatus = type("'pending' | 'in_progress' | 'done' | 'failed' | 'skipped'");
|
|
239
|
+
var Task = type({
|
|
240
|
+
id: "string",
|
|
241
|
+
goal: "string",
|
|
242
|
+
skills: "string[]",
|
|
243
|
+
depends_on: "string[]",
|
|
244
|
+
status: TaskStatus,
|
|
245
|
+
result_summary: "string",
|
|
246
|
+
number: "string"
|
|
247
|
+
});
|
|
248
|
+
export {
|
|
249
|
+
AgentSession,
|
|
250
|
+
AgentSessionError,
|
|
251
|
+
AuthBusyReconnect,
|
|
252
|
+
BladeApiError,
|
|
253
|
+
BladeClient,
|
|
254
|
+
ChatGroupsResource,
|
|
255
|
+
ClientProjectionBuilder,
|
|
256
|
+
ComputersResource,
|
|
257
|
+
DEFAULT_REPLAY_SPEED,
|
|
258
|
+
EMPTY_PLATFORM_ENDPOINTS,
|
|
259
|
+
EMPTY_SESSION_QUEUE,
|
|
260
|
+
LayoutType,
|
|
261
|
+
ModelsResource,
|
|
262
|
+
OOM_MESSAGE,
|
|
263
|
+
PluginsResource,
|
|
264
|
+
PollingBackoff,
|
|
265
|
+
SDK_NAME,
|
|
266
|
+
SDK_VERSION,
|
|
267
|
+
SessionHub,
|
|
268
|
+
SessionInfo,
|
|
269
|
+
SessionSetupError,
|
|
270
|
+
SessionStatus,
|
|
271
|
+
Task,
|
|
272
|
+
TaskStatus,
|
|
273
|
+
acceptedPostChatFollowupCompletesLatestRun,
|
|
274
|
+
acknowledgeTurnEvents,
|
|
275
|
+
applyTurnPatch,
|
|
276
|
+
authBusyRetryDelayMs,
|
|
277
|
+
buildMessageContent,
|
|
278
|
+
buildToolUiCardKey,
|
|
279
|
+
canCancelQueuedMessage,
|
|
280
|
+
canDeliverQueuedMessage,
|
|
281
|
+
canEditQueuedMessage,
|
|
282
|
+
canToggleComputer,
|
|
283
|
+
chatErrorForDisplay,
|
|
284
|
+
collectInlineToolUiCards,
|
|
285
|
+
collectPreviewToolUiCards,
|
|
286
|
+
computerDaemonVersion,
|
|
287
|
+
computerOS,
|
|
288
|
+
computerPlatformLabel,
|
|
289
|
+
computerState,
|
|
290
|
+
contentPreview,
|
|
291
|
+
contextProjectionData,
|
|
292
|
+
createInitialSessionState,
|
|
293
|
+
createSocket,
|
|
294
|
+
extractTextAttachments,
|
|
295
|
+
getContextDisplayState,
|
|
296
|
+
getContextGroupDisplayState,
|
|
297
|
+
getFileParts,
|
|
298
|
+
getImageParts,
|
|
299
|
+
getTextContent,
|
|
300
|
+
groupAdjacentContextRuns,
|
|
301
|
+
groupMessagesByLoop,
|
|
302
|
+
hasChatRunEvent,
|
|
303
|
+
inferToolStatus,
|
|
304
|
+
isAppDevToolUiCard,
|
|
305
|
+
isBackgroundWakeMessage,
|
|
306
|
+
isCommandEnvelope,
|
|
307
|
+
isEntryGoneError,
|
|
308
|
+
isHiddenInternalMessage,
|
|
309
|
+
isInboundEnvelope,
|
|
310
|
+
isInternalStatusToolUiCard,
|
|
311
|
+
isMcpAppData,
|
|
312
|
+
isOomText,
|
|
313
|
+
isSessionQueueSnapshot,
|
|
314
|
+
isToolUiCard,
|
|
315
|
+
isWorkflowRunToolName,
|
|
316
|
+
latestPostChatFollowup,
|
|
317
|
+
loadPlatformEndpoints,
|
|
318
|
+
normalizeMessageContent,
|
|
319
|
+
parentForkToolCallIdFromTurn,
|
|
320
|
+
parseQueueAck,
|
|
321
|
+
prependOlder,
|
|
322
|
+
queuePauseReasonLabel,
|
|
323
|
+
queuedMessageStatusLabel,
|
|
324
|
+
reconcileHistoricalUserTurns,
|
|
325
|
+
reconcileOptimisticUserTurns,
|
|
326
|
+
replaceWindow,
|
|
327
|
+
resolveServiceUrl,
|
|
328
|
+
resolveToolUiCardContent,
|
|
329
|
+
sessionStatusFromChatEnd,
|
|
330
|
+
shouldApplySnapshot,
|
|
331
|
+
sortComputers,
|
|
332
|
+
toReplaySnapshot,
|
|
333
|
+
transformSlashCommand,
|
|
334
|
+
upsertTurn,
|
|
335
|
+
userFacingErrorText,
|
|
336
|
+
withTurns,
|
|
337
|
+
workflowEntriesFromOutput,
|
|
338
|
+
workflowNameFromArguments
|
|
339
|
+
};
|
|
340
|
+
//# sourceMappingURL=internal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/polling-backoff.ts","../src/platform-endpoints.ts","../src/commands/protocol.ts","../src/schemas/projection-utils.ts","../src/schemas/solution.ts","../src/schemas/task.ts"],"sourcesContent":["import { BladeApiError } from \"./rest\"\n\nconst MAX_BACKOFF_MS = 60_000\nconst MAX_TIMER_MS = 2_147_483_647\n\n/** Scheduling policy for read-only polling; never sends or replays a request. */\nexport class PollingBackoff {\n private failures = 0\n private nextAt: number | false = 0\n\n constructor(private readonly intervalMs: number) {\n if (!Number.isFinite(intervalMs) || intervalMs <= 0 || intervalMs > MAX_BACKOFF_MS) {\n throw new RangeError(\"Polling interval must be between 0 and 60000 ms\")\n }\n }\n\n reset(): void {\n this.failures = 0\n this.nextAt = 0\n }\n\n failed(error: unknown): void {\n if (\n (error instanceof Error && error.name === \"AbortError\") ||\n (error instanceof BladeApiError && error.status < 500 &&\n error.status !== 408 && error.status !== 429)\n ) {\n this.nextAt = false\n return\n }\n this.failures = Math.min(this.failures + 1, 10)\n const ceiling = Math.min(MAX_BACKOFF_MS, this.intervalMs * 2 ** this.failures)\n const backoff = Math.max(this.intervalMs, ceiling * (0.5 + Math.random() * 0.5))\n const header = error instanceof BladeApiError\n ? error.response.headers.get(\"Retry-After\")?.trim()\n : undefined\n const retryAfter = header\n ? /^\\d+$/.test(header) ? Number(header) * 1000 : Date.parse(header) - Date.now()\n : 0\n const delay = Math.max(backoff, Number.isNaN(retryAfter) ? 0 : retryAfter)\n // Oversized server delays must not overflow browser timers into a hot loop.\n this.nextAt = delay > MAX_TIMER_MS ? false : Date.now() + delay\n }\n\n /** Zero means ready, false means stop, otherwise wait at least this many ms. */\n waitMs(): number | false {\n return this.nextAt === false ? false : Math.max(0, this.nextAt - Date.now())\n }\n}\n","import { isRecord } from \"./shared/type-guards\"\n\nexport const PLATFORM_SERVICE_NAMES = [\n \"os\",\n \"hub\",\n \"agent\",\n \"oauth\",\n \"llmGateway\",\n \"gitea\",\n \"tile\",\n] as const\n\nexport type PlatformServiceName = (typeof PLATFORM_SERVICE_NAMES)[number]\n\nexport interface PlatformEndpoints {\n services: Partial<Record<PlatformServiceName, string>>\n}\n\nexport const EMPTY_PLATFORM_ENDPOINTS: PlatformEndpoints = Object.freeze({\n services: Object.freeze({}),\n})\n\nexport interface LoadPlatformEndpointsOptions {\n baseUrl?: string\n fetchImpl?: typeof fetch\n timeoutMs?: number\n}\n\nfunction defaultDocumentBaseUrl(): string | undefined {\n if (typeof document === \"undefined\") return undefined\n if (document.querySelector(\"base[href]\")) return document.baseURI\n if (typeof location !== \"undefined\" && location.origin) return `${location.origin}/`\n return document.baseURI\n}\n\nfunction normalizeServiceUrl(value: unknown): string | null {\n if (typeof value !== \"string\" || !value.trim()) return null\n if (value.includes(\"?\") || value.includes(\"#\")) return null\n try {\n const url = new URL(value.trim())\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") return null\n if (url.username || url.password || url.search || url.hash) return null\n return url.toString().replace(/\\/$/, \"\")\n } catch {\n return null\n }\n}\n\nexport function parsePlatformEndpoints(value: unknown): PlatformEndpoints | null {\n if (!isRecord(value) || !isRecord(value.services)) return null\n\n const services: Partial<Record<PlatformServiceName, string>> = {}\n for (const name of PLATFORM_SERVICE_NAMES) {\n if (!(name in value.services)) continue\n const url = normalizeServiceUrl(value.services[name])\n if (!url) return null\n if (name === \"agent\" && new URL(url).pathname !== \"/\") return null\n services[name] = url\n }\n\n return { services }\n}\n\nexport async function loadPlatformEndpoints(\n options: LoadPlatformEndpointsOptions = {},\n): Promise<PlatformEndpoints> {\n const fetchImpl = options.fetchImpl ?? globalThis.fetch\n const baseUrl = options.baseUrl ?? defaultDocumentBaseUrl()\n if (!fetchImpl || !baseUrl) return EMPTY_PLATFORM_ENDPOINTS\n\n const controller = new AbortController()\n const timeout = globalThis.setTimeout(() => controller.abort(), options.timeoutMs ?? 3_000)\n try {\n const response = await fetchImpl(new URL(\"config.json\", baseUrl), {\n cache: \"no-store\",\n credentials: \"same-origin\",\n headers: { Accept: \"application/json\" },\n signal: controller.signal,\n })\n if (!response.ok) return EMPTY_PLATFORM_ENDPOINTS\n return parsePlatformEndpoints(await response.json()) ?? EMPTY_PLATFORM_ENDPOINTS\n } catch {\n return EMPTY_PLATFORM_ENDPOINTS\n } finally {\n globalThis.clearTimeout(timeout)\n }\n}\n\nexport function resolveServiceUrl(\n endpoints: PlatformEndpoints,\n name: PlatformServiceName,\n path = \"\",\n): string | null {\n const baseUrl = endpoints.services[name]\n if (!baseUrl) return null\n if (!path) return baseUrl\n const pathReference = path.trimStart()\n if (\n path.includes(\"\\\\\") ||\n pathReference.startsWith(\"//\") ||\n /^[a-z][a-z0-9+.-]*:/i.test(pathReference)\n ) {\n return null\n }\n const base = new URL(`${baseUrl}/`)\n const target = new URL(path.replace(/^\\/+/, \"\"), base)\n if (target.origin !== base.origin || !target.pathname.startsWith(base.pathname)) {\n return null\n }\n return target.toString()\n}\n","/**\n * 页面协作协议(对应后端 `_meta.bridge` 通道,见 docs/specs/260417-embed-bridge)。\n *\n * ## action 从哪里来\n *\n * 智能体 → 宿主方向的每一条指令,都源自**技能作者写的工具代码**:工具返回值\n * JSON 里带 `_meta.bridge: { action, payload }`,后端在持久化前把它剥离成独立\n * 事件送达前端(LLM 的对话历史里读不到它)。因此:\n *\n * - action 字符串(如 \"map.highlight\")是**技能作者与宿主页面开发者之间的业务\n * 契约**,LLM 不参与协议、SDK 不做枚举校验;\n * - 宿主页面用 `session.onCommand(\"map.highlight\", fn)` 消费;\n * - 未注册 handler 的 action 会进入有限缓冲等待注册,超限后丢弃并 console 告警。\n *\n * 宿主 → 智能体方向只有三个白名单动作:attach(附件入输入框)/ insertText\n * (追加输入文本)/ send(直接发消息),对应协议层的 addContext / appendInput /\n * sendMessage。\n */\n\nexport interface CommandEnvelope {\n __bladeBridge: true\n direction: \"agent-to-host\"\n action: string\n payload: unknown\n meta: {\n sessionId: string\n toolCallId?: string\n timestamp: number\n }\n}\n\nexport type InboundAction = \"addContext\" | \"appendInput\" | \"sendMessage\"\n\nexport interface InboundEnvelope {\n __bladeBridge: true\n direction: \"host-to-agent\"\n action: InboundAction\n payload: unknown\n}\n\nexport function isCommandEnvelope(value: unknown): value is CommandEnvelope {\n if (typeof value !== \"object\" || value === null) return false\n const record = value as Record<string, unknown>\n return (\n record.__bladeBridge === true &&\n record.direction === \"agent-to-host\" &&\n typeof record.action === \"string\"\n )\n}\n\nexport function isInboundEnvelope(value: unknown): value is InboundEnvelope {\n if (typeof value !== \"object\" || value === null) return false\n const record = value as Record<string, unknown>\n return (\n record.__bladeBridge === true &&\n record.direction === \"host-to-agent\" &&\n (record.action === \"addContext\" || record.action === \"appendInput\" || record.action === \"sendMessage\")\n )\n}\n","import type { PostChatFollowup, TurnProjection } from \"./projection\"\n\n/** 返回最新根会话轮次的小结;新用户消息到达后旧小结立即失效。 */\nexport function latestPostChatFollowup(turns: TurnProjection[]): PostChatFollowup | null {\n for (let index = turns.length - 1; index >= 0; index -= 1) {\n const turn = turns[index]\n if (\n turn.loop_id === \"root\" &&\n (turn.role === \"user\" || turn.role === \"assistant\") &&\n (turn.kind ?? \"message\") === \"message\" &&\n !turn.blocks.some((block) =>\n [\"mode_change\", \"plan_status\", \"ask_user_answer\"].includes(block.type),\n )\n ) {\n return turn.role === \"assistant\" ? (turn.post_chat_followup ?? null) : null\n }\n }\n return null\n}\n","export enum LayoutType {\n Default = \"default\",\n SkillEditor = \"skill-editor\",\n SolutionEditor = \"solution-editor\",\n SolutionApp = \"solution-app\",\n Custom = \"custom\",\n}\n\nexport interface Solution {\n id: string\n name: string\n version: string\n description?: string | null\n source?: \"builtin\" | \"personal\" | string | null\n layout_type: LayoutType | string\n initial_mode?: \"planning\" | \"executing\" | string | null\n initial_message?: string | null\n preview?: { url: string; title?: string | null } | null\n layout?: {\n available?: boolean\n source_dir?: string\n entry?: string\n export?: string\n } | null\n roles?: BizRole[] | null\n data?: Record<string, unknown> | null\n ui_config?: SolutionAppUiConfig | null\n}\n\nexport interface SolutionAppUiConfig {\n branding: {\n name: string\n subtitle?: string\n icon_text: string\n icon_gradient?: string\n }\n list: {\n title: string\n create_button: string\n card?: {\n subtitle?: string\n stats?: Array<{\n label: string\n value: string\n color?: string\n }>\n }\n }\n create: {\n title: string\n description?: string\n submit_button: string\n sections: Array<{\n id: string\n title: string\n description?: string\n fields: Array<SolutionAppField>\n }>\n }\n}\n\nexport type SolutionAppField =\n | {\n id: string\n kind: \"textarea\"\n label: string\n placeholder?: string\n }\n | {\n id: string\n kind: \"file-upload\"\n accept?: string[]\n categories?: Array<{\n label: string\n description: string\n color: string\n }>\n }\n\nexport interface SolutionAppState {\n pipeline: Array<{\n id: string\n label: string\n status: \"done\" | \"active\" | \"pending\" | \"error\"\n }>\n meta: Record<\n string,\n {\n label: string\n value: string\n color?: string\n }\n >\n}\n\nexport interface BizRole {\n id: string\n name: string\n description?: string | null\n preview?: { url: string; title?: string | null } | null\n}\n","import { type } from \"arktype\"\n\nexport const TaskStatus = type(\"'pending' | 'in_progress' | 'done' | 'failed' | 'skipped'\")\nexport type TaskStatus = typeof TaskStatus.infer\n\nexport const Task = type({\n id: \"string\",\n goal: \"string\",\n skills: \"string[]\",\n depends_on: \"string[]\",\n status: TaskStatus,\n result_summary: \"string\",\n number: \"string\",\n})\nexport type Task = typeof Task.infer\n"],"mappings":"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","names":["LayoutType"]}
|
|
@@ -66,6 +66,7 @@ export interface TurnProjection {
|
|
|
66
66
|
kind?: "message" | "context" | "compaction";
|
|
67
67
|
role: "user" | "assistant" | "system";
|
|
68
68
|
status: "streaming" | "completed" | "paused" | "failed" | "interrupted";
|
|
69
|
+
error_message?: string | null;
|
|
69
70
|
blocks: ContentBlock[];
|
|
70
71
|
tool_calls: ToolCallProjection[];
|
|
71
72
|
model?: string | null;
|
|
@@ -134,6 +135,8 @@ export interface PatchEnvelope {
|
|
|
134
135
|
tool_call_id?: string;
|
|
135
136
|
tool_name?: string;
|
|
136
137
|
workspace_path?: string;
|
|
138
|
+
/** 本次工具改动的文件(相对工作区);缺省表示不知道具体文件。 */
|
|
139
|
+
paths?: string[];
|
|
137
140
|
};
|
|
138
141
|
};
|
|
139
142
|
}
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
export declare enum LayoutType {
|
|
2
2
|
Default = "default",
|
|
3
3
|
SkillEditor = "skill-editor",
|
|
4
|
-
BladeCoa = "blade-coa",
|
|
5
4
|
SolutionEditor = "solution-editor",
|
|
6
|
-
SolutionEditor2 = "solution-editor2",
|
|
7
|
-
ChatPreview = "chat-preview",
|
|
8
|
-
ChatOnly = "chat-only",
|
|
9
5
|
SolutionApp = "solution-app",
|
|
10
6
|
Custom = "custom"
|
|
11
7
|
}
|
|
@@ -15,11 +15,13 @@ export interface SessionRuntime {
|
|
|
15
15
|
fetchTurnsPage(sessionId: string, query?: SessionTurnsQuery, init?: RequestInit): Promise<SessionTurnsPage>;
|
|
16
16
|
fetchTurnIndex(sessionId: string): Promise<SessionTurnIndex>;
|
|
17
17
|
fetchCommands(sessionId: string): Promise<HistoricalCommand[]>;
|
|
18
|
-
/**
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
/**
|
|
19
|
+
* 会话详情包含会话状态、回放状态、查看权限和运行时类型。`fresh` 为 true 时必须取最新值
|
|
20
|
+
* (重连补数);为 false 时宿主可以复用刚取过的一份(进入会话)。
|
|
21
|
+
*/
|
|
22
|
+
fetchSessionInfo(sessionId: string, options?: {
|
|
23
|
+
fresh?: boolean;
|
|
24
|
+
}): Promise<SessionDetailSnapshot>;
|
|
23
25
|
updateReplay(sessionId: string, payload: {
|
|
24
26
|
speed?: ReplaySpeed;
|
|
25
27
|
status?: "autonomous";
|
|
@@ -34,6 +36,20 @@ export interface SessionRuntime {
|
|
|
34
36
|
*/
|
|
35
37
|
onDispose(session: AgentSession): boolean;
|
|
36
38
|
}
|
|
39
|
+
export interface SessionDetailSnapshot {
|
|
40
|
+
status?: SessionStatus;
|
|
41
|
+
replay_state?: ReplayState | null;
|
|
42
|
+
viewer_role?: "owner" | "viewer";
|
|
43
|
+
runtime_type?: string | null;
|
|
44
|
+
}
|
|
45
|
+
/** 服务端 chat:end 载荷里 AgentSession 关心的字段。 */
|
|
46
|
+
export interface ChatEndPayload {
|
|
47
|
+
status?: string;
|
|
48
|
+
/** 排队中断:服务端取消了排队中的发送,`cancelled_client_request_ids` 是被取消的请求。 */
|
|
49
|
+
queued?: boolean;
|
|
50
|
+
cancelled_client_request_ids?: unknown;
|
|
51
|
+
pause_tool_data?: Record<string, unknown>;
|
|
52
|
+
}
|
|
37
53
|
export interface AttachAppOptions {
|
|
38
54
|
/** 可选;只需要页面上下文时无需提供 CLI。 */
|
|
39
55
|
cli?: AppCliDefinition;
|
|
@@ -49,6 +65,8 @@ export interface SendOptions {
|
|
|
49
65
|
model?: string;
|
|
50
66
|
/** 本次运行是否强制开/关思考。 */
|
|
51
67
|
thinkingOverride?: boolean;
|
|
68
|
+
/** 本次运行的推理强度(模型支持时生效)。 */
|
|
69
|
+
reasoningLevel?: string;
|
|
52
70
|
whatif?: {
|
|
53
71
|
from_step: number;
|
|
54
72
|
quotes: Array<Record<string, unknown>>;
|
|
@@ -74,6 +92,10 @@ export declare function sessionStatusFromChatEnd(status: string | undefined): Se
|
|
|
74
92
|
export declare class AgentSession {
|
|
75
93
|
readonly sessionId: string;
|
|
76
94
|
private state;
|
|
95
|
+
/** status 每变化一次加一(单调递增)。异步读取会话详情时据此判断请求期间状态是否变过,避免 running→终态→running 这类来回被误认为「没变」。 */
|
|
96
|
+
private statusRevision;
|
|
97
|
+
/** 实时事件写入 status 时调用:值不变也要记一次,才能识别请求期间收到过更新的状态。 */
|
|
98
|
+
private noteLiveStatus;
|
|
77
99
|
private readonly listeners;
|
|
78
100
|
private readonly emitter;
|
|
79
101
|
private readonly commands;
|
|
@@ -127,6 +149,20 @@ export declare class AgentSession {
|
|
|
127
149
|
private getAppContext;
|
|
128
150
|
private sendPending;
|
|
129
151
|
private manualCompactionPending;
|
|
152
|
+
/** 手动整理的在途标记,同时写进状态(界面据此保持「正在整理」,见 SessionState.compactionPending)。 */
|
|
153
|
+
private setManualCompactionPending;
|
|
154
|
+
/** 最近一次还在等服务端结果的发送请求 id;排队中断的 chat:end 据此判断回滚是否过期。 */
|
|
155
|
+
private pendingChatRequestId;
|
|
156
|
+
/** 会话详情给出的运行时类型;"native" 时启用原生智能体的投影规则(见 _handleTurnEvents / _handleChatEnd)。 */
|
|
157
|
+
private runtimeType;
|
|
158
|
+
/** workflow_run_id → 触发它的 workflow:run 工具调用 id(只有 run:start 事件带工具调用 id)。 */
|
|
159
|
+
private readonly workflowRunToolCalls;
|
|
160
|
+
/**
|
|
161
|
+
* 第一方 Web 的精简模式传输优化:订阅时是否要 token 级事件。null 表示宿主没设置,订阅时不带这个字段。
|
|
162
|
+
* `desiredStreamTokens` 是宿主最新的选择;运行中不切换,等这一轮结束再重订阅。
|
|
163
|
+
*/
|
|
164
|
+
private desiredStreamTokens;
|
|
165
|
+
private joinedStreamTokens;
|
|
130
166
|
private readonly deliveredCommandKeys;
|
|
131
167
|
private readonly deliveredToolPreviews;
|
|
132
168
|
private readonly oomNotifiedKeys;
|
|
@@ -135,6 +171,7 @@ export declare class AgentSession {
|
|
|
135
171
|
private readonly emittedMessageTurnIds;
|
|
136
172
|
constructor(sessionId: string, runtime: SessionRuntime, connection: ConnectionStatus, options?: {
|
|
137
173
|
staticHistory?: boolean;
|
|
174
|
+
streamTokens?: boolean | null;
|
|
138
175
|
});
|
|
139
176
|
/**
|
|
140
177
|
* 静态历史(分享页 / `fromTurns`):没有目录接口,也**没有**"目录还没到位"这个中间态。
|
|
@@ -143,8 +180,11 @@ export declare class AgentSession {
|
|
|
143
180
|
* 旧分支的发言,拿它兜底会把已经失效的 entry id 重新摆到轨道上,点了必然找不到。
|
|
144
181
|
*/
|
|
145
182
|
readonly isStatic: boolean;
|
|
146
|
-
/**
|
|
147
|
-
|
|
183
|
+
/**
|
|
184
|
+
* 从一份静态 turn 快照构造只展示历史的会话(例如公开分享页)。`overrides` 覆盖展示相关的少数字段
|
|
185
|
+
* (只读身份、开发调试页模拟的流式状态)。
|
|
186
|
+
*/
|
|
187
|
+
static fromTurns(sessionId: string, turns: TurnProjection[], overrides?: Partial<Pick<SessionState, "isStreaming" | "status" | "viewerRole">>): AgentSession;
|
|
148
188
|
/** 返回当前会话快照。引用稳定:状态未变化时返回同一对象。 */
|
|
149
189
|
getState(): SessionState;
|
|
150
190
|
get hasOlderHistory(): boolean;
|
|
@@ -169,6 +209,17 @@ export declare class AgentSession {
|
|
|
169
209
|
* 否则"运行刚结束时点一下侧栏"就会把终态对账一起中止,流式与历史对不上。
|
|
170
210
|
*/
|
|
171
211
|
cancelPendingLocate(): void;
|
|
212
|
+
/**
|
|
213
|
+
* 历史被外部改写后(rewind / checkout 分支等由宿主发起的操作)整窗重新加载最新一页:
|
|
214
|
+
* 作废在途的旧结果,递增 `timelineRevision`;同时向服务端确认一次运行状态(改写期间错过的
|
|
215
|
+
* chat:end 会让界面停在「运行中」)。
|
|
216
|
+
*/
|
|
217
|
+
reloadHistory(): Promise<boolean>;
|
|
218
|
+
/**
|
|
219
|
+
* 向服务端确认会话此刻是否在运行,校准流式状态(残留的「运行中」会被清掉)。只在已加入房间时
|
|
220
|
+
* 生效;不带 resume,服务端不会重发上一轮的终态事件(否则会被当成一次新的结束)。
|
|
221
|
+
*/
|
|
222
|
+
refreshRunningState(): Promise<void>;
|
|
172
223
|
/**
|
|
173
224
|
* timeline 被整体改写(rewind / checkout / 释放):推进纪元,并把在途定位请求一并中止
|
|
174
225
|
* ——它已经属于旧 timeline,却还占着替换队列,会让改写后的权威窗口排在后面等它跑完。
|
|
@@ -281,8 +332,10 @@ export declare class AgentSession {
|
|
|
281
332
|
private enqueueSubscription;
|
|
282
333
|
/** 改回放是 owner 专属(服务端 PATCH 走 _get_owned_session)。 */
|
|
283
334
|
private get canControlReplay();
|
|
284
|
-
/**
|
|
285
|
-
private
|
|
335
|
+
/** 拉一次会话详情,填会话状态、回放状态、只读身份和运行时类型;失败不挡启动。 */
|
|
336
|
+
private syncSessionFromDetail;
|
|
337
|
+
/** 安装一份会话详情;`statusRevisionAtRequest` 是发出请求时的状态修订号。 */
|
|
338
|
+
private applySessionDetail;
|
|
286
339
|
/** 调整回放倍速;不是回放会话、或只读身份时什么都不做。 */
|
|
287
340
|
setReplaySpeed(speed: ReplaySpeed): Promise<void>;
|
|
288
341
|
/** 退出回放,之后的对话交给真实模型运行;不是回放会话、或只读身份时什么都不做。 */
|
|
@@ -299,14 +352,17 @@ export declare class AgentSession {
|
|
|
299
352
|
_handleTurnEvents(events: RawEvent[], replayed?: boolean): void;
|
|
300
353
|
/** @internal */
|
|
301
354
|
_handleChatStart(): void;
|
|
302
|
-
/**
|
|
303
|
-
|
|
355
|
+
/**
|
|
356
|
+
* @internal 返回 false 表示这是一条过期的排队回滚(被取消的是更早的请求,当前运行不受影响),
|
|
357
|
+
* Hub 据此不把它当成一次运行结束广播出去。
|
|
358
|
+
*/
|
|
359
|
+
_handleChatEnd(payload?: ChatEndPayload): boolean;
|
|
304
360
|
/** @internal */
|
|
305
361
|
_handleSystemError(message: string, code?: string): void;
|
|
306
362
|
/** @internal */
|
|
307
363
|
_handleTaskUpdated(tasks: unknown[]): void;
|
|
308
364
|
/** @internal */
|
|
309
|
-
_handleWorkspaceFilesChanged(filePath?: string): void;
|
|
365
|
+
_handleWorkspaceFilesChanged(filePath?: string, paths?: string[] | null): void;
|
|
310
366
|
/** @internal */
|
|
311
367
|
_handleSessionUpdated(data: {
|
|
312
368
|
workspace_path?: string;
|
|
@@ -334,6 +390,20 @@ export declare class AgentSession {
|
|
|
334
390
|
_applyRunningState(isRunning: boolean, liveRevisionAtJoin?: number): void;
|
|
335
391
|
private markRunningIfIdle;
|
|
336
392
|
private finishStreaming;
|
|
393
|
+
/**
|
|
394
|
+
* 原生智能体常在用户发言之前就宣告一个空的 assistant 回合(投影的起点),它的真实内容会随第一条
|
|
395
|
+
* 输出再发一次。消息列表在启动期间本来就显示一个「正在生成」占位,两者并存会出现两个占位,
|
|
396
|
+
* 所以只丢掉原生会话里这种空的流式回合。
|
|
397
|
+
*/
|
|
398
|
+
private isNativeBootstrapTurn;
|
|
399
|
+
/** 实时 workflow:* 事件叠加到对应工具调用的时间线上(见 workflow.ts 的来源规则)。 */
|
|
400
|
+
private applyWorkflowEvents;
|
|
401
|
+
/**
|
|
402
|
+
* @internal 宿主改了 token 订阅偏好(精简模式)。空闲时立即重订阅;运行中等这一轮结束再换,
|
|
403
|
+
* 避免在输出中途丢掉 token 流。
|
|
404
|
+
*/
|
|
405
|
+
_setStreamTokens(enabled: boolean): void;
|
|
406
|
+
private applyDesiredStreamTokens;
|
|
337
407
|
private completeChat;
|
|
338
408
|
private markTurnFresh;
|
|
339
409
|
private markOptimisticTurnPending;
|
package/dist/session/events.d.ts
CHANGED
|
@@ -67,9 +67,23 @@ export interface AgentSessionEvents {
|
|
|
67
67
|
loopId?: string;
|
|
68
68
|
metadata?: Record<string, unknown>;
|
|
69
69
|
};
|
|
70
|
-
/**
|
|
70
|
+
/**
|
|
71
|
+
* 工作区文件发生变化(写文件、重命名等)。`paths` 是已知的变化路径(相对工作区,
|
|
72
|
+
* 目录以 `/` 结尾);没有 `filePath` 也没有 `paths` 时表示不知道具体变了什么。
|
|
73
|
+
*/
|
|
71
74
|
workspaceChanged: {
|
|
72
75
|
filePath?: string;
|
|
76
|
+
paths?: string[];
|
|
77
|
+
/** 工具切换了会话工作目录时的新目录(例如绑定到分组工作区)。 */
|
|
78
|
+
workspacePath?: string;
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* 一条回合在实时通道上落地(新出现或内容更新),供宿主做自己的副作用(打开预览、标记面板未读等)。
|
|
82
|
+
* 历史加载(REST)不触发;`source` 区分真正的实时更新与订阅时服务端重发的缓冲。
|
|
83
|
+
*/
|
|
84
|
+
turnUpdated: {
|
|
85
|
+
turn: TurnProjection;
|
|
86
|
+
source: "live" | "bootstrap_replay" | "reconnect_replay";
|
|
73
87
|
};
|
|
74
88
|
/** 智能体产出了文件成果(artifact:created / artifact:updated)。 */
|
|
75
89
|
artifact: {
|