@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 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 `JobSetting` object and an optional `RunOptions` object.
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 JobSetting } from "@perstack/core"
49
+ import { type RunSetting } from "@perstack/core"
50
50
 
51
- // Configure the job
52
- const setting: JobSetting = {
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
- // ... configuration for model, experts, etc.
59
+ experts: { /* ... */ },
60
+ // ... other configuration
57
61
  }
58
62
 
59
63
  // Execute the job
60
- const finalJob = await run({ setting }, {
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
- PreparingForStep --> CallingTools: resumeToolCalls
248
- PreparingForStep --> FinishingStep: finishAllToolCalls
249
-
250
- GeneratingToolCall --> CallingTools: callTools
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
- CallingTools --> ResolvingToolResults: resolveToolResults
254
- CallingTools --> ResolvingThought: resolveThought
255
- CallingTools --> GeneratingRunResult: attemptCompletion
256
- CallingTools --> CallingDelegate: callDelegates
257
- CallingTools --> CallingInteractiveTool: callInteractiveTool
262
+ CallingMcpTools --> ResolvingToolResult: resolveToolResults
263
+ CallingMcpTools --> GeneratingRunResult: attemptCompletion
264
+ CallingMcpTools --> CallingDelegates: finishMcpTools
265
+ CallingMcpTools --> Stopped: completeRun
258
266
 
259
- ResolvingToolResults --> FinishingStep: finishToolCall
260
- ResolvingThought --> FinishingStep: finishToolCall
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`, `resumeToolCalls`, `finishAllToolCalls`
277
- - **Special Types**: `resolveThought`
278
- - **Delegation**: `callDelegate` (triggers new Run(s) for delegate(s), parallel when multiple)
279
- - **Interactive**: `callInteractiveTool` (Coordinator only)
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-SIMOIKWR.js';
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.92",
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
- this.resolvePromise?.(runState.context.checkpoint);
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, getModel, loadLockfile, package_default, run, runtimeStateMachine };
3772
- //# sourceMappingURL=chunk-SIMOIKWR.js.map
3773
- //# sourceMappingURL=chunk-SIMOIKWR.js.map
3683
+ export { findLockfile, getLockfileExpertToolDefinitions, loadLockfile, package_default, run, runtimeStateMachine };
3684
+ //# sourceMappingURL=chunk-ZVUNZKPP.js.map
3685
+ //# sourceMappingURL=chunk-ZVUNZKPP.js.map