@perstack/core 0.0.49 → 0.0.50
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/dist/src/index.d.ts +4999 -4613
- package/dist/src/index.js +1797 -1760
- package/dist/src/index.js.map +1 -1
- package/package.json +6 -3
package/dist/src/index.js
CHANGED
|
@@ -1,1870 +1,1907 @@
|
|
|
1
|
-
import { createId } from
|
|
2
|
-
import { z } from
|
|
1
|
+
import { createId } from "@paralleldrive/cuid2";
|
|
2
|
+
import { z } from "zod";
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
//#region src/adapters/event-creators.ts
|
|
5
5
|
function createEmptyUsage() {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
return {
|
|
7
|
+
inputTokens: 0,
|
|
8
|
+
outputTokens: 0,
|
|
9
|
+
reasoningTokens: 0,
|
|
10
|
+
totalTokens: 0,
|
|
11
|
+
cachedInputTokens: 0
|
|
12
|
+
};
|
|
13
13
|
}
|
|
14
14
|
function createNormalizedCheckpoint(params) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
15
|
+
const { jobId, runId, expert, output } = params;
|
|
16
|
+
return {
|
|
17
|
+
id: createId(),
|
|
18
|
+
jobId,
|
|
19
|
+
runId,
|
|
20
|
+
status: "completed",
|
|
21
|
+
stepNumber: 1,
|
|
22
|
+
messages: [{
|
|
23
|
+
id: createId(),
|
|
24
|
+
type: "expertMessage",
|
|
25
|
+
contents: [{
|
|
26
|
+
type: "textPart",
|
|
27
|
+
id: createId(),
|
|
28
|
+
text: output
|
|
29
|
+
}]
|
|
30
|
+
}],
|
|
31
|
+
expert: {
|
|
32
|
+
key: expert.key,
|
|
33
|
+
name: expert.name,
|
|
34
|
+
version: expert.version
|
|
35
|
+
},
|
|
36
|
+
usage: createEmptyUsage()
|
|
37
|
+
};
|
|
32
38
|
}
|
|
33
39
|
function createStartRunEvent(jobId, runId, expertKey, checkpoint) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
return {
|
|
41
|
+
type: "startRun",
|
|
42
|
+
id: createId(),
|
|
43
|
+
expertKey,
|
|
44
|
+
timestamp: Date.now(),
|
|
45
|
+
jobId,
|
|
46
|
+
runId,
|
|
47
|
+
stepNumber: checkpoint.stepNumber,
|
|
48
|
+
initialCheckpoint: checkpoint,
|
|
49
|
+
inputMessages: []
|
|
50
|
+
};
|
|
45
51
|
}
|
|
46
52
|
function createRuntimeInitEvent(jobId, runId, expertName, version, query) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
53
|
+
return {
|
|
54
|
+
type: "initializeRuntime",
|
|
55
|
+
id: createId(),
|
|
56
|
+
timestamp: Date.now(),
|
|
57
|
+
jobId,
|
|
58
|
+
runId,
|
|
59
|
+
runtimeVersion: version,
|
|
60
|
+
expertName,
|
|
61
|
+
experts: [],
|
|
62
|
+
model: "local:default",
|
|
63
|
+
maxRetries: 0,
|
|
64
|
+
timeout: 0,
|
|
65
|
+
query
|
|
66
|
+
};
|
|
61
67
|
}
|
|
62
68
|
function createCompleteRunEvent(jobId, runId, expertKey, checkpoint, output, startedAt) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
69
|
+
const lastMessage = checkpoint.messages[checkpoint.messages.length - 1];
|
|
70
|
+
return {
|
|
71
|
+
type: "completeRun",
|
|
72
|
+
id: createId(),
|
|
73
|
+
expertKey,
|
|
74
|
+
timestamp: Date.now(),
|
|
75
|
+
jobId,
|
|
76
|
+
runId,
|
|
77
|
+
stepNumber: checkpoint.stepNumber,
|
|
78
|
+
checkpoint,
|
|
79
|
+
step: {
|
|
80
|
+
stepNumber: checkpoint.stepNumber,
|
|
81
|
+
newMessages: lastMessage ? [lastMessage] : [],
|
|
82
|
+
usage: createEmptyUsage(),
|
|
83
|
+
startedAt: startedAt ?? Date.now()
|
|
84
|
+
},
|
|
85
|
+
text: output,
|
|
86
|
+
usage: createEmptyUsage()
|
|
87
|
+
};
|
|
82
88
|
}
|
|
83
89
|
function createCallToolsEvent(jobId, runId, expertKey, stepNumber, toolCalls, _checkpoint) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
90
|
+
const expertMessage = {
|
|
91
|
+
id: createId(),
|
|
92
|
+
type: "expertMessage",
|
|
93
|
+
contents: []
|
|
94
|
+
};
|
|
95
|
+
return {
|
|
96
|
+
type: "callTools",
|
|
97
|
+
id: createId(),
|
|
98
|
+
expertKey,
|
|
99
|
+
timestamp: Date.now(),
|
|
100
|
+
jobId,
|
|
101
|
+
runId,
|
|
102
|
+
stepNumber,
|
|
103
|
+
newMessage: expertMessage,
|
|
104
|
+
toolCalls,
|
|
105
|
+
usage: createEmptyUsage()
|
|
106
|
+
};
|
|
101
107
|
}
|
|
102
108
|
function createResolveToolResultsEvent(jobId, runId, expertKey, stepNumber, toolResults) {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
109
|
+
return {
|
|
110
|
+
type: "resolveToolResults",
|
|
111
|
+
id: createId(),
|
|
112
|
+
expertKey,
|
|
113
|
+
timestamp: Date.now(),
|
|
114
|
+
jobId,
|
|
115
|
+
runId,
|
|
116
|
+
stepNumber,
|
|
117
|
+
toolResults
|
|
118
|
+
};
|
|
113
119
|
}
|
|
114
120
|
function createToolMessage(toolCallId, toolName, resultText) {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
121
|
+
return {
|
|
122
|
+
id: createId(),
|
|
123
|
+
type: "toolMessage",
|
|
124
|
+
contents: [{
|
|
125
|
+
type: "toolResultPart",
|
|
126
|
+
id: createId(),
|
|
127
|
+
toolCallId,
|
|
128
|
+
toolName,
|
|
129
|
+
contents: [{
|
|
130
|
+
type: "textPart",
|
|
131
|
+
id: createId(),
|
|
132
|
+
text: resultText
|
|
133
|
+
}]
|
|
134
|
+
}]
|
|
135
|
+
};
|
|
128
136
|
}
|
|
129
137
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
138
|
+
//#endregion
|
|
139
|
+
//#region src/constants/constants.ts
|
|
140
|
+
const defaultPerstackApiBaseUrl = "https://api.perstack.ai";
|
|
141
|
+
const expertKeyRegex = /^((?:@[a-z0-9][a-z0-9_.-]*\/)?[a-z0-9][a-z0-9_.-]*)(?:@((?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-[\w.-]+)?(?:\+[\w.-]+)?)|@([a-z0-9][a-z0-9_.-]*))?$/;
|
|
142
|
+
const expertNameRegex = /^(@[a-z0-9][a-z0-9_-]*\/)?[a-z0-9][a-z0-9_-]*$/;
|
|
143
|
+
const expertVersionRegex = /^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-[\w.-]+)?(?:\+[\w.-]+)?$/;
|
|
144
|
+
const tagNameRegex = /^[a-z0-9][a-z0-9_-]*$/;
|
|
145
|
+
const maxExpertNameLength = 255;
|
|
146
|
+
const defaultMaxSteps = 100;
|
|
147
|
+
const defaultMaxRetries = 5;
|
|
148
|
+
const defaultTimeout = 5 * 1e3 * 60;
|
|
149
|
+
const maxSkillNameLength = 255;
|
|
150
|
+
const maxSkillToolNameLength = 255;
|
|
142
151
|
|
|
143
|
-
|
|
152
|
+
//#endregion
|
|
153
|
+
//#region src/errors.ts
|
|
144
154
|
var PerstackError = class extends Error {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
155
|
+
constructor(message) {
|
|
156
|
+
super(message);
|
|
157
|
+
this.name = "PerstackError";
|
|
158
|
+
}
|
|
149
159
|
};
|
|
150
160
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
{
|
|
342
|
-
name: "gemma3:1b",
|
|
343
|
-
contextWindow: 32e3,
|
|
344
|
-
maxOutputTokens: 32e3
|
|
345
|
-
},
|
|
346
|
-
// https://ai.google.dev/gemma/docs/core/model_card_3
|
|
347
|
-
{
|
|
348
|
-
name: "gemma3:4b",
|
|
349
|
-
contextWindow: 128e3,
|
|
350
|
-
maxOutputTokens: 128e3
|
|
351
|
-
},
|
|
352
|
-
// https://ai.google.dev/gemma/docs/core/model_card_3
|
|
353
|
-
{
|
|
354
|
-
name: "gemma3:12b",
|
|
355
|
-
contextWindow: 128e3,
|
|
356
|
-
maxOutputTokens: 128e3
|
|
357
|
-
},
|
|
358
|
-
// https://ai.google.dev/gemma/docs/core/model_card_3
|
|
359
|
-
{
|
|
360
|
-
name: "gemma3:27b",
|
|
361
|
-
contextWindow: 128e3,
|
|
362
|
-
maxOutputTokens: 128e3
|
|
363
|
-
}
|
|
364
|
-
]
|
|
365
|
-
}
|
|
161
|
+
//#endregion
|
|
162
|
+
//#region src/known-models/index.ts
|
|
163
|
+
const knownModels = [
|
|
164
|
+
{
|
|
165
|
+
provider: "anthropic",
|
|
166
|
+
models: [
|
|
167
|
+
{
|
|
168
|
+
name: "claude-opus-4-6",
|
|
169
|
+
contextWindow: 2e5,
|
|
170
|
+
maxOutputTokens: 128e3
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
name: "claude-opus-4-5",
|
|
174
|
+
contextWindow: 2e5,
|
|
175
|
+
maxOutputTokens: 32e3
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
name: "claude-opus-4-1",
|
|
179
|
+
contextWindow: 2e5,
|
|
180
|
+
maxOutputTokens: 32e3
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
name: "claude-opus-4-20250514",
|
|
184
|
+
contextWindow: 2e5,
|
|
185
|
+
maxOutputTokens: 32e3
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
name: "claude-sonnet-4-5",
|
|
189
|
+
contextWindow: 2e5,
|
|
190
|
+
maxOutputTokens: 64e3
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
name: "claude-sonnet-4-20250514",
|
|
194
|
+
contextWindow: 2e5,
|
|
195
|
+
maxOutputTokens: 64e3
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
name: "claude-3-7-sonnet-20250219",
|
|
199
|
+
contextWindow: 2e5,
|
|
200
|
+
maxOutputTokens: 64e3
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
name: "claude-haiku-4-5",
|
|
204
|
+
contextWindow: 2e5,
|
|
205
|
+
maxOutputTokens: 8192
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
name: "claude-3-5-haiku-latest",
|
|
209
|
+
contextWindow: 2e5,
|
|
210
|
+
maxOutputTokens: 8192
|
|
211
|
+
}
|
|
212
|
+
]
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
provider: "google",
|
|
216
|
+
models: [
|
|
217
|
+
{
|
|
218
|
+
name: "gemini-3-flash-preview",
|
|
219
|
+
contextWindow: 1048576,
|
|
220
|
+
maxOutputTokens: 65536
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
name: "gemini-3-pro-preview",
|
|
224
|
+
contextWindow: 1048576,
|
|
225
|
+
maxOutputTokens: 65536
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
name: "gemini-2.5-pro",
|
|
229
|
+
contextWindow: 1048576,
|
|
230
|
+
maxOutputTokens: 65536
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
name: "gemini-2.5-flash",
|
|
234
|
+
contextWindow: 1048576,
|
|
235
|
+
maxOutputTokens: 65536
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
name: "gemini-2.5-flash-lite",
|
|
239
|
+
contextWindow: 1048576,
|
|
240
|
+
maxOutputTokens: 65536
|
|
241
|
+
}
|
|
242
|
+
]
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
provider: "openai",
|
|
246
|
+
models: [
|
|
247
|
+
{
|
|
248
|
+
name: "gpt-5",
|
|
249
|
+
contextWindow: 4e5,
|
|
250
|
+
maxOutputTokens: 128e3
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
name: "gpt-5-mini",
|
|
254
|
+
contextWindow: 4e5,
|
|
255
|
+
maxOutputTokens: 128e3
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
name: "gpt-5-nano",
|
|
259
|
+
contextWindow: 4e5,
|
|
260
|
+
maxOutputTokens: 128e3
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
name: "gpt-5.2",
|
|
264
|
+
contextWindow: 4e5,
|
|
265
|
+
maxOutputTokens: 128e3
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
name: "gpt-5.2-pro",
|
|
269
|
+
contextWindow: 4e5,
|
|
270
|
+
maxOutputTokens: 128e3
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
name: "gpt-5.1",
|
|
274
|
+
contextWindow: 4e5,
|
|
275
|
+
maxOutputTokens: 128e3
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
name: "gpt-5-chat-latest",
|
|
279
|
+
contextWindow: 128e3,
|
|
280
|
+
maxOutputTokens: 16384
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
name: "o4-mini",
|
|
284
|
+
contextWindow: 2e5,
|
|
285
|
+
maxOutputTokens: 1e5
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
name: "o3",
|
|
289
|
+
contextWindow: 2e5,
|
|
290
|
+
maxOutputTokens: 1e4
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
name: "o3-mini",
|
|
294
|
+
contextWindow: 2e5,
|
|
295
|
+
maxOutputTokens: 1e4
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
name: "gpt-4.1",
|
|
299
|
+
contextWindow: 1047576,
|
|
300
|
+
maxOutputTokens: 32768
|
|
301
|
+
}
|
|
302
|
+
]
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
provider: "deepseek",
|
|
306
|
+
models: [{
|
|
307
|
+
name: "deepseek-chat",
|
|
308
|
+
contextWindow: 128e3,
|
|
309
|
+
maxOutputTokens: 8192
|
|
310
|
+
}, {
|
|
311
|
+
name: "deepseek-reasoner",
|
|
312
|
+
contextWindow: 128e3,
|
|
313
|
+
maxOutputTokens: 64e3
|
|
314
|
+
}]
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
provider: "ollama",
|
|
318
|
+
models: [
|
|
319
|
+
{
|
|
320
|
+
name: "gpt-oss:20b",
|
|
321
|
+
contextWindow: 131072,
|
|
322
|
+
maxOutputTokens: 131072
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
name: "gpt-oss:120b",
|
|
326
|
+
contextWindow: 131072,
|
|
327
|
+
maxOutputTokens: 131072
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
name: "gemma3:1b",
|
|
331
|
+
contextWindow: 32e3,
|
|
332
|
+
maxOutputTokens: 32e3
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
name: "gemma3:4b",
|
|
336
|
+
contextWindow: 128e3,
|
|
337
|
+
maxOutputTokens: 128e3
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
name: "gemma3:12b",
|
|
341
|
+
contextWindow: 128e3,
|
|
342
|
+
maxOutputTokens: 128e3
|
|
343
|
+
},
|
|
344
|
+
{
|
|
345
|
+
name: "gemma3:27b",
|
|
346
|
+
contextWindow: 128e3,
|
|
347
|
+
maxOutputTokens: 128e3
|
|
348
|
+
}
|
|
349
|
+
]
|
|
350
|
+
}
|
|
366
351
|
];
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
352
|
+
|
|
353
|
+
//#endregion
|
|
354
|
+
//#region src/schemas/message-part.ts
|
|
355
|
+
const basePartSchema = z.object({ id: z.string() });
|
|
356
|
+
const textPartSchema = basePartSchema.extend({
|
|
357
|
+
type: z.literal("textPart"),
|
|
358
|
+
text: z.string()
|
|
359
|
+
});
|
|
360
|
+
const imageUrlPartSchema = basePartSchema.extend({
|
|
361
|
+
type: z.literal("imageUrlPart"),
|
|
362
|
+
url: z.url(),
|
|
363
|
+
mimeType: z.string()
|
|
364
|
+
});
|
|
365
|
+
const imageInlinePartSchema = basePartSchema.extend({
|
|
366
|
+
type: z.literal("imageInlinePart"),
|
|
367
|
+
encodedData: z.string(),
|
|
368
|
+
mimeType: z.string()
|
|
369
|
+
});
|
|
370
|
+
const imageBinaryPartSchema = basePartSchema.extend({
|
|
371
|
+
type: z.literal("imageBinaryPart"),
|
|
372
|
+
data: z.string(),
|
|
373
|
+
mimeType: z.string()
|
|
374
|
+
});
|
|
375
|
+
const fileUrlPartSchema = basePartSchema.extend({
|
|
376
|
+
type: z.literal("fileUrlPart"),
|
|
377
|
+
url: z.string().url(),
|
|
378
|
+
mimeType: z.string()
|
|
379
|
+
});
|
|
380
|
+
const fileInlinePartSchema = basePartSchema.extend({
|
|
381
|
+
type: z.literal("fileInlinePart"),
|
|
382
|
+
encodedData: z.string(),
|
|
383
|
+
mimeType: z.string()
|
|
384
|
+
});
|
|
385
|
+
const fileBinaryPartSchema = basePartSchema.extend({
|
|
386
|
+
type: z.literal("fileBinaryPart"),
|
|
387
|
+
data: z.string(),
|
|
388
|
+
mimeType: z.string()
|
|
389
|
+
});
|
|
390
|
+
const toolCallPartSchema = basePartSchema.extend({
|
|
391
|
+
type: z.literal("toolCallPart"),
|
|
392
|
+
toolCallId: z.string(),
|
|
393
|
+
toolName: z.string(),
|
|
394
|
+
args: z.unknown()
|
|
395
|
+
});
|
|
396
|
+
const thinkingPartSchema = basePartSchema.extend({
|
|
397
|
+
type: z.literal("thinkingPart"),
|
|
398
|
+
thinking: z.string(),
|
|
399
|
+
signature: z.string().optional()
|
|
400
|
+
});
|
|
401
|
+
const toolResultPartSchema = basePartSchema.extend({
|
|
402
|
+
type: z.literal("toolResultPart"),
|
|
403
|
+
toolCallId: z.string(),
|
|
404
|
+
toolName: z.string(),
|
|
405
|
+
contents: z.array(z.union([
|
|
406
|
+
textPartSchema,
|
|
407
|
+
imageInlinePartSchema,
|
|
408
|
+
fileInlinePartSchema
|
|
409
|
+
])),
|
|
410
|
+
isError: z.boolean().optional()
|
|
411
|
+
});
|
|
412
|
+
const messagePartSchema = z.discriminatedUnion("type", [
|
|
413
|
+
textPartSchema,
|
|
414
|
+
imageUrlPartSchema,
|
|
415
|
+
imageInlinePartSchema,
|
|
416
|
+
imageBinaryPartSchema,
|
|
417
|
+
fileUrlPartSchema,
|
|
418
|
+
fileInlinePartSchema,
|
|
419
|
+
fileBinaryPartSchema,
|
|
420
|
+
toolCallPartSchema,
|
|
421
|
+
toolResultPartSchema,
|
|
422
|
+
thinkingPartSchema
|
|
433
423
|
]);
|
|
434
424
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
});
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
425
|
+
//#endregion
|
|
426
|
+
//#region src/schemas/activity.ts
|
|
427
|
+
const baseActivitySchema = z.object({
|
|
428
|
+
id: z.string(),
|
|
429
|
+
expertKey: z.string(),
|
|
430
|
+
runId: z.string(),
|
|
431
|
+
previousActivityId: z.string().optional(),
|
|
432
|
+
delegatedBy: z.object({
|
|
433
|
+
expertKey: z.string(),
|
|
434
|
+
runId: z.string()
|
|
435
|
+
}).optional(),
|
|
436
|
+
reasoning: z.string().optional()
|
|
437
|
+
});
|
|
438
|
+
const queryActivitySchema = baseActivitySchema.extend({
|
|
439
|
+
type: z.literal("query"),
|
|
440
|
+
text: z.string()
|
|
441
|
+
});
|
|
442
|
+
const retryActivitySchema = baseActivitySchema.extend({
|
|
443
|
+
type: z.literal("retry"),
|
|
444
|
+
error: z.string(),
|
|
445
|
+
message: z.string()
|
|
446
|
+
});
|
|
447
|
+
const completeActivitySchema = baseActivitySchema.extend({
|
|
448
|
+
type: z.literal("complete"),
|
|
449
|
+
text: z.string()
|
|
450
|
+
});
|
|
451
|
+
const errorActivitySchema = baseActivitySchema.extend({
|
|
452
|
+
type: z.literal("error"),
|
|
453
|
+
error: z.string().optional(),
|
|
454
|
+
errorName: z.string().optional(),
|
|
455
|
+
isRetryable: z.boolean().optional()
|
|
456
|
+
});
|
|
457
|
+
const attemptCompletionActivitySchema = baseActivitySchema.extend({
|
|
458
|
+
type: z.literal("attemptCompletion"),
|
|
459
|
+
remainingTodos: z.array(z.object({
|
|
460
|
+
id: z.number(),
|
|
461
|
+
title: z.string(),
|
|
462
|
+
completed: z.boolean()
|
|
463
|
+
})).optional(),
|
|
464
|
+
error: z.string().optional()
|
|
465
|
+
});
|
|
466
|
+
const todoActivitySchema = baseActivitySchema.extend({
|
|
467
|
+
type: z.literal("todo"),
|
|
468
|
+
newTodos: z.array(z.string()).optional(),
|
|
469
|
+
completedTodos: z.array(z.number()).optional(),
|
|
470
|
+
todos: z.array(z.object({
|
|
471
|
+
id: z.number(),
|
|
472
|
+
title: z.string(),
|
|
473
|
+
completed: z.boolean()
|
|
474
|
+
})),
|
|
475
|
+
error: z.string().optional()
|
|
476
|
+
});
|
|
477
|
+
const clearTodoActivitySchema = baseActivitySchema.extend({
|
|
478
|
+
type: z.literal("clearTodo"),
|
|
479
|
+
error: z.string().optional()
|
|
480
|
+
});
|
|
481
|
+
const readImageFileActivitySchema = baseActivitySchema.extend({
|
|
482
|
+
type: z.literal("readImageFile"),
|
|
483
|
+
path: z.string(),
|
|
484
|
+
mimeType: z.string().optional(),
|
|
485
|
+
size: z.number().optional(),
|
|
486
|
+
error: z.string().optional()
|
|
487
|
+
});
|
|
488
|
+
const readPdfFileActivitySchema = baseActivitySchema.extend({
|
|
489
|
+
type: z.literal("readPdfFile"),
|
|
490
|
+
path: z.string(),
|
|
491
|
+
mimeType: z.string().optional(),
|
|
492
|
+
size: z.number().optional(),
|
|
493
|
+
error: z.string().optional()
|
|
494
|
+
});
|
|
495
|
+
const readTextFileActivitySchema = baseActivitySchema.extend({
|
|
496
|
+
type: z.literal("readTextFile"),
|
|
497
|
+
path: z.string(),
|
|
498
|
+
content: z.string().optional(),
|
|
499
|
+
from: z.number().optional(),
|
|
500
|
+
to: z.number().optional(),
|
|
501
|
+
error: z.string().optional()
|
|
502
|
+
});
|
|
503
|
+
const editTextFileActivitySchema = baseActivitySchema.extend({
|
|
504
|
+
type: z.literal("editTextFile"),
|
|
505
|
+
path: z.string(),
|
|
506
|
+
newText: z.string(),
|
|
507
|
+
oldText: z.string(),
|
|
508
|
+
error: z.string().optional()
|
|
509
|
+
});
|
|
510
|
+
const writeTextFileActivitySchema = baseActivitySchema.extend({
|
|
511
|
+
type: z.literal("writeTextFile"),
|
|
512
|
+
path: z.string(),
|
|
513
|
+
text: z.string(),
|
|
514
|
+
error: z.string().optional()
|
|
515
|
+
});
|
|
516
|
+
const execActivitySchema = baseActivitySchema.extend({
|
|
517
|
+
type: z.literal("exec"),
|
|
518
|
+
command: z.string(),
|
|
519
|
+
args: z.array(z.string()),
|
|
520
|
+
cwd: z.string(),
|
|
521
|
+
output: z.string().optional(),
|
|
522
|
+
error: z.string().optional(),
|
|
523
|
+
stdout: z.string().optional(),
|
|
524
|
+
stderr: z.string().optional()
|
|
525
|
+
});
|
|
526
|
+
const delegateActivitySchema = baseActivitySchema.extend({
|
|
527
|
+
type: z.literal("delegate"),
|
|
528
|
+
delegateExpertKey: z.string(),
|
|
529
|
+
query: z.string()
|
|
530
|
+
});
|
|
531
|
+
const delegationCompleteActivitySchema = baseActivitySchema.extend({
|
|
532
|
+
type: z.literal("delegationComplete"),
|
|
533
|
+
count: z.number()
|
|
534
|
+
});
|
|
535
|
+
const interactiveToolActivitySchema = baseActivitySchema.extend({
|
|
536
|
+
type: z.literal("interactiveTool"),
|
|
537
|
+
skillName: z.string(),
|
|
538
|
+
toolName: z.string(),
|
|
539
|
+
args: z.record(z.string(), z.unknown())
|
|
540
|
+
});
|
|
541
|
+
const generalToolActivitySchema = baseActivitySchema.extend({
|
|
542
|
+
type: z.literal("generalTool"),
|
|
543
|
+
skillName: z.string(),
|
|
544
|
+
toolName: z.string(),
|
|
545
|
+
args: z.record(z.string(), z.unknown()),
|
|
546
|
+
result: z.array(messagePartSchema).optional(),
|
|
547
|
+
error: z.string().optional()
|
|
548
|
+
});
|
|
549
|
+
const addSkillActivitySchema = baseActivitySchema.extend({
|
|
550
|
+
type: z.literal("addSkill"),
|
|
551
|
+
name: z.string(),
|
|
552
|
+
skillType: z.string(),
|
|
553
|
+
tools: z.array(z.string()).optional(),
|
|
554
|
+
error: z.string().optional()
|
|
555
|
+
});
|
|
556
|
+
const removeSkillActivitySchema = baseActivitySchema.extend({
|
|
557
|
+
type: z.literal("removeSkill"),
|
|
558
|
+
skillName: z.string(),
|
|
559
|
+
error: z.string().optional()
|
|
560
|
+
});
|
|
561
|
+
const addDelegateActivitySchema = baseActivitySchema.extend({
|
|
562
|
+
type: z.literal("addDelegate"),
|
|
563
|
+
targetExpertKey: z.string(),
|
|
564
|
+
delegateToolName: z.string().optional(),
|
|
565
|
+
error: z.string().optional()
|
|
566
|
+
});
|
|
567
|
+
const removeDelegateActivitySchema = baseActivitySchema.extend({
|
|
568
|
+
type: z.literal("removeDelegate"),
|
|
569
|
+
expertName: z.string(),
|
|
570
|
+
error: z.string().optional()
|
|
571
|
+
});
|
|
572
|
+
const createExpertActivitySchema = baseActivitySchema.extend({
|
|
573
|
+
type: z.literal("createExpert"),
|
|
574
|
+
targetKey: z.string(),
|
|
575
|
+
description: z.string().optional(),
|
|
576
|
+
resultExpertKey: z.string().optional(),
|
|
577
|
+
error: z.string().optional()
|
|
578
|
+
});
|
|
579
|
+
const activitySchema = z.discriminatedUnion("type", [
|
|
580
|
+
queryActivitySchema,
|
|
581
|
+
retryActivitySchema,
|
|
582
|
+
completeActivitySchema,
|
|
583
|
+
errorActivitySchema,
|
|
584
|
+
attemptCompletionActivitySchema,
|
|
585
|
+
todoActivitySchema,
|
|
586
|
+
clearTodoActivitySchema,
|
|
587
|
+
readImageFileActivitySchema,
|
|
588
|
+
readPdfFileActivitySchema,
|
|
589
|
+
readTextFileActivitySchema,
|
|
590
|
+
editTextFileActivitySchema,
|
|
591
|
+
writeTextFileActivitySchema,
|
|
592
|
+
execActivitySchema,
|
|
593
|
+
delegateActivitySchema,
|
|
594
|
+
delegationCompleteActivitySchema,
|
|
595
|
+
interactiveToolActivitySchema,
|
|
596
|
+
generalToolActivitySchema,
|
|
597
|
+
addSkillActivitySchema,
|
|
598
|
+
removeSkillActivitySchema,
|
|
599
|
+
addDelegateActivitySchema,
|
|
600
|
+
removeDelegateActivitySchema,
|
|
601
|
+
createExpertActivitySchema
|
|
568
602
|
]);
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
});
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
603
|
+
const parallelActivitiesGroupSchema = z.object({
|
|
604
|
+
type: z.literal("parallelGroup"),
|
|
605
|
+
id: z.string(),
|
|
606
|
+
expertKey: z.string(),
|
|
607
|
+
runId: z.string(),
|
|
608
|
+
reasoning: z.string().optional(),
|
|
609
|
+
activities: z.array(activitySchema)
|
|
610
|
+
});
|
|
611
|
+
const activityOrGroupSchema = z.union([activitySchema, parallelActivitiesGroupSchema]);
|
|
612
|
+
|
|
613
|
+
//#endregion
|
|
614
|
+
//#region src/schemas/message.ts
|
|
615
|
+
const baseMessageSchema = z.object({ id: z.string() });
|
|
616
|
+
const instructionMessageSchema = baseMessageSchema.extend({
|
|
617
|
+
type: z.literal("instructionMessage"),
|
|
618
|
+
contents: z.array(textPartSchema),
|
|
619
|
+
cache: z.boolean().optional()
|
|
620
|
+
});
|
|
621
|
+
const userMessageSchema = baseMessageSchema.extend({
|
|
622
|
+
type: z.literal("userMessage"),
|
|
623
|
+
contents: z.array(z.union([
|
|
624
|
+
textPartSchema,
|
|
625
|
+
imageUrlPartSchema,
|
|
626
|
+
imageInlinePartSchema,
|
|
627
|
+
imageBinaryPartSchema,
|
|
628
|
+
fileUrlPartSchema,
|
|
629
|
+
fileInlinePartSchema,
|
|
630
|
+
fileBinaryPartSchema
|
|
631
|
+
])),
|
|
632
|
+
cache: z.boolean().optional()
|
|
633
|
+
});
|
|
634
|
+
const expertMessageSchema = baseMessageSchema.extend({
|
|
635
|
+
type: z.literal("expertMessage"),
|
|
636
|
+
contents: z.array(z.union([
|
|
637
|
+
textPartSchema,
|
|
638
|
+
toolCallPartSchema,
|
|
639
|
+
thinkingPartSchema
|
|
640
|
+
])),
|
|
641
|
+
cache: z.boolean().optional()
|
|
642
|
+
});
|
|
643
|
+
const toolMessageSchema = baseMessageSchema.extend({
|
|
644
|
+
type: z.literal("toolMessage"),
|
|
645
|
+
contents: z.array(toolResultPartSchema),
|
|
646
|
+
cache: z.boolean().optional()
|
|
647
|
+
});
|
|
648
|
+
const messageSchema = z.union([
|
|
649
|
+
instructionMessageSchema,
|
|
650
|
+
userMessageSchema,
|
|
651
|
+
expertMessageSchema,
|
|
652
|
+
toolMessageSchema
|
|
616
653
|
]);
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
654
|
+
|
|
655
|
+
//#endregion
|
|
656
|
+
//#region src/schemas/tool-call.ts
|
|
657
|
+
const toolCallSchema = z.object({
|
|
658
|
+
id: z.string().min(1).max(255),
|
|
659
|
+
skillName: z.string().min(1).max(maxSkillNameLength),
|
|
660
|
+
toolName: z.string().min(1).max(maxSkillToolNameLength),
|
|
661
|
+
args: z.record(z.string().min(1), z.unknown())
|
|
662
|
+
});
|
|
663
|
+
|
|
664
|
+
//#endregion
|
|
665
|
+
//#region src/schemas/tool-result.ts
|
|
666
|
+
const toolResultSchema = z.object({
|
|
667
|
+
id: z.string().min(1).max(255),
|
|
668
|
+
skillName: z.string().min(1).max(maxSkillNameLength),
|
|
669
|
+
toolName: z.string().min(1).max(maxSkillToolNameLength),
|
|
670
|
+
result: z.array(messagePartSchema)
|
|
671
|
+
});
|
|
672
|
+
|
|
673
|
+
//#endregion
|
|
674
|
+
//#region src/schemas/usage.ts
|
|
675
|
+
const usageSchema = z.object({
|
|
676
|
+
inputTokens: z.number(),
|
|
677
|
+
outputTokens: z.number(),
|
|
678
|
+
reasoningTokens: z.number(),
|
|
679
|
+
totalTokens: z.number(),
|
|
680
|
+
cachedInputTokens: z.number()
|
|
635
681
|
});
|
|
636
682
|
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
683
|
+
//#endregion
|
|
684
|
+
//#region src/schemas/checkpoint.ts
|
|
685
|
+
const checkpointStatusSchema = z.enum([
|
|
686
|
+
"init",
|
|
687
|
+
"proceeding",
|
|
688
|
+
"completed",
|
|
689
|
+
"stoppedByInteractiveTool",
|
|
690
|
+
"stoppedByDelegate",
|
|
691
|
+
"stoppedByExceededMaxSteps",
|
|
692
|
+
"stoppedByError",
|
|
693
|
+
"stoppedByCancellation"
|
|
647
694
|
]);
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
});
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
});
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
name: z.string().min(1),
|
|
704
|
-
definition: z.string().min(1)
|
|
705
|
-
});
|
|
706
|
-
var anthropicProviderSkillSchema = z.discriminatedUnion("type", [
|
|
707
|
-
builtinAnthropicSkillSchema,
|
|
708
|
-
customAnthropicSkillSchema
|
|
695
|
+
const delegationTargetSchema = z.object({
|
|
696
|
+
expert: z.object({
|
|
697
|
+
key: z.string(),
|
|
698
|
+
name: z.string(),
|
|
699
|
+
version: z.string()
|
|
700
|
+
}),
|
|
701
|
+
toolCallId: z.string(),
|
|
702
|
+
toolName: z.string(),
|
|
703
|
+
query: z.string()
|
|
704
|
+
});
|
|
705
|
+
const checkpointSchema = z.object({
|
|
706
|
+
id: z.string(),
|
|
707
|
+
jobId: z.string(),
|
|
708
|
+
runId: z.string(),
|
|
709
|
+
status: checkpointStatusSchema,
|
|
710
|
+
stepNumber: z.number(),
|
|
711
|
+
messages: z.array(messageSchema),
|
|
712
|
+
expert: z.object({
|
|
713
|
+
key: z.string(),
|
|
714
|
+
name: z.string(),
|
|
715
|
+
version: z.string()
|
|
716
|
+
}),
|
|
717
|
+
delegateTo: z.array(delegationTargetSchema).optional(),
|
|
718
|
+
delegatedBy: z.object({
|
|
719
|
+
expert: z.object({
|
|
720
|
+
key: z.string(),
|
|
721
|
+
name: z.string(),
|
|
722
|
+
version: z.string()
|
|
723
|
+
}),
|
|
724
|
+
toolCallId: z.string(),
|
|
725
|
+
toolName: z.string(),
|
|
726
|
+
checkpointId: z.string(),
|
|
727
|
+
runId: z.string()
|
|
728
|
+
}).optional(),
|
|
729
|
+
usage: usageSchema,
|
|
730
|
+
contextWindow: z.number().optional(),
|
|
731
|
+
contextWindowUsage: z.number().optional(),
|
|
732
|
+
pendingToolCalls: z.array(toolCallSchema).optional(),
|
|
733
|
+
partialToolResults: z.array(toolResultSchema).optional(),
|
|
734
|
+
metadata: z.object({}).passthrough().optional(),
|
|
735
|
+
error: z.object({
|
|
736
|
+
name: z.string(),
|
|
737
|
+
message: z.string(),
|
|
738
|
+
statusCode: z.number().optional(),
|
|
739
|
+
isRetryable: z.boolean()
|
|
740
|
+
}).optional(),
|
|
741
|
+
retryCount: z.number().optional()
|
|
742
|
+
});
|
|
743
|
+
|
|
744
|
+
//#endregion
|
|
745
|
+
//#region src/schemas/provider-tools.ts
|
|
746
|
+
const anthropicProviderToolNameSchema = z.enum([
|
|
747
|
+
"webSearch",
|
|
748
|
+
"webFetch",
|
|
749
|
+
"codeExecution"
|
|
709
750
|
]);
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
751
|
+
const builtinAnthropicSkillSchema = z.object({
|
|
752
|
+
type: z.literal("builtin"),
|
|
753
|
+
skillId: z.enum([
|
|
754
|
+
"pdf",
|
|
755
|
+
"docx",
|
|
756
|
+
"pptx",
|
|
757
|
+
"xlsx"
|
|
758
|
+
])
|
|
759
|
+
});
|
|
760
|
+
const customAnthropicSkillSchema = z.object({
|
|
761
|
+
type: z.literal("custom"),
|
|
762
|
+
name: z.string().min(1),
|
|
763
|
+
definition: z.string().min(1)
|
|
764
|
+
});
|
|
765
|
+
const anthropicProviderSkillSchema = z.discriminatedUnion("type", [builtinAnthropicSkillSchema, customAnthropicSkillSchema]);
|
|
766
|
+
const openaiProviderToolNameSchema = z.enum([
|
|
767
|
+
"webSearch",
|
|
768
|
+
"fileSearch",
|
|
769
|
+
"codeInterpreter",
|
|
770
|
+
"imageGeneration"
|
|
715
771
|
]);
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
772
|
+
const googleProviderToolNameSchema = z.enum([
|
|
773
|
+
"googleSearch",
|
|
774
|
+
"codeExecution",
|
|
775
|
+
"urlContext",
|
|
776
|
+
"fileSearch",
|
|
777
|
+
"googleMaps"
|
|
722
778
|
]);
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
779
|
+
const azureOpenAIProviderToolNameSchema = z.enum([
|
|
780
|
+
"webSearchPreview",
|
|
781
|
+
"fileSearch",
|
|
782
|
+
"codeInterpreter",
|
|
783
|
+
"imageGeneration"
|
|
728
784
|
]);
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
785
|
+
const vertexProviderToolNameSchema = z.enum([
|
|
786
|
+
"codeExecution",
|
|
787
|
+
"urlContext",
|
|
788
|
+
"googleSearch",
|
|
789
|
+
"enterpriseWebSearch",
|
|
790
|
+
"googleMaps"
|
|
735
791
|
]);
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
});
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
webFetch: webFetchOptionsSchema.optional(),
|
|
750
|
-
fileSearch: fileSearchOptionsSchema.optional()
|
|
792
|
+
const webSearchOptionsSchema = z.object({
|
|
793
|
+
maxUses: z.number().int().positive().optional(),
|
|
794
|
+
allowedDomains: z.array(z.string()).optional()
|
|
795
|
+
});
|
|
796
|
+
const webFetchOptionsSchema = z.object({ maxUses: z.number().int().positive().optional() });
|
|
797
|
+
const fileSearchOptionsSchema = z.object({
|
|
798
|
+
vectorStoreIds: z.array(z.string()).optional(),
|
|
799
|
+
maxNumResults: z.number().int().positive().optional()
|
|
800
|
+
});
|
|
801
|
+
const providerToolOptionsSchema = z.object({
|
|
802
|
+
webSearch: webSearchOptionsSchema.optional(),
|
|
803
|
+
webFetch: webFetchOptionsSchema.optional(),
|
|
804
|
+
fileSearch: fileSearchOptionsSchema.optional()
|
|
751
805
|
}).optional();
|
|
752
|
-
|
|
806
|
+
|
|
807
|
+
//#endregion
|
|
808
|
+
//#region src/schemas/runtime-version.ts
|
|
809
|
+
const runtimeVersionSchema = z.string().regex(/^v\d+\.\d+$/, "Runtime version must be in format \"vX.Y\" (e.g., \"v1.0\")").transform((v) => v);
|
|
810
|
+
|
|
811
|
+
//#endregion
|
|
812
|
+
//#region src/schemas/skill.ts
|
|
753
813
|
function isPrivateOrLocalIP(hostname) {
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
if (hostname.startsWith("::ffff:")) {
|
|
773
|
-
const ipv4Part = hostname.slice(7);
|
|
774
|
-
if (isPrivateOrLocalIP(ipv4Part)) {
|
|
775
|
-
return true;
|
|
776
|
-
}
|
|
777
|
-
}
|
|
778
|
-
return false;
|
|
814
|
+
if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1" || hostname === "0.0.0.0") return true;
|
|
815
|
+
const ipv4Match = hostname.match(/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/);
|
|
816
|
+
if (ipv4Match) {
|
|
817
|
+
const a = Number(ipv4Match[1]);
|
|
818
|
+
const b = Number(ipv4Match[2]);
|
|
819
|
+
if (a === 10) return true;
|
|
820
|
+
if (a === 172 && b >= 16 && b <= 31) return true;
|
|
821
|
+
if (a === 192 && b === 168) return true;
|
|
822
|
+
if (a === 169 && b === 254) return true;
|
|
823
|
+
if (a === 127) return true;
|
|
824
|
+
}
|
|
825
|
+
if (hostname.includes(":")) {
|
|
826
|
+
if (hostname.startsWith("fe80:") || hostname.startsWith("fc") || hostname.startsWith("fd")) return true;
|
|
827
|
+
}
|
|
828
|
+
if (hostname.startsWith("::ffff:")) {
|
|
829
|
+
if (isPrivateOrLocalIP(hostname.slice(7))) return true;
|
|
830
|
+
}
|
|
831
|
+
return false;
|
|
779
832
|
}
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
)
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
});
|
|
833
|
-
var skillSchema = z.discriminatedUnion("type", [
|
|
834
|
-
mcpStdioSkillSchema,
|
|
835
|
-
mcpSseSkillSchema,
|
|
836
|
-
interactiveSkillSchema
|
|
833
|
+
const sseEndpointSchema$1 = z.string().url().refine((url) => {
|
|
834
|
+
try {
|
|
835
|
+
const parsed = new URL(url);
|
|
836
|
+
if (parsed.protocol !== "https:") return false;
|
|
837
|
+
if (isPrivateOrLocalIP(parsed.hostname)) return false;
|
|
838
|
+
return true;
|
|
839
|
+
} catch {
|
|
840
|
+
return false;
|
|
841
|
+
}
|
|
842
|
+
}, { message: "Endpoint must be a public HTTPS URL" });
|
|
843
|
+
const mcpStdioSkillSchema = z.object({
|
|
844
|
+
type: z.literal("mcpStdioSkill"),
|
|
845
|
+
name: z.string(),
|
|
846
|
+
description: z.string().optional(),
|
|
847
|
+
rule: z.string().optional(),
|
|
848
|
+
pick: z.array(z.string()).optional().default([]),
|
|
849
|
+
omit: z.array(z.string()).optional().default([]),
|
|
850
|
+
command: z.string(),
|
|
851
|
+
packageName: z.string().optional(),
|
|
852
|
+
args: z.array(z.string()).optional().default([]),
|
|
853
|
+
requiredEnv: z.array(z.string()).optional().default([])
|
|
854
|
+
});
|
|
855
|
+
const mcpSseSkillSchema = z.object({
|
|
856
|
+
type: z.literal("mcpSseSkill"),
|
|
857
|
+
name: z.string(),
|
|
858
|
+
description: z.string().optional(),
|
|
859
|
+
rule: z.string().optional(),
|
|
860
|
+
pick: z.array(z.string()).optional().default([]),
|
|
861
|
+
omit: z.array(z.string()).optional().default([]),
|
|
862
|
+
endpoint: sseEndpointSchema$1
|
|
863
|
+
});
|
|
864
|
+
const interactiveToolSchema = z.object({
|
|
865
|
+
name: z.string(),
|
|
866
|
+
description: z.string().optional(),
|
|
867
|
+
inputJsonSchema: z.string()
|
|
868
|
+
});
|
|
869
|
+
const interactiveSkillSchema = z.object({
|
|
870
|
+
type: z.literal("interactiveSkill"),
|
|
871
|
+
name: z.string(),
|
|
872
|
+
description: z.string().optional(),
|
|
873
|
+
rule: z.string().optional(),
|
|
874
|
+
tools: z.record(z.string(), interactiveToolSchema.omit({ name: true })).transform((tools) => {
|
|
875
|
+
return Object.fromEntries(Object.entries(tools).map(([key, toolWithoutName]) => [key, interactiveToolSchema.parse({
|
|
876
|
+
...toolWithoutName,
|
|
877
|
+
name: key
|
|
878
|
+
})]));
|
|
879
|
+
})
|
|
880
|
+
});
|
|
881
|
+
const skillSchema = z.discriminatedUnion("type", [
|
|
882
|
+
mcpStdioSkillSchema,
|
|
883
|
+
mcpSseSkillSchema,
|
|
884
|
+
interactiveSkillSchema
|
|
837
885
|
]);
|
|
838
886
|
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
"stoppedByInteractiveTool",
|
|
887
|
-
"stoppedByError",
|
|
888
|
-
"stoppedByCancellation"
|
|
887
|
+
//#endregion
|
|
888
|
+
//#region src/schemas/expert.ts
|
|
889
|
+
const expertSchema = z.object({
|
|
890
|
+
key: z.string().regex(expertKeyRegex).min(1),
|
|
891
|
+
name: z.string().regex(expertNameRegex).min(1).max(maxExpertNameLength),
|
|
892
|
+
version: z.string().regex(expertVersionRegex),
|
|
893
|
+
description: z.string().max(1024 * 2).optional(),
|
|
894
|
+
instruction: z.string().min(1).max(1024 * 20),
|
|
895
|
+
skills: z.record(z.string(), z.discriminatedUnion("type", [
|
|
896
|
+
mcpStdioSkillSchema.omit({ name: true }),
|
|
897
|
+
mcpSseSkillSchema.omit({ name: true }),
|
|
898
|
+
interactiveSkillSchema.omit({ name: true })
|
|
899
|
+
])).optional().default({ "@perstack/base": {
|
|
900
|
+
type: "mcpStdioSkill",
|
|
901
|
+
description: "Base skill",
|
|
902
|
+
command: "npx",
|
|
903
|
+
args: ["-y", "@perstack/base"],
|
|
904
|
+
pick: [],
|
|
905
|
+
omit: [],
|
|
906
|
+
requiredEnv: []
|
|
907
|
+
} }).transform((skills) => {
|
|
908
|
+
return Object.fromEntries(Object.entries(skills).map(([key, skillWithoutName]) => [key, z.discriminatedUnion("type", [
|
|
909
|
+
mcpStdioSkillSchema,
|
|
910
|
+
mcpSseSkillSchema,
|
|
911
|
+
interactiveSkillSchema
|
|
912
|
+
]).parse({
|
|
913
|
+
...skillWithoutName,
|
|
914
|
+
name: key
|
|
915
|
+
})]));
|
|
916
|
+
}),
|
|
917
|
+
delegates: z.array(z.string().regex(expertKeyRegex).min(1)).optional().default([]),
|
|
918
|
+
tags: z.array(z.string().regex(tagNameRegex).min(1)).optional().default([]),
|
|
919
|
+
minRuntimeVersion: runtimeVersionSchema.default("v1.0"),
|
|
920
|
+
providerTools: z.array(z.string()).optional(),
|
|
921
|
+
providerSkills: z.array(anthropicProviderSkillSchema).optional(),
|
|
922
|
+
providerToolOptions: providerToolOptionsSchema
|
|
923
|
+
});
|
|
924
|
+
|
|
925
|
+
//#endregion
|
|
926
|
+
//#region src/schemas/job.ts
|
|
927
|
+
const jobStatusSchema = z.enum([
|
|
928
|
+
"running",
|
|
929
|
+
"completed",
|
|
930
|
+
"stoppedByMaxSteps",
|
|
931
|
+
"stoppedByInteractiveTool",
|
|
932
|
+
"stoppedByError",
|
|
933
|
+
"stoppedByCancellation"
|
|
889
934
|
]);
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
});
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
935
|
+
const jobSchema = z.object({
|
|
936
|
+
id: z.string(),
|
|
937
|
+
status: jobStatusSchema,
|
|
938
|
+
coordinatorExpertKey: z.string(),
|
|
939
|
+
runtimeVersion: runtimeVersionSchema,
|
|
940
|
+
totalSteps: z.number(),
|
|
941
|
+
maxSteps: z.number().optional(),
|
|
942
|
+
usage: usageSchema,
|
|
943
|
+
startedAt: z.number(),
|
|
944
|
+
finishedAt: z.number().optional()
|
|
945
|
+
});
|
|
946
|
+
|
|
947
|
+
//#endregion
|
|
948
|
+
//#region src/schemas/lockfile.ts
|
|
949
|
+
const lockfileToolDefinitionSchema = z.object({
|
|
950
|
+
skillName: z.string(),
|
|
951
|
+
name: z.string(),
|
|
952
|
+
description: z.string().optional(),
|
|
953
|
+
inputSchema: z.record(z.string(), z.unknown())
|
|
954
|
+
});
|
|
955
|
+
const lockfileExpertSchema = z.object({
|
|
956
|
+
key: z.string(),
|
|
957
|
+
name: z.string(),
|
|
958
|
+
version: z.string(),
|
|
959
|
+
description: z.string().optional(),
|
|
960
|
+
instruction: z.string(),
|
|
961
|
+
skills: z.record(z.string(), skillSchema),
|
|
962
|
+
delegates: z.array(z.string()),
|
|
963
|
+
tags: z.array(z.string()),
|
|
964
|
+
toolDefinitions: z.array(lockfileToolDefinitionSchema)
|
|
965
|
+
});
|
|
966
|
+
const lockfileSchema = z.object({
|
|
967
|
+
version: z.literal("1"),
|
|
968
|
+
generatedAt: z.number(),
|
|
969
|
+
configPath: z.string(),
|
|
970
|
+
experts: z.record(z.string(), lockfileExpertSchema)
|
|
971
|
+
});
|
|
972
|
+
|
|
973
|
+
//#endregion
|
|
974
|
+
//#region src/schemas/provider-config.ts
|
|
975
|
+
const headersSchema = z.record(z.string(), z.string()).optional();
|
|
976
|
+
const providerNameSchema = z.enum([
|
|
977
|
+
"anthropic",
|
|
978
|
+
"google",
|
|
979
|
+
"openai",
|
|
980
|
+
"ollama",
|
|
981
|
+
"azure-openai",
|
|
982
|
+
"amazon-bedrock",
|
|
983
|
+
"google-vertex",
|
|
984
|
+
"deepseek"
|
|
934
985
|
]);
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
});
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
});
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
});
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
});
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
});
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
});
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
});
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
});
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
986
|
+
const anthropicProviderConfigSchema = z.object({
|
|
987
|
+
providerName: z.literal(providerNameSchema.enum.anthropic),
|
|
988
|
+
apiKey: z.string(),
|
|
989
|
+
baseUrl: z.string().optional(),
|
|
990
|
+
headers: headersSchema
|
|
991
|
+
});
|
|
992
|
+
const googleGenerativeAiProviderConfigSchema = z.object({
|
|
993
|
+
providerName: z.literal(providerNameSchema.enum.google),
|
|
994
|
+
apiKey: z.string(),
|
|
995
|
+
baseUrl: z.string().optional(),
|
|
996
|
+
headers: headersSchema
|
|
997
|
+
});
|
|
998
|
+
const openAiProviderConfigSchema = z.object({
|
|
999
|
+
providerName: z.literal(providerNameSchema.enum.openai),
|
|
1000
|
+
apiKey: z.string(),
|
|
1001
|
+
baseUrl: z.string().optional(),
|
|
1002
|
+
organization: z.string().optional(),
|
|
1003
|
+
project: z.string().optional(),
|
|
1004
|
+
name: z.string().optional(),
|
|
1005
|
+
headers: headersSchema
|
|
1006
|
+
});
|
|
1007
|
+
const ollamaProviderConfigSchema = z.object({
|
|
1008
|
+
providerName: z.literal(providerNameSchema.enum.ollama),
|
|
1009
|
+
baseUrl: z.string().optional(),
|
|
1010
|
+
headers: headersSchema
|
|
1011
|
+
});
|
|
1012
|
+
const azureOpenAiProviderConfigSchema = z.object({
|
|
1013
|
+
providerName: z.literal(providerNameSchema.enum["azure-openai"]),
|
|
1014
|
+
apiKey: z.string(),
|
|
1015
|
+
resourceName: z.string().optional(),
|
|
1016
|
+
apiVersion: z.string().optional(),
|
|
1017
|
+
baseUrl: z.string().optional(),
|
|
1018
|
+
headers: headersSchema,
|
|
1019
|
+
useDeploymentBasedUrls: z.boolean().optional()
|
|
1020
|
+
});
|
|
1021
|
+
const amazonBedrockProviderConfigSchema = z.object({
|
|
1022
|
+
providerName: z.literal(providerNameSchema.enum["amazon-bedrock"]),
|
|
1023
|
+
accessKeyId: z.string(),
|
|
1024
|
+
secretAccessKey: z.string(),
|
|
1025
|
+
region: z.string(),
|
|
1026
|
+
sessionToken: z.string().optional()
|
|
1027
|
+
});
|
|
1028
|
+
const googleVertexProviderConfigSchema = z.object({
|
|
1029
|
+
providerName: z.literal(providerNameSchema.enum["google-vertex"]),
|
|
1030
|
+
project: z.string().optional(),
|
|
1031
|
+
location: z.string().optional(),
|
|
1032
|
+
baseUrl: z.string().optional(),
|
|
1033
|
+
headers: headersSchema
|
|
1034
|
+
});
|
|
1035
|
+
const deepseekProviderConfigSchema = z.object({
|
|
1036
|
+
providerName: z.literal(providerNameSchema.enum.deepseek),
|
|
1037
|
+
apiKey: z.string(),
|
|
1038
|
+
baseUrl: z.string().optional(),
|
|
1039
|
+
headers: headersSchema
|
|
1040
|
+
});
|
|
1041
|
+
const providerConfigSchema = z.discriminatedUnion("providerName", [
|
|
1042
|
+
anthropicProviderConfigSchema,
|
|
1043
|
+
googleGenerativeAiProviderConfigSchema,
|
|
1044
|
+
openAiProviderConfigSchema,
|
|
1045
|
+
ollamaProviderConfigSchema,
|
|
1046
|
+
azureOpenAiProviderConfigSchema,
|
|
1047
|
+
amazonBedrockProviderConfigSchema,
|
|
1048
|
+
googleVertexProviderConfigSchema,
|
|
1049
|
+
deepseekProviderConfigSchema
|
|
999
1050
|
]);
|
|
1000
1051
|
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
});
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
)
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
})
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
}),
|
|
1097
|
-
z.object({
|
|
1098
|
-
providerName: z.literal("deepseek"),
|
|
1099
|
-
setting: deepseekSettingSchema.optional()
|
|
1100
|
-
})
|
|
1052
|
+
//#endregion
|
|
1053
|
+
//#region src/schemas/perstack-toml.ts
|
|
1054
|
+
/** Default reasoning budget - enables extended thinking by default */
|
|
1055
|
+
const defaultReasoningBudget = "low";
|
|
1056
|
+
const reasoningBudgetSchema = z.union([z.enum([
|
|
1057
|
+
"none",
|
|
1058
|
+
"minimal",
|
|
1059
|
+
"low",
|
|
1060
|
+
"medium",
|
|
1061
|
+
"high"
|
|
1062
|
+
]), z.number().int().nonnegative()]);
|
|
1063
|
+
const domainPatternRegex = /^(\*\.)?[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?)*$/;
|
|
1064
|
+
const punycodeRegex = /(?:^|\.)(xn--)/i;
|
|
1065
|
+
const domainPatternSchema = z.string().regex(domainPatternRegex, { message: "Invalid domain pattern. Use exact domain (example.com) or wildcard prefix (*.example.com)" }).refine((domain) => !punycodeRegex.test(domain), { message: "Punycode domains (xn--) are not allowed to prevent homograph attacks. Use ASCII domains only." });
|
|
1066
|
+
const sseEndpointSchema = z.string().url().refine((url) => {
|
|
1067
|
+
try {
|
|
1068
|
+
const parsed = new URL(url);
|
|
1069
|
+
if (parsed.protocol !== "https:") return false;
|
|
1070
|
+
if (isPrivateOrLocalIP(parsed.hostname)) return false;
|
|
1071
|
+
return true;
|
|
1072
|
+
} catch {
|
|
1073
|
+
return false;
|
|
1074
|
+
}
|
|
1075
|
+
}, { message: "SSE endpoint must be a public HTTPS URL" });
|
|
1076
|
+
const httpsUrlSchema = z.string().url().refine((url) => url.startsWith("https://"), { message: "URL must use HTTPS" });
|
|
1077
|
+
const anthropicSettingSchema = z.object({
|
|
1078
|
+
baseUrl: httpsUrlSchema.optional(),
|
|
1079
|
+
headers: headersSchema
|
|
1080
|
+
});
|
|
1081
|
+
const googleSettingSchema = z.object({
|
|
1082
|
+
baseUrl: httpsUrlSchema.optional(),
|
|
1083
|
+
headers: headersSchema
|
|
1084
|
+
});
|
|
1085
|
+
const openAiSettingSchema = z.object({
|
|
1086
|
+
baseUrl: httpsUrlSchema.optional(),
|
|
1087
|
+
organization: z.string().optional(),
|
|
1088
|
+
project: z.string().optional(),
|
|
1089
|
+
name: z.string().optional(),
|
|
1090
|
+
headers: headersSchema
|
|
1091
|
+
});
|
|
1092
|
+
const ollamaSettingSchema = z.object({
|
|
1093
|
+
baseUrl: z.string().optional(),
|
|
1094
|
+
headers: headersSchema
|
|
1095
|
+
});
|
|
1096
|
+
const azureOpenAiSettingSchema = z.object({
|
|
1097
|
+
resourceName: z.string().optional(),
|
|
1098
|
+
apiVersion: z.string().optional(),
|
|
1099
|
+
baseUrl: httpsUrlSchema.optional(),
|
|
1100
|
+
headers: headersSchema,
|
|
1101
|
+
useDeploymentBasedUrls: z.boolean().optional()
|
|
1102
|
+
});
|
|
1103
|
+
const amazonBedrockSettingSchema = z.object({ region: z.string().optional() });
|
|
1104
|
+
const googleVertexSettingSchema = z.object({
|
|
1105
|
+
project: z.string().optional(),
|
|
1106
|
+
location: z.string().optional(),
|
|
1107
|
+
baseUrl: httpsUrlSchema.optional(),
|
|
1108
|
+
headers: headersSchema
|
|
1109
|
+
});
|
|
1110
|
+
const deepseekSettingSchema = z.object({
|
|
1111
|
+
baseUrl: httpsUrlSchema.optional(),
|
|
1112
|
+
headers: headersSchema
|
|
1113
|
+
});
|
|
1114
|
+
const providerTableSchema = z.discriminatedUnion("providerName", [
|
|
1115
|
+
z.object({
|
|
1116
|
+
providerName: z.literal("anthropic"),
|
|
1117
|
+
setting: anthropicSettingSchema.optional()
|
|
1118
|
+
}),
|
|
1119
|
+
z.object({
|
|
1120
|
+
providerName: z.literal("google"),
|
|
1121
|
+
setting: googleSettingSchema.optional()
|
|
1122
|
+
}),
|
|
1123
|
+
z.object({
|
|
1124
|
+
providerName: z.literal("openai"),
|
|
1125
|
+
setting: openAiSettingSchema.optional()
|
|
1126
|
+
}),
|
|
1127
|
+
z.object({
|
|
1128
|
+
providerName: z.literal("ollama"),
|
|
1129
|
+
setting: ollamaSettingSchema.optional()
|
|
1130
|
+
}),
|
|
1131
|
+
z.object({
|
|
1132
|
+
providerName: z.literal("azure-openai"),
|
|
1133
|
+
setting: azureOpenAiSettingSchema.optional()
|
|
1134
|
+
}),
|
|
1135
|
+
z.object({
|
|
1136
|
+
providerName: z.literal("amazon-bedrock"),
|
|
1137
|
+
setting: amazonBedrockSettingSchema.optional()
|
|
1138
|
+
}),
|
|
1139
|
+
z.object({
|
|
1140
|
+
providerName: z.literal("google-vertex"),
|
|
1141
|
+
setting: googleVertexSettingSchema.optional()
|
|
1142
|
+
}),
|
|
1143
|
+
z.object({
|
|
1144
|
+
providerName: z.literal("deepseek"),
|
|
1145
|
+
setting: deepseekSettingSchema.optional()
|
|
1146
|
+
})
|
|
1101
1147
|
]);
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
tags: z.array(z.string()).optional(),
|
|
1156
|
-
providerTools: z.array(z.string()).optional(),
|
|
1157
|
-
providerSkills: z.array(anthropicProviderSkillSchema).optional(),
|
|
1158
|
-
providerToolOptions: providerToolOptionsSchema
|
|
1159
|
-
})
|
|
1160
|
-
).optional(),
|
|
1161
|
-
perstackApiBaseUrl: z.url().refine((url) => url.startsWith("https://"), { message: "perstackApiBaseUrl must use HTTPS" }).optional(),
|
|
1162
|
-
perstackBaseSkillCommand: z.array(z.string()).optional(),
|
|
1163
|
-
envPath: z.array(z.string()).optional()
|
|
1164
|
-
});
|
|
1165
|
-
var commandOptionsSchema = z.object({
|
|
1166
|
-
config: z.string().optional(),
|
|
1167
|
-
provider: providerNameSchema.optional(),
|
|
1168
|
-
model: z.string().optional(),
|
|
1169
|
-
reasoningBudget: z.string().optional().transform((value) => {
|
|
1170
|
-
if (value === void 0) return void 0;
|
|
1171
|
-
if (["none", "minimal", "low", "medium", "high"].includes(value)) {
|
|
1172
|
-
return value;
|
|
1173
|
-
}
|
|
1174
|
-
const parsedValue = Number.parseInt(value, 10);
|
|
1175
|
-
if (Number.isNaN(parsedValue)) return void 0;
|
|
1176
|
-
return parsedValue;
|
|
1177
|
-
}).pipe(reasoningBudgetSchema.optional()),
|
|
1178
|
-
maxSteps: z.string().optional().transform((value) => {
|
|
1179
|
-
if (value === void 0) return void 0;
|
|
1180
|
-
const parsedValue = Number.parseInt(value, 10);
|
|
1181
|
-
if (Number.isNaN(parsedValue)) return void 0;
|
|
1182
|
-
return parsedValue;
|
|
1183
|
-
}),
|
|
1184
|
-
maxRetries: z.string().optional().transform((value) => {
|
|
1185
|
-
if (value === void 0) return void 0;
|
|
1186
|
-
const parsedValue = Number.parseInt(value, 10);
|
|
1187
|
-
if (Number.isNaN(parsedValue)) return void 0;
|
|
1188
|
-
return parsedValue;
|
|
1189
|
-
}),
|
|
1190
|
-
timeout: z.string().optional().transform((value) => {
|
|
1191
|
-
if (value === void 0) return void 0;
|
|
1192
|
-
const parsedValue = Number.parseInt(value, 10);
|
|
1193
|
-
if (Number.isNaN(parsedValue)) return void 0;
|
|
1194
|
-
return parsedValue;
|
|
1195
|
-
}),
|
|
1196
|
-
jobId: z.string().optional(),
|
|
1197
|
-
runId: z.string().optional(),
|
|
1198
|
-
envPath: z.array(z.string()).optional().transform((value) => value && value.length > 0 ? value : void 0),
|
|
1199
|
-
verbose: z.boolean().optional(),
|
|
1200
|
-
continue: z.boolean().optional(),
|
|
1201
|
-
continueJob: z.string().optional(),
|
|
1202
|
-
resumeFrom: z.string().optional(),
|
|
1203
|
-
interactiveToolCallResult: z.boolean().optional(),
|
|
1204
|
-
filter: z.string().optional().transform((value) => {
|
|
1205
|
-
if (value === void 0) return void 0;
|
|
1206
|
-
return value.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
1207
|
-
}).pipe(z.array(z.string()).optional())
|
|
1208
|
-
});
|
|
1209
|
-
var runCommandInputSchema = z.object({
|
|
1210
|
-
expertKey: z.string(),
|
|
1211
|
-
query: z.string(),
|
|
1212
|
-
options: commandOptionsSchema
|
|
1213
|
-
});
|
|
1214
|
-
var startCommandInputSchema = z.object({
|
|
1215
|
-
expertKey: z.string().optional(),
|
|
1216
|
-
query: z.string().optional(),
|
|
1217
|
-
options: commandOptionsSchema
|
|
1148
|
+
const perstackConfigSchema = z.object({
|
|
1149
|
+
provider: providerTableSchema.optional(),
|
|
1150
|
+
model: z.string().optional(),
|
|
1151
|
+
reasoningBudget: reasoningBudgetSchema.optional(),
|
|
1152
|
+
maxSteps: z.number().optional(),
|
|
1153
|
+
maxRetries: z.number().optional(),
|
|
1154
|
+
timeout: z.number().optional(),
|
|
1155
|
+
experts: z.record(z.string(), z.object({
|
|
1156
|
+
version: z.string().optional(),
|
|
1157
|
+
minRuntimeVersion: runtimeVersionSchema.optional(),
|
|
1158
|
+
description: z.string().optional(),
|
|
1159
|
+
instruction: z.string(),
|
|
1160
|
+
skills: z.record(z.string(), z.discriminatedUnion("type", [
|
|
1161
|
+
z.object({
|
|
1162
|
+
type: z.literal("mcpStdioSkill"),
|
|
1163
|
+
description: z.string().optional(),
|
|
1164
|
+
rule: z.string().optional(),
|
|
1165
|
+
pick: z.array(z.string()).optional(),
|
|
1166
|
+
omit: z.array(z.string()).optional(),
|
|
1167
|
+
command: z.string(),
|
|
1168
|
+
packageName: z.string().optional(),
|
|
1169
|
+
args: z.array(z.string()).optional(),
|
|
1170
|
+
requiredEnv: z.array(z.string()).optional(),
|
|
1171
|
+
allowedDomains: z.array(domainPatternSchema).optional()
|
|
1172
|
+
}),
|
|
1173
|
+
z.object({
|
|
1174
|
+
type: z.literal("mcpSseSkill"),
|
|
1175
|
+
description: z.string().optional(),
|
|
1176
|
+
rule: z.string().optional(),
|
|
1177
|
+
pick: z.array(z.string()).optional(),
|
|
1178
|
+
omit: z.array(z.string()).optional(),
|
|
1179
|
+
endpoint: sseEndpointSchema,
|
|
1180
|
+
allowedDomains: z.array(domainPatternSchema).optional()
|
|
1181
|
+
}),
|
|
1182
|
+
z.object({
|
|
1183
|
+
type: z.literal("interactiveSkill"),
|
|
1184
|
+
description: z.string().optional(),
|
|
1185
|
+
rule: z.string().optional(),
|
|
1186
|
+
tools: z.record(z.string(), z.object({
|
|
1187
|
+
description: z.string().optional(),
|
|
1188
|
+
inputJsonSchema: z.string()
|
|
1189
|
+
}))
|
|
1190
|
+
})
|
|
1191
|
+
])).optional(),
|
|
1192
|
+
delegates: z.array(z.string()).optional(),
|
|
1193
|
+
tags: z.array(z.string()).optional(),
|
|
1194
|
+
providerTools: z.array(z.string()).optional(),
|
|
1195
|
+
providerSkills: z.array(anthropicProviderSkillSchema).optional(),
|
|
1196
|
+
providerToolOptions: providerToolOptionsSchema
|
|
1197
|
+
})).optional(),
|
|
1198
|
+
perstackApiBaseUrl: z.url().refine((url) => url.startsWith("https://"), { message: "perstackApiBaseUrl must use HTTPS" }).optional(),
|
|
1199
|
+
perstackBaseSkillCommand: z.array(z.string()).optional(),
|
|
1200
|
+
envPath: z.array(z.string()).optional()
|
|
1218
1201
|
});
|
|
1202
|
+
|
|
1203
|
+
//#endregion
|
|
1204
|
+
//#region src/schemas/run-command.ts
|
|
1205
|
+
const commandOptionsSchema = z.object({
|
|
1206
|
+
config: z.string().optional(),
|
|
1207
|
+
provider: providerNameSchema.optional(),
|
|
1208
|
+
model: z.string().optional(),
|
|
1209
|
+
reasoningBudget: z.string().optional().transform((value) => {
|
|
1210
|
+
if (value === void 0) return void 0;
|
|
1211
|
+
if ([
|
|
1212
|
+
"none",
|
|
1213
|
+
"minimal",
|
|
1214
|
+
"low",
|
|
1215
|
+
"medium",
|
|
1216
|
+
"high"
|
|
1217
|
+
].includes(value)) return value;
|
|
1218
|
+
const parsedValue = Number.parseInt(value, 10);
|
|
1219
|
+
if (Number.isNaN(parsedValue)) return void 0;
|
|
1220
|
+
return parsedValue;
|
|
1221
|
+
}).pipe(reasoningBudgetSchema.optional()),
|
|
1222
|
+
maxSteps: z.string().optional().transform((value) => {
|
|
1223
|
+
if (value === void 0) return void 0;
|
|
1224
|
+
const parsedValue = Number.parseInt(value, 10);
|
|
1225
|
+
if (Number.isNaN(parsedValue)) return void 0;
|
|
1226
|
+
return parsedValue;
|
|
1227
|
+
}),
|
|
1228
|
+
maxRetries: z.string().optional().transform((value) => {
|
|
1229
|
+
if (value === void 0) return void 0;
|
|
1230
|
+
const parsedValue = Number.parseInt(value, 10);
|
|
1231
|
+
if (Number.isNaN(parsedValue)) return void 0;
|
|
1232
|
+
return parsedValue;
|
|
1233
|
+
}),
|
|
1234
|
+
timeout: z.string().optional().transform((value) => {
|
|
1235
|
+
if (value === void 0) return void 0;
|
|
1236
|
+
const parsedValue = Number.parseInt(value, 10);
|
|
1237
|
+
if (Number.isNaN(parsedValue)) return void 0;
|
|
1238
|
+
return parsedValue;
|
|
1239
|
+
}),
|
|
1240
|
+
jobId: z.string().optional(),
|
|
1241
|
+
runId: z.string().optional(),
|
|
1242
|
+
envPath: z.array(z.string()).optional().transform((value) => value && value.length > 0 ? value : void 0),
|
|
1243
|
+
verbose: z.boolean().optional(),
|
|
1244
|
+
continue: z.boolean().optional(),
|
|
1245
|
+
continueJob: z.string().optional(),
|
|
1246
|
+
resumeFrom: z.string().optional(),
|
|
1247
|
+
interactiveToolCallResult: z.boolean().optional(),
|
|
1248
|
+
filter: z.string().optional().transform((value) => {
|
|
1249
|
+
if (value === void 0) return void 0;
|
|
1250
|
+
return value.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
1251
|
+
}).pipe(z.array(z.string()).optional())
|
|
1252
|
+
});
|
|
1253
|
+
const runCommandInputSchema = z.object({
|
|
1254
|
+
expertKey: z.string(),
|
|
1255
|
+
query: z.string(),
|
|
1256
|
+
options: commandOptionsSchema
|
|
1257
|
+
});
|
|
1258
|
+
const startCommandInputSchema = z.object({
|
|
1259
|
+
expertKey: z.string().optional(),
|
|
1260
|
+
query: z.string().optional(),
|
|
1261
|
+
options: commandOptionsSchema
|
|
1262
|
+
});
|
|
1263
|
+
|
|
1264
|
+
//#endregion
|
|
1265
|
+
//#region src/schemas/runtime.ts
|
|
1266
|
+
/** Parse an expert key into its components */
|
|
1219
1267
|
function parseExpertKey(expertKey) {
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1268
|
+
const match = expertKey.match(expertKeyRegex);
|
|
1269
|
+
if (!match) throw new PerstackError(`Invalid expert key format: ${expertKey}`);
|
|
1270
|
+
const [key, name, version, tag] = match;
|
|
1271
|
+
if (!name) throw new PerstackError(`Invalid expert key format: ${expertKey}`);
|
|
1272
|
+
return {
|
|
1273
|
+
key,
|
|
1274
|
+
name,
|
|
1275
|
+
version,
|
|
1276
|
+
tag
|
|
1277
|
+
};
|
|
1229
1278
|
}
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
});
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
env: z.record(z.string(), z.string()).optional().default({}),
|
|
1296
|
-
proxyUrl: z.string().optional(),
|
|
1297
|
-
verbose: z.boolean().optional()
|
|
1298
|
-
}),
|
|
1299
|
-
checkpoint: checkpointSchema.optional()
|
|
1300
|
-
});
|
|
1279
|
+
const runSettingSchema = z.object({
|
|
1280
|
+
model: z.string(),
|
|
1281
|
+
providerConfig: providerConfigSchema,
|
|
1282
|
+
jobId: z.string(),
|
|
1283
|
+
runId: z.string(),
|
|
1284
|
+
expertKey: z.string().min(1).regex(expertKeyRegex),
|
|
1285
|
+
input: z.object({
|
|
1286
|
+
text: z.string().optional(),
|
|
1287
|
+
interactiveToolCallResult: z.object({
|
|
1288
|
+
toolCallId: z.string(),
|
|
1289
|
+
toolName: z.string(),
|
|
1290
|
+
skillName: z.string(),
|
|
1291
|
+
text: z.string()
|
|
1292
|
+
}).optional()
|
|
1293
|
+
}),
|
|
1294
|
+
experts: z.record(z.string(), expertSchema),
|
|
1295
|
+
reasoningBudget: reasoningBudgetSchema.default(defaultReasoningBudget),
|
|
1296
|
+
maxSteps: z.number().min(1).optional().default(defaultMaxSteps),
|
|
1297
|
+
maxRetries: z.number().min(0),
|
|
1298
|
+
timeout: z.number().min(0),
|
|
1299
|
+
startedAt: z.number(),
|
|
1300
|
+
updatedAt: z.number(),
|
|
1301
|
+
perstackApiBaseUrl: z.string().url(),
|
|
1302
|
+
perstackApiKey: z.string().optional(),
|
|
1303
|
+
perstackBaseSkillCommand: z.array(z.string()).optional(),
|
|
1304
|
+
env: z.record(z.string(), z.string()),
|
|
1305
|
+
proxyUrl: z.string().optional(),
|
|
1306
|
+
verbose: z.boolean().optional()
|
|
1307
|
+
});
|
|
1308
|
+
const runParamsSchema = z.object({
|
|
1309
|
+
setting: z.object({
|
|
1310
|
+
model: z.string(),
|
|
1311
|
+
providerConfig: providerConfigSchema,
|
|
1312
|
+
jobId: z.string().optional().default(() => createId()),
|
|
1313
|
+
runId: z.string().optional().default(() => createId()),
|
|
1314
|
+
expertKey: z.string().min(1).regex(expertKeyRegex),
|
|
1315
|
+
input: z.object({
|
|
1316
|
+
text: z.string().optional(),
|
|
1317
|
+
interactiveToolCallResult: z.object({
|
|
1318
|
+
toolCallId: z.string(),
|
|
1319
|
+
toolName: z.string(),
|
|
1320
|
+
skillName: z.string(),
|
|
1321
|
+
text: z.string()
|
|
1322
|
+
}).optional()
|
|
1323
|
+
}),
|
|
1324
|
+
experts: z.record(z.string().min(1).regex(expertKeyRegex), expertSchema.omit({ key: true })).optional().default({}).transform((experts) => Object.fromEntries(Object.entries(experts).map(([key, expertWithoutKey]) => [key, expertSchema.parse({
|
|
1325
|
+
...expertWithoutKey,
|
|
1326
|
+
key
|
|
1327
|
+
})]))),
|
|
1328
|
+
reasoningBudget: reasoningBudgetSchema.optional().default(defaultReasoningBudget),
|
|
1329
|
+
maxSteps: z.number().min(1).optional().default(defaultMaxSteps),
|
|
1330
|
+
maxRetries: z.number().min(0).optional().default(defaultMaxRetries),
|
|
1331
|
+
timeout: z.number().min(0).optional().default(defaultTimeout),
|
|
1332
|
+
startedAt: z.number().optional().default(Date.now()),
|
|
1333
|
+
updatedAt: z.number().optional().default(Date.now()),
|
|
1334
|
+
perstackApiBaseUrl: z.url().optional().default(defaultPerstackApiBaseUrl),
|
|
1335
|
+
perstackApiKey: z.string().optional(),
|
|
1336
|
+
perstackBaseSkillCommand: z.array(z.string()).optional(),
|
|
1337
|
+
env: z.record(z.string(), z.string()).optional().default({}),
|
|
1338
|
+
proxyUrl: z.string().optional(),
|
|
1339
|
+
verbose: z.boolean().optional()
|
|
1340
|
+
}),
|
|
1341
|
+
checkpoint: checkpointSchema.optional()
|
|
1342
|
+
});
|
|
1343
|
+
/** Factory function to create expert state events */
|
|
1301
1344
|
function createEvent(type) {
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1345
|
+
return (setting, checkpoint, data) => {
|
|
1346
|
+
return {
|
|
1347
|
+
type,
|
|
1348
|
+
id: createId(),
|
|
1349
|
+
expertKey: checkpoint.expert.key,
|
|
1350
|
+
timestamp: Date.now(),
|
|
1351
|
+
jobId: setting.jobId,
|
|
1352
|
+
runId: setting.runId,
|
|
1353
|
+
stepNumber: checkpoint.stepNumber,
|
|
1354
|
+
...data
|
|
1355
|
+
};
|
|
1356
|
+
};
|
|
1314
1357
|
}
|
|
1358
|
+
/** Factory function to create streaming events */
|
|
1315
1359
|
function createStreamingEvent(type, setting, checkpoint, data) {
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1360
|
+
return {
|
|
1361
|
+
type,
|
|
1362
|
+
id: createId(),
|
|
1363
|
+
expertKey: checkpoint.expert.key,
|
|
1364
|
+
timestamp: Date.now(),
|
|
1365
|
+
jobId: setting.jobId,
|
|
1366
|
+
runId: setting.runId,
|
|
1367
|
+
stepNumber: checkpoint.stepNumber,
|
|
1368
|
+
...data
|
|
1369
|
+
};
|
|
1326
1370
|
}
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1371
|
+
const startRun = createEvent("startRun");
|
|
1372
|
+
const resumeFromStop = createEvent("resumeFromStop");
|
|
1373
|
+
const proceedToInteractiveTools = createEvent("proceedToInteractiveTools");
|
|
1374
|
+
const startGeneration = createEvent("startGeneration");
|
|
1375
|
+
const retry = createEvent("retry");
|
|
1376
|
+
const callTools = createEvent("callTools");
|
|
1377
|
+
const finishMcpTools = createEvent("finishMcpTools");
|
|
1378
|
+
const skipDelegates = createEvent("skipDelegates");
|
|
1379
|
+
const resolveToolResults = createEvent("resolveToolResults");
|
|
1380
|
+
const attemptCompletion = createEvent("attemptCompletion");
|
|
1381
|
+
const finishToolCall = createEvent("finishToolCall");
|
|
1382
|
+
const resumeToolCalls = createEvent("resumeToolCalls");
|
|
1383
|
+
const completeRun = createEvent("completeRun");
|
|
1384
|
+
const stopRunByInteractiveTool = createEvent("stopRunByInteractiveTool");
|
|
1385
|
+
const stopRunByDelegate = createEvent("stopRunByDelegate");
|
|
1386
|
+
const stopRunByExceededMaxSteps = createEvent("stopRunByExceededMaxSteps");
|
|
1387
|
+
const stopRunByError = createEvent("stopRunByError");
|
|
1388
|
+
const continueToNextStep = createEvent("continueToNextStep");
|
|
1389
|
+
/** Factory function to create runtime events */
|
|
1345
1390
|
function createRuntimeEvent(type, jobId, runId, data) {
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1391
|
+
return {
|
|
1392
|
+
type,
|
|
1393
|
+
id: createId(),
|
|
1394
|
+
timestamp: Date.now(),
|
|
1395
|
+
jobId,
|
|
1396
|
+
runId,
|
|
1397
|
+
...data
|
|
1398
|
+
};
|
|
1354
1399
|
}
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1400
|
+
/**
|
|
1401
|
+
* Valid expert state event types (state machine transitions)
|
|
1402
|
+
*/
|
|
1403
|
+
const EXPERT_STATE_EVENT_TYPES = new Set([
|
|
1404
|
+
"startRun",
|
|
1405
|
+
"resumeFromStop",
|
|
1406
|
+
"proceedToInteractiveTools",
|
|
1407
|
+
"startGeneration",
|
|
1408
|
+
"retry",
|
|
1409
|
+
"callTools",
|
|
1410
|
+
"finishMcpTools",
|
|
1411
|
+
"skipDelegates",
|
|
1412
|
+
"resolveToolResults",
|
|
1413
|
+
"attemptCompletion",
|
|
1414
|
+
"finishToolCall",
|
|
1415
|
+
"resumeToolCalls",
|
|
1416
|
+
"continueToNextStep",
|
|
1417
|
+
"stopRunByInteractiveTool",
|
|
1418
|
+
"stopRunByDelegate",
|
|
1419
|
+
"stopRunByExceededMaxSteps",
|
|
1420
|
+
"stopRunByError",
|
|
1421
|
+
"completeRun"
|
|
1374
1422
|
]);
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1423
|
+
/**
|
|
1424
|
+
* Valid streaming event types
|
|
1425
|
+
*/
|
|
1426
|
+
const STREAMING_EVENT_TYPES = new Set([
|
|
1427
|
+
"startStreamingReasoning",
|
|
1428
|
+
"streamReasoning",
|
|
1429
|
+
"completeStreamingReasoning",
|
|
1430
|
+
"startStreamingRunResult",
|
|
1431
|
+
"streamRunResult",
|
|
1432
|
+
"completeStreamingRunResult"
|
|
1382
1433
|
]);
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1434
|
+
/**
|
|
1435
|
+
* Valid runtime event types (infrastructure-level events)
|
|
1436
|
+
*/
|
|
1437
|
+
const RUNTIME_EVENT_TYPES = new Set([
|
|
1438
|
+
"initializeRuntime",
|
|
1439
|
+
"skillStarting",
|
|
1440
|
+
"skillConnected",
|
|
1441
|
+
"skillStderr",
|
|
1442
|
+
"skillDisconnected"
|
|
1389
1443
|
]);
|
|
1444
|
+
/** Validate if a string is a valid RunEvent type (ExpertStateEvent or StreamingEvent) */
|
|
1390
1445
|
function isValidEventType(type) {
|
|
1391
|
-
|
|
1446
|
+
return EXPERT_STATE_EVENT_TYPES.has(type) || STREAMING_EVENT_TYPES.has(type);
|
|
1392
1447
|
}
|
|
1448
|
+
/** Validate if a string is a valid RuntimeEvent type */
|
|
1393
1449
|
function isValidRuntimeEventType(type) {
|
|
1394
|
-
|
|
1450
|
+
return RUNTIME_EVENT_TYPES.has(type);
|
|
1395
1451
|
}
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1452
|
+
|
|
1453
|
+
//#endregion
|
|
1454
|
+
//#region src/schemas/step.ts
|
|
1455
|
+
const stepSchema = z.object({
|
|
1456
|
+
stepNumber: z.number(),
|
|
1457
|
+
inputMessages: z.array(z.union([
|
|
1458
|
+
instructionMessageSchema,
|
|
1459
|
+
userMessageSchema,
|
|
1460
|
+
toolMessageSchema
|
|
1461
|
+
])).optional(),
|
|
1462
|
+
newMessages: z.array(messageSchema),
|
|
1463
|
+
toolCalls: z.array(toolCallSchema).optional(),
|
|
1464
|
+
toolResults: z.array(toolResultSchema).optional(),
|
|
1465
|
+
pendingToolCalls: z.array(toolCallSchema).optional(),
|
|
1466
|
+
partialToolResults: z.array(toolResultSchema).optional(),
|
|
1467
|
+
usage: usageSchema,
|
|
1468
|
+
startedAt: z.number(),
|
|
1469
|
+
finishedAt: z.number().optional()
|
|
1407
1470
|
});
|
|
1408
1471
|
|
|
1409
|
-
|
|
1410
|
-
|
|
1472
|
+
//#endregion
|
|
1473
|
+
//#region src/utils/activity.ts
|
|
1474
|
+
const BASE_SKILL_PREFIX = "@perstack/base";
|
|
1475
|
+
/**
|
|
1476
|
+
* Extracts reasoning from Step.newMessages by finding thinkingParts.
|
|
1477
|
+
*/
|
|
1411
1478
|
function extractReasoning(newMessages) {
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
thinkingParts.push(content);
|
|
1417
|
-
}
|
|
1418
|
-
}
|
|
1419
|
-
}
|
|
1420
|
-
if (thinkingParts.length === 0) return void 0;
|
|
1421
|
-
return thinkingParts.map((p) => p.thinking).join("\n\n");
|
|
1479
|
+
const thinkingParts = [];
|
|
1480
|
+
for (const message of newMessages) for (const content of message.contents) if (content.type === "thinkingPart") thinkingParts.push(content);
|
|
1481
|
+
if (thinkingParts.length === 0) return void 0;
|
|
1482
|
+
return thinkingParts.map((p) => p.thinking).join("\n\n");
|
|
1422
1483
|
}
|
|
1484
|
+
/**
|
|
1485
|
+
* Wraps multiple activities into a ParallelActivitiesGroup when they share reasoning.
|
|
1486
|
+
* Single activities are returned as-is.
|
|
1487
|
+
*/
|
|
1423
1488
|
function wrapInGroupIfParallel(activities, reasoning, expertKey, runId, stepNumber) {
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
activities: activitiesWithoutReasoning
|
|
1438
|
-
};
|
|
1439
|
-
return [group];
|
|
1489
|
+
if (activities.length <= 1) return activities;
|
|
1490
|
+
const activitiesWithoutReasoning = activities.map((a) => {
|
|
1491
|
+
const { reasoning: _, ...rest } = a;
|
|
1492
|
+
return rest;
|
|
1493
|
+
});
|
|
1494
|
+
return [{
|
|
1495
|
+
type: "parallelGroup",
|
|
1496
|
+
id: `parallel-${runId}-step${stepNumber}`,
|
|
1497
|
+
expertKey,
|
|
1498
|
+
runId,
|
|
1499
|
+
reasoning,
|
|
1500
|
+
activities: activitiesWithoutReasoning
|
|
1501
|
+
}];
|
|
1440
1502
|
}
|
|
1503
|
+
/**
|
|
1504
|
+
* Computes activities from a checkpoint and step.
|
|
1505
|
+
* Returns an array of activities or activity groups, supporting parallel tool calls and delegations.
|
|
1506
|
+
* When multiple activities are produced from a single step, they are wrapped in a ParallelActivitiesGroup
|
|
1507
|
+
* with shared reasoning.
|
|
1508
|
+
*/
|
|
1441
1509
|
function getActivities(params) {
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
const toolResults = step.toolResults ?? [];
|
|
1495
|
-
if (toolCalls.length === 0) {
|
|
1496
|
-
if (status === "completed") {
|
|
1497
|
-
return prependQuery([createCompleteActivity(step.newMessages, reasoning)]);
|
|
1498
|
-
}
|
|
1499
|
-
if (status === "proceeding" || status === "init") {
|
|
1500
|
-
return prependQuery([]);
|
|
1501
|
-
}
|
|
1502
|
-
return prependQuery([createRetryActivity(step.newMessages, reasoning)]);
|
|
1503
|
-
}
|
|
1504
|
-
const toolActivities = [];
|
|
1505
|
-
for (const toolCall of toolCalls) {
|
|
1506
|
-
const toolResult = toolResults.find((tr) => tr.id === toolCall.id);
|
|
1507
|
-
if (!toolResult) {
|
|
1508
|
-
continue;
|
|
1509
|
-
}
|
|
1510
|
-
const { skillName, toolName } = toolCall;
|
|
1511
|
-
if (skillName.startsWith(BASE_SKILL_PREFIX)) {
|
|
1512
|
-
toolActivities.push(createBaseToolActivity(toolName, toolCall, toolResult, reasoning));
|
|
1513
|
-
} else {
|
|
1514
|
-
toolActivities.push(
|
|
1515
|
-
createGeneralToolActivity(skillName, toolName, toolCall, toolResult, reasoning)
|
|
1516
|
-
);
|
|
1517
|
-
}
|
|
1518
|
-
}
|
|
1519
|
-
if (toolActivities.length === 0) {
|
|
1520
|
-
if (status === "completed") {
|
|
1521
|
-
return prependQuery([createCompleteActivity(step.newMessages, reasoning)]);
|
|
1522
|
-
}
|
|
1523
|
-
if (status === "proceeding" || status === "init") {
|
|
1524
|
-
return prependQuery([]);
|
|
1525
|
-
}
|
|
1526
|
-
return prependQuery([createRetryActivity(step.newMessages, reasoning)]);
|
|
1527
|
-
}
|
|
1528
|
-
const result = wrapInGroupIfParallel(toolActivities, reasoning, expertKey, runId, stepNumber);
|
|
1529
|
-
if (status === "completed") {
|
|
1530
|
-
result.push(createCompleteActivity(step.newMessages, void 0));
|
|
1531
|
-
}
|
|
1532
|
-
return prependQuery(result);
|
|
1510
|
+
const { checkpoint, step } = params;
|
|
1511
|
+
const { status, delegateTo, runId, stepNumber } = checkpoint;
|
|
1512
|
+
const expertKey = checkpoint.expert.key;
|
|
1513
|
+
const reasoning = extractReasoning(step.newMessages);
|
|
1514
|
+
let queryActivity;
|
|
1515
|
+
if (stepNumber === 1 && step.inputMessages) {
|
|
1516
|
+
const userMessage = step.inputMessages.find((m) => m.type === "userMessage");
|
|
1517
|
+
if (userMessage) {
|
|
1518
|
+
const textPart = userMessage.contents.find((c) => c.type === "textPart");
|
|
1519
|
+
if (textPart && "text" in textPart) queryActivity = {
|
|
1520
|
+
type: "query",
|
|
1521
|
+
id: "",
|
|
1522
|
+
expertKey,
|
|
1523
|
+
runId,
|
|
1524
|
+
text: textPart.text
|
|
1525
|
+
};
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
const prependQuery = (result) => queryActivity ? [queryActivity, ...result] : result;
|
|
1529
|
+
if (status === "stoppedByError") return prependQuery([createErrorActivity(checkpoint, reasoning)]);
|
|
1530
|
+
if (status === "stoppedByDelegate") {
|
|
1531
|
+
if (!delegateTo || delegateTo.length === 0) return prependQuery([createRetryActivity(step.newMessages, reasoning, "Delegate status but no delegation targets")]);
|
|
1532
|
+
return prependQuery(wrapInGroupIfParallel(delegateTo.map((d) => createDelegateActivity(d, reasoning)), reasoning, expertKey, runId, stepNumber));
|
|
1533
|
+
}
|
|
1534
|
+
if (status === "stoppedByInteractiveTool") {
|
|
1535
|
+
const toolCalls = step.toolCalls ?? [];
|
|
1536
|
+
if (toolCalls.length === 0) return prependQuery([createRetryActivity(step.newMessages, reasoning)]);
|
|
1537
|
+
return prependQuery(wrapInGroupIfParallel(toolCalls.map((tc) => createInteractiveToolActivity(tc.skillName, tc.toolName, tc, reasoning)), reasoning, expertKey, runId, stepNumber));
|
|
1538
|
+
}
|
|
1539
|
+
const toolCalls = step.toolCalls ?? [];
|
|
1540
|
+
const toolResults = step.toolResults ?? [];
|
|
1541
|
+
if (toolCalls.length === 0) {
|
|
1542
|
+
if (status === "completed") return prependQuery([createCompleteActivity(step.newMessages, reasoning)]);
|
|
1543
|
+
if (status === "proceeding" || status === "init") return prependQuery([]);
|
|
1544
|
+
return prependQuery([createRetryActivity(step.newMessages, reasoning)]);
|
|
1545
|
+
}
|
|
1546
|
+
const toolActivities = [];
|
|
1547
|
+
for (const toolCall of toolCalls) {
|
|
1548
|
+
const toolResult = toolResults.find((tr) => tr.id === toolCall.id);
|
|
1549
|
+
if (!toolResult) continue;
|
|
1550
|
+
const { skillName, toolName } = toolCall;
|
|
1551
|
+
if (skillName.startsWith(BASE_SKILL_PREFIX)) toolActivities.push(createBaseToolActivity(toolName, toolCall, toolResult, reasoning));
|
|
1552
|
+
else toolActivities.push(createGeneralToolActivity(skillName, toolName, toolCall, toolResult, reasoning));
|
|
1553
|
+
}
|
|
1554
|
+
if (toolActivities.length === 0) {
|
|
1555
|
+
if (status === "completed") return prependQuery([createCompleteActivity(step.newMessages, reasoning)]);
|
|
1556
|
+
if (status === "proceeding" || status === "init") return prependQuery([]);
|
|
1557
|
+
return prependQuery([createRetryActivity(step.newMessages, reasoning)]);
|
|
1558
|
+
}
|
|
1559
|
+
const result = wrapInGroupIfParallel(toolActivities, reasoning, expertKey, runId, stepNumber);
|
|
1560
|
+
if (status === "completed") result.push(createCompleteActivity(step.newMessages, void 0));
|
|
1561
|
+
return prependQuery(result);
|
|
1533
1562
|
}
|
|
1534
1563
|
function createCompleteActivity(newMessages, reasoning) {
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
text: textPart?.text ?? ""
|
|
1544
|
-
};
|
|
1564
|
+
return {
|
|
1565
|
+
type: "complete",
|
|
1566
|
+
id: "",
|
|
1567
|
+
expertKey: "",
|
|
1568
|
+
runId: "",
|
|
1569
|
+
reasoning,
|
|
1570
|
+
text: ([...newMessages].reverse().find((m) => m.type === "expertMessage")?.contents.find((c) => c.type === "textPart"))?.text ?? ""
|
|
1571
|
+
};
|
|
1545
1572
|
}
|
|
1546
1573
|
function createDelegateActivity(delegate, reasoning) {
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1574
|
+
return {
|
|
1575
|
+
type: "delegate",
|
|
1576
|
+
id: "",
|
|
1577
|
+
expertKey: "",
|
|
1578
|
+
runId: "",
|
|
1579
|
+
reasoning,
|
|
1580
|
+
delegateExpertKey: delegate.expert.key,
|
|
1581
|
+
query: delegate.query
|
|
1582
|
+
};
|
|
1556
1583
|
}
|
|
1557
1584
|
function createInteractiveToolActivity(skillName, toolName, toolCall, reasoning) {
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1585
|
+
return {
|
|
1586
|
+
type: "interactiveTool",
|
|
1587
|
+
id: "",
|
|
1588
|
+
expertKey: "",
|
|
1589
|
+
runId: "",
|
|
1590
|
+
reasoning,
|
|
1591
|
+
skillName,
|
|
1592
|
+
toolName,
|
|
1593
|
+
args: toolCall.args
|
|
1594
|
+
};
|
|
1568
1595
|
}
|
|
1569
1596
|
function createRetryActivity(newMessages, reasoning, customError) {
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
};
|
|
1597
|
+
const textPart = newMessages[newMessages.length - 1]?.contents.find((c) => c.type === "textPart");
|
|
1598
|
+
return {
|
|
1599
|
+
type: "retry",
|
|
1600
|
+
id: "",
|
|
1601
|
+
expertKey: "",
|
|
1602
|
+
runId: "",
|
|
1603
|
+
reasoning,
|
|
1604
|
+
error: customError ?? "No tool call or result found",
|
|
1605
|
+
message: textPart?.text ?? ""
|
|
1606
|
+
};
|
|
1581
1607
|
}
|
|
1582
1608
|
function createErrorActivity(checkpoint, reasoning) {
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1609
|
+
const error = checkpoint.error;
|
|
1610
|
+
return {
|
|
1611
|
+
type: "error",
|
|
1612
|
+
id: "",
|
|
1613
|
+
expertKey: "",
|
|
1614
|
+
runId: "",
|
|
1615
|
+
reasoning,
|
|
1616
|
+
error: error?.message ?? "Unknown error",
|
|
1617
|
+
errorName: error?.name,
|
|
1618
|
+
isRetryable: error?.isRetryable
|
|
1619
|
+
};
|
|
1594
1620
|
}
|
|
1595
1621
|
function createBaseToolActivity(toolName, toolCall, toolResult, reasoning) {
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1622
|
+
const args = toolCall.args;
|
|
1623
|
+
const resultContents = toolResult.result;
|
|
1624
|
+
const errorText = getErrorFromResult(resultContents);
|
|
1625
|
+
const baseFields = {
|
|
1626
|
+
id: "",
|
|
1627
|
+
expertKey: "",
|
|
1628
|
+
runId: "",
|
|
1629
|
+
reasoning
|
|
1630
|
+
};
|
|
1631
|
+
switch (toolName) {
|
|
1632
|
+
case "attemptCompletion": {
|
|
1633
|
+
const remainingTodos = parseRemainingTodosFromResult(resultContents);
|
|
1634
|
+
return {
|
|
1635
|
+
type: "attemptCompletion",
|
|
1636
|
+
...baseFields,
|
|
1637
|
+
remainingTodos,
|
|
1638
|
+
error: errorText
|
|
1639
|
+
};
|
|
1640
|
+
}
|
|
1641
|
+
case "todo": {
|
|
1642
|
+
const todos = parseTodosFromResult(resultContents);
|
|
1643
|
+
return {
|
|
1644
|
+
type: "todo",
|
|
1645
|
+
...baseFields,
|
|
1646
|
+
newTodos: Array.isArray(args["newTodos"]) ? args["newTodos"].map(String) : void 0,
|
|
1647
|
+
completedTodos: Array.isArray(args["completedTodos"]) ? args["completedTodos"].map(Number) : void 0,
|
|
1648
|
+
todos,
|
|
1649
|
+
error: errorText
|
|
1650
|
+
};
|
|
1651
|
+
}
|
|
1652
|
+
case "clearTodo": return {
|
|
1653
|
+
type: "clearTodo",
|
|
1654
|
+
...baseFields,
|
|
1655
|
+
error: errorText
|
|
1656
|
+
};
|
|
1657
|
+
case "readImageFile": return {
|
|
1658
|
+
type: "readImageFile",
|
|
1659
|
+
...baseFields,
|
|
1660
|
+
path: String(args["path"] ?? ""),
|
|
1661
|
+
mimeType: parseStringField(resultContents, "mimeType"),
|
|
1662
|
+
size: parseNumberField(resultContents, "size"),
|
|
1663
|
+
error: errorText
|
|
1664
|
+
};
|
|
1665
|
+
case "readPdfFile": return {
|
|
1666
|
+
type: "readPdfFile",
|
|
1667
|
+
...baseFields,
|
|
1668
|
+
path: String(args["path"] ?? ""),
|
|
1669
|
+
mimeType: parseStringField(resultContents, "mimeType"),
|
|
1670
|
+
size: parseNumberField(resultContents, "size"),
|
|
1671
|
+
error: errorText
|
|
1672
|
+
};
|
|
1673
|
+
case "readTextFile": return {
|
|
1674
|
+
type: "readTextFile",
|
|
1675
|
+
...baseFields,
|
|
1676
|
+
path: String(args["path"] ?? ""),
|
|
1677
|
+
content: parseStringField(resultContents, "content"),
|
|
1678
|
+
from: typeof args["from"] === "number" ? args["from"] : void 0,
|
|
1679
|
+
to: typeof args["to"] === "number" ? args["to"] : void 0,
|
|
1680
|
+
error: errorText
|
|
1681
|
+
};
|
|
1682
|
+
case "editTextFile": return {
|
|
1683
|
+
type: "editTextFile",
|
|
1684
|
+
...baseFields,
|
|
1685
|
+
path: String(args["path"] ?? ""),
|
|
1686
|
+
newText: String(args["newText"] ?? ""),
|
|
1687
|
+
oldText: String(args["oldText"] ?? ""),
|
|
1688
|
+
error: errorText
|
|
1689
|
+
};
|
|
1690
|
+
case "writeTextFile": return {
|
|
1691
|
+
type: "writeTextFile",
|
|
1692
|
+
...baseFields,
|
|
1693
|
+
path: String(args["path"] ?? ""),
|
|
1694
|
+
text: String(args["text"] ?? ""),
|
|
1695
|
+
error: errorText
|
|
1696
|
+
};
|
|
1697
|
+
case "exec": return {
|
|
1698
|
+
type: "exec",
|
|
1699
|
+
...baseFields,
|
|
1700
|
+
command: String(args["command"] ?? ""),
|
|
1701
|
+
args: Array.isArray(args["args"]) ? args["args"].map(String) : [],
|
|
1702
|
+
cwd: String(args["cwd"] ?? ""),
|
|
1703
|
+
output: parseStringField(resultContents, "output"),
|
|
1704
|
+
error: errorText,
|
|
1705
|
+
stdout: parseStringField(resultContents, "stdout"),
|
|
1706
|
+
stderr: parseStringField(resultContents, "stderr")
|
|
1707
|
+
};
|
|
1708
|
+
case "addSkill": return {
|
|
1709
|
+
type: "addSkill",
|
|
1710
|
+
...baseFields,
|
|
1711
|
+
name: String(args["name"] ?? ""),
|
|
1712
|
+
skillType: String(args["type"] ?? ""),
|
|
1713
|
+
tools: parseStringArrayField(resultContents, "tools"),
|
|
1714
|
+
error: errorText
|
|
1715
|
+
};
|
|
1716
|
+
case "removeSkill": return {
|
|
1717
|
+
type: "removeSkill",
|
|
1718
|
+
...baseFields,
|
|
1719
|
+
skillName: String(args["skillName"] ?? ""),
|
|
1720
|
+
error: errorText
|
|
1721
|
+
};
|
|
1722
|
+
case "addDelegate": return {
|
|
1723
|
+
type: "addDelegate",
|
|
1724
|
+
...baseFields,
|
|
1725
|
+
targetExpertKey: String(args["expertKey"] ?? ""),
|
|
1726
|
+
delegateToolName: parseStringField(resultContents, "delegateToolName"),
|
|
1727
|
+
error: errorText
|
|
1728
|
+
};
|
|
1729
|
+
case "removeDelegate": return {
|
|
1730
|
+
type: "removeDelegate",
|
|
1731
|
+
...baseFields,
|
|
1732
|
+
expertName: String(args["expertName"] ?? ""),
|
|
1733
|
+
error: errorText
|
|
1734
|
+
};
|
|
1735
|
+
case "createExpert": return {
|
|
1736
|
+
type: "createExpert",
|
|
1737
|
+
...baseFields,
|
|
1738
|
+
targetKey: String(args["key"] ?? ""),
|
|
1739
|
+
description: typeof args["description"] === "string" ? args["description"] : void 0,
|
|
1740
|
+
resultExpertKey: parseStringField(resultContents, "expertKey"),
|
|
1741
|
+
error: errorText
|
|
1742
|
+
};
|
|
1743
|
+
default: return createGeneralToolActivity(toolCall.skillName, toolName, toolCall, toolResult, reasoning);
|
|
1744
|
+
}
|
|
1693
1745
|
}
|
|
1694
1746
|
function createGeneralToolActivity(skillName, toolName, toolCall, toolResult, reasoning) {
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1747
|
+
const errorText = getErrorFromResult(toolResult.result);
|
|
1748
|
+
return {
|
|
1749
|
+
type: "generalTool",
|
|
1750
|
+
id: "",
|
|
1751
|
+
expertKey: "",
|
|
1752
|
+
runId: "",
|
|
1753
|
+
reasoning,
|
|
1754
|
+
skillName,
|
|
1755
|
+
toolName,
|
|
1756
|
+
args: toolCall.args,
|
|
1757
|
+
result: toolResult.result,
|
|
1758
|
+
error: errorText
|
|
1759
|
+
};
|
|
1708
1760
|
}
|
|
1709
1761
|
function getErrorFromResult(result) {
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
if (trimmed.toLowerCase().startsWith("error:") || trimmed.toLowerCase().startsWith("error ")) {
|
|
1720
|
-
return textPart.text;
|
|
1721
|
-
}
|
|
1722
|
-
}
|
|
1723
|
-
return void 0;
|
|
1762
|
+
const textPart = result.find((p) => p.type === "textPart");
|
|
1763
|
+
if (!textPart?.text) return void 0;
|
|
1764
|
+
try {
|
|
1765
|
+
const parsed = JSON.parse(textPart.text);
|
|
1766
|
+
if (typeof parsed.error === "string") return parsed.error;
|
|
1767
|
+
} catch {
|
|
1768
|
+
const trimmed = textPart.text.trim();
|
|
1769
|
+
if (trimmed.toLowerCase().startsWith("error:") || trimmed.toLowerCase().startsWith("error ")) return textPart.text;
|
|
1770
|
+
}
|
|
1724
1771
|
}
|
|
1725
1772
|
function parseStringField(result, field) {
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1773
|
+
const textPart = result.find((p) => p.type === "textPart");
|
|
1774
|
+
if (!textPart?.text) return void 0;
|
|
1775
|
+
try {
|
|
1776
|
+
const parsed = JSON.parse(textPart.text);
|
|
1777
|
+
return typeof parsed[field] === "string" ? parsed[field] : void 0;
|
|
1778
|
+
} catch {
|
|
1779
|
+
return;
|
|
1780
|
+
}
|
|
1734
1781
|
}
|
|
1735
1782
|
function parseNumberField(result, field) {
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1783
|
+
const textPart = result.find((p) => p.type === "textPart");
|
|
1784
|
+
if (!textPart?.text) return void 0;
|
|
1785
|
+
try {
|
|
1786
|
+
const parsed = JSON.parse(textPart.text);
|
|
1787
|
+
return typeof parsed[field] === "number" ? parsed[field] : void 0;
|
|
1788
|
+
} catch {
|
|
1789
|
+
return;
|
|
1790
|
+
}
|
|
1791
|
+
}
|
|
1792
|
+
function parseStringArrayField(result, field) {
|
|
1793
|
+
const textPart = result.find((p) => p.type === "textPart");
|
|
1794
|
+
if (!textPart?.text) return void 0;
|
|
1795
|
+
try {
|
|
1796
|
+
const parsed = JSON.parse(textPart.text);
|
|
1797
|
+
if (Array.isArray(parsed[field])) return parsed[field].map(String);
|
|
1798
|
+
} catch {}
|
|
1744
1799
|
}
|
|
1745
1800
|
function parseRemainingTodosFromResult(result) {
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
})
|
|
1757
|
-
);
|
|
1758
|
-
}
|
|
1759
|
-
} catch {
|
|
1760
|
-
}
|
|
1761
|
-
return void 0;
|
|
1801
|
+
const textPart = result.find((p) => p.type === "textPart");
|
|
1802
|
+
if (!textPart?.text) return void 0;
|
|
1803
|
+
try {
|
|
1804
|
+
const parsed = JSON.parse(textPart.text);
|
|
1805
|
+
if (Array.isArray(parsed.remainingTodos)) return parsed.remainingTodos.map((t, i) => ({
|
|
1806
|
+
id: typeof t.id === "number" ? t.id : i,
|
|
1807
|
+
title: typeof t.title === "string" ? t.title : "",
|
|
1808
|
+
completed: typeof t.completed === "boolean" ? t.completed : false
|
|
1809
|
+
}));
|
|
1810
|
+
} catch {}
|
|
1762
1811
|
}
|
|
1763
1812
|
function parseTodosFromResult(result) {
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
);
|
|
1776
|
-
}
|
|
1777
|
-
} catch {
|
|
1778
|
-
}
|
|
1779
|
-
return [];
|
|
1813
|
+
const textPart = result.find((p) => p.type === "textPart");
|
|
1814
|
+
if (!textPart?.text) return [];
|
|
1815
|
+
try {
|
|
1816
|
+
const parsed = JSON.parse(textPart.text);
|
|
1817
|
+
if (Array.isArray(parsed.todos)) return parsed.todos.map((t, i) => ({
|
|
1818
|
+
id: typeof t.id === "number" ? t.id : i,
|
|
1819
|
+
title: typeof t.title === "string" ? t.title : "",
|
|
1820
|
+
completed: typeof t.completed === "boolean" ? t.completed : false
|
|
1821
|
+
}));
|
|
1822
|
+
} catch {}
|
|
1823
|
+
return [];
|
|
1780
1824
|
}
|
|
1781
1825
|
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
"NPM_CONFIG_HTTPS_PROXY"
|
|
1826
|
+
//#endregion
|
|
1827
|
+
//#region src/utils/env-filter.ts
|
|
1828
|
+
const SAFE_ENV_VARS = [
|
|
1829
|
+
"PATH",
|
|
1830
|
+
"HOME",
|
|
1831
|
+
"SHELL",
|
|
1832
|
+
"TERM",
|
|
1833
|
+
"NODE_PATH",
|
|
1834
|
+
"HTTP_PROXY",
|
|
1835
|
+
"HTTPS_PROXY",
|
|
1836
|
+
"http_proxy",
|
|
1837
|
+
"https_proxy",
|
|
1838
|
+
"NO_PROXY",
|
|
1839
|
+
"no_proxy",
|
|
1840
|
+
"PERSTACK_PROXY_URL",
|
|
1841
|
+
"NPM_CONFIG_PROXY",
|
|
1842
|
+
"NPM_CONFIG_HTTPS_PROXY"
|
|
1800
1843
|
];
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1844
|
+
const PROTECTED_ENV_VARS = new Set([
|
|
1845
|
+
"PATH",
|
|
1846
|
+
"HOME",
|
|
1847
|
+
"SHELL",
|
|
1848
|
+
"NODE_PATH",
|
|
1849
|
+
"LD_PRELOAD",
|
|
1850
|
+
"LD_LIBRARY_PATH",
|
|
1851
|
+
"DYLD_INSERT_LIBRARIES",
|
|
1852
|
+
"DYLD_LIBRARY_PATH",
|
|
1853
|
+
"NODE_OPTIONS",
|
|
1854
|
+
"PYTHONPATH",
|
|
1855
|
+
"PERL5LIB",
|
|
1856
|
+
"RUBYLIB"
|
|
1814
1857
|
]);
|
|
1815
1858
|
function getFilteredEnv(additional) {
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
if (additional) {
|
|
1823
|
-
for (const [key, value] of Object.entries(additional)) {
|
|
1824
|
-
if (!PROTECTED_ENV_VARS.has(key.toUpperCase())) {
|
|
1825
|
-
filtered[key] = value;
|
|
1826
|
-
}
|
|
1827
|
-
}
|
|
1828
|
-
}
|
|
1829
|
-
return filtered;
|
|
1859
|
+
const filtered = {};
|
|
1860
|
+
for (const key of SAFE_ENV_VARS) if (process.env[key]) filtered[key] = process.env[key];
|
|
1861
|
+
if (additional) {
|
|
1862
|
+
for (const [key, value] of Object.entries(additional)) if (!PROTECTED_ENV_VARS.has(key.toUpperCase())) filtered[key] = value;
|
|
1863
|
+
}
|
|
1864
|
+
return filtered;
|
|
1830
1865
|
}
|
|
1831
1866
|
|
|
1832
|
-
|
|
1867
|
+
//#endregion
|
|
1868
|
+
//#region src/utils/event-filter.ts
|
|
1869
|
+
/**
|
|
1870
|
+
* Validate and parse event filter option
|
|
1871
|
+
* @param filter - Array of event type strings to validate
|
|
1872
|
+
* @returns The validated filter array
|
|
1873
|
+
* @throws Error if any event type is invalid
|
|
1874
|
+
*/
|
|
1833
1875
|
function validateEventFilter(filter) {
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
`Invalid event type(s): ${invalid.join(", ")}. Valid event types are: startRun, completeRun, stopRunByError, callTools, etc. See documentation for full list.`
|
|
1838
|
-
);
|
|
1839
|
-
}
|
|
1840
|
-
return filter;
|
|
1876
|
+
const invalid = filter.filter((type) => !isValidEventType(type) && !isValidRuntimeEventType(type));
|
|
1877
|
+
if (invalid.length > 0) throw new PerstackError(`Invalid event type(s): ${invalid.join(", ")}. Valid event types are: startRun, completeRun, stopRunByError, callTools, etc. See documentation for full list.`);
|
|
1878
|
+
return filter;
|
|
1841
1879
|
}
|
|
1880
|
+
/**
|
|
1881
|
+
* Create a filtered event listener that only emits events of allowed types
|
|
1882
|
+
* @param listener - The original event listener to wrap
|
|
1883
|
+
* @param allowedTypes - Set of event types to allow through
|
|
1884
|
+
* @returns A filtered event listener
|
|
1885
|
+
*/
|
|
1842
1886
|
function createFilteredEventListener(listener, allowedTypes) {
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
}
|
|
1847
|
-
};
|
|
1887
|
+
return (event) => {
|
|
1888
|
+
if (allowedTypes.has(event.type)) listener(event);
|
|
1889
|
+
};
|
|
1848
1890
|
}
|
|
1849
1891
|
|
|
1850
|
-
|
|
1892
|
+
//#endregion
|
|
1893
|
+
//#region src/utils/zod-error.ts
|
|
1851
1894
|
function formatZodError(error) {
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
});
|
|
1856
|
-
return `Validation failed:
|
|
1857
|
-
${issues.join("\n")}`;
|
|
1895
|
+
return `Validation failed:\n${error.issues.map((issue) => {
|
|
1896
|
+
return ` - ${issue.path.length > 0 ? `${issue.path.join(".")}: ` : ""}${issue.message}`;
|
|
1897
|
+
}).join("\n")}`;
|
|
1858
1898
|
}
|
|
1859
1899
|
function parseWithFriendlyError(schema, data, context) {
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
}
|
|
1864
|
-
const prefix = context ? `${context}: ` : "";
|
|
1865
|
-
throw new PerstackError(`${prefix}${formatZodError(result.error)}`);
|
|
1900
|
+
const result = schema.safeParse(data);
|
|
1901
|
+
if (result.success) return result.data;
|
|
1902
|
+
throw new PerstackError(`${context ? `${context}: ` : ""}${formatZodError(result.error)}`);
|
|
1866
1903
|
}
|
|
1867
1904
|
|
|
1868
|
-
|
|
1869
|
-
|
|
1905
|
+
//#endregion
|
|
1906
|
+
export { BASE_SKILL_PREFIX, PerstackError, SAFE_ENV_VARS, activityOrGroupSchema, activitySchema, addDelegateActivitySchema, addSkillActivitySchema, amazonBedrockProviderConfigSchema, anthropicProviderConfigSchema, anthropicProviderSkillSchema, anthropicProviderToolNameSchema, attemptCompletion, attemptCompletionActivitySchema, azureOpenAIProviderToolNameSchema, azureOpenAiProviderConfigSchema, basePartSchema, builtinAnthropicSkillSchema, callTools, checkpointSchema, checkpointStatusSchema, clearTodoActivitySchema, completeActivitySchema, completeRun, continueToNextStep, createBaseToolActivity, createCallToolsEvent, createCompleteRunEvent, createEmptyUsage, createEvent, createExpertActivitySchema, createFilteredEventListener, createGeneralToolActivity, createNormalizedCheckpoint, createResolveToolResultsEvent, createRuntimeEvent, createRuntimeInitEvent, createStartRunEvent, createStreamingEvent, createToolMessage, customAnthropicSkillSchema, deepseekProviderConfigSchema, defaultMaxRetries, defaultMaxSteps, defaultPerstackApiBaseUrl, defaultReasoningBudget, defaultTimeout, delegateActivitySchema, delegationCompleteActivitySchema, delegationTargetSchema, domainPatternSchema, editTextFileActivitySchema, errorActivitySchema, execActivitySchema, expertKeyRegex, expertMessageSchema, expertNameRegex, expertSchema, expertVersionRegex, fileBinaryPartSchema, fileInlinePartSchema, fileSearchOptionsSchema, fileUrlPartSchema, finishMcpTools, finishToolCall, formatZodError, generalToolActivitySchema, getActivities, getFilteredEnv, googleGenerativeAiProviderConfigSchema, googleProviderToolNameSchema, googleVertexProviderConfigSchema, headersSchema, imageBinaryPartSchema, imageInlinePartSchema, imageUrlPartSchema, instructionMessageSchema, interactiveSkillSchema, interactiveToolActivitySchema, interactiveToolSchema, isPrivateOrLocalIP, isValidEventType, isValidRuntimeEventType, jobSchema, jobStatusSchema, knownModels, lockfileExpertSchema, lockfileSchema, lockfileToolDefinitionSchema, maxExpertNameLength, maxSkillNameLength, maxSkillToolNameLength, mcpSseSkillSchema, mcpStdioSkillSchema, messagePartSchema, messageSchema, ollamaProviderConfigSchema, openAiProviderConfigSchema, openaiProviderToolNameSchema, parallelActivitiesGroupSchema, parseExpertKey, parseWithFriendlyError, perstackConfigSchema, proceedToInteractiveTools, providerConfigSchema, providerNameSchema, providerTableSchema, providerToolOptionsSchema, queryActivitySchema, readImageFileActivitySchema, readPdfFileActivitySchema, readTextFileActivitySchema, reasoningBudgetSchema, removeDelegateActivitySchema, removeSkillActivitySchema, resolveToolResults, resumeFromStop, resumeToolCalls, retry, retryActivitySchema, runCommandInputSchema, runParamsSchema, runSettingSchema, runtimeVersionSchema, skillSchema, skipDelegates, startCommandInputSchema, startGeneration, startRun, stepSchema, stopRunByDelegate, stopRunByError, stopRunByExceededMaxSteps, stopRunByInteractiveTool, tagNameRegex, textPartSchema, thinkingPartSchema, todoActivitySchema, toolCallPartSchema, toolCallSchema, toolMessageSchema, toolResultPartSchema, toolResultSchema, usageSchema, userMessageSchema, validateEventFilter, vertexProviderToolNameSchema, webFetchOptionsSchema, webSearchOptionsSchema, writeTextFileActivitySchema };
|
|
1870
1907
|
//# sourceMappingURL=index.js.map
|