@perstack/core 0.0.52 → 0.0.54

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/dist/src/adapters/event-creators.d.ts +26 -0
  2. package/dist/src/adapters/event-creators.d.ts.map +1 -0
  3. package/dist/src/adapters/event-creators.js +126 -0
  4. package/dist/src/adapters/event-creators.js.map +1 -0
  5. package/dist/src/adapters/index.d.ts +2 -0
  6. package/dist/src/adapters/index.d.ts.map +1 -0
  7. package/dist/src/adapters/index.js +2 -0
  8. package/dist/src/adapters/index.js.map +1 -0
  9. package/dist/src/constants/constants.d.ts +11 -0
  10. package/dist/src/constants/constants.d.ts.map +1 -0
  11. package/dist/src/constants/constants.js +13 -0
  12. package/dist/src/constants/constants.js.map +1 -0
  13. package/dist/src/errors.d.ts +4 -0
  14. package/dist/src/errors.d.ts.map +1 -0
  15. package/dist/src/errors.js +7 -0
  16. package/dist/src/errors.js.map +1 -0
  17. package/dist/src/index.d.ts +28 -6219
  18. package/dist/src/index.d.ts.map +1 -0
  19. package/dist/src/index.js +28 -1904
  20. package/dist/src/index.js.map +1 -1
  21. package/dist/src/known-models/index.d.ts +9 -0
  22. package/dist/src/known-models/index.d.ts.map +1 -0
  23. package/dist/src/known-models/index.js +216 -0
  24. package/dist/src/known-models/index.js.map +1 -0
  25. package/dist/src/schemas/activity.d.ts +2159 -0
  26. package/dist/src/schemas/activity.d.ts.map +1 -0
  27. package/dist/src/schemas/activity.js +209 -0
  28. package/dist/src/schemas/activity.js.map +1 -0
  29. package/dist/src/schemas/checkpoint.d.ts +338 -0
  30. package/dist/src/schemas/checkpoint.d.ts.map +1 -0
  31. package/dist/src/schemas/checkpoint.js +69 -0
  32. package/dist/src/schemas/checkpoint.js.map +1 -0
  33. package/dist/src/schemas/expert.d.ts +309 -0
  34. package/dist/src/schemas/expert.d.ts.map +1 -0
  35. package/dist/src/schemas/expert.js +70 -0
  36. package/dist/src/schemas/expert.js.map +1 -0
  37. package/dist/src/schemas/job.d.ts +44 -0
  38. package/dist/src/schemas/job.d.ts.map +1 -0
  39. package/dist/src/schemas/job.js +22 -0
  40. package/dist/src/schemas/job.js.map +1 -0
  41. package/dist/src/schemas/lockfile.d.ts +143 -0
  42. package/dist/src/schemas/lockfile.d.ts.map +1 -0
  43. package/dist/src/schemas/lockfile.js +26 -0
  44. package/dist/src/schemas/lockfile.js.map +1 -0
  45. package/dist/src/schemas/message-part.d.ts +239 -0
  46. package/dist/src/schemas/message-part.d.ts.map +1 -0
  47. package/dist/src/schemas/message-part.js +80 -0
  48. package/dist/src/schemas/message-part.js.map +1 -0
  49. package/dist/src/schemas/message.d.ts +236 -0
  50. package/dist/src/schemas/message.d.ts.map +1 -0
  51. package/dist/src/schemas/message.js +44 -0
  52. package/dist/src/schemas/message.js.map +1 -0
  53. package/dist/src/schemas/perstack-toml.d.ts +366 -0
  54. package/dist/src/schemas/perstack-toml.d.ts.map +1 -0
  55. package/dist/src/schemas/perstack-toml.js +175 -0
  56. package/dist/src/schemas/perstack-toml.js.map +1 -0
  57. package/dist/src/schemas/provider-config.d.ts +216 -0
  58. package/dist/src/schemas/provider-config.d.ts.map +1 -0
  59. package/dist/src/schemas/provider-config.js +86 -0
  60. package/dist/src/schemas/provider-config.js.map +1 -0
  61. package/dist/src/schemas/provider-tools.d.ts +93 -0
  62. package/dist/src/schemas/provider-tools.d.ts.map +1 -0
  63. package/dist/src/schemas/provider-tools.js +60 -0
  64. package/dist/src/schemas/provider-tools.js.map +1 -0
  65. package/dist/src/schemas/run-command.d.ts +127 -0
  66. package/dist/src/schemas/run-command.d.ts.map +1 -0
  67. package/dist/src/schemas/run-command.js +82 -0
  68. package/dist/src/schemas/run-command.js.map +1 -0
  69. package/dist/src/schemas/runtime-version.d.ts +4 -0
  70. package/dist/src/schemas/runtime-version.d.ts.map +1 -0
  71. package/dist/src/schemas/runtime-version.js +6 -0
  72. package/dist/src/schemas/runtime-version.js.map +1 -0
  73. package/dist/src/schemas/runtime.d.ts +1317 -0
  74. package/dist/src/schemas/runtime.d.ts.map +1 -0
  75. package/dist/src/schemas/runtime.js +205 -0
  76. package/dist/src/schemas/runtime.js.map +1 -0
  77. package/dist/src/schemas/skill-manager.d.ts +64 -0
  78. package/dist/src/schemas/skill-manager.d.ts.map +1 -0
  79. package/dist/src/schemas/skill-manager.js +2 -0
  80. package/dist/src/schemas/skill-manager.js.map +1 -0
  81. package/dist/src/schemas/skill.d.ts +147 -0
  82. package/dist/src/schemas/skill.d.ts.map +1 -0
  83. package/dist/src/schemas/skill.js +99 -0
  84. package/dist/src/schemas/skill.js.map +1 -0
  85. package/dist/src/schemas/step.d.ts +370 -0
  86. package/dist/src/schemas/step.d.ts.map +1 -0
  87. package/dist/src/schemas/step.js +21 -0
  88. package/dist/src/schemas/step.js.map +1 -0
  89. package/dist/src/schemas/tool-call.d.ts +19 -0
  90. package/dist/src/schemas/tool-call.d.ts.map +1 -0
  91. package/dist/src/schemas/tool-call.js +10 -0
  92. package/dist/src/schemas/tool-call.js.map +1 -0
  93. package/dist/src/schemas/tool-result.d.ts +86 -0
  94. package/dist/src/schemas/tool-result.d.ts.map +1 -0
  95. package/dist/src/schemas/tool-result.js +11 -0
  96. package/dist/src/schemas/tool-result.js.map +1 -0
  97. package/dist/src/schemas/usage.d.ts +22 -0
  98. package/dist/src/schemas/usage.d.ts.map +1 -0
  99. package/dist/src/schemas/usage.js +10 -0
  100. package/dist/src/schemas/usage.js.map +1 -0
  101. package/dist/src/utils/activity.d.ts +20 -0
  102. package/dist/src/utils/activity.d.ts.map +1 -0
  103. package/dist/src/utils/activity.js +449 -0
  104. package/dist/src/utils/activity.js.map +1 -0
  105. package/dist/src/utils/env-filter.d.ts +4 -0
  106. package/dist/src/utils/env-filter.d.ts.map +1 -0
  107. package/dist/src/utils/env-filter.js +50 -0
  108. package/dist/src/utils/env-filter.js.map +1 -0
  109. package/dist/src/utils/event-filter.d.ts +16 -0
  110. package/dist/src/utils/event-filter.d.ts.map +1 -0
  111. package/dist/src/utils/event-filter.js +31 -0
  112. package/dist/src/utils/event-filter.js.map +1 -0
  113. package/dist/src/utils/expert-type.d.ts +38 -0
  114. package/dist/src/utils/expert-type.d.ts.map +1 -0
  115. package/dist/src/utils/expert-type.js +88 -0
  116. package/dist/src/utils/expert-type.js.map +1 -0
  117. package/dist/src/utils/zod-error.d.ts +4 -0
  118. package/dist/src/utils/zod-error.d.ts.map +1 -0
  119. package/dist/src/utils/zod-error.js +17 -0
  120. package/dist/src/utils/zod-error.js.map +1 -0
  121. package/package.json +19 -17
  122. package/LICENSE +0 -202
