@mondaydotcomorg/atp-client 0.19.6 → 0.19.8
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 +4 -1
- package/dist/client.d.ts +23 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +26 -5
- package/dist/client.js.map +1 -1
- package/dist/core/api-operations.d.ts +4 -2
- package/dist/core/api-operations.d.ts.map +1 -1
- package/dist/core/api-operations.js +25 -1
- package/dist/core/api-operations.js.map +1 -1
- package/dist/core/execution-operations.d.ts +4 -2
- package/dist/core/execution-operations.d.ts.map +1 -1
- package/dist/core/execution-operations.js +60 -40
- package/dist/core/execution-operations.js.map +1 -1
- package/dist/core/in-process-session.d.ts +96 -0
- package/dist/core/in-process-session.d.ts.map +1 -0
- package/dist/core/in-process-session.js +175 -0
- package/dist/core/in-process-session.js.map +1 -0
- package/dist/core/index.cjs +1192 -0
- package/dist/core/index.cjs.map +1 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1181 -5
- package/dist/core/index.js.map +1 -1
- package/dist/core/session.d.ts +24 -1
- package/dist/core/session.d.ts.map +1 -1
- package/dist/core/session.js.map +1 -1
- package/dist/index.cjs +1589 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1577 -6
- package/dist/index.js.map +1 -1
- package/package.json +12 -7
- package/src/client.ts +51 -7
- package/src/core/api-operations.ts +38 -3
- package/src/core/execution-operations.ts +73 -45
- package/src/core/in-process-session.ts +293 -0
- package/src/core/index.ts +1 -0
- package/src/core/session.ts +20 -1
- package/src/index.ts +2 -0
package/dist/core/index.js
CHANGED
|
@@ -1,7 +1,1183 @@
|
|
|
1
|
-
|
|
2
|
-
export * from './api-operations.js';
|
|
3
|
-
export * from './execution-operations.js';
|
|
4
|
-
export * from './service-providers.js';
|
|
5
|
-
export * from './types.js';
|
|
1
|
+
import { ExecutionStatus, CallbackType, ToolOperation } from '@mondaydotcomorg/atp-protocol';
|
|
6
2
|
export { CallbackType } from '@mondaydotcomorg/atp-protocol';
|
|
3
|
+
import { log } from '@mondaydotcomorg/atp-runtime';
|
|
4
|
+
|
|
5
|
+
var __defProp = Object.defineProperty;
|
|
6
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
7
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
8
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
9
|
+
}) : x)(function(x) {
|
|
10
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
11
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
// src/core/session.ts
|
|
15
|
+
var ClientSession = class {
|
|
16
|
+
static {
|
|
17
|
+
__name(this, "ClientSession");
|
|
18
|
+
}
|
|
19
|
+
baseUrl;
|
|
20
|
+
customHeaders;
|
|
21
|
+
clientId;
|
|
22
|
+
clientToken;
|
|
23
|
+
initPromise;
|
|
24
|
+
hooks;
|
|
25
|
+
constructor(baseUrl, headers, hooks) {
|
|
26
|
+
this.baseUrl = baseUrl;
|
|
27
|
+
this.customHeaders = headers || {};
|
|
28
|
+
this.hooks = hooks;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Initializes the client session with the server.
|
|
32
|
+
* This MUST be called before any other operations.
|
|
33
|
+
* The server generates and returns a unique client ID and token.
|
|
34
|
+
* @param clientInfo - Optional client information
|
|
35
|
+
* @param tools - Optional client tool definitions to register with the server
|
|
36
|
+
* @param services - Optional client service capabilities (LLM, approval, embedding)
|
|
37
|
+
*/
|
|
38
|
+
async init(clientInfo, tools, services) {
|
|
39
|
+
if (this.initPromise) {
|
|
40
|
+
await this.initPromise;
|
|
41
|
+
return {
|
|
42
|
+
clientId: this.clientId,
|
|
43
|
+
token: this.clientToken,
|
|
44
|
+
expiresAt: 0,
|
|
45
|
+
tokenRotateAt: 0
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
this.initPromise = (async () => {
|
|
49
|
+
const url = `${this.baseUrl}/api/init`;
|
|
50
|
+
const body = JSON.stringify({
|
|
51
|
+
clientInfo,
|
|
52
|
+
tools: tools || [],
|
|
53
|
+
services
|
|
54
|
+
});
|
|
55
|
+
const headers = await this.prepareHeaders("POST", url, body);
|
|
56
|
+
const response = await fetch(url, {
|
|
57
|
+
method: "POST",
|
|
58
|
+
headers,
|
|
59
|
+
body
|
|
60
|
+
});
|
|
61
|
+
if (!response.ok) {
|
|
62
|
+
throw new Error(`Client initialization failed: ${response.status} ${response.statusText}`);
|
|
63
|
+
}
|
|
64
|
+
const data = await response.json();
|
|
65
|
+
this.clientId = data.clientId;
|
|
66
|
+
this.clientToken = data.token;
|
|
67
|
+
})();
|
|
68
|
+
await this.initPromise;
|
|
69
|
+
return {
|
|
70
|
+
clientId: this.clientId,
|
|
71
|
+
token: this.clientToken,
|
|
72
|
+
expiresAt: 0,
|
|
73
|
+
tokenRotateAt: 0
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Gets the unique client ID.
|
|
78
|
+
*/
|
|
79
|
+
getClientId() {
|
|
80
|
+
if (!this.clientId) {
|
|
81
|
+
throw new Error("Client not initialized. Call init() first.");
|
|
82
|
+
}
|
|
83
|
+
return this.clientId;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Ensures the client is initialized before making requests.
|
|
87
|
+
*/
|
|
88
|
+
async ensureInitialized() {
|
|
89
|
+
if (!this.clientId) {
|
|
90
|
+
throw new Error("Client not initialized. Call init() first.");
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Creates HTTP headers for requests.
|
|
95
|
+
*/
|
|
96
|
+
getHeaders() {
|
|
97
|
+
const headers = {
|
|
98
|
+
"Content-Type": "application/json",
|
|
99
|
+
...this.customHeaders
|
|
100
|
+
};
|
|
101
|
+
if (this.clientId) {
|
|
102
|
+
headers["X-Client-ID"] = this.clientId;
|
|
103
|
+
}
|
|
104
|
+
if (this.clientToken) {
|
|
105
|
+
headers["Authorization"] = `Bearer ${this.clientToken}`;
|
|
106
|
+
}
|
|
107
|
+
return headers;
|
|
108
|
+
}
|
|
109
|
+
getBaseUrl() {
|
|
110
|
+
return this.baseUrl;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Updates the client token from response headers (token refresh).
|
|
114
|
+
*/
|
|
115
|
+
updateToken(response) {
|
|
116
|
+
const newToken = response.headers.get("X-ATP-Token");
|
|
117
|
+
if (newToken) {
|
|
118
|
+
this.clientToken = newToken;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Prepares headers for a request, calling preRequest hook if configured
|
|
123
|
+
*/
|
|
124
|
+
async prepareHeaders(method, url, body) {
|
|
125
|
+
let headers = {
|
|
126
|
+
"Content-Type": "application/json",
|
|
127
|
+
...this.customHeaders
|
|
128
|
+
};
|
|
129
|
+
if (this.clientId) {
|
|
130
|
+
headers["X-Client-ID"] = this.clientId;
|
|
131
|
+
}
|
|
132
|
+
if (this.clientToken) {
|
|
133
|
+
headers["Authorization"] = `Bearer ${this.clientToken}`;
|
|
134
|
+
}
|
|
135
|
+
if (this.hooks?.preRequest) {
|
|
136
|
+
try {
|
|
137
|
+
const result = await this.hooks.preRequest({
|
|
138
|
+
url,
|
|
139
|
+
method,
|
|
140
|
+
currentHeaders: headers,
|
|
141
|
+
body
|
|
142
|
+
});
|
|
143
|
+
if (result.abort) {
|
|
144
|
+
throw new Error(result.abortReason || "Request aborted by preRequest hook");
|
|
145
|
+
}
|
|
146
|
+
if (result.headers) {
|
|
147
|
+
headers = result.headers;
|
|
148
|
+
}
|
|
149
|
+
} catch (error) {
|
|
150
|
+
throw error;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return headers;
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
// src/core/in-process-session.ts
|
|
158
|
+
var InProcessSession = class {
|
|
159
|
+
static {
|
|
160
|
+
__name(this, "InProcessSession");
|
|
161
|
+
}
|
|
162
|
+
server;
|
|
163
|
+
clientId;
|
|
164
|
+
clientToken;
|
|
165
|
+
initialized = false;
|
|
166
|
+
initPromise;
|
|
167
|
+
constructor(server) {
|
|
168
|
+
this.server = server;
|
|
169
|
+
}
|
|
170
|
+
async init(clientInfo, tools, services) {
|
|
171
|
+
if (this.initPromise) {
|
|
172
|
+
await this.initPromise;
|
|
173
|
+
return {
|
|
174
|
+
clientId: this.clientId,
|
|
175
|
+
token: this.clientToken,
|
|
176
|
+
expiresAt: 0,
|
|
177
|
+
tokenRotateAt: 0
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
this.initPromise = (async () => {
|
|
181
|
+
await this.server.start();
|
|
182
|
+
const ctx = this.createContext({
|
|
183
|
+
method: "POST",
|
|
184
|
+
path: "/api/init",
|
|
185
|
+
body: {
|
|
186
|
+
clientInfo,
|
|
187
|
+
tools: tools || [],
|
|
188
|
+
services
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
const result = await this.server.handleInit(ctx);
|
|
192
|
+
this.clientId = result.clientId;
|
|
193
|
+
this.clientToken = result.token;
|
|
194
|
+
this.initialized = true;
|
|
195
|
+
})();
|
|
196
|
+
await this.initPromise;
|
|
197
|
+
return {
|
|
198
|
+
clientId: this.clientId,
|
|
199
|
+
token: this.clientToken,
|
|
200
|
+
expiresAt: 0,
|
|
201
|
+
tokenRotateAt: 0
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
getClientId() {
|
|
205
|
+
if (!this.clientId) {
|
|
206
|
+
throw new Error("Client not initialized. Call init() first.");
|
|
207
|
+
}
|
|
208
|
+
return this.clientId;
|
|
209
|
+
}
|
|
210
|
+
async ensureInitialized() {
|
|
211
|
+
if (!this.initialized) {
|
|
212
|
+
throw new Error("Client not initialized. Call init() first.");
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
getHeaders() {
|
|
216
|
+
const headers = {
|
|
217
|
+
"content-type": "application/json"
|
|
218
|
+
};
|
|
219
|
+
if (this.clientId) {
|
|
220
|
+
headers["x-client-id"] = this.clientId;
|
|
221
|
+
}
|
|
222
|
+
if (this.clientToken) {
|
|
223
|
+
headers["authorization"] = `Bearer ${this.clientToken}`;
|
|
224
|
+
}
|
|
225
|
+
return headers;
|
|
226
|
+
}
|
|
227
|
+
getBaseUrl() {
|
|
228
|
+
return "";
|
|
229
|
+
}
|
|
230
|
+
updateToken(_response) {
|
|
231
|
+
}
|
|
232
|
+
async prepareHeaders(_method, _url, _body) {
|
|
233
|
+
return this.getHeaders();
|
|
234
|
+
}
|
|
235
|
+
async getDefinitions(options) {
|
|
236
|
+
await this.ensureInitialized();
|
|
237
|
+
const ctx = this.createContext({
|
|
238
|
+
method: "GET",
|
|
239
|
+
path: "/api/definitions",
|
|
240
|
+
query: options?.apiGroups ? {
|
|
241
|
+
apiGroups: options.apiGroups.join(",")
|
|
242
|
+
} : {}
|
|
243
|
+
});
|
|
244
|
+
return await this.server.getDefinitions(ctx);
|
|
245
|
+
}
|
|
246
|
+
async getRuntimeDefinitions(options) {
|
|
247
|
+
await this.ensureInitialized();
|
|
248
|
+
const ctx = this.createContext({
|
|
249
|
+
method: "GET",
|
|
250
|
+
path: "/api/runtime",
|
|
251
|
+
query: options?.apis?.length ? {
|
|
252
|
+
apis: options.apis.join(",")
|
|
253
|
+
} : {}
|
|
254
|
+
});
|
|
255
|
+
return await this.server.getRuntimeDefinitions(ctx);
|
|
256
|
+
}
|
|
257
|
+
async getServerInfo() {
|
|
258
|
+
await this.ensureInitialized();
|
|
259
|
+
return this.server.getInfo();
|
|
260
|
+
}
|
|
261
|
+
async search(query, options) {
|
|
262
|
+
await this.ensureInitialized();
|
|
263
|
+
const ctx = this.createContext({
|
|
264
|
+
method: "POST",
|
|
265
|
+
path: "/api/search",
|
|
266
|
+
body: {
|
|
267
|
+
query,
|
|
268
|
+
...options
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
return await this.server.handleSearch(ctx);
|
|
272
|
+
}
|
|
273
|
+
async explore(path) {
|
|
274
|
+
await this.ensureInitialized();
|
|
275
|
+
const ctx = this.createContext({
|
|
276
|
+
method: "POST",
|
|
277
|
+
path: "/api/explore",
|
|
278
|
+
body: {
|
|
279
|
+
path
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
return await this.server.handleExplore(ctx);
|
|
283
|
+
}
|
|
284
|
+
async execute(code, config) {
|
|
285
|
+
await this.ensureInitialized();
|
|
286
|
+
const ctx = this.createContext({
|
|
287
|
+
method: "POST",
|
|
288
|
+
path: "/api/execute",
|
|
289
|
+
body: {
|
|
290
|
+
code,
|
|
291
|
+
config
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
return await this.server.handleExecute(ctx);
|
|
295
|
+
}
|
|
296
|
+
async resume(executionId, callbackResult) {
|
|
297
|
+
await this.ensureInitialized();
|
|
298
|
+
const ctx = this.createContext({
|
|
299
|
+
method: "POST",
|
|
300
|
+
path: `/api/resume/${executionId}`,
|
|
301
|
+
body: {
|
|
302
|
+
result: callbackResult
|
|
303
|
+
}
|
|
304
|
+
});
|
|
305
|
+
return await this.server.handleResume(ctx, executionId);
|
|
306
|
+
}
|
|
307
|
+
async resumeWithBatchResults(executionId, batchResults) {
|
|
308
|
+
await this.ensureInitialized();
|
|
309
|
+
const ctx = this.createContext({
|
|
310
|
+
method: "POST",
|
|
311
|
+
path: `/api/resume/${executionId}`,
|
|
312
|
+
body: {
|
|
313
|
+
results: batchResults
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
return await this.server.handleResume(ctx, executionId);
|
|
317
|
+
}
|
|
318
|
+
createContext(options) {
|
|
319
|
+
const noopLogger = {
|
|
320
|
+
debug: /* @__PURE__ */ __name(() => {
|
|
321
|
+
}, "debug"),
|
|
322
|
+
info: /* @__PURE__ */ __name(() => {
|
|
323
|
+
}, "info"),
|
|
324
|
+
warn: /* @__PURE__ */ __name(() => {
|
|
325
|
+
}, "warn"),
|
|
326
|
+
error: /* @__PURE__ */ __name(() => {
|
|
327
|
+
}, "error")
|
|
328
|
+
};
|
|
329
|
+
return {
|
|
330
|
+
method: options.method,
|
|
331
|
+
path: options.path,
|
|
332
|
+
query: options.query || {},
|
|
333
|
+
headers: this.getHeaders(),
|
|
334
|
+
body: options.body,
|
|
335
|
+
clientId: this.clientId,
|
|
336
|
+
clientToken: this.clientToken,
|
|
337
|
+
logger: noopLogger,
|
|
338
|
+
status: 200,
|
|
339
|
+
responseBody: null,
|
|
340
|
+
throw: /* @__PURE__ */ __name((status, message) => {
|
|
341
|
+
const error = new Error(message);
|
|
342
|
+
error.status = status;
|
|
343
|
+
throw error;
|
|
344
|
+
}, "throw"),
|
|
345
|
+
assert: /* @__PURE__ */ __name((condition, message) => {
|
|
346
|
+
if (!condition) {
|
|
347
|
+
throw new Error(message);
|
|
348
|
+
}
|
|
349
|
+
}, "assert"),
|
|
350
|
+
set: /* @__PURE__ */ __name(() => {
|
|
351
|
+
}, "set")
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
// src/core/api-operations.ts
|
|
357
|
+
var APIOperations = class {
|
|
358
|
+
static {
|
|
359
|
+
__name(this, "APIOperations");
|
|
360
|
+
}
|
|
361
|
+
session;
|
|
362
|
+
inProcessSession;
|
|
363
|
+
apiDefinitions;
|
|
364
|
+
constructor(session, inProcessSession) {
|
|
365
|
+
this.session = session;
|
|
366
|
+
this.inProcessSession = inProcessSession;
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* Connects to the server and retrieves API definitions.
|
|
370
|
+
*/
|
|
371
|
+
async connect(options) {
|
|
372
|
+
await this.session.ensureInitialized();
|
|
373
|
+
if (this.inProcessSession) {
|
|
374
|
+
const data2 = await this.inProcessSession.getDefinitions(options);
|
|
375
|
+
this.apiDefinitions = data2.typescript;
|
|
376
|
+
return {
|
|
377
|
+
serverVersion: data2.version,
|
|
378
|
+
capabilities: {},
|
|
379
|
+
apiGroups: data2.apiGroups
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
const params = new URLSearchParams();
|
|
383
|
+
if (options?.apiGroups) {
|
|
384
|
+
params.set("apiGroups", options.apiGroups.join(","));
|
|
385
|
+
}
|
|
386
|
+
const url = `${this.session.getBaseUrl()}/api/definitions?${params}`;
|
|
387
|
+
const headers = await this.session.prepareHeaders("GET", url);
|
|
388
|
+
const response = await fetch(url, {
|
|
389
|
+
headers
|
|
390
|
+
});
|
|
391
|
+
if (!response.ok) {
|
|
392
|
+
throw new Error(`Connection failed: ${response.status} ${response.statusText}`);
|
|
393
|
+
}
|
|
394
|
+
const data = await response.json();
|
|
395
|
+
this.apiDefinitions = data.typescript;
|
|
396
|
+
return {
|
|
397
|
+
serverVersion: data.version,
|
|
398
|
+
capabilities: {},
|
|
399
|
+
apiGroups: data.apiGroups
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Gets the TypeScript type definitions for available APIs.
|
|
404
|
+
*/
|
|
405
|
+
getTypeDefinitions() {
|
|
406
|
+
if (!this.apiDefinitions) {
|
|
407
|
+
throw new Error("Not connected. Call connect() first.");
|
|
408
|
+
}
|
|
409
|
+
return this.apiDefinitions;
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Searches for available API functions.
|
|
413
|
+
*/
|
|
414
|
+
async searchAPI(query, options) {
|
|
415
|
+
await this.session.ensureInitialized();
|
|
416
|
+
if (this.inProcessSession) {
|
|
417
|
+
const data2 = await this.inProcessSession.search(query, options);
|
|
418
|
+
return data2.results;
|
|
419
|
+
}
|
|
420
|
+
const url = `${this.session.getBaseUrl()}/api/search`;
|
|
421
|
+
const body = JSON.stringify({
|
|
422
|
+
query,
|
|
423
|
+
...options
|
|
424
|
+
});
|
|
425
|
+
const headers = await this.session.prepareHeaders("POST", url, body);
|
|
426
|
+
const response = await fetch(url, {
|
|
427
|
+
method: "POST",
|
|
428
|
+
headers,
|
|
429
|
+
body
|
|
430
|
+
});
|
|
431
|
+
if (!response.ok) {
|
|
432
|
+
throw new Error(`Search failed: ${response.status} ${response.statusText}`);
|
|
433
|
+
}
|
|
434
|
+
const data = await response.json();
|
|
435
|
+
return data.results;
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Explores the API filesystem at the given path.
|
|
439
|
+
*/
|
|
440
|
+
async exploreAPI(path) {
|
|
441
|
+
await this.session.ensureInitialized();
|
|
442
|
+
if (this.inProcessSession) {
|
|
443
|
+
return await this.inProcessSession.explore(path);
|
|
444
|
+
}
|
|
445
|
+
const url = `${this.session.getBaseUrl()}/api/explore`;
|
|
446
|
+
const body = JSON.stringify({
|
|
447
|
+
path
|
|
448
|
+
});
|
|
449
|
+
const headers = await this.session.prepareHeaders("POST", url, body);
|
|
450
|
+
const response = await fetch(url, {
|
|
451
|
+
method: "POST",
|
|
452
|
+
headers,
|
|
453
|
+
body
|
|
454
|
+
});
|
|
455
|
+
if (!response.ok) {
|
|
456
|
+
throw new Error(`Explore failed: ${response.status} ${response.statusText}`);
|
|
457
|
+
}
|
|
458
|
+
return await response.json();
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Gets information about the server.
|
|
462
|
+
*/
|
|
463
|
+
async getServerInfo() {
|
|
464
|
+
await this.session.ensureInitialized();
|
|
465
|
+
if (this.inProcessSession) {
|
|
466
|
+
return await this.inProcessSession.getServerInfo();
|
|
467
|
+
}
|
|
468
|
+
const url = `${this.session.getBaseUrl()}/api/info`;
|
|
469
|
+
const headers = await this.session.prepareHeaders("GET", url);
|
|
470
|
+
const response = await fetch(url, {
|
|
471
|
+
headers
|
|
472
|
+
});
|
|
473
|
+
if (!response.ok) {
|
|
474
|
+
throw new Error(`Failed to get server info: ${response.status}`);
|
|
475
|
+
}
|
|
476
|
+
return await response.json();
|
|
477
|
+
}
|
|
478
|
+
/**
|
|
479
|
+
* Gets ATP runtime API definitions as TypeScript declarations.
|
|
480
|
+
* Returns the full TypeScript definitions for atp.llm.*, atp.cache.*, etc.
|
|
481
|
+
* These are the APIs available during code execution.
|
|
482
|
+
*
|
|
483
|
+
* Behavior:
|
|
484
|
+
* - No options: Returns APIs based on client capabilities (default filtering)
|
|
485
|
+
* - apis: ['llm', 'cache']: Returns only specified APIs (intersection with client capabilities)
|
|
486
|
+
* - apis: []: Returns all APIs regardless of client capabilities
|
|
487
|
+
*
|
|
488
|
+
* @param options - Optional filtering options
|
|
489
|
+
* @param options.apis - Specific APIs to include (e.g., ['llm', 'cache', 'approval'])
|
|
490
|
+
*/
|
|
491
|
+
async getRuntimeDefinitions(options) {
|
|
492
|
+
await this.session.ensureInitialized();
|
|
493
|
+
if (this.inProcessSession) {
|
|
494
|
+
return await this.inProcessSession.getRuntimeDefinitions(options?.apis ? {
|
|
495
|
+
apis: options.apis
|
|
496
|
+
} : void 0);
|
|
497
|
+
}
|
|
498
|
+
const params = new URLSearchParams();
|
|
499
|
+
if (options?.apis && options.apis.length > 0) {
|
|
500
|
+
params.set("apis", options.apis.join(","));
|
|
501
|
+
}
|
|
502
|
+
const url = `${this.session.getBaseUrl()}/api/runtime${params.toString() ? `?${params}` : ""}`;
|
|
503
|
+
const headers = await this.session.prepareHeaders("GET", url);
|
|
504
|
+
const response = await fetch(url, {
|
|
505
|
+
headers
|
|
506
|
+
});
|
|
507
|
+
if (!response.ok) {
|
|
508
|
+
throw new Error(`Failed to get runtime definitions: ${response.status}`);
|
|
509
|
+
}
|
|
510
|
+
return await response.text();
|
|
511
|
+
}
|
|
512
|
+
};
|
|
513
|
+
|
|
514
|
+
// src/errors.ts
|
|
515
|
+
var ClientCallbackError = class extends Error {
|
|
516
|
+
static {
|
|
517
|
+
__name(this, "ClientCallbackError");
|
|
518
|
+
}
|
|
519
|
+
constructor(message) {
|
|
520
|
+
super(message);
|
|
521
|
+
this.name = "ClientCallbackError";
|
|
522
|
+
}
|
|
523
|
+
};
|
|
524
|
+
|
|
525
|
+
// src/core/provenance-registry.ts
|
|
526
|
+
var ProvenanceTokenRegistry = class {
|
|
527
|
+
static {
|
|
528
|
+
__name(this, "ProvenanceTokenRegistry");
|
|
529
|
+
}
|
|
530
|
+
cache = /* @__PURE__ */ new Map();
|
|
531
|
+
maxSize;
|
|
532
|
+
ttl;
|
|
533
|
+
sequenceCounter = 0;
|
|
534
|
+
constructor(maxSize = 1e4, ttlHours = 1) {
|
|
535
|
+
this.maxSize = maxSize;
|
|
536
|
+
this.ttl = ttlHours * 3600 * 1e3;
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* Add a token to the registry
|
|
540
|
+
*/
|
|
541
|
+
add(token) {
|
|
542
|
+
this.evictExpired();
|
|
543
|
+
if (this.cache.size >= this.maxSize) {
|
|
544
|
+
this.evictLRU();
|
|
545
|
+
}
|
|
546
|
+
this.cache.set(token, {
|
|
547
|
+
token,
|
|
548
|
+
addedAt: Date.now(),
|
|
549
|
+
sequence: this.sequenceCounter++
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* Get recent tokens (non-expired, sorted by age, limited)
|
|
554
|
+
* Returns tokens in chronological order (oldest first, most recent last)
|
|
555
|
+
*/
|
|
556
|
+
getRecentTokens(maxCount = 1e3) {
|
|
557
|
+
if (maxCount <= 0) {
|
|
558
|
+
return [];
|
|
559
|
+
}
|
|
560
|
+
this.evictExpired();
|
|
561
|
+
const now = Date.now();
|
|
562
|
+
const expiredTokens = [];
|
|
563
|
+
const entries = Array.from(this.cache.values()).filter((entry) => {
|
|
564
|
+
try {
|
|
565
|
+
const [body] = entry.token.split(".");
|
|
566
|
+
if (!body) {
|
|
567
|
+
expiredTokens.push(entry.token);
|
|
568
|
+
return false;
|
|
569
|
+
}
|
|
570
|
+
const payload = JSON.parse(Buffer.from(body, "base64url").toString());
|
|
571
|
+
if (!payload.expiresAt || payload.expiresAt <= now) {
|
|
572
|
+
expiredTokens.push(entry.token);
|
|
573
|
+
return false;
|
|
574
|
+
}
|
|
575
|
+
return true;
|
|
576
|
+
} catch {
|
|
577
|
+
expiredTokens.push(entry.token);
|
|
578
|
+
return false;
|
|
579
|
+
}
|
|
580
|
+
}).sort((a, b) => a.sequence - b.sequence).slice(-maxCount);
|
|
581
|
+
for (const token of expiredTokens) {
|
|
582
|
+
this.cache.delete(token);
|
|
583
|
+
}
|
|
584
|
+
return entries.map((e) => e.token);
|
|
585
|
+
}
|
|
586
|
+
/**
|
|
587
|
+
* Clear all tokens
|
|
588
|
+
*/
|
|
589
|
+
clear() {
|
|
590
|
+
this.cache.clear();
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* Get registry size
|
|
594
|
+
*/
|
|
595
|
+
size() {
|
|
596
|
+
return this.cache.size;
|
|
597
|
+
}
|
|
598
|
+
/**
|
|
599
|
+
* Evict expired tokens
|
|
600
|
+
*/
|
|
601
|
+
evictExpired() {
|
|
602
|
+
const now = Date.now();
|
|
603
|
+
const toDelete = [];
|
|
604
|
+
for (const [token, entry] of this.cache.entries()) {
|
|
605
|
+
if (now - entry.addedAt > this.ttl) {
|
|
606
|
+
toDelete.push(token);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
for (const token of toDelete) {
|
|
610
|
+
this.cache.delete(token);
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
/**
|
|
614
|
+
* Evict least recently used (oldest) token
|
|
615
|
+
*/
|
|
616
|
+
evictLRU() {
|
|
617
|
+
let oldestToken = null;
|
|
618
|
+
let oldestSequence = Infinity;
|
|
619
|
+
for (const [token, entry] of this.cache.entries()) {
|
|
620
|
+
if (entry.sequence < oldestSequence) {
|
|
621
|
+
oldestSequence = entry.sequence;
|
|
622
|
+
oldestToken = token;
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
if (oldestToken) {
|
|
626
|
+
this.cache.delete(oldestToken);
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
};
|
|
630
|
+
|
|
631
|
+
// src/core/execution-operations.ts
|
|
632
|
+
var ExecutionOperations = class {
|
|
633
|
+
static {
|
|
634
|
+
__name(this, "ExecutionOperations");
|
|
635
|
+
}
|
|
636
|
+
session;
|
|
637
|
+
inProcessSession;
|
|
638
|
+
serviceProviders;
|
|
639
|
+
tokenRegistry;
|
|
640
|
+
lastExecutionConfig = null;
|
|
641
|
+
constructor(session, serviceProviders, inProcessSession) {
|
|
642
|
+
this.session = session;
|
|
643
|
+
this.inProcessSession = inProcessSession;
|
|
644
|
+
this.serviceProviders = serviceProviders;
|
|
645
|
+
this.tokenRegistry = new ProvenanceTokenRegistry();
|
|
646
|
+
}
|
|
647
|
+
/**
|
|
648
|
+
* Executes code on the server with real-time progress updates via SSE.
|
|
649
|
+
*/
|
|
650
|
+
async executeStream(code, config, onProgress) {
|
|
651
|
+
await this.session.ensureInitialized();
|
|
652
|
+
const url = `${this.session.getBaseUrl()}/api/execute/stream`;
|
|
653
|
+
const body = JSON.stringify({
|
|
654
|
+
code,
|
|
655
|
+
config
|
|
656
|
+
});
|
|
657
|
+
const headers = await this.session.prepareHeaders("POST", url, body);
|
|
658
|
+
return new Promise((resolve, reject) => {
|
|
659
|
+
const fetchImpl = typeof fetch !== "undefined" ? fetch : __require("undici").fetch;
|
|
660
|
+
fetchImpl(url, {
|
|
661
|
+
method: "POST",
|
|
662
|
+
headers,
|
|
663
|
+
body
|
|
664
|
+
}).then(async (response) => {
|
|
665
|
+
if (!response.ok) {
|
|
666
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
667
|
+
}
|
|
668
|
+
const reader = response.body?.getReader();
|
|
669
|
+
if (!reader) {
|
|
670
|
+
throw new Error("Response body is not readable");
|
|
671
|
+
}
|
|
672
|
+
const decoder = new TextDecoder();
|
|
673
|
+
let buffer = "";
|
|
674
|
+
let result = null;
|
|
675
|
+
while (true) {
|
|
676
|
+
const { done, value } = await reader.read();
|
|
677
|
+
if (done) break;
|
|
678
|
+
buffer += decoder.decode(value, {
|
|
679
|
+
stream: true
|
|
680
|
+
});
|
|
681
|
+
const lines = buffer.split("\n");
|
|
682
|
+
buffer = lines.pop() || "";
|
|
683
|
+
for (let i = 0; i < lines.length; i++) {
|
|
684
|
+
const line = lines[i];
|
|
685
|
+
if (line && line.startsWith("event:")) {
|
|
686
|
+
const event = line.substring(6).trim();
|
|
687
|
+
for (let j = i + 1; j < lines.length; j++) {
|
|
688
|
+
const dataLine = lines[j];
|
|
689
|
+
if (dataLine && dataLine.startsWith("data:")) {
|
|
690
|
+
const dataStr = dataLine.substring(5).trim();
|
|
691
|
+
if (dataStr) {
|
|
692
|
+
try {
|
|
693
|
+
const data = JSON.parse(dataStr);
|
|
694
|
+
if (event === "progress" && onProgress) {
|
|
695
|
+
onProgress(data.message, data.fraction);
|
|
696
|
+
} else if (event === "result") {
|
|
697
|
+
result = data;
|
|
698
|
+
} else if (event === "error") {
|
|
699
|
+
reject(new Error(data.message));
|
|
700
|
+
return;
|
|
701
|
+
}
|
|
702
|
+
} catch (e) {
|
|
703
|
+
log.error("Failed to parse SSE data", {
|
|
704
|
+
dataStr,
|
|
705
|
+
error: e
|
|
706
|
+
});
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
break;
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
if (result) {
|
|
716
|
+
resolve(result);
|
|
717
|
+
} else {
|
|
718
|
+
reject(new Error("No result received from server"));
|
|
719
|
+
}
|
|
720
|
+
}).catch(reject);
|
|
721
|
+
});
|
|
722
|
+
}
|
|
723
|
+
/**
|
|
724
|
+
* Executes code on the server in a sandboxed environment.
|
|
725
|
+
*/
|
|
726
|
+
async execute(code, config) {
|
|
727
|
+
await this.session.ensureInitialized();
|
|
728
|
+
const hints = this.tokenRegistry.getRecentTokens(1e3);
|
|
729
|
+
const detectedClientServices = {
|
|
730
|
+
hasLLM: !!this.serviceProviders.getLLM(),
|
|
731
|
+
hasApproval: !!this.serviceProviders.getApproval(),
|
|
732
|
+
hasEmbedding: !!this.serviceProviders.getEmbedding(),
|
|
733
|
+
hasTools: this.serviceProviders.hasTools()
|
|
734
|
+
};
|
|
735
|
+
const executionConfig = {
|
|
736
|
+
...config,
|
|
737
|
+
clientServices: {
|
|
738
|
+
...detectedClientServices,
|
|
739
|
+
...config?.clientServices || {}
|
|
740
|
+
},
|
|
741
|
+
provenanceHints: hints.length > 0 ? hints : void 0
|
|
742
|
+
};
|
|
743
|
+
this.lastExecutionConfig = executionConfig;
|
|
744
|
+
let result;
|
|
745
|
+
if (this.inProcessSession) {
|
|
746
|
+
result = await this.inProcessSession.execute(code, executionConfig);
|
|
747
|
+
} else {
|
|
748
|
+
const url = `${this.session.getBaseUrl()}/api/execute`;
|
|
749
|
+
const body = JSON.stringify({
|
|
750
|
+
code,
|
|
751
|
+
config: executionConfig
|
|
752
|
+
});
|
|
753
|
+
const headers = await this.session.prepareHeaders("POST", url, body);
|
|
754
|
+
const response = await fetch(url, {
|
|
755
|
+
method: "POST",
|
|
756
|
+
headers,
|
|
757
|
+
body
|
|
758
|
+
});
|
|
759
|
+
this.session.updateToken(response);
|
|
760
|
+
if (!response.ok) {
|
|
761
|
+
const error = await response.json();
|
|
762
|
+
throw new Error(`Execution failed: ${error.error || response.statusText}`);
|
|
763
|
+
}
|
|
764
|
+
result = await response.json();
|
|
765
|
+
}
|
|
766
|
+
if (result.provenanceTokens && result.provenanceTokens.length > 0) {
|
|
767
|
+
for (const { token } of result.provenanceTokens) {
|
|
768
|
+
this.tokenRegistry.add(token);
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
if (result.status === ExecutionStatus.PAUSED && result.needsCallbacks) {
|
|
772
|
+
return await this.handleBatchCallbacksAndResume(result);
|
|
773
|
+
}
|
|
774
|
+
if (result.status === ExecutionStatus.PAUSED && result.needsCallback) {
|
|
775
|
+
return await this.handlePauseAndResume(result);
|
|
776
|
+
}
|
|
777
|
+
return result;
|
|
778
|
+
}
|
|
779
|
+
/**
|
|
780
|
+
* Handles batch callbacks by executing them in parallel and resuming.
|
|
781
|
+
*/
|
|
782
|
+
async handleBatchCallbacksAndResume(pausedResult) {
|
|
783
|
+
if (!pausedResult.needsCallbacks || pausedResult.needsCallbacks.length === 0) {
|
|
784
|
+
throw new Error("No batch callback requests in paused execution");
|
|
785
|
+
}
|
|
786
|
+
const missingServiceIds = new Set(pausedResult.needsCallbacks.filter((cb) => !this.serviceProviders.hasServiceForCallback(cb.type)).map((cb) => cb.id));
|
|
787
|
+
if (missingServiceIds.size > 0) {
|
|
788
|
+
const missingServices = pausedResult.needsCallbacks.filter((cb) => missingServiceIds.has(cb.id));
|
|
789
|
+
const explicitlyRequestedMissing = missingServices.filter((cb) => this.wasServiceExplicitlyRequested(cb.type));
|
|
790
|
+
const unexpectedMissing = missingServices.filter((cb) => !this.wasServiceExplicitlyRequested(cb.type));
|
|
791
|
+
if (explicitlyRequestedMissing.length > 0) {
|
|
792
|
+
return pausedResult;
|
|
793
|
+
}
|
|
794
|
+
const errorMessage = `Missing service providers for callback types: ${unexpectedMissing.map((cb) => cb.type).join(", ")}`;
|
|
795
|
+
log.error(`Auto-handling batch paused execution without service providers: ${errorMessage}`, {
|
|
796
|
+
executionId: pausedResult.executionId,
|
|
797
|
+
missingServices: unexpectedMissing.map((cb) => ({
|
|
798
|
+
type: cb.type,
|
|
799
|
+
operation: cb.operation,
|
|
800
|
+
id: cb.id
|
|
801
|
+
}))
|
|
802
|
+
});
|
|
803
|
+
const existingCallbacks = pausedResult.needsCallbacks.filter((cb) => !missingServiceIds.has(cb.id));
|
|
804
|
+
if (existingCallbacks.length > 0) {
|
|
805
|
+
try {
|
|
806
|
+
const existingResults = await Promise.all(existingCallbacks.map(async (cb) => {
|
|
807
|
+
const callbackResult = await this.serviceProviders.handleCallback(cb.type, {
|
|
808
|
+
...cb.payload,
|
|
809
|
+
operation: cb.operation
|
|
810
|
+
});
|
|
811
|
+
return {
|
|
812
|
+
id: cb.id,
|
|
813
|
+
result: callbackResult
|
|
814
|
+
};
|
|
815
|
+
}));
|
|
816
|
+
const allResults = pausedResult.needsCallbacks.map((cb) => {
|
|
817
|
+
if (missingServiceIds.has(cb.id)) {
|
|
818
|
+
return {
|
|
819
|
+
id: cb.id,
|
|
820
|
+
result: {
|
|
821
|
+
__error: true,
|
|
822
|
+
message: `${cb.type} service not provided by client`
|
|
823
|
+
}
|
|
824
|
+
};
|
|
825
|
+
}
|
|
826
|
+
return existingResults.find((r) => r.id === cb.id);
|
|
827
|
+
});
|
|
828
|
+
return await this.resumeWithBatchResults(pausedResult.executionId, allResults);
|
|
829
|
+
} catch (error) {
|
|
830
|
+
const errorMessage2 = error instanceof Error ? error.message : String(error);
|
|
831
|
+
log.error(`Error handling existing services in batch: ${errorMessage2}`, {
|
|
832
|
+
executionId: pausedResult.executionId
|
|
833
|
+
});
|
|
834
|
+
const allErrorResults = pausedResult.needsCallbacks.map((cb) => ({
|
|
835
|
+
id: cb.id,
|
|
836
|
+
result: {
|
|
837
|
+
__error: true,
|
|
838
|
+
message: missingServiceIds.has(cb.id) ? `${cb.type} service not provided by client` : errorMessage2
|
|
839
|
+
}
|
|
840
|
+
}));
|
|
841
|
+
return await this.resumeWithBatchResults(pausedResult.executionId, allErrorResults);
|
|
842
|
+
}
|
|
843
|
+
} else {
|
|
844
|
+
const allErrorResults = pausedResult.needsCallbacks.map((cb) => ({
|
|
845
|
+
id: cb.id,
|
|
846
|
+
result: {
|
|
847
|
+
__error: true,
|
|
848
|
+
message: `${cb.type} service not provided by client`
|
|
849
|
+
}
|
|
850
|
+
}));
|
|
851
|
+
return await this.resumeWithBatchResults(pausedResult.executionId, allErrorResults);
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
try {
|
|
855
|
+
const batchResults = await Promise.all(pausedResult.needsCallbacks.map(async (cb) => {
|
|
856
|
+
const callbackResult = await this.serviceProviders.handleCallback(cb.type, {
|
|
857
|
+
...cb.payload,
|
|
858
|
+
operation: cb.operation
|
|
859
|
+
});
|
|
860
|
+
return {
|
|
861
|
+
id: cb.id,
|
|
862
|
+
result: callbackResult
|
|
863
|
+
};
|
|
864
|
+
}));
|
|
865
|
+
return await this.resumeWithBatchResults(pausedResult.executionId, batchResults);
|
|
866
|
+
} catch (error) {
|
|
867
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
868
|
+
log.error(`Error handling batch callbacks: ${errorMessage}`, {
|
|
869
|
+
executionId: pausedResult.executionId,
|
|
870
|
+
callbackCount: pausedResult.needsCallbacks.length
|
|
871
|
+
});
|
|
872
|
+
const allErrorResults = pausedResult.needsCallbacks.map((cb) => ({
|
|
873
|
+
id: cb.id,
|
|
874
|
+
result: {
|
|
875
|
+
__error: true,
|
|
876
|
+
message: errorMessage
|
|
877
|
+
}
|
|
878
|
+
}));
|
|
879
|
+
return await this.resumeWithBatchResults(pausedResult.executionId, allErrorResults);
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
/**
|
|
883
|
+
* Handles a paused execution by processing the callback and resuming.
|
|
884
|
+
*/
|
|
885
|
+
async handlePauseAndResume(pausedResult) {
|
|
886
|
+
if (!pausedResult.needsCallback) {
|
|
887
|
+
throw new Error("No callback request in paused execution");
|
|
888
|
+
}
|
|
889
|
+
if (!this.serviceProviders.hasServiceForCallback(pausedResult.needsCallback.type)) {
|
|
890
|
+
const wasExplicitlyRequested = this.wasServiceExplicitlyRequested(pausedResult.needsCallback.type);
|
|
891
|
+
if (wasExplicitlyRequested) {
|
|
892
|
+
return pausedResult;
|
|
893
|
+
}
|
|
894
|
+
const errorMessage = `${pausedResult.needsCallback.type} service not provided by client`;
|
|
895
|
+
log.error(`Auto-handling paused execution without service provider: ${errorMessage}`, {
|
|
896
|
+
executionId: pausedResult.executionId,
|
|
897
|
+
callbackType: pausedResult.needsCallback.type,
|
|
898
|
+
operation: pausedResult.needsCallback.operation
|
|
899
|
+
});
|
|
900
|
+
return await this.resume(pausedResult.executionId, {
|
|
901
|
+
__error: true,
|
|
902
|
+
message: errorMessage
|
|
903
|
+
});
|
|
904
|
+
}
|
|
905
|
+
try {
|
|
906
|
+
const callbackResult = await this.serviceProviders.handleCallback(pausedResult.needsCallback.type, {
|
|
907
|
+
...pausedResult.needsCallback.payload,
|
|
908
|
+
operation: pausedResult.needsCallback.operation,
|
|
909
|
+
executionId: pausedResult.executionId
|
|
910
|
+
});
|
|
911
|
+
return await this.resume(pausedResult.executionId, callbackResult);
|
|
912
|
+
} catch (error) {
|
|
913
|
+
if (error instanceof ClientCallbackError) {
|
|
914
|
+
throw error;
|
|
915
|
+
}
|
|
916
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
917
|
+
log.error(`Error handling callback: ${errorMessage}`, {
|
|
918
|
+
executionId: pausedResult.executionId,
|
|
919
|
+
callbackType: pausedResult.needsCallback.type,
|
|
920
|
+
operation: pausedResult.needsCallback.operation
|
|
921
|
+
});
|
|
922
|
+
return await this.resume(pausedResult.executionId, {
|
|
923
|
+
__error: true,
|
|
924
|
+
message: errorMessage
|
|
925
|
+
});
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
/**
|
|
929
|
+
* Check if a service was explicitly requested in clientServices config
|
|
930
|
+
*/
|
|
931
|
+
wasServiceExplicitlyRequested(callbackType) {
|
|
932
|
+
if (!this.lastExecutionConfig?.clientServices) {
|
|
933
|
+
return false;
|
|
934
|
+
}
|
|
935
|
+
switch (callbackType) {
|
|
936
|
+
case CallbackType.LLM:
|
|
937
|
+
return this.lastExecutionConfig.clientServices.hasLLM;
|
|
938
|
+
case CallbackType.APPROVAL:
|
|
939
|
+
return this.lastExecutionConfig.clientServices.hasApproval;
|
|
940
|
+
case CallbackType.EMBEDDING:
|
|
941
|
+
return this.lastExecutionConfig.clientServices.hasEmbedding;
|
|
942
|
+
case CallbackType.TOOL:
|
|
943
|
+
return this.lastExecutionConfig.clientServices.hasTools;
|
|
944
|
+
default:
|
|
945
|
+
return false;
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
/**
|
|
949
|
+
* Resumes a paused execution with a callback result.
|
|
950
|
+
*/
|
|
951
|
+
async resume(executionId, callbackResult) {
|
|
952
|
+
await this.session.ensureInitialized();
|
|
953
|
+
let result;
|
|
954
|
+
if (this.inProcessSession) {
|
|
955
|
+
result = await this.inProcessSession.resume(executionId, callbackResult);
|
|
956
|
+
} else {
|
|
957
|
+
const url = `${this.session.getBaseUrl()}/api/resume/${executionId}`;
|
|
958
|
+
const body = JSON.stringify({
|
|
959
|
+
result: callbackResult
|
|
960
|
+
});
|
|
961
|
+
const headers = await this.session.prepareHeaders("POST", url, body);
|
|
962
|
+
const response = await fetch(url, {
|
|
963
|
+
method: "POST",
|
|
964
|
+
headers,
|
|
965
|
+
body
|
|
966
|
+
});
|
|
967
|
+
this.session.updateToken(response);
|
|
968
|
+
if (!response.ok) {
|
|
969
|
+
const error = await response.json();
|
|
970
|
+
throw new Error(`Resume failed: ${error.error || response.statusText}`);
|
|
971
|
+
}
|
|
972
|
+
result = await response.json();
|
|
973
|
+
}
|
|
974
|
+
if (result.provenanceTokens && result.provenanceTokens.length > 0) {
|
|
975
|
+
for (const { token } of result.provenanceTokens) {
|
|
976
|
+
this.tokenRegistry.add(token);
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
if (result.status === ExecutionStatus.PAUSED && result.needsCallbacks) {
|
|
980
|
+
return await this.handleBatchCallbacksAndResume(result);
|
|
981
|
+
}
|
|
982
|
+
if (result.status === ExecutionStatus.PAUSED && result.needsCallback) {
|
|
983
|
+
return await this.handlePauseAndResume(result);
|
|
984
|
+
}
|
|
985
|
+
return result;
|
|
986
|
+
}
|
|
987
|
+
/**
|
|
988
|
+
* Resumes a paused execution with batch callback results.
|
|
989
|
+
*/
|
|
990
|
+
async resumeWithBatchResults(executionId, batchResults) {
|
|
991
|
+
await this.session.ensureInitialized();
|
|
992
|
+
let result;
|
|
993
|
+
if (this.inProcessSession) {
|
|
994
|
+
result = await this.inProcessSession.resumeWithBatchResults(executionId, batchResults);
|
|
995
|
+
} else {
|
|
996
|
+
const url = `${this.session.getBaseUrl()}/api/resume/${executionId}`;
|
|
997
|
+
const body = JSON.stringify({
|
|
998
|
+
results: batchResults
|
|
999
|
+
});
|
|
1000
|
+
const headers = await this.session.prepareHeaders("POST", url, body);
|
|
1001
|
+
const response = await fetch(url, {
|
|
1002
|
+
method: "POST",
|
|
1003
|
+
headers,
|
|
1004
|
+
body
|
|
1005
|
+
});
|
|
1006
|
+
this.session.updateToken(response);
|
|
1007
|
+
if (!response.ok) {
|
|
1008
|
+
const error = await response.json();
|
|
1009
|
+
throw new Error(`Batch resume failed: ${error.error || response.statusText}`);
|
|
1010
|
+
}
|
|
1011
|
+
result = await response.json();
|
|
1012
|
+
}
|
|
1013
|
+
if (result.provenanceTokens && result.provenanceTokens.length > 0) {
|
|
1014
|
+
for (const { token } of result.provenanceTokens) {
|
|
1015
|
+
this.tokenRegistry.add(token);
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
if (result.status === ExecutionStatus.PAUSED && result.needsCallbacks) {
|
|
1019
|
+
return await this.handleBatchCallbacksAndResume(result);
|
|
1020
|
+
}
|
|
1021
|
+
if (result.status === ExecutionStatus.PAUSED && result.needsCallback) {
|
|
1022
|
+
return await this.handlePauseAndResume(result);
|
|
1023
|
+
}
|
|
1024
|
+
return result;
|
|
1025
|
+
}
|
|
1026
|
+
};
|
|
1027
|
+
var LLMOperation = {
|
|
1028
|
+
CALL: "call",
|
|
1029
|
+
EXTRACT: "extract",
|
|
1030
|
+
CLASSIFY: "classify"
|
|
1031
|
+
};
|
|
1032
|
+
var EmbeddingOperation = {
|
|
1033
|
+
EMBED: "embed",
|
|
1034
|
+
SEARCH: "search"
|
|
1035
|
+
};
|
|
1036
|
+
var ServiceProviders = class {
|
|
1037
|
+
static {
|
|
1038
|
+
__name(this, "ServiceProviders");
|
|
1039
|
+
}
|
|
1040
|
+
providers = {};
|
|
1041
|
+
toolHandlers = /* @__PURE__ */ new Map();
|
|
1042
|
+
constructor(providers) {
|
|
1043
|
+
this.providers = providers || {};
|
|
1044
|
+
if (providers?.tools) {
|
|
1045
|
+
for (const tool of providers.tools) {
|
|
1046
|
+
this.toolHandlers.set(tool.name, tool.handler);
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
provideLLM(handler) {
|
|
1051
|
+
this.providers.llm = handler;
|
|
1052
|
+
}
|
|
1053
|
+
provideApproval(handler) {
|
|
1054
|
+
this.providers.approval = handler;
|
|
1055
|
+
}
|
|
1056
|
+
provideEmbedding(handler) {
|
|
1057
|
+
this.providers.embedding = handler;
|
|
1058
|
+
}
|
|
1059
|
+
provideTools(tools) {
|
|
1060
|
+
this.providers.tools = tools;
|
|
1061
|
+
for (const tool of tools) {
|
|
1062
|
+
this.toolHandlers.set(tool.name, tool.handler);
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
getLLM() {
|
|
1066
|
+
return this.providers.llm;
|
|
1067
|
+
}
|
|
1068
|
+
getApproval() {
|
|
1069
|
+
return this.providers.approval;
|
|
1070
|
+
}
|
|
1071
|
+
getEmbedding() {
|
|
1072
|
+
return this.providers.embedding;
|
|
1073
|
+
}
|
|
1074
|
+
getTools() {
|
|
1075
|
+
return this.providers.tools;
|
|
1076
|
+
}
|
|
1077
|
+
/**
|
|
1078
|
+
* Get tool definitions (without handlers) for sending to server
|
|
1079
|
+
*/
|
|
1080
|
+
getToolDefinitions() {
|
|
1081
|
+
if (!this.providers.tools) {
|
|
1082
|
+
return [];
|
|
1083
|
+
}
|
|
1084
|
+
return this.providers.tools.map((tool) => {
|
|
1085
|
+
const { handler, ...definition } = tool;
|
|
1086
|
+
return definition;
|
|
1087
|
+
});
|
|
1088
|
+
}
|
|
1089
|
+
/**
|
|
1090
|
+
* Check if client has tools
|
|
1091
|
+
*/
|
|
1092
|
+
hasTools() {
|
|
1093
|
+
return !!(this.providers.tools && this.providers.tools.length > 0);
|
|
1094
|
+
}
|
|
1095
|
+
/**
|
|
1096
|
+
* Check if client has any services or tools
|
|
1097
|
+
*/
|
|
1098
|
+
hasAnyServices() {
|
|
1099
|
+
return !!(this.providers.llm || this.providers.approval || this.providers.embedding || this.hasTools());
|
|
1100
|
+
}
|
|
1101
|
+
/**
|
|
1102
|
+
* Check if client has a service for a specific callback type
|
|
1103
|
+
*/
|
|
1104
|
+
hasServiceForCallback(callbackType) {
|
|
1105
|
+
switch (callbackType) {
|
|
1106
|
+
case CallbackType.LLM:
|
|
1107
|
+
return !!this.providers.llm;
|
|
1108
|
+
case CallbackType.APPROVAL:
|
|
1109
|
+
return !!this.providers.approval;
|
|
1110
|
+
case CallbackType.EMBEDDING:
|
|
1111
|
+
return !!this.providers.embedding;
|
|
1112
|
+
case CallbackType.TOOL:
|
|
1113
|
+
return this.hasTools();
|
|
1114
|
+
default:
|
|
1115
|
+
return false;
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
async handleCallback(callbackType, payload) {
|
|
1119
|
+
if (payload.operation === "batch_parallel" && payload.calls) {
|
|
1120
|
+
return await Promise.all(payload.calls.map(async (call) => {
|
|
1121
|
+
return await this.handleCallback(call.type, {
|
|
1122
|
+
...call.payload,
|
|
1123
|
+
operation: call.operation
|
|
1124
|
+
});
|
|
1125
|
+
}));
|
|
1126
|
+
}
|
|
1127
|
+
switch (callbackType) {
|
|
1128
|
+
case CallbackType.LLM:
|
|
1129
|
+
if (!this.providers.llm) {
|
|
1130
|
+
throw new Error("LLM service not provided by client");
|
|
1131
|
+
}
|
|
1132
|
+
if (payload.operation === LLMOperation.CALL) {
|
|
1133
|
+
return await this.providers.llm.call(payload.prompt, payload.options);
|
|
1134
|
+
} else if (payload.operation === LLMOperation.EXTRACT && this.providers.llm.extract) {
|
|
1135
|
+
return await this.providers.llm.extract(payload.prompt, payload.schema, payload.options);
|
|
1136
|
+
} else if (payload.operation === LLMOperation.CLASSIFY && this.providers.llm.classify) {
|
|
1137
|
+
return await this.providers.llm.classify(payload.text, payload.categories, payload.options);
|
|
1138
|
+
}
|
|
1139
|
+
throw new Error(`Unsupported LLM operation: ${payload.operation}`);
|
|
1140
|
+
case CallbackType.APPROVAL:
|
|
1141
|
+
if (!this.providers.approval) {
|
|
1142
|
+
throw new Error("Approval service not provided by client");
|
|
1143
|
+
}
|
|
1144
|
+
const contextWithExecutionId = payload.context ? {
|
|
1145
|
+
...payload.context,
|
|
1146
|
+
executionId: payload.executionId
|
|
1147
|
+
} : {
|
|
1148
|
+
executionId: payload.executionId
|
|
1149
|
+
};
|
|
1150
|
+
return await this.providers.approval.request(payload.message, contextWithExecutionId);
|
|
1151
|
+
case CallbackType.EMBEDDING:
|
|
1152
|
+
if (!this.providers.embedding) {
|
|
1153
|
+
throw new Error("Embedding service not provided by client");
|
|
1154
|
+
}
|
|
1155
|
+
if (payload.operation === EmbeddingOperation.EMBED) {
|
|
1156
|
+
return await this.providers.embedding.embed(payload.text);
|
|
1157
|
+
} else if (payload.operation === EmbeddingOperation.SEARCH) {
|
|
1158
|
+
const queryEmbedding = await this.providers.embedding.embed(payload.query);
|
|
1159
|
+
return queryEmbedding;
|
|
1160
|
+
} else if (payload.operation === "similarity" && this.providers.embedding.similarity) {
|
|
1161
|
+
return await this.providers.embedding.similarity(payload.text1, payload.text2);
|
|
1162
|
+
}
|
|
1163
|
+
throw new Error(`Unsupported embedding operation: ${payload.operation}`);
|
|
1164
|
+
case CallbackType.TOOL:
|
|
1165
|
+
if (payload.operation === ToolOperation.CALL) {
|
|
1166
|
+
const toolName = payload.toolName;
|
|
1167
|
+
const handler = this.toolHandlers.get(toolName);
|
|
1168
|
+
if (!handler) {
|
|
1169
|
+
throw new Error(`Tool '${toolName}' not found in client tools`);
|
|
1170
|
+
}
|
|
1171
|
+
const result = await handler(payload.input);
|
|
1172
|
+
return result;
|
|
1173
|
+
}
|
|
1174
|
+
throw new Error(`Unsupported tool operation: ${payload.operation}`);
|
|
1175
|
+
default:
|
|
1176
|
+
throw new Error(`Unknown callback type: ${callbackType}`);
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
};
|
|
1180
|
+
|
|
1181
|
+
export { APIOperations, ClientSession, ExecutionOperations, InProcessSession, ServiceProviders };
|
|
1182
|
+
//# sourceMappingURL=index.js.map
|
|
7
1183
|
//# sourceMappingURL=index.js.map
|