@parcha/agentrun-pi 0.1.0-beta.1 → 0.1.0-beta.3

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 (44) hide show
  1. package/README.md +69 -27
  2. package/dist/cli.js +5 -3
  3. package/dist/demo.js +1 -0
  4. package/dist/extension-service.js +12 -4
  5. package/dist/extension.js +329 -57
  6. package/dist/host-addendum.d.ts +4 -0
  7. package/dist/host-addendum.js +19 -0
  8. package/dist/index.d.ts +1 -2
  9. package/dist/index.js +1 -2
  10. package/dist/presentation.js +2 -2
  11. package/dist/skills/author/SKILL.md +135 -0
  12. package/{skills → dist/skills}/author/references/jev-decisions.md +9 -8
  13. package/dist/skills/author/references/language.md +128 -0
  14. package/dist/skills/author/references/sdk-authoring.md +9 -0
  15. package/{skills → dist/skills}/author/references/workflow-format.md +7 -15
  16. package/dist/triage-demo.d.ts +62 -0
  17. package/dist/triage-demo.js +153 -0
  18. package/dist/types.d.ts +3 -0
  19. package/dist/workflow-inspector.d.ts +47 -0
  20. package/dist/workflow-inspector.js +235 -0
  21. package/dist/workflow-session.d.ts +19 -0
  22. package/dist/workflow-session.js +167 -0
  23. package/dist/workflow-store.d.ts +30 -0
  24. package/dist/workflow-store.js +249 -0
  25. package/dist/workflow-view.d.ts +64 -0
  26. package/dist/workflow-view.js +268 -0
  27. package/package.json +5 -6
  28. package/dist/admission.d.ts +0 -6
  29. package/dist/admission.js +0 -51
  30. package/dist/author.d.ts +0 -21
  31. package/dist/author.js +0 -72
  32. package/dist/skill-bundle.d.ts +0 -5
  33. package/dist/skill-bundle.js +0 -15
  34. package/skills/author/SKILL.md +0 -102
  35. package/skills/author/references/sdk-authoring.md +0 -16
  36. /package/{skills → dist/skills}/author/examples/evidence-gate.input.json +0 -0
  37. /package/{skills → dist/skills}/author/examples/evidence-gate.json +0 -0
  38. /package/{skills → dist/skills}/author/examples/read-file.input.json +0 -0
  39. /package/{skills → dist/skills}/author/examples/read-file.json +0 -0
  40. /package/{skills → dist/skills}/author/examples/read-source-decision.input.json +0 -0
  41. /package/{skills → dist/skills}/author/examples/read-source-decision.json +0 -0
  42. /package/{skills → dist/skills}/author/examples/release-note.txt +0 -0
  43. /package/{skills → dist/skills}/author/examples/review-release-notes.input.json +0 -0
  44. /package/{skills → dist/skills}/author/examples/review-release-notes.json +0 -0
package/README.md CHANGED
@@ -1,25 +1,25 @@
1
1
  # agent.run() + Pi
2
2
 
3
- Describe a task in Pi. AgentRun turns it into a workflow you can inspect and runs its steps using your current Pi model. Requires Node 22.19+ and Pi 0.87.0.
3
+ Describe a task in Pi, inspect the workflow, run it with your current model, and save its definition for new input. Requires Node 22.19+ and Pi 0.87.0.
4
4
 
5
- ## Install from source
5
+ ## Install
6
6
 
7
- Build the extension and use the included Pi CLI. From a new terminal:
7
+ If you do not have Pi, install the tested host version first:
8
8
 
9
9
  ```sh
10
- git clone --branch main --single-branch https://github.com/Parcha-ai/agentrun.git
11
- cd agentrun
12
- npm ci --ignore-scripts
13
- npm run build
14
- ./node_modules/.bin/pi install ./packages/pi -l
15
- ./node_modules/.bin/pi --offline
10
+ npm install -g @earendil-works/pi-coding-agent@0.87.0
16
11
  ```
17
12
 
