@davidorex/pi-agent-dispatch 0.32.0 → 0.33.0
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/CHANGELOG.md +8 -0
- package/README.md +9 -0
- package/dist/call-agent-tool.d.ts.map +1 -1
- package/dist/call-agent-tool.js +16 -9
- package/dist/call-agent-tool.js.map +1 -1
- package/dist/dispatch-loader.d.ts +26 -0
- package/dist/dispatch-loader.d.ts.map +1 -0
- package/dist/dispatch-loader.js +28 -0
- package/dist/dispatch-loader.js.map +1 -0
- package/dist/dispatch-model.d.ts +31 -0
- package/dist/dispatch-model.d.ts.map +1 -0
- package/dist/dispatch-model.js +41 -0
- package/dist/dispatch-model.js.map +1 -0
- package/dist/subprocess-dispatch.d.ts +81 -0
- package/dist/subprocess-dispatch.d.ts.map +1 -0
- package/dist/subprocess-dispatch.js +206 -0
- package/dist/subprocess-dispatch.js.map +1 -0
- package/dist/work-order-loop.d.ts +31 -11
- package/dist/work-order-loop.d.ts.map +1 -1
- package/dist/work-order-loop.js +109 -38
- package/dist/work-order-loop.js.map +1 -1
- package/package.json +6 -6
- package/skills/pi-agent-dispatch/SKILL.md +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,14 @@ All notable changes to this package are documented here. Format follows [Keep a
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.33.0] - 2026-07-08
|
|
8
|
+
|
|
9
|
+
- Bundled agent-spec RESOLUTION from a fresh substrate: both dispatch loaders supply pi-workflows' bundled `agents/` directory as the LAST search tier (via `dispatchLoadContext(cwd)` in `dispatch-loader.ts`, consuming pi-workflows' `./bundled-dirs` subpath export); resolution order ahead of it is unchanged (substrate `agents/`, then `~/.pi/agent/agents/`, then bundled), so a local or user spec of the same name still wins. pi-behavior-monitors' classifier specs remain deliberately off this path (monitor-scoped via that package's own loader).
|
|
10
|
+
- Bundled specs now also COMPILE and acquire a MODEL on the dispatch path, completing fresh-substrate dispatchability through `call-agent` and `run-work-order-loop`: (1) template resolution — both dispatch entry points build their template env with `builtinDir = bundledTemplateDir()`, so a bundled spec's task/system templates resolve against the bundled pi-jit-agents `templates/` tier rather than rendering empty (the bundled `phase-author` spec's task-template reference was also corrected upstream to resolve there). (2) model resolution (`resolveDispatchModel`, `dispatch-model.ts`, mirroring the workflow executor's precedence per the derived dispatch model-policy decision): spec model → substrate `model-config` `by_role[role]` → `model-config` `default`. `run-work-order-loop` subprocess dispatch treats a still-unresolved model as "let pi pick its own default" (the `--model` flag is omitted and pi resolves the model itself inside the subprocess); in-process `call-agent`, which must resolve a concrete model + auth before it can call, throws an informed error naming the `model-config` block as the remedy when no model resolves.
|
|
11
|
+
- The work-order loop now clamps the dispatched agent's tool grant to the work-order's declared `scope.operations`: after composing the grant (`agentGrant ∩ spec.tools`) the loop intersects it with `scope.operations`, and that clamped set becomes the subprocess `--tools` allowlist — so the dispatched agent can never exceed the operations the work-order itself authorizes, regardless of the caller's `agent_grant` (e.g. a caller grant of `[write, bash]` under a work-order `scope.operations` of `[write]` dispatches with `--tools write`; `bash` is dropped). When `scope.operations` is absent or empty the composed grant is passed through unchanged. The loop also now validates the dispatch input (`{ work_order_id }`) against the work-order's declared `input_contract` (an inline JSON Schema, checked via pi-context's canonical AJV validator) before spawning the subprocess; a contract violation throws a descriptive error naming the work-order id, and an absent contract is a no-op pass-through.
|
|
12
|
+
- The work-order loop now dispatches its `target_agent` as a `pi` subprocess (`pi --mode json -p <task> --tools <grant> --model <spec>`, the same mechanism workflow steps use) instead of the in-process `executeAgent` primitive. `executeAgent` binds no executable tools — it only passes a phantom output-schema tool — so a dispatched agent granted `[write, bash]` previously received zero tools and could not act, and every work-order requiring a side-effect failed its real-check. The composed capability grant (`agentGrant ∩ spec.tools`, the dispatch-boundary capability clamp) now becomes the subprocess `--tools` allowlist (an empty grant emits `--no-tools`), so a dispatched agent has real, callable tools. Subprocess dispatch (`subprocess-dispatch.ts`, `runPiSubprocess` + testable `buildDispatchArgs`) carries a default timeout with SIGTERM→SIGKILL grace, cancellation-signal support, an `@tmpfile` prompt for long prompts, and a bounded stdout collector; a nonzero exit, timeout, or empty assistant output throws a descriptive error. Verified end to end: a work-order whose agent must write a file completes with the file written and its runtime-demo real-check passing.
|
|
13
|
+
- The work-order loop now reports `final_status: "aborted-non-interactive"` when a real-check fails in a non-interactive context (`ctx.hasUI === false`): it checks `ctx.hasUI` before prompting and does not call `ctx.ui.confirm`, so an environment default is no longer mislabeled as `aborted-by-human`. Interactive aborts (a human answering the confirm `false`) still report `aborted-by-human`.
|
|
14
|
+
|
|
7
15
|
## [0.32.0] - 2026-07-05
|
|
8
16
|
|
|
9
17
|
- `resolveOperationVocabulary` reads the active substrate's `config.json` through pi-context's migration-aware loader instead of a raw parse: a config whose `schema_version` lags the bundled schema is walked forward through the registered chain before its `tool_operations` overrides apply, so the vocabulary can never diverge from the shape `loadConfig` sees. The fail-safe contract is unchanged — any load failure (absent, unparsable, unresolvable version, invalid) yields `TOOL_OPERATION_DEFAULTS`.
|
package/README.md
CHANGED
|
@@ -27,6 +27,15 @@ Tool grants are operation-granular. Defaults are EMPTY. At each dispatch the gra
|
|
|
27
27
|
|
|
28
28
|
The `run-work-order-loop` tool consolidates the orchestrator's prior per-iteration chain (call-agent → run-real-checks → on-pass commit-attested → on-fail decide-to-retry) into one Pi call. Every gate the prior chain enforced — capability composition at the call boundary, deterministic real-check verdict, writer-attestation footer, human-OK retry at the iteration boundary via `ctx.ui.confirm` — fires from inside the wrapped library. No path bypasses them.
|
|
29
29
|
|
|
30
|
+
## Dispatch resolution tiers
|
|
31
|
+
|
|
32
|
+
Both dispatch entry points (`call-agent`, `run-work-order-loop`) resolve an agent for dispatch across layered searches, so a fresh substrate with no local files can resolve and compile the bundled agent set from the bundled tiers while a local or user copy of the same name still wins. (Compiling and dispatching are distinct: `call-agent` additionally requires a resolvable model — see the **Model** axis — so on a fresh substrate with no `model-config`, a bundled spec that carries no `model` compiles but `call-agent` still errors for want of a model; `run-work-order-loop` omits `--model` and lets the subprocess pick its default.)
|
|
33
|
+
|
|
34
|
+
- **Agent spec** — `<contextDir>/agents/` → `~/.pi/agent/agents/` → bundled pi-workflows `agents/`.
|
|
35
|
+
- **Templates** (the spec's task/system prompt bodies) — a relative template ref is first absolutized at parse when an adjacent file exists (or, for a spec matched from the bundled tier, when a package-root sibling file exists); otherwise it stays a bare name resolved through the Nunjucks loader's tiers: `<contextDir>/templates/` → `~/.pi/agent/templates/` → bundled pi-jit-agents `templates/`.
|
|
36
|
+
- **Output schema** (the spec's `output.schema`) — a `block:<name>` sentinel resolves to the active substrate's `<contextDir>/schemas/<name>.schema.json`; a relative path is resolved at parse against the spec's own directory first, then — for a spec matched from the bundled tier only — the spec directory's PARENT (the package-root sibling `schemas/` dir the bundled `agents/`+`schemas/` layout uses), absolutized to the first that exists on disk. The parent-sibling probe is bundled-tier-only, so a local/user spec's relative ref never absolutizes onto a same-basename substrate block schema or user-config sibling. Unlike templates, an output-schema ref gets no downstream loader-tier search — a relative ref that resolves at neither probe stays a bare name whose read fails loudly when the phantom validation tool is built.
|
|
37
|
+
- **Model** — the spec's own `model` → substrate `model-config` `by_role[role]` → `model-config` `default`. When none resolves, subprocess dispatch (`run-work-order-loop`) omits `--model` and pi picks its own default inside the subprocess; in-process dispatch (`call-agent`), which must resolve a concrete model + auth before it can call, instead requires a spec or `model-config` model and errors otherwise.
|
|
38
|
+
|
|
30
39
|
## Canonical rules
|
|
31
40
|
|
|
32
41
|
- Harness-confined orchestrator (positive + negative clauses).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"call-agent-tool.d.ts","sourceRoot":"","sources":["../src/call-agent-tool.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAErG,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,KAAK,EAAE,eAAe,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"call-agent-tool.d.ts","sourceRoot":"","sources":["../src/call-agent-tool.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAErG,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,KAAK,EAAE,eAAe,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAWlH;;;;;;;GAOG;AACH,eAAO,MAAM,UAAU,EAAE;IAAE,YAAY,EAAE,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,eAAe,KAAK,OAAO,CAAC,cAAc,CAAC,CAAA;CAEzG,CAAC;AAEF,eAAO,MAAM,aAAa;;;;;;;;;;;;yBAwBX,MAAM,UACX;QACP,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE,OAAO,CAAC;QACf,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;QACxB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;QAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;KACpB,UACO,WAAW,aACR,uBAAuB,OAC7B,gBAAgB,GACnB,OAAO,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC;CAuD3C,CAAC"}
|
package/dist/call-agent-tool.js
CHANGED
|
@@ -8,9 +8,11 @@
|
|
|
8
8
|
import { createAgentLoader } from "@davidorex/pi-jit-agents/agent-spec";
|
|
9
9
|
import { compileAgent } from "@davidorex/pi-jit-agents/compile";
|
|
10
10
|
import { executeAgent as canonicalExecuteAgent } from "@davidorex/pi-jit-agents/runtime";
|
|
11
|
-
import { createTemplateEnv } from "@davidorex/pi-jit-agents/template";
|
|
11
|
+
import { bundledTemplateDir, createTemplateEnv } from "@davidorex/pi-jit-agents/template";
|
|
12
12
|
import { Type } from "@earendil-works/pi-ai";
|
|
13
13
|
import { composeToolGrant } from "./capability-composer.js";
|
|
14
|
+
import { dispatchLoadContext } from "./dispatch-loader.js";
|
|
15
|
+
import { resolveDispatchModel } from "./dispatch-model.js";
|
|
14
16
|
function parseModelSpec(spec) {
|
|
15
17
|
const slashIndex = spec.indexOf("/");
|
|
16
18
|
if (slashIndex !== -1)
|
|
@@ -35,7 +37,7 @@ export const callAgentTool = {
|
|
|
35
37
|
promptSnippet: "Dispatch a typed sub-agent with scoped capability grant.",
|
|
36
38
|
parameters: Type.Object({
|
|
37
39
|
spec_name: Type.String({
|
|
38
|
-
description: "Name of the agent spec to load (resolves to <name>.agent.yaml
|
|
40
|
+
description: "Name of the agent spec to load (resolves to <name>.agent.yaml searched across the substrate agents/ dir, then ~/.pi/agent/agents/, then the bundled pi-workflows agents).",
|
|
39
41
|
}),
|
|
40
42
|
input: Type.Unknown({ description: "Typed input passed to the agent's compileAgent context." }),
|
|
41
43
|
parent_grant: Type.Optional(Type.Array(Type.String(), { description: "The caller's own tool grant. Default-empty." })),
|
|
@@ -45,16 +47,21 @@ export const callAgentTool = {
|
|
|
45
47
|
max_tokens: Type.Optional(Type.Number({ description: "Max tokens for the LLM call. Defaults to 1024." })),
|
|
46
48
|
}),
|
|
47
49
|
async execute(_toolCallId, params, signal, _onUpdate, ctx) {
|
|
48
|
-
// 1. Load spec via jit-agents canonical loader
|
|
49
|
-
const loadAgent = createAgentLoader(
|
|
50
|
+
// 1. Load spec via jit-agents canonical loader (builtin tier = bundled pi-workflows agents/)
|
|
51
|
+
const loadAgent = createAgentLoader(dispatchLoadContext(ctx.cwd));
|
|
50
52
|
const spec = loadAgent(params.spec_name);
|
|
51
|
-
// 2. Compile spec with input
|
|
52
|
-
|
|
53
|
+
// 2. Compile spec with input (builtinDir = bundled pi-jit-agents templates/,
|
|
54
|
+
// so a bundled spec's task/system templates resolve without a local copy)
|
|
55
|
+
const env = createTemplateEnv({ cwd: ctx.cwd, builtinDir: bundledTemplateDir() });
|
|
53
56
|
const compiled = compileAgent(spec, { env, input: params.input, cwd: ctx.cwd });
|
|
54
|
-
// 3. Resolve model + auth via ExtensionContext.modelRegistry
|
|
55
|
-
|
|
57
|
+
// 3. Resolve model + auth via ExtensionContext.modelRegistry. Precedence
|
|
58
|
+
// (DEC-0023): compiled/spec model → model-config by_role[role] → default.
|
|
59
|
+
// In-process dispatch has no pi subprocess to fall through to, so a still-null
|
|
60
|
+
// resolution is an informed throw naming the model-config block as the remedy.
|
|
61
|
+
const modelSpec = compiled.model ?? spec.model ?? resolveDispatchModel(ctx.cwd, spec);
|
|
56
62
|
if (!modelSpec) {
|
|
57
|
-
throw new Error(`call-agent: agent '${params.spec_name}' has no model
|
|
63
|
+
throw new Error(`call-agent: agent '${params.spec_name}' has no model — declare one on the spec, ` +
|
|
64
|
+
`or add a matching entry to the substrate's model-config block (by_role['${spec.role ?? ""}'] or default).`);
|
|
58
65
|
}
|
|
59
66
|
const { provider, modelId } = parseModelSpec(modelSpec);
|
|
60
67
|
const model = ctx.modelRegistry.find(provider, modelId);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"call-agent-tool.js","sourceRoot":"","sources":["../src/call-agent-tool.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAChE,OAAO,EAAE,YAAY,IAAI,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzF,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"call-agent-tool.js","sourceRoot":"","sources":["../src/call-agent-tool.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAChE,OAAO,EAAE,YAAY,IAAI,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzF,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAG1F,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAE7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAE3D,SAAS,cAAc,CAAC,IAAY;IACnC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACrC,IAAI,UAAU,KAAK,CAAC,CAAC;QAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,EAAE,CAAC;IAC3G,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AACjD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,UAAU,GAAwF;IAC9G,YAAY,EAAE,qBAAqB;CACnC,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG;IAC5B,IAAI,EAAE,YAAY;IAClB,KAAK,EAAE,YAAY;IACnB,WAAW,EACV,0SAA0S;IAC3S,aAAa,EAAE,0DAA0D;IACzE,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC;QACvB,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC;YACtB,WAAW,EACV,2KAA2K;SAC5K,CAAC;QACF,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,yDAAyD,EAAE,CAAC;QAC/F,YAAY,EAAE,IAAI,CAAC,QAAQ,CAC1B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,WAAW,EAAE,6CAA6C,EAAE,CAAC,CACzF;QACD,eAAe,EAAE,IAAI,CAAC,QAAQ,CAC7B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE;YACzB,WAAW,EACV,0GAA0G;SAC3G,CAAC,CACF;QACD,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,gDAAgD,EAAE,CAAC,CAAC;KACzG,CAAC;IACF,KAAK,CAAC,OAAO,CACZ,WAAmB,EACnB,MAMC,EACD,MAAmB,EACnB,SAAkC,EAClC,GAAqB;QAErB,6FAA6F;QAC7F,MAAM,SAAS,GAAG,iBAAiB,CAAC,mBAAmB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;QAClE,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAEzC,6EAA6E;QAC7E,0EAA0E;QAC1E,MAAM,GAAG,GAAG,iBAAiB,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,UAAU,EAAE,kBAAkB,EAAE,EAAE,CAAC,CAAC;QAClF,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;QAEhF,yEAAyE;QACzE,0EAA0E;QAC1E,+EAA+E;QAC/E,+EAA+E;QAC/E,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,IAAI,oBAAoB,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACtF,IAAI,CAAC,SAAS,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CACd,sBAAsB,MAAM,CAAC,SAAS,4CAA4C;gBACjF,2EAA2E,IAAI,CAAC,IAAI,IAAI,EAAE,iBAAiB,CAC5G,CAAC;QACH,CAAC;QACD,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;QACxD,MAAM,KAAK,GAAG,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACxD,IAAI,CAAC,KAAK,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,sBAAsB,SAAS,2CAA2C,MAAM,CAAC,SAAS,IAAI,CAAC,CAAC;QACjH,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,aAAa,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;QAChE,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CAAC,2CAA2C,SAAS,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QACzF,CAAC;QAED,wEAAwE;QACxE,MAAM,aAAa,GAAG,gBAAgB,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,eAAe,CAAC,CAAC;QAEpF,yFAAyF;QACzF,MAAM,QAAQ,GAAoB;YACjC,KAAK,EAAE,KAAmB;YAC1B,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,EAAE,EAAE;YAChE,WAAW,EAAE,aAAa;YAC1B,SAAS,EAAE,MAAM,CAAC,UAAU,IAAI,IAAI;YACpC,MAAM;SACN,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,YAAY,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAEjE,OAAO;YACN,OAAO,EAAE,MAAM;YACf,OAAO,EAAE;gBACR;oBACC,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,qBAAqB,MAAM,CAAC,SAAS,aAAa,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,0BAA0B,OAAO,MAAM,CAAC,MAAM,EAAE;iBAChI;aACD;SACD,CAAC;IACH,CAAC;CACD,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dispatch-loader — the dispatch-side builtin agent tier (FGAP-127).
|
|
3
|
+
*
|
|
4
|
+
* Both dispatch entry points (call-agent, run-work-order-loop) build their
|
|
5
|
+
* pi-jit-agents `createAgentLoader` LoadContext here so the bundled
|
|
6
|
+
* pi-workflows `agents/` directory (26 shipped specs, e.g. `investigator`)
|
|
7
|
+
* becomes the LAST search tier: the active substrate's `<contextDir>/agents/`
|
|
8
|
+
* and the user tier (`~/.pi/agent/agents/`) still win on name collision.
|
|
9
|
+
*
|
|
10
|
+
* This is only the agent-spec RESOLUTION tier. A bundled spec also has to
|
|
11
|
+
* COMPILE from a fresh substrate: both entry points build their template env
|
|
12
|
+
* with `builtinDir = bundledTemplateDir()` so a bundled spec's task/system
|
|
13
|
+
* templates resolve against the bundled pi-jit-agents `templates/` tier (no
|
|
14
|
+
* local copy needed). Model resolution then follows the derived dispatch-model
|
|
15
|
+
* precedence (DEC-0023, `dispatch-model.ts`): spec → model-config `by_role` →
|
|
16
|
+
* `default`. work-order subprocess dispatch treats a still-null model as
|
|
17
|
+
* "let pi pick its own default" (no `--model` passed); in-process call-agent —
|
|
18
|
+
* which must resolve a concrete model + auth before it can call — keeps an
|
|
19
|
+
* informed throw naming the model-config block as the remedy.
|
|
20
|
+
*
|
|
21
|
+
* pi-behavior-monitors' classifier specs are deliberately NOT on this path —
|
|
22
|
+
* they are monitor-scoped, resolved via that package's own loader.
|
|
23
|
+
*/
|
|
24
|
+
import type { LoadContext } from "@davidorex/pi-jit-agents/types";
|
|
25
|
+
export declare function dispatchLoadContext(cwd: string): LoadContext;
|
|
26
|
+
//# sourceMappingURL=dispatch-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatch-loader.d.ts","sourceRoot":"","sources":["../src/dispatch-loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAGlE,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAE5D"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dispatch-loader — the dispatch-side builtin agent tier (FGAP-127).
|
|
3
|
+
*
|
|
4
|
+
* Both dispatch entry points (call-agent, run-work-order-loop) build their
|
|
5
|
+
* pi-jit-agents `createAgentLoader` LoadContext here so the bundled
|
|
6
|
+
* pi-workflows `agents/` directory (26 shipped specs, e.g. `investigator`)
|
|
7
|
+
* becomes the LAST search tier: the active substrate's `<contextDir>/agents/`
|
|
8
|
+
* and the user tier (`~/.pi/agent/agents/`) still win on name collision.
|
|
9
|
+
*
|
|
10
|
+
* This is only the agent-spec RESOLUTION tier. A bundled spec also has to
|
|
11
|
+
* COMPILE from a fresh substrate: both entry points build their template env
|
|
12
|
+
* with `builtinDir = bundledTemplateDir()` so a bundled spec's task/system
|
|
13
|
+
* templates resolve against the bundled pi-jit-agents `templates/` tier (no
|
|
14
|
+
* local copy needed). Model resolution then follows the derived dispatch-model
|
|
15
|
+
* precedence (DEC-0023, `dispatch-model.ts`): spec → model-config `by_role` →
|
|
16
|
+
* `default`. work-order subprocess dispatch treats a still-null model as
|
|
17
|
+
* "let pi pick its own default" (no `--model` passed); in-process call-agent —
|
|
18
|
+
* which must resolve a concrete model + auth before it can call — keeps an
|
|
19
|
+
* informed throw naming the model-config block as the remedy.
|
|
20
|
+
*
|
|
21
|
+
* pi-behavior-monitors' classifier specs are deliberately NOT on this path —
|
|
22
|
+
* they are monitor-scoped, resolved via that package's own loader.
|
|
23
|
+
*/
|
|
24
|
+
import { bundledDir } from "@davidorex/pi-workflows/bundled-dirs";
|
|
25
|
+
export function dispatchLoadContext(cwd) {
|
|
26
|
+
return { cwd, builtinDir: bundledDir("agents") };
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=dispatch-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatch-loader.js","sourceRoot":"","sources":["../src/dispatch-loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,sCAAsC,CAAC;AAElE,MAAM,UAAU,mBAAmB,CAAC,GAAW;IAC9C,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;AAClD,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dispatch-model — derived dispatch-model resolution (DEC-0023).
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the workflow executor's model-precedence policy at the agent-dispatch
|
|
5
|
+
* boundary: an agent spec that names no `model` of its own falls back to the
|
|
6
|
+
* active substrate's `model-config` block — first a per-role assignment
|
|
7
|
+
* (`by_role[role]`), then the block's `default`. This is the same precedence
|
|
8
|
+
* `packages/pi-workflows/src/dispatch.ts` (buildArgs) applies to workflow steps,
|
|
9
|
+
* lifted here so a bundled spec (which carries no model) can be dispatched
|
|
10
|
+
* without every caller hard-coding a model.
|
|
11
|
+
*
|
|
12
|
+
* The two dispatch entry points consume the resolved value differently, by
|
|
13
|
+
* design:
|
|
14
|
+
* - subprocess dispatch (work-order loop) treats a `null` result as "let pi
|
|
15
|
+
* pick its own default": no `--model` flag is passed and pi resolves the
|
|
16
|
+
* model from the operator's own configuration inside the subprocess.
|
|
17
|
+
* - in-process dispatch (call-agent, which must resolve a concrete model +
|
|
18
|
+
* auth through the ExtensionContext.modelRegistry before it can call) keeps
|
|
19
|
+
* an informed throw when the resolution is still `null` — there is no pi
|
|
20
|
+
* subprocess to fall through to.
|
|
21
|
+
*
|
|
22
|
+
* `model-config` is read through pi-context's `readBlock`, which THROWS when the
|
|
23
|
+
* block is absent; a missing/broken block is a fall-through, not an error, so
|
|
24
|
+
* the read is wrapped in try/catch-to-`undefined` (the same handling the
|
|
25
|
+
* workflow executor applies at `workflow-executor.ts`'s model-config load).
|
|
26
|
+
*/
|
|
27
|
+
export declare function resolveDispatchModel(cwd: string, spec: {
|
|
28
|
+
model?: string;
|
|
29
|
+
role?: string;
|
|
30
|
+
}): string | null;
|
|
31
|
+
//# sourceMappingURL=dispatch-model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatch-model.d.ts","sourceRoot":"","sources":["../src/dispatch-model.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AASH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,GAAG,IAAI,CAYxG"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dispatch-model — derived dispatch-model resolution (DEC-0023).
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the workflow executor's model-precedence policy at the agent-dispatch
|
|
5
|
+
* boundary: an agent spec that names no `model` of its own falls back to the
|
|
6
|
+
* active substrate's `model-config` block — first a per-role assignment
|
|
7
|
+
* (`by_role[role]`), then the block's `default`. This is the same precedence
|
|
8
|
+
* `packages/pi-workflows/src/dispatch.ts` (buildArgs) applies to workflow steps,
|
|
9
|
+
* lifted here so a bundled spec (which carries no model) can be dispatched
|
|
10
|
+
* without every caller hard-coding a model.
|
|
11
|
+
*
|
|
12
|
+
* The two dispatch entry points consume the resolved value differently, by
|
|
13
|
+
* design:
|
|
14
|
+
* - subprocess dispatch (work-order loop) treats a `null` result as "let pi
|
|
15
|
+
* pick its own default": no `--model` flag is passed and pi resolves the
|
|
16
|
+
* model from the operator's own configuration inside the subprocess.
|
|
17
|
+
* - in-process dispatch (call-agent, which must resolve a concrete model +
|
|
18
|
+
* auth through the ExtensionContext.modelRegistry before it can call) keeps
|
|
19
|
+
* an informed throw when the resolution is still `null` — there is no pi
|
|
20
|
+
* subprocess to fall through to.
|
|
21
|
+
*
|
|
22
|
+
* `model-config` is read through pi-context's `readBlock`, which THROWS when the
|
|
23
|
+
* block is absent; a missing/broken block is a fall-through, not an error, so
|
|
24
|
+
* the read is wrapped in try/catch-to-`undefined` (the same handling the
|
|
25
|
+
* workflow executor applies at `workflow-executor.ts`'s model-config load).
|
|
26
|
+
*/
|
|
27
|
+
import { readBlock } from "@davidorex/pi-context/block-api";
|
|
28
|
+
export function resolveDispatchModel(cwd, spec) {
|
|
29
|
+
if (spec.model)
|
|
30
|
+
return spec.model;
|
|
31
|
+
let modelConfig;
|
|
32
|
+
try {
|
|
33
|
+
modelConfig = readBlock(cwd, "model-config");
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
/* no model-config block — nothing to fall back to */
|
|
37
|
+
}
|
|
38
|
+
const byRole = spec.role ? modelConfig?.by_role?.[spec.role] : undefined;
|
|
39
|
+
return byRole ?? modelConfig?.default ?? null;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=dispatch-model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatch-model.js","sourceRoot":"","sources":["../src/dispatch-model.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAO5D,MAAM,UAAU,oBAAoB,CAAC,GAAW,EAAE,IAAuC;IACxF,IAAI,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC,KAAK,CAAC;IAElC,IAAI,WAAoC,CAAC;IACzC,IAAI,CAAC;QACJ,WAAW,GAAG,SAAS,CAAC,GAAG,EAAE,cAAc,CAAgB,CAAC;IAC7D,CAAC;IAAC,MAAM,CAAC;QACR,qDAAqD;IACtD,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE,OAAO,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACzE,OAAO,MAAM,IAAI,WAAW,EAAE,OAAO,IAAI,IAAI,CAAC;AAC/C,CAAC"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subprocess dispatch for the work-order loop (FGAP-124).
|
|
3
|
+
*
|
|
4
|
+
* The work-order loop's target agent must ACT — write files, run bash — not
|
|
5
|
+
* merely produce structured output. pi-jit-agents `executeAgent` is a
|
|
6
|
+
* single-turn completion primitive that binds NO executable tools (it only
|
|
7
|
+
* ever passes a phantom output-schema tool; `compiled.tools` feeds the
|
|
8
|
+
* the grant clamp but is never materialized as callable tools). So an
|
|
9
|
+
* agent granted [write,bash] through that path receives zero tools and every
|
|
10
|
+
* real work-order fails.
|
|
11
|
+
*
|
|
12
|
+
* Real tool execution lives only in a `pi` subprocess — the same mechanism
|
|
13
|
+
* pi-workflows uses in production (`packages/pi-workflows/src/dispatch.ts`).
|
|
14
|
+
* This module mirrors that proven pattern, focused to what the work-order
|
|
15
|
+
* loop needs: build args, spawn `pi --mode json`, stream NDJSON stdout,
|
|
16
|
+
* collect the final assistant text + usage, with timeout + cancellation.
|
|
17
|
+
*
|
|
18
|
+
* pi-jit-agents stays the classify / structured-output primitive per JI-021;
|
|
19
|
+
* the acting-agent dispatch is a subprocess.
|
|
20
|
+
*/
|
|
21
|
+
/** Default per-dispatch timeout (10 min) — an acting agent may build/test/write. */
|
|
22
|
+
export declare const DEFAULT_DISPATCH_TIMEOUT_MS = 600000;
|
|
23
|
+
export interface DispatchArgsParams {
|
|
24
|
+
/**
|
|
25
|
+
* Model spec string passed straight to `--model` (supports
|
|
26
|
+
* `provider/id[:thinking]`). Optional: when omitted the `--model` flag is not
|
|
27
|
+
* emitted at all, so pi resolves its own default model inside the subprocess
|
|
28
|
+
* (the fall-through the dispatch-model resolution takes when neither the spec
|
|
29
|
+
* nor the model-config block names a model — DEC-0023).
|
|
30
|
+
*/
|
|
31
|
+
model?: string;
|
|
32
|
+
/** Composed tool grant (already intersected at the dispatch boundary). */
|
|
33
|
+
tools: string[];
|
|
34
|
+
/**
|
|
35
|
+
* Prompt argument value — either the literal prompt text or `@<tmpfile>`
|
|
36
|
+
* for long prompts (the caller decides and rewrites this before spawn).
|
|
37
|
+
*/
|
|
38
|
+
promptArg: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Pure arg construction for the `pi` subprocess. Extracted so the exact CLI
|
|
42
|
+
* surface (mode, model, tools, prompt) is unit-testable without spawning.
|
|
43
|
+
*
|
|
44
|
+
* An EMPTY tool grant emits `--no-tools`, not an absent flag: a cleared grant
|
|
45
|
+
* means "no executable tools" (default-empty), whereas omitting
|
|
46
|
+
* `--tools` would let pi enable its full default tool set.
|
|
47
|
+
*/
|
|
48
|
+
export declare function buildDispatchArgs({ model, tools, promptArg }: DispatchArgsParams): string[];
|
|
49
|
+
export interface SubprocessDispatchResult {
|
|
50
|
+
/** Concatenated assistant text across turns (final channel of the run). */
|
|
51
|
+
text: string;
|
|
52
|
+
/** The last assistant message object seen on the NDJSON stream (raw). */
|
|
53
|
+
lastAssistantMessage: unknown;
|
|
54
|
+
usage: {
|
|
55
|
+
input: number;
|
|
56
|
+
output: number;
|
|
57
|
+
cacheRead: number;
|
|
58
|
+
cacheWrite: number;
|
|
59
|
+
cost: number;
|
|
60
|
+
};
|
|
61
|
+
exitCode: number | null;
|
|
62
|
+
stderr: string;
|
|
63
|
+
timedOut: boolean;
|
|
64
|
+
}
|
|
65
|
+
export interface RunPiSubprocessOptions {
|
|
66
|
+
cwd: string;
|
|
67
|
+
/** Model spec; when omitted pi resolves its own default inside the subprocess. */
|
|
68
|
+
model?: string;
|
|
69
|
+
tools: string[];
|
|
70
|
+
prompt: string;
|
|
71
|
+
timeoutMs?: number;
|
|
72
|
+
signal?: AbortSignal;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Spawn `pi` in JSON mode, stream NDJSON stdout, and collect the final
|
|
76
|
+
* assistant text + usage. Auth + model resolution are pi's own responsibility
|
|
77
|
+
* inside the subprocess (it loads the operator's auth.json) — no DispatchContext
|
|
78
|
+
* auth is threaded here.
|
|
79
|
+
*/
|
|
80
|
+
export declare function runPiSubprocess(options: RunPiSubprocessOptions): Promise<SubprocessDispatchResult>;
|
|
81
|
+
//# sourceMappingURL=subprocess-dispatch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subprocess-dispatch.d.ts","sourceRoot":"","sources":["../src/subprocess-dispatch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAUH,oFAAoF;AACpF,eAAO,MAAM,2BAA2B,SAAU,CAAC;AAWnD,MAAM,WAAW,kBAAkB;IAClC;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0EAA0E;IAC1E,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,kBAAkB,GAAG,MAAM,EAAE,CAU3F;AAED,MAAM,WAAW,wBAAwB;IACxC,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAC;IACb,yEAAyE;IACzE,oBAAoB,EAAE,OAAO,CAAC;IAC9B,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9F,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;CAClB;AAaD,MAAM,WAAW,sBAAsB;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ,kFAAkF;IAClF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,WAAW,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAsIxG"}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subprocess dispatch for the work-order loop (FGAP-124).
|
|
3
|
+
*
|
|
4
|
+
* The work-order loop's target agent must ACT — write files, run bash — not
|
|
5
|
+
* merely produce structured output. pi-jit-agents `executeAgent` is a
|
|
6
|
+
* single-turn completion primitive that binds NO executable tools (it only
|
|
7
|
+
* ever passes a phantom output-schema tool; `compiled.tools` feeds the
|
|
8
|
+
* the grant clamp but is never materialized as callable tools). So an
|
|
9
|
+
* agent granted [write,bash] through that path receives zero tools and every
|
|
10
|
+
* real work-order fails.
|
|
11
|
+
*
|
|
12
|
+
* Real tool execution lives only in a `pi` subprocess — the same mechanism
|
|
13
|
+
* pi-workflows uses in production (`packages/pi-workflows/src/dispatch.ts`).
|
|
14
|
+
* This module mirrors that proven pattern, focused to what the work-order
|
|
15
|
+
* loop needs: build args, spawn `pi --mode json`, stream NDJSON stdout,
|
|
16
|
+
* collect the final assistant text + usage, with timeout + cancellation.
|
|
17
|
+
*
|
|
18
|
+
* pi-jit-agents stays the classify / structured-output primitive per JI-021;
|
|
19
|
+
* the acting-agent dispatch is a subprocess.
|
|
20
|
+
*/
|
|
21
|
+
import { spawn } from "node:child_process";
|
|
22
|
+
import fs from "node:fs";
|
|
23
|
+
import os from "node:os";
|
|
24
|
+
import path from "node:path";
|
|
25
|
+
/** Grace period between SIGTERM and SIGKILL when terminating the subprocess. */
|
|
26
|
+
const SIGKILL_GRACE_MS = 5000;
|
|
27
|
+
/** Default per-dispatch timeout (10 min) — an acting agent may build/test/write. */
|
|
28
|
+
export const DEFAULT_DISPATCH_TIMEOUT_MS = 600_000;
|
|
29
|
+
/**
|
|
30
|
+
* Prompt length threshold (chars) for switching to `@file` argument passing.
|
|
31
|
+
* Mirrors pi-workflows dispatch — avoids OS argv length limits with headroom.
|
|
32
|
+
*/
|
|
33
|
+
const PROMPT_ARG_LIMIT = 8000;
|
|
34
|
+
/** Maximum stdout buffer size (10 MB) to bound memory from a runaway subprocess. */
|
|
35
|
+
const MAX_STDOUT_BYTES = 10 * 1024 * 1024;
|
|
36
|
+
/**
|
|
37
|
+
* Pure arg construction for the `pi` subprocess. Extracted so the exact CLI
|
|
38
|
+
* surface (mode, model, tools, prompt) is unit-testable without spawning.
|
|
39
|
+
*
|
|
40
|
+
* An EMPTY tool grant emits `--no-tools`, not an absent flag: a cleared grant
|
|
41
|
+
* means "no executable tools" (default-empty), whereas omitting
|
|
42
|
+
* `--tools` would let pi enable its full default tool set.
|
|
43
|
+
*/
|
|
44
|
+
export function buildDispatchArgs({ model, tools, promptArg }) {
|
|
45
|
+
const args = ["--mode", "json"];
|
|
46
|
+
if (model)
|
|
47
|
+
args.push("--model", model);
|
|
48
|
+
if (tools.length > 0) {
|
|
49
|
+
args.push("--tools", tools.join(","));
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
args.push("--no-tools");
|
|
53
|
+
}
|
|
54
|
+
args.push("-p", promptArg);
|
|
55
|
+
return args;
|
|
56
|
+
}
|
|
57
|
+
function extractText(content) {
|
|
58
|
+
if (!content || !Array.isArray(content))
|
|
59
|
+
return "";
|
|
60
|
+
const parts = [];
|
|
61
|
+
for (const part of content) {
|
|
62
|
+
if (part && typeof part === "object" && "type" in part && part.type === "text" && "text" in part) {
|
|
63
|
+
parts.push(String(part.text));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return parts.join("");
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Spawn `pi` in JSON mode, stream NDJSON stdout, and collect the final
|
|
70
|
+
* assistant text + usage. Auth + model resolution are pi's own responsibility
|
|
71
|
+
* inside the subprocess (it loads the operator's auth.json) — no DispatchContext
|
|
72
|
+
* auth is threaded here.
|
|
73
|
+
*/
|
|
74
|
+
export async function runPiSubprocess(options) {
|
|
75
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_DISPATCH_TIMEOUT_MS;
|
|
76
|
+
// Long prompts go to a temp file passed as `-p @<file>`.
|
|
77
|
+
let tmpDir = null;
|
|
78
|
+
let promptArg = options.prompt;
|
|
79
|
+
if (options.prompt.length > PROMPT_ARG_LIMIT) {
|
|
80
|
+
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-wo-"));
|
|
81
|
+
const promptFile = path.join(tmpDir, "prompt.md");
|
|
82
|
+
fs.writeFileSync(promptFile, options.prompt, { mode: 0o600 });
|
|
83
|
+
promptArg = `@${promptFile}`;
|
|
84
|
+
}
|
|
85
|
+
const args = buildDispatchArgs({ model: options.model, tools: options.tools, promptArg });
|
|
86
|
+
const proc = spawn("pi", args, {
|
|
87
|
+
cwd: options.cwd,
|
|
88
|
+
env: process.env,
|
|
89
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
90
|
+
});
|
|
91
|
+
// Cancellation
|
|
92
|
+
if (options.signal) {
|
|
93
|
+
const kill = () => {
|
|
94
|
+
proc.kill("SIGTERM");
|
|
95
|
+
setTimeout(() => {
|
|
96
|
+
if (!proc.killed)
|
|
97
|
+
proc.kill("SIGKILL");
|
|
98
|
+
}, SIGKILL_GRACE_MS);
|
|
99
|
+
};
|
|
100
|
+
if (options.signal.aborted)
|
|
101
|
+
kill();
|
|
102
|
+
else
|
|
103
|
+
options.signal.addEventListener("abort", kill, { once: true });
|
|
104
|
+
}
|
|
105
|
+
// Timeout: SIGTERM after deadline, SIGKILL after grace
|
|
106
|
+
let timedOut = false;
|
|
107
|
+
let killTimer;
|
|
108
|
+
const timeoutTimer = setTimeout(() => {
|
|
109
|
+
timedOut = true;
|
|
110
|
+
proc.kill("SIGTERM");
|
|
111
|
+
killTimer = setTimeout(() => {
|
|
112
|
+
if (!proc.killed)
|
|
113
|
+
proc.kill("SIGKILL");
|
|
114
|
+
}, SIGKILL_GRACE_MS);
|
|
115
|
+
}, timeoutMs);
|
|
116
|
+
const usage = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0 };
|
|
117
|
+
const textParts = [];
|
|
118
|
+
let lastAssistantMessage;
|
|
119
|
+
let stderrBuf = "";
|
|
120
|
+
function processEvent(evt) {
|
|
121
|
+
if (evt.type === "message_end" && evt.message && evt.message.role === "assistant") {
|
|
122
|
+
lastAssistantMessage = evt.message;
|
|
123
|
+
const u = evt.message.usage;
|
|
124
|
+
if (u) {
|
|
125
|
+
usage.input += u.input || 0;
|
|
126
|
+
usage.output += u.output || 0;
|
|
127
|
+
usage.cacheRead += u.cacheRead || 0;
|
|
128
|
+
usage.cacheWrite += u.cacheWrite || 0;
|
|
129
|
+
usage.cost += u.cost?.total || 0;
|
|
130
|
+
}
|
|
131
|
+
const text = extractText(evt.message.content);
|
|
132
|
+
if (text)
|
|
133
|
+
textParts.push(text);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
let buf = "";
|
|
137
|
+
let bufBytes = 0;
|
|
138
|
+
let stdoutTruncated = false;
|
|
139
|
+
proc.stdout?.on("data", (chunk) => {
|
|
140
|
+
bufBytes += chunk.length;
|
|
141
|
+
if (bufBytes > MAX_STDOUT_BYTES) {
|
|
142
|
+
if (!stdoutTruncated) {
|
|
143
|
+
stdoutTruncated = true;
|
|
144
|
+
if (buf.trim()) {
|
|
145
|
+
try {
|
|
146
|
+
processEvent(JSON.parse(buf));
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
// incomplete trailing line — discard
|
|
150
|
+
}
|
|
151
|
+
buf = "";
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
buf += chunk.toString();
|
|
157
|
+
const lines = buf.split("\n");
|
|
158
|
+
buf = lines.pop() || "";
|
|
159
|
+
for (const line of lines) {
|
|
160
|
+
if (!line.trim())
|
|
161
|
+
continue;
|
|
162
|
+
try {
|
|
163
|
+
processEvent(JSON.parse(line));
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
// non-JSON line — skip
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
proc.stderr?.on("data", (chunk) => {
|
|
171
|
+
stderrBuf += chunk.toString();
|
|
172
|
+
});
|
|
173
|
+
const exitCode = await new Promise((resolve) => {
|
|
174
|
+
proc.on("close", (code) => {
|
|
175
|
+
if (buf.trim()) {
|
|
176
|
+
try {
|
|
177
|
+
processEvent(JSON.parse(buf));
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
// skip unparseable remainder
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
resolve(code);
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
clearTimeout(timeoutTimer);
|
|
187
|
+
if (killTimer)
|
|
188
|
+
clearTimeout(killTimer);
|
|
189
|
+
if (tmpDir) {
|
|
190
|
+
try {
|
|
191
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
// best-effort cleanup
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return {
|
|
198
|
+
text: textParts.join("\n"),
|
|
199
|
+
lastAssistantMessage,
|
|
200
|
+
usage,
|
|
201
|
+
exitCode,
|
|
202
|
+
stderr: stderrBuf.trim(),
|
|
203
|
+
timedOut,
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
//# sourceMappingURL=subprocess-dispatch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subprocess-dispatch.js","sourceRoot":"","sources":["../src/subprocess-dispatch.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,10 +5,12 @@
|
|
|
5
5
|
* drives the end-to-end loop the work-order encodes:
|
|
6
6
|
*
|
|
7
7
|
* for iteration in 0..max_iterations:
|
|
8
|
-
* 1. dispatch the work-order's target_agent
|
|
9
|
-
*
|
|
8
|
+
* 1. dispatch the work-order's target_agent as a `pi` subprocess (FGAP-124
|
|
9
|
+
* — the only path that binds real, callable tools; pi-jit-agents'
|
|
10
|
+
* executeAgent binds none). pi-jit-agents stays the classify /
|
|
11
|
+
* structured-output library primitive per JI-021.
|
|
10
12
|
* 2. run the work-order's real_check_criteria via runRealChecks
|
|
11
|
-
* (deterministic verdict
|
|
13
|
+
* (deterministic verdict — never the
|
|
12
14
|
* executing agent's self-report).
|
|
13
15
|
* 3. on pass: commit-attested with writer-identity footer; final_status
|
|
14
16
|
* = "completed".
|
|
@@ -21,10 +23,10 @@
|
|
|
21
23
|
* / commit-attested per iteration.
|
|
22
24
|
*
|
|
23
25
|
* Per DEC-0014 the orchestrator-side composite is the only authorized
|
|
24
|
-
* driver of this loop;
|
|
26
|
+
* driver of this loop; the agent_grant the orchestrator
|
|
25
27
|
* passes is composed (intersected) at the call-agent dispatch boundary.
|
|
26
28
|
*/
|
|
27
|
-
import type {
|
|
29
|
+
import type { JitAgentResult } from "@davidorex/pi-jit-agents/types";
|
|
28
30
|
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
29
31
|
import { type AttestedCommitResult, attestedCommit as canonicalAttestedCommit } from "./attested-commit.js";
|
|
30
32
|
import { runRealChecks as canonicalRunRealChecks, type RealCheckCriteria, type RealCheckResult } from "./real-check-runner.js";
|
|
@@ -41,7 +43,7 @@ export interface WorkOrderIteration {
|
|
|
41
43
|
export interface WorkOrderLoopResult {
|
|
42
44
|
work_order_id: string;
|
|
43
45
|
iterations: WorkOrderIteration[];
|
|
44
|
-
final_status: "completed" | "failed" | "aborted-by-human";
|
|
46
|
+
final_status: "completed" | "failed" | "aborted-by-human" | "aborted-non-interactive";
|
|
45
47
|
commit_sha?: string;
|
|
46
48
|
total_duration_ms: number;
|
|
47
49
|
}
|
|
@@ -59,21 +61,39 @@ interface WorkOrderRecord {
|
|
|
59
61
|
directories?: string[];
|
|
60
62
|
operations?: string[];
|
|
61
63
|
};
|
|
64
|
+
input_contract?: Record<string, unknown>;
|
|
62
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* Clamp a composed tool grant to the operations the work-order's `scope`
|
|
68
|
+
* declares. The work-order's declared operation scope is the outer bound —
|
|
69
|
+
* the dispatched agent can never exceed the operations the work-order itself
|
|
70
|
+
* authorizes, regardless of the caller's agent_grant. When the work-order
|
|
71
|
+
* declares no `scope.operations` (absent or empty array), the composed grant
|
|
72
|
+
* is returned unchanged.
|
|
73
|
+
*/
|
|
74
|
+
export declare function clampToScope(composedGrant: string[], operations?: string[]): string[];
|
|
75
|
+
/**
|
|
76
|
+
* Validate a work-order dispatch input against the work-order's declared
|
|
77
|
+
* `input_contract` (an inline JSON Schema). Reuses the canonical pi-context
|
|
78
|
+
* AJV validator (shared instance / strictness / formats) rather than standing
|
|
79
|
+
* up a parallel validator. On a contract violation THROWS an error naming the
|
|
80
|
+
* work-order id and the AJV error detail (the loop surfaces thrown errors);
|
|
81
|
+
* when no contract is declared this is a no-op pass-through.
|
|
82
|
+
*/
|
|
83
|
+
export declare function validateWorkOrderInput(input: Record<string, unknown>, contract: Record<string, unknown> | undefined, workOrderId: string): void;
|
|
63
84
|
/**
|
|
64
85
|
* Internal indirection — tests substitute these to short-circuit the
|
|
65
|
-
*
|
|
86
|
+
* subprocess dispatch / real-check / commit paths. Production code path never
|
|
66
87
|
* reassigns; the same indirection pattern as call-agent-tool._internals.
|
|
67
88
|
*/
|
|
68
89
|
type DispatchTargetAgent = (cwd: string, wo: WorkOrderRecord, agentGrant: string[], ctx: ExtensionContext) => Promise<JitAgentResult>;
|
|
69
90
|
export declare const _internals: {
|
|
70
|
-
executeAgent: (c: CompiledAgent, d: DispatchContext) => Promise<JitAgentResult>;
|
|
71
91
|
runRealChecks: typeof canonicalRunRealChecks;
|
|
72
92
|
attestedCommit: typeof canonicalAttestedCommit;
|
|
73
93
|
/**
|
|
74
|
-
* Tests reassign this to short-circuit the
|
|
75
|
-
*
|
|
76
|
-
*
|
|
94
|
+
* Tests reassign this to short-circuit the spec compile + `pi` subprocess
|
|
95
|
+
* dispatch chain. Production code path runs the default canonical
|
|
96
|
+
* implementation below.
|
|
77
97
|
*/
|
|
78
98
|
dispatchTargetAgent: DispatchTargetAgent | undefined;
|
|
79
99
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"work-order-loop.d.ts","sourceRoot":"","sources":["../src/work-order-loop.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"work-order-loop.d.ts","sourceRoot":"","sources":["../src/work-order-loop.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAOH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACxE,OAAO,EAAE,KAAK,oBAAoB,EAAE,cAAc,IAAI,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAI5G,OAAO,EACN,aAAa,IAAI,sBAAsB,EACvC,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,MAAM,wBAAwB,CAAC;AAGhC,qBAAa,sBAAuB,SAAQ,KAAK;gBACpC,WAAW,EAAE,MAAM;CAI/B;AAED,MAAM,WAAW,kBAAkB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,OAAO,CAAC;IACtB,iBAAiB,EAAE,eAAe,CAAC;IACnC,sBAAsB,CAAC,EAAE,oBAAoB,CAAC;IAC9C,MAAM,EAAE,QAAQ,GAAG,QAAQ,CAAC;CAC5B;AAED,MAAM,WAAW,mBAAmB;IACnC,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,kBAAkB,EAAE,CAAC;IACjC,YAAY,EAAE,WAAW,GAAG,QAAQ,GAAG,kBAAkB,GAAG,yBAAyB,CAAC;IACtF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,oBAAoB;IACpC,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,UAAU,eAAe;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,CAAC,EAAE,iBAAiB,CAAC;IACxC,KAAK,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAC5E,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACzC;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,aAAa,EAAE,MAAM,EAAE,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAIrF;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACrC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAC7C,WAAW,EAAE,MAAM,GACjB,IAAI,CAWN;AAED;;;;GAIG;AACH,KAAK,mBAAmB,GAAG,CAC1B,GAAG,EAAE,MAAM,EACX,EAAE,EAAE,eAAe,EACnB,UAAU,EAAE,MAAM,EAAE,EACpB,GAAG,EAAE,gBAAgB,KACjB,OAAO,CAAC,cAAc,CAAC,CAAC;AAE7B,eAAO,MAAM,UAAU;;;IAGtB;;;;OAIG;yBAC+B,mBAAmB,GAAG,SAAS;CACjE,CAAC;AAwEF,wBAAsB,gBAAgB,CACrC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,oBAAoB,EAC7B,GAAG,EAAE,gBAAgB,GACnB,OAAO,CAAC,mBAAmB,CAAC,CAiF9B"}
|
package/dist/work-order-loop.js
CHANGED
|
@@ -5,10 +5,12 @@
|
|
|
5
5
|
* drives the end-to-end loop the work-order encodes:
|
|
6
6
|
*
|
|
7
7
|
* for iteration in 0..max_iterations:
|
|
8
|
-
* 1. dispatch the work-order's target_agent
|
|
9
|
-
*
|
|
8
|
+
* 1. dispatch the work-order's target_agent as a `pi` subprocess (FGAP-124
|
|
9
|
+
* — the only path that binds real, callable tools; pi-jit-agents'
|
|
10
|
+
* executeAgent binds none). pi-jit-agents stays the classify /
|
|
11
|
+
* structured-output library primitive per JI-021.
|
|
10
12
|
* 2. run the work-order's real_check_criteria via runRealChecks
|
|
11
|
-
* (deterministic verdict
|
|
13
|
+
* (deterministic verdict — never the
|
|
12
14
|
* executing agent's self-report).
|
|
13
15
|
* 3. on pass: commit-attested with writer-identity footer; final_status
|
|
14
16
|
* = "completed".
|
|
@@ -21,67 +23,127 @@
|
|
|
21
23
|
* / commit-attested per iteration.
|
|
22
24
|
*
|
|
23
25
|
* Per DEC-0014 the orchestrator-side composite is the only authorized
|
|
24
|
-
* driver of this loop;
|
|
26
|
+
* driver of this loop; the agent_grant the orchestrator
|
|
25
27
|
* passes is composed (intersected) at the call-agent dispatch boundary.
|
|
26
28
|
*/
|
|
27
29
|
import { readBlock } from "@davidorex/pi-context/block-api";
|
|
30
|
+
import { validate } from "@davidorex/pi-context/schema-validator";
|
|
28
31
|
import { createAgentLoader } from "@davidorex/pi-jit-agents/agent-spec";
|
|
29
32
|
import { compileAgent } from "@davidorex/pi-jit-agents/compile";
|
|
30
|
-
import {
|
|
31
|
-
import { createTemplateEnv } from "@davidorex/pi-jit-agents/template";
|
|
33
|
+
import { bundledTemplateDir, createTemplateEnv } from "@davidorex/pi-jit-agents/template";
|
|
32
34
|
import { attestedCommit as canonicalAttestedCommit } from "./attested-commit.js";
|
|
33
35
|
import { composeToolGrant } from "./capability-composer.js";
|
|
36
|
+
import { dispatchLoadContext } from "./dispatch-loader.js";
|
|
37
|
+
import { resolveDispatchModel } from "./dispatch-model.js";
|
|
34
38
|
import { runRealChecks as canonicalRunRealChecks, } from "./real-check-runner.js";
|
|
39
|
+
import { runPiSubprocess } from "./subprocess-dispatch.js";
|
|
35
40
|
export class WorkOrderNotFoundError extends Error {
|
|
36
41
|
constructor(workOrderId) {
|
|
37
42
|
super(`work-order-loop: work-order '${workOrderId}' not found in work-orders block`);
|
|
38
43
|
this.name = "WorkOrderNotFoundError";
|
|
39
44
|
}
|
|
40
45
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
+
/**
|
|
47
|
+
* Clamp a composed tool grant to the operations the work-order's `scope`
|
|
48
|
+
* declares. The work-order's declared operation scope is the outer bound —
|
|
49
|
+
* the dispatched agent can never exceed the operations the work-order itself
|
|
50
|
+
* authorizes, regardless of the caller's agent_grant. When the work-order
|
|
51
|
+
* declares no `scope.operations` (absent or empty array), the composed grant
|
|
52
|
+
* is returned unchanged.
|
|
53
|
+
*/
|
|
54
|
+
export function clampToScope(composedGrant, operations) {
|
|
55
|
+
if (!operations || operations.length === 0)
|
|
56
|
+
return composedGrant;
|
|
57
|
+
const allowed = new Set(operations);
|
|
58
|
+
return composedGrant.filter((t) => allowed.has(t));
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Validate a work-order dispatch input against the work-order's declared
|
|
62
|
+
* `input_contract` (an inline JSON Schema). Reuses the canonical pi-context
|
|
63
|
+
* AJV validator (shared instance / strictness / formats) rather than standing
|
|
64
|
+
* up a parallel validator. On a contract violation THROWS an error naming the
|
|
65
|
+
* work-order id and the AJV error detail (the loop surfaces thrown errors);
|
|
66
|
+
* when no contract is declared this is a no-op pass-through.
|
|
67
|
+
*/
|
|
68
|
+
export function validateWorkOrderInput(input, contract, workOrderId) {
|
|
69
|
+
if (!contract)
|
|
70
|
+
return;
|
|
71
|
+
try {
|
|
72
|
+
validate(contract, input, `work-order '${workOrderId}' input_contract`);
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
throw new Error(`work-order-loop: dispatch input for work-order '${workOrderId}' violates its input_contract: ${err instanceof Error ? err.message : String(err)}`);
|
|
76
|
+
}
|
|
46
77
|
}
|
|
47
78
|
export const _internals = {
|
|
48
|
-
executeAgent: canonicalExecuteAgent,
|
|
49
79
|
runRealChecks: canonicalRunRealChecks,
|
|
50
80
|
attestedCommit: canonicalAttestedCommit,
|
|
51
81
|
/**
|
|
52
|
-
* Tests reassign this to short-circuit the
|
|
53
|
-
*
|
|
54
|
-
*
|
|
82
|
+
* Tests reassign this to short-circuit the spec compile + `pi` subprocess
|
|
83
|
+
* dispatch chain. Production code path runs the default canonical
|
|
84
|
+
* implementation below.
|
|
55
85
|
*/
|
|
56
86
|
dispatchTargetAgent: undefined,
|
|
57
87
|
};
|
|
58
|
-
|
|
59
|
-
|
|
88
|
+
/**
|
|
89
|
+
* Dispatch the work-order's target agent as a `pi` subprocess (FGAP-124).
|
|
90
|
+
*
|
|
91
|
+
* The subprocess is the ONLY execution path that binds real, callable tools —
|
|
92
|
+
* pi-jit-agents `executeAgent` binds none (it materializes only a phantom
|
|
93
|
+
* output-schema tool), so an agent granted [write,bash] through that library
|
|
94
|
+
* primitive can never act. We reuse pi-workflows' proven subprocess pattern:
|
|
95
|
+
* compile the spec for its rendered task prompt + model + tool grant, then
|
|
96
|
+
* spawn `pi --mode json --model <spec> --tools <composedGrant> -p <prompt>`
|
|
97
|
+
* in `cwd` and collect the final assistant output. pi resolves model + auth
|
|
98
|
+
* itself inside the subprocess (operator auth.json), so no DispatchContext
|
|
99
|
+
* auth is threaded — `ctx` is retained only to satisfy the seam signature.
|
|
100
|
+
*/
|
|
101
|
+
async function dispatchTargetAgent(cwd, wo, agentGrant, _ctx) {
|
|
102
|
+
const loadAgent = createAgentLoader(dispatchLoadContext(cwd));
|
|
60
103
|
const spec = loadAgent(wo.target_agent);
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
104
|
+
// builtinDir = bundled pi-jit-agents templates/, so a bundled spec's task/system
|
|
105
|
+
// templates resolve without a local copy.
|
|
106
|
+
const env = createTemplateEnv({ cwd, builtinDir: bundledTemplateDir() });
|
|
107
|
+
// Guard the dispatch input against the work-order's declared input_contract
|
|
108
|
+
// BEFORE compiling/spawning; a contract violation throws and the loop
|
|
109
|
+
// surfaces it (no subprocess is spawned on a bad input).
|
|
110
|
+
const input = { work_order_id: wo.id };
|
|
111
|
+
validateWorkOrderInput(input, wo.input_contract, wo.id);
|
|
112
|
+
const compiled = compileAgent(spec, { env, input, cwd });
|
|
113
|
+
// Model precedence (DEC-0023): compiled/spec model → model-config by_role[role]
|
|
114
|
+
// → default → null. A null result is NOT an error for subprocess dispatch — no
|
|
115
|
+
// `--model` is passed and pi resolves its own default inside the subprocess.
|
|
116
|
+
const modelSpec = compiled.model ?? spec.model ?? resolveDispatchModel(cwd, spec) ?? undefined;
|
|
117
|
+
// Intersect at dispatch boundary (parent ∩ requested = agentGrant ∩ spec.tools).
|
|
118
|
+
// The clamp now actually reaches execution: composedGrant becomes the
|
|
119
|
+
// subprocess `--tools` allowlist (empty grant → `--no-tools`).
|
|
120
|
+
const composedGrant = composeToolGrant(agentGrant, spec.tools);
|
|
121
|
+
// The work-order's declared operation scope is the outer bound — clamp the
|
|
122
|
+
// composed grant to wo.scope.operations so the dispatched agent can never
|
|
123
|
+
// exceed the operations the work-order itself authorizes, regardless of the
|
|
124
|
+
// caller's agent_grant. Absent/empty scope.operations → composedGrant
|
|
125
|
+
// unchanged.
|
|
126
|
+
const finalGrant = clampToScope(composedGrant, wo.scope?.operations);
|
|
127
|
+
const result = await runPiSubprocess({
|
|
128
|
+
cwd,
|
|
129
|
+
model: modelSpec,
|
|
130
|
+
tools: finalGrant,
|
|
131
|
+
prompt: compiled.taskPrompt,
|
|
132
|
+
});
|
|
133
|
+
if (result.exitCode !== 0 || result.timedOut) {
|
|
134
|
+
throw new Error(`work-order-loop: pi subprocess for agent '${wo.target_agent}' ` +
|
|
135
|
+
`${result.timedOut ? "timed out" : `exited with code ${result.exitCode}`}` +
|
|
136
|
+
`${result.stderr ? `: ${result.stderr}` : ""}`);
|
|
71
137
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
138
|
+
if (!result.text) {
|
|
139
|
+
throw new Error(`work-order-loop: pi subprocess for agent '${wo.target_agent}' produced no assistant output ` +
|
|
140
|
+
`(exit ${result.exitCode})${result.stderr ? `: ${result.stderr}` : ""}`);
|
|
75
141
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
auth: { apiKey: auth.apiKey ?? "", headers: auth.headers ?? {} },
|
|
81
|
-
parentGrant: composedGrant,
|
|
82
|
-
maxTokens: 1024,
|
|
142
|
+
return {
|
|
143
|
+
output: result.text,
|
|
144
|
+
raw: result.lastAssistantMessage,
|
|
145
|
+
usage: result.usage,
|
|
83
146
|
};
|
|
84
|
-
return _internals.executeAgent(compiled, dispatch);
|
|
85
147
|
}
|
|
86
148
|
export async function runWorkOrderLoop(cwd, options, ctx) {
|
|
87
149
|
const start = Date.now();
|
|
@@ -130,6 +192,15 @@ export async function runWorkOrderLoop(cwd, options, ctx) {
|
|
|
130
192
|
// the loop will exit naturally as "failed" without asking the user
|
|
131
193
|
// whether to retry past max_iterations.
|
|
132
194
|
if (i < maxIterations - 1) {
|
|
195
|
+
// Non-interactive contexts have no human to ask. Do NOT call
|
|
196
|
+
// ctx.ui.confirm (which would return an environment default) and
|
|
197
|
+
// mislabel that default as a human decision. Mirror the auth-gate
|
|
198
|
+
// pattern (auth-gate.ts checks !ctx.hasUI first) and record the
|
|
199
|
+
// distinct "aborted-non-interactive" status.
|
|
200
|
+
if (ctx.hasUI === false) {
|
|
201
|
+
finalStatus = "aborted-non-interactive";
|
|
202
|
+
break;
|
|
203
|
+
}
|
|
133
204
|
const failExcerpt = JSON.stringify(realCheck.details, null, 2).slice(0, 500);
|
|
134
205
|
const proceed = await ctx.ui.confirm("Real-check failed", `Iteration ${i + 1}/${maxIterations} failed. Retry?\nFail-report: ${failExcerpt}`);
|
|
135
206
|
if (!proceed) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"work-order-loop.js","sourceRoot":"","sources":["../src/work-order-loop.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"work-order-loop.js","sourceRoot":"","sources":["../src/work-order-loop.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@davidorex/pi-agent-dispatch",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.33.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -42,13 +42,13 @@
|
|
|
42
42
|
"clean": "rm -rf dist",
|
|
43
43
|
"build": "rm -rf dist && tsc -p tsconfig.build.json",
|
|
44
44
|
"prepublishOnly": "npm run clean && npm run build",
|
|
45
|
-
"test": "tsx --test src/*.test.ts"
|
|
45
|
+
"test": "tsx --test --test-timeout=120000 src/*.test.ts"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@davidorex/pi-behavior-monitors": "^0.
|
|
49
|
-
"@davidorex/pi-context": "^0.
|
|
50
|
-
"@davidorex/pi-jit-agents": "^0.
|
|
51
|
-
"@davidorex/pi-workflows": "^0.
|
|
48
|
+
"@davidorex/pi-behavior-monitors": "^0.33.0",
|
|
49
|
+
"@davidorex/pi-context": "^0.33.0",
|
|
50
|
+
"@davidorex/pi-jit-agents": "^0.33.0",
|
|
51
|
+
"@davidorex/pi-workflows": "^0.33.0",
|
|
52
52
|
"@earendil-works/pi-ai": "^0.75.4",
|
|
53
53
|
"@earendil-works/pi-coding-agent": "^0.75.4",
|
|
54
54
|
"yaml": "^2.7.1"
|
|
@@ -29,7 +29,7 @@ Dispatch a privileged JIT-agent as a typed tool call. Loads the named .agent.yam
|
|
|
29
29
|
|
|
30
30
|
| Parameter | Type | Required | Description |
|
|
31
31
|
|-----------|------|----------|-------------|
|
|
32
|
-
| `spec_name` | string | yes | Name of the agent spec to load (resolves to <name>.agent.yaml
|
|
32
|
+
| `spec_name` | string | yes | Name of the agent spec to load (resolves to <name>.agent.yaml searched across the substrate agents/ dir, then ~/.pi/agent/agents/, then the bundled pi-workflows agents). |
|
|
33
33
|
| `input` | unknown | yes | Typed input passed to the agent's compileAgent context. |
|
|
34
34
|
| `parent_grant` | array | no | The caller's own tool grant. Default-empty. |
|
|
35
35
|
| `requested_grant` | array | no | The grant requested for the dispatched sub-agent. Will be clamped to the intersection with parent_grant. |
|