@perstack/runtime 0.0.92 → 0.0.94
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 +37 -86
- package/dist/bin/cli.js +1 -1
- package/dist/{chunk-SIMOIKWR.js → chunk-ZVUNZKPP.js} +21 -109
- package/dist/chunk-ZVUNZKPP.js.map +1 -0
- package/dist/src/index.d.ts +3 -27
- package/dist/src/index.js +3 -233
- package/dist/src/index.js.map +1 -1
- package/package.json +12 -13
- package/dist/chunk-SIMOIKWR.js.map +0 -1
package/README.md
CHANGED
|
@@ -42,22 +42,26 @@ Output is JSON events (one per line) to stdout.
|
|
|
42
42
|
|
|
43
43
|
## Programmatic Usage
|
|
44
44
|
|
|
45
|
-
The primary entry point is the `run` function. It takes a `
|
|
45
|
+
The primary entry point is the `run` function. It takes a `RunSetting` object and an optional `RunOptions` object.
|
|
46
46
|
|
|
47
47
|
```typescript
|
|
48
48
|
import { run } from "@perstack/runtime"
|
|
49
|
-
import { type
|
|
49
|
+
import { type RunSetting } from "@perstack/core"
|
|
50
50
|
|
|
51
|
-
// Configure the
|
|
52
|
-
const setting:
|
|
51
|
+
// Configure the run
|
|
52
|
+
const setting: RunSetting = {
|
|
53
|
+
model: "claude-sonnet-4-20250514",
|
|
54
|
+
providerConfig: { providerName: "anthropic", apiKey: "..." },
|
|
53
55
|
jobId: "job-123",
|
|
56
|
+
runId: "run-123",
|
|
54
57
|
expertKey: "researcher",
|
|
55
58
|
input: { text: "Research quantum computing" },
|
|
56
|
-
|
|
59
|
+
experts: { /* ... */ },
|
|
60
|
+
// ... other configuration
|
|
57
61
|
}
|
|
58
62
|
|
|
59
63
|
// Execute the job
|
|
60
|
-
const
|
|
64
|
+
const finalCheckpoint = await run({ setting }, {
|
|
61
65
|
eventListener: (event) => {
|
|
62
66
|
console.log(`[${event.type}]`, event)
|
|
63
67
|
}
|
|
@@ -243,28 +247,35 @@ The runtime ensures deterministic execution through a strictly defined state mac
|
|
|
243
247
|
stateDiagram-v2
|
|
244
248
|
[*] --> Init
|
|
245
249
|
Init --> PreparingForStep: startRun
|
|
250
|
+
Init --> ResumingFromStop: resumeFromStop
|
|
251
|
+
|
|
246
252
|
PreparingForStep --> GeneratingToolCall: startGeneration
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
253
|
+
|
|
254
|
+
ResumingFromStop --> CallingInteractiveTools: proceedToInteractiveTools
|
|
255
|
+
ResumingFromStop --> ResolvingToolResult: resolveToolResults
|
|
256
|
+
|
|
257
|
+
GeneratingToolCall --> CallingMcpTools: callTools
|
|
251
258
|
GeneratingToolCall --> FinishingStep: retry
|
|
259
|
+
GeneratingToolCall --> Stopped: stopRunByError
|
|
260
|
+
GeneratingToolCall --> Stopped: completeRun
|
|
252
261
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
CallingTools --> CallingInteractiveTool: callInteractiveTool
|
|
262
|
+
CallingMcpTools --> ResolvingToolResult: resolveToolResults
|
|
263
|
+
CallingMcpTools --> GeneratingRunResult: attemptCompletion
|
|
264
|
+
CallingMcpTools --> CallingDelegates: finishMcpTools
|
|
265
|
+
CallingMcpTools --> Stopped: completeRun
|
|
258
266
|
|
|
259
|
-
|
|
260
|
-
|
|
267
|
+
CallingDelegates --> Stopped: stopRunByDelegate
|
|
268
|
+
CallingDelegates --> CallingInteractiveTools: skipDelegates
|
|
269
|
+
|
|
270
|
+
CallingInteractiveTools --> Stopped: stopRunByInteractiveTool
|
|
271
|
+
CallingInteractiveTools --> ResolvingToolResult: resolveToolResults
|
|
272
|
+
|
|
273
|
+
ResolvingToolResult --> FinishingStep: finishToolCall
|
|
261
274
|
|
|
262
275
|
GeneratingRunResult --> Stopped: completeRun
|
|
263
276
|
GeneratingRunResult --> FinishingStep: retry
|
|
277
|
+
GeneratingRunResult --> Stopped: stopRunByError
|
|
264
278
|
|
|
265
|
-
CallingInteractiveTool --> Stopped: stopRunByInteractiveTool
|
|
266
|
-
CallingDelegate --> Stopped: stopRunByDelegate
|
|
267
|
-
|
|
268
279
|
FinishingStep --> PreparingForStep: continueToNextStep
|
|
269
280
|
FinishingStep --> Stopped: stopRunByExceededMaxSteps
|
|
270
281
|
```
|
|
@@ -272,12 +283,11 @@ stateDiagram-v2
|
|
|
272
283
|
### Events
|
|
273
284
|
Events trigger state transitions. They are emitted by the runtime logic or external inputs.
|
|
274
285
|
|
|
275
|
-
- **Lifecycle**: `startRun`, `startGeneration`, `continueToNextStep`, `completeRun`
|
|
276
|
-
- **Tool Execution**: `callTools`, `resolveToolResults`, `finishToolCall`, `
|
|
277
|
-
- **
|
|
278
|
-
- **
|
|
279
|
-
- **
|
|
280
|
-
- **Interruption**: `stopRunByInteractiveTool`, `stopRunByDelegate`, `stopRunByExceededMaxSteps`
|
|
286
|
+
- **Lifecycle**: `startRun`, `resumeFromStop`, `startGeneration`, `continueToNextStep`, `completeRun`
|
|
287
|
+
- **Tool Execution**: `callTools`, `resolveToolResults`, `finishToolCall`, `finishMcpTools`, `attemptCompletion`
|
|
288
|
+
- **Delegation**: `skipDelegates` (internal state transition)
|
|
289
|
+
- **Interactive**: `proceedToInteractiveTools` (for resuming to interactive tools)
|
|
290
|
+
- **Interruption**: `stopRunByInteractiveTool`, `stopRunByDelegate`, `stopRunByExceededMaxSteps`, `stopRunByError`
|
|
281
291
|
- **Error Handling**: `retry`
|
|
282
292
|
|
|
283
293
|
## Checkpoint Status
|
|
@@ -287,71 +297,12 @@ The `status` field in a Checkpoint indicates the current state:
|
|
|
287
297
|
- `init`, `proceeding` — Run lifecycle
|
|
288
298
|
- `completed` — Task finished successfully
|
|
289
299
|
- `stoppedByInteractiveTool`, `stoppedByDelegate` — Waiting for external input
|
|
290
|
-
- `stoppedByExceededMaxSteps`, `stoppedByError` — Run stopped
|
|
300
|
+
- `stoppedByExceededMaxSteps`, `stoppedByError`, `stoppedByCancellation` — Run stopped
|
|
291
301
|
|
|
292
302
|
For stop reasons and error handling, see [Error Handling](https://github.com/perstack-ai/perstack/blob/main/docs/using-experts/error-handling.md).
|
|
293
303
|
|
|
294
|
-
## Runtime Adapters
|
|
295
|
-
|
|
296
|
-
The runtime supports multiple execution backends through the adapter pattern. External runtime adapters are provided as separate packages:
|
|
297
|
-
|
|
298
|
-
| Package | Runtime Name | Description |
|
|
299
|
-
| ----------------------- | ------------- | ---------------------------------- |
|
|
300
|
-
| `@perstack/docker` | `docker` | Docker containerized (default) |
|
|
301
|
-
| `@perstack/runtime` | `local` | Built-in runtime without isolation |
|
|
302
|
-
| `@perstack/cursor` | `cursor` | Cursor IDE headless mode |
|
|
303
|
-
| `@perstack/claude-code` | `claude-code` | Claude Code CLI |
|
|
304
|
-
| `@perstack/gemini` | `gemini` | Gemini CLI |
|
|
305
|
-
|
|
306
|
-
### Registration Pattern
|
|
307
|
-
|
|
308
|
-
External adapters must be registered before use:
|
|
309
|
-
|
|
310
|
-
```typescript
|
|
311
|
-
import { CursorAdapter } from "@perstack/cursor"
|
|
312
|
-
import { getAdapter, isAdapterAvailable, registerAdapter } from "@perstack/runtime"
|
|
313
|
-
|
|
314
|
-
// Register external adapter
|
|
315
|
-
registerAdapter("cursor", () => new CursorAdapter())
|
|
316
|
-
|
|
317
|
-
// Check availability
|
|
318
|
-
if (isAdapterAvailable("cursor")) {
|
|
319
|
-
const adapter = getAdapter("cursor")
|
|
320
|
-
const result = await adapter.checkPrerequisites()
|
|
321
|
-
if (result.ok) {
|
|
322
|
-
await adapter.run({ setting, eventListener })
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
```
|
|
326
|
-
|
|
327
|
-
### Creating Custom Adapters
|
|
328
|
-
|
|
329
|
-
Extend `BaseAdapter` from `@perstack/core` for CLI-based runtimes:
|
|
330
|
-
|
|
331
|
-
```typescript
|
|
332
|
-
import { BaseAdapter, type AdapterRunParams, type AdapterRunResult, type PrerequisiteResult } from "@perstack/core"
|
|
333
|
-
|
|
334
|
-
class MyAdapter extends BaseAdapter {
|
|
335
|
-
readonly name = "my-runtime"
|
|
336
|
-
|
|
337
|
-
async checkPrerequisites(): Promise<PrerequisiteResult> {
|
|
338
|
-
const result = await this.execCommand(["my-cli", "--version"])
|
|
339
|
-
return result.exitCode === 0
|
|
340
|
-
? { ok: true }
|
|
341
|
-
: { ok: false, error: { type: "cli-not-found", message: "..." } }
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
async run(params: AdapterRunParams): Promise<AdapterRunResult> {
|
|
345
|
-
// Implementation
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
```
|
|
349
|
-
|
|
350
|
-
See [Multi-Runtime Support](https://github.com/perstack-ai/perstack/blob/main/docs/using-experts/multi-runtime.md) for details.
|
|
351
|
-
|
|
352
304
|
## Related Documentation
|
|
353
305
|
|
|
354
306
|
- [Runtime](https://github.com/perstack-ai/perstack/blob/main/docs/understanding-perstack/runtime.md) — Full execution model
|
|
355
307
|
- [State Management](https://github.com/perstack-ai/perstack/blob/main/docs/using-experts/state-management.md) — Jobs, Runs, and Checkpoints
|
|
356
308
|
- [Running Experts](https://github.com/perstack-ai/perstack/blob/main/docs/using-experts/running-experts.md) — CLI usage
|
|
357
|
-
- [Multi-Runtime](https://github.com/perstack-ai/perstack/blob/main/docs/using-experts/multi-runtime.md) — Multi-runtime support
|
package/dist/bin/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { package_default, findLockfile, loadLockfile, run } from '../chunk-
|
|
2
|
+
import { package_default, findLockfile, loadLockfile, run } from '../chunk-ZVUNZKPP.js';
|
|
3
3
|
import '../chunk-RG4QHAGG.js';
|
|
4
4
|
import { parseWithFriendlyError, runCommandInputSchema, validateEventFilter, createFilteredEventListener, perstackConfigSchema } from '@perstack/core';
|
|
5
5
|
import { Command } from 'commander';
|
|
@@ -3,6 +3,7 @@ import { readFileSync } from 'fs';
|
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import { parseWithFriendlyError, lockfileSchema, runParamsSchema, createRuntimeEvent, knownModels, stopRunByExceededMaxSteps, continueToNextStep, stopRunByError, retry, createStreamingEvent, completeRun, finishToolCall, resolveToolResults, stopRunByInteractiveTool, skipDelegates, stopRunByDelegate, attemptCompletion, finishMcpTools, callTools, proceedToInteractiveTools, startGeneration, startRun, resumeFromStop } from '@perstack/core';
|
|
5
5
|
import TOML from 'smol-toml';
|
|
6
|
+
import { createId } from '@paralleldrive/cuid2';
|
|
6
7
|
import { createAmazonBedrock } from '@ai-sdk/amazon-bedrock';
|
|
7
8
|
import { createAnthropic } from '@ai-sdk/anthropic';
|
|
8
9
|
import { createAzure } from '@ai-sdk/azure';
|
|
@@ -12,7 +13,6 @@ import { createVertex } from '@ai-sdk/google-vertex';
|
|
|
12
13
|
import { createOpenAI } from '@ai-sdk/openai';
|
|
13
14
|
import { createOllama } from 'ollama-ai-provider-v2';
|
|
14
15
|
import { ProxyAgent, fetch } from 'undici';
|
|
15
|
-
import { createId } from '@paralleldrive/cuid2';
|
|
16
16
|
import { setup, assign, createActor } from 'xstate';
|
|
17
17
|
import { readFile } from 'fs/promises';
|
|
18
18
|
import { dedent } from 'ts-dedent';
|
|
@@ -21,7 +21,7 @@ import { APICallError, generateText, streamText } from 'ai';
|
|
|
21
21
|
// package.json
|
|
22
22
|
var package_default = {
|
|
23
23
|
name: "@perstack/runtime",
|
|
24
|
-
version: "0.0.
|
|
24
|
+
version: "0.0.94",
|
|
25
25
|
description: "Perstack Runtime",
|
|
26
26
|
author: "Wintermute Technologies, Inc.",
|
|
27
27
|
license: "Apache-2.0",
|
|
@@ -75,7 +75,6 @@ var package_default = {
|
|
|
75
75
|
xstate: "^5.25.1"
|
|
76
76
|
},
|
|
77
77
|
devDependencies: {
|
|
78
|
-
"@perstack/adapter-base": "workspace:*",
|
|
79
78
|
"@perstack/anthropic-provider": "workspace:*",
|
|
80
79
|
"@perstack/azure-openai-provider": "workspace:*",
|
|
81
80
|
"@perstack/bedrock-provider": "workspace:*",
|
|
@@ -146,107 +145,6 @@ function getLockfileExpertToolDefinitions(lockfileExpert) {
|
|
|
146
145
|
}
|
|
147
146
|
return result;
|
|
148
147
|
}
|
|
149
|
-
function createProxyFetch(proxyUrl) {
|
|
150
|
-
const agent = new ProxyAgent(proxyUrl);
|
|
151
|
-
return (input, init) => {
|
|
152
|
-
return fetch(input, { ...init, dispatcher: agent });
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
function getModel(modelId, providerConfig, options) {
|
|
156
|
-
const customFetch = options?.proxyUrl ? createProxyFetch(options.proxyUrl) : void 0;
|
|
157
|
-
switch (providerConfig.providerName) {
|
|
158
|
-
case "anthropic": {
|
|
159
|
-
const anthropic = createAnthropic({
|
|
160
|
-
apiKey: providerConfig.apiKey,
|
|
161
|
-
baseURL: providerConfig.baseUrl,
|
|
162
|
-
headers: providerConfig.headers,
|
|
163
|
-
fetch: customFetch
|
|
164
|
-
});
|
|
165
|
-
return anthropic(modelId);
|
|
166
|
-
}
|
|
167
|
-
case "google": {
|
|
168
|
-
const google = createGoogleGenerativeAI({
|
|
169
|
-
apiKey: providerConfig.apiKey,
|
|
170
|
-
baseURL: providerConfig.baseUrl,
|
|
171
|
-
headers: providerConfig.headers,
|
|
172
|
-
fetch: customFetch
|
|
173
|
-
});
|
|
174
|
-
return google(modelId);
|
|
175
|
-
}
|
|
176
|
-
case "openai": {
|
|
177
|
-
const openai = createOpenAI({
|
|
178
|
-
apiKey: providerConfig.apiKey,
|
|
179
|
-
baseURL: providerConfig.baseUrl,
|
|
180
|
-
organization: providerConfig.organization,
|
|
181
|
-
project: providerConfig.project,
|
|
182
|
-
name: providerConfig.name,
|
|
183
|
-
headers: providerConfig.headers,
|
|
184
|
-
fetch: customFetch
|
|
185
|
-
});
|
|
186
|
-
return openai(modelId);
|
|
187
|
-
}
|
|
188
|
-
case "ollama": {
|
|
189
|
-
const ollama = createOllama({
|
|
190
|
-
baseURL: providerConfig.baseUrl,
|
|
191
|
-
headers: providerConfig.headers,
|
|
192
|
-
fetch: customFetch
|
|
193
|
-
});
|
|
194
|
-
return ollama(modelId);
|
|
195
|
-
}
|
|
196
|
-
case "azure-openai": {
|
|
197
|
-
const azure = createAzure({
|
|
198
|
-
apiKey: providerConfig.apiKey,
|
|
199
|
-
resourceName: providerConfig.resourceName,
|
|
200
|
-
apiVersion: providerConfig.apiVersion,
|
|
201
|
-
baseURL: providerConfig.baseUrl,
|
|
202
|
-
headers: providerConfig.headers,
|
|
203
|
-
useDeploymentBasedUrls: providerConfig.useDeploymentBasedUrls,
|
|
204
|
-
fetch: customFetch
|
|
205
|
-
});
|
|
206
|
-
return azure(modelId);
|
|
207
|
-
}
|
|
208
|
-
case "amazon-bedrock": {
|
|
209
|
-
const amazonBedrock = createAmazonBedrock({
|
|
210
|
-
accessKeyId: providerConfig.accessKeyId,
|
|
211
|
-
secretAccessKey: providerConfig.secretAccessKey,
|
|
212
|
-
region: providerConfig.region,
|
|
213
|
-
sessionToken: providerConfig.sessionToken,
|
|
214
|
-
fetch: customFetch
|
|
215
|
-
});
|
|
216
|
-
return amazonBedrock(modelId);
|
|
217
|
-
}
|
|
218
|
-
case "google-vertex": {
|
|
219
|
-
const vertex = createVertex({
|
|
220
|
-
project: providerConfig.project,
|
|
221
|
-
location: providerConfig.location,
|
|
222
|
-
baseURL: providerConfig.baseUrl,
|
|
223
|
-
headers: providerConfig.headers,
|
|
224
|
-
fetch: customFetch
|
|
225
|
-
});
|
|
226
|
-
return vertex(modelId);
|
|
227
|
-
}
|
|
228
|
-
case "deepseek": {
|
|
229
|
-
const deepseek = createDeepSeek({
|
|
230
|
-
apiKey: providerConfig.apiKey,
|
|
231
|
-
baseURL: providerConfig.baseUrl,
|
|
232
|
-
headers: providerConfig.headers,
|
|
233
|
-
fetch: customFetch
|
|
234
|
-
});
|
|
235
|
-
return deepseek(modelId);
|
|
236
|
-
}
|
|
237
|
-
default: {
|
|
238
|
-
const _exhaustive = providerConfig;
|
|
239
|
-
throw new Error(`Unknown provider: ${_exhaustive.providerName}`);
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
function getContextWindow(providerName, modelId) {
|
|
244
|
-
const modelConfig = knownModels.find((model) => model.provider === providerName)?.models.find((model) => model.name === modelId);
|
|
245
|
-
return modelConfig?.contextWindow;
|
|
246
|
-
}
|
|
247
|
-
function calculateContextWindowUsage(usage, contextWindow) {
|
|
248
|
-
return (usage.inputTokens + usage.cachedInputTokens + usage.outputTokens) / contextWindow;
|
|
249
|
-
}
|
|
250
148
|
|
|
251
149
|
// src/helpers/usage.ts
|
|
252
150
|
function createEmptyUsage() {
|
|
@@ -345,6 +243,13 @@ function buildDelegationReturnState(currentSetting, resultCheckpoint, parentChec
|
|
|
345
243
|
}
|
|
346
244
|
};
|
|
347
245
|
}
|
|
246
|
+
function getContextWindow(providerName, modelId) {
|
|
247
|
+
const modelConfig = knownModels.find((model) => model.provider === providerName)?.models.find((model) => model.name === modelId);
|
|
248
|
+
return modelConfig?.contextWindow;
|
|
249
|
+
}
|
|
250
|
+
function calculateContextWindowUsage(usage, contextWindow) {
|
|
251
|
+
return (usage.inputTokens + usage.cachedInputTokens + usage.outputTokens) / contextWindow;
|
|
252
|
+
}
|
|
348
253
|
|
|
349
254
|
// src/helpers/runtime-version.ts
|
|
350
255
|
function parseRuntimeVersion(version) {
|
|
@@ -2035,7 +1940,11 @@ var StateMachineCoordinator = class {
|
|
|
2035
1940
|
if (!shouldContinue) {
|
|
2036
1941
|
this.actor?.stop();
|
|
2037
1942
|
await this.closeManagers(runState.context.skillManagers);
|
|
2038
|
-
|
|
1943
|
+
const cancelledCheckpoint = {
|
|
1944
|
+
...runState.context.checkpoint,
|
|
1945
|
+
status: "stoppedByCancellation"
|
|
1946
|
+
};
|
|
1947
|
+
this.resolvePromise?.(cancelledCheckpoint);
|
|
2039
1948
|
return;
|
|
2040
1949
|
}
|
|
2041
1950
|
}
|
|
@@ -3654,7 +3563,6 @@ var SingleRunExecutor = class {
|
|
|
3654
3563
|
if (!this.options.eventListener) return;
|
|
3655
3564
|
const initEvent = createRuntimeEvent("initializeRuntime", setting.jobId, setting.runId, {
|
|
3656
3565
|
runtimeVersion: package_default.version,
|
|
3657
|
-
runtime: "local",
|
|
3658
3566
|
expertName: expertToRun.name,
|
|
3659
3567
|
experts: Object.keys(experts),
|
|
3660
3568
|
model: setting.model,
|
|
@@ -3762,12 +3670,16 @@ async function run(runInput, options) {
|
|
|
3762
3670
|
storeJob({ ...job, status: "stoppedByError", finishedAt: Date.now() });
|
|
3763
3671
|
return resultCheckpoint;
|
|
3764
3672
|
}
|
|
3673
|
+
case "stoppedByCancellation": {
|
|
3674
|
+
storeJob({ ...job, status: "stoppedByCancellation", finishedAt: Date.now() });
|
|
3675
|
+
return resultCheckpoint;
|
|
3676
|
+
}
|
|
3765
3677
|
default:
|
|
3766
3678
|
throw new Error("Run stopped by unknown reason");
|
|
3767
3679
|
}
|
|
3768
3680
|
}
|
|
3769
3681
|
}
|
|
3770
3682
|
|
|
3771
|
-
export { findLockfile, getLockfileExpertToolDefinitions,
|
|
3772
|
-
//# sourceMappingURL=chunk-
|
|
3773
|
-
//# sourceMappingURL=chunk-
|
|
3683
|
+
export { findLockfile, getLockfileExpertToolDefinitions, loadLockfile, package_default, run, runtimeStateMachine };
|
|
3684
|
+
//# sourceMappingURL=chunk-ZVUNZKPP.js.map
|
|
3685
|
+
//# sourceMappingURL=chunk-ZVUNZKPP.js.map
|