@dotcraft/sdk 0.5.9
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/LICENSE +201 -0
- package/README.md +30 -0
- package/dist/app-binding.d.ts +4 -0
- package/dist/app-binding.d.ts.map +1 -0
- package/dist/app-binding.js +2 -0
- package/dist/app-binding.js.map +1 -0
- package/dist/appServerClient.d.ts +66 -0
- package/dist/appServerClient.d.ts.map +1 -0
- package/dist/appServerClient.js +140 -0
- package/dist/appServerClient.js.map +1 -0
- package/dist/client.d.ts +90 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +418 -0
- package/dist/client.js.map +1 -0
- package/dist/client.test.d.ts +2 -0
- package/dist/client.test.d.ts.map +1 -0
- package/dist/client.test.js +244 -0
- package/dist/client.test.js.map +1 -0
- package/dist/contracts.d.ts +5 -0
- package/dist/contracts.d.ts.map +1 -0
- package/dist/contracts.js +5 -0
- package/dist/contracts.js.map +1 -0
- package/dist/dotcraft.d.ts +331 -0
- package/dist/dotcraft.d.ts.map +1 -0
- package/dist/dotcraft.js +819 -0
- package/dist/dotcraft.js.map +1 -0
- package/dist/dotcraft.test.d.ts +2 -0
- package/dist/dotcraft.test.d.ts.map +1 -0
- package/dist/dotcraft.test.js +423 -0
- package/dist/dotcraft.test.js.map +1 -0
- package/dist/dynamic-tools.d.ts +3 -0
- package/dist/dynamic-tools.d.ts.map +1 -0
- package/dist/dynamic-tools.js +2 -0
- package/dist/dynamic-tools.js.map +1 -0
- package/dist/errors.d.ts +50 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +112 -0
- package/dist/errors.js.map +1 -0
- package/dist/generated/appserver/client-notifications.generated.d.ts +9 -0
- package/dist/generated/appserver/client-notifications.generated.d.ts.map +1 -0
- package/dist/generated/appserver/client-notifications.generated.js +3 -0
- package/dist/generated/appserver/client-notifications.generated.js.map +1 -0
- package/dist/generated/appserver/client-requests.generated.d.ts +785 -0
- package/dist/generated/appserver/client-requests.generated.d.ts.map +1 -0
- package/dist/generated/appserver/client-requests.generated.js +3 -0
- package/dist/generated/appserver/client-requests.generated.js.map +1 -0
- package/dist/generated/appserver/index.d.ts +9 -0
- package/dist/generated/appserver/index.d.ts.map +1 -0
- package/dist/generated/appserver/index.js +10 -0
- package/dist/generated/appserver/index.js.map +1 -0
- package/dist/generated/appserver/item-payloads.generated.d.ts +52 -0
- package/dist/generated/appserver/item-payloads.generated.d.ts.map +1 -0
- package/dist/generated/appserver/item-payloads.generated.js +35 -0
- package/dist/generated/appserver/item-payloads.generated.js.map +1 -0
- package/dist/generated/appserver/method-groups.generated.d.ts +8 -0
- package/dist/generated/appserver/method-groups.generated.d.ts.map +1 -0
- package/dist/generated/appserver/method-groups.generated.js +274 -0
- package/dist/generated/appserver/method-groups.generated.js.map +1 -0
- package/dist/generated/appserver/models.generated.d.ts +4415 -0
- package/dist/generated/appserver/models.generated.d.ts.map +1 -0
- package/dist/generated/appserver/models.generated.js +3 -0
- package/dist/generated/appserver/models.generated.js.map +1 -0
- package/dist/generated/appserver/protocol-info.generated.d.ts +6 -0
- package/dist/generated/appserver/protocol-info.generated.d.ts.map +1 -0
- package/dist/generated/appserver/protocol-info.generated.js +7 -0
- package/dist/generated/appserver/protocol-info.generated.js.map +1 -0
- package/dist/generated/appserver/server-notifications.generated.d.ts +197 -0
- package/dist/generated/appserver/server-notifications.generated.d.ts.map +1 -0
- package/dist/generated/appserver/server-notifications.generated.js +3 -0
- package/dist/generated/appserver/server-notifications.generated.js.map +1 -0
- package/dist/generated/appserver/server-requests.generated.d.ts +73 -0
- package/dist/generated/appserver/server-requests.generated.d.ts.map +1 -0
- package/dist/generated/appserver/server-requests.generated.js +3 -0
- package/dist/generated/appserver/server-requests.generated.js.map +1 -0
- package/dist/generatedAppServer.test.d.ts +2 -0
- package/dist/generatedAppServer.test.d.ts.map +1 -0
- package/dist/generatedAppServer.test.js +112 -0
- package/dist/generatedAppServer.test.js.map +1 -0
- package/dist/hub.d.ts +6 -0
- package/dist/hub.d.ts.map +1 -0
- package/dist/hub.js +5 -0
- package/dist/hub.js.map +1 -0
- package/dist/hubClient.d.ts +134 -0
- package/dist/hubClient.d.ts.map +1 -0
- package/dist/hubClient.js +372 -0
- package/dist/hubClient.js.map +1 -0
- package/dist/hubClient.test.d.ts +2 -0
- package/dist/hubClient.test.d.ts.map +1 -0
- package/dist/hubClient.test.js +220 -0
- package/dist/hubClient.test.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/meta.d.ts +2 -0
- package/dist/meta.d.ts.map +1 -0
- package/dist/meta.js +2 -0
- package/dist/meta.js.map +1 -0
- package/dist/models.d.ts +44 -0
- package/dist/models.d.ts.map +1 -0
- package/dist/models.js +96 -0
- package/dist/models.js.map +1 -0
- package/dist/protocolBaseline.test.d.ts +2 -0
- package/dist/protocolBaseline.test.d.ts.map +1 -0
- package/dist/protocolBaseline.test.js +77 -0
- package/dist/protocolBaseline.test.js.map +1 -0
- package/dist/publicApi.test.d.ts +2 -0
- package/dist/publicApi.test.d.ts.map +1 -0
- package/dist/publicApi.test.js +29 -0
- package/dist/publicApi.test.js.map +1 -0
- package/dist/test-contract-fixtures.d.ts +6 -0
- package/dist/test-contract-fixtures.d.ts.map +1 -0
- package/dist/test-contract-fixtures.js +33 -0
- package/dist/test-contract-fixtures.js.map +1 -0
- package/dist/testing.d.ts +3 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +3 -0
- package/dist/testing.js.map +1 -0
- package/dist/transport.d.ts +54 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/transport.js +214 -0
- package/dist/transport.js.map +1 -0
- package/dist/transport.test.d.ts +2 -0
- package/dist/transport.test.d.ts.map +1 -0
- package/dist/transport.test.js +105 -0
- package/dist/transport.test.js.map +1 -0
- package/dist/turnReply.d.ts +25 -0
- package/dist/turnReply.d.ts.map +1 -0
- package/dist/turnReply.js +143 -0
- package/dist/turnReply.js.map +1 -0
- package/dist/turnReply.test.d.ts +2 -0
- package/dist/turnReply.test.d.ts.map +1 -0
- package/dist/turnReply.test.js +41 -0
- package/dist/turnReply.test.js.map +1 -0
- package/dist/wire.d.ts +8 -0
- package/dist/wire.d.ts.map +1 -0
- package/dist/wire.js +6 -0
- package/dist/wire.js.map +1 -0
- package/package.json +102 -0
package/dist/dotcraft.js
ADDED
|
@@ -0,0 +1,819 @@
|
|
|
1
|
+
import { userInfo } from "node:os";
|
|
2
|
+
import { InternalAppServerClient } from "./appServerClient.js";
|
|
3
|
+
import { JsonRpcMessage, textPart, } from "./models.js";
|
|
4
|
+
import { WebSocketTransport } from "./transport.js";
|
|
5
|
+
import { HubClient } from "./hubClient.js";
|
|
6
|
+
import { InitializationError, TurnCancelledError, TurnFailedError, TurnInProgressError, } from "./errors.js";
|
|
7
|
+
import { extractAgentReplyTextFromTurnCompletedParams, mergeReplyTextFromDeltaAndSnapshot, } from "./turnReply.js";
|
|
8
|
+
export const APP_BINDING_ERROR_CODES = {
|
|
9
|
+
offline: "AppBindingOffline",
|
|
10
|
+
expired: "AppBindingExpired",
|
|
11
|
+
revoked: "AppBindingRevoked",
|
|
12
|
+
scopeDenied: "AppBindingScopeDenied",
|
|
13
|
+
toolUnavailable: "AppBindingToolUnavailable",
|
|
14
|
+
protocolViolation: "AppBindingProtocolViolation",
|
|
15
|
+
};
|
|
16
|
+
export function appBindingToolError(errorCode, errorMessage, structuredContent) {
|
|
17
|
+
return {
|
|
18
|
+
success: false,
|
|
19
|
+
errorCode,
|
|
20
|
+
errorMessage,
|
|
21
|
+
structuredContent,
|
|
22
|
+
contentItems: [{ type: "text", text: `${errorCode}: ${errorMessage}` }],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export function appBindingUnavailableError(state, message) {
|
|
26
|
+
if (state === "expired") {
|
|
27
|
+
return appBindingToolError(APP_BINDING_ERROR_CODES.expired, message ?? "The app binding has expired.");
|
|
28
|
+
}
|
|
29
|
+
if (state === "revoked") {
|
|
30
|
+
return appBindingToolError(APP_BINDING_ERROR_CODES.revoked, message ?? "The app binding was revoked.");
|
|
31
|
+
}
|
|
32
|
+
return appBindingToolError(APP_BINDING_ERROR_CODES.offline, message ?? "The app binding is offline. Reconnect the app or refresh the binding.");
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Parse an App Binding handoff URL such as
|
|
36
|
+
* `app://dotcraft/connect?app=...&request=...&token=...&endpoint=...`.
|
|
37
|
+
*
|
|
38
|
+
* Deep links are activation hints, not authorization: always inspect the request
|
|
39
|
+
* over AppServer before rendering confirmation or accepting.
|
|
40
|
+
*/
|
|
41
|
+
export function parseAppBindingHandoff(url, options) {
|
|
42
|
+
const parsed = new URL(url);
|
|
43
|
+
const scheme = parsed.protocol.replace(/:$/, "");
|
|
44
|
+
if (options?.expectedScheme && scheme !== options.expectedScheme) {
|
|
45
|
+
throw new Error(`Unexpected handoff scheme '${scheme}', expected '${options.expectedScheme}'.`);
|
|
46
|
+
}
|
|
47
|
+
const operation = parsed.pathname.replace(/^\//, "");
|
|
48
|
+
const query = parsed.searchParams;
|
|
49
|
+
const appId = query.get("app") ?? "";
|
|
50
|
+
const requestId = query.get("request") ?? "";
|
|
51
|
+
const requestToken = query.get("token") ?? "";
|
|
52
|
+
if (!appId || !requestId || !requestToken) {
|
|
53
|
+
throw new Error("The handoff URL must contain app, request, and token query parameters.");
|
|
54
|
+
}
|
|
55
|
+
if (options?.expectedAppId && appId !== options.expectedAppId) {
|
|
56
|
+
throw new Error(`Unexpected handoff appId '${appId}', expected '${options.expectedAppId}'.`);
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
scheme,
|
|
60
|
+
operation,
|
|
61
|
+
appId,
|
|
62
|
+
requestId,
|
|
63
|
+
requestToken,
|
|
64
|
+
appServerUrl: query.get("endpoint") ?? undefined,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function defaultUserId() {
|
|
68
|
+
try {
|
|
69
|
+
return userInfo().username || "local-user";
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return "local-user";
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function normalizeIdentity(options = {}) {
|
|
76
|
+
return {
|
|
77
|
+
channelName: options.channelName ?? "sdk",
|
|
78
|
+
userId: options.userId ?? defaultUserId(),
|
|
79
|
+
...(options.workspacePath ? { workspacePath: options.workspacePath } : {}),
|
|
80
|
+
...(options.channelContext ? { channelContext: options.channelContext } : {}),
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function normalizeRunInput(input, sender) {
|
|
84
|
+
if (typeof input === "string")
|
|
85
|
+
return { input: [textPart(input)], sender };
|
|
86
|
+
if (Array.isArray(input))
|
|
87
|
+
return { input, sender };
|
|
88
|
+
return { input: input.input, sender: input.sender ?? sender };
|
|
89
|
+
}
|
|
90
|
+
function toContractSender(sender) {
|
|
91
|
+
if (!sender)
|
|
92
|
+
return undefined;
|
|
93
|
+
return {
|
|
94
|
+
...sender,
|
|
95
|
+
senderName: sender.senderName ?? sender.senderId,
|
|
96
|
+
senderRole: sender.senderRole ?? "user",
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
function stripRuntimeDynamicToolHandlers(tools) {
|
|
100
|
+
if (tools === undefined)
|
|
101
|
+
return undefined;
|
|
102
|
+
return tools.map((declaration) => {
|
|
103
|
+
if (declaration.type === "namespace") {
|
|
104
|
+
return {
|
|
105
|
+
...declaration,
|
|
106
|
+
tools: declaration.tools.map(({ handler: _handler, ...tool }) => tool),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
const { handler: _handler, ...tool } = declaration;
|
|
110
|
+
return tool;
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
function toolKey(threadId, namespace, name) {
|
|
114
|
+
return `${threadId}\u0000${namespace ?? ""}\u0000${name}`;
|
|
115
|
+
}
|
|
116
|
+
function methodToRunEventType(method) {
|
|
117
|
+
switch (method) {
|
|
118
|
+
case "thread/started": return "thread_started";
|
|
119
|
+
case "thread/resumed": return "thread_resumed";
|
|
120
|
+
case "thread/statusChanged": return "thread_status_changed";
|
|
121
|
+
case "thread/runtimeChanged": return "thread_runtime_changed";
|
|
122
|
+
case "thread/queue/updated": return "queue_updated";
|
|
123
|
+
case "turn/started": return "turn_started";
|
|
124
|
+
case "item/started": return "item_started";
|
|
125
|
+
case "item/completed": return "item_completed";
|
|
126
|
+
case "item/agentMessage/delta": return "agent_message_delta";
|
|
127
|
+
case "item/reasoning/delta": return "reasoning_delta";
|
|
128
|
+
case "item/toolCall/argumentsDelta": return "tool_arguments_delta";
|
|
129
|
+
case "item/approval/resolved": return "approval_resolved";
|
|
130
|
+
case "item/usage/delta": return "usage_delta";
|
|
131
|
+
case "subagent/progress": return "subagent_progress";
|
|
132
|
+
case "plan/updated": return "plan_updated";
|
|
133
|
+
case "system/event": return "system_event";
|
|
134
|
+
case "turn/completed": return "completed";
|
|
135
|
+
case "turn/failed": return "failed";
|
|
136
|
+
case "turn/cancelled": return "cancelled";
|
|
137
|
+
default: return "raw";
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
function paramsRecord(raw) {
|
|
141
|
+
return raw && typeof raw === "object" ? raw : {};
|
|
142
|
+
}
|
|
143
|
+
function eventTurn(params) {
|
|
144
|
+
const raw = params.turn;
|
|
145
|
+
return raw && typeof raw === "object" ? raw : null;
|
|
146
|
+
}
|
|
147
|
+
function resolveThreadId(fallbackThreadId, params) {
|
|
148
|
+
if (typeof params.threadId === "string")
|
|
149
|
+
return params.threadId;
|
|
150
|
+
const turn = params.turn;
|
|
151
|
+
if (turn && typeof turn === "object" && typeof turn.threadId === "string") {
|
|
152
|
+
return turn.threadId;
|
|
153
|
+
}
|
|
154
|
+
const thread = params.thread;
|
|
155
|
+
if (thread && typeof thread === "object" && typeof thread.id === "string") {
|
|
156
|
+
return thread.id === fallbackThreadId ? fallbackThreadId : fallbackThreadId;
|
|
157
|
+
}
|
|
158
|
+
return fallbackThreadId;
|
|
159
|
+
}
|
|
160
|
+
function abortError() {
|
|
161
|
+
const error = new Error("Operation was aborted.");
|
|
162
|
+
error.name = "AbortError";
|
|
163
|
+
return error;
|
|
164
|
+
}
|
|
165
|
+
class RunReducer {
|
|
166
|
+
itemOrder = [];
|
|
167
|
+
itemSeen = new Set();
|
|
168
|
+
perItemDelta = new Map();
|
|
169
|
+
activeAgentItemId = null;
|
|
170
|
+
lastDeltaAgentItemId = null;
|
|
171
|
+
orphanDelta = "";
|
|
172
|
+
apply(event) {
|
|
173
|
+
const params = paramsRecord(event.params);
|
|
174
|
+
if (event.method === "item/started") {
|
|
175
|
+
const item = paramsRecord(params.item);
|
|
176
|
+
if (item.type === "agentMessage" && typeof item.id === "string" && item.id) {
|
|
177
|
+
this.activeAgentItemId = item.id;
|
|
178
|
+
this.lastDeltaAgentItemId = item.id;
|
|
179
|
+
this.pushOrder(item.id);
|
|
180
|
+
}
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
if (event.method === "item/agentMessage/delta") {
|
|
184
|
+
const delta = typeof params.delta === "string" ? params.delta : "";
|
|
185
|
+
const explicit = typeof params.itemId === "string" && params.itemId ? params.itemId : null;
|
|
186
|
+
const itemId = explicit ?? this.activeAgentItemId ?? this.lastDeltaAgentItemId;
|
|
187
|
+
if (itemId) {
|
|
188
|
+
this.pushOrder(itemId);
|
|
189
|
+
this.perItemDelta.set(itemId, (this.perItemDelta.get(itemId) ?? "") + delta);
|
|
190
|
+
this.lastDeltaAgentItemId = itemId;
|
|
191
|
+
if (!this.activeAgentItemId)
|
|
192
|
+
this.activeAgentItemId = itemId;
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
this.orphanDelta += delta;
|
|
196
|
+
}
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
if (event.method === "item/completed") {
|
|
200
|
+
const item = paramsRecord(params.item);
|
|
201
|
+
if (item.type !== "agentMessage")
|
|
202
|
+
return;
|
|
203
|
+
const itemId = typeof item.id === "string" ? item.id : "";
|
|
204
|
+
if (!itemId)
|
|
205
|
+
return;
|
|
206
|
+
this.pushOrder(itemId);
|
|
207
|
+
const payload = paramsRecord(item.payload);
|
|
208
|
+
const snapshot = typeof payload.text === "string" ? payload.text : "";
|
|
209
|
+
const delta = this.perItemDelta.get(itemId) ?? "";
|
|
210
|
+
this.perItemDelta.set(itemId, mergeReplyTextFromDeltaAndSnapshot(delta, snapshot));
|
|
211
|
+
if (this.activeAgentItemId === itemId)
|
|
212
|
+
this.activeAgentItemId = null;
|
|
213
|
+
this.lastDeltaAgentItemId = itemId;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
textFromCompleted(params) {
|
|
217
|
+
const snapshot = extractAgentReplyTextFromTurnCompletedParams(params);
|
|
218
|
+
const delta = this.itemOrder.map((id) => this.perItemDelta.get(id) ?? "").join("") + this.orphanDelta;
|
|
219
|
+
return mergeReplyTextFromDeltaAndSnapshot(delta, snapshot);
|
|
220
|
+
}
|
|
221
|
+
pushOrder(itemId) {
|
|
222
|
+
if (!itemId || this.itemSeen.has(itemId))
|
|
223
|
+
return;
|
|
224
|
+
this.itemSeen.add(itemId);
|
|
225
|
+
this.itemOrder.push(itemId);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
class ThreadManagerImpl {
|
|
229
|
+
sdk;
|
|
230
|
+
constructor(sdk) {
|
|
231
|
+
this.sdk = sdk;
|
|
232
|
+
}
|
|
233
|
+
async getOrCreate(options = {}) {
|
|
234
|
+
const identity = normalizeIdentity(options);
|
|
235
|
+
const threads = await this.sdk.wire.threadList({
|
|
236
|
+
...identity,
|
|
237
|
+
includeArchived: options.includeArchived ?? false,
|
|
238
|
+
});
|
|
239
|
+
const reusable = threads.find((thread) => thread.status === "active" || thread.status === "paused");
|
|
240
|
+
if (reusable) {
|
|
241
|
+
if (reusable.status === "paused") {
|
|
242
|
+
return await this.resume(reusable.id, {
|
|
243
|
+
dynamicTools: options.dynamicTools,
|
|
244
|
+
additionalContext: options.additionalContext,
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
const snapshot = await this.sdk.wire.threadRead(reusable.id);
|
|
248
|
+
const thread = new DotCraftThread(this.sdk, snapshot, identity);
|
|
249
|
+
thread.bindDynamicTools(options.dynamicTools);
|
|
250
|
+
return thread;
|
|
251
|
+
}
|
|
252
|
+
return await this.start(options);
|
|
253
|
+
}
|
|
254
|
+
async start(options = {}) {
|
|
255
|
+
const identity = normalizeIdentity(options);
|
|
256
|
+
const snapshot = await this.sdk.wire.threadStart({
|
|
257
|
+
...identity,
|
|
258
|
+
displayName: options.displayName,
|
|
259
|
+
historyMode: options.historyMode,
|
|
260
|
+
config: options.config,
|
|
261
|
+
dynamicTools: stripRuntimeDynamicToolHandlers(options.dynamicTools),
|
|
262
|
+
additionalContext: options.additionalContext,
|
|
263
|
+
});
|
|
264
|
+
const thread = new DotCraftThread(this.sdk, snapshot, identity);
|
|
265
|
+
thread.bindDynamicTools(options.dynamicTools);
|
|
266
|
+
return thread;
|
|
267
|
+
}
|
|
268
|
+
async resume(threadId, options = {}) {
|
|
269
|
+
const snapshot = await this.sdk.wire.threadResume(threadId, {
|
|
270
|
+
dynamicTools: stripRuntimeDynamicToolHandlers(options.dynamicTools),
|
|
271
|
+
additionalContext: options.additionalContext,
|
|
272
|
+
});
|
|
273
|
+
const thread = new DotCraftThread(this.sdk, snapshot, {
|
|
274
|
+
channelName: snapshot.originChannel || "sdk",
|
|
275
|
+
userId: snapshot.userId || defaultUserId(),
|
|
276
|
+
workspacePath: snapshot.workspacePath || undefined,
|
|
277
|
+
});
|
|
278
|
+
thread.bindDynamicTools(options.dynamicTools);
|
|
279
|
+
return thread;
|
|
280
|
+
}
|
|
281
|
+
async list(options = {}) {
|
|
282
|
+
const page = await this.listPage(options);
|
|
283
|
+
return page.data;
|
|
284
|
+
}
|
|
285
|
+
async listPage(options = {}) {
|
|
286
|
+
const identity = normalizeIdentity(options);
|
|
287
|
+
return await this.sdk.wire.threadListPage({
|
|
288
|
+
...identity,
|
|
289
|
+
scope: options.scope,
|
|
290
|
+
includeArchived: options.includeArchived ?? false,
|
|
291
|
+
query: options.query,
|
|
292
|
+
limit: options.limit,
|
|
293
|
+
cursor: options.cursor,
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
async read(threadId) {
|
|
297
|
+
return await this.sdk.wire.threadRead(threadId);
|
|
298
|
+
}
|
|
299
|
+
async listTurns(threadId, options = {}) {
|
|
300
|
+
return await this.sdk.wire.threadTurnsList({ threadId, ...options });
|
|
301
|
+
}
|
|
302
|
+
async listItems(threadId, options = {}) {
|
|
303
|
+
return await this.sdk.wire.threadItemsList({ threadId, ...options });
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
class AppBindingManagerImpl {
|
|
307
|
+
sdk;
|
|
308
|
+
constructor(sdk) {
|
|
309
|
+
this.sdk = sdk;
|
|
310
|
+
}
|
|
311
|
+
async listApps(params = {}) {
|
|
312
|
+
const result = await this.sdk.request("app/list", {
|
|
313
|
+
includeCatalog: params.includeCatalog ?? true,
|
|
314
|
+
includeDisabled: params.includeDisabled ?? true,
|
|
315
|
+
threadId: params.threadId,
|
|
316
|
+
forceRefresh: params.forceRefresh ?? false,
|
|
317
|
+
});
|
|
318
|
+
return result.apps ?? [];
|
|
319
|
+
}
|
|
320
|
+
async viewApp(appId, params = {}) {
|
|
321
|
+
const result = await this.sdk.request("app/view", {
|
|
322
|
+
appId,
|
|
323
|
+
threadId: params.threadId,
|
|
324
|
+
});
|
|
325
|
+
if (!result.app)
|
|
326
|
+
throw new Error(`App '${appId}' was not returned by app/view.`);
|
|
327
|
+
return result.app;
|
|
328
|
+
}
|
|
329
|
+
async startConnection(appId, params = {}) {
|
|
330
|
+
return await this.sdk.request("app/connection/start", {
|
|
331
|
+
appId,
|
|
332
|
+
handoffMode: params.handoffMode,
|
|
333
|
+
returnTo: params.returnTo,
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
async connect(params) {
|
|
337
|
+
return await this.sdk.request("app/connection/connect", {
|
|
338
|
+
connectionRequestId: params.connectionRequestId,
|
|
339
|
+
requestToken: params.requestToken,
|
|
340
|
+
accountLabel: params.accountLabel,
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
async connectionStatus(appId) {
|
|
344
|
+
return await this.sdk.request("app/connection/status", { appId });
|
|
345
|
+
}
|
|
346
|
+
async revokeConnection(appId, reason) {
|
|
347
|
+
return await this.sdk.request("app/connection/revoke", { appId, reason });
|
|
348
|
+
}
|
|
349
|
+
async publishSurface(params) {
|
|
350
|
+
return await this.sdk.request("app/surface/publish", {
|
|
351
|
+
surfaceId: params.surfaceId,
|
|
352
|
+
endpoint: params.endpoint,
|
|
353
|
+
bearer: params.bearer,
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
async resolveSurface(params) {
|
|
357
|
+
return await this.sdk.request("app/surface/resolve", {
|
|
358
|
+
appId: params.appId,
|
|
359
|
+
surfaceId: params.surfaceId,
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
async authenticate(appId, credential) {
|
|
363
|
+
return await this.sdk.request("app/connection/authenticate", { appId, credential });
|
|
364
|
+
}
|
|
365
|
+
async refreshCredential() {
|
|
366
|
+
return await this.sdk.request("app/connection/refresh", {});
|
|
367
|
+
}
|
|
368
|
+
async activate(params) {
|
|
369
|
+
return await this.sdk.request("app/binding/activate", params);
|
|
370
|
+
}
|
|
371
|
+
async rebind(params) {
|
|
372
|
+
return await this.sdk.request("app/binding/rebind", params);
|
|
373
|
+
}
|
|
374
|
+
async confirmCapabilities(threadId, bindingId, candidateRevision, decision) {
|
|
375
|
+
return await this.sdk.request("thread/appBindings/confirmCapabilities", { threadId, bindingId, candidateRevision, decision });
|
|
376
|
+
}
|
|
377
|
+
async enable(threadId, appId) {
|
|
378
|
+
return await this.sdk.request("thread/appBindings/enable", {
|
|
379
|
+
threadId,
|
|
380
|
+
appId,
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
async createSocialBindingRequest(params) {
|
|
384
|
+
return await this.sdk.request("thread/socialBindings/request/create", {
|
|
385
|
+
threadId: params.threadId,
|
|
386
|
+
channelName: params.channelName,
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
async getBindingRequest(params) {
|
|
390
|
+
return await this.sdk.request(params.bindCode ? "app/socialBinding/request/get" : "app/binding/request/get", params.bindCode ? { code: params.bindCode } : {
|
|
391
|
+
bindingRequestId: params.bindingRequestId,
|
|
392
|
+
requestToken: params.requestToken,
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
async acceptSocialBinding(params) {
|
|
396
|
+
const target = params.socialTarget;
|
|
397
|
+
return await this.sdk.request("app/socialBinding/accept", {
|
|
398
|
+
code: params.requestToken,
|
|
399
|
+
target,
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
async resolveSocialBinding(params) {
|
|
403
|
+
return await this.sdk.request("app/socialBinding/resolve", {
|
|
404
|
+
channelName: params.channelName,
|
|
405
|
+
accountId: params.accountId,
|
|
406
|
+
conversationKind: params.conversationKind,
|
|
407
|
+
conversationId: params.conversationId,
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
async enqueueThreadInput(params) {
|
|
411
|
+
return await this.sdk.request("app/threadInput/enqueue", {
|
|
412
|
+
...params,
|
|
413
|
+
sender: toContractSender(params.sender),
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
async listThreadBindings(threadId, includeRevoked = false) {
|
|
417
|
+
const result = await this.sdk.request("thread/appBindings/list", {
|
|
418
|
+
threadId,
|
|
419
|
+
includeRevoked,
|
|
420
|
+
});
|
|
421
|
+
return result.bindings ?? [];
|
|
422
|
+
}
|
|
423
|
+
async revokeThreadBinding(threadId, bindingId, reason) {
|
|
424
|
+
return await this.sdk.request("thread/appBindings/revoke", {
|
|
425
|
+
threadId,
|
|
426
|
+
bindingId,
|
|
427
|
+
reason,
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
async refreshThreadBindings(threadId, bindingId) {
|
|
431
|
+
const result = await this.sdk.request("thread/appBindings/list", { threadId, bindingId });
|
|
432
|
+
return result.bindings ?? [];
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
class ModelManagerImpl {
|
|
436
|
+
sdk;
|
|
437
|
+
constructor(sdk) {
|
|
438
|
+
this.sdk = sdk;
|
|
439
|
+
}
|
|
440
|
+
async list() {
|
|
441
|
+
const result = await this.sdk.request("model/list", {});
|
|
442
|
+
return result.models ?? [];
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
class McpRuntimeManagerImpl {
|
|
446
|
+
sdk;
|
|
447
|
+
constructor(sdk) {
|
|
448
|
+
this.sdk = sdk;
|
|
449
|
+
}
|
|
450
|
+
listStatus(params = {}) {
|
|
451
|
+
return this.sdk.request("mcpServerStatus/list", params);
|
|
452
|
+
}
|
|
453
|
+
readResource(params) {
|
|
454
|
+
return this.sdk.request("mcpServer/resource/read", params);
|
|
455
|
+
}
|
|
456
|
+
callTool(params) {
|
|
457
|
+
return this.sdk.request("mcpServer/tool/call", params);
|
|
458
|
+
}
|
|
459
|
+
loginOAuth(params) {
|
|
460
|
+
return this.sdk.request("mcpServer/oauth/login", params);
|
|
461
|
+
}
|
|
462
|
+
reload() {
|
|
463
|
+
return this.sdk.request("config/mcpServer/reload", {});
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
export class DotCraft {
|
|
467
|
+
wire;
|
|
468
|
+
serverInfo;
|
|
469
|
+
capabilities;
|
|
470
|
+
approvalHandler;
|
|
471
|
+
userInputHandler;
|
|
472
|
+
threads;
|
|
473
|
+
appBindings;
|
|
474
|
+
models;
|
|
475
|
+
mcpRuntime;
|
|
476
|
+
constructor(wire, serverInfo, capabilities, approvalHandler, userInputHandler) {
|
|
477
|
+
this.wire = wire;
|
|
478
|
+
this.serverInfo = serverInfo;
|
|
479
|
+
this.capabilities = capabilities;
|
|
480
|
+
this.approvalHandler = approvalHandler;
|
|
481
|
+
this.userInputHandler = userInputHandler;
|
|
482
|
+
this.threads = new ThreadManagerImpl(this);
|
|
483
|
+
this.appBindings = new AppBindingManagerImpl(this);
|
|
484
|
+
this.models = new ModelManagerImpl(this);
|
|
485
|
+
this.mcpRuntime = new McpRuntimeManagerImpl(this);
|
|
486
|
+
this.installServerRequestHandlers();
|
|
487
|
+
}
|
|
488
|
+
static async local(options) {
|
|
489
|
+
if (!options.workspacePath?.trim()) {
|
|
490
|
+
throw new InitializationError("workspacePath is required for DotCraft.local().");
|
|
491
|
+
}
|
|
492
|
+
const hub = new HubClient({
|
|
493
|
+
executable: options.executable,
|
|
494
|
+
expectedExecutable: options.expectedExecutable,
|
|
495
|
+
binaryMatchPolicy: options.binaryMatchPolicy,
|
|
496
|
+
hubStartupTimeoutMs: options.hubStartupTimeoutMs,
|
|
497
|
+
homeDir: options.homeDir,
|
|
498
|
+
});
|
|
499
|
+
const ensured = await hub.ensureAppServer(options.workspacePath, {
|
|
500
|
+
clientName: options.clientName ?? "dotcraft-sdk",
|
|
501
|
+
clientVersion: options.clientVersion ?? "0.1.0",
|
|
502
|
+
});
|
|
503
|
+
const wsUrl = ensured.endpoints.appServerWebSocket;
|
|
504
|
+
if (!wsUrl)
|
|
505
|
+
throw new InitializationError("Hub response did not include endpoints.appServerWebSocket.");
|
|
506
|
+
return await DotCraft.connect(new WebSocketTransport({ url: wsUrl }), options);
|
|
507
|
+
}
|
|
508
|
+
static async localChat(options = {}) {
|
|
509
|
+
const hub = new HubClient({
|
|
510
|
+
executable: options.executable,
|
|
511
|
+
expectedExecutable: options.expectedExecutable,
|
|
512
|
+
binaryMatchPolicy: options.binaryMatchPolicy,
|
|
513
|
+
hubStartupTimeoutMs: options.hubStartupTimeoutMs,
|
|
514
|
+
homeDir: options.homeDir,
|
|
515
|
+
});
|
|
516
|
+
const ensured = await hub.ensureDefaultChatAppServer({
|
|
517
|
+
clientName: options.clientName ?? "dotcraft-sdk",
|
|
518
|
+
clientVersion: options.clientVersion ?? "0.1.0",
|
|
519
|
+
});
|
|
520
|
+
const wsUrl = ensured.endpoints.appServerWebSocket;
|
|
521
|
+
if (!wsUrl)
|
|
522
|
+
throw new InitializationError("Hub response did not include endpoints.appServerWebSocket.");
|
|
523
|
+
return await DotCraft.connect(new WebSocketTransport({ url: wsUrl }), {
|
|
524
|
+
...options,
|
|
525
|
+
workspacePath: ensured.workspacePath,
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
static async remote(options) {
|
|
529
|
+
return await DotCraft.connect(new WebSocketTransport({ url: options.url, token: options.token }), options);
|
|
530
|
+
}
|
|
531
|
+
request(method, params) {
|
|
532
|
+
return this.wire.request(method, params);
|
|
533
|
+
}
|
|
534
|
+
requestRaw(method, params) {
|
|
535
|
+
return this.wire.requestRaw(method, params);
|
|
536
|
+
}
|
|
537
|
+
on(event, handler) {
|
|
538
|
+
return this.wire.on(event, handler);
|
|
539
|
+
}
|
|
540
|
+
onRaw(event, handler) {
|
|
541
|
+
return this.wire.onRaw(event, handler);
|
|
542
|
+
}
|
|
543
|
+
async close() {
|
|
544
|
+
await this.wire.stop();
|
|
545
|
+
}
|
|
546
|
+
registerDynamicToolHandler(threadId, namespace, name, handler) {
|
|
547
|
+
const key = toolKey(threadId, namespace, name);
|
|
548
|
+
this.dynamicToolHandlers.set(key, handler);
|
|
549
|
+
return () => this.dynamicToolHandlers.delete(key);
|
|
550
|
+
}
|
|
551
|
+
dynamicToolHandlers = new Map();
|
|
552
|
+
static async connect(transport, options) {
|
|
553
|
+
if (options.capabilities?.approvalSupport === true && !options.approvalHandler) {
|
|
554
|
+
throw new InitializationError("approvalSupport requires an approvalHandler.");
|
|
555
|
+
}
|
|
556
|
+
if (options.capabilities?.requestUserInputSupport === true && !options.userInputHandler) {
|
|
557
|
+
throw new InitializationError("requestUserInputSupport requires a userInputHandler.");
|
|
558
|
+
}
|
|
559
|
+
const wire = new InternalAppServerClient(transport, { autoReconnect: true });
|
|
560
|
+
let sdk;
|
|
561
|
+
if (options.approvalHandler) {
|
|
562
|
+
wire.registerServerRequestHandler("item/approval/request", async (_id, params) => ({
|
|
563
|
+
decision: await options.approvalHandler(params),
|
|
564
|
+
}));
|
|
565
|
+
}
|
|
566
|
+
if (options.userInputHandler) {
|
|
567
|
+
wire.registerServerRequestHandler("item/tool/requestUserInput", async (_id, params) => (await options.userInputHandler(params)));
|
|
568
|
+
}
|
|
569
|
+
wire.registerServerRequestHandler("item/tool/call", async (_id, params) => {
|
|
570
|
+
const request = params;
|
|
571
|
+
const handler = sdk?.dynamicToolHandlers.get(toolKey(request.threadId, request.namespace, request.tool));
|
|
572
|
+
if (!handler) {
|
|
573
|
+
return { success: false, errorCode: "UnsupportedTool", errorMessage: "No handler registered for this dynamic tool." };
|
|
574
|
+
}
|
|
575
|
+
try {
|
|
576
|
+
return await handler(request);
|
|
577
|
+
}
|
|
578
|
+
catch (error) {
|
|
579
|
+
return {
|
|
580
|
+
success: false,
|
|
581
|
+
errorCode: "AdapterToolCallFailed",
|
|
582
|
+
errorMessage: error instanceof Error ? error.message : String(error),
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
});
|
|
586
|
+
await wire.connect();
|
|
587
|
+
const initialized = await wire.initialize({
|
|
588
|
+
clientName: options.clientName ?? "dotcraft-sdk",
|
|
589
|
+
clientVersion: options.clientVersion ?? "0.1.0",
|
|
590
|
+
clientTitle: options.clientTitle,
|
|
591
|
+
approvalSupport: Boolean(options.approvalHandler),
|
|
592
|
+
requestUserInputSupport: Boolean(options.userInputHandler),
|
|
593
|
+
streamingSupport: true,
|
|
594
|
+
configChange: true,
|
|
595
|
+
extraCapabilities: options.capabilities,
|
|
596
|
+
});
|
|
597
|
+
sdk = new DotCraft(wire, initialized.serverInfo, initialized.capabilities, options.approvalHandler, options.userInputHandler);
|
|
598
|
+
return sdk;
|
|
599
|
+
}
|
|
600
|
+
installServerRequestHandlers() {
|
|
601
|
+
if (this.approvalHandler) {
|
|
602
|
+
this.wire.registerServerRequestHandler("item/approval/request", async (_id, params) => ({
|
|
603
|
+
decision: await this.approvalHandler(params),
|
|
604
|
+
}));
|
|
605
|
+
}
|
|
606
|
+
if (this.userInputHandler) {
|
|
607
|
+
this.wire.registerServerRequestHandler("item/tool/requestUserInput", async (_id, params) => (await this.userInputHandler(params)));
|
|
608
|
+
}
|
|
609
|
+
this.wire.registerServerRequestHandler("item/tool/call", async (_id, params) => {
|
|
610
|
+
const request = params;
|
|
611
|
+
const handler = this.dynamicToolHandlers.get(toolKey(request.threadId, request.namespace, request.tool));
|
|
612
|
+
if (!handler) {
|
|
613
|
+
return { success: false, errorCode: "UnsupportedTool", errorMessage: "No handler registered for this dynamic tool." };
|
|
614
|
+
}
|
|
615
|
+
try {
|
|
616
|
+
return await handler(request);
|
|
617
|
+
}
|
|
618
|
+
catch (error) {
|
|
619
|
+
return {
|
|
620
|
+
success: false,
|
|
621
|
+
errorCode: "AdapterToolCallFailed",
|
|
622
|
+
errorMessage: error instanceof Error ? error.message : String(error),
|
|
623
|
+
};
|
|
624
|
+
}
|
|
625
|
+
});
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
export class DotCraftThread {
|
|
629
|
+
sdk;
|
|
630
|
+
identity;
|
|
631
|
+
id;
|
|
632
|
+
cached;
|
|
633
|
+
dynamicToolUnsubscribes = [];
|
|
634
|
+
constructor(sdk, snapshot, identity) {
|
|
635
|
+
this.sdk = sdk;
|
|
636
|
+
this.identity = identity;
|
|
637
|
+
this.cached = snapshot;
|
|
638
|
+
this.id = snapshot.id;
|
|
639
|
+
}
|
|
640
|
+
snapshot() {
|
|
641
|
+
return this.cached;
|
|
642
|
+
}
|
|
643
|
+
async refresh() {
|
|
644
|
+
this.cached = await this.sdk.wire.threadRead(this.id);
|
|
645
|
+
return this.cached;
|
|
646
|
+
}
|
|
647
|
+
async listTurns(options = {}) {
|
|
648
|
+
return await this.sdk.wire.threadTurnsList({ threadId: this.id, ...options });
|
|
649
|
+
}
|
|
650
|
+
async listItems(options = {}) {
|
|
651
|
+
return await this.sdk.wire.threadItemsList({ threadId: this.id, ...options });
|
|
652
|
+
}
|
|
653
|
+
async subscribe(options = {}) {
|
|
654
|
+
await this.sdk.wire.threadSubscribe(this.id, options.replayRecent ?? false);
|
|
655
|
+
return {
|
|
656
|
+
threadId: this.id,
|
|
657
|
+
unsubscribe: async () => {
|
|
658
|
+
await this.unsubscribe();
|
|
659
|
+
},
|
|
660
|
+
};
|
|
661
|
+
}
|
|
662
|
+
async unsubscribe() {
|
|
663
|
+
await this.sdk.wire.threadUnsubscribe(this.id);
|
|
664
|
+
}
|
|
665
|
+
async run(input, options = {}) {
|
|
666
|
+
let queued = null;
|
|
667
|
+
for await (const event of this.runStreamed(input, options)) {
|
|
668
|
+
if (event.type === "completed" && event.result)
|
|
669
|
+
return event.result;
|
|
670
|
+
if (event.type === "queue_updated") {
|
|
671
|
+
queued = {
|
|
672
|
+
thread: this.cached,
|
|
673
|
+
turn: null,
|
|
674
|
+
text: "",
|
|
675
|
+
items: [],
|
|
676
|
+
rawEvents: options.collectRawEvents ? [event.raw] : undefined,
|
|
677
|
+
queuedInput: event.queuedInput,
|
|
678
|
+
};
|
|
679
|
+
}
|
|
680
|
+
if (event.type === "failed") {
|
|
681
|
+
throw new TurnFailedError(event.error ?? "SessionTurn failed.", event.turn);
|
|
682
|
+
}
|
|
683
|
+
if (event.type === "cancelled") {
|
|
684
|
+
throw new TurnCancelledError("SessionTurn was cancelled.", event.turn);
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
if (queued)
|
|
688
|
+
return queued;
|
|
689
|
+
throw new TurnFailedError("Run finished without a terminal event.");
|
|
690
|
+
}
|
|
691
|
+
async *runStreamed(input, options = {}) {
|
|
692
|
+
if (options.abortSignal?.aborted)
|
|
693
|
+
throw abortError();
|
|
694
|
+
const normalized = normalizeRunInput(input, options.sender);
|
|
695
|
+
const reducer = new RunReducer();
|
|
696
|
+
const rawEvents = [];
|
|
697
|
+
const eventStream = this.sdk.wire.streamEvents(this.id);
|
|
698
|
+
let turn;
|
|
699
|
+
let abortListener = null;
|
|
700
|
+
try {
|
|
701
|
+
try {
|
|
702
|
+
turn = await this.sdk.wire.turnStart(this.id, normalized.input, toContractSender(normalized.sender));
|
|
703
|
+
}
|
|
704
|
+
catch (error) {
|
|
705
|
+
await eventStream.return?.();
|
|
706
|
+
if (error instanceof TurnInProgressError && options.enqueueIfBusy) {
|
|
707
|
+
const queued = await this.enqueue({ input: normalized.input, sender: normalized.sender });
|
|
708
|
+
const raw = JsonRpcMessage.fromDict({ method: "thread/queue/updated", params: queued.raw });
|
|
709
|
+
yield {
|
|
710
|
+
type: "queue_updated",
|
|
711
|
+
threadId: this.id,
|
|
712
|
+
raw,
|
|
713
|
+
queuedInput: queued.queuedInput,
|
|
714
|
+
};
|
|
715
|
+
return;
|
|
716
|
+
}
|
|
717
|
+
throw error;
|
|
718
|
+
}
|
|
719
|
+
if (options.abortSignal) {
|
|
720
|
+
abortListener = () => {
|
|
721
|
+
void this.interrupt(turn.id).catch(() => { });
|
|
722
|
+
};
|
|
723
|
+
options.abortSignal.addEventListener("abort", abortListener, { once: true });
|
|
724
|
+
}
|
|
725
|
+
for await (const raw of eventStream) {
|
|
726
|
+
rawEvents.push(raw);
|
|
727
|
+
reducer.apply(raw);
|
|
728
|
+
const params = paramsRecord(raw.params);
|
|
729
|
+
const resolvedTurn = eventTurn(params);
|
|
730
|
+
const type = methodToRunEventType(raw.method);
|
|
731
|
+
const base = {
|
|
732
|
+
type,
|
|
733
|
+
threadId: resolveThreadId(this.id, params),
|
|
734
|
+
turnId: typeof params.turnId === "string" ? params.turnId : resolvedTurn?.id,
|
|
735
|
+
raw,
|
|
736
|
+
};
|
|
737
|
+
if (type === "agent_message_delta" || type === "reasoning_delta" || type === "tool_arguments_delta") {
|
|
738
|
+
base.delta = typeof params.delta === "string" ? params.delta : "";
|
|
739
|
+
}
|
|
740
|
+
if (type === "item_started" || type === "item_completed" || type === "approval_resolved") {
|
|
741
|
+
base.item = params.item;
|
|
742
|
+
}
|
|
743
|
+
if (resolvedTurn)
|
|
744
|
+
base.turn = resolvedTurn;
|
|
745
|
+
if (type === "completed" && resolvedTurn) {
|
|
746
|
+
this.cached = await this.sdk.wire.threadRead(this.id);
|
|
747
|
+
const text = reducer.textFromCompleted(params);
|
|
748
|
+
base.result = {
|
|
749
|
+
thread: this.cached,
|
|
750
|
+
turn: resolvedTurn,
|
|
751
|
+
text,
|
|
752
|
+
items: resolvedTurn.items ?? [],
|
|
753
|
+
usage: resolvedTurn.tokenUsage,
|
|
754
|
+
rawEvents: options.collectRawEvents ? [...rawEvents] : undefined,
|
|
755
|
+
};
|
|
756
|
+
yield base;
|
|
757
|
+
return;
|
|
758
|
+
}
|
|
759
|
+
if (type === "failed") {
|
|
760
|
+
base.error = typeof params.error === "string" ? params.error : resolvedTurn?.error ?? "SessionTurn failed.";
|
|
761
|
+
yield base;
|
|
762
|
+
return;
|
|
763
|
+
}
|
|
764
|
+
if (type === "cancelled") {
|
|
765
|
+
yield base;
|
|
766
|
+
return;
|
|
767
|
+
}
|
|
768
|
+
yield base;
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
finally {
|
|
772
|
+
if (abortListener && options.abortSignal) {
|
|
773
|
+
options.abortSignal.removeEventListener("abort", abortListener);
|
|
774
|
+
}
|
|
775
|
+
await eventStream.return?.();
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
async enqueue(input, options = {}) {
|
|
779
|
+
const normalized = normalizeRunInput(input, options.sender);
|
|
780
|
+
const raw = await this.sdk.wire.turnEnqueue(this.id, normalized.input, toContractSender(normalized.sender));
|
|
781
|
+
return {
|
|
782
|
+
queuedInput: raw.queuedInput,
|
|
783
|
+
queuedInputs: raw.queuedInputs,
|
|
784
|
+
raw,
|
|
785
|
+
};
|
|
786
|
+
}
|
|
787
|
+
async interrupt(turnId) {
|
|
788
|
+
await this.sdk.wire.turnInterrupt(this.id, turnId);
|
|
789
|
+
}
|
|
790
|
+
async setMode(mode) {
|
|
791
|
+
await this.sdk.wire.threadSetMode(this.id, mode);
|
|
792
|
+
}
|
|
793
|
+
async archive() {
|
|
794
|
+
await this.sdk.wire.threadArchive(this.id);
|
|
795
|
+
}
|
|
796
|
+
async delete() {
|
|
797
|
+
await this.sdk.wire.threadDelete(this.id);
|
|
798
|
+
}
|
|
799
|
+
onToolCall(namespace, name, handler) {
|
|
800
|
+
return this.sdk.registerDynamicToolHandler(this.id, namespace, name, handler);
|
|
801
|
+
}
|
|
802
|
+
bindDynamicTools(tools) {
|
|
803
|
+
for (const unsubscribe of this.dynamicToolUnsubscribes.splice(0))
|
|
804
|
+
unsubscribe();
|
|
805
|
+
if (!tools)
|
|
806
|
+
return;
|
|
807
|
+
for (const declaration of tools) {
|
|
808
|
+
if (declaration.type === "namespace") {
|
|
809
|
+
for (const tool of declaration.tools) {
|
|
810
|
+
this.dynamicToolUnsubscribes.push(this.onToolCall(declaration.name, tool.name, tool.handler));
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
else {
|
|
814
|
+
this.dynamicToolUnsubscribes.push(this.onToolCall(null, declaration.name, declaration.handler));
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
//# sourceMappingURL=dotcraft.js.map
|