@perstack/runtime 0.0.38 → 0.0.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +201 -0
- package/dist/src/index.d.ts +20 -18
- package/dist/src/index.js +168 -305
- package/dist/src/index.js.map +1 -1
- package/package.json +16 -16
package/dist/src/index.js
CHANGED
|
@@ -1,24 +1,25 @@
|
|
|
1
|
-
import { setup, assign, createActor } from 'xstate';
|
|
2
1
|
import { createAmazonBedrock } from '@ai-sdk/amazon-bedrock';
|
|
3
2
|
import { createAnthropic } from '@ai-sdk/anthropic';
|
|
4
3
|
import { createAzure } from '@ai-sdk/azure';
|
|
5
4
|
import { createGoogleGenerativeAI } from '@ai-sdk/google';
|
|
6
5
|
import { createOpenAI } from '@ai-sdk/openai';
|
|
7
|
-
import { knownModels, stopRunByDelegate, stopRunByInteractiveTool, resolveThought, attemptCompletion, resolvePdfFile, resolveImageFile, resolveToolResult, stopRunByExceededMaxSteps, continueToNextStep, retry, completeRun, callDelegate, callInteractiveTool, callTool, startRun, startGeneration, finishToolCall, runParamsSchema, checkpointSchema } from '@perstack/core';
|
|
6
|
+
import { knownModels, stopRunByDelegate, stopRunByInteractiveTool, resolveThought, attemptCompletion, resolvePdfFile, resolveImageFile, resolveToolResult, stopRunByExceededMaxSteps, continueToNextStep, retry, completeRun, callDelegate, callInteractiveTool, callTool, startRun, startGeneration, finishToolCall, runParamsSchema, createRuntimeEvent, checkpointSchema } from '@perstack/core';
|
|
8
7
|
import { createOllama } from 'ollama-ai-provider-v2';
|
|
8
|
+
import { existsSync } from 'fs';
|
|
9
|
+
import { readFile, writeFile, mkdir, readdir } from 'fs/promises';
|
|
10
|
+
import path from 'path';
|
|
11
|
+
import { createId } from '@paralleldrive/cuid2';
|
|
12
|
+
import { setup, assign, createActor } from 'xstate';
|
|
13
|
+
import { ApiV1Client } from '@perstack/api-client/v1';
|
|
9
14
|
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
10
15
|
import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
|
|
11
16
|
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
|
12
17
|
import { McpError } from '@modelcontextprotocol/sdk/types.js';
|
|
13
|
-
import { createId } from '@paralleldrive/cuid2';
|
|
14
18
|
import { generateText, tool, jsonSchema } from 'ai';
|
|
15
19
|
import { dedent } from 'ts-dedent';
|
|
16
|
-
import {
|
|
17
|
-
import { existsSync } from 'fs';
|
|
18
|
-
import path from 'path';
|
|
19
|
-
import { ApiV1Client } from '@perstack/api-client/v1';
|
|
20
|
+
import { createRequire } from 'module';
|
|
20
21
|
|
|
21
|
-
// src/
|
|
22
|
+
// src/model.ts
|
|
22
23
|
function getModel(modelId, providerConfig) {
|
|
23
24
|
switch (providerConfig.name) {
|
|
24
25
|
case "anthropic": {
|
|
@@ -76,6 +77,78 @@ function getContextWindow(providerName, modelId) {
|
|
|
76
77
|
function calculateContextWindowUsage(usage, contextWindow) {
|
|
77
78
|
return (usage.inputTokens + usage.cachedInputTokens + usage.outputTokens) / contextWindow;
|
|
78
79
|
}
|
|
80
|
+
async function defaultRetrieveCheckpoint(runId, checkpointId) {
|
|
81
|
+
const runDir = getRunDir(runId);
|
|
82
|
+
const checkpointFiles = await readdir(runDir, { withFileTypes: true }).then(
|
|
83
|
+
(files) => files.filter((file) => file.isFile() && file.name.startsWith("checkpoint-"))
|
|
84
|
+
);
|
|
85
|
+
const checkpointFile = checkpointFiles.find((file) => file.name.endsWith(`-${checkpointId}.json`));
|
|
86
|
+
if (!checkpointFile) {
|
|
87
|
+
throw new Error(`checkpoint not found: ${runId} ${checkpointId}`);
|
|
88
|
+
}
|
|
89
|
+
const checkpointPath = `${runDir}/${checkpointFile.name}`;
|
|
90
|
+
const checkpoint = await readFile(checkpointPath, "utf8");
|
|
91
|
+
return checkpointSchema.parse(JSON.parse(checkpoint));
|
|
92
|
+
}
|
|
93
|
+
async function defaultStoreCheckpoint(checkpoint, timestamp) {
|
|
94
|
+
const { id, runId, stepNumber } = checkpoint;
|
|
95
|
+
const runDir = getRunDir(runId);
|
|
96
|
+
const checkpointPath = `${runDir}/checkpoint-${timestamp}-${stepNumber}-${id}.json`;
|
|
97
|
+
await mkdir(runDir, { recursive: true });
|
|
98
|
+
await writeFile(checkpointPath, JSON.stringify(checkpoint));
|
|
99
|
+
}
|
|
100
|
+
async function defaultStoreEvent(event) {
|
|
101
|
+
const { timestamp, runId, stepNumber, type } = event;
|
|
102
|
+
const runDir = getRunDir(runId);
|
|
103
|
+
const eventPath = `${runDir}/event-${timestamp}-${stepNumber}-${type}.json`;
|
|
104
|
+
await mkdir(runDir, { recursive: true });
|
|
105
|
+
await writeFile(eventPath, JSON.stringify(event));
|
|
106
|
+
}
|
|
107
|
+
var RunEventEmitter = class {
|
|
108
|
+
listeners = [];
|
|
109
|
+
subscribe(listener) {
|
|
110
|
+
this.listeners.push(listener);
|
|
111
|
+
}
|
|
112
|
+
async emit(event) {
|
|
113
|
+
for (const listener of this.listeners) {
|
|
114
|
+
await listener({
|
|
115
|
+
...event,
|
|
116
|
+
id: createId(),
|
|
117
|
+
timestamp: Date.now()
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
async function resolveExpertToRun(expertKey, experts, clientOptions) {
|
|
123
|
+
if (experts[expertKey]) {
|
|
124
|
+
return experts[expertKey];
|
|
125
|
+
}
|
|
126
|
+
const client = new ApiV1Client({
|
|
127
|
+
baseUrl: clientOptions.perstackApiBaseUrl,
|
|
128
|
+
apiKey: clientOptions.perstackApiKey
|
|
129
|
+
});
|
|
130
|
+
const { expert } = await client.registry.experts.get({ expertKey });
|
|
131
|
+
experts[expertKey] = toRuntimeExpert(expert);
|
|
132
|
+
return experts[expertKey];
|
|
133
|
+
}
|
|
134
|
+
function toRuntimeExpert(expert) {
|
|
135
|
+
const skills = Object.fromEntries(
|
|
136
|
+
Object.entries(expert.skills).map(([name, skill]) => {
|
|
137
|
+
switch (skill.type) {
|
|
138
|
+
case "mcpStdioSkill":
|
|
139
|
+
return [name, { ...skill, name }];
|
|
140
|
+
case "mcpSseSkill":
|
|
141
|
+
return [name, { ...skill, name }];
|
|
142
|
+
case "interactiveSkill":
|
|
143
|
+
return [name, { ...skill, name }];
|
|
144
|
+
default: {
|
|
145
|
+
throw new Error(`Unknown skill type: ${skill.type}`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
})
|
|
149
|
+
);
|
|
150
|
+
return { ...expert, skills };
|
|
151
|
+
}
|
|
79
152
|
var SkillManager = class {
|
|
80
153
|
_toolDefinitions = [];
|
|
81
154
|
_initialized = false;
|
|
@@ -89,8 +162,12 @@ var SkillManager = class {
|
|
|
89
162
|
_mcpClient;
|
|
90
163
|
_params;
|
|
91
164
|
_env;
|
|
92
|
-
|
|
165
|
+
_runId;
|
|
166
|
+
_eventListener;
|
|
167
|
+
constructor(params, runId, eventListener) {
|
|
93
168
|
this._params = params;
|
|
169
|
+
this._runId = runId;
|
|
170
|
+
this._eventListener = eventListener;
|
|
94
171
|
this.type = params.type;
|
|
95
172
|
switch (params.type) {
|
|
96
173
|
case "mcp":
|
|
@@ -175,8 +252,16 @@ var SkillManager = class {
|
|
|
175
252
|
env[envName] = this._env[envName];
|
|
176
253
|
}
|
|
177
254
|
const { command, args } = this._getCommandArgs(params.skill);
|
|
178
|
-
const transport = new StdioClientTransport({ command, args, env });
|
|
255
|
+
const transport = new StdioClientTransport({ command, args, env, stderr: "ignore" });
|
|
179
256
|
await this._mcpClient.connect(transport);
|
|
257
|
+
if (this._eventListener) {
|
|
258
|
+
const serverInfo = this._mcpClient.getServerVersion();
|
|
259
|
+
const event = createRuntimeEvent("skillConnected", this._runId, {
|
|
260
|
+
skillName: params.skill.name,
|
|
261
|
+
serverInfo: serverInfo ? { name: serverInfo.name, version: serverInfo.version } : void 0
|
|
262
|
+
});
|
|
263
|
+
this._eventListener(event);
|
|
264
|
+
}
|
|
180
265
|
break;
|
|
181
266
|
}
|
|
182
267
|
case "mcpSseSkill": {
|
|
@@ -246,6 +331,12 @@ var SkillManager = class {
|
|
|
246
331
|
async close() {
|
|
247
332
|
if (this._mcpClient) {
|
|
248
333
|
await this._mcpClient.close();
|
|
334
|
+
if (this._eventListener && this.skill) {
|
|
335
|
+
const event = createRuntimeEvent("skillDisconnected", this._runId, {
|
|
336
|
+
skillName: this.skill.name
|
|
337
|
+
});
|
|
338
|
+
this._eventListener(event);
|
|
339
|
+
}
|
|
249
340
|
}
|
|
250
341
|
}
|
|
251
342
|
async getToolDefinitions() {
|
|
@@ -352,8 +443,8 @@ var SkillManager = class {
|
|
|
352
443
|
throw new Error(`Unsupported resource type: ${JSON.stringify(resource)}`);
|
|
353
444
|
}
|
|
354
445
|
};
|
|
355
|
-
async function getSkillManagers(expert, experts, setting) {
|
|
356
|
-
const { perstackBaseSkillCommand, env } = setting;
|
|
446
|
+
async function getSkillManagers(expert, experts, setting, eventListener) {
|
|
447
|
+
const { perstackBaseSkillCommand, env, runId } = setting;
|
|
357
448
|
const skillManagers = {};
|
|
358
449
|
const { skills } = expert;
|
|
359
450
|
if (!skills["@perstack/base"]) {
|
|
@@ -375,21 +466,29 @@ async function getSkillManagers(expert, experts, setting) {
|
|
|
375
466
|
skill.lazyInit = false;
|
|
376
467
|
}
|
|
377
468
|
}
|
|
378
|
-
const skillManager = new SkillManager(
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
469
|
+
const skillManager = new SkillManager(
|
|
470
|
+
{
|
|
471
|
+
type: "mcp",
|
|
472
|
+
skill,
|
|
473
|
+
env
|
|
474
|
+
},
|
|
475
|
+
runId,
|
|
476
|
+
eventListener
|
|
477
|
+
);
|
|
383
478
|
await skillManager.init();
|
|
384
479
|
return skillManager;
|
|
385
480
|
})
|
|
386
481
|
);
|
|
387
482
|
const interactiveSkillManagers = await Promise.all(
|
|
388
483
|
Object.values(skills).filter((skill) => skill.type === "interactiveSkill").map(async (interactiveSkill) => {
|
|
389
|
-
const skillManager = new SkillManager(
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
484
|
+
const skillManager = new SkillManager(
|
|
485
|
+
{
|
|
486
|
+
type: "interactive",
|
|
487
|
+
interactiveSkill
|
|
488
|
+
},
|
|
489
|
+
runId,
|
|
490
|
+
eventListener
|
|
491
|
+
);
|
|
393
492
|
await skillManager.init();
|
|
394
493
|
return skillManager;
|
|
395
494
|
})
|
|
@@ -397,10 +496,14 @@ async function getSkillManagers(expert, experts, setting) {
|
|
|
397
496
|
const delegateSkillManagers = await Promise.all(
|
|
398
497
|
expert.delegates.map(async (delegateExpertName) => {
|
|
399
498
|
const delegate = experts[delegateExpertName];
|
|
400
|
-
const skillManager = new SkillManager(
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
499
|
+
const skillManager = new SkillManager(
|
|
500
|
+
{
|
|
501
|
+
type: "delegate",
|
|
502
|
+
expert: delegate
|
|
503
|
+
},
|
|
504
|
+
runId,
|
|
505
|
+
eventListener
|
|
506
|
+
);
|
|
404
507
|
await skillManager.init();
|
|
405
508
|
return skillManager;
|
|
406
509
|
})
|
|
@@ -1618,266 +1721,20 @@ var StateMachineLogics = {
|
|
|
1618
1721
|
CallingDelegate: callingDelegateLogic,
|
|
1619
1722
|
FinishingStep: finishingStepLogic
|
|
1620
1723
|
};
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
(files) => files.filter((file) => file.isFile() && file.name.startsWith("checkpoint-"))
|
|
1625
|
-
);
|
|
1626
|
-
const checkpointFile = checkpointFiles.find((file) => file.name.endsWith(`-${checkpointId}.json`));
|
|
1627
|
-
if (!checkpointFile) {
|
|
1628
|
-
throw new Error(`checkpoint not found: ${runId} ${checkpointId}`);
|
|
1724
|
+
var getVersion = () => {
|
|
1725
|
+
if (typeof __RUNTIME_VERSION__ !== "undefined") {
|
|
1726
|
+
return __RUNTIME_VERSION__;
|
|
1629
1727
|
}
|
|
1630
|
-
const
|
|
1631
|
-
const
|
|
1632
|
-
return
|
|
1633
|
-
}
|
|
1634
|
-
async function defaultStoreCheckpoint(checkpoint, timestamp) {
|
|
1635
|
-
const { id, runId, stepNumber } = checkpoint;
|
|
1636
|
-
const runDir = getRunDir(runId);
|
|
1637
|
-
const checkpointPath = `${runDir}/checkpoint-${timestamp}-${stepNumber}-${id}.json`;
|
|
1638
|
-
await mkdir(runDir, { recursive: true });
|
|
1639
|
-
await writeFile(checkpointPath, JSON.stringify(checkpoint, null, 2));
|
|
1640
|
-
}
|
|
1641
|
-
async function defaultStoreEvent(event) {
|
|
1642
|
-
const { timestamp, runId, stepNumber, type } = event;
|
|
1643
|
-
const runDir = getRunDir(runId);
|
|
1644
|
-
const eventPath = `${runDir}/event-${timestamp}-${stepNumber}-${type}.json`;
|
|
1645
|
-
await mkdir(runDir, { recursive: true });
|
|
1646
|
-
await writeFile(eventPath, JSON.stringify(event, null, 2));
|
|
1647
|
-
}
|
|
1648
|
-
|
|
1649
|
-
// package.json
|
|
1650
|
-
var package_default = {
|
|
1651
|
-
version: "0.0.38"};
|
|
1652
|
-
|
|
1653
|
-
// src/events/default-event-listener.ts
|
|
1654
|
-
var log = console.info;
|
|
1655
|
-
var debug = console.debug;
|
|
1656
|
-
var header = (e) => {
|
|
1657
|
-
const t = (/* @__PURE__ */ new Date()).toISOString();
|
|
1658
|
-
const stepNumber = e.stepNumber;
|
|
1659
|
-
const key = e.expertKey;
|
|
1660
|
-
return `${t} ${stepNumber} ${key}`;
|
|
1728
|
+
const require2 = createRequire(import.meta.url);
|
|
1729
|
+
const pkg = require2("../package.json");
|
|
1730
|
+
return pkg.version;
|
|
1661
1731
|
};
|
|
1662
|
-
|
|
1663
|
-
await defaultStoreEvent(e);
|
|
1664
|
-
switch (e.type) {
|
|
1665
|
-
case "startRun": {
|
|
1666
|
-
log(`${header(e)} Perstack@${package_default.version} started`);
|
|
1667
|
-
break;
|
|
1668
|
-
}
|
|
1669
|
-
case "startGeneration": {
|
|
1670
|
-
log(`${header(e)} Generating tool call`);
|
|
1671
|
-
break;
|
|
1672
|
-
}
|
|
1673
|
-
case "retry": {
|
|
1674
|
-
log(`${header(e)} Retrying tool call generation`);
|
|
1675
|
-
debug(e.reason);
|
|
1676
|
-
break;
|
|
1677
|
-
}
|
|
1678
|
-
case "callTool": {
|
|
1679
|
-
log(`${header(e)} Calling tool`);
|
|
1680
|
-
if (e.toolCall.skillName === "@perstack/base") {
|
|
1681
|
-
switch (e.toolCall.toolName) {
|
|
1682
|
-
case "think": {
|
|
1683
|
-
const thought = e.toolCall.args.thought;
|
|
1684
|
-
log(`${header(e)} Thought Updated:`);
|
|
1685
|
-
debug(thought);
|
|
1686
|
-
break;
|
|
1687
|
-
}
|
|
1688
|
-
case "readPdfFile": {
|
|
1689
|
-
const path2 = e.toolCall.args.path;
|
|
1690
|
-
log(`${header(e)} Reading PDF: ${path2}`);
|
|
1691
|
-
break;
|
|
1692
|
-
}
|
|
1693
|
-
case "readImageFile": {
|
|
1694
|
-
const path2 = e.toolCall.args.path;
|
|
1695
|
-
log(`${header(e)} Reading Image: ${path2}`);
|
|
1696
|
-
break;
|
|
1697
|
-
}
|
|
1698
|
-
default: {
|
|
1699
|
-
log(`${header(e)} Tool: ${e.toolCall.skillName}/${e.toolCall.toolName}`);
|
|
1700
|
-
debug(`${header(e)} Args: ${JSON.stringify(e.toolCall.args, null, 2)}`);
|
|
1701
|
-
break;
|
|
1702
|
-
}
|
|
1703
|
-
}
|
|
1704
|
-
} else {
|
|
1705
|
-
log(`${header(e)} Tool: ${e.toolCall.skillName}/${e.toolCall.toolName}`);
|
|
1706
|
-
debug(`${header(e)} Args: ${JSON.stringify(e.toolCall.args, null, 2)}`);
|
|
1707
|
-
}
|
|
1708
|
-
break;
|
|
1709
|
-
}
|
|
1710
|
-
case "callInteractiveTool": {
|
|
1711
|
-
log(`${header(e)} Calling interactive tool`);
|
|
1712
|
-
log(`${header(e)} Tool: ${e.toolCall.skillName}/${e.toolCall.toolName}`);
|
|
1713
|
-
debug(`${header(e)} Args: ${JSON.stringify(e.toolCall.args, null, 2)}`);
|
|
1714
|
-
break;
|
|
1715
|
-
}
|
|
1716
|
-
case "callDelegate": {
|
|
1717
|
-
log(`${header(e)} Calling delegate`);
|
|
1718
|
-
log(`${header(e)} Tool: ${e.toolCall.toolName}`);
|
|
1719
|
-
debug(`${header(e)} Args: ${JSON.stringify(e.toolCall.args, null, 2)}`);
|
|
1720
|
-
break;
|
|
1721
|
-
}
|
|
1722
|
-
case "resolveToolResult": {
|
|
1723
|
-
log(`${header(e)} Resolved Tool Result`);
|
|
1724
|
-
if (e.toolResult.skillName === "@perstack/base") {
|
|
1725
|
-
switch (e.toolResult.toolName) {
|
|
1726
|
-
case "todo": {
|
|
1727
|
-
const text = e.toolResult.result.find((r) => r.type === "textPart")?.text;
|
|
1728
|
-
const { todos } = JSON.parse(text ?? "{}");
|
|
1729
|
-
log(`${header(e)} Todo:`);
|
|
1730
|
-
for (const todo of todos) {
|
|
1731
|
-
debug(`${todo.completed ? "[x]" : "[ ]"} ${todo.id}: ${todo.title}`);
|
|
1732
|
-
}
|
|
1733
|
-
break;
|
|
1734
|
-
}
|
|
1735
|
-
default: {
|
|
1736
|
-
log(`${header(e)} Tool: ${e.toolResult.skillName}/${e.toolResult.toolName}`);
|
|
1737
|
-
debug(`${header(e)} Result: ${JSON.stringify(e.toolResult.result, null, 2)}`);
|
|
1738
|
-
break;
|
|
1739
|
-
}
|
|
1740
|
-
}
|
|
1741
|
-
} else {
|
|
1742
|
-
log(`${header(e)} Tool: ${e.toolResult.skillName}/${e.toolResult.toolName}`);
|
|
1743
|
-
debug(`${header(e)} Result: ${JSON.stringify(e.toolResult.result, null, 2)}`);
|
|
1744
|
-
}
|
|
1745
|
-
break;
|
|
1746
|
-
}
|
|
1747
|
-
case "resolveThought": {
|
|
1748
|
-
log(`${header(e)} Resolved Thought:`, e.toolResult);
|
|
1749
|
-
break;
|
|
1750
|
-
}
|
|
1751
|
-
case "resolvePdfFile": {
|
|
1752
|
-
log(`${header(e)} Resolved PDF:`, e.toolResult);
|
|
1753
|
-
break;
|
|
1754
|
-
}
|
|
1755
|
-
case "resolveImageFile": {
|
|
1756
|
-
log(`${header(e)} Resolved Image:`, e.toolResult);
|
|
1757
|
-
break;
|
|
1758
|
-
}
|
|
1759
|
-
case "attemptCompletion": {
|
|
1760
|
-
log(`${header(e)} Attempting completion`);
|
|
1761
|
-
break;
|
|
1762
|
-
}
|
|
1763
|
-
case "completeRun": {
|
|
1764
|
-
logUsage(e);
|
|
1765
|
-
log(`${header(e)} Completing run`);
|
|
1766
|
-
debug(`${header(e)} Result:`, e.text);
|
|
1767
|
-
break;
|
|
1768
|
-
}
|
|
1769
|
-
case "stopRunByInteractiveTool": {
|
|
1770
|
-
logUsage(e);
|
|
1771
|
-
log(`${header(e)} Stopping run by interactive tool`);
|
|
1772
|
-
break;
|
|
1773
|
-
}
|
|
1774
|
-
case "stopRunByDelegate": {
|
|
1775
|
-
logUsage(e);
|
|
1776
|
-
log(`${header(e)} Stopping run by delegate`);
|
|
1777
|
-
break;
|
|
1778
|
-
}
|
|
1779
|
-
case "stopRunByExceededMaxSteps": {
|
|
1780
|
-
logUsage(e);
|
|
1781
|
-
log(`${header(e)} Stopping run by exceeded max steps`);
|
|
1782
|
-
break;
|
|
1783
|
-
}
|
|
1784
|
-
case "continueToNextStep": {
|
|
1785
|
-
logUsage(e);
|
|
1786
|
-
log(`${header(e)} Continuing to next step`);
|
|
1787
|
-
if (e.checkpoint.contextWindowUsage) {
|
|
1788
|
-
log(`${header(e)} Context window usage: ${e.checkpoint.contextWindowUsage.toFixed(2)}%`);
|
|
1789
|
-
}
|
|
1790
|
-
break;
|
|
1791
|
-
}
|
|
1792
|
-
}
|
|
1793
|
-
}
|
|
1794
|
-
function logUsage(e) {
|
|
1795
|
-
const usageByStep = [
|
|
1796
|
-
`In: ${e.step.usage.inputTokens.toLocaleString()}`,
|
|
1797
|
-
`Reasoning: ${e.step.usage.reasoningTokens.toLocaleString()}`,
|
|
1798
|
-
`Out: ${e.step.usage.outputTokens.toLocaleString()}`,
|
|
1799
|
-
`Total: ${e.step.usage.totalTokens.toLocaleString()}`,
|
|
1800
|
-
`Cache-read: ${e.step.usage.cachedInputTokens.toLocaleString()}`
|
|
1801
|
-
].join(", ");
|
|
1802
|
-
const usageByRun = [
|
|
1803
|
-
`In: ${e.checkpoint.usage.inputTokens.toLocaleString()}`,
|
|
1804
|
-
`Reasoning: ${e.checkpoint.usage.reasoningTokens.toLocaleString()}`,
|
|
1805
|
-
`Out: ${e.checkpoint.usage.outputTokens.toLocaleString()}`,
|
|
1806
|
-
`Total: ${e.checkpoint.usage.totalTokens.toLocaleString()}`,
|
|
1807
|
-
`Cache-read: ${e.checkpoint.usage.cachedInputTokens.toLocaleString()}`
|
|
1808
|
-
].join(", ");
|
|
1809
|
-
log(`${header(e)} Tokens usage by step: ${usageByStep}`);
|
|
1810
|
-
log(`${header(e)} Tokens usage by run: ${usageByRun}`);
|
|
1811
|
-
}
|
|
1812
|
-
var RunEventEmitter = class {
|
|
1813
|
-
listeners = [];
|
|
1814
|
-
subscribe(listener) {
|
|
1815
|
-
this.listeners.push(listener);
|
|
1816
|
-
}
|
|
1817
|
-
async emit(event) {
|
|
1818
|
-
for (const listener of this.listeners) {
|
|
1819
|
-
await listener({
|
|
1820
|
-
...event,
|
|
1821
|
-
id: createId(),
|
|
1822
|
-
timestamp: Date.now()
|
|
1823
|
-
});
|
|
1824
|
-
}
|
|
1825
|
-
}
|
|
1826
|
-
};
|
|
1827
|
-
async function resolveExpertToRun(expertKey, experts, clientOptions) {
|
|
1828
|
-
console.log(experts);
|
|
1829
|
-
if (experts[expertKey]) {
|
|
1830
|
-
return experts[expertKey];
|
|
1831
|
-
}
|
|
1832
|
-
const client = new ApiV1Client({
|
|
1833
|
-
baseUrl: clientOptions.perstackApiBaseUrl,
|
|
1834
|
-
apiKey: clientOptions.perstackApiKey
|
|
1835
|
-
});
|
|
1836
|
-
const { expert } = await client.registry.experts.get({ expertKey });
|
|
1837
|
-
experts[expertKey] = toRuntimeExpert(expert);
|
|
1838
|
-
return experts[expertKey];
|
|
1839
|
-
}
|
|
1840
|
-
function toRuntimeExpert(expert) {
|
|
1841
|
-
const skills = Object.fromEntries(
|
|
1842
|
-
Object.entries(expert.skills).map(([name, skill]) => {
|
|
1843
|
-
switch (skill.type) {
|
|
1844
|
-
case "mcpStdioSkill":
|
|
1845
|
-
return [
|
|
1846
|
-
name,
|
|
1847
|
-
{
|
|
1848
|
-
...skill,
|
|
1849
|
-
name
|
|
1850
|
-
}
|
|
1851
|
-
];
|
|
1852
|
-
case "mcpSseSkill":
|
|
1853
|
-
return [
|
|
1854
|
-
name,
|
|
1855
|
-
{
|
|
1856
|
-
...skill,
|
|
1857
|
-
name
|
|
1858
|
-
}
|
|
1859
|
-
];
|
|
1860
|
-
case "interactiveSkill":
|
|
1861
|
-
return [
|
|
1862
|
-
name,
|
|
1863
|
-
{
|
|
1864
|
-
...skill,
|
|
1865
|
-
name
|
|
1866
|
-
}
|
|
1867
|
-
];
|
|
1868
|
-
}
|
|
1869
|
-
})
|
|
1870
|
-
);
|
|
1871
|
-
return {
|
|
1872
|
-
...expert,
|
|
1873
|
-
skills
|
|
1874
|
-
};
|
|
1875
|
-
}
|
|
1732
|
+
var RUNTIME_VERSION = getVersion();
|
|
1876
1733
|
|
|
1877
1734
|
// src/runtime.ts
|
|
1878
1735
|
async function run(runInput, options) {
|
|
1879
1736
|
const runParams = runParamsSchema.parse(runInput);
|
|
1880
|
-
const eventListener = options
|
|
1737
|
+
const eventListener = getEventListener(options);
|
|
1881
1738
|
const retrieveCheckpoint = options?.retrieveCheckpoint ?? defaultRetrieveCheckpoint;
|
|
1882
1739
|
const storeCheckpoint = options?.storeCheckpoint ?? defaultStoreCheckpoint;
|
|
1883
1740
|
const eventEmitter = new RunEventEmitter();
|
|
@@ -1893,8 +1750,27 @@ async function run(runInput, options) {
|
|
|
1893
1750
|
await storeRunSetting(setting);
|
|
1894
1751
|
while (true) {
|
|
1895
1752
|
const { expertToRun, experts } = await setupExperts(setting);
|
|
1896
|
-
|
|
1897
|
-
|
|
1753
|
+
if (options?.eventListener) {
|
|
1754
|
+
const initEvent = createRuntimeEvent("initializeRuntime", setting.runId, {
|
|
1755
|
+
runtimeVersion: RUNTIME_VERSION,
|
|
1756
|
+
expertName: expertToRun.name,
|
|
1757
|
+
experts: Object.keys(experts),
|
|
1758
|
+
model: setting.model,
|
|
1759
|
+
temperature: setting.temperature,
|
|
1760
|
+
maxSteps: setting.maxSteps,
|
|
1761
|
+
maxRetries: setting.maxRetries,
|
|
1762
|
+
timeout: setting.timeout,
|
|
1763
|
+
query: setting.input.text,
|
|
1764
|
+
interactiveToolCall: setting.input.interactiveToolCallResult
|
|
1765
|
+
});
|
|
1766
|
+
options.eventListener(initEvent);
|
|
1767
|
+
}
|
|
1768
|
+
const skillManagers = await getSkillManagers(
|
|
1769
|
+
expertToRun,
|
|
1770
|
+
experts,
|
|
1771
|
+
setting,
|
|
1772
|
+
options?.eventListener
|
|
1773
|
+
);
|
|
1898
1774
|
const runActor = createActor(runtimeStateMachine, {
|
|
1899
1775
|
input: {
|
|
1900
1776
|
setting: {
|
|
@@ -2060,23 +1936,14 @@ async function setupExperts(setting) {
|
|
|
2060
1936
|
}
|
|
2061
1937
|
return { expertToRun, experts };
|
|
2062
1938
|
}
|
|
2063
|
-
function
|
|
2064
|
-
console.log(
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
console.log(`Timeout: ${setting.timeout}`);
|
|
2072
|
-
if (setting.input.text) {
|
|
2073
|
-
console.log(`Query: ${setting.input.text}`);
|
|
2074
|
-
}
|
|
2075
|
-
if (setting.input.interactiveToolCallResult) {
|
|
2076
|
-
console.log(`Tool: ${setting.input.interactiveToolCallResult.toolName}`);
|
|
2077
|
-
console.log(`Tool Call ID: ${setting.input.interactiveToolCallResult.toolCallId}`);
|
|
2078
|
-
console.log(`Tool Result: ${setting.input.interactiveToolCallResult.text}`);
|
|
2079
|
-
}
|
|
1939
|
+
function getEventListener(options) {
|
|
1940
|
+
const listener = options?.eventListener ?? ((e) => console.log(JSON.stringify(e)));
|
|
1941
|
+
return async (event) => {
|
|
1942
|
+
if ("stepNumber" in event) {
|
|
1943
|
+
await defaultStoreEvent(event);
|
|
1944
|
+
}
|
|
1945
|
+
listener(event);
|
|
1946
|
+
};
|
|
2080
1947
|
}
|
|
2081
1948
|
async function storeRunSetting(setting) {
|
|
2082
1949
|
const runDir = getRunDir(setting.runId);
|
|
@@ -2084,20 +1951,16 @@ async function storeRunSetting(setting) {
|
|
|
2084
1951
|
const runSettingPath = path.resolve(runDir, "run-setting.json");
|
|
2085
1952
|
const runSetting = JSON.parse(await readFile(runSettingPath, "utf-8"));
|
|
2086
1953
|
runSetting.updatedAt = Date.now();
|
|
2087
|
-
await writeFile(runSettingPath, JSON.stringify(runSetting
|
|
1954
|
+
await writeFile(runSettingPath, JSON.stringify(runSetting), "utf-8");
|
|
2088
1955
|
} else {
|
|
2089
1956
|
await mkdir(runDir, { recursive: true });
|
|
2090
|
-
await writeFile(
|
|
2091
|
-
path.resolve(runDir, "run-setting.json"),
|
|
2092
|
-
JSON.stringify(setting, null, 2),
|
|
2093
|
-
"utf-8"
|
|
2094
|
-
);
|
|
1957
|
+
await writeFile(path.resolve(runDir, "run-setting.json"), JSON.stringify(setting), "utf-8");
|
|
2095
1958
|
}
|
|
2096
1959
|
}
|
|
2097
1960
|
function getRunDir(runId) {
|
|
2098
1961
|
return `${process.cwd()}/perstack/runs/${runId}`;
|
|
2099
1962
|
}
|
|
2100
1963
|
|
|
2101
|
-
export { StateMachineLogics, calculateContextWindowUsage,
|
|
1964
|
+
export { RUNTIME_VERSION, StateMachineLogics, calculateContextWindowUsage, getContextWindow, getModel, getRunDir, run, runtimeStateMachine };
|
|
2102
1965
|
//# sourceMappingURL=index.js.map
|
|
2103
1966
|
//# sourceMappingURL=index.js.map
|