@yusukeshib/pi-babysit 0.3.11 → 0.3.13
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 +28 -17
- package/agents.ts +23 -9
- package/index.ts +610 -225
- package/package.json +1 -1
- package/self-reap.ts +30 -23
package/README.md
CHANGED
|
@@ -33,7 +33,7 @@ reachable from anywhere (`~/.pi-babysit/<pi-session-id>/`). Two kinds:
|
|
|
33
33
|
| kind | started by | completion | on completion |
|
|
34
34
|
| ---- | ---------- | ---------- | ------------- |
|
|
35
35
|
| **process** | `babysit_run { command }` | process **exit** | automatic notification message (`triggerTurn`), batched for all exits observed in the same poll — the agent may end its turn after starting and is resumed on exit, same contract as the old `process` tool |
|
|
36
|
-
| **subagent** | `babysit_run { profile: "subagent", task }` | `
|
|
36
|
+
| **subagent** | `babysit_run { profile: "subagent", task }` | `agent_settled` in the RPC event stream (process stays alive) | none — the agent polls `babysit_check` or blocks on `babysit_wait`; the idle session accepts follow-up tasks |
|
|
37
37
|
|
|
38
38
|
The **profile is a tool parameter, not a separate tool set**: domain knowledge
|
|
39
39
|
(RPC bookkeeping, per-task byte offsets, parked-turn detection, PTY-safe
|
|
@@ -62,8 +62,11 @@ programs** (installers, wizards, REPLs): type with `babysit_send`
|
|
|
62
62
|
| `babysit_wait` | Block until done: process exit (or `expect: "regex"` readiness marker), subagent task completion. Multi-wait: `ids` + `mode: "any"\|"all"` |
|
|
63
63
|
| `babysit_kill` | Terminate a session, verify terminal state, then suppress the exit notification |
|
|
64
64
|
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
The built-in `bash` tool is removed from the active tool set so the model does
|
|
66
|
+
not waste a failed tool turn before choosing `babysit_run`. A fallback
|
|
67
|
+
`tool_call` hook still blocks direct shell calls if another extension or preset
|
|
68
|
+
re-enables `bash`, including shell backgrounding (`… &`, `nohup`, `setsid`,
|
|
69
|
+
`disown`). Set `PI_BABYSIT_ALLOW_BASH=1` to retain direct `bash` explicitly.
|
|
67
70
|
|
|
68
71
|
## Commands (human)
|
|
69
72
|
|
|
@@ -91,9 +94,10 @@ babysit_check { id: "cargo-test", lines: 50 }
|
|
|
91
94
|
babysit_check { id: "cargo-test", pattern: "FAIL|ERROR", lines: 50 }
|
|
92
95
|
```
|
|
93
96
|
|
|
94
|
-
Tail and search results are capped at 200 lines and
|
|
95
|
-
|
|
96
|
-
|
|
97
|
+
Tail and search results are capped at 200 lines, and the complete returned tool
|
|
98
|
+
result (including lifecycle headers) is clipped to 8 KB. Pattern search returns
|
|
99
|
+
the latest matching lines with line numbers. Prefer a targeted pattern over a
|
|
100
|
+
broad tail, and do not read a potentially large log file in full.
|
|
97
101
|
|
|
98
102
|
Subagent logs also compact Pi's streaming `message_update` events before they
|
|
99
103
|
are recorded. Pi repeats the complete growing assistant message and partial
|
|
@@ -103,7 +107,8 @@ events untouched. This keeps long RPC sessions approximately linear in emitted
|
|
|
103
107
|
content without changing final answers, completion detection, or follow-up
|
|
104
108
|
behavior. Live `/babysit` and attach views render the retained deltas.
|
|
105
109
|
|
|
106
|
-
All shell commands, including `pwd` and Git,
|
|
110
|
+
All shell commands, including `pwd` and Git, go through `babysit_run`. Bundle
|
|
111
|
+
closely related tiny observations when doing so safely reduces tool turns.
|
|
107
112
|
Set `PI_BABYSIT_ALLOW_BASH=1` only as an explicit emergency escape hatch.
|
|
108
113
|
|
|
109
114
|
## Unexpected worker loss
|
|
@@ -117,18 +122,24 @@ because blindly rerunning an arbitrary command can duplicate side effects.
|
|
|
117
122
|
|
|
118
123
|
## How completion detection works
|
|
119
124
|
|
|
120
|
-
- **Process**: a 2.5s poller watches for running→exited transitions and
|
|
121
|
-
|
|
122
|
-
|
|
125
|
+
- **Process**: a 2.5s poller watches for running→exited transitions and, once the
|
|
126
|
+
parent agent is idle, injects one
|
|
127
|
+
`pi.sendMessage(…, { triggerTurn: true, deliverAs: "steer" })` containing every
|
|
128
|
+
deliverable exit observed in that poll (deduped via `meta/<id>.json`). Waiting
|
|
129
|
+
for idleness prevents an immediately-following `babysit_wait` from racing the
|
|
130
|
+
poller and receiving a duplicate completion.
|
|
123
131
|
`babysit_kill` and an exit already reported by `babysit_wait` suppress the
|
|
124
132
|
notification.
|
|
125
|
-
- **Subagent**: `babysit_wait` blocks on `babysit expect '"type":"
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
133
|
+
- **Subagent**: `babysit_wait` blocks on `babysit expect '"type":"agent_settled"'`.
|
|
134
|
+
Unlike `agent_end`, `agent_settled` cannot precede an automatic retry,
|
|
135
|
+
compaction retry, or queued continuation. A settled run containing a
|
|
136
|
+
**parked** toolResult — a `babysit_run { command }` result carrying the
|
|
137
|
+
`[notify-on-exit]` marker (or the legacy `process` tool) — only means "turn
|
|
138
|
+
parked awaiting a process-exit notification; pi resumes on its own", so the
|
|
139
|
+
wait continues. The marker-bearing result may be followed by a short
|
|
140
|
+
assistant note without defeating parked detection. Per-task byte offsets
|
|
141
|
+
scope check/wait to the CURRENT task, and appended log bytes are parsed
|
|
142
|
+
incrementally, which keeps follow-up tasks efficient.
|
|
132
143
|
|
|
133
144
|
Subagents load `self-reap.ts`, which exits an idle finished subagent after a
|
|
134
145
|
grace window (`PI_BABYSIT_REAP_AFTER`, default 120s) using the same parked-turn
|
package/agents.ts
CHANGED
|
@@ -56,20 +56,34 @@ function loadAgentsFromDir(
|
|
|
56
56
|
continue;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
let parsed: ReturnType<typeof parseFrontmatter<Record<string, unknown>>>;
|
|
60
|
+
try {
|
|
61
|
+
parsed = parseFrontmatter<Record<string, unknown>>(content);
|
|
62
|
+
} catch {
|
|
63
|
+
// One malformed definition must not prevent every other named agent
|
|
64
|
+
// from being discovered.
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
const { frontmatter, body } = parsed;
|
|
68
|
+
if (
|
|
69
|
+
typeof frontmatter.name !== "string" ||
|
|
70
|
+
typeof frontmatter.description !== "string"
|
|
71
|
+
) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
62
74
|
|
|
63
|
-
const tools = frontmatter.tools
|
|
64
|
-
|
|
65
|
-
.
|
|
66
|
-
|
|
75
|
+
const tools = Array.isArray(frontmatter.tools)
|
|
76
|
+
? frontmatter.tools.filter((tool): tool is string => typeof tool === "string")
|
|
77
|
+
: typeof frontmatter.tools === "string"
|
|
78
|
+
? frontmatter.tools.split(",")
|
|
79
|
+
: [];
|
|
80
|
+
const normalizedTools = tools.map((tool) => tool.trim()).filter(Boolean);
|
|
67
81
|
|
|
68
82
|
agents.push({
|
|
69
83
|
name: frontmatter.name,
|
|
70
84
|
description: frontmatter.description,
|
|
71
|
-
tools:
|
|
72
|
-
model: frontmatter.model,
|
|
85
|
+
tools: normalizedTools.length > 0 ? normalizedTools : undefined,
|
|
86
|
+
model: typeof frontmatter.model === "string" ? frontmatter.model : undefined,
|
|
73
87
|
systemPrompt: body,
|
|
74
88
|
source,
|
|
75
89
|
filePath,
|