@runtypelabs/sdk 1.7.1 → 1.7.3

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.
Files changed (80) hide show
  1. package/dist/index.cjs +7026 -0
  2. package/dist/index.cjs.map +1 -0
  3. package/dist/index.d.cts +5147 -0
  4. package/dist/index.d.ts +5146 -27
  5. package/dist/index.js +6955 -77
  6. package/dist/index.js.map +1 -1
  7. package/package.json +14 -7
  8. package/dist/batch-builder.d.ts +0 -106
  9. package/dist/batch-builder.d.ts.map +0 -1
  10. package/dist/batch-builder.js +0 -124
  11. package/dist/batch-builder.js.map +0 -1
  12. package/dist/batches-namespace.d.ts +0 -132
  13. package/dist/batches-namespace.d.ts.map +0 -1
  14. package/dist/batches-namespace.js +0 -128
  15. package/dist/batches-namespace.js.map +0 -1
  16. package/dist/case-types.d.ts +0 -42
  17. package/dist/case-types.d.ts.map +0 -1
  18. package/dist/case-types.js +0 -16
  19. package/dist/case-types.js.map +0 -1
  20. package/dist/client-token-types.d.ts +0 -143
  21. package/dist/client-token-types.d.ts.map +0 -1
  22. package/dist/client-token-types.js +0 -11
  23. package/dist/client-token-types.js.map +0 -1
  24. package/dist/client.d.ts +0 -131
  25. package/dist/client.d.ts.map +0 -1
  26. package/dist/client.js +0 -501
  27. package/dist/client.js.map +0 -1
  28. package/dist/endpoints.d.ts +0 -1248
  29. package/dist/endpoints.d.ts.map +0 -1
  30. package/dist/endpoints.js +0 -1649
  31. package/dist/endpoints.js.map +0 -1
  32. package/dist/error-handling-types.d.ts +0 -71
  33. package/dist/error-handling-types.d.ts.map +0 -1
  34. package/dist/error-handling-types.js +0 -12
  35. package/dist/error-handling-types.js.map +0 -1
  36. package/dist/eval-builder.d.ts +0 -216
  37. package/dist/eval-builder.d.ts.map +0 -1
  38. package/dist/eval-builder.js +0 -225
  39. package/dist/eval-builder.js.map +0 -1
  40. package/dist/evals-namespace.d.ts +0 -205
  41. package/dist/evals-namespace.d.ts.map +0 -1
  42. package/dist/evals-namespace.js +0 -208
  43. package/dist/evals-namespace.js.map +0 -1
  44. package/dist/flow-builder.d.ts +0 -717
  45. package/dist/flow-builder.d.ts.map +0 -1
  46. package/dist/flow-builder.js +0 -592
  47. package/dist/flow-builder.js.map +0 -1
  48. package/dist/flow-result.d.ts +0 -117
  49. package/dist/flow-result.d.ts.map +0 -1
  50. package/dist/flow-result.js +0 -175
  51. package/dist/flow-result.js.map +0 -1
  52. package/dist/flows-namespace.d.ts +0 -442
  53. package/dist/flows-namespace.d.ts.map +0 -1
  54. package/dist/flows-namespace.js +0 -686
  55. package/dist/flows-namespace.js.map +0 -1
  56. package/dist/generated-tool-gate.d.ts +0 -75
  57. package/dist/generated-tool-gate.d.ts.map +0 -1
  58. package/dist/generated-tool-gate.js +0 -314
  59. package/dist/generated-tool-gate.js.map +0 -1
  60. package/dist/index.d.ts.map +0 -1
  61. package/dist/prompts-namespace.d.ts +0 -237
  62. package/dist/prompts-namespace.d.ts.map +0 -1
  63. package/dist/prompts-namespace.js +0 -222
  64. package/dist/prompts-namespace.js.map +0 -1
  65. package/dist/runtype.d.ts +0 -232
  66. package/dist/runtype.d.ts.map +0 -1
  67. package/dist/runtype.js +0 -367
  68. package/dist/runtype.js.map +0 -1
  69. package/dist/stream-utils.d.ts +0 -58
  70. package/dist/stream-utils.d.ts.map +0 -1
  71. package/dist/stream-utils.js +0 -373
  72. package/dist/stream-utils.js.map +0 -1
  73. package/dist/transform.d.ts +0 -30
  74. package/dist/transform.d.ts.map +0 -1
  75. package/dist/transform.js +0 -196
  76. package/dist/transform.js.map +0 -1
  77. package/dist/types.d.ts +0 -717
  78. package/dist/types.d.ts.map +0 -1
  79. package/dist/types.js +0 -7
  80. package/dist/types.js.map +0 -1
