@tshu-w/pi-agents 0.0.0-stage → 0.1.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/LICENSE +661 -0
- package/README.md +81 -2
- package/bin/daemon.mjs +204 -0
- package/bin/host.mjs +170 -0
- package/bin/pd.mjs +139 -0
- package/docs/PROGRAM.md +310 -0
- package/docs/SPEC.md +427 -0
- package/docs/WORKBENCH.md +165 -0
- package/package.json +62 -4
- package/src/agents/agents.ts +882 -0
- package/src/agents/registry.ts +257 -0
- package/src/agents/scheduler.ts +204 -0
- package/src/agents/search.ts +131 -0
- package/src/agents/tool.ts +205 -0
- package/src/daemon/client.mjs +84 -0
- package/src/daemon/router.mjs +103 -0
- package/src/daemon/sessions.mjs +129 -0
- package/src/daemon/version.mjs +19 -0
- package/src/host/client.mjs +139 -0
- package/src/host/extension.ts +74 -0
- package/src/host/frames.mjs +34 -0
- package/src/host/keys.mjs +19 -0
- package/src/index.ts +208 -0
- package/src/output.ts +56 -0
- package/src/params.ts +4 -0
- package/src/pi.mjs +16 -0
- package/src/programs/codemode.ts +74 -0
- package/src/programs/execute.ts +131 -0
- package/src/programs/host-patches.ts +128 -0
- package/src/programs/loadout.ts +99 -0
- package/src/programs/programs.ts +284 -0
- package/src/programs/sandbox.ts +90 -0
- package/src/programs/scope.ts +94 -0
- package/src/programs/tool.ts +198 -0
- package/src/render-call.ts +90 -0
- package/src/roots/discovery.mjs +113 -0
- package/src/roots/guard.mjs +227 -0
- package/src/roots/lock-extension.mjs +167 -0
- package/src/roots/locks.mjs +167 -0
- package/src/roots/paths.mjs +66 -0
- package/src/roots/report.ts +156 -0
- package/src/roots/runtime.ts +174 -0
- package/src/roots/snapshot.mjs +46 -0
- package/src/roots/socket-recovery.mjs +21 -0
- package/src/roots/transport.mjs +341 -0
- package/src/ui/panel.ts +96 -0
- package/src/ui/viewer.ts +445 -0
- package/src/workbench.mjs +587 -0
package/docs/PROGRAM.md
ADDED
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
# Pi Agents Program Specification
|
|
2
|
+
|
|
3
|
+
A Program is JavaScript that calls tools and Agents. Agents are defined in
|
|
4
|
+
SPEC.md.
|
|
5
|
+
|
|
6
|
+
The `program` tool replaces Pi's `codemode` tool and keeps its script API,
|
|
7
|
+
tool list, result format, and truncation. This document describes what
|
|
8
|
+
Programs add.
|
|
9
|
+
|
|
10
|
+
## 1. Semantic model
|
|
11
|
+
|
|
12
|
+
An Agent runs a **Program** with the `program` tool. That Agent is the
|
|
13
|
+
Program's **caller**. The Program can call the caller's tools and create
|
|
14
|
+
Agents.
|
|
15
|
+
|
|
16
|
+
A Program runs in the **foreground** or the **background**. In the
|
|
17
|
+
foreground, the tool call returns the Program's result. In the background,
|
|
18
|
+
the tool call returns the Program's ID, and the caller gets the result with
|
|
19
|
+
`wait`.
|
|
20
|
+
|
|
21
|
+
A Program is shown by its short ID: the shortest prefix of its ID, at least
|
|
22
|
+
8 characters, that none of the caller's other Programs' IDs starts with. A
|
|
23
|
+
target is an ID or a unique ID prefix.
|
|
24
|
+
|
|
25
|
+
Agents created with `agent()` belong to the Program: it gets their results
|
|
26
|
+
from `send()`, without `wait` or notifications, and only it can abort
|
|
27
|
+
them. Each of these Agents and the Agents under it see only one another,
|
|
28
|
+
and no other Agent sees them. The user sees them in `/tasks` and `/agents`,
|
|
29
|
+
and can talk to them or interrupt them in the viewer; an interrupted input
|
|
30
|
+
makes its `send()` throw. When the Program ends, their unfinished inputs end
|
|
31
|
+
as `aborted`, and the Agents go offline for good, from the bottom up.
|
|
32
|
+
|
|
33
|
+
A Program is `running` until it ends in one of three ways:
|
|
34
|
+
|
|
35
|
+
- `completed`: it returned.
|
|
36
|
+
- `failed`: it threw an error.
|
|
37
|
+
- `stopped`: it was stopped or timed out.
|
|
38
|
+
|
|
39
|
+
## 2. Operations
|
|
40
|
+
|
|
41
|
+
- `run` runs a Program in the foreground or background, with an optional
|
|
42
|
+
timeout.
|
|
43
|
+
- `wait` waits for background Programs and returns their results.
|
|
44
|
+
- `list` lists the caller's background Programs.
|
|
45
|
+
- `stop` stops a running Program.
|
|
46
|
+
|
|
47
|
+
When a background Program ends and its caller is not waiting for it, the
|
|
48
|
+
caller gets a notification, as in SPEC §5.
|
|
49
|
+
|
|
50
|
+
## 3. Program API
|
|
51
|
+
|
|
52
|
+
`tools` holds the caller's tools, except `program`; which tools the caller
|
|
53
|
+
can use is checked at each call. If a Program fails or is stopped, the
|
|
54
|
+
error or stop reason follows its output. Its `store()` writes are kept
|
|
55
|
+
only if it completes.
|
|
56
|
+
|
|
57
|
+
A Program also creates Agents with `agent()`:
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
agent(options?: {
|
|
61
|
+
name?: string;
|
|
62
|
+
cwd?: string;
|
|
63
|
+
context?: "fresh" | "fork";
|
|
64
|
+
model?: string;
|
|
65
|
+
thinkingLevel?: string;
|
|
66
|
+
}): AgentHandle
|
|
67
|
+
|
|
68
|
+
interface AgentHandle {
|
|
69
|
+
readonly id: string;
|
|
70
|
+
readonly name: string;
|
|
71
|
+
send(message: string, options?: {
|
|
72
|
+
deliverAs?: "followUp" | "steer" | "write";
|
|
73
|
+
schema?: JsonSchema;
|
|
74
|
+
}): Promise<unknown>;
|
|
75
|
+
abort(): Promise<void>;
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
`agent()` creates an idle Agent. Options work like `agent` `spawn`; an
|
|
80
|
+
omitted name is generated, unique within the Program. `send()` sends a
|
|
81
|
+
message and returns its result. `abort()` works like `agent` `abort`.
|
|
82
|
+
It gets its tools as if the caller had spawned it.
|
|
83
|
+
|
|
84
|
+
A result is the Agent's answer. If the input fails or is aborted, the
|
|
85
|
+
result throws an Error. A write returns `undefined` once accepted.
|
|
86
|
+
|
|
87
|
+
With `schema`, the Agent must call `submit_result` with a value that
|
|
88
|
+
matches the schema, and the result is that value. If it does not, the
|
|
89
|
+
input fails. `send()` throws if `schema` is used without `followUp`.
|
|
90
|
+
|
|
91
|
+
## 4. Lifecycle
|
|
92
|
+
|
|
93
|
+
When a Program ends, it cancels its unfinished tool calls and aborts its
|
|
94
|
+
Agents' unfinished inputs, and waits for its Agents to go offline. It
|
|
95
|
+
returns its result after cleanup. Work not stopped within the cleanup
|
|
96
|
+
timeout is abandoned and may keep running; the Program's result and `stop`
|
|
97
|
+
report it as an error.
|
|
98
|
+
Stopping a Program does not undo completed tool calls.
|
|
99
|
+
|
|
100
|
+
When the caller goes offline, its running Programs stop. Their results
|
|
101
|
+
remain available when the caller is loaded again.
|
|
102
|
+
|
|
103
|
+
## 5. Limits
|
|
104
|
+
|
|
105
|
+
A Program's Agents and the Agents under them count toward the caller's
|
|
106
|
+
tree: they share its slots and `maxOutstanding` limit, as in SPEC §4. At
|
|
107
|
+
`maxOutstanding`, `send()` throws.
|
|
108
|
+
|
|
109
|
+
An owned caller gives up its slot while a foreground Program runs or while
|
|
110
|
+
it waits for background Programs, and takes one again before continuing.
|
|
111
|
+
|
|
112
|
+
## 6. Model-facing tool
|
|
113
|
+
|
|
114
|
+
### `program`
|
|
115
|
+
|
|
116
|
+
description:
|
|
117
|
+
|
|
118
|
+
Run JavaScript that composes tool calls and Agents; only its output and
|
|
119
|
+
return value reach the caller. `run` runs a Program in the foreground, or
|
|
120
|
+
in the background with `background`; `wait` waits for background Programs
|
|
121
|
+
and returns their results; `list` lists background Programs; `stop` stops
|
|
122
|
+
a running Program. When a background Program ends while its caller is not
|
|
123
|
+
waiting for it, the caller receives a notification; `wait` returns the
|
|
124
|
+
result.
|
|
125
|
+
|
|
126
|
+
Program code is the body of an async function. It calls the caller's tools
|
|
127
|
+
through `tools.*`, which excludes `program`, and creates Agents through
|
|
128
|
+
`agent()`. These Agents belong to the Program, are isolated from other
|
|
129
|
+
Agents, and go offline when it ends.
|
|
130
|
+
|
|
131
|
+
`program` replaces the `codemode` tool; wherever `codemode` is mentioned,
|
|
132
|
+
use `program`.
|
|
133
|
+
|
|
134
|
+
[the script API of `codemode`, without its Model API]
|
|
135
|
+
|
|
136
|
+
Agent API:
|
|
137
|
+
```ts
|
|
138
|
+
type JsonSchema = boolean | Record<string, unknown>;
|
|
139
|
+
interface AgentOptions {
|
|
140
|
+
/** Default: generated, unique within the Program. */
|
|
141
|
+
name?: string;
|
|
142
|
+
/** Default: the caller's cwd. */
|
|
143
|
+
cwd?: string;
|
|
144
|
+
/** `fresh` starts without the caller's conversation; `fork` snapshots it. Default: `fresh`. */
|
|
145
|
+
context?: "fresh" | "fork";
|
|
146
|
+
/** provider/modelId. Default: the caller's model. */
|
|
147
|
+
model?: string;
|
|
148
|
+
/** Default: the caller's level. */
|
|
149
|
+
thinkingLevel?: string;
|
|
150
|
+
}
|
|
151
|
+
interface SendOptions {
|
|
152
|
+
/** Default: `followUp`. */
|
|
153
|
+
deliverAs?: "followUp" | "steer" | "write";
|
|
154
|
+
/** `followUp` only. The Agent must submit a value matching it. */
|
|
155
|
+
schema?: JsonSchema;
|
|
156
|
+
}
|
|
157
|
+
interface AgentHandle {
|
|
158
|
+
readonly id: string;
|
|
159
|
+
readonly name: string;
|
|
160
|
+
/** Resolves with the answer, or with the submitted value when `schema` is set; a write resolves with undefined once accepted. Throws if the input fails or is aborted. */
|
|
161
|
+
send(message: string, options?: SendOptions): Promise<unknown>;
|
|
162
|
+
/** Aborts the Agent's current turn and queued inputs; the Agent stays usable. */
|
|
163
|
+
abort(): Promise<void>;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/** Creates an idle Agent that belongs to the Program. */
|
|
167
|
+
declare function agent(options?: AgentOptions): AgentHandle;
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
[the Model API of `codemode`]
|
|
171
|
+
|
|
172
|
+
[the tool list, as set by `codemode.mode`]
|
|
173
|
+
|
|
174
|
+
promptSnippet:
|
|
175
|
+
|
|
176
|
+
Run JavaScript that composes tool calls and Agents
|
|
177
|
+
|
|
178
|
+
promptGuidelines:
|
|
179
|
+
|
|
180
|
+
- Use `program(action='run', code=...)` to call tools or Agents several
|
|
181
|
+
times without a model turn between the calls, for example to read many
|
|
182
|
+
files, filter large tool output, fan out Agents, or loop until a
|
|
183
|
+
condition holds.
|
|
184
|
+
- Use `Promise.allSettled` for independent calls. Return only what the
|
|
185
|
+
caller needs; use `text()` for progress worth reading.
|
|
186
|
+
- Use `background=true` for long Programs, and `program(action='wait', ...)`
|
|
187
|
+
when the next step depends on their results.
|
|
188
|
+
|
|
189
|
+
parameters:
|
|
190
|
+
|
|
191
|
+
- `action`: Operation and applicable parameters: `run(code, background?, timeout?)`, `wait(target?, timeout?)`, `list(limit?, offset?)`, or `stop(target)`.
|
|
192
|
+
- `code`: JavaScript async-function body for `run`.
|
|
193
|
+
- `background`: Whether `run` returns the Program ID at once (default: false).
|
|
194
|
+
- `timeout`: Maximum seconds. For `run` (default: none), expiry stops the Program. For `wait` (default: 30, min: 10, max: 3600), expiry does not stop Programs.
|
|
195
|
+
- `target`: Program ID or unique ID prefix for `wait` or `stop`. `wait` also accepts an array. When omitted for `wait`, selects running Programs and ended Programs whose result has not been returned.
|
|
196
|
+
- `limit`: Maximum Programs returned by `list` (default: 20, max: 200).
|
|
197
|
+
- `offset`: Number of Programs to skip for `list` (default: 0).
|
|
198
|
+
|
|
199
|
+
results:
|
|
200
|
+
|
|
201
|
+
In these formats, `<id>` is the Program's short ID.
|
|
202
|
+
|
|
203
|
+
`run` in the foreground returns the Program result, as an error if the
|
|
204
|
+
Program failed or was stopped.
|
|
205
|
+
|
|
206
|
+
`run` in the background:
|
|
207
|
+
|
|
208
|
+
```text
|
|
209
|
+
Program <id> started.
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
`wait` returns one block per result, followed by running Programs on
|
|
213
|
+
timeout:
|
|
214
|
+
|
|
215
|
+
```text
|
|
216
|
+
<program-result id="<id>" status="<outcome>">
|
|
217
|
+
<result>
|
|
218
|
+
</program-result>
|
|
219
|
+
|
|
220
|
+
Still running: <id>, ...
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
A single completed result, with nothing running, is returned alone. When
|
|
224
|
+
there are no results or running Programs:
|
|
225
|
+
|
|
226
|
+
```text
|
|
227
|
+
No results.
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
`list` returns one entry per background Program, newest first:
|
|
231
|
+
|
|
232
|
+
```text
|
|
233
|
+
<id> <state>
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
When more entries remain:
|
|
237
|
+
|
|
238
|
+
```text
|
|
239
|
+
[N more results. Use offset=X to continue.]
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
When there are no background Programs:
|
|
243
|
+
|
|
244
|
+
```text
|
|
245
|
+
No Programs.
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
`stop`:
|
|
249
|
+
|
|
250
|
+
```text
|
|
251
|
+
Program <id> stopped.
|
|
252
|
+
Program <id> has already ended.
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
When some of the Program's work does not stop within the timeout, `stop`
|
|
256
|
+
fails with:
|
|
257
|
+
|
|
258
|
+
```text
|
|
259
|
+
Program <id> did not stop within the timeout and may still be running.
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
and the Program's result ends with:
|
|
263
|
+
|
|
264
|
+
```text
|
|
265
|
+
Cleanup error: some of the Program's work did not stop within the timeout and may still be running.
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
errors:
|
|
269
|
+
|
|
270
|
+
Invalid calls fail with an error. Errors that need a follow-up say what to
|
|
271
|
+
do:
|
|
272
|
+
|
|
273
|
+
```text
|
|
274
|
+
No Program matches "<target>". Use list to find Programs.
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
```text
|
|
278
|
+
"<target>" matches several Programs: <id>, ... Retry with a longer ID prefix.
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
truncation:
|
|
282
|
+
|
|
283
|
+
`wait` text beyond Pi's output limits is truncated as in SPEC §6. `wait`
|
|
284
|
+
adds results in order; the result that crosses the limit is truncated but keeps
|
|
285
|
+
its closing tag, and later results are omitted. A truncated result counts
|
|
286
|
+
as returned. Omitted results stay unreturned, and the text ends with:
|
|
287
|
+
|
|
288
|
+
```text
|
|
289
|
+
[Results omitted: <id>, ... Use wait with fewer targets.]
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
messages:
|
|
293
|
+
|
|
294
|
+
A notification to the caller:
|
|
295
|
+
|
|
296
|
+
```text
|
|
297
|
+
Program <id> <outcome>.
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
## 7. Human interface
|
|
301
|
+
|
|
302
|
+
The task panel (SPEC §7) lists running background Programs.
|
|
303
|
+
|
|
304
|
+
## 8. Configuration
|
|
305
|
+
|
|
306
|
+
`program` is inactive by default, like `codemode`; enable it with `"defaultTools": ["+program"]` or `--tools`.
|
|
307
|
+
MCP treats `program` as `codemode`: it activates `program` when its servers need a script tool and neither is active, unless `autoEnableCodemode` is false, and a Program waits for the MCP servers its code names.
|
|
308
|
+
When both `program` and `codemode` are active, Pi warns once per Session, since they do a similar job.
|
|
309
|
+
`codemode.mode` decides how the tool list is presented, as for `codemode`.
|
|
310
|
+
`--program-only` activates `program` and uses `only` for the process, including its owned Agents.
|