@yusukeshib/pi-babysit 0.2.3 → 0.3.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 +21 -4
- package/index.ts +94 -26
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# pi-babysit
|
|
2
2
|
|
|
3
|
-
A [pi](https://github.com/earendil-works/pi) extension that runs **
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
A [pi](https://github.com/earendil-works/pi) extension that runs **any shell
|
|
4
|
+
command** under [babysit](https://github.com/yusukeshib/babysit)-supervised
|
|
5
|
+
sessions — one context-safe substrate for quick commands, background processes,
|
|
6
|
+
and pi subagents.
|
|
6
7
|
It retires both `@mjakl/pi-processes` (the `process` tool) and the old
|
|
7
8
|
`pi-subagent` extension.
|
|
8
9
|
|
|
@@ -48,7 +49,7 @@ programs** (installers, wizards, REPLs): type with `babysit_send`
|
|
|
48
49
|
|
|
49
50
|
| Tool | What it does |
|
|
50
51
|
| ---- | ------------ |
|
|
51
|
-
| `babysit_run` |
|
|
52
|
+
| `babysit_run` | Run any command (`command`, optional `name`/`pty`/`timeout`/`idleTimeout`) or start a subagent (`profile: "subagent"`, `task`, optional `agent`/`model`/`tools`). Quick commands return inline; longer ones continue in the background |
|
|
52
53
|
| `babysit_check` | List all sessions, or inspect one: process → state + log tail (or `screen: true` for TUIs); subagent → live progress (turns, recent tool calls, partial answer) |
|
|
53
54
|
| `babysit_send` | Process: type `text` / press `keys` into the PTY. Subagent: steer mid-run, or send a follow-up task when idle (`mode: auto/steer/task`) |
|
|
54
55
|
| `babysit_wait` | Block until done: process exit (or `expect: "regex"` readiness marker), subagent task completion. Multi-wait: `ids` + `mode: "any"\|"all"` |
|
|
@@ -67,6 +68,22 @@ A `tool_call` hook also blocks bash commands that background themselves
|
|
|
67
68
|
A minimal widget above the editor shows live counts
|
|
68
69
|
(`N processes · M subagents working · K idle`).
|
|
69
70
|
|
|
71
|
+
## Logs without context flooding
|
|
72
|
+
|
|
73
|
+
`babysit_run`, `babysit_wait`, and automatic completion notifications always
|
|
74
|
+
return lifecycle metadata and the absolute path to the complete `output.log`.
|
|
75
|
+
When the complete output is at most 8 KB it is returned inline; larger output
|
|
76
|
+
stays out of model context. Inspect large logs on demand with bounded shell
|
|
77
|
+
commands such as:
|
|
78
|
+
|
|
79
|
+
```sh
|
|
80
|
+
tail -n 50 /path/to/output.log
|
|
81
|
+
rg -n 'FAIL|ERROR' /path/to/output.log
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
`babysit_check { id, lines }` remains available as a convenient bounded tail.
|
|
85
|
+
Do not read a potentially large log file in full.
|
|
86
|
+
|
|
70
87
|
## How completion detection works
|
|
71
88
|
|
|
72
89
|
- **Process**: a 2.5s poller watches for running→exited transitions and injects
|
package/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* pi-babysit: run
|
|
3
|
-
* for background processes AND pi subagents. Retires both `pi-processes`
|
|
2
|
+
* pi-babysit: run ANY shell command under babysit — one context-safe supervision
|
|
3
|
+
* substrate for quick commands, background processes, AND pi subagents. Retires both `pi-processes`
|
|
4
4
|
* (the `process` tool) and `pi-subagent`.
|
|
5
5
|
*
|
|
6
6
|
* Every session is a babysit-supervised PTY (state in $PI_BABYSIT_DIR,
|
|
@@ -80,6 +80,7 @@ const SUBAGENT_GUIDANCE = [
|
|
|
80
80
|
"your controller reads it from the event stream.",
|
|
81
81
|
].join(" ");
|
|
82
82
|
const POLL_MS = 2500;
|
|
83
|
+
const QUICK_COMMAND_GRACE = process.env.PI_BABYSIT_QUICK_GRACE ?? "1s";
|
|
83
84
|
|
|
84
85
|
interface BsSession {
|
|
85
86
|
id: string;
|
|
@@ -231,6 +232,7 @@ interface Meta {
|
|
|
231
232
|
name?: string;
|
|
232
233
|
command?: string;
|
|
233
234
|
notified?: boolean;
|
|
235
|
+
completionObservedAt?: number;
|
|
234
236
|
startedAt?: number;
|
|
235
237
|
// subagent
|
|
236
238
|
task?: string;
|
|
@@ -239,6 +241,7 @@ interface Meta {
|
|
|
239
241
|
}
|
|
240
242
|
|
|
241
243
|
const metaDir = () => path.join(ROOT, "meta");
|
|
244
|
+
const logPath = (id: string) => path.join(ROOT, "sessions", id, "output.log");
|
|
242
245
|
|
|
243
246
|
function writeMeta(id: string, m: Meta): void {
|
|
244
247
|
try {
|
|
@@ -364,7 +367,8 @@ function parseDurMs(s?: string): number | null {
|
|
|
364
367
|
// megabytes, so we also cap bytes, eliding the middle so both the head and
|
|
365
368
|
// the tail of the output stay visible.
|
|
366
369
|
|
|
367
|
-
const TAIL_MAX_BYTES = 8_000; //
|
|
370
|
+
const TAIL_MAX_BYTES = 8_000; // explicit tails / screens
|
|
371
|
+
const INLINE_OUTPUT_MAX_BYTES = 8_000; // complete output returned only below this threshold
|
|
368
372
|
const ANSWER_MAX_BYTES = 24_000; // subagent answers / error messages
|
|
369
373
|
|
|
370
374
|
function clip(s: string, maxBytes = TAIL_MAX_BYTES): string {
|
|
@@ -377,6 +381,27 @@ function clip(s: string, maxBytes = TAIL_MAX_BYTES): string {
|
|
|
377
381
|
return `${head}\n… [${buf.length - maxBytes} bytes elided] …\n${tail}`;
|
|
378
382
|
}
|
|
379
383
|
|
|
384
|
+
async function inlineOutput(id: string, status: BsSession): Promise<string> {
|
|
385
|
+
let bytes = status.output_bytes;
|
|
386
|
+
if (bytes == null) {
|
|
387
|
+
try {
|
|
388
|
+
bytes = fs.statSync(logPath(id)).size;
|
|
389
|
+
} catch {
|
|
390
|
+
bytes = Number.POSITIVE_INFINITY;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
if (bytes > INLINE_OUTPUT_MAX_BYTES) {
|
|
394
|
+
const size = Number.isFinite(bytes) ? `${bytes} bytes` : "size unavailable";
|
|
395
|
+
return `\nOutput omitted (${size}; inline limit ${INLINE_OUTPUT_MAX_BYTES}).`;
|
|
396
|
+
}
|
|
397
|
+
const output = (await bs(["log", "-s", id])).stdout.trimEnd();
|
|
398
|
+
if (Buffer.byteLength(output) > INLINE_OUTPUT_MAX_BYTES) {
|
|
399
|
+
return `\nOutput omitted (exceeds inline limit ${INLINE_OUTPUT_MAX_BYTES} bytes).`;
|
|
400
|
+
}
|
|
401
|
+
return output ? `\n\nOutput:\n${output}` : "";
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
|
|
380
405
|
// ---------------------------------------------------------------------------
|
|
381
406
|
// parked-turn detection (shared rule with self-reap.ts)
|
|
382
407
|
// ---------------------------------------------------------------------------
|
|
@@ -830,7 +855,7 @@ interface WaitOutcome {
|
|
|
830
855
|
// Wait for ONE subagent's current task. Completion = an agent_end whose last
|
|
831
856
|
// message is NOT a parked babysit_run/process toolResult (that one only means
|
|
832
857
|
// "turn parked, waiting for a background process — pi resumes on its own").
|
|
833
|
-
// Loop: analyze the current-task log slice; done →
|
|
858
|
+
// Loop: analyze the current-task log slice; done → return; still going →
|
|
834
859
|
// block on the next agent_end via `babysit expect` (race-free byte offsets).
|
|
835
860
|
async function waitForTask(
|
|
836
861
|
id: string,
|
|
@@ -949,6 +974,14 @@ function suppressNotify(id: string): void {
|
|
|
949
974
|
}
|
|
950
975
|
}
|
|
951
976
|
|
|
977
|
+
function enableNotify(id: string): void {
|
|
978
|
+
const meta = readMeta(id);
|
|
979
|
+
if (meta && meta.kind === "process" && meta.notified) {
|
|
980
|
+
meta.notified = false;
|
|
981
|
+
writeMeta(id, meta);
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
|
|
952
985
|
// Wait for a PROCESS session: either until a regex appears in its output
|
|
953
986
|
// (`expect` — e.g. "server listening") or until the process exits.
|
|
954
987
|
async function waitForExit(
|
|
@@ -965,12 +998,11 @@ async function waitForExit(
|
|
|
965
998
|
return { id, kind: "interrupted", ok: false, text: `wait for ${id} was interrupted.` };
|
|
966
999
|
}
|
|
967
1000
|
if (e.code === 0) {
|
|
968
|
-
const tail = clip((await bs(["log", "-s", id, "--tail", "10"])).stdout.trim());
|
|
969
1001
|
return {
|
|
970
1002
|
id,
|
|
971
1003
|
kind: "done",
|
|
972
1004
|
ok: true,
|
|
973
|
-
text: `Pattern /${expectPattern}/ matched in ${id} output (process still running).\
|
|
1005
|
+
text: `Pattern /${expectPattern}/ matched in ${id} output (process still running).\nLog: ${logPath(id)}`,
|
|
974
1006
|
};
|
|
975
1007
|
}
|
|
976
1008
|
const st0 = await statusOf(id);
|
|
@@ -985,14 +1017,19 @@ async function waitForExit(
|
|
|
985
1017
|
}
|
|
986
1018
|
// fall through: session exited before the pattern appeared
|
|
987
1019
|
} else {
|
|
1020
|
+
// An explicit wait owns completion delivery. Mark it before blocking so
|
|
1021
|
+
// the exit poller cannot race us and inject a duplicate notification.
|
|
1022
|
+
suppressNotify(id);
|
|
988
1023
|
const w = await bs(["wait", "-s", id, "--timeout", t], { signal });
|
|
989
1024
|
if (signal?.aborted || w.code === 130) {
|
|
1025
|
+
enableNotify(id);
|
|
990
1026
|
return { id, kind: "interrupted", ok: false, text: `wait for ${id} was interrupted.` };
|
|
991
1027
|
}
|
|
992
1028
|
if (w.code === 124) {
|
|
993
1029
|
// 124 is ambiguous (timeout vs child exiting 124) — disambiguate.
|
|
994
1030
|
const st0 = await statusOf(id);
|
|
995
1031
|
if (st0?.state === "running") {
|
|
1032
|
+
enableNotify(id);
|
|
996
1033
|
return {
|
|
997
1034
|
id,
|
|
998
1035
|
kind: "timeout",
|
|
@@ -1009,9 +1046,9 @@ async function waitForExit(
|
|
|
1009
1046
|
return { id, kind: "exited", ok: false, text: `No such session: ${id}` };
|
|
1010
1047
|
}
|
|
1011
1048
|
suppressNotify(id); // the agent sees the exit here; don't notify again
|
|
1012
|
-
const tail = clip((await bs(["log", "-s", id, "--tail", "20"])).stdout.trim());
|
|
1013
|
-
const ok = st.exit_code === 0;
|
|
1014
1049
|
const meta = readMeta(id);
|
|
1050
|
+
const ok = st.exit_code === 0;
|
|
1051
|
+
const output = await inlineOutput(id, st);
|
|
1015
1052
|
return {
|
|
1016
1053
|
id,
|
|
1017
1054
|
kind: "exited",
|
|
@@ -1020,7 +1057,7 @@ async function waitForExit(
|
|
|
1020
1057
|
`Process ${id}${meta?.command ? ` (${meta.command})` : ""} ` +
|
|
1021
1058
|
`${ok ? "completed successfully" : `exited with code ${st.exit_code ?? "?"}`}` +
|
|
1022
1059
|
`${expectPattern ? ` before /${expectPattern}/ appeared` : ""}.` +
|
|
1023
|
-
|
|
1060
|
+
`\nLog: ${logPath(id)}` + output,
|
|
1024
1061
|
status: st,
|
|
1025
1062
|
};
|
|
1026
1063
|
}
|
|
@@ -1067,10 +1104,19 @@ export default function (pi: ExtensionAPI) {
|
|
|
1067
1104
|
if (s.state === "running") continue;
|
|
1068
1105
|
const meta = readMeta(s.id);
|
|
1069
1106
|
if (!meta || meta.kind !== "process" || meta.notified) continue;
|
|
1107
|
+
// Delay delivery by one poll interval. This gives an agent that chose
|
|
1108
|
+
// babysit_wait immediately after babysit_run enough time to claim the
|
|
1109
|
+
// completion and suppress the otherwise duplicate automatic message.
|
|
1110
|
+
if (!meta.completionObservedAt) {
|
|
1111
|
+
meta.completionObservedAt = Date.now();
|
|
1112
|
+
writeMeta(s.id, meta);
|
|
1113
|
+
continue;
|
|
1114
|
+
}
|
|
1115
|
+
if (Date.now() - meta.completionObservedAt < POLL_MS) continue;
|
|
1070
1116
|
meta.notified = true;
|
|
1071
1117
|
writeMeta(s.id, meta);
|
|
1072
|
-
const tail = clip((await bs(["log", "-s", s.id, "--tail", "20"])).stdout.trim());
|
|
1073
1118
|
const ok = s.exit_code === 0;
|
|
1119
|
+
const output = await inlineOutput(s.id, s);
|
|
1074
1120
|
const runtime = meta.startedAt
|
|
1075
1121
|
? `${Math.round((Date.now() - meta.startedAt) / 1000)}s`
|
|
1076
1122
|
: "?";
|
|
@@ -1083,11 +1129,10 @@ export default function (pi: ExtensionAPI) {
|
|
|
1083
1129
|
{
|
|
1084
1130
|
customType: "pi-babysit-process-end",
|
|
1085
1131
|
content:
|
|
1086
|
-
`${summary}\nCommand: ${meta.command ?? "?"}` +
|
|
1087
|
-
|
|
1088
|
-
`\n\nThis is the automatic process-end notification. Do not call babysit_check just to re-verify; use it once only if you need more logs for debugging.`,
|
|
1132
|
+
`${summary}\nCommand: ${meta.command ?? "?"}\nLog: ${logPath(s.id)}${output}` +
|
|
1133
|
+
`\n\nThis is the automatic process-end notification. Do not call babysit_check just to re-verify. Inspect the log only when needed, using bounded commands such as tail or rg; never read it in full.`,
|
|
1089
1134
|
display: true,
|
|
1090
|
-
details: { id: s.id, exitCode: s.exit_code, success: ok, runtime },
|
|
1135
|
+
details: { id: s.id, exitCode: s.exit_code, success: ok, runtime, logPath: logPath(s.id) },
|
|
1091
1136
|
},
|
|
1092
1137
|
{ triggerTurn: true, deliverAs: "steer" },
|
|
1093
1138
|
);
|
|
@@ -1196,20 +1241,25 @@ export default function (pi: ExtensionAPI) {
|
|
|
1196
1241
|
name: "babysit_run",
|
|
1197
1242
|
label: "Babysit: run",
|
|
1198
1243
|
description:
|
|
1199
|
-
"
|
|
1200
|
-
"
|
|
1201
|
-
"
|
|
1202
|
-
"
|
|
1203
|
-
"
|
|
1244
|
+
"Run any shell command in a supervised babysit session. Commands that finish within a short " +
|
|
1245
|
+
"grace period return completion metadata immediately; longer commands continue in the background " +
|
|
1246
|
+
"and trigger an automatic notification on exit. Complete output is returned inline only when it is " +
|
|
1247
|
+
"small; larger output stays in the log path for bounded inspection with tail or rg. " +
|
|
1248
|
+
"In non-interactive mode (`pi -p`, no UI), process mode blocks until exit because there is no " +
|
|
1249
|
+
"notification loop. Two modes: (1) `command` — run any shell command, including builds, tests, " +
|
|
1250
|
+
"dev servers, watchers, and interactive TUIs; you can type into it with babysit_send and read " +
|
|
1251
|
+
"its screen with babysit_check. " +
|
|
1204
1252
|
"you can type into it with babysit_send and read its screen with babysit_check. " +
|
|
1205
1253
|
"(2) `profile: \"subagent\"` + `task` — spawn a pi subagent that works on the task in the " +
|
|
1206
1254
|
"background; poll with babysit_check, steer with babysit_send, block with babysit_wait, " +
|
|
1207
1255
|
"stop with babysit_kill.",
|
|
1208
1256
|
promptSnippet:
|
|
1209
|
-
"Run
|
|
1257
|
+
"Run any shell command with context-safe captured output; quick commands return metadata, longer ones continue in background",
|
|
1210
1258
|
promptGuidelines: [
|
|
1211
|
-
"
|
|
1259
|
+
"Use babysit_run as the default for shell commands, not only long-running work. Small output is returned directly; large stdout/stderr stays out of model context in the returned log path. Give meaningful commands a clear stable `name`.",
|
|
1260
|
+
"Inspect a babysit log only with explicitly bounded commands such as `tail -n N` or focused `rg`; never read or cat a potentially large log in full. Those small inspection commands may use bash directly to avoid recursively creating babysit sessions.",
|
|
1212
1261
|
"After babysit_run { command } starts a process, end your response immediately so the automatic process-end notification can resume you; NEVER poll with babysit_check or sleep. Set continueAfterStart: true only when you have immediate, specific, non-polling work to do next. Call babysit_wait when you must consume the result inside the current turn (optionally with `expect` to wait for a readiness line like 'listening on').",
|
|
1262
|
+
"babysit_run returns only minimal lifecycle information and a path to the complete log. Inspect that file with bounded shell commands such as `tail` or `rg`; never read a potentially large log in full.",
|
|
1213
1263
|
"babysit_run gives full PTY control: drive interactive programs (installers, wizards, REPLs) with babysit_send (text or named keys) and read the rendered screen with babysit_check { screen: true }.",
|
|
1214
1264
|
"Delegate self-contained tasks (codebase recon, a parallelizable subtask, work that would pollute your context) with babysit_run { profile: \"subagent\", task }. Launch several for independent subtasks; they run concurrently.",
|
|
1215
1265
|
"After spawning subagents, do not idle-wait and do not end your turn to wait for them: keep making progress, then call babysit_wait (ids + mode any/all) when you need their results. Steer or send follow-up tasks with babysit_send; kill runaways with babysit_kill.",
|
|
@@ -1269,6 +1319,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
1269
1319
|
"Process mode only. Default false: starting a process ENDS the current turn (you are resumed by the exit notification). Set true only when you have immediate, specific, non-polling work to do after starting.",
|
|
1270
1320
|
}),
|
|
1271
1321
|
),
|
|
1322
|
+
|
|
1272
1323
|
}),
|
|
1273
1324
|
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
1274
1325
|
await requireBabysit();
|
|
@@ -1304,7 +1355,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
1304
1355
|
timeout: params.timeout,
|
|
1305
1356
|
idleTimeout: params.idleTimeout,
|
|
1306
1357
|
pty: params.pty ?? true,
|
|
1307
|
-
|
|
1358
|
+
});
|
|
1308
1359
|
if ("error" in res) {
|
|
1309
1360
|
return {
|
|
1310
1361
|
content: [{ type: "text", text: `Failed to start process: ${res.error}` }],
|
|
@@ -1326,7 +1377,23 @@ export default function (pi: ExtensionAPI) {
|
|
|
1326
1377
|
return {
|
|
1327
1378
|
content: [{ type: "text", text: outcome.text }],
|
|
1328
1379
|
isError: !outcome.ok,
|
|
1329
|
-
details: { id: res.id, kind: "process", command: params.command },
|
|
1380
|
+
details: { id: res.id, kind: "process", command: params.command, logPath: logPath(res.id) },
|
|
1381
|
+
};
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1384
|
+
// Keep ordinary quick commands ergonomic. Give the process a short grace
|
|
1385
|
+
// period; if it exits, return only lifecycle metadata + log path now.
|
|
1386
|
+
// A timeout means it is genuinely background work and follows the normal
|
|
1387
|
+
// parked-turn / automatic-notification contract below.
|
|
1388
|
+
await bs(["wait", "-s", res.id, "--timeout", QUICK_COMMAND_GRACE], { signal: _signal });
|
|
1389
|
+
const quickStatus = await statusOf(res.id);
|
|
1390
|
+
if (quickStatus && quickStatus.state !== "running") {
|
|
1391
|
+
const outcome = await waitForExit(res.id, null, _signal);
|
|
1392
|
+
await refreshWidget(ctx);
|
|
1393
|
+
return {
|
|
1394
|
+
content: [{ type: "text", text: outcome.text }],
|
|
1395
|
+
isError: !outcome.ok,
|
|
1396
|
+
details: { id: res.id, kind: "process", command: params.command, logPath: logPath(res.id) },
|
|
1330
1397
|
};
|
|
1331
1398
|
}
|
|
1332
1399
|
|
|
@@ -1339,13 +1406,13 @@ export default function (pi: ExtensionAPI) {
|
|
|
1339
1406
|
{
|
|
1340
1407
|
type: "text",
|
|
1341
1408
|
text:
|
|
1342
|
-
`Process started (id: ${res.id}). ${NOTIFY_MARKER}\n${nextStep}\n` +
|
|
1409
|
+
`Process started (id: ${res.id}). ${NOTIFY_MARKER}\nLog: ${logPath(res.id)}\n${nextStep}\n` +
|
|
1343
1410
|
`Inspect: babysit_check { id: "${res.id}" } (screen: true for TUIs) · ` +
|
|
1344
1411
|
`Wait: babysit_wait { id: "${res.id}" } · Kill: babysit_kill { id: "${res.id}" }\n` +
|
|
1345
1412
|
`Human can watch/take over: /babysit`,
|
|
1346
1413
|
},
|
|
1347
1414
|
],
|
|
1348
|
-
details: { id: res.id, kind: "process", command: params.command },
|
|
1415
|
+
details: { id: res.id, kind: "process", command: params.command, logPath: logPath(res.id) },
|
|
1349
1416
|
// Do not return `terminate: true` here. In RPC/subagent hosts that hint
|
|
1350
1417
|
// can shut down the hosting pi worker, whose process-tree cleanup then
|
|
1351
1418
|
// kills the otherwise detached babysit supervisor and closes its PTY
|
|
@@ -1482,6 +1549,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
1482
1549
|
}
|
|
1483
1550
|
if (st.exit_code != null) header += ` exit_code=${st.exit_code}`;
|
|
1484
1551
|
if (meta?.command) header += `\ncommand: ${meta.command}`;
|
|
1552
|
+
header += `\nlog: ${logPath(params.id)}`;
|
|
1485
1553
|
if (st.note) header += ` ⚑ ${st.note}`;
|
|
1486
1554
|
parts.push(header);
|
|
1487
1555
|
if (params.screen) {
|
|
@@ -1496,7 +1564,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
1496
1564
|
}
|
|
1497
1565
|
return {
|
|
1498
1566
|
content: [{ type: "text", text: parts.join("\n") }],
|
|
1499
|
-
details: { status: st, kind: "process" },
|
|
1567
|
+
details: { status: st, kind: "process", logPath: logPath(params.id) },
|
|
1500
1568
|
};
|
|
1501
1569
|
}
|
|
1502
1570
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yusukeshib/pi-babysit",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Run
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Run any shell command and pi subagents under babysit, with context-safe captured output.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
|
7
7
|
"pi-extension",
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"LICENSE"
|
|
28
28
|
],
|
|
29
29
|
"scripts": {
|
|
30
|
+
"test": "bun test",
|
|
30
31
|
"release": "npm publish --access public"
|
|
31
32
|
},
|
|
32
33
|
"pi": {
|