18
- `-l` writes project settings in `.pi/settings.json`. Omit it to install for all your Pi sessions. `--offline` skips startup downloads; it does not disable model calls.
13
+ Then, in your project:
14
+
15
+ ```sh
16
+ pi install npm:@parcha/agentrun-pi@0.1.0-beta.3 -l
17
+ pi --offline
18
+ ```
19
19
 
20
- On first launch, Pi asks whether you trust the project before loading its extension. Review the checkout before accepting.
20
+ `-l` writes project settings in `.pi/settings.json`. Omit it to install for all your Pi sessions. `--offline` skips startup downloads; it does not disable model calls. No AgentRun checkout or build is needed.
21
21
 
22
- Already built this checkout? Start at the `pi install` line. The included CLI is the tested Pi 0.87.0 version; a global Pi installation is unnecessary. If Pi 0.87.0 is already open, use `/reload`. Keep this checkout: Pi loads the extension and skill from it. Rebuild after source changes, then reload. `/reload` clears the current workflow definition; run the demo or describe your task again to create one.
22
+ On first launch, Pi asks whether you trust the project before loading its extension. If Pi is already open, use `/reload`. The current draft is restored from a persisted Pi session branch when available; named definition saves are stored separately.
23
23
 
24
24
  For live tasks, configure model access in Pi first. AgentRun uses Pi's current model and authentication; it needs no separate model configuration. The scripted demo below works without provider access.
25
25
 
@@ -31,30 +31,53 @@ Try the bundled example inside Pi:
31
31
 
32
32
  The demo shows the workflow graph, progress, and a completed result with call counts. It uses scripted responses over fictional sources. It makes no model calls and does not test model quality. Run `/agentrun status` to check the loaded skill and Pi host version. The tested version is 0.87.0; status flags a different host without blocking it. Missing Pi or Jev access does not prevent the scripted demo. To repeat it, run `/agentrun run` or `/agentrun demo`. A scripted demo stays scripted on rerun, including its missing-evidence path. Use `/agentrun demo live` to switch to real Pi and Jev calls. Workflows authored by Pi use real adapters.
33
33
 
34
- For an offline Pi startup, use `./node_modules/.bin/pi --offline`. Without that flag, Pi may download optional command-line tools on first launch. This is separate from the scripted demo, which makes no network calls.
34
+ For an offline Pi startup, use `pi --offline`. Without that flag, Pi may download optional command-line tools on first launch. This is separate from the scripted demo, which makes no network calls.
35
+
36
+ ## Preview, run, save, reuse
37
+
38
+ ```text
39
+ /agentrun Preview a reusable workflow that identifies breaking changes and migration actions in supplied release notes. Do not run it yet.
40
+ ```
41
+
42
+ The command loads the `agentrun-author` skill. Its source ships in `@parcha/agentrun-dsl`; this package registers it rendered with the Pi host rules. A preview validates and displays the graph without running it. Ask Pi to run when ready, or use `/agentrun run`. You can also invoke `/skill:agentrun-author <task>` directly.
43
+
44
+ Open `/agentrun` to inspect the graph in the native terminal UI. Select a stage to see its contract, instructions or criteria, and observed evidence. The Actions page offers run, input, edit, save, load, and history. Arrow keys navigate, Enter inspects, `a` opens Actions, and Escape goes back or closes the view. Closing the inspector does not cancel execution; non-TUI hosts receive a text view.
35
45
 
36
- ## Describe, inspect, run
46
+ After inspecting a definition, save it and reuse it in a new Pi session in the same project:
37
47
 
38
48
  ```text
39
- /agentrun Find the main entry points in this repository and summarize how requests reach them.
49
+ /agentrun input The release note says requests now require X-Workspace.
50
+ /agentrun run
51
+ /agentrun save release-review
40
52
  ```
41
53
 
42
- The command loads the packaged `agentrun-author` skill. Pi reads the available tools, builds a workflow, inspects its graph, then runs it with the task's input. You can also invoke `/skill:agentrun-author <task>` directly. Ask Pi to change a step or explain a result as you would in an ordinary conversation.
54
+ ```text
55
+ /agentrun load release-review
56
+ /agentrun input The next release removes /events; clients must use /v2/events.
57
+ /agentrun run
58
+ ```
59
+
60
+ Loading starts with empty input and does not execute. A save retains the definition, not input or execution permission. Scripted demo adapters are not saved: loading a saved demo uses live adapters and requires the corresponding model and Jev access. Each run restarts with the current input and model; it is not checkpoint resume.
43
61
 
