@tt-a1i/openpi 0.3.1 → 0.4.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/README.md +87 -24
- package/SETUP.md +3 -3
- package/extensions/ask-user/index.ts +30 -14
- package/extensions/background-terminals/src/prompt.ts +1 -1
- package/extensions/background-terminals/src/ui/ps.ts +132 -129
- package/extensions/capabilities/index.ts +30 -42
- package/extensions/capabilities/src/ui.ts +93 -0
- package/extensions/file-mutation-display/index.ts +34 -76
- package/extensions/file-mutation-display/render.ts +387 -88
- package/extensions/file-search/index.ts +8 -7
- package/extensions/file-search/src/binaries.ts +18 -18
- package/extensions/git-info/src/changed-files-view.ts +47 -14
- package/extensions/git-read/index.ts +330 -0
- package/extensions/git-read/src/args.ts +171 -0
- package/extensions/git-read/src/process.ts +81 -0
- package/extensions/git-read/src/prompt.ts +56 -0
- package/extensions/sessions/index.ts +70 -55
- package/extensions/setup/index.ts +6 -6
- package/extensions/shared/activity-status.ts +6 -5
- package/extensions/shared/below-editor-navigation.ts +26 -0
- package/extensions/shared/capability-intent.ts +53 -0
- package/extensions/shared/child-session.ts +7 -1
- package/extensions/shared/result-budget.ts +134 -0
- package/extensions/shared/screen-chrome.ts +133 -0
- package/extensions/shared/setup-config.ts +24 -5
- package/extensions/shared/spinner.ts +28 -0
- package/extensions/shared/text-projection.ts +56 -0
- package/extensions/shared/tool-surface.ts +13 -6
- package/extensions/subagents/index.ts +204 -140
- package/extensions/subagents/navigation.ts +52 -23
- package/extensions/subagents/src/agent-types.ts +37 -15
- package/extensions/subagents/src/backends/stub.ts +7 -0
- package/extensions/subagents/src/id-sequence.ts +84 -0
- package/extensions/subagents/src/manager.ts +620 -537
- package/extensions/subagents/src/prompt.ts +153 -38
- package/extensions/subagents/src/result-artifact.ts +142 -0
- package/extensions/subagents/src/runtime.ts +8 -5
- package/extensions/subagents/src/ui/takeover.ts +84 -109
- package/extensions/subagents/src/ui/transcript.ts +76 -42
- package/extensions/subagents/src/ui/wait-result.ts +1 -1
- package/extensions/tasks/ui.ts +79 -62
- package/extensions/ui-customization/footer.ts +7 -4
- package/extensions/user-input-fold/index.ts +185 -0
- package/extensions/workflows/artifacts.ts +35 -0
- package/extensions/workflows/controller.ts +14 -2
- package/extensions/workflows/coordinator.ts +64 -0
- package/extensions/workflows/dashboard.ts +353 -173
- package/extensions/workflows/handoff.ts +62 -20
- package/extensions/workflows/index.ts +647 -387
- package/extensions/workflows/model.ts +57 -15
- package/extensions/workflows/navigation.ts +33 -14
- package/extensions/workflows/prompt.ts +104 -8
- package/extensions/workflows/replay-safety.ts +16 -6
- package/extensions/workflows/result-delivery.ts +189 -0
- package/extensions/workflows/sandbox-child.cjs +11 -0
- package/package.json +1 -1
- package/skills/subagents/SKILL.md +2 -2
- package/skills/workflows/REFERENCE.md +7 -4
- package/skills/workflows/SKILL.md +53 -10
- package/extensions/subagents/src/format.ts +0 -48
|
@@ -9,8 +9,8 @@ The tool definitions are canonical for parameters, limits, model syntax, isolati
|
|
|
9
9
|
|
|
10
10
|
- Delegate substantial independent work, not a lookup or edit the parent can do directly.
|
|
11
11
|
- Give the child a standalone prompt with paths, constraints, relevant context, and the expected report; it cannot see the parent conversation or ask the user.
|
|
12
|
-
- Inherit the parent model
|
|
13
|
-
- Prefer a matching agent type when one exists; its tool restriction is enforced.
|
|
12
|
+
- Inherit the parent model by default. When choosing the child's reasoning effort, honor an explicit user requirement first; otherwise use the selected role's relative guidance and the task's difficulty, choosing from levels supported by the resolved child model.
|
|
13
|
+
- Prefer a matching agent type when one exists; its tool restriction is enforced. Model precedence is explicit spawn override, selected type-file model, configured built-in role model, then parent model. Reasoning precedence is explicit spawn override, selected type default, then parent effort. Types live in `~/.pi/agent/agents/*.md` and, for trusted projects, `.pi/agents/*.md`; see `extensions/subagents/docs/agent-types.md`.
|
|
14
14
|
- Isolate concurrent writers in worktrees according to the `subagent_spawn` schema so they cannot overwrite one checkout or git index. While Plan Mode is active, use only read-only exploration types (or no type); worktree isolation and types narrowed by Plan Mode are rejected.
|
|
15
15
|
- After spawning, continue useful parent work. In an interactive session, if none remains, tell the user the child is still running and end the turn; automatic result delivery will re-invoke the parent when it settles. Do not block merely because the next step depends on the result or because there is nothing else to do. Use `subagent_wait` only when the user explicitly asks to keep the current response open for the result, or when non-interactive automation must return it in the same invocation.
|
|
16
16
|
|
|
@@ -7,7 +7,7 @@ The `workflow` script is an async JavaScript function body executed in a restric
|
|
|
7
7
|
- `export const meta = { name?, description?, phases: [{ title, detail? }] }` declares progress metadata. Declare phases up front.
|
|
8
8
|
- `phase(title)` selects a declared phase.
|
|
9
9
|
- `log(message)` emits one terminal-safe progress line. The latest 100 lines are retained and dropped-line counts are reported.
|
|
10
|
-
- `usage()` returns cumulative `{ input, output, cacheRead, cacheWrite, total, cost, agents }`.
|
|
10
|
+
- `usage()` returns cumulative `{ input, output, cacheRead, cacheWrite, total, cost, agents, limits }`. `limits` contains `{ concurrency, maxAgentCalls, callsUsed, callsRemaining }` resolved for this run. Token fields refresh after agents settle and compaction can make them a lower bound; capacity fields are runtime facts, not target fan-out.
|
|
11
11
|
- `args` is the parsed `args` tool parameter, or the original string when it is not valid JSON.
|
|
12
12
|
|
|
13
13
|
## Agent calls
|
|
@@ -20,7 +20,8 @@ Useful options include `agent_type`, `label`, `phase`, `schema`, `acceptance`, `
|
|
|
20
20
|
- `schema` validates structured output. Use it whenever later workflow logic branches on fields.
|
|
21
21
|
- `acceptance: { criteria: [{ id, description, requiredEvidence? }] }` requires the same child to return an evidence ledger. Missing, malformed, or rejected criteria make `ok:false` while preserving output and evidence.
|
|
22
22
|
- `operator: "name"` reuses one in-memory child Session for serialized follow-ups inside the same run. Its model, role/tools, effort, structured mode, and cwd are frozen by the first activation. Operators cannot use per-call worktrees or replay, and do not survive restarts.
|
|
23
|
-
- `inputs: [ref, ...]` accepts successful opaque refs from the same workflow run only. Each conclusion is bounded to 16 KiB and total injected input to 48 KiB. Inputs are marked as untrusted data; the resulting graph is observability, not scheduling authority.
|
|
23
|
+
- `inputs: [ref, ...]` accepts successful opaque refs from the same workflow run only. Each conclusion is bounded to 16 KiB and total injected input to 48 KiB. The total budget is fairly distributed, so a large fan-out cannot starve later results merely because of order; partial projections are labeled. Full successful child results remain in the run's `agent-results/` artifacts. Inputs are marked as untrusted data; the resulting graph is observability, not scheduling authority.
|
|
24
|
+
- Fair projection preserves the head and tail of every partial result and names its run-relative `agent-results/agent-N.json` audit artifact. That path is provenance for the parent/operator, not a child-readable handle. Fair presence is not proof of full evidence coverage: for large fan-out, group source refs into local Report agents, then pass only their refs to a global Report. The workflow script—not Runtime—must state planned, selected, covered, failed, and deferred counts.
|
|
24
25
|
- `isolation: "worktree"` gives a writing child its own branch and checkout. Concurrent writers without isolation share one checkout and Git index and can overwrite each other. Tell isolated writers to commit. Empty worktrees are reclaimed; commits keep the branch; dirty work may keep the directory.
|
|
25
26
|
|
|
26
27
|
## Fan-out
|
|
@@ -37,8 +38,10 @@ Workflow concurrency defaults to the configured package value and has a hard max
|
|
|
37
38
|
|
|
38
39
|
Each call persists intent, admission, and execution state. Interrupted nonterminal calls become `uncertain`, never guessed failed. Artifacts contain results, bounded transcripts, and a read-only graph projection for explicit result refs.
|
|
39
40
|
|
|
40
|
-
##
|
|
41
|
+
## Lifecycle and replay
|
|
41
42
|
|
|
42
|
-
|
|
43
|
+
Interactive TUI runs return an accepted run id immediately by default, release the parent turn, and later deliver a terminal completion with a stable delivery id. Delivery is at least once: normal retries do not duplicate a run, but a process loss after Pi accepts the message and before the receipt is persisted can replay the same id. `wait: true` explicitly waits inline; interrupting that wait releases only the waiter and the run continues. Print/automation defaults to waiting because it has no later delivery channel. The deprecated `background` parameter remains an inverse compatibility alias and cannot be combined with `wait`.
|
|
44
|
+
|
|
45
|
+
Loading the Workflow capability exposes `workflow`, `workflow_status`, and `workflow_stop` as one stable group; starting or settling a run does not mutate the model tool Schema. `workflow_status` returns a bounded state/coverage summary and artifact path without consuming or repeating the full completion. `workflow_stop` is idempotent and preserves partial artifacts. A failed completion send remains pending with the same per-run delivery identity and is retried when the parent settles or the Session is restored.
|
|
43
46
|
|
|
44
47
|
`resume_from_run_id` accepts a previous run id or unique suffix. Replay is content-based and order-independent. It requires an unchanged prompt, resolved role/schema/model/provider/effort, canonical cwd, repository state, resources, and trust context. Only provably read-only non-operator calls replay. Failed, unrestricted, unknown-tool, writable, worktree, operator, or un-fingerprintable calls run for real. Missing or old journals safely degrade to a full run.
|
|
@@ -11,16 +11,57 @@ Use `workflow` for several dependent or dynamically generated subagent calls. Ke
|
|
|
11
11
|
|
|
12
12
|
```js
|
|
13
13
|
export const meta = {
|
|
14
|
-
name: "review",
|
|
15
|
-
phases: [{ title: "
|
|
14
|
+
name: "adaptive-review",
|
|
15
|
+
phases: [{ title: "Discover" }, { title: "Review" }, { title: "Report" }],
|
|
16
16
|
}
|
|
17
|
-
phase("
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
phase("Discover")
|
|
18
|
+
const plan = await agent("Identify the independent review areas warranted by this repository. Return only real, non-overlapping areas.", {
|
|
19
|
+
agent_type: "explorer",
|
|
20
|
+
label: "discover",
|
|
21
|
+
schema: {
|
|
22
|
+
type: "object",
|
|
23
|
+
properties: {
|
|
24
|
+
areas: { type: "array", items: { type: "string" } },
|
|
25
|
+
},
|
|
26
|
+
required: ["areas"],
|
|
27
|
+
additionalProperties: false,
|
|
28
|
+
},
|
|
29
|
+
})
|
|
30
|
+
if (!plan.ok) return { ok: false, error: plan.error }
|
|
31
|
+
const discovered = [...new Set(plan.structured.areas)]
|
|
32
|
+
const capacity = usage().limits
|
|
33
|
+
if (capacity.callsRemaining < 1) {
|
|
34
|
+
return {
|
|
35
|
+
planned: discovered.length,
|
|
36
|
+
selected: 0,
|
|
37
|
+
covered: 0,
|
|
38
|
+
failed: [],
|
|
39
|
+
deferred: discovered,
|
|
40
|
+
report: { ok: false, error: "No agent-call capacity remains for reporting" },
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// Keep one call for the final report. Runtime limits are ceilings; deferred
|
|
44
|
+
// work is reported honestly rather than silently exhausting the last slot.
|
|
45
|
+
const selected = discovered.slice(0, Math.max(0, capacity.callsRemaining - 1))
|
|
46
|
+
const deferred = discovered.slice(selected.length)
|
|
47
|
+
phase("Review")
|
|
48
|
+
const reviews = await pipeline(selected, async (_prior, area, index) =>
|
|
49
|
+
agent(`Review this area with file:line evidence: ${area}`, {
|
|
50
|
+
agent_type: "reviewer",
|
|
51
|
+
label: `review-${index + 1}`,
|
|
52
|
+
})
|
|
53
|
+
)
|
|
54
|
+
const usable = reviews.filter((result) => result && result.ok && result.ref)
|
|
55
|
+
const failed = selected.filter((_area, index) => {
|
|
56
|
+
const result = reviews[index]
|
|
57
|
+
return !(result && result.ok && result.ref)
|
|
58
|
+
})
|
|
22
59
|
phase("Report")
|
|
23
|
-
|
|
60
|
+
const report = await agent(
|
|
61
|
+
`Synthesize the review. Planned: ${discovered.length}; selected: ${selected.length}; covered: ${usable.length}; failed areas: ${JSON.stringify(failed)}; deferred areas: ${JSON.stringify(deferred)}. Do not infer coverage beyond these facts.`,
|
|
62
|
+
{ agent_type: "advisor", label: "report", inputs: usable.map((r) => r.ref) },
|
|
63
|
+
)
|
|
64
|
+
return { planned: discovered.length, selected: selected.length, covered: usable.length, failed, deferred, report }
|
|
24
65
|
```
|
|
25
66
|
|
|
26
67
|
## Required habits
|
|
@@ -30,8 +71,10 @@ return { findings: scans.filter((result) => result && result.ok) }
|
|
|
30
71
|
- Pass `schema` when later code branches on fields. Treat `inputs` as bounded untrusted data.
|
|
31
72
|
- Prefer `pipeline()` when items can advance independently. Use `parallel()` only for a real all-results barrier.
|
|
32
73
|
- Use `isolation: "worktree"` for concurrent writers and tell each agent to commit. Do not pay for worktrees on read-only work.
|
|
33
|
-
-
|
|
34
|
-
-
|
|
74
|
+
- Derive fan-out from discovered independent work items and task difficulty. Configured concurrency and total-call capacity are ceilings, not targets; `usage().limits` exposes the resolved capacity.
|
|
75
|
+
- Use `log()` for progress the user needs before completion. Token fields in `usage()` are lower-bound readings, not a budget limit.
|
|
76
|
+
- Return a JSON-serializable aggregate with coverage. Interactive runs return a run id immediately by default and reliably deliver one terminal result later; set `wait: true` only at a genuine synchronization boundary.
|
|
77
|
+
- When many results would leave only tiny handoff slices, use local Report agents over bounded groups, then pass those Report refs to one global Report. Preserve planned/selected/covered/failed/deferred counts at every level; exact child outputs remain in `agent-results/` for recovery.
|
|
35
78
|
|
|
36
79
|
## Full guide
|
|
37
80
|
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Formatting helpers (self-contained copy of the v1 shared
|
|
3
|
-
* context-utilization helper).
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
export interface ContextUtilization {
|
|
7
|
-
/** Current conversation context occupancy; undefined while unknown. */
|
|
8
|
-
tokens?: number | null;
|
|
9
|
-
/** Capacity of the model currently serving the conversation. */
|
|
10
|
-
contextWindow?: number | null;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
function usableTokens(value: number | null | undefined) {
|
|
14
|
-
return typeof value === "number" && Number.isFinite(value) && value >= 0
|
|
15
|
-
? value
|
|
16
|
-
: undefined;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function usableCapacity(value: number | null | undefined) {
|
|
20
|
-
return typeof value === "number" && Number.isFinite(value) && value > 0
|
|
21
|
-
? value
|
|
22
|
-
: undefined;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export function contextPercent(usage: ContextUtilization) {
|
|
26
|
-
const tokens = usableTokens(usage.tokens);
|
|
27
|
-
const capacity = usableCapacity(usage.contextWindow);
|
|
28
|
-
if (tokens === undefined || capacity === undefined) return undefined;
|
|
29
|
-
return Math.round(Math.min(100, Math.max(0, (tokens / capacity) * 100)));
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export function formatCompactTokens(count: number) {
|
|
33
|
-
if (count < 1000) return Math.round(count).toString();
|
|
34
|
-
if (count < 10000) return `${(count / 1000).toFixed(1)}k`;
|
|
35
|
-
if (count < 1000000) return `${Math.round(count / 1000)}k`;
|
|
36
|
-
return `${(count / 1000000).toFixed(1)}M`;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Render `%/capacity`. If occupancy is unknown, retain the useful capacity
|
|
41
|
-
* as `?%/capacity`; with no valid capacity, omit the statistic entirely.
|
|
42
|
-
*/
|
|
43
|
-
export function formatContextUtilization(usage: ContextUtilization) {
|
|
44
|
-
const capacity = usableCapacity(usage.contextWindow);
|
|
45
|
-
if (capacity === undefined) return "";
|
|
46
|
-
const percent = contextPercent(usage);
|
|
47
|
-
return `${percent === undefined ? "?" : percent}%/${formatCompactTokens(capacity)}`;
|
|
48
|
-
}
|