package/dist/src/index.js CHANGED
@@ -1,1905 +1,29 @@
1
- import { createId } from "@paralleldrive/cuid2";
2
- import { z } from "zod";
3
-
4
- //#region src/adapters/event-creators.ts
5
- function createEmptyUsage() {
6
- return {
7
- inputTokens: 0,
8
- outputTokens: 0,
9
- reasoningTokens: 0,
10
- totalTokens: 0,
11
- cachedInputTokens: 0
12
- };
13
- }
14
- function createNormalizedCheckpoint(params) {
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
- };
38
- }
39
- function createStartRunEvent(jobId, runId, expertKey, checkpoint) {
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
- };
51
- }
52
- function createRuntimeInitEvent(jobId, runId, expertName, version, query) {
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
- };
67
- }
68
- function createCompleteRunEvent(jobId, runId, expertKey, checkpoint, output, startedAt) {
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
- };
88
- }
89
- function createCallToolsEvent(jobId, runId, expertKey, stepNumber, toolCalls, _checkpoint) {
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
- };
107
- }
108
- function createResolveToolResultsEvent(jobId, runId, expertKey, stepNumber, toolResults) {
109
- return {
110
- type: "resolveToolResults",
111
- id: createId(),
112
- expertKey,
113
- timestamp: Date.now(),
114
- jobId,
115
- runId,
116
- stepNumber,
117
- toolResults
118
- };
119
- }
120
- function createToolMessage(toolCallId, toolName, resultText) {
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
- };
136
- }
137
-
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;
151
-
152
- //#endregion
153
- //#region src/errors.ts
154
- var PerstackError = class extends Error {
155
- constructor(message) {
156
- super(message);
157
- this.name = "PerstackError";
158
- }
159
- };
160
-
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
- }
351
- ];
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.record(z.string(), 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
423
- ]);
424
-
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
602
- ]);
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
653
- ]);
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()
681
- });
682
-
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"
694
- ]);
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"
750
- ]);
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"
771
- ]);
772
- const googleProviderToolNameSchema = z.enum([
773
- "googleSearch",
774
- "codeExecution",
775
- "urlContext",
776
- "fileSearch",
777
- "googleMaps"
778
- ]);
779
- const azureOpenAIProviderToolNameSchema = z.enum([
780
- "webSearchPreview",
781
- "fileSearch",
782
- "codeInterpreter",
783
- "imageGeneration"
784
- ]);
785
- const vertexProviderToolNameSchema = z.enum([
786
- "codeExecution",
787
- "urlContext",
788
- "googleSearch",
789
- "enterpriseWebSearch",
790
- "googleMaps"
791
- ]);
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()
805
- }).optional();
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
813
- function isPrivateOrLocalIP(hostname) {
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;
832
- }
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
885
- ]);
886
-
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"
934
- ]);
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"
985
- ]);
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
1050
- ]);
1051
-
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
- })
1147
- ]);
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()
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 */
1267
- function parseExpertKey(expertKey) {
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
- };
1278
- }
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 */
1344
- function createEvent(type) {
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
- };
1357
- }
1358
- /** Factory function to create streaming events */
1359
- function createStreamingEvent(type, setting, checkpoint, data) {
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
- };
1370
- }
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 finishToolCall = createEvent("finishToolCall");
1381
- const resumeToolCalls = createEvent("resumeToolCalls");
1382
- const completeRun = createEvent("completeRun");
1383
- const stopRunByInteractiveTool = createEvent("stopRunByInteractiveTool");
1384
- const stopRunByDelegate = createEvent("stopRunByDelegate");
1385
- const stopRunByExceededMaxSteps = createEvent("stopRunByExceededMaxSteps");
1386
- const stopRunByError = createEvent("stopRunByError");
1387
- const continueToNextStep = createEvent("continueToNextStep");
1388
- /** Factory function to create runtime events */
1389
- function createRuntimeEvent(type, jobId, runId, data) {
1390
- return {
1391
- type,
1392
- id: createId(),
1393
- timestamp: Date.now(),
1394
- jobId,
1395
- runId,
1396
- ...data
1397
- };
1398
- }
1399
- /**
1400
- * Valid expert state event types (state machine transitions)
1401
- */
1402
- const EXPERT_STATE_EVENT_TYPES = new Set([
1403
- "startRun",
1404
- "resumeFromStop",
1405
- "proceedToInteractiveTools",
1406
- "startGeneration",
1407
- "retry",
1408
- "callTools",
1409
- "finishMcpTools",
1410
- "skipDelegates",
1411
- "resolveToolResults",
1412
- "finishToolCall",
1413
- "resumeToolCalls",
1414
- "continueToNextStep",
1415
- "stopRunByInteractiveTool",
1416
- "stopRunByDelegate",
1417
- "stopRunByExceededMaxSteps",
1418
- "stopRunByError",
1419
- "completeRun"
1420
- ]);
1421
- /**
1422
- * Valid streaming event types
1423
- */
1424
- const STREAMING_EVENT_TYPES = new Set([
1425
- "startStreamingReasoning",
1426
- "streamReasoning",
1427
- "completeStreamingReasoning",
1428
- "startStreamingRunResult",
1429
- "streamRunResult",
1430
- "completeStreamingRunResult"
1431
- ]);
1432
- /**
1433
- * Valid runtime event types (infrastructure-level events)
1434
- */
1435
- const RUNTIME_EVENT_TYPES = new Set([
1436
- "initializeRuntime",
1437
- "skillStarting",
1438
- "skillConnected",
1439
- "skillStderr",
1440
- "skillDisconnected"
1441
- ]);
1442
- /** Validate if a string is a valid RunEvent type (ExpertStateEvent or StreamingEvent) */
1443
- function isValidEventType(type) {
1444
- return EXPERT_STATE_EVENT_TYPES.has(type) || STREAMING_EVENT_TYPES.has(type);
1445
- }
1446
- /** Validate if a string is a valid RuntimeEvent type */
1447
- function isValidRuntimeEventType(type) {
1448
- return RUNTIME_EVENT_TYPES.has(type);
1449
- }
1450
-
1451
- //#endregion
1452
- //#region src/schemas/step.ts
1453
- const stepSchema = z.object({
1454
- stepNumber: z.number(),
1455
- inputMessages: z.array(z.union([
1456
- instructionMessageSchema,
1457
- userMessageSchema,
1458
- toolMessageSchema
1459
- ])).optional(),
1460
- newMessages: z.array(messageSchema),
1461
- toolCalls: z.array(toolCallSchema).optional(),
1462
- toolResults: z.array(toolResultSchema).optional(),
1463
- pendingToolCalls: z.array(toolCallSchema).optional(),
1464
- partialToolResults: z.array(toolResultSchema).optional(),
1465
- usage: usageSchema,
1466
- startedAt: z.number(),
1467
- finishedAt: z.number().optional()
1468
- });
1469
-
1470
- //#endregion
1471
- //#region src/utils/activity.ts
1472
- const BASE_SKILL_PREFIX = "@perstack/base";
1473
- /**
1474
- * Extracts reasoning from Step.newMessages by finding thinkingParts.
1475
- */
1476
- function extractReasoning(newMessages) {
1477
- const thinkingParts = [];
1478
- for (const message of newMessages) for (const content of message.contents) if (content.type === "thinkingPart") thinkingParts.push(content);
1479
- if (thinkingParts.length === 0) return void 0;
1480
- return thinkingParts.map((p) => p.thinking).join("\n\n");
1481
- }
1482
- /**
1483
- * Wraps multiple activities into a ParallelActivitiesGroup when they share reasoning.
1484
- * Single activities are returned as-is.
1485
- */
1486
- function wrapInGroupIfParallel(activities, reasoning, expertKey, runId, stepNumber) {
1487
- if (activities.length <= 1) return activities;
1488
- const activitiesWithoutReasoning = activities.map((a) => {
1489
- const { reasoning: _, ...rest } = a;
1490
- return rest;
1491
- });
1492
- return [{
1493
- type: "parallelGroup",
1494
- id: `parallel-${runId}-step${stepNumber}`,
1495
- expertKey,
1496
- runId,
1497
- reasoning,
1498
- activities: activitiesWithoutReasoning
1499
- }];
1500
- }
1501
- /**
1502
- * Computes activities from a checkpoint and step.
1503
- * Returns an array of activities or activity groups, supporting parallel tool calls and delegations.
1504
- * When multiple activities are produced from a single step, they are wrapped in a ParallelActivitiesGroup
1505
- * with shared reasoning.
1506
- */
1507
- function getActivities(params) {
1508
- const { checkpoint, step } = params;
1509
- const { status, delegateTo, runId, stepNumber } = checkpoint;
1510
- const expertKey = checkpoint.expert.key;
1511
- const reasoning = extractReasoning(step.newMessages);
1512
- let queryActivity;
1513
- if (stepNumber === 1 && step.inputMessages) {
1514
- const userMessage = step.inputMessages.find((m) => m.type === "userMessage");
1515
- if (userMessage) {
1516
- const textPart = userMessage.contents.find((c) => c.type === "textPart");
1517
- if (textPart && "text" in textPart) queryActivity = {
1518
- type: "query",
1519
- id: "",
1520
- expertKey,
1521
- runId,
1522
- text: textPart.text
1523
- };
1524
- }
1525
- }
1526
- const prependQuery = (result) => queryActivity ? [queryActivity, ...result] : result;
1527
- if (status === "stoppedByError") return prependQuery([createErrorActivity(checkpoint, reasoning)]);
1528
- if (status === "stoppedByDelegate") {
1529
- if (!delegateTo || delegateTo.length === 0) return prependQuery([createRetryActivity(step.newMessages, reasoning, "Delegate status but no delegation targets")]);
1530
- return prependQuery(wrapInGroupIfParallel(delegateTo.map((d) => createDelegateActivity(d, reasoning)), reasoning, expertKey, runId, stepNumber));
1531
- }
1532
- if (status === "stoppedByInteractiveTool") {
1533
- const toolCalls = step.toolCalls ?? [];
1534
- if (toolCalls.length === 0) return prependQuery([createRetryActivity(step.newMessages, reasoning)]);
1535
- return prependQuery(wrapInGroupIfParallel(toolCalls.map((tc) => createInteractiveToolActivity(tc.skillName, tc.toolName, tc, reasoning)), reasoning, expertKey, runId, stepNumber));
1536
- }
1537
- const toolCalls = step.toolCalls ?? [];
1538
- const toolResults = step.toolResults ?? [];
1539
- if (toolCalls.length === 0) {
1540
- if (status === "completed") return prependQuery([createCompleteActivity(step.newMessages, reasoning)]);
1541
- if (status === "proceeding" || status === "init") return prependQuery([]);
1542
- return prependQuery([createRetryActivity(step.newMessages, reasoning)]);
1543
- }
1544
- const toolActivities = [];
1545
- for (const toolCall of toolCalls) {
1546
- const toolResult = toolResults.find((tr) => tr.id === toolCall.id);
1547
- if (!toolResult) continue;
1548
- const { skillName, toolName } = toolCall;
1549
- if (skillName.startsWith(BASE_SKILL_PREFIX)) toolActivities.push(createBaseToolActivity(toolName, toolCall, toolResult, reasoning));
1550
- else toolActivities.push(createGeneralToolActivity(skillName, toolName, toolCall, toolResult, reasoning));
1551
- }
1552
- if (toolActivities.length === 0) {
1553
- if (status === "completed") return prependQuery([createCompleteActivity(step.newMessages, reasoning)]);
1554
- if (status === "proceeding" || status === "init") return prependQuery([]);
1555
- return prependQuery([createRetryActivity(step.newMessages, reasoning)]);
1556
- }
1557
- const result = wrapInGroupIfParallel(toolActivities, reasoning, expertKey, runId, stepNumber);
1558
- if (status === "completed") result.push(createCompleteActivity(step.newMessages, void 0));
1559
- return prependQuery(result);
1560
- }
1561
- function createCompleteActivity(newMessages, reasoning) {
1562
- return {
1563
- type: "complete",
1564
- id: "",
1565
- expertKey: "",
1566
- runId: "",
1567
- reasoning,
1568
- text: ([...newMessages].reverse().find((m) => m.type === "expertMessage")?.contents.find((c) => c.type === "textPart"))?.text ?? ""
1569
- };
1570
- }
1571
- function createDelegateActivity(delegate, reasoning) {
1572
- return {
1573
- type: "delegate",
1574
- id: "",
1575
- expertKey: "",
1576
- runId: "",
1577
- reasoning,
1578
- delegateExpertKey: delegate.expert.key,
1579
- query: delegate.query
1580
- };
1581
- }
1582
- function createInteractiveToolActivity(skillName, toolName, toolCall, reasoning) {
1583
- return {
1584
- type: "interactiveTool",
1585
- id: "",
1586
- expertKey: "",
1587
- runId: "",
1588
- reasoning,
1589
- skillName,
1590
- toolName,
1591
- args: toolCall.args
1592
- };
1593
- }
1594
- function createRetryActivity(newMessages, reasoning, customError) {
1595
- const textPart = newMessages[newMessages.length - 1]?.contents.find((c) => c.type === "textPart");
1596
- return {
1597
- type: "retry",
1598
- id: "",
1599
- expertKey: "",
1600
- runId: "",
1601
- reasoning,
1602
- error: customError ?? "No tool call or result found",
1603
- message: textPart?.text ?? ""
1604
- };
1605
- }
1606
- function createErrorActivity(checkpoint, reasoning) {
1607
- const error = checkpoint.error;
1608
- return {
1609
- type: "error",
1610
- id: "",
1611
- expertKey: "",
1612
- runId: "",
1613
- reasoning,
1614
- error: error?.message ?? "Unknown error",
1615
- errorName: error?.name,
1616
- isRetryable: error?.isRetryable
1617
- };
1618
- }
1619
- function createBaseToolActivity(toolName, toolCall, toolResult, reasoning) {
1620
- const args = toolCall.args;
1621
- const resultContents = toolResult.result;
1622
- const errorText = getErrorFromResult(resultContents);
1623
- const baseFields = {
1624
- id: "",
1625
- expertKey: "",
1626
- runId: "",
1627
- reasoning
1628
- };
1629
- switch (toolName) {
1630
- case "attemptCompletion": {
1631
- const remainingTodos = parseRemainingTodosFromResult(resultContents);
1632
- return {
1633
- type: "attemptCompletion",
1634
- ...baseFields,
1635
- remainingTodos,
1636
- error: errorText
1637
- };
1638
- }
1639
- case "todo": {
1640
- const todos = parseTodosFromResult(resultContents);
1641
- return {
1642
- type: "todo",
1643
- ...baseFields,
1644
- newTodos: Array.isArray(args["newTodos"]) ? args["newTodos"].map(String) : void 0,
1645
- completedTodos: Array.isArray(args["completedTodos"]) ? args["completedTodos"].map(Number) : void 0,
1646
- todos,
1647
- error: errorText
1648
- };
1649
- }
1650
- case "clearTodo": return {
1651
- type: "clearTodo",
1652
- ...baseFields,
1653
- error: errorText
1654
- };
1655
- case "readImageFile": return {
1656
- type: "readImageFile",
1657
- ...baseFields,
1658
- path: String(args["path"] ?? ""),
1659
- mimeType: parseStringField(resultContents, "mimeType"),
1660
- size: parseNumberField(resultContents, "size"),
1661
- error: errorText
1662
- };
1663
- case "readPdfFile": return {
1664
- type: "readPdfFile",
1665
- ...baseFields,
1666
- path: String(args["path"] ?? ""),
1667
- mimeType: parseStringField(resultContents, "mimeType"),
1668
- size: parseNumberField(resultContents, "size"),
1669
- error: errorText
1670
- };
1671
- case "readTextFile": return {
1672
- type: "readTextFile",
1673
- ...baseFields,
1674
- path: String(args["path"] ?? ""),
1675
- content: parseStringField(resultContents, "content"),
1676
- from: typeof args["from"] === "number" ? args["from"] : void 0,
1677
- to: typeof args["to"] === "number" ? args["to"] : void 0,
1678
- error: errorText
1679
- };
1680
- case "editTextFile": return {
1681
- type: "editTextFile",
1682
- ...baseFields,
1683
- path: String(args["path"] ?? ""),
1684
- newText: String(args["newText"] ?? ""),
1685
- oldText: String(args["oldText"] ?? ""),
1686
- error: errorText
1687
- };
1688
- case "writeTextFile": return {
1689
- type: "writeTextFile",
1690
- ...baseFields,
1691
- path: String(args["path"] ?? ""),
1692
- text: String(args["text"] ?? ""),
1693
- error: errorText
1694
- };
1695
- case "exec": return {
1696
- type: "exec",
1697
- ...baseFields,
1698
- command: String(args["command"] ?? ""),
1699
- args: Array.isArray(args["args"]) ? args["args"].map(String) : [],
1700
- cwd: String(args["cwd"] ?? ""),
1701
- output: parseStringField(resultContents, "output"),
1702
- error: errorText,
1703
- stdout: parseStringField(resultContents, "stdout"),
1704
- stderr: parseStringField(resultContents, "stderr")
1705
- };
1706
- case "addSkill": return {
1707
- type: "addSkill",
1708
- ...baseFields,
1709
- name: String(args["name"] ?? ""),
1710
- skillType: String(args["type"] ?? ""),
1711
- tools: parseStringArrayField(resultContents, "tools"),
1712
- error: errorText
1713
- };
1714
- case "removeSkill": return {
1715
- type: "removeSkill",
1716
- ...baseFields,
1717
- skillName: String(args["skillName"] ?? ""),
1718
- error: errorText
1719
- };
1720
- case "addDelegate": return {
1721
- type: "addDelegate",
1722
- ...baseFields,
1723
- targetExpertKey: String(args["expertKey"] ?? ""),
1724
- delegateToolName: parseStringField(resultContents, "delegateToolName"),
1725
- error: errorText
1726
- };
1727
- case "removeDelegate": return {
1728
- type: "removeDelegate",
1729
- ...baseFields,
1730
- expertName: String(args["expertName"] ?? ""),
1731
- error: errorText
1732
- };
1733
- case "createExpert": return {
1734
- type: "createExpert",
1735
- ...baseFields,
1736
- targetKey: String(args["key"] ?? ""),
1737
- description: typeof args["description"] === "string" ? args["description"] : void 0,
1738
- resultExpertKey: parseStringField(resultContents, "expertKey"),
1739
- error: errorText
1740
- };
1741
- default: return createGeneralToolActivity(toolCall.skillName, toolName, toolCall, toolResult, reasoning);
1742
- }
1743
- }
1744
- function createGeneralToolActivity(skillName, toolName, toolCall, toolResult, reasoning) {
1745
- const errorText = getErrorFromResult(toolResult.result);
1746
- return {
1747
- type: "generalTool",
1748
- id: "",
1749
- expertKey: "",
1750
- runId: "",
1751
- reasoning,
1752
- skillName,
1753
- toolName,
1754
- args: toolCall.args,
1755
- result: toolResult.result,
1756
- error: errorText
1757
- };
1758
- }
1759
- function getErrorFromResult(result) {
1760
- const textPart = result.find((p) => p.type === "textPart");
1761
- if (!textPart?.text) return void 0;
1762
- try {
1763
- const parsed = JSON.parse(textPart.text);
1764
- if (typeof parsed.error === "string") return parsed.error;
1765
- } catch {
1766
- const trimmed = textPart.text.trim();
1767
- if (trimmed.toLowerCase().startsWith("error:") || trimmed.toLowerCase().startsWith("error ")) return textPart.text;
1768
- }
1769
- }
1770
- function parseStringField(result, field) {
1771
- const textPart = result.find((p) => p.type === "textPart");
1772
- if (!textPart?.text) return void 0;
1773
- try {
1774
- const parsed = JSON.parse(textPart.text);
1775
- return typeof parsed[field] === "string" ? parsed[field] : void 0;
1776
- } catch {
1777
- return;
1778
- }
1779
- }
1780
- function parseNumberField(result, field) {
1781
- const textPart = result.find((p) => p.type === "textPart");
1782
- if (!textPart?.text) return void 0;
1783
- try {
1784
- const parsed = JSON.parse(textPart.text);
1785
- return typeof parsed[field] === "number" ? parsed[field] : void 0;
1786
- } catch {
1787
- return;
1788
- }
1789
- }
1790
- function parseStringArrayField(result, field) {
1791
- const textPart = result.find((p) => p.type === "textPart");
1792
- if (!textPart?.text) return void 0;
1793
- try {
1794
- const parsed = JSON.parse(textPart.text);
1795
- if (Array.isArray(parsed[field])) return parsed[field].map(String);
1796
- } catch {}
1797
- }
1798
- function parseRemainingTodosFromResult(result) {
1799
- const textPart = result.find((p) => p.type === "textPart");
1800
- if (!textPart?.text) return void 0;
1801
- try {
1802
- const parsed = JSON.parse(textPart.text);
1803
- if (Array.isArray(parsed.remainingTodos)) return parsed.remainingTodos.map((t, i) => ({
1804
- id: typeof t.id === "number" ? t.id : i,
1805
- title: typeof t.title === "string" ? t.title : "",
1806
- completed: typeof t.completed === "boolean" ? t.completed : false
1807
- }));
1808
- } catch {}
1809
- }
1810
- function parseTodosFromResult(result) {
1811
- const textPart = result.find((p) => p.type === "textPart");
1812
- if (!textPart?.text) return [];
1813
- try {
1814
- const parsed = JSON.parse(textPart.text);
1815
- if (Array.isArray(parsed.todos)) return parsed.todos.map((t, i) => ({
1816
- id: typeof t.id === "number" ? t.id : i,
1817
- title: typeof t.title === "string" ? t.title : "",
1818
- completed: typeof t.completed === "boolean" ? t.completed : false
1819
- }));
1820
- } catch {}
1821
- return [];
1822
- }
1823
-
1824
- //#endregion
1825
- //#region src/utils/env-filter.ts
1826
- const SAFE_ENV_VARS = [
1827
- "PATH",
1828
- "HOME",
1829
- "SHELL",
1830
- "TERM",
1831
- "NODE_PATH",
1832
- "HTTP_PROXY",
1833
- "HTTPS_PROXY",
1834
- "http_proxy",
1835
- "https_proxy",
1836
- "NO_PROXY",
1837
- "no_proxy",
1838
- "PERSTACK_PROXY_URL",
1839
- "NPM_CONFIG_PROXY",
1840
- "NPM_CONFIG_HTTPS_PROXY"
1841
- ];
1842
- const PROTECTED_ENV_VARS = new Set([
1843
- "PATH",
1844
- "HOME",
1845
- "SHELL",
1846
- "NODE_PATH",
1847
- "LD_PRELOAD",
1848
- "LD_LIBRARY_PATH",
1849
- "DYLD_INSERT_LIBRARIES",
1850
- "DYLD_LIBRARY_PATH",
1851
- "NODE_OPTIONS",
1852
- "PYTHONPATH",
1853
- "PERL5LIB",
1854
- "RUBYLIB"
1855
- ]);
1856
- function getFilteredEnv(additional) {
1857
- const filtered = {};
1858
- for (const key of SAFE_ENV_VARS) if (process.env[key]) filtered[key] = process.env[key];
1859
- if (additional) {
1860
- for (const [key, value] of Object.entries(additional)) if (!PROTECTED_ENV_VARS.has(key.toUpperCase())) filtered[key] = value;
1861
- }
1862
- return filtered;
1863
- }
1864
-
1865
- //#endregion
1866
- //#region src/utils/event-filter.ts
1867
- /**
1868
- * Validate and parse event filter option
1869
- * @param filter - Array of event type strings to validate
1870
- * @returns The validated filter array
1871
- * @throws Error if any event type is invalid
1872
- */
1873
- function validateEventFilter(filter) {
1874
- const invalid = filter.filter((type) => !isValidEventType(type) && !isValidRuntimeEventType(type));
1875
- 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.`);
1876
- return filter;
1877
- }
1878
- /**
1879
- * Create a filtered event listener that only emits events of allowed types
1880
- * @param listener - The original event listener to wrap
1881
- * @param allowedTypes - Set of event types to allow through
1882
- * @returns A filtered event listener
1883
- */
1884
- function createFilteredEventListener(listener, allowedTypes) {
1885
- return (event) => {
1886
- if (allowedTypes.has(event.type)) listener(event);
1887
- };
1888
- }
1889
-
1890
- //#endregion
1891
- //#region src/utils/zod-error.ts
1892
- function formatZodError(error) {
1893
- return `Validation failed:\n${error.issues.map((issue) => {
1894
- return ` - ${issue.path.length > 0 ? `${issue.path.join(".")}: ` : ""}${issue.message}`;
1895
- }).join("\n")}`;
1896
- }
1897
- function parseWithFriendlyError(schema, data, context) {
1898
- const result = schema.safeParse(data);
1899
- if (result.success) return result.data;
1900
- throw new PerstackError(`${context ? `${context}: ` : ""}${formatZodError(result.error)}`);
1901
- }
1902
-
1903
- //#endregion
1904
- export { BASE_SKILL_PREFIX, PerstackError, SAFE_ENV_VARS, activityOrGroupSchema, activitySchema, addDelegateActivitySchema, addSkillActivitySchema, amazonBedrockProviderConfigSchema, anthropicProviderConfigSchema, anthropicProviderSkillSchema, anthropicProviderToolNameSchema, 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 };
1
+ export * from "./adapters/index.js";
2
+ export * from "./constants/constants.js";
3
+ export * from "./errors.js";
4
+ export * from "./known-models/index.js";
5
+ export * from "./schemas/activity.js";
6
+ export * from "./schemas/checkpoint.js";
7
+ export * from "./schemas/expert.js";
8
+ export * from "./schemas/job.js";
9
+ export * from "./schemas/lockfile.js";
10
+ export * from "./schemas/message.js";
11
+ export * from "./schemas/message-part.js";
12
+ export * from "./schemas/perstack-toml.js";
13
+ export * from "./schemas/provider-config.js";
14
+ export * from "./schemas/provider-tools.js";
15
+ export * from "./schemas/run-command.js";
16
+ export * from "./schemas/runtime.js";
17
+ export * from "./schemas/runtime-version.js";
18
+ export * from "./schemas/skill.js";
19
+ export * from "./schemas/skill-manager.js";
20
+ export * from "./schemas/step.js";
21
+ export * from "./schemas/tool-call.js";
22
+ export * from "./schemas/tool-result.js";
23
+ export * from "./schemas/usage.js";
24
+ export * from "./utils/activity.js";
25
+ export * from "./utils/env-filter.js";
26
+ export * from "./utils/event-filter.js";
27
+ export * from "./utils/expert-type.js";
28
+ export * from "./utils/zod-error.js";
1905
29
  //# sourceMappingURL=index.js.map