44
62
  | Command | What happens |
45
63
  | --- | --- |
46
- | `/agentrun <task>` | Ask Pi to build, inspect, and run a workflow for the task. |
64
+ | `/agentrun <task>` | Ask Pi to author, edit, or run; say when you want a preview only. |
47
65
  | `/agentrun help` | List commands and demo modes. |
48
- | `/agentrun` | Show the current workflow, or help if there is none. |
66
+ | `/agentrun` | Inspect the current workflow, or show help if there is none. |
67
+ | `/agentrun input <case or JSON>` | Set new input without changing the definition or running it. |
49
68
  | `/agentrun run` | Repeat the current workflow with its last supplied input. Scripted demos stay scripted; authored workflows use real adapters. |
69
+ | `/agentrun save <name>` | Save an immutable, project-local definition revision. |
70
+ | `/agentrun load <name> [digest]` | Load the newest or exact revision; input starts empty. |
71
+ | `/agentrun list` | List saved revisions. |
72
+ | `/agentrun history` | Inspect retained run receipts on this Pi branch. |
50
73
  | `/agentrun status` | Check skill discovery, active Pi selection, and Jev configuration without making provider calls. |
51
74
  | `/agentrun stop` | Request cancellation of the running workflow. |
52
75
 
53
- A progress widget shows active steps and the number finished. Results appear in Pi, with full output and events in the structured result.
76
+ A progress widget shows active steps and the number finished. Results distinguish completion, escalation, failure, and interruption. Decision records show supplied evidence, criteria, answer, and route, not hidden reasoning or proof of correctness.
54
77
 
55
78
  Pi 0.87.0 cannot export a fresh session containing only slash-command results. To save an offline research receipt from the checkout, run `node examples/research-live.mjs --out research-result.json`. This runs the scripted example again and writes its result; it does not export the Pi session.
56
79
 
57
- One workflow runs at a time. Definitions and run state belong to the current Pi session; switching sessions or closing Pi does not create a saved workflow library. Named saves and reuse across sessions are planned for V2. This extension does not support them.
80
+ One workflow runs at a time. Named definitions are durable across sessions in the same project. Pi run receipts belong to the current branch and may remain in memory until Pi persists its session; saving a definition does not save a receipt.
58
81
 
59
82
  ### Three demo modes
60
83
 
@@ -64,7 +87,7 @@ One workflow runs at a time. Definitions and run state belong to the current Pi
64
87
  | `/agentrun demo empty` | Scripted insufficient-evidence path, without model calls. |
65
88
  | `/agentrun demo live` | Real Pi agent steps and Jev system one decisions over the same fictional sources. |
66
89
 
