@parcha/agentrun-pi 0.1.0-beta.2 → 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 (52) hide show
  1. package/README.md +46 -19
  2. package/dist/cli.js +5 -3
  3. package/dist/demo.js +1 -0
  4. package/dist/extension-service.js +11 -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/benchmark-contract.d.ts +0 -88
  33. package/dist/benchmark-contract.js +0 -50
  34. package/dist/benchmark-freeze.d.ts +0 -9
  35. package/dist/benchmark-freeze.js +0 -9
  36. package/dist/benchmark.d.ts +0 -127
  37. package/dist/benchmark.js +0 -260
  38. package/dist/comparison.d.ts +0 -69
  39. package/dist/comparison.js +0 -229
  40. package/dist/skill-bundle.d.ts +0 -5
  41. package/dist/skill-bundle.js +0 -15
  42. package/skills/author/SKILL.md +0 -102
  43. package/skills/author/references/sdk-authoring.md +0 -16
  44. /package/{skills → dist/skills}/author/examples/evidence-gate.input.json +0 -0
  45. /package/{skills → dist/skills}/author/examples/evidence-gate.json +0 -0
  46. /package/{skills → dist/skills}/author/examples/read-file.input.json +0 -0
  47. /package/{skills → dist/skills}/author/examples/read-file.json +0 -0
  48. /package/{skills → dist/skills}/author/examples/read-source-decision.input.json +0 -0
  49. /package/{skills → dist/skills}/author/examples/read-source-decision.json +0 -0
  50. /package/{skills → dist/skills}/author/examples/release-note.txt +0 -0
  51. /package/{skills → dist/skills}/author/examples/review-release-notes.input.json +0 -0
  52. /package/{skills → dist/skills}/author/examples/review-release-notes.json +0 -0
package/README.md CHANGED
@@ -1,6 +1,6 @@
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
5
  ## Install
6
6
 
@@ -13,13 +13,13 @@ npm install -g @earendil-works/pi-coding-agent@0.87.0
13
13
  Then, in your project:
14
14
 
15
15
  ```sh
16
- pi install npm:@parcha/agentrun-pi@0.1.0-beta.2 -l
16
+ pi install npm:@parcha/agentrun-pi@0.1.0-beta.3 -l
17
17
  pi --offline
18
18
  ```
19
19
 
20
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
- On first launch, Pi asks whether you trust the project before loading its extension. If Pi is already open, use `/reload`. Reloading 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
 
@@ -33,28 +33,51 @@ The demo shows the workflow graph, progress, and a completed result with call co
33
33
 
34
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
35
 
36
- ## Describe, inspect, run
36
+ ## Preview, run, save, reuse
37
37
 
38
38
  ```text
39
- /agentrun Find the main entry points in this repository and summarize how requests reach them.
39
+ /agentrun Preview a reusable workflow that identifies breaking changes and migration actions in supplied release notes. Do not run it yet.
40
40
  ```
41
41
 
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.
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.
45
+
46
+ After inspecting a definition, save it and reuse it in a new Pi session in the same project:
47
+
48
+ ```text
49
+ /agentrun input The release note says requests now require X-Workspace.
50
+ /agentrun run
51
+ /agentrun save release-review
52
+ ```
53
+
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
 
@@ -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,23 +197,24 @@ 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
 
@@ -205,11 +229,14 @@ git clone --branch main --single-branch https://github.com/Parcha-ai/agentrun.gi
205
229
  cd agentrun
206
230
  npm ci --ignore-scripts
207
231
  npm run build
208
- ./node_modules/.bin/pi install ./packages/pi -l
209
- ./node_modules/.bin/pi --offline
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
210
237
  ```
211
238
 
212
- Use a separate project for this source installation. Pi loads the extension and skill from the checkout, so keep it in place. After source changes, rebuild and run `/reload`.
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`.
213
240
 
214
241
  ## Dependencies and retained data
215
242
 
@@ -217,7 +244,7 @@ Pi is optional for `@parcha/agentrun-dsl`. This package brings the Pi coding-age
217
244
 
218
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.
219
246
 
220
- 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.
221
248
 
222
249
  ## License
223
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) {
@@ -259,7 +258,7 @@ export class WorkflowExtensionService {
259
258
  const inspection = inspectWorkflow(workflow);
260
259
  if (inspection.nodes.length > extensionStructuralLimits.maxNodes)
261
260
  throw new ExtensionServiceError('bounds', 'A workflow may contain at most 200 nodes.');
262
- 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] });
263
262
  for (const entry of inspection.nodes) {
264
263
  const node = entry.path.split('/').slice(1).reduce((item, key) => item[key.replace(/~1/g, '/').replace(/~0/g, '~')], workflow);
265
264
  if (node.node === 'artifact')
@@ -456,9 +455,17 @@ export class WorkflowExtensionService {
456
455
  failure.errors.slice(0, 100).forEach(collect);
457
456
  };
458
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);
459
463
  report = { digest: prepared.digest, status: code === 'cancelled' || code === 'deadline' ? 'interrupted' : 'failed', calls, events,
460
464
  error: !owned && !signal.aborted && !invalidInput && localDiagnostic(error) || { code,
461
- ...(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.' },
462
469
  ...(unknown.length ? { uncertainEffects: unknown } : {}), ...(traceTruncated ? { traceTruncated: true } : {}) };
463
470
  }
464
471
  finally {