package/dist/endpoints.js DELETED
@@ -1,1649 +0,0 @@
1
- "use strict";
2
- /**
3
- * API endpoint handlers with automatic camelCase/snake_case transformation
4
- */
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.AgentsEndpoint = exports.ClientTokensEndpoint = exports.EvalEndpoint = exports.ToolsEndpoint = exports.ContextTemplatesEndpoint = exports.FlowStepsEndpoint = exports.AnalyticsEndpoint = exports.UsersEndpoint = exports.ChatEndpoint = exports.DispatchEndpoint = exports.ModelConfigsEndpoint = exports.ApiKeysEndpoint = exports.RecordsEndpoint = exports.PromptsEndpoint = exports.FlowsEndpoint = void 0;
7
- const generated_tool_gate_1 = require("./generated-tool-gate");
8
- /**
9
- * Flows endpoint handlers
10
- */
11
- class FlowsEndpoint {
12
- constructor(client) {
13
- this.client = client;
14
- }
15
- /**
16
- * List all flows for the authenticated user
17
- */
18
- async list(params) {
19
- return this.client.get('/flows', params);
20
- }
21
- /**
22
- * Get a specific flow by ID
23
- */
24
- async get(id) {
25
- const response = await this.client.get(`/flows/${id}`);
26
- return response;
27
- }
28
- /**
29
- * Create a new flow
30
- */
31
- async create(data) {
32
- return this.client.post('/flows', data);
33
- }
34
- /**
35
- * Update an existing flow
36
- */
37
- async update(id, data) {
38
- return this.client.put(`/flows/${id}`, data);
39
- }
40
- /**
41
- * Delete a flow
42
- */
43
- async delete(id) {
44
- return this.client.delete(`/flows/${id}`);
45
- }
46
- /**
47
- * Run a flow on all records of a specific type
48
- */
49
- async runOnRecordType(id, recordType) {
50
- return this.client.post(`/flows/${id}/run-on-record-type`, {
51
- recordType,
52
- });
53
- }
54
- /**
55
- * Publish flow (promote draft to published)
56
- */
57
- async publish(id) {
58
- return this.client.post(`/flows/${id}/publish`);
59
- }
60
- }
61
- exports.FlowsEndpoint = FlowsEndpoint;
62
- /**
63
- * Prompts endpoint handlers
64
- */
65
- class PromptsEndpoint {
66
- constructor(client) {
67
- this.client = client;
68
- }
69
- /**
70
- * List all prompts for the authenticated user
71
- */
72
- async list(params) {
73
- return this.client.get('/prompts', params);
74
- }
75
- /**
76
- * Get a specific prompt by ID
77
- */
78
- async get(id) {
79
- return this.client.get(`/prompts/${id}`);
80
- }
81
- /**
82
- * Create a new prompt
83
- */
84
- async create(data) {
85
- return this.client.post('/prompts', data);
86
- }
87
- /**
88
- * Update an existing prompt
89
- */
90
- async update(id, data) {
91
- return this.client.put(`/prompts/${id}`, data);
92
- }
93
- /**
94
- * Delete a prompt
95
- */
96
- async delete(id) {
97
- return this.client.delete(`/prompts/${id}`);
98
- }
99
- /**
100
- * Run a prompt on a specific record
101
- */
102
- async runOnRecord(id, recordId) {
103
- return this.client.post(`/prompts/${id}/run-on-record`, { recordId });
104
- }
105
- /**
106
- * Get flows using this prompt
107
- */
108
- async getFlows(id) {
109
- return this.client.get(`/prompts/${id}/flows`);
110
- }
111
- /**
112
- * Update flow attachments for a prompt
113
- */
114
- async updateFlows(id, flowIds) {
115
- return this.client.put(`/prompts/${id}/flows`, { flowIds });
116
- }
117
- }
118
- exports.PromptsEndpoint = PromptsEndpoint;
119
- /**
120
- * Records endpoint handlers
121
- */
122
- class RecordsEndpoint {
123
- constructor(client) {
124
- this.client = client;
125
- }
126
- /**
127
- * List all records for the authenticated user
128
- */
129
- async list(params) {
130
- return this.client.get('/records', params);
131
- }
132
- /**
133
- * Get a specific record by ID
134
- */
135
- async get(id) {
136
- return this.client.get(`/records/${id}`);
137
- }
138
- /**
139
- * Create a new record
140
- */
141
- async create(data) {
142
- return this.client.post('/records', data);
143
- }
144
- /**
145
- * Update an existing record
146
- */
147
- async update(id, data) {
148
- return this.client.put(`/records/${id}`, data);
149
- }
150
- /**
151
- * Delete a record
152
- */
153
- async delete(id) {
154
- return this.client.delete(`/records/${id}`);
155
- }
156
- /**
157
- * Bulk delete multiple records
158
- */
159
- async bulkDelete(ids) {
160
- return this.client.post('/records/bulk-delete', { ids });
161
- }
162
- /**
163
- * Bulk edit multiple records
164
- */
165
- async bulkEdit(data) {
166
- return this.client.post('/records/bulk-edit', data);
167
- }
168
- /**
169
- * Get results for a record
170
- */
171
- async getResults(id, params) {
172
- return this.client.get(`/records/${id}/results`, params);
173
- }
174
- /**
175
- * Delete a specific result for a record
176
- */
177
- async deleteResult(id, resultId) {
178
- return this.client.delete(`/records/${id}/results`, { resultId });
179
- }
180
- /**
181
- * Upload CSV file to create multiple records
182
- */
183
- async uploadCsv(file, params) {
184
- const formData = new FormData();
185
- formData.append('file', file);
186
- if (params?.typeColumn) {
187
- formData.append('typeColumn', params.typeColumn);
188
- }
189
- if (params?.nameColumn) {
190
- formData.append('nameColumn', params.nameColumn);
191
- }
192
- return this.client.postFormData('/records/upload-csv', formData);
193
- }
194
- /**
195
- * Get record types (distinct values)
196
- */
197
- async getTypes() {
198
- return this.client.get('/records?distinct=types');
199
- }
200
- /**
201
- * Get example record by type and/or name
202
- */
203
- async getExample(params) {
204
- return this.client.get('/records', {
205
- ...params,
206
- includeFields: true,
207
- limit: 1,
208
- });
209
- }
210
- }
211
- exports.RecordsEndpoint = RecordsEndpoint;
212
- /**
213
- * API Keys endpoint handlers
214
- */
215
- class ApiKeysEndpoint {
216
- constructor(client) {
217
- this.client = client;
218
- }
219
- /**
220
- * List all API keys for the authenticated user
221
- */
222
- async list() {
223
- const response = await this.client.get('/api-keys');
224
- return response.apiKeys;
225
- }
226
- /**
227
- * Get a specific API key by ID
228
- */
229
- async get(id) {
230
- return this.client.get(`/api-keys/${id}`);
231
- }
232
- /**
233
- * Create a new API key
234
- */
235
- async create(data) {
236
- return this.client.post('/api-keys', data);
237
- }
238
- /**
239
- * Update an existing API key
240
- */
241
- async update(id, data) {
242
- return this.client.put(`/api-keys/${id}`, data);
243
- }
244
- /**
245
- * Delete an API key
246
- */
247
- async delete(id) {
248
- return this.client.delete(`/api-keys/${id}`);
249
- }
250
- /**
251
- * Regenerate an API key
252
- */
253
- async regenerate(id) {
254
- return this.client.post(`/api-keys/${id}/regenerate`);
255
- }
256
- /**
257
- * Get API key analytics
258
- */
259
- async getAnalytics(id) {
260
- return this.client.get(`/api-keys/${id}/analytics`);
261
- }
262
- /**
263
- * Get usage logs for an API key
264
- */
265
- async getUsage(id, params) {
266
- return this.client.get(`/api-keys/${id}/usage`, params);
267
- }
268
- /**
269
- * Get API key analytics (all keys or specific key)
270
- */
271
- async getAnalyticsEnhanced(apiKeyId, params) {
272
- const endpoint = apiKeyId === 'all' ? '/api-keys/analytics' : `/api-keys/${apiKeyId}/analytics`;
273
- return this.client.get(endpoint, params);
274
- }
275
- /**
276
- * Get API key usage logs (all keys or specific key)
277
- */
278
- async getLogs(apiKeyId, params) {
279
- const endpoint = apiKeyId === 'all' ? '/api-keys/logs' : `/api-keys/${apiKeyId}/logs`;
280
- return this.client.get(endpoint, params);
281
- }
282
- /**
283
- * Get API key permission options
284
- */
285
- async getPermissionOptions() {
286
- return this.client.get('/api-keys/options');
287
- }
288
- /**
289
- * Get API key security logs
290
- */
291
- async getSecurityLogs(id) {
292
- return this.client.get(`/api-keys/${id}/security-logs`);
293
- }
294
- /**
295
- * Update API key security settings
296
- */
297
- async updateSecurity(id, data) {
298
- return this.client.put(`/api-keys/${id}/security`, data);
299
- }
300
- /**
301
- * Clear suspicious activity for API key
302
- */
303
- async clearSuspiciousActivity(id) {
304
- return this.client.post(`/api-keys/${id}/clear-suspicious`);
305
- }
306
- }
307
- exports.ApiKeysEndpoint = ApiKeysEndpoint;
308
- /**
309
- * Model Configurations endpoint handlers
310
- */
311
- class ModelConfigsEndpoint {
312
- constructor(client) {
313
- this.client = client;
314
- }
315
- /**
316
- * Get available models catalog
317
- */
318
- async getAvailable() {
319
- const response = await this.client.get('/model-configs/available');
320
- // Handle both wrapped and direct array responses
321
- return Array.isArray(response) ? response : response.data || [];
322
- }
323
- /**
324
- * Get search-capable models (all available, regardless of user configuration)
325
- */
326
- async getSearchCapable() {
327
- const response = await this.client.get('/model-configs/search-capable');
328
- return response.data || [];
329
- }
330
- /**
331
- * Get configured search-capable models (only user's configured and enabled models)
332
- */
333
- async getSearchConfigured() {
334
- const response = await this.client.get('/model-configs/search-configured');
335
- return response.data || [];
336
- }
337
- /**
338
- * List user's model configurations
339
- */
340
- async list() {
341
- const response = await this.client.get('/model-configs');
342
- // Handle both wrapped and direct array responses
343
- return Array.isArray(response) ? response : response.data || [];
344
- }
345
- /**
346
- * Create a new model configuration
347
- */
348
- async create(data) {
349
- return this.client.post('/model-configs', data);
350
- }
351
- /**
352
- * Update an existing model configuration
353
- */
354
- async update(id, data) {
355
- return this.client.put(`/model-configs/${id}`, data);
356
- }
357
- /**
358
- * Delete a model configuration
359
- */
360
- async delete(id) {
361
- return this.client.delete(`/model-configs/${id}`);
362
- }
363
- /**
364
- * Enable/disable a model configuration
365
- */
366
- async updateStatus(id, isEnabled) {
367
- return this.client.patch(`/model-configs/${id}/status`, { isEnabled });
368
- }
369
- /**
370
- * Set a model configuration as default
371
- */
372
- async setDefault(id) {
373
- return this.client.patch(`/model-configs/${id}/default`);
374
- }
375
- /**
376
- * Get usage statistics
377
- */
378
- async getUsage() {
379
- return this.client.get('/model-configs/usage');
380
- }
381
- }
382
- exports.ModelConfigsEndpoint = ModelConfigsEndpoint;
383
- /**
384
- * Dispatch endpoint handler for atomic record/flow creation and execution
385
- */
386
- class DispatchEndpoint {
387
- constructor(client) {
388
- this.client = client;
389
- }
390
- /**
391
- * Dispatch: create and/or execute flows on records atomically
392
- */
393
- async execute(data) {
394
- return this.client.post('/dispatch', data);
395
- }
396
- /**
397
- * Dispatch with streaming response
398
- */
399
- async executeStream(data) {
400
- return this.client.requestStream('/dispatch', {
401
- method: 'POST',
402
- body: JSON.stringify(data),
403
- });
404
- }
405
- /**
406
- * Resume paused flow execution
407
- * API expects snake_case field names
408
- *
409
- * @param data.execution_id - The execution ID to resume
410
- * @param data.tool_outputs - Tool outputs to inject into the flow
411
- * @param data.stream_response - Whether to stream the response
412
- * @param data.messages - Optional messages to override the original dispatch messages
413
- */
414
- async resume(data) {
415
- if (data.streamResponse) {
416
- return this.client.requestStream('/dispatch/resume', {
417
- method: 'POST',
418
- body: JSON.stringify(data),
419
- });
420
- }
421
- return this.client.post('/dispatch/resume', data);
422
- }
423
- /**
424
- * Evaluate a model-proposed runtime tool against a configurable allowlist policy.
425
- * Useful for local `propose_runtime_tool` handlers before redispatch.
426
- */
427
- gateGeneratedRuntimeToolProposal(proposal, options) {
428
- return (0, generated_tool_gate_1.evaluateGeneratedRuntimeToolProposal)(proposal, options);
429
- }
430
- /**
431
- * Build standardized local-tool output for a generated tool proposal.
432
- * Returns `{ approved, reason, violations, tool? }`.
433
- */
434
- buildGeneratedRuntimeToolGateOutput(proposal, options) {
435
- return (0, generated_tool_gate_1.buildGeneratedRuntimeToolGateOutput)(proposal, options);
436
- }
437
- /**
438
- * Attach approved runtime tools to a prompt step in a redispatch request.
439
- * Returns a new request object and does not mutate the original.
440
- */
441
- attachApprovedRuntimeTools(request, runtimeTools, options) {
442
- return (0, generated_tool_gate_1.attachRuntimeToolsToDispatchRequest)(request, runtimeTools, options);
443
- }
444
- /**
445
- * Validate a generated runtime tool proposal and attach it to the redispatch
446
- * request if approved, in one call.
447
- */
448
- applyGeneratedRuntimeToolProposal(request, proposal, options) {
449
- return (0, generated_tool_gate_1.applyGeneratedRuntimeToolProposalToDispatchRequest)(request, proposal, options);
450
- }
451
- }
452
- exports.DispatchEndpoint = DispatchEndpoint;
453
- /**
454
- * Chat endpoint handler
455
- */
456
- class ChatEndpoint {
457
- constructor(client) {
458
- this.client = client;
459
- }
460
- /**
461
- * Send a chat message
462
- */
463
- async send(message) {
464
- return this.client.post('/chat', { message });
465
- }
466
- /**
467
- * Send a chat message with streaming response
468
- */
469
- async sendStream(message, options) {
470
- return this.client.requestStream('/chat', {
471
- method: 'POST',
472
- body: JSON.stringify({ message, ...options }),
473
- });
474
- }
475
- }
476
- exports.ChatEndpoint = ChatEndpoint;
477
- /**
478
- * Users endpoint handlers
479
- */
480
- class UsersEndpoint {
481
- constructor(client) {
482
- this.client = client;
483
- }
484
- /**
485
- * Get current user profile
486
- */
487
- async getProfile() {
488
- return this.client.get('/users/profile');
489
- }
490
- /**
491
- * Update user profile
492
- */
493
- async updateProfile(data) {
494
- return this.client.put('/users/profile', data);
495
- }
496
- }
497
- exports.UsersEndpoint = UsersEndpoint;
498
- /**
499
- * Analytics endpoint handlers
500
- */
501
- class AnalyticsEndpoint {
502
- constructor(client) {
503
- this.client = client;
504
- }
505
- /**
506
- * Get analytics stats
507
- */
508
- async getStats(params) {
509
- return this.client.get('/analytics/stats', params);
510
- }
511
- /**
512
- * Get analytics executions
513
- */
514
- async getExecutions(params) {
515
- return this.client.get('/analytics/record-results', params);
516
- }
517
- /**
518
- * Get all record results (same as executions)
519
- */
520
- async getAllRecordResults(params) {
521
- return this.client.get('/analytics/record-results', params);
522
- }
523
- /**
524
- * Get model usage analytics
525
- */
526
- async getModelUsage(params) {
527
- return this.client.get('/model-usage', params);
528
- }
529
- }
530
- exports.AnalyticsEndpoint = AnalyticsEndpoint;
531
- /**
532
- * Flow Steps endpoint handlers
533
- *
534
- * @deprecated Flow steps are now consolidated into the flows endpoint.
535
- * Use `flows.get(id)` to get a flow with embedded `flowSteps`.
536
- * Use `flows.update(id, { flow_steps: [...] })` to update flow steps.
537
- */
538
- class FlowStepsEndpoint {
539
- constructor(client) {
540
- this.client = client;
541
- }
542
- /**
543
- * Get flow steps for a flow
544
- * @deprecated Use `flows.get(flowId)` instead - flow steps are now embedded in the flow response as `flowSteps`
545
- */
546
- async getByFlow(flowId) {
547
- console.warn('[Runtype SDK] flowSteps.getByFlow() is deprecated. Use flows.get(flowId) instead - flow steps are now embedded in the flow response as flowSteps.');
548
- return this.client.get(`/flow-steps/flow/${flowId}`);
549
- }
550
- /**
551
- * Get a specific flow step
552
- * @deprecated Use `flows.get(flowId)` and find the step in `flowSteps` array
553
- */
554
- async get(id) {
555
- console.warn('[Runtype SDK] flowSteps.get() is deprecated. Use flows.get(flowId) and find the step in flowSteps array.');
556
- return this.client.get(`/flow-steps/${id}`);
557
- }
558
- /**
559
- * Create a flow step
560
- * @deprecated Use `flows.update(flowId, { flow_steps: [...] })` to add steps
561
- */
562
- async create(data) {
563
- console.warn('[Runtype SDK] flowSteps.create() is deprecated. Use flows.update(flowId, { flow_steps: [...] }) to add steps.');
564
- return this.client.post('/flow-steps', data);
565
- }
566
- /**
567
- * Update a flow step
568
- * @deprecated Use `flows.update(flowId, { flow_steps: [...] })` to update steps
569
- */
570
- async update(id, data) {
571
- console.warn('[Runtype SDK] flowSteps.update() is deprecated. Use flows.update(flowId, { flow_steps: [...] }) to update steps.');
572
- return this.client.put(`/flow-steps/${id}`, data);
573
- }
574
- /**
575
- * Delete a flow step
576
- * @deprecated Use `flows.update(flowId, { flow_steps: [...] })` with the step removed
577
- */
578
- async delete(id) {
579
- console.warn('[Runtype SDK] flowSteps.delete() is deprecated. Use flows.update(flowId, { flow_steps: [...] }) with the step removed.');
580
- return this.client.delete(`/flow-steps/${id}`);
581
- }
582
- /**
583
- * Reorder flow steps
584
- * @deprecated Use `flows.update(flowId, { flow_steps: [...] })` with updated order values
585
- */
586
- async reorder(flowId, stepOrders) {
587
- console.warn('[Runtype SDK] flowSteps.reorder() is deprecated. Use flows.update(flowId, { flow_steps: [...] }) with updated order values.');
588
- return this.client.post('/flow-steps/reorder', {
589
- flowId,
590
- stepOrders,
591
- });
592
- }
593
- }
594
- exports.FlowStepsEndpoint = FlowStepsEndpoint;
595
- /**
596
- * Context Templates endpoint handlers
597
- */
598
- class ContextTemplatesEndpoint {
599
- constructor(client) {
600
- this.client = client;
601
- }
602
- /**
603
- * List context templates
604
- */
605
- async list(params) {
606
- return this.client.get('/context-templates', params);
607
- }
608
- /**
609
- * Get a specific context template
610
- */
611
- async get(id) {
612
- return this.client.get(`/context-templates/${id}`);
613
- }
614
- /**
615
- * Create a context template
616
- */
617
- async create(data) {
618
- return this.client.post('/context-templates', data);
619
- }
620
- /**
621
- * Update a context template
622
- */
623
- async update(id, data) {
624
- return this.client.put(`/context-templates/${id}`, data);
625
- }
626
- /**
627
- * Delete a context template
628
- */
629
- async delete(id) {
630
- return this.client.delete(`/context-templates/${id}`);
631
- }
632
- }
633
- exports.ContextTemplatesEndpoint = ContextTemplatesEndpoint;
634
- /**
635
- * Tools endpoint handlers
636
- */
637
- class ToolsEndpoint {
638
- constructor(client) {
639
- this.client = client;
640
- }
641
- /**
642
- * List all tools for the authenticated user
643
- */
644
- async list(params) {
645
- return this.client.get('/tools', params);
646
- }
647
- /**
648
- * Get a specific tool by ID
649
- */
650
- async get(id) {
651
- return this.client.get(`/tools/${id}`);
652
- }
653
- /**
654
- * Create a new tool
655
- */
656
- async create(data) {
657
- return this.client.post('/tools', data);
658
- }
659
- /**
660
- * Update an existing tool
661
- */
662
- async update(id, data) {
663
- return this.client.put(`/tools/${id}`, data);
664
- }
665
- /**
666
- * Delete a tool
667
- */
668
- async delete(id) {
669
- return this.client.delete(`/tools/${id}`);
670
- }
671
- /**
672
- * Execute a tool
673
- */
674
- async execute(id, data) {
675
- return this.client.post(`/tools/${id}/execute`, data);
676
- }
677
- /**
678
- * Execute a tool with streaming response
679
- */
680
- async executeStream(id, data) {
681
- return this.client.requestStream(`/tools/${id}/execute`, {
682
- method: 'POST',
683
- body: JSON.stringify(data),
684
- });
685
- }
686
- /**
687
- * Test a tool (same as execute but for testing purposes)
688
- */
689
- async test(id, data) {
690
- return this.client.post(`/tools/${id}/test`, data);
691
- }
692
- /**
693
- * Get tool executions for a specific tool
694
- */
695
- async getExecutions(toolId, params) {
696
- return this.client.get(`/tools/${toolId}/executions`, params);
697
- }
698
- /**
699
- * Get AI SDK compatible tool schemas
700
- */
701
- async getSchemas(params) {
702
- return this.client.get('/tools/schema', params);
703
- }
704
- /**
705
- * Get available tools for prompts
706
- */
707
- async getAvailable() {
708
- const response = await this.client.get('/tools', {
709
- isActive: true,
710
- limit: 200,
711
- });
712
- const payload = response;
713
- if (Array.isArray(payload?.data)) {
714
- return payload.data;
715
- }
716
- if (Array.isArray(payload)) {
717
- return payload;
718
- }
719
- return [];
720
- }
721
- /**
722
- * Convert a flow to a tool
723
- */
724
- async convertFromFlow(flowId, data) {
725
- return this.client.post(`/flows/${flowId}/convert-to-tool`, data);
726
- }
727
- /**
728
- * Get all built-in tools
729
- */
730
- async getBuiltInTools() {
731
- return this.client.get('/tools/builtin');
732
- }
733
- /**
734
- * Get built-in tools compatible with a specific model and provider
735
- */
736
- async getCompatibleBuiltInTools(model, provider) {
737
- return this.client.get('/tools/builtin/compatible', {
738
- model,
739
- provider,
740
- });
741
- }
742
- /**
743
- * Get parameter schema for a specific built-in tool
744
- */
745
- async getBuiltInToolSchema(toolId) {
746
- return this.client.get(`/tools/builtin/${toolId}/schema`);
747
- }
748
- }
749
- exports.ToolsEndpoint = ToolsEndpoint;
750
- /**
751
- * Eval endpoint handlers
752
- */
753
- class EvalEndpoint {
754
- constructor(client) {
755
- this.client = client;
756
- }
757
- /**
758
- * Run virtual eval with streaming response
759
- * Executes multiple eval configs simultaneously and streams results via multiplexed SSE
760
- */
761
- async runVirtualEval(data) {
762
- return this.client.requestStream('/eval/stream', {
763
- method: 'POST',
764
- body: JSON.stringify(data),
765
- });
766
- }
767
- }
768
- exports.EvalEndpoint = EvalEndpoint;
769
- /**
770
- * Client Tokens endpoint handlers
771
- *
772
- * Manages client tokens for secure browser-to-API communication.
773
- * Client tokens enable embedding chat widgets in external applications.
774
- */
775
- class ClientTokensEndpoint {
776
- constructor(client) {
777
- this.client = client;
778
- }
779
- /**
780
- * List all client tokens for the authenticated user
781
- */
782
- async list() {
783
- const response = await this.client.get('/client-tokens');
784
- return response.clientTokens;
785
- }
786
- /**
787
- * Get a specific client token by ID
788
- */
789
- async get(id) {
790
- return this.client.get(`/client-tokens/${id}`);
791
- }
792
- /**
793
- * Create a new client token
794
- *
795
- * @returns The created token with the plain token value (shown only once)
796
- */
797
- async create(data) {
798
- return this.client.post('/client-tokens', data);
799
- }
800
- /**
801
- * Update an existing client token
802
- */
803
- async update(id, data) {
804
- return this.client.put(`/client-tokens/${id}`, data);
805
- }
806
- /**
807
- * Delete a client token
808
- */
809
- async delete(id) {
810
- return this.client.delete(`/client-tokens/${id}`);
811
- }
812
- /**
813
- * Regenerate a client token's value
814
- *
815
- * @returns The updated token with the new plain token value (shown only once)
816
- */
817
- async regenerate(id) {
818
- return this.client.post(`/client-tokens/${id}/regenerate`);
819
- }
820
- /**
821
- * Get the plain token value for a client token
822
- *
823
- * Note: Only works if the token was just created or regenerated in the same session
824
- */
825
- async getToken(id) {
826
- return this.client.get(`/client-tokens/${id}/token`);
827
- }
828
- /**
829
- * List conversations for a client token
830
- */
831
- async listConversations(id, params) {
832
- return this.client.get(`/client-tokens/${id}/conversations`, params);
833
- }
834
- }
835
- exports.ClientTokensEndpoint = ClientTokensEndpoint;
836
- /**
837
- * Parse SSE stream chunks into individual events with event type support
838
- */
839
- function parseSSEChunkWithEventType(chunk, buffer) {
840
- buffer += chunk;
841
- // Split on double newlines to get complete events
842
- const parts = buffer.split('\n\n');
843
- const remainingBuffer = parts.pop() || '';
844
- const events = [];
845
- for (const part of parts) {
846
- if (!part.trim())
847
- continue;
848
- const lines = part.split('\n');
849
- let eventType = null;
850
- let dataStr = null;
851
- for (const line of lines) {
852
- if (line.startsWith('event: ')) {
853
- eventType = line.slice(7).trim();
854
- }
855
- else if (line.startsWith('data: ')) {
856
- dataStr = line.slice(6).trim();
857
- }
858
- }
859
- if (dataStr && dataStr !== '[DONE]') {
860
- try {
861
- const data = JSON.parse(dataStr);
862
- events.push({ eventType, data });
863
- }
864
- catch {
865
- // Invalid JSON, skip
866
- }
867
- }
868
- }
869
- return { events, remainingBuffer };
870
- }
871
- /**
872
- * Dispatch a parsed agent event to the appropriate callback
873
- */
874
- function dispatchAgentEvent(event, callbacks) {
875
- const { eventType, data } = event;
876
- const typedData = data;
877
- // If no event type, try to get it from the data
878
- const type = eventType || typedData?.type;
879
- // @snake-case-ok-start: Agent event type identifiers use snake_case to match flow events
880
- switch (type) {
881
- case 'agent_start':
882
- callbacks.onAgentStart?.(typedData);
883
- break;
884
- case 'agent_iteration_start':
885
- callbacks.onIterationStart?.(typedData);
886
- break;
887
- case 'agent_turn_start':
888
- callbacks.onTurnStart?.(typedData);
889
- break;
890
- case 'agent_turn_delta':
891
- callbacks.onTurnDelta?.(typedData);
892
- break;
893
- case 'agent_turn_complete':
894
- callbacks.onTurnComplete?.(typedData);
895
- break;
896
- case 'agent_tool_start':
897
- callbacks.onToolStart?.(typedData);
898
- break;
899
- case 'agent_tool_delta':
900
- callbacks.onToolDelta?.(typedData);
901
- break;
902
- case 'agent_tool_complete':
903
- callbacks.onToolComplete?.(typedData);
904
- break;
905
- case 'agent_iteration_complete':
906
- callbacks.onIterationComplete?.(typedData);
907
- break;
908
- case 'agent_reflection':
909
- callbacks.onReflection?.(typedData);
910
- break;
911
- case 'agent_complete':
912
- callbacks.onAgentComplete?.(typedData);
913
- break;
914
- case 'agent_error':
915
- callbacks.onError?.(typedData);
916
- break;
917
- case 'agent_await':
918
- callbacks.onAgentPaused?.(typedData);
919
- break;
920
- case 'agent_ping':
921
- callbacks.onPing?.(typedData);
922
- break;
923
- default:
924
- callbacks.onUnknownEvent?.(event);
925
- }
926
- // @snake-case-ok-end
927
- }
928
- /**
929
- * Process agent stream with callbacks
930
- */
931
- async function processAgentStream(body, callbacks) {
932
- if (!body)
933
- return;
934
- const reader = body.getReader();
935
- const decoder = new TextDecoder();
936
- let buffer = '';
937
- try {
938
- while (true) {
939
- const { done, value } = await reader.read();
940
- if (done) {
941
- // Process any remaining buffer
942
- if (buffer.trim()) {
943
- const { events } = parseSSEChunkWithEventType(buffer + '\n\n', '');
944
- for (const event of events) {
945
- dispatchAgentEvent(event, callbacks);
946
- }
947
- }
948
- break;
949
- }
950
- const chunk = decoder.decode(value, { stream: true });
951
- const { events, remainingBuffer } = parseSSEChunkWithEventType(chunk, buffer);
952
- buffer = remainingBuffer;
953
- for (const event of events) {
954
- dispatchAgentEvent(event, callbacks);
955
- }
956
- }
957
- }
958
- finally {
959
- reader.releaseLock();
960
- }
961
- }
962
- const GENERATED_RUNTIME_TOOL_PROPOSAL_SCHEMA = {
963
- type: 'object',
964
- properties: {
965
- name: {
966
- type: 'string',
967
- description: 'Tool name. Use letters/numbers/underscore only.',
968
- },
969
- description: {
970
- type: 'string',
971
- description: 'Clear description of what the generated tool does.',
972
- },
973
- toolType: {
974
- type: 'string',
975
- enum: ['custom'],
976
- description: 'Must be "custom" for generated code execution tools.',
977
- },
978
- parametersSchema: {
979
- type: 'object',
980
- description: 'JSON schema for tool call arguments.',
981
- },
982
- config: {
983
- type: 'object',
984
- description: 'Runtime tool config including code, sandboxProvider, language, and timeout.',
985
- },
986
- reason: {
987
- type: 'string',
988
- description: 'Why this tool is needed.',
989
- },
990
- },
991
- required: ['name', 'description', 'toolType', 'parametersSchema', 'config'],
992
- };
993
- function appendRuntimeToolsToAgentRequest(request, runtimeTools) {
994
- const existing = request.tools?.runtimeTools || [];
995
- const existingNames = new Set(existing.map((tool) => tool.name));
996
- const converted = runtimeTools
997
- .filter((tool) => !existingNames.has(tool.name))
998
- .map((tool) => ({
999
- name: tool.name,
1000
- description: tool.description,
1001
- toolType: tool.toolType,
1002
- parametersSchema: tool.parametersSchema,
1003
- ...(tool.config ? { config: tool.config } : {}),
1004
- }));
1005
- return {
1006
- ...request,
1007
- tools: {
1008
- ...request.tools,
1009
- runtimeTools: [...existing, ...converted],
1010
- },
1011
- };
1012
- }
1013
- /**
1014
- * Agents endpoint handlers
1015
- */
1016
- class AgentsEndpoint {
1017
- constructor(client) {
1018
- this.client = client;
1019
- }
1020
- /**
1021
- * List all agents for the authenticated user
1022
- */
1023
- async list(params) {
1024
- return this.client.get('/agents', params);
1025
- }
1026
- /**
1027
- * Get a specific agent by ID
1028
- */
1029
- async get(id) {
1030
- return this.client.get(`/agents/${id}`);
1031
- }
1032
- /**
1033
- * Create a new agent
1034
- */
1035
- async create(data) {
1036
- return this.client.post('/agents', data);
1037
- }
1038
- /**
1039
- * Update an existing agent
1040
- */
1041
- async update(id, data) {
1042
- return this.client.put(`/agents/${id}`, data);
1043
- }
1044
- /**
1045
- * Delete an agent
1046
- */
1047
- async delete(id) {
1048
- return this.client.delete(`/agents/${id}`);
1049
- }
1050
- /**
1051
- * Evaluate a model-proposed runtime tool against a configurable allowlist policy.
1052
- * Useful for local `propose_runtime_tool` handlers before follow-up execution.
1053
- */
1054
- gateGeneratedRuntimeToolProposal(proposal, options) {
1055
- return (0, generated_tool_gate_1.evaluateGeneratedRuntimeToolProposal)(proposal, options);
1056
- }
1057
- /**
1058
- * Build standardized local-tool output for a generated tool proposal.
1059
- * Returns `{ approved, reason, violations, tool? }`.
1060
- */
1061
- buildGeneratedRuntimeToolGateOutput(proposal, options) {
1062
- return (0, generated_tool_gate_1.buildGeneratedRuntimeToolGateOutput)(proposal, options);
1063
- }
1064
- /**
1065
- * Create a local tool definition that validates model-proposed runtime tools.
1066
- * Plug this into `executeWithLocalTools()` under a name like `propose_runtime_tool`.
1067
- */
1068
- createGeneratedRuntimeToolGateLocalTool(options) {
1069
- const { description, ...gateOptions } = options || {};
1070
- return {
1071
- description: description ||
1072
- 'Validate a generated runtime custom tool and return { approved, reason, violations, tool? }',
1073
- parametersSchema: GENERATED_RUNTIME_TOOL_PROPOSAL_SCHEMA,
1074
- execute: async (args) => (0, generated_tool_gate_1.buildGeneratedRuntimeToolGateOutput)(args, gateOptions),
1075
- };
1076
- }
1077
- /**
1078
- * Attach approved runtime tools to an agent execute request.
1079
- * Returns a new request object and does not mutate the original.
1080
- */
1081
- attachApprovedRuntimeTools(request, runtimeTools) {
1082
- return appendRuntimeToolsToAgentRequest(request, runtimeTools);
1083
- }
1084
- /**
1085
- * Validate a generated runtime tool proposal and append it to an agent execute
1086
- * request if approved, in one call.
1087
- */
1088
- applyGeneratedRuntimeToolProposal(request, proposal, options) {
1089
- const decision = (0, generated_tool_gate_1.evaluateGeneratedRuntimeToolProposal)(proposal, options);
1090
- if (!decision.approved || !decision.tool) {
1091
- return { decision, request };
1092
- }
1093
- return {
1094
- decision,
1095
- request: appendRuntimeToolsToAgentRequest(request, [decision.tool]),
1096
- };
1097
- }
1098
- /**
1099
- * Execute an agent (non-streaming)
1100
- */
1101
- async execute(id, data) {
1102
- return this.client.post(`/agents/${id}/execute`, {
1103
- ...data,
1104
- streamResponse: false,
1105
- });
1106
- }
1107
- /**
1108
- * Execute an agent with streaming response
1109
- *
1110
- * Returns a Response object with SSE stream.
1111
- * Use `executeWithCallbacks` for easier handling.
1112
- *
1113
- * @example
1114
- * ```typescript
1115
- * const response = await client.agents.executeStream('agt_123', {
1116
- * messages: [{ role: 'user', content: 'Write me a poem' }],
1117
- * debugMode: true,
1118
- * })
1119
- *
1120
- * // Process the stream manually
1121
- * const reader = response.body?.getReader()
1122
- * // ...
1123
- * ```
1124
- */
1125
- async executeStream(id, data) {
1126
- return this.client.requestStream(`/agents/${id}/execute`, {
1127
- method: 'POST',
1128
- body: JSON.stringify({
1129
- ...data,
1130
- streamResponse: true,
1131
- }),
1132
- });
1133
- }
1134
- /**
1135
- * Execute an agent with streaming and callbacks
1136
- *
1137
- * Processes the SSE stream and calls the appropriate callbacks for each event type.
1138
- * This is the recommended way to handle agent streaming.
1139
- *
1140
- * @example
1141
- * ```typescript
1142
- * let content = ''
1143
- *
1144
- * const result = await client.agents.executeWithCallbacks('agt_123', {
1145
- * messages: [{ role: 'user', content: 'Write me a poem' }],
1146
- * debugMode: true,
1147
- * }, {
1148
- * onTurnDelta: (event) => {
1149
- * content += event.delta
1150
- * process.stdout.write(event.delta)
1151
- * },
1152
- * onIterationComplete: (event) => {
1153
- * console.log(`\nIteration ${event.iteration} complete`)
1154
- * },
1155
- * onAgentComplete: (event) => {
1156
- * console.log(`\nAgent finished: ${event.stopReason}`)
1157
- * },
1158
- * onError: (event) => {
1159
- * console.error(`Error: ${event.error.message}`)
1160
- * },
1161
- * })
1162
- *
1163
- * console.log('Final result:', result)
1164
- * ```
1165
- */
1166
- async executeWithCallbacks(id, data, callbacks) {
1167
- const response = await this.executeStream(id, data);
1168
- if (!response.ok) {
1169
- const error = await response.json().catch(() => ({ error: 'Unknown error' }));
1170
- throw new Error(error.error || `HTTP ${response.status}`);
1171
- }
1172
- let completeEvent = null;
1173
- await processAgentStream(response.body, {
1174
- ...callbacks,
1175
- onAgentComplete: (event) => {
1176
- completeEvent = event;
1177
- callbacks.onAgentComplete?.(event);
1178
- },
1179
- });
1180
- return completeEvent;
1181
- }
1182
- /**
1183
- * Execute an agent with local tool support (pause/resume loop)
1184
- *
1185
- * When the agent hits a tool with `toolType: 'local'`, the server emits
1186
- * `agent_await`. This method automatically executes the local tool and
1187
- * resumes execution, repeating until the agent completes.
1188
- *
1189
- * @example
1190
- * ```typescript
1191
- * const result = await client.agents.executeWithLocalTools('agt_123', {
1192
- * messages: [{ role: 'user', content: 'Create a file called hello.txt' }],
1193
- * }, {
1194
- * write_file: async ({ path, content }) => {
1195
- * fs.writeFileSync(path, content)
1196
- * return 'ok'
1197
- * },
1198
- * })
1199
- * ```
1200
- */
1201
- async executeWithLocalTools(id, data, localTools, callbacks) {
1202
- // Build runtime tool definitions from local tool schemas and inject into request
1203
- const runtimeTools = Object.entries(localTools).map(([name, def]) => ({
1204
- name,
1205
- description: def.description,
1206
- toolType: 'local',
1207
- parametersSchema: def.parametersSchema,
1208
- }));
1209
- const requestData = {
1210
- ...data,
1211
- tools: {
1212
- ...data.tools,
1213
- runtimeTools: [...(data.tools?.runtimeTools || []), ...runtimeTools],
1214
- },
1215
- };
1216
- const response = await this.executeStream(id, requestData);
1217
- if (!response.ok) {
1218
- const error = await response.json().catch(() => ({ error: 'Unknown error' }));
1219
- throw new Error(error.error || `HTTP ${response.status}`);
1220
- }
1221
- let currentBody = response.body;
1222
- while (true) {
1223
- let pausedEvent = null;
1224
- let completeEvent = null;
1225
- await processAgentStream(currentBody, {
1226
- ...callbacks,
1227
- onAgentPaused: (event) => {
1228
- pausedEvent = event;
1229
- callbacks?.onAgentPaused?.(event);
1230
- },
1231
- onAgentComplete: (event) => {
1232
- completeEvent = event;
1233
- callbacks?.onAgentComplete?.(event);
1234
- },
1235
- });
1236
- if (completeEvent)
1237
- return completeEvent;
1238
- if (pausedEvent) {
1239
- const { toolName, parameters, executionId } = pausedEvent;
1240
- const toolDef = localTools[toolName];
1241
- if (!toolDef) {
1242
- throw new Error(`Local tool "${toolName}" required but not provided`);
1243
- }
1244
- // Recursively unwrap stringified parameters — the server pipeline may
1245
- // double-serialize: object → JSON string → JSON string
1246
- let parsedParams = {};
1247
- let current = parameters;
1248
- for (let i = 0; i < 3; i++) {
1249
- if (typeof current === 'string') {
1250
- try {
1251
- current = JSON.parse(current);
1252
- }
1253
- catch {
1254
- console.warn(`[local-tools] Failed to parse parameters (attempt ${i + 1}):`, typeof current, String(current).slice(0, 200));
1255
- break;
1256
- }
1257
- }
1258
- else {
1259
- break;
1260
- }
1261
- }
1262
- if (current && typeof current === 'object' && !Array.isArray(current)) {
1263
- parsedParams = current;
1264
- }
1265
- else {
1266
- console.warn('[local-tools] Parameters could not be resolved to an object:', typeof current, String(current).slice(0, 200));
1267
- }
1268
- let toolResult;
1269
- try {
1270
- toolResult = await toolDef.execute(parsedParams);
1271
- }
1272
- catch (err) {
1273
- // Return the error as a tool result so the agent can recover
1274
- toolResult = `Error: ${err instanceof Error ? err.message : String(err)}`;
1275
- }
1276
- // Resume via agent resume endpoint
1277
- const resumeResponse = await this.client.requestStream(`/agents/${id}/resume`, {
1278
- method: 'POST',
1279
- body: JSON.stringify({
1280
- executionId,
1281
- toolOutputs: { [toolName]: toolResult },
1282
- streamResponse: true,
1283
- debugMode: data.debugMode,
1284
- }),
1285
- });
1286
- if (!resumeResponse.ok) {
1287
- const error = await resumeResponse.json().catch(() => ({ error: 'Unknown error' }));
1288
- throw new Error(error.error || `HTTP ${resumeResponse.status}`);
1289
- }
1290
- currentBody = resumeResponse.body;
1291
- continue;
1292
- }
1293
- // Stream ended without complete or paused
1294
- return null;
1295
- }
1296
- }
1297
- // ─── Long-Task Agent Execution ───────────────────────────────────────
1298
- /**
1299
- * Run a long-task agent across multiple sessions with automatic state management.
1300
- *
1301
- * Each session is a single agent execution. The SDK drives the loop client-side,
1302
- * calling the agent's execute endpoint repeatedly and accumulating context.
1303
- * Progress is optionally synced to a Runtype record for dashboard visibility.
1304
- *
1305
- * @example
1306
- * ```typescript
1307
- * const result = await client.agents.runTask('agt_123', {
1308
- * message: 'Build a REST API with CRUD endpoints',
1309
- * maxSessions: 20,
1310
- * maxCost: 5.00,
1311
- * trackProgress: true,
1312
- * onSession: (state) => {
1313
- * console.log(`Session ${state.sessionCount}: ${state.lastStopReason} ($${state.totalCost.toFixed(4)})`)
1314
- * },
1315
- * })
1316
- *
1317
- * console.log(`Finished: ${result.status} after ${result.sessionCount} sessions`)
1318
- * ```
1319
- */
1320
- async runTask(id, options) {
1321
- const maxSessions = options.maxSessions ?? 50;
1322
- const maxCost = options.maxCost;
1323
- const useStream = options.stream ?? true;
1324
- // Resolve agent metadata
1325
- const agent = await this.get(id);
1326
- const taskName = typeof options.trackProgress === 'string'
1327
- ? options.trackProgress
1328
- : options.trackProgress
1329
- ? `${agent.name} task`
1330
- : '';
1331
- // Initialize state
1332
- const state = {
1333
- agentId: id,
1334
- agentName: agent.name,
1335
- taskName: taskName || `${agent.name} task`,
1336
- status: 'running',
1337
- sessionCount: 0,
1338
- totalCost: 0,
1339
- lastOutput: '',
1340
- lastStopReason: 'complete',
1341
- sessions: [],
1342
- startedAt: new Date().toISOString(),
1343
- updatedAt: new Date().toISOString(),
1344
- };
1345
- // Track the record ID if we're syncing
1346
- let recordId;
1347
- // Extract local tool names for prompt injection
1348
- const localToolNames = options.localTools ? Object.keys(options.localTools) : undefined;
1349
- // Session loop
1350
- for (let session = 0; session < maxSessions; session++) {
1351
- // Build continuation context for resumed runs (first session only)
1352
- const continuationContext = session === 0 && options.previousMessages
1353
- ? {
1354
- previousMessages: options.previousMessages,
1355
- newUserMessage: options.continuationMessage,
1356
- compact: options.compact,
1357
- }
1358
- : undefined;
1359
- // Store original message on first invocation (not a continuation)
1360
- if (session === 0 && !options.previousMessages) {
1361
- state.originalMessage = options.message;
1362
- }
1363
- // Build messages for this session
1364
- const messages = this.buildSessionMessages(options.message, state, session, maxSessions, localToolNames, continuationContext);
1365
- // Execute one session
1366
- let sessionResult;
1367
- const sessionData = {
1368
- messages,
1369
- debugMode: options.debugMode,
1370
- model: options.model,
1371
- };
1372
- if (useStream && options.localTools) {
1373
- // Local tools require the pause/resume streaming loop
1374
- const completeEvent = await this.executeWithLocalTools(id, sessionData, options.localTools, options.streamCallbacks);
1375
- if (!completeEvent) {
1376
- throw new Error('Agent stream ended without a complete event');
1377
- }
1378
- sessionResult = {
1379
- success: completeEvent.success,
1380
- result: completeEvent.finalOutput || '',
1381
- iterations: completeEvent.iterations,
1382
- totalCost: completeEvent.totalCost || 0,
1383
- stopReason: completeEvent.stopReason,
1384
- error: completeEvent.error,
1385
- };
1386
- }
1387
- else if (useStream && options.streamCallbacks) {
1388
- const completeEvent = await this.executeWithCallbacks(id, sessionData, options.streamCallbacks);
1389
- if (!completeEvent) {
1390
- throw new Error('Agent stream ended without a complete event');
1391
- }
1392
- sessionResult = {
1393
- success: completeEvent.success,
1394
- result: completeEvent.finalOutput || '',
1395
- iterations: completeEvent.iterations,
1396
- totalCost: completeEvent.totalCost || 0,
1397
- stopReason: completeEvent.stopReason,
1398
- error: completeEvent.error,
1399
- };
1400
- }
1401
- else {
1402
- sessionResult = await this.execute(id, sessionData);
1403
- }
1404
- // Update state
1405
- const sessionCost = sessionResult.totalCost;
1406
- state.sessionCount = session + 1;
1407
- state.totalCost += sessionCost;
1408
- state.lastOutput = sessionResult.result;
1409
- state.lastStopReason = sessionResult.stopReason;
1410
- state.updatedAt = new Date().toISOString();
1411
- state.sessions.push({
1412
- index: session + 1,
1413
- cost: sessionCost,
1414
- iterations: sessionResult.iterations,
1415
- stopReason: sessionResult.stopReason,
1416
- outputPreview: sessionResult.result.slice(0, 300),
1417
- completedAt: new Date().toISOString(),
1418
- });
1419
- // Track cost by model
1420
- const modelKey = options.model || 'default';
1421
- if (!state.costByModel)
1422
- state.costByModel = {};
1423
- state.costByModel[modelKey] = (state.costByModel[modelKey] || 0) + sessionCost;
1424
- // Accumulate messages for future continuation
1425
- if (!state.messages)
1426
- state.messages = [];
1427
- state.messages.push(...messages);
1428
- // Also store the assistant's response as a message
1429
- if (sessionResult.result) {
1430
- state.messages.push({ role: 'assistant', content: sessionResult.result });
1431
- }
1432
- // Keep session log trimmed to last 50 entries
1433
- if (state.sessions.length > 50) {
1434
- state.sessions = state.sessions.slice(-50);
1435
- }
1436
- // Check terminal conditions
1437
- if (sessionResult.stopReason === 'complete') {
1438
- state.status = 'complete';
1439
- }
1440
- else if (sessionResult.stopReason === 'error') {
1441
- state.status = 'complete';
1442
- }
1443
- else if (sessionResult.stopReason === 'max_cost') {
1444
- state.status = 'budget_exceeded';
1445
- }
1446
- else if (this.detectTaskCompletion(sessionResult.result)) {
1447
- // Client-side stop-phrase detection for non-loop agents returning 'end_turn'
1448
- state.status = 'complete';
1449
- }
1450
- else if (maxCost && state.totalCost >= maxCost) {
1451
- state.status = 'budget_exceeded';
1452
- }
1453
- else if (session + 1 >= maxSessions) {
1454
- state.status = 'max_sessions';
1455
- }
1456
- // Sync to record if enabled
1457
- if (options.trackProgress) {
1458
- recordId = await this.syncProgressRecord(state, recordId);
1459
- }
1460
- // Notify caller
1461
- if (options.onSession) {
1462
- const shouldStop = await options.onSession(state);
1463
- if (shouldStop === false) {
1464
- state.status = 'paused';
1465
- }
1466
- }
1467
- // Stop if terminal
1468
- if (state.status !== 'running') {
1469
- break;
1470
- }
1471
- }
1472
- return {
1473
- status: state.status,
1474
- sessionCount: state.sessionCount,
1475
- totalCost: state.totalCost,
1476
- lastOutput: state.lastOutput,
1477
- sessions: state.sessions,
1478
- recordId,
1479
- };
1480
- }
1481
- /**
1482
- * Client-side fallback for detecting task completion in agent output.
1483
- * Mirrors the API's detectAutoComplete() for non-loop agents that return 'end_turn'.
1484
- */
1485
- detectTaskCompletion(output) {
1486
- const upper = output.toUpperCase();
1487
- return AgentsEndpoint.STOP_PHRASES.some((phrase) => upper.includes(phrase.toUpperCase()));
1488
- }
1489
- /**
1490
- * Generate a compact summary of prior work for continuation context.
1491
- * Used when compact mode is enabled to keep token usage low.
1492
- */
1493
- generateCompactSummary(state) {
1494
- const sessionSummaries = (state.sessions ?? [])
1495
- .map((s) => `- Session ${s.index}: ${s.stopReason} ($${s.cost.toFixed(4)}) -- ${s.outputPreview.slice(0, 100)}`)
1496
- .join('\n');
1497
- return [
1498
- `Task: ${state.taskName}`,
1499
- `Status: ${state.status}`,
1500
- `Sessions completed: ${state.sessionCount}`,
1501
- `Total cost: $${state.totalCost.toFixed(4)}`,
1502
- '',
1503
- 'Session history:',
1504
- sessionSummaries,
1505
- '',
1506
- 'Last output (truncated):',
1507
- (state.lastOutput || '').slice(0, 1500),
1508
- ].join('\n');
1509
- }
1510
- /**
1511
- * Build messages for a session, injecting progress context for continuation sessions.
1512
- * Optionally accepts continuation context for marathon resume scenarios.
1513
- */
1514
- buildSessionMessages(originalMessage, state, sessionIndex, maxSessions, localToolNames, continuationContext) {
1515
- // Build local tools guidance block when tools are available
1516
- const toolsBlock = localToolNames?.length
1517
- ? [
1518
- '',
1519
- '--- Local Tools ---',
1520
- `You have access to local filesystem tools (${localToolNames.join(', ')}) that execute directly on the user's machine.`,
1521
- 'Use these tools to create working, runnable files — not just code in your response.',
1522
- 'Prefer creating self-contained HTML files that the user can open in a web browser.',
1523
- 'For example, write a single .html file with inline CSS and JavaScript that demonstrates the result.',
1524
- 'Always use write_file to save your output so the user can run it immediately.',
1525
- ].join('\n')
1526
- : '';
1527
- const multiSessionInstruction = `This is a multi-session task (session ${sessionIndex + 1}/${maxSessions}). When you have fully completed the task, end your response with TASK_COMPLETE on its own line.`;
1528
- // Continuation resume: first session of a resumed run with prior context
1529
- if (continuationContext && sessionIndex === 0) {
1530
- const defaultContinueMessage = 'Continue the task. Review your prior work above and proceed with any remaining work. If everything is already complete, respond with TASK_COMPLETE.';
1531
- const userMessage = continuationContext.newUserMessage || defaultContinueMessage;
1532
- if (continuationContext.compact) {
1533
- // Compact mode: summarize prior work instead of full history
1534
- const summary = this.generateCompactSummary(state);
1535
- const messages = [
1536
- {
1537
- role: 'system',
1538
- content: `You are continuing a previously completed task. Here is a summary of prior work:\n\n${summary}\n\nDo NOT redo any of the above work.`,
1539
- },
1540
- {
1541
- role: 'user',
1542
- content: [userMessage, toolsBlock, '', multiSessionInstruction].join('\n'),
1543
- },
1544
- ];
1545
- return messages;
1546
- }
1547
- // Full history mode: replay all previous messages with do-not-redo instruction
1548
- const messages = [
1549
- ...continuationContext.previousMessages,
1550
- {
1551
- role: 'system',
1552
- content: 'IMPORTANT: You are continuing a previously completed task. The conversation above shows your prior work. Do NOT redo any of it. Build on what was already accomplished. If there is nothing new to do, respond with TASK_COMPLETE.',
1553
- },
1554
- {
1555
- role: 'user',
1556
- content: [userMessage, toolsBlock, '', multiSessionInstruction].join('\n'),
1557
- },
1558
- ];
1559
- return messages;
1560
- }
1561
- // First session (non-continuation): user message + completion signal instruction
1562
- if (sessionIndex === 0) {
1563
- const content = [originalMessage, toolsBlock, '', multiSessionInstruction].join('\n');
1564
- return [{ role: 'user', content }];
1565
- }
1566
- // Continuation sessions within a run: inject progress context
1567
- const recentSessions = state.sessions.slice(-5);
1568
- const progressSummary = recentSessions
1569
- .map((s) => ` Session ${s.index}: ${s.stopReason} ($${s.cost.toFixed(4)}) — ${s.outputPreview.slice(0, 100)}`)
1570
- .join('\n');
1571
- const content = [
1572
- originalMessage,
1573
- toolsBlock,
1574
- '',
1575
- `--- Progress (session ${sessionIndex + 1}/${maxSessions}, $${state.totalCost.toFixed(4)} spent) ---`,
1576
- `Previous sessions:`,
1577
- progressSummary,
1578
- '',
1579
- `Last output (do NOT repeat this — build on it):`,
1580
- state.lastOutput.slice(0, 1000),
1581
- '',
1582
- 'Continue where you left off. Do not redo previous work. If the task is already complete, respond with TASK_COMPLETE.',
1583
- ].join('\n');
1584
- return [{ role: 'user', content }];
1585
- }
1586
- /**
1587
- * Upsert a record to sync long-task progress to the dashboard.
1588
- * Creates the record on first call, updates it on subsequent calls.
1589
- */
1590
- async syncProgressRecord(state, existingRecordId) {
1591
- const metadata = {
1592
- agentId: state.agentId,
1593
- agentName: state.agentName,
1594
- status: state.status,
1595
- sessionCount: state.sessionCount,
1596
- totalCost: state.totalCost,
1597
- lastStopReason: state.lastStopReason,
1598
- lastOutputPreview: state.lastOutput.slice(0, 500),
1599
- sessions: state.sessions.slice(-10), // Keep last 10 in the record
1600
- startedAt: state.startedAt,
1601
- updatedAt: state.updatedAt,
1602
- };
1603
- try {
1604
- if (existingRecordId) {
1605
- // Update existing record
1606
- const record = await this.client.put(`/records/${existingRecordId}`, {
1607
- metadata,
1608
- });
1609
- return record.id;
1610
- }
1611
- else {
1612
- // Try to find existing record by type + name first
1613
- const existing = await this.client.get('/records', {
1614
- type: 'agent-task',
1615
- name: state.taskName,
1616
- limit: 1,
1617
- });
1618
- if (existing.data.length > 0) {
1619
- const record = await this.client.put(`/records/${existing.data[0].id}`, {
1620
- metadata,
1621
- });
1622
- return record.id;
1623
- }
1624
- // Create new record
1625
- const record = await this.client.post('/records', {
1626
- type: 'agent-task',
1627
- name: state.taskName,
1628
- metadata,
1629
- });
1630
- return record.id;
1631
- }
1632
- }
1633
- catch {
1634
- // Record sync is best-effort — don't fail the task
1635
- return existingRecordId || '';
1636
- }
1637
- }
1638
- }
1639
- exports.AgentsEndpoint = AgentsEndpoint;
1640
- /** Stop phrases that indicate the agent considers its task complete. */
1641
- AgentsEndpoint.STOP_PHRASES = [
1642
- 'DONE:',
1643
- 'TASK_COMPLETE',
1644
- 'FINISHED',
1645
- '[COMPLETE]',
1646
- 'STATUS: RESOLVED',
1647
- 'STATUS: COMPLETE',
1648
- ];
1649
- //# sourceMappingURL=endpoints.js.map