@perstack/runtime 0.0.70 → 0.0.72
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 +0 -1
- package/dist/bin/cli.js +12 -5
- package/dist/bin/cli.js.map +1 -1
- package/dist/{chunk-3RWT2GPO.js → chunk-BXJGGA3Q.js} +1780 -758
- package/dist/chunk-BXJGGA3Q.js.map +1 -0
- package/dist/chunk-RG4QHAGG.js +935 -0
- package/dist/chunk-RG4QHAGG.js.map +1 -0
- package/dist/lockfile-skill-manager-LG2E4KAZ.js +3 -0
- package/dist/lockfile-skill-manager-LG2E4KAZ.js.map +1 -0
- package/dist/src/index.d.ts +160 -16
- package/dist/src/index.js +8 -6
- package/dist/src/index.js.map +1 -1
- package/package.json +12 -11
- package/dist/chunk-3RWT2GPO.js.map +0 -1
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import { getSkillManagersFromLockfile, getSkillManagers, closeSkillManagers, getSkillManagerByToolName, getToolSet } from './chunk-RG4QHAGG.js';
|
|
2
|
+
import { readFileSync } from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { parseWithFriendlyError, lockfileSchema, runParamsSchema, createRuntimeEvent, knownModels, stopRunByExceededMaxSteps, continueToNextStep, stopRunByDelegate, stopRunByInteractiveTool, stopRunByError, retry, completeRun, finishToolCall, resolveToolResults, attemptCompletion, callDelegate, callInteractiveTool, callTools, resumeToolCalls, finishAllToolCalls, startGeneration, startRun } from '@perstack/core';
|
|
5
|
+
import TOML from 'smol-toml';
|
|
1
6
|
import { createAmazonBedrock } from '@ai-sdk/amazon-bedrock';
|
|
2
7
|
import { createAnthropic } from '@ai-sdk/anthropic';
|
|
3
8
|
import { createAzure } from '@ai-sdk/azure';
|
|
@@ -5,24 +10,19 @@ import { createDeepSeek } from '@ai-sdk/deepseek';
|
|
|
5
10
|
import { createGoogleGenerativeAI } from '@ai-sdk/google';
|
|
6
11
|
import { createVertex } from '@ai-sdk/google-vertex';
|
|
7
12
|
import { createOpenAI } from '@ai-sdk/openai';
|
|
8
|
-
import { runParamsSchema, createRuntimeEvent, knownModels, getFilteredEnv, stopRunByExceededMaxSteps, continueToNextStep, stopRunByDelegate, stopRunByInteractiveTool, retry, completeRun, finishToolCall, resolveToolResults, attemptCompletion, callDelegate, callInteractiveTool, callTools, resumeToolCalls, finishAllToolCalls, startGeneration, startRun } from '@perstack/core';
|
|
9
13
|
import { createOllama } from 'ollama-ai-provider-v2';
|
|
10
14
|
import { ProxyAgent, fetch } from 'undici';
|
|
15
|
+
import { createApiClient } from '@perstack/api-client';
|
|
11
16
|
import { setup, assign, createActor } from 'xstate';
|
|
12
|
-
import { generateText, tool, jsonSchema } from 'ai';
|
|
13
|
-
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
14
|
-
import { McpError } from '@modelcontextprotocol/sdk/types.js';
|
|
15
|
-
import { createId } from '@paralleldrive/cuid2';
|
|
16
|
-
import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
|
|
17
|
-
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
|
18
17
|
import { readFile } from 'fs/promises';
|
|
18
|
+
import { createId } from '@paralleldrive/cuid2';
|
|
19
19
|
import { dedent } from 'ts-dedent';
|
|
20
|
-
import {
|
|
20
|
+
import { APICallError, generateText, streamText } from 'ai';
|
|
21
21
|
|
|
22
22
|
// package.json
|
|
23
23
|
var package_default = {
|
|
24
24
|
name: "@perstack/runtime",
|
|
25
|
-
version: "0.0.
|
|
25
|
+
version: "0.0.72",
|
|
26
26
|
description: "Perstack Runtime",
|
|
27
27
|
author: "Wintermute Technologies, Inc.",
|
|
28
28
|
license: "Apache-2.0",
|
|
@@ -54,21 +54,22 @@ var package_default = {
|
|
|
54
54
|
typecheck: "tsc --noEmit"
|
|
55
55
|
},
|
|
56
56
|
dependencies: {
|
|
57
|
-
"@ai-sdk/amazon-bedrock": "^3.0.
|
|
58
|
-
"@ai-sdk/anthropic": "^2.0.
|
|
59
|
-
"@ai-sdk/azure": "^2.0.
|
|
60
|
-
"@ai-sdk/deepseek": "^1.0.
|
|
61
|
-
"@ai-sdk/google": "^2.0.
|
|
62
|
-
"@ai-sdk/google-vertex": "^3.0.
|
|
63
|
-
"@ai-sdk/openai": "^2.0.
|
|
57
|
+
"@ai-sdk/amazon-bedrock": "^3.0.0",
|
|
58
|
+
"@ai-sdk/anthropic": "^2.0.0",
|
|
59
|
+
"@ai-sdk/azure": "^2.0.0",
|
|
60
|
+
"@ai-sdk/deepseek": "^1.0.0",
|
|
61
|
+
"@ai-sdk/google": "^2.0.0",
|
|
62
|
+
"@ai-sdk/google-vertex": "^3.0.0",
|
|
63
|
+
"@ai-sdk/openai": "^2.0.0",
|
|
64
64
|
"@modelcontextprotocol/sdk": "^1.25.1",
|
|
65
65
|
"@paralleldrive/cuid2": "^3.0.4",
|
|
66
66
|
"@perstack/api-client": "workspace:*",
|
|
67
|
+
"@perstack/base": "workspace:*",
|
|
67
68
|
"@perstack/core": "workspace:*",
|
|
68
69
|
ai: "^5.0.115",
|
|
70
|
+
"ollama-ai-provider-v2": "^1.5.5",
|
|
69
71
|
commander: "^14.0.2",
|
|
70
72
|
dotenv: "^17.2.3",
|
|
71
|
-
"ollama-ai-provider-v2": "^1.5.5",
|
|
72
73
|
"smol-toml": "^1.5.2",
|
|
73
74
|
"ts-dedent": "^2.2.0",
|
|
74
75
|
undici: "^7.16.0",
|
|
@@ -86,6 +87,56 @@ var package_default = {
|
|
|
86
87
|
node: ">=22.0.0"
|
|
87
88
|
}
|
|
88
89
|
};
|
|
90
|
+
function loadLockfile(lockfilePath) {
|
|
91
|
+
try {
|
|
92
|
+
const content = readFileSync(lockfilePath, "utf-8");
|
|
93
|
+
const parsed = TOML.parse(content);
|
|
94
|
+
return parseWithFriendlyError(lockfileSchema, parsed, "perstack.lock");
|
|
95
|
+
} catch {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function isRemoteUrl(configPath) {
|
|
100
|
+
const lower = configPath.toLowerCase();
|
|
101
|
+
return lower.startsWith("https://") || lower.startsWith("http://");
|
|
102
|
+
}
|
|
103
|
+
function findLockfile(configPath) {
|
|
104
|
+
if (configPath) {
|
|
105
|
+
if (isRemoteUrl(configPath)) {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
const configDir = path.dirname(path.resolve(process.cwd(), configPath));
|
|
109
|
+
return path.join(configDir, "perstack.lock");
|
|
110
|
+
}
|
|
111
|
+
return findLockfileRecursively(process.cwd());
|
|
112
|
+
}
|
|
113
|
+
function findLockfileRecursively(cwd) {
|
|
114
|
+
const lockfilePath = path.resolve(cwd, "perstack.lock");
|
|
115
|
+
try {
|
|
116
|
+
readFileSync(lockfilePath);
|
|
117
|
+
return lockfilePath;
|
|
118
|
+
} catch {
|
|
119
|
+
if (cwd === path.parse(cwd).root) {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
return findLockfileRecursively(path.dirname(cwd));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function getLockfileExpertToolDefinitions(lockfileExpert) {
|
|
126
|
+
const result = {};
|
|
127
|
+
for (const toolDef of lockfileExpert.toolDefinitions) {
|
|
128
|
+
if (!result[toolDef.skillName]) {
|
|
129
|
+
result[toolDef.skillName] = [];
|
|
130
|
+
}
|
|
131
|
+
result[toolDef.skillName].push({
|
|
132
|
+
skillName: toolDef.skillName,
|
|
133
|
+
name: toolDef.name,
|
|
134
|
+
description: toolDef.description,
|
|
135
|
+
inputSchema: toolDef.inputSchema
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
return result;
|
|
139
|
+
}
|
|
89
140
|
function createProxyFetch(proxyUrl) {
|
|
90
141
|
const agent = new ProxyAgent(proxyUrl);
|
|
91
142
|
return (input, init) => {
|
|
@@ -217,523 +268,136 @@ function sumUsage(a, b) {
|
|
|
217
268
|
};
|
|
218
269
|
}
|
|
219
270
|
|
|
220
|
-
// src/
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
throw new Error(`Skill ${this.name} is already initialized`);
|
|
239
|
-
}
|
|
240
|
-
if (this._initializing) {
|
|
241
|
-
throw new Error(`Skill ${this.name} is already initializing`);
|
|
242
|
-
}
|
|
243
|
-
const initPromise = this._performInit();
|
|
244
|
-
this._initializing = initPromise;
|
|
245
|
-
if (!this.lazyInit) {
|
|
246
|
-
try {
|
|
247
|
-
await initPromise;
|
|
248
|
-
} catch (error) {
|
|
249
|
-
this._initialized = false;
|
|
250
|
-
this._initializing = void 0;
|
|
251
|
-
throw error;
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
isInitialized() {
|
|
256
|
-
return this._initialized;
|
|
257
|
-
}
|
|
258
|
-
async _performInit() {
|
|
259
|
-
await this._doInit();
|
|
260
|
-
this._initialized = true;
|
|
261
|
-
this._initializing = void 0;
|
|
262
|
-
}
|
|
263
|
-
async getToolDefinitions() {
|
|
264
|
-
if (!this.isInitialized() && this._initializing) {
|
|
265
|
-
await this._initializing;
|
|
266
|
-
}
|
|
267
|
-
if (!this.isInitialized()) {
|
|
268
|
-
throw new Error(`Skill ${this.name} is not initialized`);
|
|
269
|
-
}
|
|
270
|
-
return this._filterTools(this._toolDefinitions);
|
|
271
|
-
}
|
|
272
|
-
_filterTools(tools) {
|
|
273
|
-
return tools;
|
|
274
|
-
}
|
|
275
|
-
};
|
|
276
|
-
|
|
277
|
-
// src/skill-manager/command-args.ts
|
|
278
|
-
function getCommandArgs(skill) {
|
|
279
|
-
const { name, command, packageName, args } = skill;
|
|
280
|
-
if (!packageName && (!args || args.length === 0)) {
|
|
281
|
-
throw new Error(`Skill ${name} has no packageName or args. Please provide one of them.`);
|
|
282
|
-
}
|
|
283
|
-
if (packageName && args && args.length > 0) {
|
|
284
|
-
throw new Error(`Skill ${name} has both packageName and args. Please provide only one of them.`);
|
|
285
|
-
}
|
|
286
|
-
let newArgs = args && args.length > 0 ? args : [packageName];
|
|
287
|
-
if (command === "npx" && !newArgs.includes("-y")) {
|
|
288
|
-
newArgs = ["-y", ...newArgs];
|
|
289
|
-
}
|
|
290
|
-
return { command, args: newArgs };
|
|
271
|
+
// src/helpers/checkpoint.ts
|
|
272
|
+
function createInitialCheckpoint(checkpointId, params) {
|
|
273
|
+
return {
|
|
274
|
+
id: checkpointId,
|
|
275
|
+
jobId: params.jobId,
|
|
276
|
+
runId: params.runId,
|
|
277
|
+
expert: {
|
|
278
|
+
key: params.expertKey,
|
|
279
|
+
name: params.expert.name,
|
|
280
|
+
version: params.expert.version
|
|
281
|
+
},
|
|
282
|
+
stepNumber: 1,
|
|
283
|
+
status: "init",
|
|
284
|
+
messages: [],
|
|
285
|
+
usage: createEmptyUsage(),
|
|
286
|
+
contextWindow: params.contextWindow,
|
|
287
|
+
contextWindowUsage: params.contextWindow ? 0 : void 0
|
|
288
|
+
};
|
|
291
289
|
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
expert;
|
|
299
|
-
constructor(expert, jobId, runId, eventListener) {
|
|
300
|
-
super(jobId, runId, eventListener);
|
|
301
|
-
this.name = expert.name;
|
|
302
|
-
this.expert = expert;
|
|
303
|
-
}
|
|
304
|
-
async _doInit() {
|
|
305
|
-
this._toolDefinitions = [
|
|
306
|
-
{
|
|
307
|
-
skillName: this.expert.name,
|
|
308
|
-
name: this.expert.name.split("/").pop() ?? this.expert.name,
|
|
309
|
-
description: this.expert.description,
|
|
310
|
-
inputSchema: {
|
|
311
|
-
type: "object",
|
|
312
|
-
properties: {
|
|
313
|
-
query: { type: "string" }
|
|
314
|
-
},
|
|
315
|
-
required: ["query"]
|
|
316
|
-
},
|
|
317
|
-
interactive: false
|
|
318
|
-
}
|
|
319
|
-
];
|
|
320
|
-
}
|
|
321
|
-
async close() {
|
|
322
|
-
}
|
|
323
|
-
async callTool(_toolName, _input) {
|
|
324
|
-
return [];
|
|
325
|
-
}
|
|
326
|
-
};
|
|
327
|
-
|
|
328
|
-
// src/skill-manager/interactive.ts
|
|
329
|
-
var InteractiveSkillManager = class extends BaseSkillManager {
|
|
330
|
-
name;
|
|
331
|
-
type = "interactive";
|
|
332
|
-
lazyInit = false;
|
|
333
|
-
interactiveSkill;
|
|
334
|
-
constructor(interactiveSkill, jobId, runId, eventListener) {
|
|
335
|
-
super(jobId, runId, eventListener);
|
|
336
|
-
this.name = interactiveSkill.name;
|
|
337
|
-
this.interactiveSkill = interactiveSkill;
|
|
338
|
-
}
|
|
339
|
-
async _doInit() {
|
|
340
|
-
this._toolDefinitions = Object.values(this.interactiveSkill.tools).map((tool2) => ({
|
|
341
|
-
skillName: this.interactiveSkill.name,
|
|
342
|
-
name: tool2.name,
|
|
343
|
-
description: tool2.description,
|
|
344
|
-
inputSchema: JSON.parse(tool2.inputJsonSchema),
|
|
345
|
-
interactive: true
|
|
346
|
-
}));
|
|
347
|
-
}
|
|
348
|
-
async close() {
|
|
349
|
-
}
|
|
350
|
-
async callTool(_toolName, _input) {
|
|
351
|
-
return [];
|
|
352
|
-
}
|
|
353
|
-
};
|
|
354
|
-
|
|
355
|
-
// src/skill-manager/ip-validator.ts
|
|
356
|
-
function isPrivateOrLocalIP(hostname) {
|
|
357
|
-
if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1" || hostname === "0.0.0.0") {
|
|
358
|
-
return true;
|
|
359
|
-
}
|
|
360
|
-
const ipv4Match = hostname.match(/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/);
|
|
361
|
-
if (ipv4Match) {
|
|
362
|
-
const [, a, b] = ipv4Match.map(Number);
|
|
363
|
-
if (a === 10) return true;
|
|
364
|
-
if (a === 172 && b >= 16 && b <= 31) return true;
|
|
365
|
-
if (a === 192 && b === 168) return true;
|
|
366
|
-
if (a === 169 && b === 254) return true;
|
|
367
|
-
if (a === 127) return true;
|
|
368
|
-
}
|
|
369
|
-
if (hostname.includes(":")) {
|
|
370
|
-
if (hostname.startsWith("fe80:")) return true;
|
|
371
|
-
if (hostname.startsWith("fc") || hostname.startsWith("fd")) return true;
|
|
372
|
-
}
|
|
373
|
-
if (hostname.startsWith("::ffff:")) {
|
|
374
|
-
const ipv4Part = hostname.slice(7);
|
|
375
|
-
if (isPrivateOrLocalIP(ipv4Part)) {
|
|
376
|
-
return true;
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
return false;
|
|
290
|
+
function createNextStepCheckpoint(checkpointId, checkpoint) {
|
|
291
|
+
return {
|
|
292
|
+
...checkpoint,
|
|
293
|
+
id: checkpointId,
|
|
294
|
+
stepNumber: checkpoint.stepNumber + 1
|
|
295
|
+
};
|
|
380
296
|
}
|
|
381
|
-
function
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
type: "textPart",
|
|
386
|
-
text: `Error calling tool ${toolName}: ${error.message}`,
|
|
387
|
-
id: createId()
|
|
388
|
-
}
|
|
389
|
-
];
|
|
297
|
+
function buildDelegationReturnState(currentSetting, resultCheckpoint, parentCheckpoint) {
|
|
298
|
+
const { messages, delegatedBy } = resultCheckpoint;
|
|
299
|
+
if (!delegatedBy) {
|
|
300
|
+
throw new Error("delegatedBy is required for buildDelegationReturnState");
|
|
390
301
|
}
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
if (!result.content || result.content.length === 0) {
|
|
395
|
-
return [
|
|
396
|
-
{
|
|
397
|
-
type: "textPart",
|
|
398
|
-
text: `Tool ${toolName} returned nothing with arguments: ${JSON.stringify(input)}`,
|
|
399
|
-
id: createId()
|
|
400
|
-
}
|
|
401
|
-
];
|
|
302
|
+
const delegateResultMessage = messages[messages.length - 1];
|
|
303
|
+
if (!delegateResultMessage || delegateResultMessage.type !== "expertMessage") {
|
|
304
|
+
throw new Error("Delegation error: delegation result message is incorrect");
|
|
402
305
|
}
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
if (!part.text || part.text === "") {
|
|
409
|
-
return { type: "textPart", text: "Error: No content", id: createId() };
|
|
410
|
-
}
|
|
411
|
-
return { type: "textPart", text: part.text, id: createId() };
|
|
412
|
-
case "image":
|
|
413
|
-
if (!part.data || !part.mimeType) {
|
|
414
|
-
throw new Error("Image part must have both data and mimeType");
|
|
415
|
-
}
|
|
416
|
-
return {
|
|
417
|
-
type: "imageInlinePart",
|
|
418
|
-
encodedData: part.data,
|
|
419
|
-
mimeType: part.mimeType,
|
|
420
|
-
id: createId()
|
|
421
|
-
};
|
|
422
|
-
case "resource":
|
|
423
|
-
if (!part.resource) {
|
|
424
|
-
throw new Error("Resource part must have resource content");
|
|
425
|
-
}
|
|
426
|
-
return convertResource(part.resource);
|
|
306
|
+
const delegateText = delegateResultMessage.contents.find((content) => content.type === "textPart");
|
|
307
|
+
if (!delegateText) {
|
|
308
|
+
console.warn(
|
|
309
|
+
`Delegation result from ${resultCheckpoint.expert.key} has no text content. Parent expert ${delegatedBy.expert.key} will receive empty string.`
|
|
310
|
+
);
|
|
427
311
|
}
|
|
312
|
+
const { expert, toolCallId, toolName } = delegatedBy;
|
|
313
|
+
return {
|
|
314
|
+
setting: {
|
|
315
|
+
...currentSetting,
|
|
316
|
+
expertKey: expert.key,
|
|
317
|
+
input: {
|
|
318
|
+
interactiveToolCallResult: {
|
|
319
|
+
toolCallId,
|
|
320
|
+
toolName,
|
|
321
|
+
skillName: `delegate/${resultCheckpoint.expert.key}`,
|
|
322
|
+
text: delegateText?.text ?? ""
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
},
|
|
326
|
+
checkpoint: {
|
|
327
|
+
...parentCheckpoint,
|
|
328
|
+
stepNumber: resultCheckpoint.stepNumber,
|
|
329
|
+
usage: resultCheckpoint.usage,
|
|
330
|
+
pendingToolCalls: parentCheckpoint.pendingToolCalls,
|
|
331
|
+
partialToolResults: parentCheckpoint.partialToolResults
|
|
332
|
+
}
|
|
333
|
+
};
|
|
428
334
|
}
|
|
429
|
-
function
|
|
430
|
-
if (
|
|
431
|
-
|
|
432
|
-
}
|
|
433
|
-
if (resource.text && typeof resource.text === "string") {
|
|
434
|
-
return { type: "textPart", text: resource.text, id: createId() };
|
|
335
|
+
async function resolveExpertToRun(expertKey, experts, clientOptions) {
|
|
336
|
+
if (experts[expertKey]) {
|
|
337
|
+
return experts[expertKey];
|
|
435
338
|
}
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
};
|
|
339
|
+
const client = createApiClient({
|
|
340
|
+
baseUrl: clientOptions.perstackApiBaseUrl,
|
|
341
|
+
apiKey: clientOptions.perstackApiKey
|
|
342
|
+
});
|
|
343
|
+
const result = await client.registry.experts.get(expertKey);
|
|
344
|
+
if (!result.ok) {
|
|
345
|
+
throw new Error(`Failed to resolve expert "${expertKey}": ${result.error.message}`);
|
|
443
346
|
}
|
|
444
|
-
|
|
347
|
+
return toRuntimeExpert(result.data);
|
|
445
348
|
}
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
};
|
|
459
|
-
var defaultTransportFactory = new DefaultTransportFactory();
|
|
460
|
-
|
|
461
|
-
// src/skill-manager/mcp.ts
|
|
462
|
-
var McpSkillManager = class extends BaseSkillManager {
|
|
463
|
-
name;
|
|
464
|
-
type = "mcp";
|
|
465
|
-
lazyInit;
|
|
466
|
-
skill;
|
|
467
|
-
_mcpClient;
|
|
468
|
-
_env;
|
|
469
|
-
_transportFactory;
|
|
470
|
-
constructor(skill, env, jobId, runId, eventListener, options) {
|
|
471
|
-
super(jobId, runId, eventListener);
|
|
472
|
-
this.name = skill.name;
|
|
473
|
-
this.skill = skill;
|
|
474
|
-
this._env = env;
|
|
475
|
-
this._transportFactory = options?.transportFactory ?? defaultTransportFactory;
|
|
476
|
-
this.lazyInit = skill.type === "mcpStdioSkill" && skill.lazyInit && skill.name !== "@perstack/base";
|
|
477
|
-
}
|
|
478
|
-
async _doInit() {
|
|
479
|
-
this._mcpClient = new Client({
|
|
480
|
-
name: `${this.skill.name}-mcp-client`,
|
|
481
|
-
version: "1.0.0"
|
|
482
|
-
});
|
|
483
|
-
let timingInfo;
|
|
484
|
-
if (this.skill.type === "mcpStdioSkill") {
|
|
485
|
-
timingInfo = await this._initStdio(this.skill);
|
|
486
|
-
} else {
|
|
487
|
-
await this._initSse(this.skill);
|
|
488
|
-
}
|
|
489
|
-
const toolDiscoveryStartTime = Date.now();
|
|
490
|
-
const { tools } = await this._mcpClient.listTools();
|
|
491
|
-
const toolDiscoveryDurationMs = Date.now() - toolDiscoveryStartTime;
|
|
492
|
-
this._toolDefinitions = tools.map((tool2) => ({
|
|
493
|
-
skillName: this.skill.name,
|
|
494
|
-
name: tool2.name,
|
|
495
|
-
description: tool2.description,
|
|
496
|
-
inputSchema: tool2.inputSchema,
|
|
497
|
-
interactive: false
|
|
498
|
-
}));
|
|
499
|
-
if (this._eventListener && timingInfo) {
|
|
500
|
-
const totalDurationMs = Date.now() - timingInfo.startTime;
|
|
501
|
-
const event = createRuntimeEvent("skillConnected", this._jobId, this._runId, {
|
|
502
|
-
skillName: this.skill.name,
|
|
503
|
-
serverInfo: timingInfo.serverInfo,
|
|
504
|
-
spawnDurationMs: timingInfo.spawnDurationMs,
|
|
505
|
-
handshakeDurationMs: timingInfo.handshakeDurationMs,
|
|
506
|
-
toolDiscoveryDurationMs,
|
|
507
|
-
connectDurationMs: timingInfo.spawnDurationMs + timingInfo.handshakeDurationMs,
|
|
508
|
-
totalDurationMs
|
|
509
|
-
});
|
|
510
|
-
this._eventListener(event);
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
async _initStdio(skill) {
|
|
514
|
-
if (!skill.command) {
|
|
515
|
-
throw new Error(`Skill ${skill.name} has no command`);
|
|
516
|
-
}
|
|
517
|
-
const requiredEnv = {};
|
|
518
|
-
for (const envName of skill.requiredEnv) {
|
|
519
|
-
if (!this._env[envName]) {
|
|
520
|
-
throw new Error(`Skill ${skill.name} requires environment variable ${envName}`);
|
|
521
|
-
}
|
|
522
|
-
requiredEnv[envName] = this._env[envName];
|
|
523
|
-
}
|
|
524
|
-
const env = getFilteredEnv(requiredEnv);
|
|
525
|
-
const startTime = Date.now();
|
|
526
|
-
const { command, args } = getCommandArgs(skill);
|
|
527
|
-
if (this._eventListener) {
|
|
528
|
-
const event = createRuntimeEvent("skillStarting", this._jobId, this._runId, {
|
|
529
|
-
skillName: skill.name,
|
|
530
|
-
command,
|
|
531
|
-
args
|
|
532
|
-
});
|
|
533
|
-
this._eventListener(event);
|
|
534
|
-
}
|
|
535
|
-
const transport = this._transportFactory.createStdio({ command, args, env, stderr: "pipe" });
|
|
536
|
-
const spawnDurationMs = Date.now() - startTime;
|
|
537
|
-
if (transport.stderr) {
|
|
538
|
-
transport.stderr.on("data", (chunk) => {
|
|
539
|
-
if (this._eventListener) {
|
|
540
|
-
const event = createRuntimeEvent("skillStderr", this._jobId, this._runId, {
|
|
541
|
-
skillName: skill.name,
|
|
542
|
-
message: chunk.toString().trim()
|
|
543
|
-
});
|
|
544
|
-
this._eventListener(event);
|
|
349
|
+
function toRuntimeExpert(expert) {
|
|
350
|
+
const skills = Object.fromEntries(
|
|
351
|
+
Object.entries(expert.skills).map(([name, skill]) => {
|
|
352
|
+
switch (skill.type) {
|
|
353
|
+
case "mcpStdioSkill":
|
|
354
|
+
return [name, { ...skill, name }];
|
|
355
|
+
case "mcpSseSkill":
|
|
356
|
+
return [name, { ...skill, name }];
|
|
357
|
+
case "interactiveSkill":
|
|
358
|
+
return [name, { ...skill, name }];
|
|
359
|
+
default: {
|
|
360
|
+
throw new Error(`Unknown skill type: ${skill.type}`);
|
|
545
361
|
}
|
|
546
|
-
});
|
|
547
|
-
}
|
|
548
|
-
const connectStartTime = Date.now();
|
|
549
|
-
await this._mcpClient.connect(transport);
|
|
550
|
-
const handshakeDurationMs = Date.now() - connectStartTime;
|
|
551
|
-
const serverVersion = this._mcpClient.getServerVersion();
|
|
552
|
-
return {
|
|
553
|
-
startTime,
|
|
554
|
-
spawnDurationMs,
|
|
555
|
-
handshakeDurationMs,
|
|
556
|
-
serverInfo: serverVersion ? { name: serverVersion.name, version: serverVersion.version } : void 0
|
|
557
|
-
};
|
|
558
|
-
}
|
|
559
|
-
async _initSse(skill) {
|
|
560
|
-
if (!skill.endpoint) {
|
|
561
|
-
throw new Error(`Skill ${skill.name} has no endpoint`);
|
|
562
|
-
}
|
|
563
|
-
const url = new URL(skill.endpoint);
|
|
564
|
-
if (url.protocol !== "https:") {
|
|
565
|
-
throw new Error(`Skill ${skill.name} SSE endpoint must use HTTPS: ${skill.endpoint}`);
|
|
566
|
-
}
|
|
567
|
-
if (isPrivateOrLocalIP(url.hostname)) {
|
|
568
|
-
throw new Error(
|
|
569
|
-
`Skill ${skill.name} SSE endpoint cannot use private/local IP: ${skill.endpoint}`
|
|
570
|
-
);
|
|
571
|
-
}
|
|
572
|
-
const transport = this._transportFactory.createSse({ url });
|
|
573
|
-
await this._mcpClient.connect(transport);
|
|
574
|
-
}
|
|
575
|
-
async close() {
|
|
576
|
-
if (this._mcpClient) {
|
|
577
|
-
await this._mcpClient.close();
|
|
578
|
-
if (this._eventListener && this.skill) {
|
|
579
|
-
const event = createRuntimeEvent("skillDisconnected", this._jobId, this._runId, {
|
|
580
|
-
skillName: this.skill.name
|
|
581
|
-
});
|
|
582
|
-
this._eventListener(event);
|
|
583
362
|
}
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
const pick = this.skill.pick ?? [];
|
|
589
|
-
return tools.filter((tool2) => omit.length > 0 ? !omit.includes(tool2.name) : true).filter((tool2) => pick.length > 0 ? pick.includes(tool2.name) : true);
|
|
590
|
-
}
|
|
591
|
-
async callTool(toolName, input) {
|
|
592
|
-
if (!this.isInitialized() || !this._mcpClient) {
|
|
593
|
-
throw new Error(`${this.name} is not initialized`);
|
|
594
|
-
}
|
|
595
|
-
try {
|
|
596
|
-
const result = await this._mcpClient.callTool({
|
|
597
|
-
name: toolName,
|
|
598
|
-
arguments: input
|
|
599
|
-
});
|
|
600
|
-
return convertToolResult(result, toolName, input);
|
|
601
|
-
} catch (error) {
|
|
602
|
-
return handleToolError(error, toolName, McpError);
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
};
|
|
606
|
-
|
|
607
|
-
// src/skill-manager/skill-manager-factory.ts
|
|
608
|
-
var DefaultSkillManagerFactory = class {
|
|
609
|
-
createMcp(skill, context) {
|
|
610
|
-
return new McpSkillManager(
|
|
611
|
-
skill,
|
|
612
|
-
context.env,
|
|
613
|
-
context.jobId,
|
|
614
|
-
context.runId,
|
|
615
|
-
context.eventListener,
|
|
616
|
-
context.mcpOptions
|
|
617
|
-
);
|
|
618
|
-
}
|
|
619
|
-
createInteractive(skill, context) {
|
|
620
|
-
return new InteractiveSkillManager(skill, context.jobId, context.runId, context.eventListener);
|
|
621
|
-
}
|
|
622
|
-
createDelegate(expert, context) {
|
|
623
|
-
return new DelegateSkillManager(expert, context.jobId, context.runId, context.eventListener);
|
|
624
|
-
}
|
|
625
|
-
};
|
|
626
|
-
var defaultSkillManagerFactory = new DefaultSkillManagerFactory();
|
|
363
|
+
})
|
|
364
|
+
);
|
|
365
|
+
return { ...expert, skills };
|
|
366
|
+
}
|
|
627
367
|
|
|
628
|
-
// src/
|
|
629
|
-
async function
|
|
630
|
-
const
|
|
631
|
-
const
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
throw firstRejected.reason;
|
|
636
|
-
}
|
|
637
|
-
}
|
|
638
|
-
async function getSkillManagers(expert, experts, setting, eventListener, options) {
|
|
639
|
-
const { perstackBaseSkillCommand, env, jobId, runId } = setting;
|
|
640
|
-
const { skills } = expert;
|
|
641
|
-
const factory = options?.factory ?? defaultSkillManagerFactory;
|
|
642
|
-
if (!skills["@perstack/base"]) {
|
|
643
|
-
throw new Error("Base skill is not defined");
|
|
644
|
-
}
|
|
645
|
-
const factoryContext = {
|
|
646
|
-
env,
|
|
647
|
-
jobId,
|
|
648
|
-
runId,
|
|
649
|
-
eventListener
|
|
368
|
+
// src/helpers/setup-experts.ts
|
|
369
|
+
async function setupExperts(setting, resolveExpertToRun2 = resolveExpertToRun) {
|
|
370
|
+
const { expertKey } = setting;
|
|
371
|
+
const experts = { ...setting.experts };
|
|
372
|
+
const clientOptions = {
|
|
373
|
+
perstackApiBaseUrl: setting.perstackApiBaseUrl,
|
|
374
|
+
perstackApiKey: setting.perstackApiKey
|
|
650
375
|
};
|
|
651
|
-
const
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
if (perstackBaseSkillCommand && skill.type === "mcpStdioSkill") {
|
|
656
|
-
const matchesBaseByPackage = skill.command === "npx" && skill.packageName === "@perstack/base";
|
|
657
|
-
const matchesBaseByArgs = skill.command === "npx" && Array.isArray(skill.args) && skill.args.includes("@perstack/base");
|
|
658
|
-
if (matchesBaseByPackage || matchesBaseByArgs) {
|
|
659
|
-
const [overrideCommand, ...overrideArgs] = perstackBaseSkillCommand;
|
|
660
|
-
if (!overrideCommand) {
|
|
661
|
-
throw new Error("perstackBaseSkillCommand must have at least one element");
|
|
662
|
-
}
|
|
663
|
-
return {
|
|
664
|
-
...skill,
|
|
665
|
-
command: overrideCommand,
|
|
666
|
-
packageName: void 0,
|
|
667
|
-
args: overrideArgs,
|
|
668
|
-
lazyInit: false
|
|
669
|
-
};
|
|
670
|
-
}
|
|
671
|
-
}
|
|
672
|
-
return skill;
|
|
673
|
-
});
|
|
674
|
-
const mcpSkillManagers = mcpSkills.map((skill) => {
|
|
675
|
-
const manager = factory.createMcp(skill, factoryContext);
|
|
676
|
-
allManagers.push(manager);
|
|
677
|
-
return manager;
|
|
678
|
-
});
|
|
679
|
-
await initSkillManagersWithCleanup(mcpSkillManagers, allManagers);
|
|
680
|
-
if (!options?.isDelegatedRun) {
|
|
681
|
-
const interactiveSkills = Object.values(skills).filter(
|
|
682
|
-
(skill) => skill.type === "interactiveSkill"
|
|
683
|
-
);
|
|
684
|
-
const interactiveSkillManagers = interactiveSkills.map((interactiveSkill) => {
|
|
685
|
-
const manager = factory.createInteractive(interactiveSkill, factoryContext);
|
|
686
|
-
allManagers.push(manager);
|
|
687
|
-
return manager;
|
|
688
|
-
});
|
|
689
|
-
await initSkillManagersWithCleanup(interactiveSkillManagers, allManagers);
|
|
690
|
-
}
|
|
691
|
-
const delegateSkillManagers = [];
|
|
692
|
-
for (const delegateExpertName of expert.delegates) {
|
|
693
|
-
const delegate = experts[delegateExpertName];
|
|
376
|
+
const expertToRun = await resolveExpertToRun2(expertKey, experts, clientOptions);
|
|
377
|
+
experts[expertKey] = expertToRun;
|
|
378
|
+
for (const delegateName of expertToRun.delegates) {
|
|
379
|
+
const delegate = await resolveExpertToRun2(delegateName, experts, clientOptions);
|
|
694
380
|
if (!delegate) {
|
|
695
|
-
|
|
696
|
-
})));
|
|
697
|
-
throw new Error(`Delegate expert "${delegateExpertName}" not found in experts`);
|
|
698
|
-
}
|
|
699
|
-
const manager = factory.createDelegate(delegate, factoryContext);
|
|
700
|
-
allManagers.push(manager);
|
|
701
|
-
delegateSkillManagers.push(manager);
|
|
702
|
-
}
|
|
703
|
-
await initSkillManagersWithCleanup(delegateSkillManagers, allManagers);
|
|
704
|
-
const skillManagers = {};
|
|
705
|
-
for (const manager of allManagers) {
|
|
706
|
-
skillManagers[manager.name] = manager;
|
|
707
|
-
}
|
|
708
|
-
return skillManagers;
|
|
709
|
-
}
|
|
710
|
-
async function closeSkillManagers(skillManagers) {
|
|
711
|
-
await Promise.all(Object.values(skillManagers).map((m) => m.close().catch(() => {
|
|
712
|
-
})));
|
|
713
|
-
}
|
|
714
|
-
async function getSkillManagerByToolName(skillManagers, toolName) {
|
|
715
|
-
for (const skillManager of Object.values(skillManagers)) {
|
|
716
|
-
const toolDefinitions = await skillManager.getToolDefinitions();
|
|
717
|
-
for (const toolDefinition of toolDefinitions) {
|
|
718
|
-
if (toolDefinition.name === toolName) {
|
|
719
|
-
return skillManager;
|
|
720
|
-
}
|
|
381
|
+
throw new Error(`Delegate ${delegateName} not found`);
|
|
721
382
|
}
|
|
383
|
+
experts[delegateName] = delegate;
|
|
722
384
|
}
|
|
723
|
-
|
|
385
|
+
return { expertToRun, experts };
|
|
724
386
|
}
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
387
|
+
|
|
388
|
+
// src/helpers/thinking.ts
|
|
389
|
+
function extractThinkingParts(reasoning) {
|
|
390
|
+
if (!reasoning) return [];
|
|
391
|
+
return reasoning.map((r) => ({
|
|
392
|
+
type: "thinkingPart",
|
|
393
|
+
thinking: r.text,
|
|
394
|
+
// Signature is in providerMetadata for Anthropic (output from API)
|
|
395
|
+
signature: r.providerMetadata?.anthropic?.signature
|
|
396
|
+
}));
|
|
397
|
+
}
|
|
398
|
+
function extractThinkingText(reasoning) {
|
|
399
|
+
if (!reasoning) return "";
|
|
400
|
+
return reasoning.filter((r) => r.text).map((r) => r.text).join("\n");
|
|
737
401
|
}
|
|
738
402
|
function isFileInfo(value) {
|
|
739
403
|
return typeof value === "object" && value !== null && "path" in value && "mimeType" in value && "size" in value && typeof value.path === "string" && typeof value.mimeType === "string" && typeof value.size === "number";
|
|
@@ -759,9 +423,9 @@ async function processFileToolResult(toolResult, toolName) {
|
|
|
759
423
|
processedContents.push(part);
|
|
760
424
|
continue;
|
|
761
425
|
}
|
|
762
|
-
const { path, mimeType } = fileInfo;
|
|
426
|
+
const { path: path2, mimeType } = fileInfo;
|
|
763
427
|
try {
|
|
764
|
-
const buffer = await readFile(
|
|
428
|
+
const buffer = await readFile(path2);
|
|
765
429
|
if (toolName === "readImageFile") {
|
|
766
430
|
processedContents.push({
|
|
767
431
|
type: "imageInlinePart",
|
|
@@ -781,7 +445,7 @@ async function processFileToolResult(toolResult, toolName) {
|
|
|
781
445
|
processedContents.push({
|
|
782
446
|
type: "textPart",
|
|
783
447
|
id: part.id,
|
|
784
|
-
text: `Failed to read file "${
|
|
448
|
+
text: `Failed to read file "${path2}": ${error instanceof Error ? error.message : String(error)}`
|
|
785
449
|
});
|
|
786
450
|
}
|
|
787
451
|
}
|
|
@@ -1157,6 +821,8 @@ function expertContentsToCoreContent(contents) {
|
|
|
1157
821
|
return textPartToCoreTextPart(part);
|
|
1158
822
|
case "toolCallPart":
|
|
1159
823
|
return toolCallPartToCoreToolCallPart(part);
|
|
824
|
+
case "thinkingPart":
|
|
825
|
+
return thinkingPartToCoreThinkingPart(part);
|
|
1160
826
|
default:
|
|
1161
827
|
throw new Error(`Unknown expert content type: ${part.type}`);
|
|
1162
828
|
}
|
|
@@ -1228,6 +894,13 @@ function toolCallPartToCoreToolCallPart(part) {
|
|
|
1228
894
|
input: part.args
|
|
1229
895
|
};
|
|
1230
896
|
}
|
|
897
|
+
function thinkingPartToCoreThinkingPart(part) {
|
|
898
|
+
return {
|
|
899
|
+
type: "reasoning",
|
|
900
|
+
text: part.thinking,
|
|
901
|
+
providerOptions: part.signature ? { anthropic: { signature: part.signature } } : void 0
|
|
902
|
+
};
|
|
903
|
+
}
|
|
1231
904
|
function toolResultPartToCoreToolResultPart(part) {
|
|
1232
905
|
const { contents } = part;
|
|
1233
906
|
if (contents.length === 1 && contents[0].type === "textPart") {
|
|
@@ -1256,7 +929,9 @@ function toolResultPartToCoreToolResultPart(part) {
|
|
|
1256
929
|
async function generatingRunResultLogic({
|
|
1257
930
|
setting,
|
|
1258
931
|
checkpoint,
|
|
1259
|
-
step
|
|
932
|
+
step,
|
|
933
|
+
eventListener,
|
|
934
|
+
llmExecutor
|
|
1260
935
|
}) {
|
|
1261
936
|
if (!step.toolCalls || !step.toolResults || step.toolResults.length === 0) {
|
|
1262
937
|
throw new Error("No tool calls or tool results found");
|
|
@@ -1273,37 +948,90 @@ async function generatingRunResultLogic({
|
|
|
1273
948
|
};
|
|
1274
949
|
});
|
|
1275
950
|
const toolMessage = createToolMessage(toolResultParts);
|
|
1276
|
-
const model = getModel(setting.model, setting.providerConfig, { proxyUrl: setting.proxyUrl });
|
|
1277
951
|
const { messages } = checkpoint;
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
952
|
+
const coreMessages = [...messages, toolMessage].map(messageToCoreMessage);
|
|
953
|
+
let reasoningCompletedViaCallback = false;
|
|
954
|
+
const callbacks = {
|
|
955
|
+
onReasoningStart: () => {
|
|
956
|
+
eventListener(createRuntimeEvent("startReasoning", setting.jobId, setting.runId, {}));
|
|
957
|
+
},
|
|
958
|
+
onReasoningDelta: (delta) => {
|
|
959
|
+
eventListener(createRuntimeEvent("streamReasoning", setting.jobId, setting.runId, { delta }));
|
|
960
|
+
},
|
|
961
|
+
onReasoningComplete: (text2) => {
|
|
962
|
+
eventListener(createRuntimeEvent("completeReasoning", setting.jobId, setting.runId, { text: text2 }));
|
|
963
|
+
reasoningCompletedViaCallback = true;
|
|
964
|
+
},
|
|
965
|
+
onResultStart: () => {
|
|
966
|
+
eventListener(createRuntimeEvent("startRunResult", setting.jobId, setting.runId, {}));
|
|
967
|
+
},
|
|
968
|
+
onResultDelta: (delta) => {
|
|
969
|
+
eventListener(createRuntimeEvent("streamRunResult", setting.jobId, setting.runId, { delta }));
|
|
970
|
+
}
|
|
971
|
+
};
|
|
972
|
+
const executionResult = await llmExecutor.streamText(
|
|
973
|
+
{
|
|
974
|
+
messages: coreMessages,
|
|
1284
975
|
maxRetries: setting.maxRetries,
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
976
|
+
tools: {},
|
|
977
|
+
// No tools for run result generation
|
|
978
|
+
abortSignal: AbortSignal.timeout(setting.timeout),
|
|
979
|
+
reasoningBudget: setting.reasoningBudget
|
|
980
|
+
},
|
|
981
|
+
callbacks
|
|
982
|
+
);
|
|
983
|
+
if (!executionResult.success) {
|
|
984
|
+
const { error, isRetryable } = executionResult;
|
|
985
|
+
const currentRetryCount = checkpoint.retryCount ?? 0;
|
|
986
|
+
if (!isRetryable || currentRetryCount >= setting.maxRetries) {
|
|
987
|
+
return stopRunByError(setting, checkpoint, {
|
|
988
|
+
checkpoint: {
|
|
989
|
+
...checkpoint,
|
|
990
|
+
status: "stoppedByError"
|
|
991
|
+
},
|
|
992
|
+
step: {
|
|
993
|
+
...step,
|
|
994
|
+
finishedAt: Date.now()
|
|
995
|
+
},
|
|
996
|
+
error: {
|
|
997
|
+
name: error.name ?? "Error",
|
|
998
|
+
message: currentRetryCount >= setting.maxRetries ? `Max retries (${setting.maxRetries}) exceeded: ${error.message}` : error.message,
|
|
999
|
+
statusCode: error.statusCode,
|
|
1000
|
+
isRetryable: false
|
|
1001
|
+
}
|
|
1294
1002
|
});
|
|
1295
1003
|
}
|
|
1296
|
-
|
|
1004
|
+
const reason = JSON.stringify({ error: error.name ?? "Error", message: error.message });
|
|
1005
|
+
return retry(setting, checkpoint, {
|
|
1006
|
+
reason,
|
|
1007
|
+
newMessages: [toolMessage, createUserMessage([{ type: "textPart", text: reason }])],
|
|
1008
|
+
usage: createEmptyUsage()
|
|
1009
|
+
});
|
|
1297
1010
|
}
|
|
1011
|
+
const generationResult = executionResult.result;
|
|
1298
1012
|
const usage = usageFromGenerateTextResult(generationResult);
|
|
1299
|
-
const { text } = generationResult;
|
|
1300
|
-
const
|
|
1013
|
+
const { text, reasoning } = generationResult;
|
|
1014
|
+
const thinkingParts = extractThinkingParts(reasoning);
|
|
1015
|
+
const thinkingText = extractThinkingText(reasoning);
|
|
1016
|
+
const expertContents = [
|
|
1017
|
+
...thinkingParts,
|
|
1018
|
+
{ type: "textPart", text: text ?? "" }
|
|
1019
|
+
];
|
|
1020
|
+
const newMessages = [toolMessage, createExpertMessage(expertContents)];
|
|
1021
|
+
if (thinkingText && !reasoningCompletedViaCallback) {
|
|
1022
|
+
await eventListener(
|
|
1023
|
+
createRuntimeEvent("completeReasoning", setting.jobId, setting.runId, {
|
|
1024
|
+
text: thinkingText
|
|
1025
|
+
})
|
|
1026
|
+
);
|
|
1027
|
+
}
|
|
1028
|
+
const newUsage = sumUsage(checkpoint.usage, usage);
|
|
1301
1029
|
return completeRun(setting, checkpoint, {
|
|
1302
1030
|
checkpoint: {
|
|
1303
1031
|
...checkpoint,
|
|
1304
1032
|
messages: [...messages, ...newMessages],
|
|
1305
|
-
usage:
|
|
1306
|
-
contextWindowUsage: checkpoint.contextWindow ? calculateContextWindowUsage(
|
|
1033
|
+
usage: newUsage,
|
|
1034
|
+
contextWindowUsage: checkpoint.contextWindow ? calculateContextWindowUsage(newUsage, checkpoint.contextWindow) : void 0,
|
|
1307
1035
|
status: "completed"
|
|
1308
1036
|
},
|
|
1309
1037
|
step: {
|
|
@@ -1354,38 +1082,121 @@ function buildToolCalls(toolCalls) {
|
|
|
1354
1082
|
async function generatingToolCallLogic({
|
|
1355
1083
|
setting,
|
|
1356
1084
|
checkpoint,
|
|
1357
|
-
|
|
1085
|
+
step,
|
|
1086
|
+
skillManagers,
|
|
1087
|
+
eventListener,
|
|
1088
|
+
llmExecutor
|
|
1358
1089
|
}) {
|
|
1359
1090
|
const { messages } = checkpoint;
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1091
|
+
let reasoningCompletedViaCallback = false;
|
|
1092
|
+
const callbacks = {
|
|
1093
|
+
onReasoningStart: () => {
|
|
1094
|
+
eventListener(createRuntimeEvent("startReasoning", setting.jobId, setting.runId, {}));
|
|
1095
|
+
},
|
|
1096
|
+
onReasoningDelta: (delta) => {
|
|
1097
|
+
eventListener(createRuntimeEvent("streamReasoning", setting.jobId, setting.runId, { delta }));
|
|
1098
|
+
},
|
|
1099
|
+
onReasoningComplete: (text2) => {
|
|
1100
|
+
eventListener(createRuntimeEvent("completeReasoning", setting.jobId, setting.runId, { text: text2 }));
|
|
1101
|
+
reasoningCompletedViaCallback = true;
|
|
1102
|
+
}
|
|
1103
|
+
// onResultStart and onResultDelta intentionally not set - result streaming only in GeneratingRunResult
|
|
1104
|
+
};
|
|
1105
|
+
const executionResult = await llmExecutor.streamText(
|
|
1106
|
+
{
|
|
1107
|
+
messages: messages.map(messageToCoreMessage),
|
|
1108
|
+
maxRetries: setting.maxRetries,
|
|
1368
1109
|
tools: await getToolSet(skillManagers),
|
|
1369
|
-
toolChoice: "
|
|
1370
|
-
abortSignal: AbortSignal.timeout(setting.timeout)
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1110
|
+
toolChoice: "auto",
|
|
1111
|
+
abortSignal: AbortSignal.timeout(setting.timeout),
|
|
1112
|
+
reasoningBudget: setting.reasoningBudget
|
|
1113
|
+
},
|
|
1114
|
+
callbacks
|
|
1115
|
+
);
|
|
1116
|
+
if (!executionResult.success) {
|
|
1117
|
+
const { error, isRetryable } = executionResult;
|
|
1118
|
+
const currentRetryCount = checkpoint.retryCount ?? 0;
|
|
1119
|
+
if (!isRetryable || currentRetryCount >= setting.maxRetries) {
|
|
1120
|
+
return stopRunByError(setting, checkpoint, {
|
|
1121
|
+
checkpoint: {
|
|
1122
|
+
...checkpoint,
|
|
1123
|
+
status: "stoppedByError"
|
|
1124
|
+
},
|
|
1125
|
+
step: {
|
|
1126
|
+
...step,
|
|
1127
|
+
finishedAt: Date.now()
|
|
1128
|
+
},
|
|
1129
|
+
error: {
|
|
1130
|
+
name: error.name ?? "Error",
|
|
1131
|
+
message: currentRetryCount >= setting.maxRetries ? `Max retries (${setting.maxRetries}) exceeded: ${error.message}` : error.message,
|
|
1132
|
+
statusCode: error.statusCode,
|
|
1133
|
+
isRetryable: false
|
|
1134
|
+
}
|
|
1379
1135
|
});
|
|
1380
1136
|
}
|
|
1381
|
-
|
|
1137
|
+
const reason = JSON.stringify({ error: error.name ?? "Error", message: error.message });
|
|
1138
|
+
return retry(setting, checkpoint, {
|
|
1139
|
+
reason,
|
|
1140
|
+
newMessages: [createUserMessage([{ type: "textPart", text: reason }])],
|
|
1141
|
+
usage: createEmptyUsage()
|
|
1142
|
+
});
|
|
1382
1143
|
}
|
|
1144
|
+
const result = executionResult.result;
|
|
1383
1145
|
const usage = usageFromGenerateTextResult(result);
|
|
1384
|
-
const { text, toolCalls, finishReason } = result;
|
|
1146
|
+
const { text, toolCalls, finishReason, reasoning } = result;
|
|
1147
|
+
const thinkingParts = extractThinkingParts(reasoning);
|
|
1148
|
+
const thinkingText = extractThinkingText(reasoning);
|
|
1149
|
+
if (toolCalls.length === 0 && text) {
|
|
1150
|
+
const contents = [...thinkingParts, { type: "textPart", text }];
|
|
1151
|
+
const newMessage = createExpertMessage(contents);
|
|
1152
|
+
const newUsage = sumUsage(checkpoint.usage, usage);
|
|
1153
|
+
if (thinkingText && !reasoningCompletedViaCallback) {
|
|
1154
|
+
await eventListener(
|
|
1155
|
+
createRuntimeEvent("completeReasoning", setting.jobId, setting.runId, {
|
|
1156
|
+
text: thinkingText
|
|
1157
|
+
})
|
|
1158
|
+
);
|
|
1159
|
+
}
|
|
1160
|
+
return completeRun(setting, checkpoint, {
|
|
1161
|
+
checkpoint: {
|
|
1162
|
+
...checkpoint,
|
|
1163
|
+
messages: [...messages, newMessage],
|
|
1164
|
+
usage: newUsage,
|
|
1165
|
+
contextWindowUsage: checkpoint.contextWindow ? calculateContextWindowUsage(newUsage, checkpoint.contextWindow) : void 0,
|
|
1166
|
+
status: "completed"
|
|
1167
|
+
},
|
|
1168
|
+
step: {
|
|
1169
|
+
...step,
|
|
1170
|
+
newMessages: [...step.newMessages, newMessage],
|
|
1171
|
+
finishedAt: Date.now(),
|
|
1172
|
+
usage: sumUsage(step.usage, usage)
|
|
1173
|
+
},
|
|
1174
|
+
text,
|
|
1175
|
+
usage
|
|
1176
|
+
});
|
|
1177
|
+
}
|
|
1385
1178
|
if (toolCalls.length === 0) {
|
|
1179
|
+
const currentRetryCount = checkpoint.retryCount ?? 0;
|
|
1180
|
+
if (currentRetryCount >= setting.maxRetries) {
|
|
1181
|
+
return stopRunByError(setting, checkpoint, {
|
|
1182
|
+
checkpoint: {
|
|
1183
|
+
...checkpoint,
|
|
1184
|
+
status: "stoppedByError"
|
|
1185
|
+
},
|
|
1186
|
+
step: {
|
|
1187
|
+
...step,
|
|
1188
|
+
finishedAt: Date.now()
|
|
1189
|
+
},
|
|
1190
|
+
error: {
|
|
1191
|
+
name: "MaxRetriesExceeded",
|
|
1192
|
+
message: `Max retries (${setting.maxRetries}) exceeded: No tool call or text generated`,
|
|
1193
|
+
isRetryable: false
|
|
1194
|
+
}
|
|
1195
|
+
});
|
|
1196
|
+
}
|
|
1386
1197
|
const reason = JSON.stringify({
|
|
1387
|
-
error: "Error: No tool call generated",
|
|
1388
|
-
message: "You must generate a tool call. Try again."
|
|
1198
|
+
error: "Error: No tool call or text generated",
|
|
1199
|
+
message: "You must generate a tool call or provide a response. Try again."
|
|
1389
1200
|
});
|
|
1390
1201
|
return retry(setting, checkpoint, {
|
|
1391
1202
|
reason,
|
|
@@ -1397,11 +1208,15 @@ async function generatingToolCallLogic({
|
|
|
1397
1208
|
const sorted = sortToolCallsByPriority(classified);
|
|
1398
1209
|
if (finishReason === "tool-calls" || finishReason === "stop") {
|
|
1399
1210
|
const toolCallParts = buildToolCallParts(sorted);
|
|
1400
|
-
const contents = [...toolCallParts];
|
|
1401
|
-
if (text) {
|
|
1402
|
-
contents.push({ type: "textPart", text });
|
|
1403
|
-
}
|
|
1211
|
+
const contents = [...thinkingParts, ...text ? [{ type: "textPart", text }] : [], ...toolCallParts];
|
|
1404
1212
|
const allToolCalls = buildToolCalls(sorted);
|
|
1213
|
+
if (thinkingText && !reasoningCompletedViaCallback) {
|
|
1214
|
+
await eventListener(
|
|
1215
|
+
createRuntimeEvent("completeReasoning", setting.jobId, setting.runId, {
|
|
1216
|
+
text: thinkingText
|
|
1217
|
+
})
|
|
1218
|
+
);
|
|
1219
|
+
}
|
|
1405
1220
|
return callTools(setting, checkpoint, {
|
|
1406
1221
|
newMessage: createExpertMessage(contents),
|
|
1407
1222
|
toolCalls: allToolCalls,
|
|
@@ -1413,6 +1228,24 @@ async function generatingToolCallLogic({
|
|
|
1413
1228
|
if (!firstToolCall) {
|
|
1414
1229
|
throw new Error("No tool call found");
|
|
1415
1230
|
}
|
|
1231
|
+
const currentRetryCount = checkpoint.retryCount ?? 0;
|
|
1232
|
+
if (currentRetryCount >= setting.maxRetries) {
|
|
1233
|
+
return stopRunByError(setting, checkpoint, {
|
|
1234
|
+
checkpoint: {
|
|
1235
|
+
...checkpoint,
|
|
1236
|
+
status: "stoppedByError"
|
|
1237
|
+
},
|
|
1238
|
+
step: {
|
|
1239
|
+
...step,
|
|
1240
|
+
finishedAt: Date.now()
|
|
1241
|
+
},
|
|
1242
|
+
error: {
|
|
1243
|
+
name: "MaxRetriesExceeded",
|
|
1244
|
+
message: `Max retries (${setting.maxRetries}) exceeded: Generation length exceeded`,
|
|
1245
|
+
isRetryable: false
|
|
1246
|
+
}
|
|
1247
|
+
});
|
|
1248
|
+
}
|
|
1416
1249
|
const reason = JSON.stringify({
|
|
1417
1250
|
error: "Error: Tool call generation failed",
|
|
1418
1251
|
message: "Generation length exceeded. Try again."
|
|
@@ -1662,11 +1495,6 @@ async function resolvingToolResultLogic({
|
|
|
1662
1495
|
});
|
|
1663
1496
|
}
|
|
1664
1497
|
|
|
1665
|
-
// src/state-machine/states/resolving-thought.ts
|
|
1666
|
-
async function resolvingThoughtLogic(context) {
|
|
1667
|
-
return resolvingToolResultLogic(context);
|
|
1668
|
-
}
|
|
1669
|
-
|
|
1670
1498
|
// src/state-machine/machine.ts
|
|
1671
1499
|
var runtimeStateMachine = setup({
|
|
1672
1500
|
types: {
|
|
@@ -1689,7 +1517,8 @@ var runtimeStateMachine = setup({
|
|
|
1689
1517
|
startedAt: Date.now()
|
|
1690
1518
|
},
|
|
1691
1519
|
eventListener: input.eventListener,
|
|
1692
|
-
skillManagers: input.skillManagers
|
|
1520
|
+
skillManagers: input.skillManagers,
|
|
1521
|
+
llmExecutor: input.llmExecutor
|
|
1693
1522
|
}),
|
|
1694
1523
|
states: {
|
|
1695
1524
|
Init: {
|
|
@@ -1768,7 +1597,8 @@ var runtimeStateMachine = setup({
|
|
|
1768
1597
|
checkpoint: ({ context, event }) => ({
|
|
1769
1598
|
...context.checkpoint,
|
|
1770
1599
|
messages: [...context.checkpoint.messages, ...event.newMessages],
|
|
1771
|
-
usage: sumUsage(context.checkpoint.usage, event.usage)
|
|
1600
|
+
usage: sumUsage(context.checkpoint.usage, event.usage),
|
|
1601
|
+
retryCount: (context.checkpoint.retryCount ?? 0) + 1
|
|
1772
1602
|
}),
|
|
1773
1603
|
step: ({ context, event }) => ({
|
|
1774
1604
|
...context.step,
|
|
@@ -1779,15 +1609,42 @@ var runtimeStateMachine = setup({
|
|
|
1779
1609
|
})
|
|
1780
1610
|
})
|
|
1781
1611
|
},
|
|
1612
|
+
stopRunByError: {
|
|
1613
|
+
target: "Stopped",
|
|
1614
|
+
actions: assign({
|
|
1615
|
+
checkpoint: ({ event }) => ({
|
|
1616
|
+
...event.checkpoint,
|
|
1617
|
+
error: event.error
|
|
1618
|
+
}),
|
|
1619
|
+
step: ({ event }) => ({
|
|
1620
|
+
...event.step,
|
|
1621
|
+
inputMessages: void 0
|
|
1622
|
+
})
|
|
1623
|
+
})
|
|
1624
|
+
},
|
|
1625
|
+
completeRun: {
|
|
1626
|
+
target: "Stopped",
|
|
1627
|
+
actions: assign({
|
|
1628
|
+
checkpoint: ({ event }) => ({ ...event.checkpoint, retryCount: 0 }),
|
|
1629
|
+
step: ({ event }) => ({
|
|
1630
|
+
...event.step,
|
|
1631
|
+
inputMessages: void 0
|
|
1632
|
+
})
|
|
1633
|
+
})
|
|
1634
|
+
},
|
|
1782
1635
|
callTools: {
|
|
1783
1636
|
target: "CallingTool",
|
|
1784
1637
|
actions: assign({
|
|
1785
|
-
checkpoint: ({ context, event }) =>
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1638
|
+
checkpoint: ({ context, event }) => {
|
|
1639
|
+
const newUsage = sumUsage(context.checkpoint.usage, event.usage);
|
|
1640
|
+
return {
|
|
1641
|
+
...context.checkpoint,
|
|
1642
|
+
messages: [...context.checkpoint.messages, event.newMessage],
|
|
1643
|
+
usage: newUsage,
|
|
1644
|
+
contextWindowUsage: context.checkpoint.contextWindow ? calculateContextWindowUsage(newUsage, context.checkpoint.contextWindow) : void 0,
|
|
1645
|
+
retryCount: 0
|
|
1646
|
+
};
|
|
1647
|
+
},
|
|
1791
1648
|
step: ({ context, event }) => ({
|
|
1792
1649
|
...context.step,
|
|
1793
1650
|
newMessages: [event.newMessage],
|
|
@@ -1799,12 +1656,17 @@ var runtimeStateMachine = setup({
|
|
|
1799
1656
|
callInteractiveTool: {
|
|
1800
1657
|
target: "CallingInteractiveTool",
|
|
1801
1658
|
actions: assign({
|
|
1802
|
-
checkpoint: ({ context, event }) =>
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1659
|
+
checkpoint: ({ context, event }) => {
|
|
1660
|
+
const newUsage = sumUsage(context.checkpoint.usage, event.usage);
|
|
1661
|
+
return {
|
|
1662
|
+
...context.checkpoint,
|
|
1663
|
+
messages: [...context.checkpoint.messages, event.newMessage],
|
|
1664
|
+
usage: newUsage,
|
|
1665
|
+
contextWindowUsage: context.checkpoint.contextWindow ? calculateContextWindowUsage(newUsage, context.checkpoint.contextWindow) : void 0,
|
|
1666
|
+
retryCount: 0
|
|
1667
|
+
// Reset on successful generation
|
|
1668
|
+
};
|
|
1669
|
+
},
|
|
1808
1670
|
step: ({ context, event }) => ({
|
|
1809
1671
|
...context.step,
|
|
1810
1672
|
newMessages: [event.newMessage],
|
|
@@ -1816,12 +1678,17 @@ var runtimeStateMachine = setup({
|
|
|
1816
1678
|
callDelegate: {
|
|
1817
1679
|
target: "CallingDelegate",
|
|
1818
1680
|
actions: assign({
|
|
1819
|
-
checkpoint: ({ context, event }) =>
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1681
|
+
checkpoint: ({ context, event }) => {
|
|
1682
|
+
const newUsage = sumUsage(context.checkpoint.usage, event.usage);
|
|
1683
|
+
return {
|
|
1684
|
+
...context.checkpoint,
|
|
1685
|
+
messages: [...context.checkpoint.messages, event.newMessage],
|
|
1686
|
+
usage: newUsage,
|
|
1687
|
+
contextWindowUsage: context.checkpoint.contextWindow ? calculateContextWindowUsage(newUsage, context.checkpoint.contextWindow) : void 0,
|
|
1688
|
+
retryCount: 0
|
|
1689
|
+
// Reset on successful generation
|
|
1690
|
+
};
|
|
1691
|
+
},
|
|
1825
1692
|
step: ({ context, event }) => ({
|
|
1826
1693
|
...context.step,
|
|
1827
1694
|
newMessages: [event.newMessage],
|
|
@@ -1844,15 +1711,6 @@ var runtimeStateMachine = setup({
|
|
|
1844
1711
|
})
|
|
1845
1712
|
})
|
|
1846
1713
|
},
|
|
1847
|
-
resolveThought: {
|
|
1848
|
-
target: "ResolvingThought",
|
|
1849
|
-
actions: assign({
|
|
1850
|
-
step: ({ context, event }) => ({
|
|
1851
|
-
...context.step,
|
|
1852
|
-
toolResults: [event.toolResult]
|
|
1853
|
-
})
|
|
1854
|
-
})
|
|
1855
|
-
},
|
|
1856
1714
|
attemptCompletion: {
|
|
1857
1715
|
target: "GeneratingRunResult",
|
|
1858
1716
|
actions: assign({
|
|
@@ -1905,23 +1763,6 @@ var runtimeStateMachine = setup({
|
|
|
1905
1763
|
}
|
|
1906
1764
|
}
|
|
1907
1765
|
},
|
|
1908
|
-
ResolvingThought: {
|
|
1909
|
-
on: {
|
|
1910
|
-
finishToolCall: {
|
|
1911
|
-
target: "FinishingStep",
|
|
1912
|
-
actions: assign({
|
|
1913
|
-
checkpoint: ({ context, event }) => ({
|
|
1914
|
-
...context.checkpoint,
|
|
1915
|
-
messages: [...context.checkpoint.messages, ...event.newMessages]
|
|
1916
|
-
}),
|
|
1917
|
-
step: ({ context, event }) => ({
|
|
1918
|
-
...context.step,
|
|
1919
|
-
newMessages: [...context.step.newMessages, ...event.newMessages]
|
|
1920
|
-
})
|
|
1921
|
-
})
|
|
1922
|
-
}
|
|
1923
|
-
}
|
|
1924
|
-
},
|
|
1925
1766
|
GeneratingRunResult: {
|
|
1926
1767
|
on: {
|
|
1927
1768
|
retry: {
|
|
@@ -1930,7 +1771,8 @@ var runtimeStateMachine = setup({
|
|
|
1930
1771
|
checkpoint: ({ context, event }) => ({
|
|
1931
1772
|
...context.checkpoint,
|
|
1932
1773
|
messages: [...context.checkpoint.messages, ...event.newMessages],
|
|
1933
|
-
usage: sumUsage(context.checkpoint.usage, event.usage)
|
|
1774
|
+
usage: sumUsage(context.checkpoint.usage, event.usage),
|
|
1775
|
+
retryCount: (context.checkpoint.retryCount ?? 0) + 1
|
|
1934
1776
|
}),
|
|
1935
1777
|
step: ({ context, event }) => ({
|
|
1936
1778
|
...context.step,
|
|
@@ -1941,10 +1783,23 @@ var runtimeStateMachine = setup({
|
|
|
1941
1783
|
})
|
|
1942
1784
|
})
|
|
1943
1785
|
},
|
|
1786
|
+
stopRunByError: {
|
|
1787
|
+
target: "Stopped",
|
|
1788
|
+
actions: assign({
|
|
1789
|
+
checkpoint: ({ event }) => ({
|
|
1790
|
+
...event.checkpoint,
|
|
1791
|
+
error: event.error
|
|
1792
|
+
}),
|
|
1793
|
+
step: ({ event }) => ({
|
|
1794
|
+
...event.step,
|
|
1795
|
+
inputMessages: void 0
|
|
1796
|
+
})
|
|
1797
|
+
})
|
|
1798
|
+
},
|
|
1944
1799
|
completeRun: {
|
|
1945
1800
|
target: "Stopped",
|
|
1946
1801
|
actions: assign({
|
|
1947
|
-
checkpoint: ({ event }) => event.checkpoint,
|
|
1802
|
+
checkpoint: ({ event }) => ({ ...event.checkpoint, retryCount: 0 }),
|
|
1948
1803
|
step: ({ event }) => ({
|
|
1949
1804
|
...event.step,
|
|
1950
1805
|
inputMessages: void 0
|
|
@@ -2017,7 +1872,6 @@ var StateMachineLogics = {
|
|
|
2017
1872
|
GeneratingToolCall: generatingToolCallLogic,
|
|
2018
1873
|
CallingTool: callingToolLogic,
|
|
2019
1874
|
ResolvingToolResult: resolvingToolResultLogic,
|
|
2020
|
-
ResolvingThought: resolvingThoughtLogic,
|
|
2021
1875
|
GeneratingRunResult: generatingRunResultLogic,
|
|
2022
1876
|
CallingInteractiveTool: callingInteractiveToolLogic,
|
|
2023
1877
|
CallingDelegate: callingDelegateLogic,
|
|
@@ -2048,13 +1902,14 @@ var StateMachineCoordinator = class {
|
|
|
2048
1902
|
* Execute the state machine and return the final checkpoint.
|
|
2049
1903
|
*/
|
|
2050
1904
|
async execute() {
|
|
2051
|
-
const { setting, initialCheckpoint, eventListener, skillManagers } = this.params;
|
|
1905
|
+
const { setting, initialCheckpoint, eventListener, skillManagers, llmExecutor } = this.params;
|
|
2052
1906
|
this.actor = this.actorFactory.create({
|
|
2053
1907
|
input: {
|
|
2054
1908
|
setting,
|
|
2055
1909
|
initialCheckpoint,
|
|
2056
1910
|
eventListener,
|
|
2057
|
-
skillManagers
|
|
1911
|
+
skillManagers,
|
|
1912
|
+
llmExecutor
|
|
2058
1913
|
}
|
|
2059
1914
|
});
|
|
2060
1915
|
return new Promise((resolve, reject) => {
|
|
@@ -2131,118 +1986,6 @@ async function executeStateMachine(params) {
|
|
|
2131
1986
|
const coordinator = new StateMachineCoordinator(params);
|
|
2132
1987
|
return coordinator.execute();
|
|
2133
1988
|
}
|
|
2134
|
-
|
|
2135
|
-
// src/helpers/checkpoint.ts
|
|
2136
|
-
function createInitialCheckpoint(checkpointId, params) {
|
|
2137
|
-
return {
|
|
2138
|
-
id: checkpointId,
|
|
2139
|
-
jobId: params.jobId,
|
|
2140
|
-
runId: params.runId,
|
|
2141
|
-
expert: {
|
|
2142
|
-
key: params.expertKey,
|
|
2143
|
-
name: params.expert.name,
|
|
2144
|
-
version: params.expert.version
|
|
2145
|
-
},
|
|
2146
|
-
stepNumber: 1,
|
|
2147
|
-
status: "init",
|
|
2148
|
-
messages: [],
|
|
2149
|
-
usage: createEmptyUsage(),
|
|
2150
|
-
contextWindow: params.contextWindow,
|
|
2151
|
-
contextWindowUsage: params.contextWindow ? 0 : void 0
|
|
2152
|
-
};
|
|
2153
|
-
}
|
|
2154
|
-
function createNextStepCheckpoint(checkpointId, checkpoint) {
|
|
2155
|
-
return {
|
|
2156
|
-
...checkpoint,
|
|
2157
|
-
id: checkpointId,
|
|
2158
|
-
stepNumber: checkpoint.stepNumber + 1
|
|
2159
|
-
};
|
|
2160
|
-
}
|
|
2161
|
-
function buildDelegationReturnState(currentSetting, resultCheckpoint, parentCheckpoint) {
|
|
2162
|
-
const { messages, delegatedBy } = resultCheckpoint;
|
|
2163
|
-
if (!delegatedBy) {
|
|
2164
|
-
throw new Error("delegatedBy is required for buildDelegationReturnState");
|
|
2165
|
-
}
|
|
2166
|
-
const delegateResultMessage = messages[messages.length - 1];
|
|
2167
|
-
if (!delegateResultMessage || delegateResultMessage.type !== "expertMessage") {
|
|
2168
|
-
throw new Error("Delegation error: delegation result message is incorrect");
|
|
2169
|
-
}
|
|
2170
|
-
const delegateText = delegateResultMessage.contents.find((content) => content.type === "textPart");
|
|
2171
|
-
if (!delegateText) {
|
|
2172
|
-
throw new Error("Delegation error: delegation result message does not contain a text");
|
|
2173
|
-
}
|
|
2174
|
-
const { expert, toolCallId, toolName } = delegatedBy;
|
|
2175
|
-
return {
|
|
2176
|
-
setting: {
|
|
2177
|
-
...currentSetting,
|
|
2178
|
-
expertKey: expert.key,
|
|
2179
|
-
input: {
|
|
2180
|
-
interactiveToolCallResult: {
|
|
2181
|
-
toolCallId,
|
|
2182
|
-
toolName,
|
|
2183
|
-
skillName: `delegate/${resultCheckpoint.expert.key}`,
|
|
2184
|
-
text: delegateText.text
|
|
2185
|
-
}
|
|
2186
|
-
}
|
|
2187
|
-
},
|
|
2188
|
-
checkpoint: {
|
|
2189
|
-
...parentCheckpoint,
|
|
2190
|
-
stepNumber: resultCheckpoint.stepNumber,
|
|
2191
|
-
usage: resultCheckpoint.usage,
|
|
2192
|
-
pendingToolCalls: parentCheckpoint.pendingToolCalls,
|
|
2193
|
-
partialToolResults: parentCheckpoint.partialToolResults
|
|
2194
|
-
}
|
|
2195
|
-
};
|
|
2196
|
-
}
|
|
2197
|
-
async function resolveExpertToRun(expertKey, experts, clientOptions) {
|
|
2198
|
-
if (experts[expertKey]) {
|
|
2199
|
-
return experts[expertKey];
|
|
2200
|
-
}
|
|
2201
|
-
const client = new ApiV1Client({
|
|
2202
|
-
baseUrl: clientOptions.perstackApiBaseUrl,
|
|
2203
|
-
apiKey: clientOptions.perstackApiKey
|
|
2204
|
-
});
|
|
2205
|
-
const { expert } = await client.registry.experts.get({ expertKey });
|
|
2206
|
-
return toRuntimeExpert(expert);
|
|
2207
|
-
}
|
|
2208
|
-
function toRuntimeExpert(expert) {
|
|
2209
|
-
const skills = Object.fromEntries(
|
|
2210
|
-
Object.entries(expert.skills).map(([name, skill]) => {
|
|
2211
|
-
switch (skill.type) {
|
|
2212
|
-
case "mcpStdioSkill":
|
|
2213
|
-
return [name, { ...skill, name }];
|
|
2214
|
-
case "mcpSseSkill":
|
|
2215
|
-
return [name, { ...skill, name }];
|
|
2216
|
-
case "interactiveSkill":
|
|
2217
|
-
return [name, { ...skill, name }];
|
|
2218
|
-
default: {
|
|
2219
|
-
throw new Error(`Unknown skill type: ${skill.type}`);
|
|
2220
|
-
}
|
|
2221
|
-
}
|
|
2222
|
-
})
|
|
2223
|
-
);
|
|
2224
|
-
return { ...expert, skills };
|
|
2225
|
-
}
|
|
2226
|
-
|
|
2227
|
-
// src/helpers/setup-experts.ts
|
|
2228
|
-
async function setupExperts(setting, resolveExpertToRun2 = resolveExpertToRun) {
|
|
2229
|
-
const { expertKey } = setting;
|
|
2230
|
-
const experts = { ...setting.experts };
|
|
2231
|
-
const clientOptions = {
|
|
2232
|
-
perstackApiBaseUrl: setting.perstackApiBaseUrl,
|
|
2233
|
-
perstackApiKey: setting.perstackApiKey
|
|
2234
|
-
};
|
|
2235
|
-
const expertToRun = await resolveExpertToRun2(expertKey, experts, clientOptions);
|
|
2236
|
-
experts[expertKey] = expertToRun;
|
|
2237
|
-
for (const delegateName of expertToRun.delegates) {
|
|
2238
|
-
const delegate = await resolveExpertToRun2(delegateName, experts, clientOptions);
|
|
2239
|
-
if (!delegate) {
|
|
2240
|
-
throw new Error(`Delegate ${delegateName} not found`);
|
|
2241
|
-
}
|
|
2242
|
-
experts[delegateName] = delegate;
|
|
2243
|
-
}
|
|
2244
|
-
return { expertToRun, experts };
|
|
2245
|
-
}
|
|
2246
1989
|
var SingleDelegationStrategy = class {
|
|
2247
1990
|
async execute(delegations, setting, context, parentExpert, _runFn, _parentOptions) {
|
|
2248
1991
|
if (delegations.length !== 1) {
|
|
@@ -2409,13 +2152,15 @@ var ParallelDelegationStrategy = class {
|
|
|
2409
2152
|
}
|
|
2410
2153
|
const textPart = lastMessage.contents.find((c) => c.type === "textPart");
|
|
2411
2154
|
if (!textPart || textPart.type !== "textPart") {
|
|
2412
|
-
|
|
2155
|
+
console.warn(
|
|
2156
|
+
`Delegation result from ${expertKey} has no text content. Parent expert will receive empty string.`
|
|
2157
|
+
);
|
|
2413
2158
|
}
|
|
2414
2159
|
return {
|
|
2415
2160
|
toolCallId,
|
|
2416
2161
|
toolName,
|
|
2417
2162
|
expertKey,
|
|
2418
|
-
text: textPart.text,
|
|
2163
|
+
text: textPart?.type === "textPart" ? textPart.text : "",
|
|
2419
2164
|
stepNumber: checkpoint.stepNumber,
|
|
2420
2165
|
deltaUsage: checkpoint.usage
|
|
2421
2166
|
};
|
|
@@ -2468,22 +2213,1298 @@ var RunEventEmitter = class {
|
|
|
2468
2213
|
}
|
|
2469
2214
|
};
|
|
2470
2215
|
|
|
2471
|
-
// src/
|
|
2472
|
-
var
|
|
2473
|
-
|
|
2216
|
+
// src/helpers/provider-adapter-factory.ts
|
|
2217
|
+
var PROVIDER_PACKAGE_NAMES = {
|
|
2218
|
+
anthropic: "anthropic-provider",
|
|
2219
|
+
openai: "openai-provider",
|
|
2220
|
+
google: "google-provider",
|
|
2221
|
+
ollama: "ollama-provider",
|
|
2222
|
+
"azure-openai": "azure-openai-provider",
|
|
2223
|
+
"amazon-bedrock": "bedrock-provider",
|
|
2224
|
+
"google-vertex": "vertex-provider",
|
|
2225
|
+
deepseek: "deepseek-provider"
|
|
2226
|
+
};
|
|
2227
|
+
var ProviderNotInstalledError = class extends Error {
|
|
2228
|
+
constructor(providerName) {
|
|
2229
|
+
const packageName = PROVIDER_PACKAGE_NAMES[providerName];
|
|
2230
|
+
super(
|
|
2231
|
+
`Provider "${providerName}" is not installed. Run: npm install @perstack/${packageName}`
|
|
2232
|
+
);
|
|
2233
|
+
this.name = "ProviderNotInstalledError";
|
|
2234
|
+
}
|
|
2235
|
+
};
|
|
2236
|
+
var adapterRegistry = /* @__PURE__ */ new Map();
|
|
2237
|
+
var adapterInstances = /* @__PURE__ */ new Map();
|
|
2238
|
+
var pendingCreations = /* @__PURE__ */ new Map();
|
|
2239
|
+
function getCacheKey(config, options) {
|
|
2240
|
+
return JSON.stringify({
|
|
2241
|
+
providerName: config.providerName,
|
|
2242
|
+
apiKey: "apiKey" in config ? config.apiKey : void 0,
|
|
2243
|
+
baseUrl: "baseUrl" in config ? config.baseUrl : void 0,
|
|
2244
|
+
proxyUrl: options?.proxyUrl
|
|
2245
|
+
});
|
|
2246
|
+
}
|
|
2247
|
+
function registerProviderAdapter(providerName, loader) {
|
|
2248
|
+
adapterRegistry.set(providerName, loader);
|
|
2249
|
+
}
|
|
2250
|
+
async function createProviderAdapter(config, options) {
|
|
2251
|
+
const cacheKey = getCacheKey(config, options);
|
|
2252
|
+
const cached = adapterInstances.get(cacheKey);
|
|
2253
|
+
if (cached) return cached;
|
|
2254
|
+
const pending = pendingCreations.get(cacheKey);
|
|
2255
|
+
if (pending) return pending;
|
|
2256
|
+
const loader = adapterRegistry.get(config.providerName);
|
|
2257
|
+
if (!loader) {
|
|
2258
|
+
throw new ProviderNotInstalledError(config.providerName);
|
|
2259
|
+
}
|
|
2260
|
+
const creationPromise = (async () => {
|
|
2261
|
+
try {
|
|
2262
|
+
const AdapterClass = await loader();
|
|
2263
|
+
const adapter = new AdapterClass(config, options);
|
|
2264
|
+
adapterInstances.set(cacheKey, adapter);
|
|
2265
|
+
return adapter;
|
|
2266
|
+
} finally {
|
|
2267
|
+
pendingCreations.delete(cacheKey);
|
|
2268
|
+
}
|
|
2269
|
+
})();
|
|
2270
|
+
pendingCreations.set(cacheKey, creationPromise);
|
|
2271
|
+
return creationPromise;
|
|
2272
|
+
}
|
|
2273
|
+
var BaseProviderAdapter = class {
|
|
2274
|
+
options;
|
|
2275
|
+
constructor(options) {
|
|
2474
2276
|
this.options = options;
|
|
2475
2277
|
}
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
)
|
|
2278
|
+
getProviderTools(_toolNames, _options) {
|
|
2279
|
+
return {};
|
|
2280
|
+
}
|
|
2281
|
+
getProviderOptions(_config) {
|
|
2282
|
+
return void 0;
|
|
2283
|
+
}
|
|
2284
|
+
getReasoningOptions(_budget) {
|
|
2285
|
+
return void 0;
|
|
2286
|
+
}
|
|
2287
|
+
normalizeError(error) {
|
|
2288
|
+
if (error instanceof Error) {
|
|
2289
|
+
return {
|
|
2290
|
+
name: error.name,
|
|
2291
|
+
message: error.message,
|
|
2292
|
+
isRetryable: this.isRetryable(error),
|
|
2293
|
+
provider: this.providerName,
|
|
2294
|
+
originalError: error
|
|
2295
|
+
};
|
|
2296
|
+
}
|
|
2297
|
+
return {
|
|
2298
|
+
name: "UnknownError",
|
|
2299
|
+
message: String(error),
|
|
2300
|
+
isRetryable: false,
|
|
2301
|
+
provider: this.providerName,
|
|
2302
|
+
originalError: error
|
|
2303
|
+
};
|
|
2304
|
+
}
|
|
2305
|
+
isRetryable(error) {
|
|
2306
|
+
if (error instanceof Error) {
|
|
2307
|
+
const retryablePatterns = [
|
|
2308
|
+
/rate limit/i,
|
|
2309
|
+
/timeout/i,
|
|
2310
|
+
/overloaded/i,
|
|
2311
|
+
/service unavailable/i,
|
|
2312
|
+
/internal server error/i,
|
|
2313
|
+
/bad gateway/i,
|
|
2314
|
+
/gateway timeout/i
|
|
2315
|
+
];
|
|
2316
|
+
return retryablePatterns.some((pattern) => pattern.test(error.message));
|
|
2317
|
+
}
|
|
2318
|
+
return false;
|
|
2319
|
+
}
|
|
2320
|
+
createProxyFetch(proxyUrl) {
|
|
2321
|
+
const agent = new ProxyAgent(proxyUrl);
|
|
2322
|
+
return (input, init) => {
|
|
2323
|
+
return fetch(input, { ...init, dispatcher: agent });
|
|
2324
|
+
};
|
|
2325
|
+
}
|
|
2326
|
+
};
|
|
2327
|
+
function normalizeAnthropicError(error) {
|
|
2328
|
+
if (error instanceof APICallError) {
|
|
2329
|
+
return {
|
|
2330
|
+
name: error.name,
|
|
2331
|
+
message: error.message,
|
|
2332
|
+
statusCode: error.statusCode,
|
|
2333
|
+
isRetryable: isAnthropicRetryable(error),
|
|
2334
|
+
provider: "anthropic",
|
|
2335
|
+
originalError: error
|
|
2336
|
+
};
|
|
2337
|
+
}
|
|
2338
|
+
if (error instanceof Error) {
|
|
2339
|
+
return {
|
|
2340
|
+
name: error.name,
|
|
2341
|
+
message: error.message,
|
|
2342
|
+
isRetryable: isAnthropicRetryable(error),
|
|
2343
|
+
provider: "anthropic",
|
|
2344
|
+
originalError: error
|
|
2345
|
+
};
|
|
2346
|
+
}
|
|
2347
|
+
return {
|
|
2348
|
+
name: "UnknownError",
|
|
2349
|
+
message: String(error),
|
|
2350
|
+
isRetryable: false,
|
|
2351
|
+
provider: "anthropic",
|
|
2352
|
+
originalError: error
|
|
2353
|
+
};
|
|
2354
|
+
}
|
|
2355
|
+
function isAnthropicRetryable(error) {
|
|
2356
|
+
if (error instanceof APICallError) {
|
|
2357
|
+
if (error.isRetryable) return true;
|
|
2358
|
+
const statusCode = error.statusCode;
|
|
2359
|
+
if (statusCode === 429) return true;
|
|
2360
|
+
if (statusCode === 500) return true;
|
|
2361
|
+
if (statusCode === 502) return true;
|
|
2362
|
+
if (statusCode === 503) return true;
|
|
2363
|
+
if (statusCode === 504) return true;
|
|
2364
|
+
}
|
|
2365
|
+
if (error instanceof Error) {
|
|
2366
|
+
const message = error.message.toLowerCase();
|
|
2367
|
+
if (message.includes("rate limit")) return true;
|
|
2368
|
+
if (message.includes("overloaded")) return true;
|
|
2369
|
+
if (message.includes("timeout")) return true;
|
|
2370
|
+
if (message.includes("service unavailable")) return true;
|
|
2371
|
+
}
|
|
2372
|
+
return false;
|
|
2373
|
+
}
|
|
2374
|
+
|
|
2375
|
+
// ../../packages/providers/anthropic/src/skills.ts
|
|
2376
|
+
function convertSkill(skill) {
|
|
2377
|
+
if (skill.type === "builtin") {
|
|
2378
|
+
return {
|
|
2379
|
+
type: "builtin",
|
|
2380
|
+
name: skill.skillId
|
|
2381
|
+
};
|
|
2382
|
+
}
|
|
2383
|
+
try {
|
|
2384
|
+
return {
|
|
2385
|
+
type: "custom",
|
|
2386
|
+
name: skill.name,
|
|
2387
|
+
mcp_config: JSON.parse(skill.definition)
|
|
2388
|
+
};
|
|
2389
|
+
} catch (error) {
|
|
2390
|
+
throw new Error(
|
|
2391
|
+
`Invalid JSON in custom skill definition for "${skill.name}": ${error instanceof Error ? error.message : String(error)}`
|
|
2392
|
+
);
|
|
2393
|
+
}
|
|
2394
|
+
}
|
|
2395
|
+
function buildProviderOptions(skills) {
|
|
2396
|
+
if (!skills || skills.length === 0) {
|
|
2397
|
+
return void 0;
|
|
2398
|
+
}
|
|
2399
|
+
return {
|
|
2400
|
+
anthropic: {
|
|
2401
|
+
container: {
|
|
2402
|
+
skills: skills.map(convertSkill)
|
|
2403
|
+
}
|
|
2404
|
+
}
|
|
2405
|
+
};
|
|
2406
|
+
}
|
|
2407
|
+
|
|
2408
|
+
// ../../packages/providers/anthropic/src/tools.ts
|
|
2409
|
+
function buildAnthropicTools(client, toolNames, options) {
|
|
2410
|
+
const tools = {};
|
|
2411
|
+
for (const name of toolNames) {
|
|
2412
|
+
switch (name) {
|
|
2413
|
+
case "webSearch": {
|
|
2414
|
+
const webSearchTool = client.tools.webSearch_20250305({
|
|
2415
|
+
maxUses: options?.webSearch?.maxUses,
|
|
2416
|
+
allowedDomains: options?.webSearch?.allowedDomains
|
|
2417
|
+
});
|
|
2418
|
+
tools["web_search"] = webSearchTool;
|
|
2419
|
+
break;
|
|
2420
|
+
}
|
|
2421
|
+
case "webFetch": {
|
|
2422
|
+
const webFetchTool = client.tools.webFetch_20250910({
|
|
2423
|
+
maxUses: options?.webFetch?.maxUses
|
|
2424
|
+
});
|
|
2425
|
+
tools["web_fetch"] = webFetchTool;
|
|
2426
|
+
break;
|
|
2427
|
+
}
|
|
2428
|
+
case "codeExecution": {
|
|
2429
|
+
const codeExecutionTool = client.tools.codeExecution_20250522();
|
|
2430
|
+
tools["code_execution"] = codeExecutionTool;
|
|
2431
|
+
break;
|
|
2432
|
+
}
|
|
2433
|
+
}
|
|
2434
|
+
}
|
|
2435
|
+
return tools;
|
|
2436
|
+
}
|
|
2437
|
+
|
|
2438
|
+
// ../../packages/providers/anthropic/src/adapter.ts
|
|
2439
|
+
var AnthropicProviderAdapter = class extends BaseProviderAdapter {
|
|
2440
|
+
constructor(config, options) {
|
|
2441
|
+
super(options);
|
|
2442
|
+
this.config = config;
|
|
2443
|
+
this.client = createAnthropic({
|
|
2444
|
+
apiKey: config.apiKey,
|
|
2445
|
+
baseURL: config.baseUrl,
|
|
2446
|
+
headers: config.headers,
|
|
2447
|
+
fetch: options?.proxyUrl ? this.createProxyFetch(options.proxyUrl) : void 0
|
|
2448
|
+
});
|
|
2449
|
+
}
|
|
2450
|
+
providerName = "anthropic";
|
|
2451
|
+
client;
|
|
2452
|
+
createModel(modelId) {
|
|
2453
|
+
return this.client(modelId);
|
|
2454
|
+
}
|
|
2455
|
+
getProviderTools(toolNames, options) {
|
|
2456
|
+
return buildAnthropicTools(this.client, toolNames, options);
|
|
2457
|
+
}
|
|
2458
|
+
getProviderOptions(config) {
|
|
2459
|
+
return buildProviderOptions(config?.skills);
|
|
2460
|
+
}
|
|
2461
|
+
getReasoningOptions(budget) {
|
|
2462
|
+
const budgetTokens = this.budgetToTokens(budget);
|
|
2463
|
+
return {
|
|
2464
|
+
anthropic: {
|
|
2465
|
+
thinking: { type: "enabled", budgetTokens }
|
|
2466
|
+
}
|
|
2467
|
+
};
|
|
2468
|
+
}
|
|
2469
|
+
budgetToTokens(budget) {
|
|
2470
|
+
if (typeof budget === "number") return budget;
|
|
2471
|
+
const map = {
|
|
2472
|
+
minimal: 1024,
|
|
2473
|
+
low: 2048,
|
|
2474
|
+
medium: 5e3,
|
|
2475
|
+
high: 1e4
|
|
2476
|
+
};
|
|
2477
|
+
return map[budget] ?? 5e3;
|
|
2478
|
+
}
|
|
2479
|
+
normalizeError(error) {
|
|
2480
|
+
return normalizeAnthropicError(error);
|
|
2481
|
+
}
|
|
2482
|
+
isRetryable(error) {
|
|
2483
|
+
return isAnthropicRetryable(error);
|
|
2484
|
+
}
|
|
2485
|
+
};
|
|
2486
|
+
function normalizeAzureOpenAIError(error) {
|
|
2487
|
+
if (error instanceof APICallError) {
|
|
2488
|
+
return {
|
|
2489
|
+
name: error.name,
|
|
2490
|
+
message: error.message,
|
|
2491
|
+
statusCode: error.statusCode,
|
|
2492
|
+
isRetryable: isAzureOpenAIRetryable(error),
|
|
2493
|
+
provider: "azure-openai",
|
|
2494
|
+
originalError: error
|
|
2495
|
+
};
|
|
2496
|
+
}
|
|
2497
|
+
if (error instanceof Error) {
|
|
2498
|
+
return {
|
|
2499
|
+
name: error.name,
|
|
2500
|
+
message: error.message,
|
|
2501
|
+
isRetryable: isAzureOpenAIRetryable(error),
|
|
2502
|
+
provider: "azure-openai",
|
|
2503
|
+
originalError: error
|
|
2504
|
+
};
|
|
2505
|
+
}
|
|
2506
|
+
return {
|
|
2507
|
+
name: "UnknownError",
|
|
2508
|
+
message: String(error),
|
|
2509
|
+
isRetryable: false,
|
|
2510
|
+
provider: "azure-openai",
|
|
2511
|
+
originalError: error
|
|
2512
|
+
};
|
|
2513
|
+
}
|
|
2514
|
+
function isAzureOpenAIRetryable(error) {
|
|
2515
|
+
if (error instanceof APICallError) {
|
|
2516
|
+
if (error.isRetryable) return true;
|
|
2517
|
+
const statusCode = error.statusCode;
|
|
2518
|
+
if (statusCode === 429) return true;
|
|
2519
|
+
if (statusCode === 500) return true;
|
|
2520
|
+
if (statusCode === 502) return true;
|
|
2521
|
+
if (statusCode === 503) return true;
|
|
2522
|
+
if (statusCode === 504) return true;
|
|
2523
|
+
}
|
|
2524
|
+
if (error instanceof Error) {
|
|
2525
|
+
const message = error.message.toLowerCase();
|
|
2526
|
+
if (message.includes("rate limit")) return true;
|
|
2527
|
+
if (message.includes("timeout")) return true;
|
|
2528
|
+
if (message.includes("service unavailable")) return true;
|
|
2529
|
+
}
|
|
2530
|
+
return false;
|
|
2531
|
+
}
|
|
2532
|
+
|
|
2533
|
+
// ../../packages/providers/azure-openai/src/tools.ts
|
|
2534
|
+
function buildAzureOpenAITools(client, toolNames, options) {
|
|
2535
|
+
const tools = {};
|
|
2536
|
+
for (const name of toolNames) {
|
|
2537
|
+
switch (name) {
|
|
2538
|
+
case "webSearchPreview": {
|
|
2539
|
+
const webSearchTool = client.tools.webSearchPreview({});
|
|
2540
|
+
tools["web_search_preview"] = webSearchTool;
|
|
2541
|
+
break;
|
|
2542
|
+
}
|
|
2543
|
+
case "fileSearch": {
|
|
2544
|
+
const vectorStoreIds = options?.fileSearch?.vectorStoreIds;
|
|
2545
|
+
if (!vectorStoreIds || vectorStoreIds.length === 0) {
|
|
2546
|
+
console.warn(
|
|
2547
|
+
"Azure OpenAI fileSearch tool requires vectorStoreIds. Set providerToolOptions.fileSearch.vectorStoreIds to use this tool."
|
|
2548
|
+
);
|
|
2549
|
+
break;
|
|
2550
|
+
}
|
|
2551
|
+
const fileSearchTool = client.tools.fileSearch({
|
|
2552
|
+
vectorStoreIds,
|
|
2553
|
+
maxNumResults: options?.fileSearch?.maxNumResults
|
|
2554
|
+
});
|
|
2555
|
+
tools["file_search"] = fileSearchTool;
|
|
2556
|
+
break;
|
|
2557
|
+
}
|
|
2558
|
+
case "codeInterpreter": {
|
|
2559
|
+
const codeInterpreterTool = client.tools.codeInterpreter();
|
|
2560
|
+
tools["code_interpreter"] = codeInterpreterTool;
|
|
2561
|
+
break;
|
|
2562
|
+
}
|
|
2563
|
+
case "imageGeneration": {
|
|
2564
|
+
const imageGenerationTool = client.tools.imageGeneration();
|
|
2565
|
+
tools["image_generation"] = imageGenerationTool;
|
|
2566
|
+
break;
|
|
2567
|
+
}
|
|
2568
|
+
}
|
|
2569
|
+
}
|
|
2570
|
+
return tools;
|
|
2571
|
+
}
|
|
2572
|
+
|
|
2573
|
+
// ../../packages/providers/azure-openai/src/adapter.ts
|
|
2574
|
+
var AzureOpenAIProviderAdapter = class extends BaseProviderAdapter {
|
|
2575
|
+
constructor(config, options) {
|
|
2576
|
+
super(options);
|
|
2577
|
+
this.config = config;
|
|
2578
|
+
this.client = createAzure({
|
|
2579
|
+
apiKey: config.apiKey,
|
|
2580
|
+
resourceName: config.resourceName,
|
|
2581
|
+
apiVersion: config.apiVersion,
|
|
2582
|
+
baseURL: config.baseUrl,
|
|
2583
|
+
headers: config.headers,
|
|
2584
|
+
useDeploymentBasedUrls: config.useDeploymentBasedUrls,
|
|
2585
|
+
fetch: options?.proxyUrl ? this.createProxyFetch(options.proxyUrl) : void 0
|
|
2586
|
+
});
|
|
2587
|
+
}
|
|
2588
|
+
providerName = "azure-openai";
|
|
2589
|
+
client;
|
|
2590
|
+
createModel(modelId) {
|
|
2591
|
+
return this.client(modelId);
|
|
2592
|
+
}
|
|
2593
|
+
getProviderTools(toolNames, options) {
|
|
2594
|
+
return buildAzureOpenAITools(this.client, toolNames, options);
|
|
2595
|
+
}
|
|
2596
|
+
normalizeError(error) {
|
|
2597
|
+
return normalizeAzureOpenAIError(error);
|
|
2598
|
+
}
|
|
2599
|
+
isRetryable(error) {
|
|
2600
|
+
return isAzureOpenAIRetryable(error);
|
|
2601
|
+
}
|
|
2602
|
+
};
|
|
2603
|
+
function normalizeBedrockError(error) {
|
|
2604
|
+
if (error instanceof APICallError) {
|
|
2605
|
+
return {
|
|
2606
|
+
name: error.name,
|
|
2607
|
+
message: error.message,
|
|
2608
|
+
statusCode: error.statusCode,
|
|
2609
|
+
isRetryable: isBedrockRetryable(error),
|
|
2610
|
+
provider: "amazon-bedrock",
|
|
2611
|
+
originalError: error
|
|
2612
|
+
};
|
|
2613
|
+
}
|
|
2614
|
+
if (error instanceof Error) {
|
|
2615
|
+
return {
|
|
2616
|
+
name: error.name,
|
|
2617
|
+
message: error.message,
|
|
2618
|
+
isRetryable: isBedrockRetryable(error),
|
|
2619
|
+
provider: "amazon-bedrock",
|
|
2620
|
+
originalError: error
|
|
2621
|
+
};
|
|
2622
|
+
}
|
|
2623
|
+
return {
|
|
2624
|
+
name: "UnknownError",
|
|
2625
|
+
message: String(error),
|
|
2626
|
+
isRetryable: false,
|
|
2627
|
+
provider: "amazon-bedrock",
|
|
2628
|
+
originalError: error
|
|
2629
|
+
};
|
|
2630
|
+
}
|
|
2631
|
+
function isBedrockRetryable(error) {
|
|
2632
|
+
if (error instanceof APICallError) {
|
|
2633
|
+
if (error.isRetryable) return true;
|
|
2634
|
+
const statusCode = error.statusCode;
|
|
2635
|
+
if (statusCode === 429) return true;
|
|
2636
|
+
if (statusCode === 500) return true;
|
|
2637
|
+
if (statusCode === 502) return true;
|
|
2638
|
+
if (statusCode === 503) return true;
|
|
2639
|
+
if (statusCode === 504) return true;
|
|
2640
|
+
}
|
|
2641
|
+
if (error instanceof Error) {
|
|
2642
|
+
const message = error.message.toLowerCase();
|
|
2643
|
+
if (message.includes("rate limit")) return true;
|
|
2644
|
+
if (message.includes("throttl")) return true;
|
|
2645
|
+
if (message.includes("timeout")) return true;
|
|
2646
|
+
if (message.includes("service unavailable")) return true;
|
|
2647
|
+
}
|
|
2648
|
+
return false;
|
|
2649
|
+
}
|
|
2650
|
+
|
|
2651
|
+
// ../../packages/providers/bedrock/src/adapter.ts
|
|
2652
|
+
var BedrockProviderAdapter = class extends BaseProviderAdapter {
|
|
2653
|
+
constructor(config, options) {
|
|
2654
|
+
super(options);
|
|
2655
|
+
this.config = config;
|
|
2656
|
+
this.client = createAmazonBedrock({
|
|
2657
|
+
accessKeyId: config.accessKeyId,
|
|
2658
|
+
secretAccessKey: config.secretAccessKey,
|
|
2659
|
+
region: config.region,
|
|
2660
|
+
sessionToken: config.sessionToken,
|
|
2661
|
+
fetch: options?.proxyUrl ? this.createProxyFetch(options.proxyUrl) : void 0
|
|
2662
|
+
});
|
|
2663
|
+
}
|
|
2664
|
+
providerName = "amazon-bedrock";
|
|
2665
|
+
client;
|
|
2666
|
+
createModel(modelId) {
|
|
2667
|
+
return this.client(modelId);
|
|
2668
|
+
}
|
|
2669
|
+
getProviderOptions(config) {
|
|
2670
|
+
if (!config?.guardrails && !config?.cachePoint) {
|
|
2671
|
+
return void 0;
|
|
2672
|
+
}
|
|
2673
|
+
const bedrockOptions = {};
|
|
2674
|
+
if (config.guardrails) {
|
|
2675
|
+
const guardrailConfig = {
|
|
2676
|
+
guardrailIdentifier: config.guardrails.guardrailIdentifier,
|
|
2677
|
+
guardrailVersion: config.guardrails.guardrailVersion
|
|
2678
|
+
};
|
|
2679
|
+
if (config.guardrails.trace) {
|
|
2680
|
+
guardrailConfig["trace"] = config.guardrails.trace;
|
|
2681
|
+
}
|
|
2682
|
+
bedrockOptions["guardrailConfig"] = guardrailConfig;
|
|
2683
|
+
}
|
|
2684
|
+
if (config.cachePoint) {
|
|
2685
|
+
bedrockOptions["cachePoint"] = { type: config.cachePoint.type };
|
|
2686
|
+
}
|
|
2687
|
+
return { bedrock: bedrockOptions };
|
|
2688
|
+
}
|
|
2689
|
+
getReasoningOptions(budget) {
|
|
2690
|
+
if (budget === "none" || budget === 0) {
|
|
2691
|
+
return void 0;
|
|
2692
|
+
}
|
|
2693
|
+
const budgetTokens = this.budgetToTokens(budget);
|
|
2694
|
+
return {
|
|
2695
|
+
bedrock: {
|
|
2696
|
+
reasoning: {
|
|
2697
|
+
budgetTokens
|
|
2698
|
+
}
|
|
2699
|
+
}
|
|
2700
|
+
};
|
|
2701
|
+
}
|
|
2702
|
+
budgetToTokens(budget) {
|
|
2703
|
+
if (typeof budget === "number") return budget;
|
|
2704
|
+
const map = {
|
|
2705
|
+
minimal: 1024,
|
|
2706
|
+
low: 2048,
|
|
2707
|
+
medium: 5e3,
|
|
2708
|
+
high: 1e4
|
|
2709
|
+
};
|
|
2710
|
+
return map[budget] ?? 5e3;
|
|
2711
|
+
}
|
|
2712
|
+
normalizeError(error) {
|
|
2713
|
+
return normalizeBedrockError(error);
|
|
2714
|
+
}
|
|
2715
|
+
isRetryable(error) {
|
|
2716
|
+
return isBedrockRetryable(error);
|
|
2717
|
+
}
|
|
2718
|
+
};
|
|
2719
|
+
function normalizeDeepSeekError(error) {
|
|
2720
|
+
if (error instanceof APICallError) {
|
|
2721
|
+
return {
|
|
2722
|
+
name: error.name,
|
|
2723
|
+
message: error.message,
|
|
2724
|
+
statusCode: error.statusCode,
|
|
2725
|
+
isRetryable: isDeepSeekRetryable(error),
|
|
2726
|
+
provider: "deepseek",
|
|
2727
|
+
originalError: error
|
|
2728
|
+
};
|
|
2729
|
+
}
|
|
2730
|
+
if (error instanceof Error) {
|
|
2731
|
+
return {
|
|
2732
|
+
name: error.name,
|
|
2733
|
+
message: error.message,
|
|
2734
|
+
isRetryable: isDeepSeekRetryable(error),
|
|
2735
|
+
provider: "deepseek",
|
|
2736
|
+
originalError: error
|
|
2737
|
+
};
|
|
2738
|
+
}
|
|
2739
|
+
return {
|
|
2740
|
+
name: "UnknownError",
|
|
2741
|
+
message: String(error),
|
|
2742
|
+
isRetryable: false,
|
|
2743
|
+
provider: "deepseek",
|
|
2744
|
+
originalError: error
|
|
2745
|
+
};
|
|
2746
|
+
}
|
|
2747
|
+
function isDeepSeekRetryable(error) {
|
|
2748
|
+
if (error instanceof APICallError) {
|
|
2749
|
+
if (error.isRetryable) return true;
|
|
2750
|
+
const statusCode = error.statusCode;
|
|
2751
|
+
if (statusCode === 429) return true;
|
|
2752
|
+
if (statusCode === 500) return true;
|
|
2753
|
+
if (statusCode === 502) return true;
|
|
2754
|
+
if (statusCode === 503) return true;
|
|
2755
|
+
if (statusCode === 504) return true;
|
|
2756
|
+
}
|
|
2757
|
+
if (error instanceof Error) {
|
|
2758
|
+
const message = error.message.toLowerCase();
|
|
2759
|
+
if (message.includes("rate limit")) return true;
|
|
2760
|
+
if (message.includes("timeout")) return true;
|
|
2761
|
+
if (message.includes("service unavailable")) return true;
|
|
2762
|
+
}
|
|
2763
|
+
return false;
|
|
2764
|
+
}
|
|
2765
|
+
|
|
2766
|
+
// ../../packages/providers/deepseek/src/adapter.ts
|
|
2767
|
+
var DeepseekProviderAdapter = class extends BaseProviderAdapter {
|
|
2768
|
+
constructor(config, options) {
|
|
2769
|
+
super(options);
|
|
2770
|
+
this.config = config;
|
|
2771
|
+
this.client = createDeepSeek({
|
|
2772
|
+
apiKey: config.apiKey,
|
|
2773
|
+
baseURL: config.baseUrl,
|
|
2774
|
+
headers: config.headers,
|
|
2775
|
+
fetch: options?.proxyUrl ? this.createProxyFetch(options.proxyUrl) : void 0
|
|
2776
|
+
});
|
|
2777
|
+
}
|
|
2778
|
+
providerName = "deepseek";
|
|
2779
|
+
client;
|
|
2780
|
+
createModel(modelId) {
|
|
2781
|
+
return this.client(modelId);
|
|
2782
|
+
}
|
|
2783
|
+
normalizeError(error) {
|
|
2784
|
+
return normalizeDeepSeekError(error);
|
|
2785
|
+
}
|
|
2786
|
+
isRetryable(error) {
|
|
2787
|
+
return isDeepSeekRetryable(error);
|
|
2788
|
+
}
|
|
2789
|
+
};
|
|
2790
|
+
function normalizeGoogleError(error) {
|
|
2791
|
+
if (error instanceof APICallError) {
|
|
2792
|
+
return {
|
|
2793
|
+
name: error.name,
|
|
2794
|
+
message: error.message,
|
|
2795
|
+
statusCode: error.statusCode,
|
|
2796
|
+
isRetryable: isGoogleRetryable(error),
|
|
2797
|
+
provider: "google",
|
|
2798
|
+
originalError: error
|
|
2799
|
+
};
|
|
2800
|
+
}
|
|
2801
|
+
if (error instanceof Error) {
|
|
2802
|
+
return {
|
|
2803
|
+
name: error.name,
|
|
2804
|
+
message: error.message,
|
|
2805
|
+
isRetryable: isGoogleRetryable(error),
|
|
2806
|
+
provider: "google",
|
|
2807
|
+
originalError: error
|
|
2808
|
+
};
|
|
2809
|
+
}
|
|
2810
|
+
return {
|
|
2811
|
+
name: "UnknownError",
|
|
2812
|
+
message: String(error),
|
|
2813
|
+
isRetryable: false,
|
|
2814
|
+
provider: "google",
|
|
2815
|
+
originalError: error
|
|
2816
|
+
};
|
|
2817
|
+
}
|
|
2818
|
+
function isGoogleRetryable(error) {
|
|
2819
|
+
if (error instanceof APICallError) {
|
|
2820
|
+
if (error.isRetryable) return true;
|
|
2821
|
+
const statusCode = error.statusCode;
|
|
2822
|
+
if (statusCode === 429) return true;
|
|
2823
|
+
if (statusCode === 500) return true;
|
|
2824
|
+
if (statusCode === 502) return true;
|
|
2825
|
+
if (statusCode === 503) return true;
|
|
2826
|
+
if (statusCode === 504) return true;
|
|
2827
|
+
}
|
|
2828
|
+
if (error instanceof Error) {
|
|
2829
|
+
const message = error.message.toLowerCase();
|
|
2830
|
+
if (message.includes("rate limit")) return true;
|
|
2831
|
+
if (message.includes("quota exceeded")) return true;
|
|
2832
|
+
if (message.includes("timeout")) return true;
|
|
2833
|
+
if (message.includes("service unavailable")) return true;
|
|
2834
|
+
}
|
|
2835
|
+
return false;
|
|
2836
|
+
}
|
|
2837
|
+
|
|
2838
|
+
// ../../packages/providers/google/src/tools.ts
|
|
2839
|
+
function buildGoogleTools(client, toolNames, options) {
|
|
2840
|
+
const tools = {};
|
|
2841
|
+
for (const name of toolNames) {
|
|
2842
|
+
switch (name) {
|
|
2843
|
+
case "googleSearch": {
|
|
2844
|
+
const googleSearchTool = client.tools.googleSearch({});
|
|
2845
|
+
tools["google_search"] = googleSearchTool;
|
|
2846
|
+
break;
|
|
2847
|
+
}
|
|
2848
|
+
case "codeExecution": {
|
|
2849
|
+
const codeExecutionTool = client.tools.codeExecution({});
|
|
2850
|
+
tools["code_execution"] = codeExecutionTool;
|
|
2851
|
+
break;
|
|
2852
|
+
}
|
|
2853
|
+
case "urlContext": {
|
|
2854
|
+
const urlContextTool = client.tools.urlContext({});
|
|
2855
|
+
tools["url_context"] = urlContextTool;
|
|
2856
|
+
break;
|
|
2857
|
+
}
|
|
2858
|
+
case "fileSearch": {
|
|
2859
|
+
const storeNames = options?.fileSearch?.vectorStoreIds;
|
|
2860
|
+
if (!storeNames || storeNames.length === 0) {
|
|
2861
|
+
console.warn(
|
|
2862
|
+
"Google fileSearch tool requires fileSearchStoreNames. Set providerToolOptions.fileSearch.vectorStoreIds to use this tool."
|
|
2863
|
+
);
|
|
2864
|
+
break;
|
|
2865
|
+
}
|
|
2866
|
+
const fileSearchTool = client.tools.fileSearch({
|
|
2867
|
+
fileSearchStoreNames: storeNames,
|
|
2868
|
+
topK: options?.fileSearch?.maxNumResults
|
|
2869
|
+
});
|
|
2870
|
+
tools["file_search"] = fileSearchTool;
|
|
2871
|
+
break;
|
|
2872
|
+
}
|
|
2873
|
+
case "googleMaps": {
|
|
2874
|
+
const googleMapsTool = client.tools.googleMaps(options?.googleMaps?.retrievalConfig ?? {});
|
|
2875
|
+
tools["google_maps"] = googleMapsTool;
|
|
2876
|
+
break;
|
|
2877
|
+
}
|
|
2878
|
+
}
|
|
2879
|
+
}
|
|
2880
|
+
return tools;
|
|
2881
|
+
}
|
|
2882
|
+
|
|
2883
|
+
// ../../packages/providers/google/src/adapter.ts
|
|
2884
|
+
var GoogleProviderAdapter = class extends BaseProviderAdapter {
|
|
2885
|
+
constructor(config, options) {
|
|
2886
|
+
super(options);
|
|
2887
|
+
this.config = config;
|
|
2888
|
+
this.client = createGoogleGenerativeAI({
|
|
2889
|
+
apiKey: config.apiKey,
|
|
2890
|
+
baseURL: config.baseUrl,
|
|
2891
|
+
headers: config.headers,
|
|
2892
|
+
fetch: options?.proxyUrl ? this.createProxyFetch(options.proxyUrl) : void 0
|
|
2893
|
+
});
|
|
2894
|
+
}
|
|
2895
|
+
providerName = "google";
|
|
2896
|
+
client;
|
|
2897
|
+
createModel(modelId) {
|
|
2898
|
+
return this.client(modelId);
|
|
2899
|
+
}
|
|
2900
|
+
getProviderTools(toolNames, options) {
|
|
2901
|
+
return buildGoogleTools(this.client, toolNames, options);
|
|
2902
|
+
}
|
|
2903
|
+
normalizeError(error) {
|
|
2904
|
+
return normalizeGoogleError(error);
|
|
2905
|
+
}
|
|
2906
|
+
isRetryable(error) {
|
|
2907
|
+
return isGoogleRetryable(error);
|
|
2908
|
+
}
|
|
2909
|
+
getReasoningOptions(budget) {
|
|
2910
|
+
const budgetTokens = this.budgetToTokens(budget);
|
|
2911
|
+
return {
|
|
2912
|
+
google: {
|
|
2913
|
+
thinkingConfig: {
|
|
2914
|
+
thinkingBudget: budgetTokens,
|
|
2915
|
+
includeThoughts: true
|
|
2916
|
+
}
|
|
2917
|
+
}
|
|
2918
|
+
};
|
|
2919
|
+
}
|
|
2920
|
+
budgetToTokens(budget) {
|
|
2921
|
+
if (typeof budget === "number") return budget;
|
|
2922
|
+
const map = {
|
|
2923
|
+
minimal: 1024,
|
|
2924
|
+
low: 2048,
|
|
2925
|
+
medium: 5e3,
|
|
2926
|
+
high: 1e4
|
|
2927
|
+
};
|
|
2928
|
+
return map[budget] ?? 5e3;
|
|
2929
|
+
}
|
|
2930
|
+
};
|
|
2931
|
+
function normalizeOllamaError(error) {
|
|
2932
|
+
if (error instanceof APICallError) {
|
|
2933
|
+
return {
|
|
2934
|
+
name: error.name,
|
|
2935
|
+
message: error.message,
|
|
2936
|
+
statusCode: error.statusCode,
|
|
2937
|
+
isRetryable: isOllamaRetryable(error),
|
|
2938
|
+
provider: "ollama",
|
|
2939
|
+
originalError: error
|
|
2940
|
+
};
|
|
2941
|
+
}
|
|
2942
|
+
if (error instanceof Error) {
|
|
2943
|
+
return {
|
|
2944
|
+
name: error.name,
|
|
2945
|
+
message: error.message,
|
|
2946
|
+
isRetryable: isOllamaRetryable(error),
|
|
2947
|
+
provider: "ollama",
|
|
2948
|
+
originalError: error
|
|
2949
|
+
};
|
|
2950
|
+
}
|
|
2951
|
+
return {
|
|
2952
|
+
name: "UnknownError",
|
|
2953
|
+
message: String(error),
|
|
2954
|
+
isRetryable: false,
|
|
2955
|
+
provider: "ollama",
|
|
2956
|
+
originalError: error
|
|
2957
|
+
};
|
|
2958
|
+
}
|
|
2959
|
+
function isOllamaRetryable(error) {
|
|
2960
|
+
if (error instanceof APICallError) {
|
|
2961
|
+
if (error.isRetryable) return true;
|
|
2962
|
+
const statusCode = error.statusCode;
|
|
2963
|
+
if (statusCode === 429) return true;
|
|
2964
|
+
if (statusCode === 500) return true;
|
|
2965
|
+
if (statusCode === 502) return true;
|
|
2966
|
+
if (statusCode === 503) return true;
|
|
2967
|
+
if (statusCode === 504) return true;
|
|
2968
|
+
}
|
|
2969
|
+
if (error instanceof Error) {
|
|
2970
|
+
const message = error.message.toLowerCase();
|
|
2971
|
+
if (message.includes("rate limit")) return true;
|
|
2972
|
+
if (message.includes("timeout")) return true;
|
|
2973
|
+
if (message.includes("service unavailable")) return true;
|
|
2974
|
+
if (message.includes("connection refused")) return true;
|
|
2975
|
+
}
|
|
2976
|
+
return false;
|
|
2977
|
+
}
|
|
2978
|
+
|
|
2979
|
+
// ../../packages/providers/ollama/src/adapter.ts
|
|
2980
|
+
var OllamaProviderAdapter = class extends BaseProviderAdapter {
|
|
2981
|
+
constructor(config, options) {
|
|
2982
|
+
super(options);
|
|
2983
|
+
this.config = config;
|
|
2984
|
+
this.client = createOllama({
|
|
2985
|
+
baseURL: config.baseUrl,
|
|
2986
|
+
headers: config.headers,
|
|
2987
|
+
fetch: options?.proxyUrl ? this.createProxyFetch(options.proxyUrl) : void 0
|
|
2988
|
+
});
|
|
2989
|
+
}
|
|
2990
|
+
providerName = "ollama";
|
|
2991
|
+
client;
|
|
2992
|
+
createModel(modelId) {
|
|
2993
|
+
return this.client(modelId);
|
|
2994
|
+
}
|
|
2995
|
+
getProviderOptions(config) {
|
|
2996
|
+
if (config?.think === void 0) {
|
|
2997
|
+
return void 0;
|
|
2998
|
+
}
|
|
2999
|
+
return {
|
|
3000
|
+
ollama: {
|
|
3001
|
+
think: config.think
|
|
3002
|
+
}
|
|
3003
|
+
};
|
|
3004
|
+
}
|
|
3005
|
+
getReasoningOptions(budget) {
|
|
3006
|
+
if (budget === "none" || budget === 0) {
|
|
3007
|
+
return void 0;
|
|
3008
|
+
}
|
|
3009
|
+
return {
|
|
3010
|
+
ollama: {
|
|
3011
|
+
think: true
|
|
3012
|
+
}
|
|
3013
|
+
};
|
|
3014
|
+
}
|
|
3015
|
+
normalizeError(error) {
|
|
3016
|
+
return normalizeOllamaError(error);
|
|
3017
|
+
}
|
|
3018
|
+
isRetryable(error) {
|
|
3019
|
+
return isOllamaRetryable(error);
|
|
3020
|
+
}
|
|
3021
|
+
};
|
|
3022
|
+
function normalizeOpenAIError(error) {
|
|
3023
|
+
if (error instanceof APICallError) {
|
|
3024
|
+
return {
|
|
3025
|
+
name: error.name,
|
|
3026
|
+
message: error.message,
|
|
3027
|
+
statusCode: error.statusCode,
|
|
3028
|
+
isRetryable: isOpenAIRetryable(error),
|
|
3029
|
+
provider: "openai",
|
|
3030
|
+
originalError: error
|
|
3031
|
+
};
|
|
3032
|
+
}
|
|
3033
|
+
if (error instanceof Error) {
|
|
3034
|
+
return {
|
|
3035
|
+
name: error.name,
|
|
3036
|
+
message: error.message,
|
|
3037
|
+
isRetryable: isOpenAIRetryable(error),
|
|
3038
|
+
provider: "openai",
|
|
3039
|
+
originalError: error
|
|
3040
|
+
};
|
|
3041
|
+
}
|
|
3042
|
+
return {
|
|
3043
|
+
name: "UnknownError",
|
|
3044
|
+
message: String(error),
|
|
3045
|
+
isRetryable: false,
|
|
3046
|
+
provider: "openai",
|
|
3047
|
+
originalError: error
|
|
3048
|
+
};
|
|
3049
|
+
}
|
|
3050
|
+
function isOpenAIRetryable(error) {
|
|
3051
|
+
if (error instanceof APICallError) {
|
|
3052
|
+
if (error.isRetryable) return true;
|
|
3053
|
+
const statusCode = error.statusCode;
|
|
3054
|
+
if (statusCode === 429) return true;
|
|
3055
|
+
if (statusCode === 500) return true;
|
|
3056
|
+
if (statusCode === 502) return true;
|
|
3057
|
+
if (statusCode === 503) return true;
|
|
3058
|
+
if (statusCode === 504) return true;
|
|
3059
|
+
}
|
|
3060
|
+
if (error instanceof Error) {
|
|
3061
|
+
const message = error.message.toLowerCase();
|
|
3062
|
+
if (message.includes("rate limit")) return true;
|
|
3063
|
+
if (message.includes("timeout")) return true;
|
|
3064
|
+
if (message.includes("service unavailable")) return true;
|
|
3065
|
+
}
|
|
3066
|
+
return false;
|
|
3067
|
+
}
|
|
3068
|
+
|
|
3069
|
+
// ../../packages/providers/openai/src/tools.ts
|
|
3070
|
+
function buildOpenAITools(client, toolNames, options) {
|
|
3071
|
+
const tools = {};
|
|
3072
|
+
for (const name of toolNames) {
|
|
3073
|
+
switch (name) {
|
|
3074
|
+
case "webSearch": {
|
|
3075
|
+
const webSearchTool = client.tools.webSearch();
|
|
3076
|
+
tools["web_search"] = webSearchTool;
|
|
3077
|
+
break;
|
|
3078
|
+
}
|
|
3079
|
+
case "fileSearch": {
|
|
3080
|
+
const vectorStoreIds = options?.fileSearch?.vectorStoreIds;
|
|
3081
|
+
if (!vectorStoreIds || vectorStoreIds.length === 0) {
|
|
3082
|
+
console.warn(
|
|
3083
|
+
"OpenAI fileSearch tool requires vectorStoreIds. Set providerToolOptions.fileSearch.vectorStoreIds to use this tool."
|
|
3084
|
+
);
|
|
3085
|
+
break;
|
|
3086
|
+
}
|
|
3087
|
+
const fileSearchTool = client.tools.fileSearch({
|
|
3088
|
+
vectorStoreIds,
|
|
3089
|
+
maxNumResults: options?.fileSearch?.maxNumResults
|
|
3090
|
+
});
|
|
3091
|
+
tools["file_search"] = fileSearchTool;
|
|
3092
|
+
break;
|
|
3093
|
+
}
|
|
3094
|
+
case "codeInterpreter": {
|
|
3095
|
+
const codeInterpreterTool = client.tools.codeInterpreter();
|
|
3096
|
+
tools["code_interpreter"] = codeInterpreterTool;
|
|
3097
|
+
break;
|
|
3098
|
+
}
|
|
3099
|
+
case "imageGeneration": {
|
|
3100
|
+
const imageGenerationTool = client.tools.imageGeneration();
|
|
3101
|
+
tools["image_generation"] = imageGenerationTool;
|
|
3102
|
+
break;
|
|
3103
|
+
}
|
|
3104
|
+
}
|
|
3105
|
+
}
|
|
3106
|
+
return tools;
|
|
3107
|
+
}
|
|
3108
|
+
|
|
3109
|
+
// ../../packages/providers/openai/src/adapter.ts
|
|
3110
|
+
var OpenAIProviderAdapter = class extends BaseProviderAdapter {
|
|
3111
|
+
constructor(config, options) {
|
|
3112
|
+
super(options);
|
|
3113
|
+
this.config = config;
|
|
3114
|
+
this.client = createOpenAI({
|
|
3115
|
+
apiKey: config.apiKey,
|
|
3116
|
+
baseURL: config.baseUrl,
|
|
3117
|
+
organization: config.organization,
|
|
3118
|
+
project: config.project,
|
|
3119
|
+
name: config.name,
|
|
3120
|
+
headers: config.headers,
|
|
3121
|
+
fetch: options?.proxyUrl ? this.createProxyFetch(options.proxyUrl) : void 0
|
|
3122
|
+
});
|
|
3123
|
+
}
|
|
3124
|
+
providerName = "openai";
|
|
3125
|
+
client;
|
|
3126
|
+
createModel(modelId) {
|
|
3127
|
+
return this.client(modelId);
|
|
3128
|
+
}
|
|
3129
|
+
getProviderTools(toolNames, options) {
|
|
3130
|
+
return buildOpenAITools(this.client, toolNames, options);
|
|
3131
|
+
}
|
|
3132
|
+
getReasoningOptions(budget) {
|
|
3133
|
+
const effort = this.budgetToEffort(budget);
|
|
3134
|
+
return {
|
|
3135
|
+
openai: { reasoningEffort: effort }
|
|
3136
|
+
};
|
|
3137
|
+
}
|
|
3138
|
+
budgetToEffort(budget) {
|
|
3139
|
+
if (typeof budget === "number") {
|
|
3140
|
+
if (budget <= 2048) return "low";
|
|
3141
|
+
if (budget <= 5e3) return "medium";
|
|
3142
|
+
return "high";
|
|
3143
|
+
}
|
|
3144
|
+
if (budget === "minimal") return "low";
|
|
3145
|
+
return budget;
|
|
3146
|
+
}
|
|
3147
|
+
normalizeError(error) {
|
|
3148
|
+
return normalizeOpenAIError(error);
|
|
3149
|
+
}
|
|
3150
|
+
isRetryable(error) {
|
|
3151
|
+
return isOpenAIRetryable(error);
|
|
3152
|
+
}
|
|
3153
|
+
};
|
|
3154
|
+
function normalizeVertexError(error) {
|
|
3155
|
+
if (error instanceof APICallError) {
|
|
3156
|
+
return {
|
|
3157
|
+
name: error.name,
|
|
3158
|
+
message: error.message,
|
|
3159
|
+
statusCode: error.statusCode,
|
|
3160
|
+
isRetryable: isVertexRetryable(error),
|
|
3161
|
+
provider: "google-vertex",
|
|
3162
|
+
originalError: error
|
|
3163
|
+
};
|
|
3164
|
+
}
|
|
3165
|
+
if (error instanceof Error) {
|
|
3166
|
+
return {
|
|
3167
|
+
name: error.name,
|
|
3168
|
+
message: error.message,
|
|
3169
|
+
isRetryable: isVertexRetryable(error),
|
|
3170
|
+
provider: "google-vertex",
|
|
3171
|
+
originalError: error
|
|
3172
|
+
};
|
|
3173
|
+
}
|
|
3174
|
+
return {
|
|
3175
|
+
name: "UnknownError",
|
|
3176
|
+
message: String(error),
|
|
3177
|
+
isRetryable: false,
|
|
3178
|
+
provider: "google-vertex",
|
|
3179
|
+
originalError: error
|
|
3180
|
+
};
|
|
3181
|
+
}
|
|
3182
|
+
function isVertexRetryable(error) {
|
|
3183
|
+
if (error instanceof APICallError) {
|
|
3184
|
+
if (error.isRetryable) return true;
|
|
3185
|
+
const statusCode = error.statusCode;
|
|
3186
|
+
if (statusCode === 429) return true;
|
|
3187
|
+
if (statusCode === 500) return true;
|
|
3188
|
+
if (statusCode === 502) return true;
|
|
3189
|
+
if (statusCode === 503) return true;
|
|
3190
|
+
if (statusCode === 504) return true;
|
|
3191
|
+
}
|
|
3192
|
+
if (error instanceof Error) {
|
|
3193
|
+
const message = error.message.toLowerCase();
|
|
3194
|
+
if (message.includes("rate limit")) return true;
|
|
3195
|
+
if (message.includes("quota exceeded")) return true;
|
|
3196
|
+
if (message.includes("timeout")) return true;
|
|
3197
|
+
if (message.includes("service unavailable")) return true;
|
|
3198
|
+
}
|
|
3199
|
+
return false;
|
|
3200
|
+
}
|
|
3201
|
+
|
|
3202
|
+
// ../../packages/providers/vertex/src/tools.ts
|
|
3203
|
+
function buildVertexTools(client, toolNames, options) {
|
|
3204
|
+
const tools = {};
|
|
3205
|
+
for (const name of toolNames) {
|
|
3206
|
+
switch (name) {
|
|
3207
|
+
case "googleSearch": {
|
|
3208
|
+
const googleSearchTool = client.tools.googleSearch({});
|
|
3209
|
+
tools["google_search"] = googleSearchTool;
|
|
3210
|
+
break;
|
|
3211
|
+
}
|
|
3212
|
+
case "codeExecution": {
|
|
3213
|
+
const codeExecutionTool = client.tools.codeExecution({});
|
|
3214
|
+
tools["code_execution"] = codeExecutionTool;
|
|
3215
|
+
break;
|
|
3216
|
+
}
|
|
3217
|
+
case "urlContext": {
|
|
3218
|
+
const urlContextTool = client.tools.urlContext({});
|
|
3219
|
+
tools["url_context"] = urlContextTool;
|
|
3220
|
+
break;
|
|
3221
|
+
}
|
|
3222
|
+
case "enterpriseWebSearch": {
|
|
3223
|
+
const enterpriseWebSearchTool = client.tools.enterpriseWebSearch({});
|
|
3224
|
+
tools["enterprise_web_search"] = enterpriseWebSearchTool;
|
|
3225
|
+
break;
|
|
3226
|
+
}
|
|
3227
|
+
case "googleMaps": {
|
|
3228
|
+
const googleMapsTool = client.tools.googleMaps(options?.googleMaps?.retrievalConfig ?? {});
|
|
3229
|
+
tools["google_maps"] = googleMapsTool;
|
|
3230
|
+
break;
|
|
3231
|
+
}
|
|
3232
|
+
}
|
|
3233
|
+
}
|
|
3234
|
+
return tools;
|
|
3235
|
+
}
|
|
3236
|
+
|
|
3237
|
+
// ../../packages/providers/vertex/src/adapter.ts
|
|
3238
|
+
var VertexProviderAdapter = class extends BaseProviderAdapter {
|
|
3239
|
+
constructor(config, options) {
|
|
3240
|
+
super(options);
|
|
3241
|
+
this.config = config;
|
|
3242
|
+
this.client = createVertex({
|
|
3243
|
+
project: config.project,
|
|
3244
|
+
location: config.location,
|
|
3245
|
+
baseURL: config.baseUrl,
|
|
3246
|
+
headers: config.headers,
|
|
3247
|
+
fetch: options?.proxyUrl ? this.createProxyFetch(options.proxyUrl) : void 0
|
|
3248
|
+
});
|
|
3249
|
+
}
|
|
3250
|
+
providerName = "google-vertex";
|
|
3251
|
+
client;
|
|
3252
|
+
createModel(modelId) {
|
|
3253
|
+
return this.client(modelId);
|
|
3254
|
+
}
|
|
3255
|
+
getProviderTools(toolNames, options) {
|
|
3256
|
+
return buildVertexTools(this.client, toolNames, options);
|
|
3257
|
+
}
|
|
3258
|
+
getProviderOptions(config) {
|
|
3259
|
+
if (!config?.safetySettings || config.safetySettings.length === 0) {
|
|
3260
|
+
return void 0;
|
|
3261
|
+
}
|
|
3262
|
+
return {
|
|
3263
|
+
vertex: {
|
|
3264
|
+
safetySettings: config.safetySettings
|
|
3265
|
+
}
|
|
3266
|
+
};
|
|
3267
|
+
}
|
|
3268
|
+
getReasoningOptions(budget) {
|
|
3269
|
+
if (budget === "none" || budget === 0) {
|
|
3270
|
+
return void 0;
|
|
3271
|
+
}
|
|
3272
|
+
const budgetTokens = this.budgetToTokens(budget);
|
|
3273
|
+
return {
|
|
3274
|
+
vertex: {
|
|
3275
|
+
thinkingConfig: {
|
|
3276
|
+
thinkingBudget: budgetTokens,
|
|
3277
|
+
includeThoughts: true
|
|
3278
|
+
}
|
|
3279
|
+
}
|
|
3280
|
+
};
|
|
3281
|
+
}
|
|
3282
|
+
budgetToTokens(budget) {
|
|
3283
|
+
if (typeof budget === "number") return budget;
|
|
3284
|
+
const map = {
|
|
3285
|
+
minimal: 1024,
|
|
3286
|
+
low: 2048,
|
|
3287
|
+
medium: 5e3,
|
|
3288
|
+
high: 1e4
|
|
3289
|
+
};
|
|
3290
|
+
return map[budget] ?? 5e3;
|
|
3291
|
+
}
|
|
3292
|
+
normalizeError(error) {
|
|
3293
|
+
return normalizeVertexError(error);
|
|
3294
|
+
}
|
|
3295
|
+
isRetryable(error) {
|
|
3296
|
+
return isVertexRetryable(error);
|
|
3297
|
+
}
|
|
3298
|
+
};
|
|
3299
|
+
|
|
3300
|
+
// src/helpers/register-providers.ts
|
|
3301
|
+
registerProviderAdapter(
|
|
3302
|
+
"anthropic",
|
|
3303
|
+
async () => AnthropicProviderAdapter
|
|
3304
|
+
);
|
|
3305
|
+
registerProviderAdapter(
|
|
3306
|
+
"openai",
|
|
3307
|
+
async () => OpenAIProviderAdapter
|
|
3308
|
+
);
|
|
3309
|
+
registerProviderAdapter(
|
|
3310
|
+
"google",
|
|
3311
|
+
async () => GoogleProviderAdapter
|
|
3312
|
+
);
|
|
3313
|
+
registerProviderAdapter(
|
|
3314
|
+
"ollama",
|
|
3315
|
+
async () => OllamaProviderAdapter
|
|
3316
|
+
);
|
|
3317
|
+
registerProviderAdapter(
|
|
3318
|
+
"azure-openai",
|
|
3319
|
+
async () => AzureOpenAIProviderAdapter
|
|
3320
|
+
);
|
|
3321
|
+
registerProviderAdapter(
|
|
3322
|
+
"amazon-bedrock",
|
|
3323
|
+
async () => BedrockProviderAdapter
|
|
3324
|
+
);
|
|
3325
|
+
registerProviderAdapter(
|
|
3326
|
+
"google-vertex",
|
|
3327
|
+
async () => VertexProviderAdapter
|
|
3328
|
+
);
|
|
3329
|
+
registerProviderAdapter(
|
|
3330
|
+
"deepseek",
|
|
3331
|
+
async () => DeepseekProviderAdapter
|
|
3332
|
+
);
|
|
3333
|
+
var shouldEnableReasoning = (budget) => budget !== void 0 && budget !== "none" && budget !== 0;
|
|
3334
|
+
var LLMExecutor = class {
|
|
3335
|
+
constructor(adapter, model) {
|
|
3336
|
+
this.adapter = adapter;
|
|
3337
|
+
this.model = model;
|
|
3338
|
+
}
|
|
3339
|
+
async generateText(params) {
|
|
3340
|
+
const providerTools = this.adapter.getProviderTools(
|
|
3341
|
+
params.providerToolNames ?? [],
|
|
3342
|
+
params.providerToolOptions
|
|
3343
|
+
);
|
|
3344
|
+
const baseProviderOptions = this.adapter.getProviderOptions(params.providerOptionsConfig);
|
|
3345
|
+
const reasoningEnabled = shouldEnableReasoning(params.reasoningBudget);
|
|
3346
|
+
const reasoningOptions = reasoningEnabled && params.reasoningBudget ? this.adapter.getReasoningOptions(params.reasoningBudget) : void 0;
|
|
3347
|
+
const providerOptions = this.mergeProviderOptions(baseProviderOptions, reasoningOptions);
|
|
3348
|
+
try {
|
|
3349
|
+
const result = await generateText({
|
|
3350
|
+
model: this.model,
|
|
3351
|
+
messages: params.messages,
|
|
3352
|
+
maxRetries: params.maxRetries,
|
|
3353
|
+
tools: { ...params.tools, ...providerTools },
|
|
3354
|
+
toolChoice: params.toolChoice,
|
|
3355
|
+
abortSignal: params.abortSignal,
|
|
3356
|
+
providerOptions
|
|
3357
|
+
});
|
|
3358
|
+
return { success: true, result };
|
|
3359
|
+
} catch (error) {
|
|
3360
|
+
const providerError = this.adapter.normalizeError(error);
|
|
3361
|
+
return {
|
|
3362
|
+
success: false,
|
|
3363
|
+
error: providerError,
|
|
3364
|
+
isRetryable: this.adapter.isRetryable(error)
|
|
3365
|
+
};
|
|
3366
|
+
}
|
|
3367
|
+
}
|
|
3368
|
+
mergeProviderOptions(...options) {
|
|
3369
|
+
const defined = options.filter(Boolean);
|
|
3370
|
+
if (defined.length === 0) return void 0;
|
|
3371
|
+
const result = {};
|
|
3372
|
+
for (const opt of defined) {
|
|
3373
|
+
for (const [provider, settings] of Object.entries(opt)) {
|
|
3374
|
+
result[provider] = { ...result[provider], ...settings };
|
|
3375
|
+
}
|
|
3376
|
+
}
|
|
3377
|
+
return result;
|
|
3378
|
+
}
|
|
3379
|
+
async generateTextWithoutTools(params) {
|
|
3380
|
+
const baseProviderOptions = this.adapter.getProviderOptions(params.providerOptionsConfig);
|
|
3381
|
+
const reasoningEnabled = shouldEnableReasoning(params.reasoningBudget);
|
|
3382
|
+
const reasoningOptions = reasoningEnabled && params.reasoningBudget ? this.adapter.getReasoningOptions(params.reasoningBudget) : void 0;
|
|
3383
|
+
const providerOptions = this.mergeProviderOptions(baseProviderOptions, reasoningOptions);
|
|
3384
|
+
try {
|
|
3385
|
+
const result = await generateText({
|
|
3386
|
+
model: this.model,
|
|
3387
|
+
messages: params.messages,
|
|
3388
|
+
maxRetries: params.maxRetries,
|
|
3389
|
+
abortSignal: params.abortSignal,
|
|
3390
|
+
providerOptions
|
|
3391
|
+
});
|
|
3392
|
+
return { success: true, result };
|
|
3393
|
+
} catch (error) {
|
|
3394
|
+
const providerError = this.adapter.normalizeError(error);
|
|
3395
|
+
return {
|
|
3396
|
+
success: false,
|
|
3397
|
+
error: providerError,
|
|
3398
|
+
isRetryable: this.adapter.isRetryable(error)
|
|
3399
|
+
};
|
|
3400
|
+
}
|
|
3401
|
+
}
|
|
3402
|
+
async streamText(params, callbacks) {
|
|
3403
|
+
const providerTools = this.adapter.getProviderTools(
|
|
3404
|
+
params.providerToolNames ?? [],
|
|
3405
|
+
params.providerToolOptions
|
|
3406
|
+
);
|
|
3407
|
+
const baseProviderOptions = this.adapter.getProviderOptions(params.providerOptionsConfig);
|
|
3408
|
+
const reasoningEnabled = shouldEnableReasoning(params.reasoningBudget);
|
|
3409
|
+
const reasoningOptions = reasoningEnabled && params.reasoningBudget ? this.adapter.getReasoningOptions(params.reasoningBudget) : void 0;
|
|
3410
|
+
const providerOptions = this.mergeProviderOptions(baseProviderOptions, reasoningOptions);
|
|
3411
|
+
const streamResult = streamText({
|
|
3412
|
+
model: this.model,
|
|
3413
|
+
messages: params.messages,
|
|
3414
|
+
maxRetries: params.maxRetries,
|
|
3415
|
+
tools: { ...params.tools, ...providerTools },
|
|
3416
|
+
toolChoice: params.toolChoice,
|
|
3417
|
+
abortSignal: params.abortSignal,
|
|
3418
|
+
providerOptions
|
|
3419
|
+
});
|
|
3420
|
+
let reasoningStarted = false;
|
|
3421
|
+
let reasoningCompleted = false;
|
|
3422
|
+
let resultStarted = false;
|
|
3423
|
+
let accumulatedReasoning = "";
|
|
3424
|
+
try {
|
|
3425
|
+
for await (const part of streamResult.fullStream) {
|
|
3426
|
+
if (part.type === "reasoning-delta") {
|
|
3427
|
+
if (!reasoningStarted) {
|
|
3428
|
+
callbacks.onReasoningStart?.();
|
|
3429
|
+
reasoningStarted = true;
|
|
3430
|
+
}
|
|
3431
|
+
accumulatedReasoning += part.text;
|
|
3432
|
+
callbacks.onReasoningDelta?.(part.text);
|
|
3433
|
+
}
|
|
3434
|
+
if (part.type === "text-delta") {
|
|
3435
|
+
if (reasoningStarted && !reasoningCompleted) {
|
|
3436
|
+
callbacks.onReasoningComplete?.(accumulatedReasoning);
|
|
3437
|
+
reasoningCompleted = true;
|
|
3438
|
+
}
|
|
3439
|
+
if (!resultStarted) {
|
|
3440
|
+
callbacks.onResultStart?.();
|
|
3441
|
+
resultStarted = true;
|
|
3442
|
+
}
|
|
3443
|
+
callbacks.onResultDelta?.(part.text);
|
|
3444
|
+
}
|
|
3445
|
+
}
|
|
3446
|
+
if (reasoningStarted && !reasoningCompleted) {
|
|
3447
|
+
callbacks.onReasoningComplete?.(accumulatedReasoning);
|
|
3448
|
+
reasoningCompleted = true;
|
|
3449
|
+
}
|
|
3450
|
+
const text = await streamResult.text;
|
|
3451
|
+
const toolCalls = await streamResult.toolCalls;
|
|
3452
|
+
const finishReason = await streamResult.finishReason;
|
|
3453
|
+
const usage = await streamResult.usage;
|
|
3454
|
+
const reasoning = await streamResult.reasoning;
|
|
3455
|
+
const response = await streamResult.response;
|
|
3456
|
+
const result = {
|
|
3457
|
+
text,
|
|
3458
|
+
toolCalls,
|
|
3459
|
+
finishReason,
|
|
3460
|
+
usage,
|
|
3461
|
+
reasoning,
|
|
3462
|
+
response,
|
|
3463
|
+
// These properties are required by GenerateTextResult but not available in streamText
|
|
3464
|
+
// They're optional or have safe defaults
|
|
3465
|
+
toolResults: [],
|
|
3466
|
+
steps: [],
|
|
3467
|
+
experimental_output: void 0,
|
|
3468
|
+
providerMetadata: void 0,
|
|
3469
|
+
request: { body: "" }
|
|
3470
|
+
};
|
|
3471
|
+
return { success: true, result };
|
|
3472
|
+
} catch (error) {
|
|
3473
|
+
const providerError = this.adapter.normalizeError(error);
|
|
3474
|
+
return {
|
|
3475
|
+
success: false,
|
|
3476
|
+
error: providerError,
|
|
3477
|
+
isRetryable: this.adapter.isRetryable(error)
|
|
3478
|
+
};
|
|
3479
|
+
}
|
|
3480
|
+
}
|
|
3481
|
+
};
|
|
3482
|
+
|
|
3483
|
+
// src/orchestration/single-run-executor.ts
|
|
3484
|
+
var SingleRunExecutor = class {
|
|
3485
|
+
constructor(options = {}) {
|
|
3486
|
+
this.options = options;
|
|
3487
|
+
}
|
|
3488
|
+
async execute(setting, checkpoint) {
|
|
3489
|
+
const adapter = await createProviderAdapter(setting.providerConfig, {
|
|
3490
|
+
proxyUrl: setting.proxyUrl
|
|
3491
|
+
});
|
|
3492
|
+
const model = adapter.createModel(setting.model);
|
|
3493
|
+
const llmExecutor = new LLMExecutor(adapter, model);
|
|
3494
|
+
const contextWindow = getContextWindow(setting.providerConfig.providerName, setting.model);
|
|
3495
|
+
const { expertToRun, experts } = await setupExperts(setting, this.options.resolveExpertToRun);
|
|
3496
|
+
this.emitInitEvent(setting, expertToRun, experts);
|
|
3497
|
+
const lockfileExpert = this.options.lockfile?.experts[setting.expertKey];
|
|
3498
|
+
const skillManagers = lockfileExpert ? await getSkillManagersFromLockfile(
|
|
3499
|
+
expertToRun,
|
|
3500
|
+
experts,
|
|
3501
|
+
setting,
|
|
3502
|
+
getLockfileExpertToolDefinitions(lockfileExpert),
|
|
3503
|
+
this.options.eventListener,
|
|
3504
|
+
{ isDelegatedRun: !!checkpoint?.delegatedBy }
|
|
3505
|
+
) : await getSkillManagers(expertToRun, experts, setting, this.options.eventListener, {
|
|
3506
|
+
isDelegatedRun: !!checkpoint?.delegatedBy
|
|
3507
|
+
});
|
|
2487
3508
|
const initialCheckpoint = checkpoint ? createNextStepCheckpoint(createId(), checkpoint) : createInitialCheckpoint(createId(), {
|
|
2488
3509
|
jobId: setting.jobId,
|
|
2489
3510
|
runId: setting.runId,
|
|
@@ -2499,6 +3520,7 @@ var SingleRunExecutor = class {
|
|
|
2499
3520
|
initialCheckpoint,
|
|
2500
3521
|
eventListener,
|
|
2501
3522
|
skillManagers,
|
|
3523
|
+
llmExecutor,
|
|
2502
3524
|
eventEmitter,
|
|
2503
3525
|
storeCheckpoint: this.options.storeCheckpoint ?? (async () => {
|
|
2504
3526
|
}),
|
|
@@ -2524,7 +3546,6 @@ var SingleRunExecutor = class {
|
|
|
2524
3546
|
expertName: expertToRun.name,
|
|
2525
3547
|
experts: Object.keys(experts),
|
|
2526
3548
|
model: setting.model,
|
|
2527
|
-
temperature: setting.temperature,
|
|
2528
3549
|
maxSteps: setting.maxSteps,
|
|
2529
3550
|
maxRetries: setting.maxRetries,
|
|
2530
3551
|
timeout: setting.timeout,
|
|
@@ -2565,7 +3586,8 @@ async function run(runInput, options) {
|
|
|
2565
3586
|
storeCheckpoint: options?.storeCheckpoint,
|
|
2566
3587
|
storeEvent: options?.storeEvent,
|
|
2567
3588
|
eventListener: options?.eventListener,
|
|
2568
|
-
resolveExpertToRun: options?.resolveExpertToRun
|
|
3589
|
+
resolveExpertToRun: options?.resolveExpertToRun,
|
|
3590
|
+
lockfile: options?.lockfile
|
|
2569
3591
|
});
|
|
2570
3592
|
while (true) {
|
|
2571
3593
|
const runResult = await runExecutor.execute(setting, checkpoint);
|
|
@@ -2633,6 +3655,6 @@ async function run(runInput, options) {
|
|
|
2633
3655
|
}
|
|
2634
3656
|
}
|
|
2635
3657
|
|
|
2636
|
-
export { getModel, package_default, run, runtimeStateMachine };
|
|
2637
|
-
//# sourceMappingURL=chunk-
|
|
2638
|
-
//# sourceMappingURL=chunk-
|
|
3658
|
+
export { findLockfile, getLockfileExpertToolDefinitions, getModel, loadLockfile, package_default, run, runtimeStateMachine };
|
|
3659
|
+
//# sourceMappingURL=chunk-BXJGGA3Q.js.map
|
|
3660
|
+
//# sourceMappingURL=chunk-BXJGGA3Q.js.map
|