67
- Live mode uses your active Pi model and requires configured TypeSafe access for Jev. It still does not search the web or prove accuracy on real research. See the [Jev adapter configuration](../jev/README.md). Live calls can incur usage charges; scripted mode needs no provider access.
90
+ Live mode uses your active Pi model and requires configured TypeSafe access for Jev. It still does not search the web or prove accuracy on real research. See the [Jev adapter configuration](https://github.com/Parcha-ai/agentrun/tree/main/packages/jev#readme). Live calls can incur usage charges; scripted mode needs no provider access.
68
91
 
69
92
  ## Tools and execution
70
93
 
@@ -81,7 +104,7 @@ A direct `call` to a Pi built-in returns a Pi tool result. Its `content` is an a
81
104
  Jev design guidance is bundled with the author skill and returned by `describe`
82
105
  under `authoring.jev`, including for hosts without a file-reading tool. No separate
83
106
  TypeSafe skill install is required for DSL authoring. The
84
- [source-read example](skills/author/examples/read-source-decision.json) preserves
107
+ [source-read example](../dsl/skills/author/examples/read-source-decision.json) preserves
85
108
  original tool evidence through a Jev decision and deterministic projection; its
86
109
  fictional tests demonstrate wiring, not measured semantic accuracy. Explicit
87
110
  `tools: []` disables tools for an agent node; omission inherits the host allowlist.
@@ -174,35 +197,54 @@ The child model delivers `{value: result}` through its `submit` tool. Schema and
174
197
 
175
198
  ## SDK: retain candidates and check fixed fixtures
176
199
 
177
- The SDK author saves candidate files separately from the native extension's session-local workflow. Supply configured runner options and host-owned acceptance checks:
200
+ `authorWorkflow` lives in `@parcha/agentrun-dsl` beside the language it teaches. It saves candidate files separately from the native extension's current draft and named procedure revisions. Give it a Pi runner with no host tools, and bound its submissions by the candidate limit:
178
201
 
179
202
  ```js
180
- import { authorWorkflow } from '@parcha/agentrun-pi';
203
+ import { authorWorkflow } from '@parcha/agentrun-dsl';
204
+ import { createPiRunner } from '@parcha/agentrun-pi';
181
205
 
182
206
  const candidate = await authorWorkflow({
183
207
  request: 'Extract a numeric count from text',
184
208
  outputDir: './candidates',
185
209
  inputKeys: ['text'],
186
- pi: options, // Your configured PiRunnerOptions.
210
+ runNode: createPiRunner({ ...options, tools: [], maxSubmissions: 4 }), // Your configured PiRunnerOptions.
187
211
  maxCandidates: 4,
188
212
  acceptance: workflow => checkAgainstYourFixtures(workflow),
189
213
  });
190
214
  console.log(candidate.path, candidate.checks);
191
215
  ```
192
216
 
193
- The host owns `checkAgainstYourFixtures`: return diagnostics, or `[]` to accept. Without that callback, acceptance is labeled `structural` and does not establish correct behavior. The author retains each submitted version and its feedback, never activates it, and cannot edit the host's acceptance checks.
217
+ The host owns `checkAgainstYourFixtures`: return diagnostics, or `[]` to accept. Without that callback, acceptance is labeled `structural` and does not establish correct behavior. The author retains each submitted version and its feedback, never activates it, and cannot edit the host's acceptance checks. See [the author contract](../../docs/authoring.md#one-author-contract) for the host addendum.
194
218
 
195
219
  With `rubricSections`, every supplied section must appear on every generated LLM node, including child workflows. The author conservatively rejects Jev nodes, semantic `ask` predicates, and `verify` clauses under that policy; those need a separately reviewed question contract. Schema properties named `node`, `verify`, or `predicate` remain ordinary data. Supply the authoritative rubric as `deps.sop` when executing the candidate.
196
220
 
197
221
  The standalone CLI remains available as `node packages/pi/dist/cli.js --help` from source. It imports a trusted caller-owned `--config` module for `author` and `run`; importing that module executes its code. `validate` can evaluate code probes. Review executable workflows before using it.
198
222
 
223
+ ## Develop from source
224
+
225
+ To change the extension itself, clone and build the repository:
226
+
227
+ ```sh
228
+ git clone --branch main --single-branch https://github.com/Parcha-ai/agentrun.git
229
+ cd agentrun
230
+ npm ci --ignore-scripts
231
+ npm run build
232
+ agentrun_checkout="$PWD"
233
+ mkdir -p ../agentrun-pi-project
234
+ cd ../agentrun-pi-project
235
+ "$agentrun_checkout/node_modules/.bin/pi" install "$agentrun_checkout/packages/pi" -l
236
+ "$agentrun_checkout/node_modules/.bin/pi" --offline
237
+ ```
238
+
239
+ These commands create a separate `agentrun-pi-project` beside the checkout. You can use your own project directory instead. Pi loads the extension and skill from the checkout, so keep it in place. After source changes, rebuild and run `/reload`.
240
+
199
241
  ## Dependencies and retained data
200
242
 
201
243
  Pi is optional for `@parcha/agentrun-dsl`. This package brings the Pi coding-agent SDK, its provider dependencies, and the Jev adapter; its dependency footprint is larger than the core. The release inventory records the locked versions.
202
244
 
203
245
  The SDK dependencies remain pinned so standalone applications and the CLI have a complete runtime. When loaded as an extension, Pi resolves its core packages and TypeBox through the host loader. The tested host is Pi 0.87.0; installed SDK pins do not make an older or newer host compatible. The offline loader regression checks competing local dependencies, a native file read, and the scripted workflow. Pi's [package guidance](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs/packages.md#dependencies) recommends peers for extension-only packages; this package also provides the standalone SDK.
204
246
 
205
- Candidate directories retain request text, rubric text, workflow versions, and feedback. Native Pi messages can contain workflow inputs and results. Choose storage and tool access appropriate for that data. The accompanying `skills/author/SKILL.md` describes the native and SDK authoring paths for agents.
247
+ Candidate directories retain request text, rubric text, workflow versions, and feedback. Native Pi messages can contain workflow inputs and results. Choose storage and tool access appropriate for that data. The author skill in `@parcha/agentrun-dsl` describes the native and SDK authoring paths for agents.
206
248
 
207
249
  ## License
208
250
 
package/dist/cli.js CHANGED
@@ -2,8 +2,7 @@
2
2
  import { readFile } from "node:fs/promises";
3
3
  import { resolve } from "node:path";
4
4
  import { pathToFileURL } from "node:url";
5
- import { runWorkflow, validateWorkflow } from "@parcha/agentrun-dsl";
6
- import { authorWorkflow } from "./author.js";
5
+ import { authorWorkflow, runWorkflow, validateWorkflow } from "@parcha/agentrun-dsl";
7
6
  import { createPiRunner } from "./runner.js";
8
7
  const help = `Usage:
9
8
  agentrun-pi validate workflow.json [--inputs key1,key2]
@@ -51,7 +50,10 @@ async function main(args) {
51
50
  if (command === "author") {
52
51
  if (args.length !== 1)
53
52
  throw new Error(help);
54
- const authored = await authorWorkflow({ request: args[0], outputDir, inputKeys, pi: config.default });
53
+ const maxCandidates = 4;
54
+ // The author session gets no host tools and stops at the candidate limit.
55
+ const runNode = createPiRunner({ ...config.default, tools: [], maxSubmissions: maxCandidates });
56
+ const authored = await authorWorkflow({ request: args[0], outputDir, inputKeys, runNode, maxCandidates });
55
57
  console.log(JSON.stringify({ path: authored.path, candidates: authored.candidates, checks: authored.checks }, null, 2));
56
58
  }
57
59
  else {
package/dist/demo.js CHANGED
@@ -8,6 +8,7 @@ export function demoSearchTool() {
8
8
  name: 'search', label: 'Search example sources',
9
9
  description: 'Read the bundled fictional wiki-migration sources. This does not search the internet.',
10
10
  parameters: { type: 'object', properties: { question: { type: 'string' } }, required: ['question'], additionalProperties: false },
11
+ resultSchema: { type: 'object', properties: { sources: { type: 'array', items: { type: 'object' } } }, required: ['sources'], additionalProperties: false },
11
12
  async execute(_id, _args, signal) {
12
13
  signal?.throwIfAborted();
13
14
  return { content: [{ type: 'text', text: JSON.stringify({ sources: demoSources }) }], details: { sources: structuredClone(demoSources) } };
@@ -2,8 +2,7 @@ import { types as utilTypes } from 'node:util';
2
2
  import { JevError, isJevResponseReason } from '@parcha/agentrun-jev';
3
3
  import { PiRunError } from './runner.js';
4
4
  import { ToolInputValidationError } from './tool-input-error.js';
5
- import { inspectWorkflow, runWorkflow, validateWorkflow, EffectOutcomeUnknownError, WorkflowInvalidError, WorkflowInputInvalidError, WorkflowOutputInvalidError, WorkflowCodeError, WorkflowStateError, EffectDeadlineExceededError, } from '@parcha/agentrun-dsl';
6
- import { workflowPolicyErrors } from './admission.js';
5
+ import { inspectWorkflow, runWorkflow, validateWorkflow, candidatePolicyErrors, EffectOutcomeUnknownError, WorkflowInvalidError, WorkflowInputInvalidError, WorkflowOutputInvalidError, WorkflowCodeError, WorkflowStateError, EffectDeadlineExceededError, } from '@parcha/agentrun-dsl';
7
6
  export class ExtensionServiceError extends Error {
8
7
  code;
9
8
  constructor(code, message) {
@@ -111,6 +110,7 @@ function localDiagnostic(error) {
111
110
  empty_selection: 'The selection list is empty and none is not allowed. Handle missing evidence explicitly.',
112
111
  missing_map_result: 'A map body did not produce its resultPath. Select a path in the completed body state; a body with as is collected automatically when resultPath is omitted.',
113
112
  parallel_write_conflict: 'Parallel branches changed the same top-level state key. Give independent branches distinct output keys and combine them after the parallel node.',
113
+ reserved_state_key: 'A node or host hook wrote an engine-owned "$"-prefixed state key such as $host. Choose another state key; host state is written only through decodeSubmission.',
114
114
  };
115
115
  return { code: error.code, stage: error.stage.slice(0, 200),
116
116
  // Parallel patch keys may be computed from source values, unlike authored paths.
@@ -258,7 +258,7 @@ export class WorkflowExtensionService {
258
258
  const inspection = inspectWorkflow(workflow);
259
259
  if (inspection.nodes.length > extensionStructuralLimits.maxNodes)
260
260
  throw new ExtensionServiceError('bounds', 'A workflow may contain at most 200 nodes.');
261
- const errors = workflowPolicyErrors(workflow, { allowExecutableCandidates: options.allowExecutableCandidates === true, rubricSections: this.rubricSections, allowedEffectTools: [...this.allowedTools] });
261
+ const errors = candidatePolicyErrors(workflow, { allowExecutableCandidates: options.allowExecutableCandidates === true, rubricSections: this.rubricSections, allowedEffectTools: [...this.allowedTools] });
262
262
  for (const entry of inspection.nodes) {
263
263
  const node = entry.path.split('/').slice(1).reduce((item, key) => item[key.replace(/~1/g, '/').replace(/~0/g, '~')], workflow);
264
264
  if (node.node === 'artifact')
@@ -455,9 +455,17 @@ export class WorkflowExtensionService {
455
455
  failure.errors.slice(0, 100).forEach(collect);
456
456
  };
457
457
  collect(error);
458
+ const failedStep = events.findLast(event => event.type === 'node.end' && event.detail?.status === 'failed');
459
+ const failedPath = failedStep?.executionPath;
460
+ const toolFailed = failedStep && failedStep.detail?.kind === 'call'
461
+ && events.some(event => event.type === 'effect.failed' && event.executionPath === failedPath);
462
+ const observedStage = failedStep?.label.slice(0, 200);
458
463
  report = { digest: prepared.digest, status: code === 'cancelled' || code === 'deadline' ? 'interrupted' : 'failed', calls, events,
459
464
  error: !owned && !signal.aborted && !invalidInput && localDiagnostic(error) || { code,
460
- ...(invalidInput ? { stage: 'input', problems: error.problems.slice(0, 8).map(problem => problem.slice(0, 500)) } : {}), message: owned ? reason.message : signal.aborted ? 'Workflow interrupted.' : invalidInput ? 'Input does not match this workflow. Pass input with action run, or inspect the workflow with its input before running.' : 'Workflow failed. Check the prepared graph, input contracts and host adapter access; provider error bodies are omitted.' },
465
+ ...(invalidInput ? { stage: 'input', problems: error.problems.slice(0, 8).map(problem => problem.slice(0, 500)) } : observedStage ? { stage: observedStage } : {}),
466
+ message: owned ? reason.message : signal.aborted ? 'Workflow interrupted.' : invalidInput ? 'Input does not match this workflow. Pass input with action run, or inspect the workflow with its input before running.'
467
+ : toolFailed ? 'A registered tool call failed. Inspect the tool step and reconcile any effect before a new run. Underlying error text is omitted.'
468
+ : 'Workflow failed. Inspect the affected step, input contracts and host adapters. Underlying error text is omitted.' },
461
469
  ...(unknown.length ? { uncertainEffects: unknown } : {}), ...(traceTruncated ? { traceTruncated: true } : {}) };
462
470
  }
463
471
  finally {