@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/index.js
CHANGED
|
@@ -1,8 +1,1579 @@
|
|
|
1
|
-
|
|
2
|
-
export * from './generator.js';
|
|
3
|
-
export * from './tools.js';
|
|
4
|
-
export * from './core/types.js';
|
|
5
|
-
export * from './errors.js';
|
|
1
|
+
import { ExecutionStatus, CallbackType, ToolOperation } from '@mondaydotcomorg/atp-protocol';
|
|
6
2
|
export { ExecutionStatus } from '@mondaydotcomorg/atp-protocol';
|
|
7
|
-
|
|
3
|
+
import { log } from '@mondaydotcomorg/atp-runtime';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { zodToJsonSchema } from 'zod-to-json-schema';
|
|
6
|
+
|
|
7
|
+
var __defProp = Object.defineProperty;
|
|
8
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
9
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
10
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
11
|
+
}) : x)(function(x) {
|
|
12
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
13
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
// src/core/session.ts
|
|
17
|
+
var ClientSession = class {
|
|
18
|
+
static {
|
|
19
|
+
__name(this, "ClientSession");
|
|
20
|
+
}
|
|
21
|
+
baseUrl;
|
|
22
|
+
customHeaders;
|
|
23
|
+
clientId;
|
|
24
|
+
clientToken;
|
|
25
|
+
initPromise;
|
|
26
|
+
hooks;
|
|
27
|
+
constructor(baseUrl, headers, hooks) {
|
|
28
|
+
this.baseUrl = baseUrl;
|
|
29
|
+
this.customHeaders = headers || {};
|
|
30
|
+
this.hooks = hooks;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Initializes the client session with the server.
|
|
34
|
+
* This MUST be called before any other operations.
|
|
35
|
+
* The server generates and returns a unique client ID and token.
|
|
36
|
+
* @param clientInfo - Optional client information
|
|
37
|
+
* @param tools - Optional client tool definitions to register with the server
|
|
38
|
+
* @param services - Optional client service capabilities (LLM, approval, embedding)
|
|
39
|
+
*/
|
|
40
|
+
async init(clientInfo, tools, services) {
|
|
41
|
+
if (this.initPromise) {
|
|
42
|
+
await this.initPromise;
|
|
43
|
+
return {
|
|
44
|
+
clientId: this.clientId,
|
|
45
|
+
token: this.clientToken,
|
|
46
|
+
expiresAt: 0,
|
|
47
|
+
tokenRotateAt: 0
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
this.initPromise = (async () => {
|
|
51
|
+
const url = `${this.baseUrl}/api/init`;
|
|
52
|
+
const body = JSON.stringify({
|
|
53
|
+
clientInfo,
|
|
54
|
+
tools: tools || [],
|
|
55
|
+
services
|
|
56
|
+
});
|
|
57
|
+
const headers = await this.prepareHeaders("POST", url, body);
|
|
58
|
+
const response = await fetch(url, {
|
|
59
|
+
method: "POST",
|
|
60
|
+
headers,
|
|
61
|
+
body
|
|
62
|
+
});
|
|
63
|
+
if (!response.ok) {
|
|
64
|
+
throw new Error(`Client initialization failed: ${response.status} ${response.statusText}`);
|
|
65
|
+
}
|
|
66
|
+
const data = await response.json();
|
|
67
|
+
this.clientId = data.clientId;
|
|
68
|
+
this.clientToken = data.token;
|
|
69
|
+
})();
|
|
70
|
+
await this.initPromise;
|
|
71
|
+
return {
|
|
72
|
+
clientId: this.clientId,
|
|
73
|
+
token: this.clientToken,
|
|
74
|
+
expiresAt: 0,
|
|
75
|
+
tokenRotateAt: 0
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Gets the unique client ID.
|
|
80
|
+
*/
|
|
81
|
+
getClientId() {
|
|
82
|
+
if (!this.clientId) {
|
|
83
|
+
throw new Error("Client not initialized. Call init() first.");
|
|
84
|
+
}
|
|
85
|
+
return this.clientId;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Ensures the client is initialized before making requests.
|
|
89
|
+
*/
|
|
90
|
+
async ensureInitialized() {
|
|
91
|
+
if (!this.clientId) {
|
|
92
|
+
throw new Error("Client not initialized. Call init() first.");
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Creates HTTP headers for requests.
|
|
97
|
+
*/
|
|
98
|
+
getHeaders() {
|
|
99
|
+
const headers = {
|
|
100
|
+
"Content-Type": "application/json",
|
|
101
|
+
...this.customHeaders
|
|
102
|
+
};
|
|
103
|
+
if (this.clientId) {
|
|
104
|
+
headers["X-Client-ID"] = this.clientId;
|
|
105
|
+
}
|
|
106
|
+
if (this.clientToken) {
|
|
107
|
+
headers["Authorization"] = `Bearer ${this.clientToken}`;
|
|
108
|
+
}
|
|
109
|
+
return headers;
|
|
110
|
+
}
|
|
111
|
+
getBaseUrl() {
|
|
112
|
+
return this.baseUrl;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Updates the client token from response headers (token refresh).
|
|
116
|
+
*/
|
|
117
|
+
updateToken(response) {
|
|
118
|
+
const newToken = response.headers.get("X-ATP-Token");
|
|
119
|
+
if (newToken) {
|
|
120
|
+
this.clientToken = newToken;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Prepares headers for a request, calling preRequest hook if configured
|
|
125
|
+
*/
|
|
126
|
+
async prepareHeaders(method, url, body) {
|
|
127
|
+
let headers = {
|
|
128
|
+
"Content-Type": "application/json",
|
|
129
|
+
...this.customHeaders
|
|
130
|
+
};
|
|
131
|
+
if (this.clientId) {
|
|
132
|
+
headers["X-Client-ID"] = this.clientId;
|
|
133
|
+
}
|
|
134
|
+
if (this.clientToken) {
|
|
135
|
+
headers["Authorization"] = `Bearer ${this.clientToken}`;
|
|
136
|
+
}
|
|
137
|
+
if (this.hooks?.preRequest) {
|
|
138
|
+
try {
|
|
139
|
+
const result = await this.hooks.preRequest({
|
|
140
|
+
url,
|
|
141
|
+
method,
|
|
142
|
+
currentHeaders: headers,
|
|
143
|
+
body
|
|
144
|
+
});
|
|
145
|
+
if (result.abort) {
|
|
146
|
+
throw new Error(result.abortReason || "Request aborted by preRequest hook");
|
|
147
|
+
}
|
|
148
|
+
if (result.headers) {
|
|
149
|
+
headers = result.headers;
|
|
150
|
+
}
|
|
151
|
+
} catch (error) {
|
|
152
|
+
throw error;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return headers;
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
// src/core/in-process-session.ts
|
|
160
|
+
var InProcessSession = class {
|
|
161
|
+
static {
|
|
162
|
+
__name(this, "InProcessSession");
|
|
163
|
+
}
|
|
164
|
+
server;
|
|
165
|
+
clientId;
|
|
166
|
+
clientToken;
|
|
167
|
+
initialized = false;
|
|
168
|
+
initPromise;
|
|
169
|
+
constructor(server) {
|
|
170
|
+
this.server = server;
|
|
171
|
+
}
|
|
172
|
+
async init(clientInfo, tools, services) {
|
|
173
|
+
if (this.initPromise) {
|
|
174
|
+
await this.initPromise;
|
|
175
|
+
return {
|
|
176
|
+
clientId: this.clientId,
|
|
177
|
+
token: this.clientToken,
|
|
178
|
+
expiresAt: 0,
|
|
179
|
+
tokenRotateAt: 0
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
this.initPromise = (async () => {
|
|
183
|
+
await this.server.start();
|
|
184
|
+
const ctx = this.createContext({
|
|
185
|
+
method: "POST",
|
|
186
|
+
path: "/api/init",
|
|
187
|
+
body: {
|
|
188
|
+
clientInfo,
|
|
189
|
+
tools: tools || [],
|
|
190
|
+
services
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
const result = await this.server.handleInit(ctx);
|
|
194
|
+
this.clientId = result.clientId;
|
|
195
|
+
this.clientToken = result.token;
|
|
196
|
+
this.initialized = true;
|
|
197
|
+
})();
|
|
198
|
+
await this.initPromise;
|
|
199
|
+
return {
|
|
200
|
+
clientId: this.clientId,
|
|
201
|
+
token: this.clientToken,
|
|
202
|
+
expiresAt: 0,
|
|
203
|
+
tokenRotateAt: 0
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
getClientId() {
|
|
207
|
+
if (!this.clientId) {
|
|
208
|
+
throw new Error("Client not initialized. Call init() first.");
|
|
209
|
+
}
|
|
210
|
+
return this.clientId;
|
|
211
|
+
}
|
|
212
|
+
async ensureInitialized() {
|
|
213
|
+
if (!this.initialized) {
|
|
214
|
+
throw new Error("Client not initialized. Call init() first.");
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
getHeaders() {
|
|
218
|
+
const headers = {
|
|
219
|
+
"content-type": "application/json"
|
|
220
|
+
};
|
|
221
|
+
if (this.clientId) {
|
|
222
|
+
headers["x-client-id"] = this.clientId;
|
|
223
|
+
}
|
|
224
|
+
if (this.clientToken) {
|
|
225
|
+
headers["authorization"] = `Bearer ${this.clientToken}`;
|
|
226
|
+
}
|
|
227
|
+
return headers;
|
|
228
|
+
}
|
|
229
|
+
getBaseUrl() {
|
|
230
|
+
return "";
|
|
231
|
+
}
|
|
232
|
+
updateToken(_response) {
|
|
233
|
+
}
|
|
234
|
+
async prepareHeaders(_method, _url, _body) {
|
|
235
|
+
return this.getHeaders();
|
|
236
|
+
}
|
|
237
|
+
async getDefinitions(options) {
|
|
238
|
+
await this.ensureInitialized();
|
|
239
|
+
const ctx = this.createContext({
|
|
240
|
+
method: "GET",
|
|
241
|
+
path: "/api/definitions",
|
|
242
|
+
query: options?.apiGroups ? {
|
|
243
|
+
apiGroups: options.apiGroups.join(",")
|
|
244
|
+
} : {}
|
|
245
|
+
});
|
|
246
|
+
return await this.server.getDefinitions(ctx);
|
|
247
|
+
}
|
|
248
|
+
async getRuntimeDefinitions(options) {
|
|
249
|
+
await this.ensureInitialized();
|
|
250
|
+
const ctx = this.createContext({
|
|
251
|
+
method: "GET",
|
|
252
|
+
path: "/api/runtime",
|
|
253
|
+
query: options?.apis?.length ? {
|
|
254
|
+
apis: options.apis.join(",")
|
|
255
|
+
} : {}
|
|
256
|
+
});
|
|
257
|
+
return await this.server.getRuntimeDefinitions(ctx);
|
|
258
|
+
}
|
|
259
|
+
async getServerInfo() {
|
|
260
|
+
await this.ensureInitialized();
|
|
261
|
+
return this.server.getInfo();
|
|
262
|
+
}
|
|
263
|
+
async search(query, options) {
|
|
264
|
+
await this.ensureInitialized();
|
|
265
|
+
const ctx = this.createContext({
|
|
266
|
+
method: "POST",
|
|
267
|
+
path: "/api/search",
|
|
268
|
+
body: {
|
|
269
|
+
query,
|
|
270
|
+
...options
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
return await this.server.handleSearch(ctx);
|
|
274
|
+
}
|
|
275
|
+
async explore(path) {
|
|
276
|
+
await this.ensureInitialized();
|
|
277
|
+
const ctx = this.createContext({
|
|
278
|
+
method: "POST",
|
|
279
|
+
path: "/api/explore",
|
|
280
|
+
body: {
|
|
281
|
+
path
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
return await this.server.handleExplore(ctx);
|
|
285
|
+
}
|
|
286
|
+
async execute(code, config) {
|
|
287
|
+
await this.ensureInitialized();
|
|
288
|
+
const ctx = this.createContext({
|
|
289
|
+
method: "POST",
|
|
290
|
+
path: "/api/execute",
|
|
291
|
+
body: {
|
|
292
|
+
code,
|
|
293
|
+
config
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
return await this.server.handleExecute(ctx);
|
|
297
|
+
}
|
|
298
|
+
async resume(executionId, callbackResult) {
|
|
299
|
+
await this.ensureInitialized();
|
|
300
|
+
const ctx = this.createContext({
|
|
301
|
+
method: "POST",
|
|
302
|
+
path: `/api/resume/${executionId}`,
|
|
303
|
+
body: {
|
|
304
|
+
result: callbackResult
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
return await this.server.handleResume(ctx, executionId);
|
|
308
|
+
}
|
|
309
|
+
async resumeWithBatchResults(executionId, batchResults) {
|
|
310
|
+
await this.ensureInitialized();
|
|
311
|
+
const ctx = this.createContext({
|
|
312
|
+
method: "POST",
|
|
313
|
+
path: `/api/resume/${executionId}`,
|
|
314
|
+
body: {
|
|
315
|
+
results: batchResults
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
return await this.server.handleResume(ctx, executionId);
|
|
319
|
+
}
|
|
320
|
+
createContext(options) {
|
|
321
|
+
const noopLogger = {
|
|
322
|
+
debug: /* @__PURE__ */ __name(() => {
|
|
323
|
+
}, "debug"),
|
|
324
|
+
info: /* @__PURE__ */ __name(() => {
|
|
325
|
+
}, "info"),
|
|
326
|
+
warn: /* @__PURE__ */ __name(() => {
|
|
327
|
+
}, "warn"),
|
|
328
|
+
error: /* @__PURE__ */ __name(() => {
|
|
329
|
+
}, "error")
|
|
330
|
+
};
|
|
331
|
+
return {
|
|
332
|
+
method: options.method,
|
|
333
|
+
path: options.path,
|
|
334
|
+
query: options.query || {},
|
|
335
|
+
headers: this.getHeaders(),
|
|
336
|
+
body: options.body,
|
|
337
|
+
clientId: this.clientId,
|
|
338
|
+
clientToken: this.clientToken,
|
|
339
|
+
logger: noopLogger,
|
|
340
|
+
status: 200,
|
|
341
|
+
responseBody: null,
|
|
342
|
+
throw: /* @__PURE__ */ __name((status, message) => {
|
|
343
|
+
const error = new Error(message);
|
|
344
|
+
error.status = status;
|
|
345
|
+
throw error;
|
|
346
|
+
}, "throw"),
|
|
347
|
+
assert: /* @__PURE__ */ __name((condition, message) => {
|
|
348
|
+
if (!condition) {
|
|
349
|
+
throw new Error(message);
|
|
350
|
+
}
|
|
351
|
+
}, "assert"),
|
|
352
|
+
set: /* @__PURE__ */ __name(() => {
|
|
353
|
+
}, "set")
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
// src/core/api-operations.ts
|
|
359
|
+
var APIOperations = class {
|
|
360
|
+
static {
|
|
361
|
+
__name(this, "APIOperations");
|
|
362
|
+
}
|
|
363
|
+
session;
|
|
364
|
+
inProcessSession;
|
|
365
|
+
apiDefinitions;
|
|
366
|
+
constructor(session, inProcessSession) {
|
|
367
|
+
this.session = session;
|
|
368
|
+
this.inProcessSession = inProcessSession;
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Connects to the server and retrieves API definitions.
|
|
372
|
+
*/
|
|
373
|
+
async connect(options) {
|
|
374
|
+
await this.session.ensureInitialized();
|
|
375
|
+
if (this.inProcessSession) {
|
|
376
|
+
const data2 = await this.inProcessSession.getDefinitions(options);
|
|
377
|
+
this.apiDefinitions = data2.typescript;
|
|
378
|
+
return {
|
|
379
|
+
serverVersion: data2.version,
|
|
380
|
+
capabilities: {},
|
|
381
|
+
apiGroups: data2.apiGroups
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
const params = new URLSearchParams();
|
|
385
|
+
if (options?.apiGroups) {
|
|
386
|
+
params.set("apiGroups", options.apiGroups.join(","));
|
|
387
|
+
}
|
|
388
|
+
const url = `${this.session.getBaseUrl()}/api/definitions?${params}`;
|
|
389
|
+
const headers = await this.session.prepareHeaders("GET", url);
|
|
390
|
+
const response = await fetch(url, {
|
|
391
|
+
headers
|
|
392
|
+
});
|
|
393
|
+
if (!response.ok) {
|
|
394
|
+
throw new Error(`Connection failed: ${response.status} ${response.statusText}`);
|
|
395
|
+
}
|
|
396
|
+
const data = await response.json();
|
|
397
|
+
this.apiDefinitions = data.typescript;
|
|
398
|
+
return {
|
|
399
|
+
serverVersion: data.version,
|
|
400
|
+
capabilities: {},
|
|
401
|
+
apiGroups: data.apiGroups
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Gets the TypeScript type definitions for available APIs.
|
|
406
|
+
*/
|
|
407
|
+
getTypeDefinitions() {
|
|
408
|
+
if (!this.apiDefinitions) {
|
|
409
|
+
throw new Error("Not connected. Call connect() first.");
|
|
410
|
+
}
|
|
411
|
+
return this.apiDefinitions;
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* Searches for available API functions.
|
|
415
|
+
*/
|
|
416
|
+
async searchAPI(query, options) {
|
|
417
|
+
await this.session.ensureInitialized();
|
|
418
|
+
if (this.inProcessSession) {
|
|
419
|
+
const data2 = await this.inProcessSession.search(query, options);
|
|
420
|
+
return data2.results;
|
|
421
|
+
}
|
|
422
|
+
const url = `${this.session.getBaseUrl()}/api/search`;
|
|
423
|
+
const body = JSON.stringify({
|
|
424
|
+
query,
|
|
425
|
+
...options
|
|
426
|
+
});
|
|
427
|
+
const headers = await this.session.prepareHeaders("POST", url, body);
|
|
428
|
+
const response = await fetch(url, {
|
|
429
|
+
method: "POST",
|
|
430
|
+
headers,
|
|
431
|
+
body
|
|
432
|
+
});
|
|
433
|
+
if (!response.ok) {
|
|
434
|
+
throw new Error(`Search failed: ${response.status} ${response.statusText}`);
|
|
435
|
+
}
|
|
436
|
+
const data = await response.json();
|
|
437
|
+
return data.results;
|
|
438
|
+
}
|
|
439
|
+
/**
|
|
440
|
+
* Explores the API filesystem at the given path.
|
|
441
|
+
*/
|
|
442
|
+
async exploreAPI(path) {
|
|
443
|
+
await this.session.ensureInitialized();
|
|
444
|
+
if (this.inProcessSession) {
|
|
445
|
+
return await this.inProcessSession.explore(path);
|
|
446
|
+
}
|
|
447
|
+
const url = `${this.session.getBaseUrl()}/api/explore`;
|
|
448
|
+
const body = JSON.stringify({
|
|
449
|
+
path
|
|
450
|
+
});
|
|
451
|
+
const headers = await this.session.prepareHeaders("POST", url, body);
|
|
452
|
+
const response = await fetch(url, {
|
|
453
|
+
method: "POST",
|
|
454
|
+
headers,
|
|
455
|
+
body
|
|
456
|
+
});
|
|
457
|
+
if (!response.ok) {
|
|
458
|
+
throw new Error(`Explore failed: ${response.status} ${response.statusText}`);
|
|
459
|
+
}
|
|
460
|
+
return await response.json();
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Gets information about the server.
|
|
464
|
+
*/
|
|
465
|
+
async getServerInfo() {
|
|
466
|
+
await this.session.ensureInitialized();
|
|
467
|
+
if (this.inProcessSession) {
|
|
468
|
+
return await this.inProcessSession.getServerInfo();
|
|
469
|
+
}
|
|
470
|
+
const url = `${this.session.getBaseUrl()}/api/info`;
|
|
471
|
+
const headers = await this.session.prepareHeaders("GET", url);
|
|
472
|
+
const response = await fetch(url, {
|
|
473
|
+
headers
|
|
474
|
+
});
|
|
475
|
+
if (!response.ok) {
|
|
476
|
+
throw new Error(`Failed to get server info: ${response.status}`);
|
|
477
|
+
}
|
|
478
|
+
return await response.json();
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* Gets ATP runtime API definitions as TypeScript declarations.
|
|
482
|
+
* Returns the full TypeScript definitions for atp.llm.*, atp.cache.*, etc.
|
|
483
|
+
* These are the APIs available during code execution.
|
|
484
|
+
*
|
|
485
|
+
* Behavior:
|
|
486
|
+
* - No options: Returns APIs based on client capabilities (default filtering)
|
|
487
|
+
* - apis: ['llm', 'cache']: Returns only specified APIs (intersection with client capabilities)
|
|
488
|
+
* - apis: []: Returns all APIs regardless of client capabilities
|
|
489
|
+
*
|
|
490
|
+
* @param options - Optional filtering options
|
|
491
|
+
* @param options.apis - Specific APIs to include (e.g., ['llm', 'cache', 'approval'])
|
|
492
|
+
*/
|
|
493
|
+
async getRuntimeDefinitions(options) {
|
|
494
|
+
await this.session.ensureInitialized();
|
|
495
|
+
if (this.inProcessSession) {
|
|
496
|
+
return await this.inProcessSession.getRuntimeDefinitions(options?.apis ? {
|
|
497
|
+
apis: options.apis
|
|
498
|
+
} : void 0);
|
|
499
|
+
}
|
|
500
|
+
const params = new URLSearchParams();
|
|
501
|
+
if (options?.apis && options.apis.length > 0) {
|
|
502
|
+
params.set("apis", options.apis.join(","));
|
|
503
|
+
}
|
|
504
|
+
const url = `${this.session.getBaseUrl()}/api/runtime${params.toString() ? `?${params}` : ""}`;
|
|
505
|
+
const headers = await this.session.prepareHeaders("GET", url);
|
|
506
|
+
const response = await fetch(url, {
|
|
507
|
+
headers
|
|
508
|
+
});
|
|
509
|
+
if (!response.ok) {
|
|
510
|
+
throw new Error(`Failed to get runtime definitions: ${response.status}`);
|
|
511
|
+
}
|
|
512
|
+
return await response.text();
|
|
513
|
+
}
|
|
514
|
+
};
|
|
515
|
+
|
|
516
|
+
// src/errors.ts
|
|
517
|
+
var ClientCallbackError = class extends Error {
|
|
518
|
+
static {
|
|
519
|
+
__name(this, "ClientCallbackError");
|
|
520
|
+
}
|
|
521
|
+
constructor(message) {
|
|
522
|
+
super(message);
|
|
523
|
+
this.name = "ClientCallbackError";
|
|
524
|
+
}
|
|
525
|
+
};
|
|
526
|
+
|
|
527
|
+
// src/core/provenance-registry.ts
|
|
528
|
+
var ProvenanceTokenRegistry = class {
|
|
529
|
+
static {
|
|
530
|
+
__name(this, "ProvenanceTokenRegistry");
|
|
531
|
+
}
|
|
532
|
+
cache = /* @__PURE__ */ new Map();
|
|
533
|
+
maxSize;
|
|
534
|
+
ttl;
|
|
535
|
+
sequenceCounter = 0;
|
|
536
|
+
constructor(maxSize = 1e4, ttlHours = 1) {
|
|
537
|
+
this.maxSize = maxSize;
|
|
538
|
+
this.ttl = ttlHours * 3600 * 1e3;
|
|
539
|
+
}
|
|
540
|
+
/**
|
|
541
|
+
* Add a token to the registry
|
|
542
|
+
*/
|
|
543
|
+
add(token) {
|
|
544
|
+
this.evictExpired();
|
|
545
|
+
if (this.cache.size >= this.maxSize) {
|
|
546
|
+
this.evictLRU();
|
|
547
|
+
}
|
|
548
|
+
this.cache.set(token, {
|
|
549
|
+
token,
|
|
550
|
+
addedAt: Date.now(),
|
|
551
|
+
sequence: this.sequenceCounter++
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
/**
|
|
555
|
+
* Get recent tokens (non-expired, sorted by age, limited)
|
|
556
|
+
* Returns tokens in chronological order (oldest first, most recent last)
|
|
557
|
+
*/
|
|
558
|
+
getRecentTokens(maxCount = 1e3) {
|
|
559
|
+
if (maxCount <= 0) {
|
|
560
|
+
return [];
|
|
561
|
+
}
|
|
562
|
+
this.evictExpired();
|
|
563
|
+
const now = Date.now();
|
|
564
|
+
const expiredTokens = [];
|
|
565
|
+
const entries = Array.from(this.cache.values()).filter((entry) => {
|
|
566
|
+
try {
|
|
567
|
+
const [body] = entry.token.split(".");
|
|
568
|
+
if (!body) {
|
|
569
|
+
expiredTokens.push(entry.token);
|
|
570
|
+
return false;
|
|
571
|
+
}
|
|
572
|
+
const payload = JSON.parse(Buffer.from(body, "base64url").toString());
|
|
573
|
+
if (!payload.expiresAt || payload.expiresAt <= now) {
|
|
574
|
+
expiredTokens.push(entry.token);
|
|
575
|
+
return false;
|
|
576
|
+
}
|
|
577
|
+
return true;
|
|
578
|
+
} catch {
|
|
579
|
+
expiredTokens.push(entry.token);
|
|
580
|
+
return false;
|
|
581
|
+
}
|
|
582
|
+
}).sort((a, b) => a.sequence - b.sequence).slice(-maxCount);
|
|
583
|
+
for (const token of expiredTokens) {
|
|
584
|
+
this.cache.delete(token);
|
|
585
|
+
}
|
|
586
|
+
return entries.map((e) => e.token);
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* Clear all tokens
|
|
590
|
+
*/
|
|
591
|
+
clear() {
|
|
592
|
+
this.cache.clear();
|
|
593
|
+
}
|
|
594
|
+
/**
|
|
595
|
+
* Get registry size
|
|
596
|
+
*/
|
|
597
|
+
size() {
|
|
598
|
+
return this.cache.size;
|
|
599
|
+
}
|
|
600
|
+
/**
|
|
601
|
+
* Evict expired tokens
|
|
602
|
+
*/
|
|
603
|
+
evictExpired() {
|
|
604
|
+
const now = Date.now();
|
|
605
|
+
const toDelete = [];
|
|
606
|
+
for (const [token, entry] of this.cache.entries()) {
|
|
607
|
+
if (now - entry.addedAt > this.ttl) {
|
|
608
|
+
toDelete.push(token);
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
for (const token of toDelete) {
|
|
612
|
+
this.cache.delete(token);
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
/**
|
|
616
|
+
* Evict least recently used (oldest) token
|
|
617
|
+
*/
|
|
618
|
+
evictLRU() {
|
|
619
|
+
let oldestToken = null;
|
|
620
|
+
let oldestSequence = Infinity;
|
|
621
|
+
for (const [token, entry] of this.cache.entries()) {
|
|
622
|
+
if (entry.sequence < oldestSequence) {
|
|
623
|
+
oldestSequence = entry.sequence;
|
|
624
|
+
oldestToken = token;
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
if (oldestToken) {
|
|
628
|
+
this.cache.delete(oldestToken);
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
};
|
|
632
|
+
|
|
633
|
+
// src/core/execution-operations.ts
|
|
634
|
+
var ExecutionOperations = class {
|
|
635
|
+
static {
|
|
636
|
+
__name(this, "ExecutionOperations");
|
|
637
|
+
}
|
|
638
|
+
session;
|
|
639
|
+
inProcessSession;
|
|
640
|
+
serviceProviders;
|
|
641
|
+
tokenRegistry;
|
|
642
|
+
lastExecutionConfig = null;
|
|
643
|
+
constructor(session, serviceProviders, inProcessSession) {
|
|
644
|
+
this.session = session;
|
|
645
|
+
this.inProcessSession = inProcessSession;
|
|
646
|
+
this.serviceProviders = serviceProviders;
|
|
647
|
+
this.tokenRegistry = new ProvenanceTokenRegistry();
|
|
648
|
+
}
|
|
649
|
+
/**
|
|
650
|
+
* Executes code on the server with real-time progress updates via SSE.
|
|
651
|
+
*/
|
|
652
|
+
async executeStream(code, config, onProgress) {
|
|
653
|
+
await this.session.ensureInitialized();
|
|
654
|
+
const url = `${this.session.getBaseUrl()}/api/execute/stream`;
|
|
655
|
+
const body = JSON.stringify({
|
|
656
|
+
code,
|
|
657
|
+
config
|
|
658
|
+
});
|
|
659
|
+
const headers = await this.session.prepareHeaders("POST", url, body);
|
|
660
|
+
return new Promise((resolve, reject) => {
|
|
661
|
+
const fetchImpl = typeof fetch !== "undefined" ? fetch : __require("undici").fetch;
|
|
662
|
+
fetchImpl(url, {
|
|
663
|
+
method: "POST",
|
|
664
|
+
headers,
|
|
665
|
+
body
|
|
666
|
+
}).then(async (response) => {
|
|
667
|
+
if (!response.ok) {
|
|
668
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
669
|
+
}
|
|
670
|
+
const reader = response.body?.getReader();
|
|
671
|
+
if (!reader) {
|
|
672
|
+
throw new Error("Response body is not readable");
|
|
673
|
+
}
|
|
674
|
+
const decoder = new TextDecoder();
|
|
675
|
+
let buffer = "";
|
|
676
|
+
let result = null;
|
|
677
|
+
while (true) {
|
|
678
|
+
const { done, value } = await reader.read();
|
|
679
|
+
if (done) break;
|
|
680
|
+
buffer += decoder.decode(value, {
|
|
681
|
+
stream: true
|
|
682
|
+
});
|
|
683
|
+
const lines = buffer.split("\n");
|
|
684
|
+
buffer = lines.pop() || "";
|
|
685
|
+
for (let i = 0; i < lines.length; i++) {
|
|
686
|
+
const line = lines[i];
|
|
687
|
+
if (line && line.startsWith("event:")) {
|
|
688
|
+
const event = line.substring(6).trim();
|
|
689
|
+
for (let j = i + 1; j < lines.length; j++) {
|
|
690
|
+
const dataLine = lines[j];
|
|
691
|
+
if (dataLine && dataLine.startsWith("data:")) {
|
|
692
|
+
const dataStr = dataLine.substring(5).trim();
|
|
693
|
+
if (dataStr) {
|
|
694
|
+
try {
|
|
695
|
+
const data = JSON.parse(dataStr);
|
|
696
|
+
if (event === "progress" && onProgress) {
|
|
697
|
+
onProgress(data.message, data.fraction);
|
|
698
|
+
} else if (event === "result") {
|
|
699
|
+
result = data;
|
|
700
|
+
} else if (event === "error") {
|
|
701
|
+
reject(new Error(data.message));
|
|
702
|
+
return;
|
|
703
|
+
}
|
|
704
|
+
} catch (e) {
|
|
705
|
+
log.error("Failed to parse SSE data", {
|
|
706
|
+
dataStr,
|
|
707
|
+
error: e
|
|
708
|
+
});
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
break;
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
if (result) {
|
|
718
|
+
resolve(result);
|
|
719
|
+
} else {
|
|
720
|
+
reject(new Error("No result received from server"));
|
|
721
|
+
}
|
|
722
|
+
}).catch(reject);
|
|
723
|
+
});
|
|
724
|
+
}
|
|
725
|
+
/**
|
|
726
|
+
* Executes code on the server in a sandboxed environment.
|
|
727
|
+
*/
|
|
728
|
+
async execute(code, config) {
|
|
729
|
+
await this.session.ensureInitialized();
|
|
730
|
+
const hints = this.tokenRegistry.getRecentTokens(1e3);
|
|
731
|
+
const detectedClientServices = {
|
|
732
|
+
hasLLM: !!this.serviceProviders.getLLM(),
|
|
733
|
+
hasApproval: !!this.serviceProviders.getApproval(),
|
|
734
|
+
hasEmbedding: !!this.serviceProviders.getEmbedding(),
|
|
735
|
+
hasTools: this.serviceProviders.hasTools()
|
|
736
|
+
};
|
|
737
|
+
const executionConfig = {
|
|
738
|
+
...config,
|
|
739
|
+
clientServices: {
|
|
740
|
+
...detectedClientServices,
|
|
741
|
+
...config?.clientServices || {}
|
|
742
|
+
},
|
|
743
|
+
provenanceHints: hints.length > 0 ? hints : void 0
|
|
744
|
+
};
|
|
745
|
+
this.lastExecutionConfig = executionConfig;
|
|
746
|
+
let result;
|
|
747
|
+
if (this.inProcessSession) {
|
|
748
|
+
result = await this.inProcessSession.execute(code, executionConfig);
|
|
749
|
+
} else {
|
|
750
|
+
const url = `${this.session.getBaseUrl()}/api/execute`;
|
|
751
|
+
const body = JSON.stringify({
|
|
752
|
+
code,
|
|
753
|
+
config: executionConfig
|
|
754
|
+
});
|
|
755
|
+
const headers = await this.session.prepareHeaders("POST", url, body);
|
|
756
|
+
const response = await fetch(url, {
|
|
757
|
+
method: "POST",
|
|
758
|
+
headers,
|
|
759
|
+
body
|
|
760
|
+
});
|
|
761
|
+
this.session.updateToken(response);
|
|
762
|
+
if (!response.ok) {
|
|
763
|
+
const error = await response.json();
|
|
764
|
+
throw new Error(`Execution failed: ${error.error || response.statusText}`);
|
|
765
|
+
}
|
|
766
|
+
result = await response.json();
|
|
767
|
+
}
|
|
768
|
+
if (result.provenanceTokens && result.provenanceTokens.length > 0) {
|
|
769
|
+
for (const { token } of result.provenanceTokens) {
|
|
770
|
+
this.tokenRegistry.add(token);
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
if (result.status === ExecutionStatus.PAUSED && result.needsCallbacks) {
|
|
774
|
+
return await this.handleBatchCallbacksAndResume(result);
|
|
775
|
+
}
|
|
776
|
+
if (result.status === ExecutionStatus.PAUSED && result.needsCallback) {
|
|
777
|
+
return await this.handlePauseAndResume(result);
|
|
778
|
+
}
|
|
779
|
+
return result;
|
|
780
|
+
}
|
|
781
|
+
/**
|
|
782
|
+
* Handles batch callbacks by executing them in parallel and resuming.
|
|
783
|
+
*/
|
|
784
|
+
async handleBatchCallbacksAndResume(pausedResult) {
|
|
785
|
+
if (!pausedResult.needsCallbacks || pausedResult.needsCallbacks.length === 0) {
|
|
786
|
+
throw new Error("No batch callback requests in paused execution");
|
|
787
|
+
}
|
|
788
|
+
const missingServiceIds = new Set(pausedResult.needsCallbacks.filter((cb) => !this.serviceProviders.hasServiceForCallback(cb.type)).map((cb) => cb.id));
|
|
789
|
+
if (missingServiceIds.size > 0) {
|
|
790
|
+
const missingServices = pausedResult.needsCallbacks.filter((cb) => missingServiceIds.has(cb.id));
|
|
791
|
+
const explicitlyRequestedMissing = missingServices.filter((cb) => this.wasServiceExplicitlyRequested(cb.type));
|
|
792
|
+
const unexpectedMissing = missingServices.filter((cb) => !this.wasServiceExplicitlyRequested(cb.type));
|
|
793
|
+
if (explicitlyRequestedMissing.length > 0) {
|
|
794
|
+
return pausedResult;
|
|
795
|
+
}
|
|
796
|
+
const errorMessage = `Missing service providers for callback types: ${unexpectedMissing.map((cb) => cb.type).join(", ")}`;
|
|
797
|
+
log.error(`Auto-handling batch paused execution without service providers: ${errorMessage}`, {
|
|
798
|
+
executionId: pausedResult.executionId,
|
|
799
|
+
missingServices: unexpectedMissing.map((cb) => ({
|
|
800
|
+
type: cb.type,
|
|
801
|
+
operation: cb.operation,
|
|
802
|
+
id: cb.id
|
|
803
|
+
}))
|
|
804
|
+
});
|
|
805
|
+
const existingCallbacks = pausedResult.needsCallbacks.filter((cb) => !missingServiceIds.has(cb.id));
|
|
806
|
+
if (existingCallbacks.length > 0) {
|
|
807
|
+
try {
|
|
808
|
+
const existingResults = await Promise.all(existingCallbacks.map(async (cb) => {
|
|
809
|
+
const callbackResult = await this.serviceProviders.handleCallback(cb.type, {
|
|
810
|
+
...cb.payload,
|
|
811
|
+
operation: cb.operation
|
|
812
|
+
});
|
|
813
|
+
return {
|
|
814
|
+
id: cb.id,
|
|
815
|
+
result: callbackResult
|
|
816
|
+
};
|
|
817
|
+
}));
|
|
818
|
+
const allResults = pausedResult.needsCallbacks.map((cb) => {
|
|
819
|
+
if (missingServiceIds.has(cb.id)) {
|
|
820
|
+
return {
|
|
821
|
+
id: cb.id,
|
|
822
|
+
result: {
|
|
823
|
+
__error: true,
|
|
824
|
+
message: `${cb.type} service not provided by client`
|
|
825
|
+
}
|
|
826
|
+
};
|
|
827
|
+
}
|
|
828
|
+
return existingResults.find((r) => r.id === cb.id);
|
|
829
|
+
});
|
|
830
|
+
return await this.resumeWithBatchResults(pausedResult.executionId, allResults);
|
|
831
|
+
} catch (error) {
|
|
832
|
+
const errorMessage2 = error instanceof Error ? error.message : String(error);
|
|
833
|
+
log.error(`Error handling existing services in batch: ${errorMessage2}`, {
|
|
834
|
+
executionId: pausedResult.executionId
|
|
835
|
+
});
|
|
836
|
+
const allErrorResults = pausedResult.needsCallbacks.map((cb) => ({
|
|
837
|
+
id: cb.id,
|
|
838
|
+
result: {
|
|
839
|
+
__error: true,
|
|
840
|
+
message: missingServiceIds.has(cb.id) ? `${cb.type} service not provided by client` : errorMessage2
|
|
841
|
+
}
|
|
842
|
+
}));
|
|
843
|
+
return await this.resumeWithBatchResults(pausedResult.executionId, allErrorResults);
|
|
844
|
+
}
|
|
845
|
+
} else {
|
|
846
|
+
const allErrorResults = pausedResult.needsCallbacks.map((cb) => ({
|
|
847
|
+
id: cb.id,
|
|
848
|
+
result: {
|
|
849
|
+
__error: true,
|
|
850
|
+
message: `${cb.type} service not provided by client`
|
|
851
|
+
}
|
|
852
|
+
}));
|
|
853
|
+
return await this.resumeWithBatchResults(pausedResult.executionId, allErrorResults);
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
try {
|
|
857
|
+
const batchResults = await Promise.all(pausedResult.needsCallbacks.map(async (cb) => {
|
|
858
|
+
const callbackResult = await this.serviceProviders.handleCallback(cb.type, {
|
|
859
|
+
...cb.payload,
|
|
860
|
+
operation: cb.operation
|
|
861
|
+
});
|
|
862
|
+
return {
|
|
863
|
+
id: cb.id,
|
|
864
|
+
result: callbackResult
|
|
865
|
+
};
|
|
866
|
+
}));
|
|
867
|
+
return await this.resumeWithBatchResults(pausedResult.executionId, batchResults);
|
|
868
|
+
} catch (error) {
|
|
869
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
870
|
+
log.error(`Error handling batch callbacks: ${errorMessage}`, {
|
|
871
|
+
executionId: pausedResult.executionId,
|
|
872
|
+
callbackCount: pausedResult.needsCallbacks.length
|
|
873
|
+
});
|
|
874
|
+
const allErrorResults = pausedResult.needsCallbacks.map((cb) => ({
|
|
875
|
+
id: cb.id,
|
|
876
|
+
result: {
|
|
877
|
+
__error: true,
|
|
878
|
+
message: errorMessage
|
|
879
|
+
}
|
|
880
|
+
}));
|
|
881
|
+
return await this.resumeWithBatchResults(pausedResult.executionId, allErrorResults);
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
/**
|
|
885
|
+
* Handles a paused execution by processing the callback and resuming.
|
|
886
|
+
*/
|
|
887
|
+
async handlePauseAndResume(pausedResult) {
|
|
888
|
+
if (!pausedResult.needsCallback) {
|
|
889
|
+
throw new Error("No callback request in paused execution");
|
|
890
|
+
}
|
|
891
|
+
if (!this.serviceProviders.hasServiceForCallback(pausedResult.needsCallback.type)) {
|
|
892
|
+
const wasExplicitlyRequested = this.wasServiceExplicitlyRequested(pausedResult.needsCallback.type);
|
|
893
|
+
if (wasExplicitlyRequested) {
|
|
894
|
+
return pausedResult;
|
|
895
|
+
}
|
|
896
|
+
const errorMessage = `${pausedResult.needsCallback.type} service not provided by client`;
|
|
897
|
+
log.error(`Auto-handling paused execution without service provider: ${errorMessage}`, {
|
|
898
|
+
executionId: pausedResult.executionId,
|
|
899
|
+
callbackType: pausedResult.needsCallback.type,
|
|
900
|
+
operation: pausedResult.needsCallback.operation
|
|
901
|
+
});
|
|
902
|
+
return await this.resume(pausedResult.executionId, {
|
|
903
|
+
__error: true,
|
|
904
|
+
message: errorMessage
|
|
905
|
+
});
|
|
906
|
+
}
|
|
907
|
+
try {
|
|
908
|
+
const callbackResult = await this.serviceProviders.handleCallback(pausedResult.needsCallback.type, {
|
|
909
|
+
...pausedResult.needsCallback.payload,
|
|
910
|
+
operation: pausedResult.needsCallback.operation,
|
|
911
|
+
executionId: pausedResult.executionId
|
|
912
|
+
});
|
|
913
|
+
return await this.resume(pausedResult.executionId, callbackResult);
|
|
914
|
+
} catch (error) {
|
|
915
|
+
if (error instanceof ClientCallbackError) {
|
|
916
|
+
throw error;
|
|
917
|
+
}
|
|
918
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
919
|
+
log.error(`Error handling callback: ${errorMessage}`, {
|
|
920
|
+
executionId: pausedResult.executionId,
|
|
921
|
+
callbackType: pausedResult.needsCallback.type,
|
|
922
|
+
operation: pausedResult.needsCallback.operation
|
|
923
|
+
});
|
|
924
|
+
return await this.resume(pausedResult.executionId, {
|
|
925
|
+
__error: true,
|
|
926
|
+
message: errorMessage
|
|
927
|
+
});
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
/**
|
|
931
|
+
* Check if a service was explicitly requested in clientServices config
|
|
932
|
+
*/
|
|
933
|
+
wasServiceExplicitlyRequested(callbackType) {
|
|
934
|
+
if (!this.lastExecutionConfig?.clientServices) {
|
|
935
|
+
return false;
|
|
936
|
+
}
|
|
937
|
+
switch (callbackType) {
|
|
938
|
+
case CallbackType.LLM:
|
|
939
|
+
return this.lastExecutionConfig.clientServices.hasLLM;
|
|
940
|
+
case CallbackType.APPROVAL:
|
|
941
|
+
return this.lastExecutionConfig.clientServices.hasApproval;
|
|
942
|
+
case CallbackType.EMBEDDING:
|
|
943
|
+
return this.lastExecutionConfig.clientServices.hasEmbedding;
|
|
944
|
+
case CallbackType.TOOL:
|
|
945
|
+
return this.lastExecutionConfig.clientServices.hasTools;
|
|
946
|
+
default:
|
|
947
|
+
return false;
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
/**
|
|
951
|
+
* Resumes a paused execution with a callback result.
|
|
952
|
+
*/
|
|
953
|
+
async resume(executionId, callbackResult) {
|
|
954
|
+
await this.session.ensureInitialized();
|
|
955
|
+
let result;
|
|
956
|
+
if (this.inProcessSession) {
|
|
957
|
+
result = await this.inProcessSession.resume(executionId, callbackResult);
|
|
958
|
+
} else {
|
|
959
|
+
const url = `${this.session.getBaseUrl()}/api/resume/${executionId}`;
|
|
960
|
+
const body = JSON.stringify({
|
|
961
|
+
result: callbackResult
|
|
962
|
+
});
|
|
963
|
+
const headers = await this.session.prepareHeaders("POST", url, body);
|
|
964
|
+
const response = await fetch(url, {
|
|
965
|
+
method: "POST",
|
|
966
|
+
headers,
|
|
967
|
+
body
|
|
968
|
+
});
|
|
969
|
+
this.session.updateToken(response);
|
|
970
|
+
if (!response.ok) {
|
|
971
|
+
const error = await response.json();
|
|
972
|
+
throw new Error(`Resume failed: ${error.error || response.statusText}`);
|
|
973
|
+
}
|
|
974
|
+
result = await response.json();
|
|
975
|
+
}
|
|
976
|
+
if (result.provenanceTokens && result.provenanceTokens.length > 0) {
|
|
977
|
+
for (const { token } of result.provenanceTokens) {
|
|
978
|
+
this.tokenRegistry.add(token);
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
if (result.status === ExecutionStatus.PAUSED && result.needsCallbacks) {
|
|
982
|
+
return await this.handleBatchCallbacksAndResume(result);
|
|
983
|
+
}
|
|
984
|
+
if (result.status === ExecutionStatus.PAUSED && result.needsCallback) {
|
|
985
|
+
return await this.handlePauseAndResume(result);
|
|
986
|
+
}
|
|
987
|
+
return result;
|
|
988
|
+
}
|
|
989
|
+
/**
|
|
990
|
+
* Resumes a paused execution with batch callback results.
|
|
991
|
+
*/
|
|
992
|
+
async resumeWithBatchResults(executionId, batchResults) {
|
|
993
|
+
await this.session.ensureInitialized();
|
|
994
|
+
let result;
|
|
995
|
+
if (this.inProcessSession) {
|
|
996
|
+
result = await this.inProcessSession.resumeWithBatchResults(executionId, batchResults);
|
|
997
|
+
} else {
|
|
998
|
+
const url = `${this.session.getBaseUrl()}/api/resume/${executionId}`;
|
|
999
|
+
const body = JSON.stringify({
|
|
1000
|
+
results: batchResults
|
|
1001
|
+
});
|
|
1002
|
+
const headers = await this.session.prepareHeaders("POST", url, body);
|
|
1003
|
+
const response = await fetch(url, {
|
|
1004
|
+
method: "POST",
|
|
1005
|
+
headers,
|
|
1006
|
+
body
|
|
1007
|
+
});
|
|
1008
|
+
this.session.updateToken(response);
|
|
1009
|
+
if (!response.ok) {
|
|
1010
|
+
const error = await response.json();
|
|
1011
|
+
throw new Error(`Batch resume failed: ${error.error || response.statusText}`);
|
|
1012
|
+
}
|
|
1013
|
+
result = await response.json();
|
|
1014
|
+
}
|
|
1015
|
+
if (result.provenanceTokens && result.provenanceTokens.length > 0) {
|
|
1016
|
+
for (const { token } of result.provenanceTokens) {
|
|
1017
|
+
this.tokenRegistry.add(token);
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
if (result.status === ExecutionStatus.PAUSED && result.needsCallbacks) {
|
|
1021
|
+
return await this.handleBatchCallbacksAndResume(result);
|
|
1022
|
+
}
|
|
1023
|
+
if (result.status === ExecutionStatus.PAUSED && result.needsCallback) {
|
|
1024
|
+
return await this.handlePauseAndResume(result);
|
|
1025
|
+
}
|
|
1026
|
+
return result;
|
|
1027
|
+
}
|
|
1028
|
+
};
|
|
1029
|
+
var LLMOperation = {
|
|
1030
|
+
CALL: "call",
|
|
1031
|
+
EXTRACT: "extract",
|
|
1032
|
+
CLASSIFY: "classify"
|
|
1033
|
+
};
|
|
1034
|
+
var EmbeddingOperation = {
|
|
1035
|
+
EMBED: "embed",
|
|
1036
|
+
SEARCH: "search"
|
|
1037
|
+
};
|
|
1038
|
+
var ServiceProviders = class {
|
|
1039
|
+
static {
|
|
1040
|
+
__name(this, "ServiceProviders");
|
|
1041
|
+
}
|
|
1042
|
+
providers = {};
|
|
1043
|
+
toolHandlers = /* @__PURE__ */ new Map();
|
|
1044
|
+
constructor(providers) {
|
|
1045
|
+
this.providers = providers || {};
|
|
1046
|
+
if (providers?.tools) {
|
|
1047
|
+
for (const tool of providers.tools) {
|
|
1048
|
+
this.toolHandlers.set(tool.name, tool.handler);
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
provideLLM(handler) {
|
|
1053
|
+
this.providers.llm = handler;
|
|
1054
|
+
}
|
|
1055
|
+
provideApproval(handler) {
|
|
1056
|
+
this.providers.approval = handler;
|
|
1057
|
+
}
|
|
1058
|
+
provideEmbedding(handler) {
|
|
1059
|
+
this.providers.embedding = handler;
|
|
1060
|
+
}
|
|
1061
|
+
provideTools(tools) {
|
|
1062
|
+
this.providers.tools = tools;
|
|
1063
|
+
for (const tool of tools) {
|
|
1064
|
+
this.toolHandlers.set(tool.name, tool.handler);
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
getLLM() {
|
|
1068
|
+
return this.providers.llm;
|
|
1069
|
+
}
|
|
1070
|
+
getApproval() {
|
|
1071
|
+
return this.providers.approval;
|
|
1072
|
+
}
|
|
1073
|
+
getEmbedding() {
|
|
1074
|
+
return this.providers.embedding;
|
|
1075
|
+
}
|
|
1076
|
+
getTools() {
|
|
1077
|
+
return this.providers.tools;
|
|
1078
|
+
}
|
|
1079
|
+
/**
|
|
1080
|
+
* Get tool definitions (without handlers) for sending to server
|
|
1081
|
+
*/
|
|
1082
|
+
getToolDefinitions() {
|
|
1083
|
+
if (!this.providers.tools) {
|
|
1084
|
+
return [];
|
|
1085
|
+
}
|
|
1086
|
+
return this.providers.tools.map((tool) => {
|
|
1087
|
+
const { handler, ...definition } = tool;
|
|
1088
|
+
return definition;
|
|
1089
|
+
});
|
|
1090
|
+
}
|
|
1091
|
+
/**
|
|
1092
|
+
* Check if client has tools
|
|
1093
|
+
*/
|
|
1094
|
+
hasTools() {
|
|
1095
|
+
return !!(this.providers.tools && this.providers.tools.length > 0);
|
|
1096
|
+
}
|
|
1097
|
+
/**
|
|
1098
|
+
* Check if client has any services or tools
|
|
1099
|
+
*/
|
|
1100
|
+
hasAnyServices() {
|
|
1101
|
+
return !!(this.providers.llm || this.providers.approval || this.providers.embedding || this.hasTools());
|
|
1102
|
+
}
|
|
1103
|
+
/**
|
|
1104
|
+
* Check if client has a service for a specific callback type
|
|
1105
|
+
*/
|
|
1106
|
+
hasServiceForCallback(callbackType) {
|
|
1107
|
+
switch (callbackType) {
|
|
1108
|
+
case CallbackType.LLM:
|
|
1109
|
+
return !!this.providers.llm;
|
|
1110
|
+
case CallbackType.APPROVAL:
|
|
1111
|
+
return !!this.providers.approval;
|
|
1112
|
+
case CallbackType.EMBEDDING:
|
|
1113
|
+
return !!this.providers.embedding;
|
|
1114
|
+
case CallbackType.TOOL:
|
|
1115
|
+
return this.hasTools();
|
|
1116
|
+
default:
|
|
1117
|
+
return false;
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
async handleCallback(callbackType, payload) {
|
|
1121
|
+
if (payload.operation === "batch_parallel" && payload.calls) {
|
|
1122
|
+
return await Promise.all(payload.calls.map(async (call) => {
|
|
1123
|
+
return await this.handleCallback(call.type, {
|
|
1124
|
+
...call.payload,
|
|
1125
|
+
operation: call.operation
|
|
1126
|
+
});
|
|
1127
|
+
}));
|
|
1128
|
+
}
|
|
1129
|
+
switch (callbackType) {
|
|
1130
|
+
case CallbackType.LLM:
|
|
1131
|
+
if (!this.providers.llm) {
|
|
1132
|
+
throw new Error("LLM service not provided by client");
|
|
1133
|
+
}
|
|
1134
|
+
if (payload.operation === LLMOperation.CALL) {
|
|
1135
|
+
return await this.providers.llm.call(payload.prompt, payload.options);
|
|
1136
|
+
} else if (payload.operation === LLMOperation.EXTRACT && this.providers.llm.extract) {
|
|
1137
|
+
return await this.providers.llm.extract(payload.prompt, payload.schema, payload.options);
|
|
1138
|
+
} else if (payload.operation === LLMOperation.CLASSIFY && this.providers.llm.classify) {
|
|
1139
|
+
return await this.providers.llm.classify(payload.text, payload.categories, payload.options);
|
|
1140
|
+
}
|
|
1141
|
+
throw new Error(`Unsupported LLM operation: ${payload.operation}`);
|
|
1142
|
+
case CallbackType.APPROVAL:
|
|
1143
|
+
if (!this.providers.approval) {
|
|
1144
|
+
throw new Error("Approval service not provided by client");
|
|
1145
|
+
}
|
|
1146
|
+
const contextWithExecutionId = payload.context ? {
|
|
1147
|
+
...payload.context,
|
|
1148
|
+
executionId: payload.executionId
|
|
1149
|
+
} : {
|
|
1150
|
+
executionId: payload.executionId
|
|
1151
|
+
};
|
|
1152
|
+
return await this.providers.approval.request(payload.message, contextWithExecutionId);
|
|
1153
|
+
case CallbackType.EMBEDDING:
|
|
1154
|
+
if (!this.providers.embedding) {
|
|
1155
|
+
throw new Error("Embedding service not provided by client");
|
|
1156
|
+
}
|
|
1157
|
+
if (payload.operation === EmbeddingOperation.EMBED) {
|
|
1158
|
+
return await this.providers.embedding.embed(payload.text);
|
|
1159
|
+
} else if (payload.operation === EmbeddingOperation.SEARCH) {
|
|
1160
|
+
const queryEmbedding = await this.providers.embedding.embed(payload.query);
|
|
1161
|
+
return queryEmbedding;
|
|
1162
|
+
} else if (payload.operation === "similarity" && this.providers.embedding.similarity) {
|
|
1163
|
+
return await this.providers.embedding.similarity(payload.text1, payload.text2);
|
|
1164
|
+
}
|
|
1165
|
+
throw new Error(`Unsupported embedding operation: ${payload.operation}`);
|
|
1166
|
+
case CallbackType.TOOL:
|
|
1167
|
+
if (payload.operation === ToolOperation.CALL) {
|
|
1168
|
+
const toolName = payload.toolName;
|
|
1169
|
+
const handler = this.toolHandlers.get(toolName);
|
|
1170
|
+
if (!handler) {
|
|
1171
|
+
throw new Error(`Tool '${toolName}' not found in client tools`);
|
|
1172
|
+
}
|
|
1173
|
+
const result = await handler(payload.input);
|
|
1174
|
+
return result;
|
|
1175
|
+
}
|
|
1176
|
+
throw new Error(`Unsupported tool operation: ${payload.operation}`);
|
|
1177
|
+
default:
|
|
1178
|
+
throw new Error(`Unknown callback type: ${callbackType}`);
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
};
|
|
1182
|
+
|
|
1183
|
+
// src/tools/types.ts
|
|
1184
|
+
var ToolNames = {
|
|
1185
|
+
SEARCH_API: "search_api",
|
|
1186
|
+
FETCH_ALL_APIS: "fetch_all_apis",
|
|
1187
|
+
EXECUTE_CODE: "execute_code",
|
|
1188
|
+
EXPLORE_API: "explore_api"
|
|
1189
|
+
};
|
|
1190
|
+
var searchApiInputSchema = z.object({
|
|
1191
|
+
query: z.string().describe("Search query string")
|
|
1192
|
+
});
|
|
1193
|
+
function createSearchApiTool(client) {
|
|
1194
|
+
return {
|
|
1195
|
+
name: ToolNames.SEARCH_API,
|
|
1196
|
+
description: 'Search for APIs by keyword. Provide search term as string like "add", "math", "user", etc.',
|
|
1197
|
+
inputSchema: zodToJsonSchema(searchApiInputSchema),
|
|
1198
|
+
zodSchema: searchApiInputSchema,
|
|
1199
|
+
func: /* @__PURE__ */ __name(async (input) => {
|
|
1200
|
+
try {
|
|
1201
|
+
const results = await client.searchAPI(input.query);
|
|
1202
|
+
return JSON.stringify({
|
|
1203
|
+
success: true,
|
|
1204
|
+
results: results.map((r) => ({
|
|
1205
|
+
apiGroup: r.apiGroup,
|
|
1206
|
+
functionName: r.functionName,
|
|
1207
|
+
description: r.description,
|
|
1208
|
+
signature: r.signature
|
|
1209
|
+
})),
|
|
1210
|
+
count: results.length
|
|
1211
|
+
}, null, 2);
|
|
1212
|
+
} catch (error) {
|
|
1213
|
+
return JSON.stringify({
|
|
1214
|
+
success: false,
|
|
1215
|
+
error: error.message
|
|
1216
|
+
}, null, 2);
|
|
1217
|
+
}
|
|
1218
|
+
}, "func")
|
|
1219
|
+
};
|
|
1220
|
+
}
|
|
1221
|
+
__name(createSearchApiTool, "createSearchApiTool");
|
|
1222
|
+
var fetchAllApisInputSchema = z.object({
|
|
1223
|
+
apiGroups: z.array(z.string()).optional().describe("Optional: Specific API groups to include")
|
|
1224
|
+
});
|
|
1225
|
+
function createFetchAllApisTool(client) {
|
|
1226
|
+
return {
|
|
1227
|
+
name: ToolNames.FETCH_ALL_APIS,
|
|
1228
|
+
description: "Get TypeScript definitions of all available APIs. Returns code showing api.add, api.getTodo, etc.",
|
|
1229
|
+
inputSchema: zodToJsonSchema(fetchAllApisInputSchema),
|
|
1230
|
+
zodSchema: fetchAllApisInputSchema,
|
|
1231
|
+
func: /* @__PURE__ */ __name(async (_input) => {
|
|
1232
|
+
try {
|
|
1233
|
+
const typescript = client.getTypeDefinitions();
|
|
1234
|
+
return JSON.stringify({
|
|
1235
|
+
success: true,
|
|
1236
|
+
typescript,
|
|
1237
|
+
message: "Use this TypeScript to understand available api.* functions"
|
|
1238
|
+
}, null, 2);
|
|
1239
|
+
} catch (error) {
|
|
1240
|
+
return JSON.stringify({
|
|
1241
|
+
success: false,
|
|
1242
|
+
error: error.message
|
|
1243
|
+
}, null, 2);
|
|
1244
|
+
}
|
|
1245
|
+
}, "func")
|
|
1246
|
+
};
|
|
1247
|
+
}
|
|
1248
|
+
__name(createFetchAllApisTool, "createFetchAllApisTool");
|
|
1249
|
+
var executeCodeInputSchema = z.object({
|
|
1250
|
+
code: z.string().describe("The JavaScript/TypeScript code to execute"),
|
|
1251
|
+
timeout: z.number().optional().describe("Execution timeout in milliseconds (default: 30000)"),
|
|
1252
|
+
maxMemory: z.number().optional().describe("Maximum memory in bytes (default: 128MB)")
|
|
1253
|
+
});
|
|
1254
|
+
function createExecuteCodeTool(client) {
|
|
1255
|
+
return {
|
|
1256
|
+
name: ToolNames.EXECUTE_CODE,
|
|
1257
|
+
description: "Execute JavaScript/TypeScript code to call APIs. IMPORTANT: Code MUST use 'return' statement to see results. Examples: 'return api.groupName.functionName({})' or 'const result = api.group.func({}); return result'. Use bracket notation for dynamic names: api['groupName']['functionName']({}).",
|
|
1258
|
+
inputSchema: zodToJsonSchema(executeCodeInputSchema),
|
|
1259
|
+
zodSchema: executeCodeInputSchema,
|
|
1260
|
+
func: /* @__PURE__ */ __name(async (input) => {
|
|
1261
|
+
try {
|
|
1262
|
+
const result = await client.execute(input.code, {
|
|
1263
|
+
timeout: input.timeout,
|
|
1264
|
+
maxMemory: input.maxMemory
|
|
1265
|
+
});
|
|
1266
|
+
if (result.status === ExecutionStatus.COMPLETED) {
|
|
1267
|
+
return JSON.stringify({
|
|
1268
|
+
success: true,
|
|
1269
|
+
result: result.result,
|
|
1270
|
+
stats: {
|
|
1271
|
+
duration: result.stats.duration,
|
|
1272
|
+
memoryUsed: result.stats.memoryUsed
|
|
1273
|
+
}
|
|
1274
|
+
}, null, 2);
|
|
1275
|
+
} else if (result.status === ExecutionStatus.FAILED) {
|
|
1276
|
+
return JSON.stringify({
|
|
1277
|
+
success: false,
|
|
1278
|
+
error: result.error?.message || "Execution failed",
|
|
1279
|
+
stack: result.error?.stack,
|
|
1280
|
+
message: "Code execution failed. Check syntax and fix errors."
|
|
1281
|
+
}, null, 2);
|
|
1282
|
+
} else {
|
|
1283
|
+
return JSON.stringify({
|
|
1284
|
+
success: false,
|
|
1285
|
+
error: "Execution timed out",
|
|
1286
|
+
message: "Code took too long. Simplify or optimize."
|
|
1287
|
+
}, null, 2);
|
|
1288
|
+
}
|
|
1289
|
+
} catch (error) {
|
|
1290
|
+
return JSON.stringify({
|
|
1291
|
+
success: false,
|
|
1292
|
+
error: error.message,
|
|
1293
|
+
message: "Failed to execute code"
|
|
1294
|
+
}, null, 2);
|
|
1295
|
+
}
|
|
1296
|
+
}, "func")
|
|
1297
|
+
};
|
|
1298
|
+
}
|
|
1299
|
+
__name(createExecuteCodeTool, "createExecuteCodeTool");
|
|
1300
|
+
var exploreApiInputSchema = z.object({
|
|
1301
|
+
path: z.string().describe('Path to explore (e.g., "/", "/openapi/github", "/mcp/filesystem/read_file")')
|
|
1302
|
+
});
|
|
1303
|
+
function createExploreApiTool(client) {
|
|
1304
|
+
return {
|
|
1305
|
+
name: ToolNames.EXPLORE_API,
|
|
1306
|
+
description: 'Explore APIs using filesystem-like navigation. Navigate through directories to discover available functions. Provide path as string like "/", "/openapi", "/openapi/github", or "/openapi/github/repos/createRepo" to see functions.',
|
|
1307
|
+
inputSchema: zodToJsonSchema(exploreApiInputSchema),
|
|
1308
|
+
zodSchema: exploreApiInputSchema,
|
|
1309
|
+
func: /* @__PURE__ */ __name(async (input) => {
|
|
1310
|
+
try {
|
|
1311
|
+
const result = await client.exploreAPI(input.path);
|
|
1312
|
+
if (result.type === "directory") {
|
|
1313
|
+
return JSON.stringify({
|
|
1314
|
+
success: true,
|
|
1315
|
+
type: "directory",
|
|
1316
|
+
path: result.path,
|
|
1317
|
+
items: result.items
|
|
1318
|
+
}, null, 2);
|
|
1319
|
+
} else {
|
|
1320
|
+
return JSON.stringify({
|
|
1321
|
+
success: true,
|
|
1322
|
+
type: "function",
|
|
1323
|
+
name: result.name,
|
|
1324
|
+
description: result.description,
|
|
1325
|
+
definition: result.definition,
|
|
1326
|
+
group: result.group,
|
|
1327
|
+
path: result.path
|
|
1328
|
+
}, null, 2);
|
|
1329
|
+
}
|
|
1330
|
+
} catch (error) {
|
|
1331
|
+
return JSON.stringify({
|
|
1332
|
+
success: false,
|
|
1333
|
+
error: error.message
|
|
1334
|
+
}, null, 2);
|
|
1335
|
+
}
|
|
1336
|
+
}, "func")
|
|
1337
|
+
};
|
|
1338
|
+
}
|
|
1339
|
+
__name(createExploreApiTool, "createExploreApiTool");
|
|
1340
|
+
|
|
1341
|
+
// src/client.ts
|
|
1342
|
+
var AgentToolProtocolClient = class {
|
|
1343
|
+
static {
|
|
1344
|
+
__name(this, "AgentToolProtocolClient");
|
|
1345
|
+
}
|
|
1346
|
+
session;
|
|
1347
|
+
inProcessSession;
|
|
1348
|
+
apiOps;
|
|
1349
|
+
execOps;
|
|
1350
|
+
serviceProviders;
|
|
1351
|
+
/**
|
|
1352
|
+
* Creates a new client instance.
|
|
1353
|
+
*
|
|
1354
|
+
* @example
|
|
1355
|
+
* ```typescript
|
|
1356
|
+
* // HTTP mode
|
|
1357
|
+
* const client = new AgentToolProtocolClient({
|
|
1358
|
+
* baseUrl: 'http://localhost:3333',
|
|
1359
|
+
* headers: { Authorization: 'Bearer token' },
|
|
1360
|
+
* hooks: {
|
|
1361
|
+
* preRequest: async (context) => {
|
|
1362
|
+
* const token = await refreshToken();
|
|
1363
|
+
* return { headers: { ...context.currentHeaders, Authorization: `Bearer ${token}` } };
|
|
1364
|
+
* }
|
|
1365
|
+
* }
|
|
1366
|
+
* });
|
|
1367
|
+
*
|
|
1368
|
+
* // In-process mode (no port binding)
|
|
1369
|
+
* const server = createServer();
|
|
1370
|
+
* server.use(myApiGroup);
|
|
1371
|
+
* const client = new AgentToolProtocolClient({ server });
|
|
1372
|
+
* ```
|
|
1373
|
+
*/
|
|
1374
|
+
constructor(options) {
|
|
1375
|
+
const { baseUrl, server, headers, serviceProviders, hooks } = options;
|
|
1376
|
+
if (!baseUrl && !server) {
|
|
1377
|
+
throw new Error("Either baseUrl or server must be provided");
|
|
1378
|
+
}
|
|
1379
|
+
if (baseUrl && server) {
|
|
1380
|
+
throw new Error("Cannot provide both baseUrl and server");
|
|
1381
|
+
}
|
|
1382
|
+
this.serviceProviders = new ServiceProviders(serviceProviders);
|
|
1383
|
+
if (server) {
|
|
1384
|
+
this.inProcessSession = new InProcessSession(server);
|
|
1385
|
+
this.session = this.inProcessSession;
|
|
1386
|
+
this.apiOps = new APIOperations(this.session, this.inProcessSession);
|
|
1387
|
+
this.execOps = new ExecutionOperations(this.session, this.serviceProviders, this.inProcessSession);
|
|
1388
|
+
} else {
|
|
1389
|
+
this.session = new ClientSession(baseUrl, headers, hooks);
|
|
1390
|
+
this.apiOps = new APIOperations(this.session);
|
|
1391
|
+
this.execOps = new ExecutionOperations(this.session, this.serviceProviders);
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
/**
|
|
1395
|
+
* Initializes the client session with the server.
|
|
1396
|
+
* Automatically registers any client-provided tools and services with the server.
|
|
1397
|
+
*/
|
|
1398
|
+
async init(clientInfo) {
|
|
1399
|
+
const toolDefinitions = this.serviceProviders.getToolDefinitions();
|
|
1400
|
+
const services = {
|
|
1401
|
+
hasLLM: !!this.serviceProviders.getLLM(),
|
|
1402
|
+
hasApproval: !!this.serviceProviders.getApproval(),
|
|
1403
|
+
hasEmbedding: !!this.serviceProviders.getEmbedding(),
|
|
1404
|
+
hasTools: this.serviceProviders.hasTools()
|
|
1405
|
+
};
|
|
1406
|
+
return await this.session.init(clientInfo, toolDefinitions, services);
|
|
1407
|
+
}
|
|
1408
|
+
/**
|
|
1409
|
+
* Gets the unique client ID.
|
|
1410
|
+
*/
|
|
1411
|
+
getClientId() {
|
|
1412
|
+
return this.session.getClientId();
|
|
1413
|
+
}
|
|
1414
|
+
/**
|
|
1415
|
+
* Provides an LLM implementation for server to use during execution.
|
|
1416
|
+
*/
|
|
1417
|
+
provideLLM(handler) {
|
|
1418
|
+
this.serviceProviders.provideLLM(handler);
|
|
1419
|
+
}
|
|
1420
|
+
/**
|
|
1421
|
+
* Provides an approval handler for server to request human approval.
|
|
1422
|
+
*/
|
|
1423
|
+
provideApproval(handler) {
|
|
1424
|
+
this.serviceProviders.provideApproval(handler);
|
|
1425
|
+
}
|
|
1426
|
+
/**
|
|
1427
|
+
* Provides an embedding model for server to use.
|
|
1428
|
+
*/
|
|
1429
|
+
provideEmbedding(handler) {
|
|
1430
|
+
this.serviceProviders.provideEmbedding(handler);
|
|
1431
|
+
}
|
|
1432
|
+
/**
|
|
1433
|
+
* Provides custom tools that execute on the client side.
|
|
1434
|
+
* Note: Must be called before init() or re-initialize after calling this.
|
|
1435
|
+
*/
|
|
1436
|
+
provideTools(tools) {
|
|
1437
|
+
this.serviceProviders.provideTools(tools);
|
|
1438
|
+
}
|
|
1439
|
+
/**
|
|
1440
|
+
* Gets all client-provided tools (registered via provideTools).
|
|
1441
|
+
* Returns the full tool objects including handlers.
|
|
1442
|
+
*/
|
|
1443
|
+
getClientTools() {
|
|
1444
|
+
return this.serviceProviders.getTools() || [];
|
|
1445
|
+
}
|
|
1446
|
+
/**
|
|
1447
|
+
* Gets client-provided tool definitions (without handlers).
|
|
1448
|
+
* Useful for sending tool metadata to servers.
|
|
1449
|
+
*/
|
|
1450
|
+
getClientToolDefinitions() {
|
|
1451
|
+
return this.serviceProviders.getToolDefinitions();
|
|
1452
|
+
}
|
|
1453
|
+
/**
|
|
1454
|
+
* Gets the ATP tools (execute_code, explore_api, search_api, fetch_all_apis).
|
|
1455
|
+
* These are ready-to-use tools that can be exposed to MCP or other frameworks.
|
|
1456
|
+
*
|
|
1457
|
+
* @example
|
|
1458
|
+
* ```typescript
|
|
1459
|
+
* const tools = client.getATPTools();
|
|
1460
|
+
* for (const tool of tools) {
|
|
1461
|
+
* mcpServer.tool(tool.name, tool.description, tool.inputSchema, async (args) => {
|
|
1462
|
+
* const result = await tool.func(args);
|
|
1463
|
+
* return { content: [{ type: 'text', text: result }] };
|
|
1464
|
+
* });
|
|
1465
|
+
* }
|
|
1466
|
+
* ```
|
|
1467
|
+
*/
|
|
1468
|
+
getATPTools() {
|
|
1469
|
+
return [
|
|
1470
|
+
createSearchApiTool(this),
|
|
1471
|
+
createFetchAllApisTool(this),
|
|
1472
|
+
createExecuteCodeTool(this),
|
|
1473
|
+
createExploreApiTool(this)
|
|
1474
|
+
];
|
|
1475
|
+
}
|
|
1476
|
+
/**
|
|
1477
|
+
* Connects to the server and retrieves API definitions.
|
|
1478
|
+
*/
|
|
1479
|
+
async connect(options) {
|
|
1480
|
+
return await this.apiOps.connect(options);
|
|
1481
|
+
}
|
|
1482
|
+
/**
|
|
1483
|
+
* Gets the TypeScript type definitions for available APIs.
|
|
1484
|
+
*/
|
|
1485
|
+
getTypeDefinitions() {
|
|
1486
|
+
return this.apiOps.getTypeDefinitions();
|
|
1487
|
+
}
|
|
1488
|
+
/**
|
|
1489
|
+
* Searches for available API functions.
|
|
1490
|
+
*/
|
|
1491
|
+
async searchAPI(query, options) {
|
|
1492
|
+
return await this.apiOps.searchAPI(query, options);
|
|
1493
|
+
}
|
|
1494
|
+
/**
|
|
1495
|
+
* Explores the API filesystem at the given path.
|
|
1496
|
+
*/
|
|
1497
|
+
async exploreAPI(path) {
|
|
1498
|
+
return await this.apiOps.exploreAPI(path);
|
|
1499
|
+
}
|
|
1500
|
+
/**
|
|
1501
|
+
* Executes code on the server with real-time progress updates via SSE.
|
|
1502
|
+
*/
|
|
1503
|
+
async executeStream(code, config, onProgress) {
|
|
1504
|
+
return await this.execOps.executeStream(code, config, onProgress);
|
|
1505
|
+
}
|
|
1506
|
+
/**
|
|
1507
|
+
* Executes code on the server in a sandboxed environment.
|
|
1508
|
+
*/
|
|
1509
|
+
async execute(code, config) {
|
|
1510
|
+
return await this.execOps.execute(code, config);
|
|
1511
|
+
}
|
|
1512
|
+
/**
|
|
1513
|
+
* Resumes a paused execution with a callback result.
|
|
1514
|
+
*/
|
|
1515
|
+
async resume(executionId, callbackResult) {
|
|
1516
|
+
return await this.execOps.resume(executionId, callbackResult);
|
|
1517
|
+
}
|
|
1518
|
+
/**
|
|
1519
|
+
* Handles a callback request from the server during execution.
|
|
1520
|
+
*/
|
|
1521
|
+
async handleCallback(callbackType, payload) {
|
|
1522
|
+
return await this.serviceProviders.handleCallback(callbackType, payload);
|
|
1523
|
+
}
|
|
1524
|
+
/**
|
|
1525
|
+
* Gets information about the server.
|
|
1526
|
+
*/
|
|
1527
|
+
async getServerInfo() {
|
|
1528
|
+
return await this.apiOps.getServerInfo();
|
|
1529
|
+
}
|
|
1530
|
+
/**
|
|
1531
|
+
* Gets ATP runtime API definitions as TypeScript declarations.
|
|
1532
|
+
* Returns the full TypeScript definitions for atp.llm.*, atp.cache.*, etc.
|
|
1533
|
+
* These are the APIs available during code execution.
|
|
1534
|
+
*
|
|
1535
|
+
* Behavior:
|
|
1536
|
+
* - No options: Returns APIs based on client capabilities (default filtering)
|
|
1537
|
+
* - apis: ['llm', 'cache']: Returns only specified APIs (intersection with client capabilities)
|
|
1538
|
+
* - apis: []: Returns all APIs regardless of client capabilities
|
|
1539
|
+
*
|
|
1540
|
+
* @param options - Optional filtering options
|
|
1541
|
+
* @param options.apis - Specific APIs to include (e.g., ['llm', 'cache', 'approval'])
|
|
1542
|
+
*/
|
|
1543
|
+
async getRuntimeDefinitions(options) {
|
|
1544
|
+
return await this.apiOps.getRuntimeDefinitions(options);
|
|
1545
|
+
}
|
|
1546
|
+
};
|
|
1547
|
+
var CodeGenerator = class {
|
|
1548
|
+
static {
|
|
1549
|
+
__name(this, "CodeGenerator");
|
|
1550
|
+
}
|
|
1551
|
+
client;
|
|
1552
|
+
constructor(client) {
|
|
1553
|
+
this.client = client;
|
|
1554
|
+
}
|
|
1555
|
+
async generateCode(intent, parameters) {
|
|
1556
|
+
const types = this.client.getTypeDefinitions();
|
|
1557
|
+
log.debug("Generating code for intent", {
|
|
1558
|
+
intent,
|
|
1559
|
+
parameters,
|
|
1560
|
+
typesLength: types.length
|
|
1561
|
+
});
|
|
1562
|
+
return "// Generated code";
|
|
1563
|
+
}
|
|
1564
|
+
};
|
|
1565
|
+
|
|
1566
|
+
// src/tools.ts
|
|
1567
|
+
function createToolsFromATPClient(client) {
|
|
1568
|
+
return [
|
|
1569
|
+
createSearchApiTool(client),
|
|
1570
|
+
createFetchAllApisTool(client),
|
|
1571
|
+
createExecuteCodeTool(client),
|
|
1572
|
+
createExploreApiTool(client)
|
|
1573
|
+
];
|
|
1574
|
+
}
|
|
1575
|
+
__name(createToolsFromATPClient, "createToolsFromATPClient");
|
|
1576
|
+
|
|
1577
|
+
export { AgentToolProtocolClient, ClientCallbackError, CodeGenerator, InProcessSession, ToolNames, createToolsFromATPClient };
|
|
1578
|
+
//# sourceMappingURL=index.js.map
|
|
8
1579
|
//# sourceMappingURL=index.js.map
|