@yusukeshib/pi-babysit 0.6.22 → 0.6.24
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 +34 -20
- package/index.ts +59 -22
- package/log-viewer.ts +5 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -50,10 +50,13 @@ at every depth.
|
|
|
50
50
|
Because sessions are real PTYs, the agent can also **drive interactive
|
|
51
51
|
programs** (installers, wizards, REPLs): type with `babysit_send`
|
|
52
52
|
(text or named keys) and read the rendered screen with
|
|
53
|
-
`babysit_check { screen: true }` — a capability neither retired extension had.
|
|
53
|
+
`babysit_check { description, screen: true }` — a capability neither retired extension had.
|
|
54
54
|
|
|
55
55
|
## Tools (LLM-callable)
|
|
56
56
|
|
|
57
|
+
All five tools require a short, non-blank `description` explaining the purpose
|
|
58
|
+
of that call.
|
|
59
|
+
|
|
57
60
|
| Tool | What it does |
|
|
58
61
|
| ---- | ------------ |
|
|
59
62
|
| `babysit_run` | Run any command (`description` + `command`, optional `name`/`pty`/`timeout`/`idleTimeout`/`retryOnWorkerDeath`/`notificationGroup`/`lifecycle`). Set `foreground: true` for one process or subagent whose result is needed in the same tool call; use `returnPattern`/`returnLines`/`maxBytes` to keep noisy process output bounded. Foreground and non-interactive process waits default to lifecycle `attached`, which terminates the process tree if that owning tool call is interrupted; background starts default to `detached`. Or start a named background subagent (`description`, `profile: "subagent"`, `task`, optional `name`/`agent`/`model`/`tools`/`maxDepth` and budget fields), then always collect it with `babysit_wait`. `maxDepth` defaults to 1. Subagent `continueAfterStart: true` is accepted as a compatibility alias for this default background behavior. Quick commands return inline; longer process runs notify in the background |
|
|
@@ -71,26 +74,35 @@ calls if another extension or preset re-enables `bash`, including shell
|
|
|
71
74
|
backgrounding (`… &`, `nohup`, `setsid`, `disown`). Set
|
|
72
75
|
`PI_BABYSIT_ALLOW_BASH=1` to retain direct `bash` explicitly.
|
|
73
76
|
|
|
74
|
-
## Describe every
|
|
77
|
+
## Describe every operation
|
|
75
78
|
|
|
76
|
-
Every
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
Every babysit tool call requires a non-blank `description`. Explain the purpose
|
|
80
|
+
briefly in language the user can understand. For `babysit_run`, `name` remains
|
|
81
|
+
a stable session identifier, while `command` / `task` contains the execution
|
|
82
|
+
instructions. Its description is trimmed and saved with the session. For
|
|
83
|
+
`babysit_check`, `babysit_send`, `babysit_wait`, and `babysit_kill`, the description
|
|
84
|
+
explains only that operation and never overwrites the session description.
|
|
85
|
+
Descriptions are display metadata, not shell code, stdin, or instructions sent
|
|
86
|
+
to the subagent.
|
|
81
87
|
|
|
82
88
|
```text
|
|
83
89
|
babysit_run { description: "Run regression tests", command: "bun test", foreground: true }
|
|
84
90
|
babysit_run { description: "Review the authentication changes", profile: "subagent", task: "Review the authentication diff for security regressions", maxTurns: 5 }
|
|
91
|
+
babysit_check { description: "Inspect build errors", id: "build", pattern: "ERROR" }
|
|
92
|
+
babysit_wait { description: "Wait for the build to finish", id: "build" }
|
|
93
|
+
babysit_send { description: "Ask the reviewer to check authorization too", id: "review", text: "Also check authorization." }
|
|
94
|
+
babysit_kill { description: "Stop the unused development server", id: "dev-server" }
|
|
85
95
|
```
|
|
86
96
|
|
|
87
97
|
In Pi's main transcript the description is the prominent yellow heading, with
|
|
88
|
-
the execution kind in muted gray. The full command or task
|
|
98
|
+
the tool name and execution kind in muted gray. The full command or task (or
|
|
99
|
+
all other operation arguments, including target IDs and input) is always visible
|
|
89
100
|
in gray beneath it, even when tool results are collapsed. Session lists, the
|
|
90
|
-
widget, and completion notifications
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
before
|
|
101
|
+
widget, and completion notifications show the session's original description.
|
|
102
|
+
Older saved sessions and tool calls without descriptions remain readable,
|
|
103
|
+
falling back to their command, task, or other arguments. Callers must supply a
|
|
104
|
+
description for every new call; blank or missing values are rejected before
|
|
105
|
+
execution.
|
|
94
106
|
|
|
95
107
|
## Remote processes over SSH
|
|
96
108
|
|
|
@@ -102,9 +114,9 @@ pi-babysit does not install remote software or copy credentials.
|
|
|
102
114
|
```text
|
|
103
115
|
babysit_run { description: "Run tests on Linux", host: "yusuke-t4", cwd: "/home/yusuke/project", command: "bun test", foreground: true, returnLines: 30 }
|
|
104
116
|
babysit_run { description: "Open a remote Python REPL", host: "user@server", command: "python3 -i", name: "remote-repl", continueAfterStart: true }
|
|
105
|
-
babysit_check { id: "remote-repl", screen: true }
|
|
106
|
-
babysit_send { id: "remote-repl", text: "print(42)" }
|
|
107
|
-
babysit_kill { id: "remote-repl" }
|
|
117
|
+
babysit_check { description: "Read the remote REPL screen", id: "remote-repl", screen: true }
|
|
118
|
+
babysit_send { description: "Evaluate a value in the remote REPL", id: "remote-repl", text: "print(42)" }
|
|
119
|
+
babysit_kill { description: "Close the remote REPL", id: "remote-repl" }
|
|
108
120
|
```
|
|
109
121
|
|
|
110
122
|
`host` omitted (or `"local"`) preserves local behavior. `cwd` is process-only:
|
|
@@ -155,9 +167,11 @@ sessions, and click again to return to running-only. Both modes show newest firs
|
|
|
155
167
|
ten per page; `< 1/4 >` shows the current/total page when needed. Click the
|
|
156
168
|
arrows to page. Rows occupy one line, previewing the description (or the command
|
|
157
169
|
for older processes and task for older agents), with `…` when clipped. Click an
|
|
158
|
-
AGENT or PROCESS row to replace the list with a
|
|
159
|
-
overlay or separate screen.
|
|
160
|
-
|
|
170
|
+
AGENT or PROCESS row to replace the list with a **log viewer in the same widget area**, not an
|
|
171
|
+
overlay or separate screen. The viewer is capped at ten lines including its header
|
|
172
|
+
and footer; all saved history remains available by scrolling. Click anywhere on
|
|
173
|
+
the viewer's header row to restore the list, preserving its mode and page.
|
|
174
|
+
There is no separate Close button or Esc binding. The viewer uses Pi's `ScrollView` for
|
|
161
175
|
scroll position and follow behavior, with a widget-local scrollbar styled using
|
|
162
176
|
Pi's scrollbar theme. Wheel, scrollbar drag/track clicks, and ↑/↓ navigate the
|
|
163
177
|
log without requiring any Pi core changes. Home/End and PageUp/PageDown remain
|
|
@@ -204,8 +218,8 @@ pending for the next poll. Larger output stays out of model context. Inspect it
|
|
|
204
218
|
through the session id without creating another shell session:
|
|
205
219
|
|
|
206
220
|
```text
|
|
207
|
-
babysit_check { id: "cargo-test", lines: 50 }
|
|
208
|
-
babysit_check { id: "cargo-test", pattern: "FAIL|ERROR", lines: 50 }
|
|
221
|
+
babysit_check { description: "Inspect the recent test output", id: "cargo-test", lines: 50 }
|
|
222
|
+
babysit_check { description: "Find test failures", id: "cargo-test", pattern: "FAIL|ERROR", lines: 50 }
|
|
209
223
|
```
|
|
210
224
|
|
|
211
225
|
Tail and search results are capped at 200 lines and default to a 4 KB total
|
package/index.ts
CHANGED
|
@@ -51,6 +51,18 @@ import { Type, type TSchema } from "typebox";
|
|
|
51
51
|
import { StringEnum } from "@earendil-works/pi-ai";
|
|
52
52
|
import { type AgentConfig, type AgentScope, discoverAgents } from "./agents";
|
|
53
53
|
|
|
54
|
+
const descriptionSchema = Type.String({
|
|
55
|
+
minLength: 1,
|
|
56
|
+
pattern: "\\S",
|
|
57
|
+
description: "Required short human-readable purpose for this operation. Explain what it does and why; shown prominently to the user.",
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
function requireDescription(value: unknown): void {
|
|
61
|
+
if (typeof value !== "string" || !value.trim()) {
|
|
62
|
+
throw new Error("`description` is required and must be a non-blank string for every babysit tool call.");
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
54
66
|
// Dedicated babysit state root so pi-managed sessions never collide with the
|
|
55
67
|
// user's own manual `babysit` sessions. The base is namespaced per pi session
|
|
56
68
|
// on session_start (BABYSIT_DIR=<base>/<session-id>), so each pi session only
|
|
@@ -1373,6 +1385,17 @@ function escapeCommandForDisplay(command: string): string {
|
|
|
1373
1385
|
);
|
|
1374
1386
|
}
|
|
1375
1387
|
|
|
1388
|
+
function renderOperationCall(name: string, args: Record<string, unknown> | undefined, theme: Theme) {
|
|
1389
|
+
const { description, ...operationArgs } = args ?? {};
|
|
1390
|
+
const purpose = typeof description === "string" ? description.trim() : "";
|
|
1391
|
+
const title = theme.fg("muted", theme.bold(name));
|
|
1392
|
+
const heading = purpose
|
|
1393
|
+
? `${title} ${theme.fg("warning", theme.bold(escapeCommandForDisplay(purpose)))}`
|
|
1394
|
+
: title;
|
|
1395
|
+
const raw = Object.keys(operationArgs).length ? JSON.stringify(operationArgs) : "";
|
|
1396
|
+
return new Text(heading + (raw ? `\n${theme.fg("muted", escapeCommandForDisplay(raw))}` : ""), 0, 0);
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1376
1399
|
export function readableLaunchCommand(command: string): string {
|
|
1377
1400
|
// Older sessions quoted every argv element, including safe paths and flags.
|
|
1378
1401
|
if (!command.startsWith("'") || !command.endsWith("'") || !command.includes("' '")) return command;
|
|
@@ -2577,6 +2600,7 @@ function renderWidgetSessionHeader(
|
|
|
2577
2600
|
// How many trailing output lines to show per session in the widget.
|
|
2578
2601
|
const WIDGET_COLLAPSED_TAIL_LINES = 1;
|
|
2579
2602
|
const WIDGET_SESSION_PAGE_SIZE = 10;
|
|
2603
|
+
const WIDGET_VIEWER_MAX_LINES = 10;
|
|
2580
2604
|
|
|
2581
2605
|
export interface WidgetSessionListState {
|
|
2582
2606
|
mode: "running" | "all";
|
|
@@ -2732,7 +2756,11 @@ export function createSessionWidget(options: {
|
|
|
2732
2756
|
viewer?.dispose();
|
|
2733
2757
|
source = undefined;
|
|
2734
2758
|
selectedId = id;
|
|
2735
|
-
viewer = createLogViewer({
|
|
2759
|
+
viewer = createLogViewer({
|
|
2760
|
+
...options,
|
|
2761
|
+
getHeight: () => Math.min(WIDGET_VIEWER_MAX_LINES, options.getHeight()),
|
|
2762
|
+
onClose: close,
|
|
2763
|
+
});
|
|
2736
2764
|
refreshViewer();
|
|
2737
2765
|
options.requestRender();
|
|
2738
2766
|
}
|
|
@@ -3286,7 +3314,7 @@ async function waitForTask(
|
|
|
3286
3314
|
ok: completed.ok,
|
|
3287
3315
|
text:
|
|
3288
3316
|
`Subagent ${id} finished its task (${stats}).\n` +
|
|
3289
|
-
`${subagentReuseHint(readMeta(id)?.reapAfter)} Follow-up: babysit_send { id: "${id}" }, ` +
|
|
3317
|
+
`${subagentReuseHint(readMeta(id)?.reapAfter)} Follow-up: babysit_send { description: "Assign a follow-up task", id: "${id}" }, ` +
|
|
3290
3318
|
`or babysit_kill when done.\n\n${completed.body}`,
|
|
3291
3319
|
status: st,
|
|
3292
3320
|
progress: prog,
|
|
@@ -3714,7 +3742,14 @@ export default function (pi: ExtensionAPI) {
|
|
|
3714
3742
|
const execute = tool.execute;
|
|
3715
3743
|
pi.registerTool({
|
|
3716
3744
|
...tool,
|
|
3745
|
+
description: tool.description + " Always provide a short human-readable `description` explaining the purpose of this operation.",
|
|
3746
|
+
promptGuidelines: [
|
|
3747
|
+
"Every babysit tool call requires a short description explaining its purpose for the user. Operation descriptions for check/send/wait/kill do not change the session's original description.",
|
|
3748
|
+
...(tool.promptGuidelines ?? []),
|
|
3749
|
+
],
|
|
3750
|
+
renderCall: tool.renderCall ?? ((args, theme) => renderOperationCall(tool.name, args as Record<string, unknown>, theme)),
|
|
3717
3751
|
async execute(toolCallId, params, signal, onUpdate, ctx) {
|
|
3752
|
+
requireDescription((params as { description?: unknown }).description);
|
|
3718
3753
|
const result = await execute(toolCallId, params, signal, onUpdate, ctx);
|
|
3719
3754
|
if ((result as typeof result & { isError?: boolean }).isError === true) {
|
|
3720
3755
|
declaredToolErrors.add(toolCallId);
|
|
@@ -4156,7 +4191,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
4156
4191
|
: d.count && d.count > 1
|
|
4157
4192
|
? theme.fg("muted", `×${d.count}`)
|
|
4158
4193
|
: "";
|
|
4159
|
-
const header = theme.fg("muted", theme.bold("babysit_run
|
|
4194
|
+
const header = theme.fg("muted", theme.bold("babysit_run PROCESS")) + (payload ? ` ${payload}` : "");
|
|
4160
4195
|
const box = new Box(1, 1, (t) => theme.bg("toolSuccessBg", t));
|
|
4161
4196
|
box.addChild(new Text(header, 0, 0));
|
|
4162
4197
|
box.addChild(new Text(renderStatus(status, theme), 0, 0));
|
|
@@ -4319,7 +4354,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
4319
4354
|
block: true,
|
|
4320
4355
|
reason:
|
|
4321
4356
|
"Use babysit_run for shell commands so output is supervised and captured outside model context. " +
|
|
4322
|
-
"Inspect an existing session log with babysit_check { id, lines, pattern? }. " +
|
|
4357
|
+
"Inspect an existing session log with babysit_check { description, id, lines, pattern? }. " +
|
|
4323
4358
|
`Retry with a short purpose description as babysit_run({ description: "Explain the purpose of this command", command: ${JSON.stringify(command)} }).`,
|
|
4324
4359
|
};
|
|
4325
4360
|
});
|
|
@@ -4330,13 +4365,11 @@ export default function (pi: ExtensionAPI) {
|
|
|
4330
4365
|
label: "Babysit: run",
|
|
4331
4366
|
description:
|
|
4332
4367
|
"Run a supervised shell command, or start a reusable pi subagent with `profile: \"subagent\"`. " +
|
|
4333
|
-
"Always provide a short human-readable `description` of what this run does and why. " +
|
|
4334
4368
|
"Use `foreground` for results needed now; otherwise long commands notify on exit. Full logs stay on disk. " +
|
|
4335
4369
|
"`returnPattern`/`returnLines` bound foreground output. Sessions support check, wait, send, and kill.",
|
|
4336
4370
|
promptSnippet: "Run supervised commands or bounded pi subagents with context-safe logs",
|
|
4337
4371
|
promptGuidelines: [
|
|
4338
4372
|
"Use babysit_run for shell commands and give meaningful sessions a stable name; bundle tiny related read-only observations into one command.",
|
|
4339
|
-
"Every babysit_run requires a short description explaining its purpose for the user, for both commands and subagents. Describe the actual work, not a generic 'run command' or 'start agent'.",
|
|
4340
4373
|
"Use babysit_run foreground mode for one process or subagent whose result is needed now; never issue sibling foreground runs in parallel. For parallel process checks, start background runs with continueAfterStart and collect them with one multi-session babysit_wait.",
|
|
4341
4374
|
"Use returnPattern/returnLines for noisy commands. During edit/fix loops run targeted checks first and one full validation suite at the end instead of repeating every full gate.",
|
|
4342
4375
|
"After a background process starts, stop the turn for its automatic notification; never poll or sleep. Use continueAfterStart only for specific non-polling process work.",
|
|
@@ -4350,11 +4383,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
4350
4383
|
return prepareBabysitRunArguments(args) as never;
|
|
4351
4384
|
},
|
|
4352
4385
|
parameters: Type.Object({
|
|
4353
|
-
description:
|
|
4354
|
-
minLength: 1,
|
|
4355
|
-
pattern: "\\S",
|
|
4356
|
-
description: "Required short human-readable purpose for this command or subagent. Explain what it does and why; shown prominently to the user.",
|
|
4357
|
-
}),
|
|
4386
|
+
description: descriptionSchema,
|
|
4358
4387
|
host: Type.Optional(Type.String({ description: "Process SSH destination/config alias (default local). Remote subagents are unsupported." })),
|
|
4359
4388
|
cwd: Type.Optional(Type.String({ description: "Process working directory. Remote default is login home; never inferred from local cwd." })),
|
|
4360
4389
|
command: Type.Optional(
|
|
@@ -4485,9 +4514,6 @@ export default function (pi: ExtensionAPI) {
|
|
|
4485
4514
|
|
|
4486
4515
|
}),
|
|
4487
4516
|
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
4488
|
-
if (typeof params.description !== "string" || !params.description.trim()) {
|
|
4489
|
-
throw new Error("`description` is required and must be a non-blank string for both commands and subagents.");
|
|
4490
|
-
}
|
|
4491
4517
|
const description = params.description.trim();
|
|
4492
4518
|
await requireBabysit();
|
|
4493
4519
|
const isSubagent = params.profile === "subagent";
|
|
@@ -4702,8 +4728,8 @@ export default function (pi: ExtensionAPI) {
|
|
|
4702
4728
|
text:
|
|
4703
4729
|
`${retried ? "Retried once after external worker death.\n" : ""}` +
|
|
4704
4730
|
`Process started (id: ${res.id}). ${NOTIFY_MARKER}\nDescription: ${escapeCommandForDisplay(description)}\nLog: ${logPath(res.id)}\n${nextStep}\n` +
|
|
4705
|
-
`Inspect: babysit_check { id: "${res.id}" } (screen: true for TUIs) · ` +
|
|
4706
|
-
`Wait: babysit_wait { id: "${res.id}" } · Kill: babysit_kill { id: "${res.id}" }\n` +
|
|
4731
|
+
`Inspect: babysit_check { description: "Inspect session output", id: "${res.id}" } (screen: true for TUIs) · ` +
|
|
4732
|
+
`Wait: babysit_wait { description: "Wait for completion", id: "${res.id}" } · Kill: babysit_kill { description: "Stop this session", id: "${res.id}" }\n` +
|
|
4707
4733
|
`Human can watch/take over: /babysit`,
|
|
4708
4734
|
},
|
|
4709
4735
|
],
|
|
@@ -4810,8 +4836,8 @@ export default function (pi: ExtensionAPI) {
|
|
|
4810
4836
|
text:
|
|
4811
4837
|
`Subagent started (id: ${res.id})${agent ? ` [agent: ${agent.name}]` : ""}${res.model ? ` [model: ${res.model}]` : ""} [depth: ${subagentNesting.childDepth}/${subagentNesting.maxDepth}].\n` +
|
|
4812
4838
|
`Description: ${escapeCommandForDisplay(description)}\nTask accepted — running in the background. You MUST collect it with babysit_wait before finishing the parent task; use foreground: true next time when no independent work is available.\n` +
|
|
4813
|
-
`Progress: babysit_check { id: "${res.id}" } (only when inspection is needed)\n` +
|
|
4814
|
-
`Collect: babysit_wait { id: "${res.id}" }\n` +
|
|
4839
|
+
`Progress: babysit_check { description: "Inspect agent progress", id: "${res.id}" } (only when inspection is needed)\n` +
|
|
4840
|
+
`Collect: babysit_wait { description: "Collect the agent result", id: "${res.id}" }\n` +
|
|
4815
4841
|
`Human can watch/steer: /babysit (pick ${res.id})`,
|
|
4816
4842
|
},
|
|
4817
4843
|
],
|
|
@@ -4833,7 +4859,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
4833
4859
|
// Legacy calls without descriptions still render their original payload safely.
|
|
4834
4860
|
renderCall(args, theme) {
|
|
4835
4861
|
const isSubagent = args.profile === "subagent";
|
|
4836
|
-
const kind = isSubagent ? "AGENT" : "
|
|
4862
|
+
const kind = isSubagent ? "AGENT" : "PROCESS";
|
|
4837
4863
|
const payload = isSubagent ? args.task : args.command;
|
|
4838
4864
|
const agent = isSubagent && args.agent ? ` [${escapeCommandForDisplay(args.agent)}]` : "";
|
|
4839
4865
|
const title = theme.fg("muted", `${theme.bold(`babysit_run ${kind}`)}${agent}`);
|
|
@@ -4895,6 +4921,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
4895
4921
|
"Do NOT poll this while merely waiting for a process to end — the exit notification is automatic.",
|
|
4896
4922
|
promptSnippet: "Check status/progress of babysit sessions (processes and subagents)",
|
|
4897
4923
|
parameters: Type.Object({
|
|
4924
|
+
description: descriptionSchema,
|
|
4898
4925
|
id: Type.Optional(Type.String({ description: "Session id. Omit to list sessions." })),
|
|
4899
4926
|
state: Type.Optional(
|
|
4900
4927
|
StringEnum(["running", "terminal", "all"] as const, {
|
|
@@ -5135,11 +5162,12 @@ export default function (pi: ExtensionAPI) {
|
|
|
5135
5162
|
description:
|
|
5136
5163
|
"Send input to a babysit session. Process: `text` types a line into its stdin (PTY), " +
|
|
5137
5164
|
"`keys` presses named keys (Enter, Tab, Esc, Up/Down/Left/Right, C-c, F1…) — use with " +
|
|
5138
|
-
"babysit_check { screen: true } to drive interactive programs. Subagent: `text` is " +
|
|
5165
|
+
"babysit_check { description, screen: true } to drive interactive programs. Subagent: `text` is " +
|
|
5139
5166
|
"STEERING while it works, or a NEW TASK after the current task settles (mode: auto/steer/task) — this " +
|
|
5140
5167
|
"is how you resume a finished subagent with full context.",
|
|
5141
5168
|
promptSnippet: "Send text/keys to a process, or steering/follow-up tasks to a subagent",
|
|
5142
5169
|
parameters: Type.Object({
|
|
5170
|
+
description: descriptionSchema,
|
|
5143
5171
|
id: Type.String({ description: "Session id." }),
|
|
5144
5172
|
text: Type.Optional(
|
|
5145
5173
|
Type.String({ description: "Text to send (a line for processes; a message for subagents)." }),
|
|
@@ -5211,7 +5239,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
5211
5239
|
content: [
|
|
5212
5240
|
{
|
|
5213
5241
|
type: "text",
|
|
5214
|
-
text: `Sent to ${params.id}. Read the reaction with babysit_check { id: "${params.id}"${params.keys?.length ? ", screen: true" : ""} } — don't expect the echo of your own input.`,
|
|
5242
|
+
text: `Sent to ${params.id}. Read the reaction with babysit_check { description: "Inspect the response to input", id: "${params.id}"${params.keys?.length ? ", screen: true" : ""} } — don't expect the echo of your own input.`,
|
|
5215
5243
|
},
|
|
5216
5244
|
],
|
|
5217
5245
|
details: { kind: "process" },
|
|
@@ -5328,6 +5356,11 @@ export default function (pi: ExtensionAPI) {
|
|
|
5328
5356
|
// New task → new bookkeeping window, so check/wait track THIS task.
|
|
5329
5357
|
writeMeta(params.id, {
|
|
5330
5358
|
kind: "subagent",
|
|
5359
|
+
name: meta?.name,
|
|
5360
|
+
description: meta?.description,
|
|
5361
|
+
launchCommand: meta?.launchCommand,
|
|
5362
|
+
reapAfter: meta?.reapAfter,
|
|
5363
|
+
startedAt: meta?.startedAt,
|
|
5331
5364
|
task: params.text,
|
|
5332
5365
|
// Start after the prompt-acceptance response. This excludes a
|
|
5333
5366
|
// preceding run that settled between `send` and RPC acceptance.
|
|
@@ -5389,6 +5422,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
5389
5422
|
"the exit notification will resume you.",
|
|
5390
5423
|
promptSnippet: "Block until session(s) finish — process exit / output pattern / subagent task done",
|
|
5391
5424
|
parameters: Type.Object({
|
|
5425
|
+
description: descriptionSchema,
|
|
5392
5426
|
id: Type.Optional(Type.String({ description: "Session id (single wait)." })),
|
|
5393
5427
|
ids: Type.Optional(
|
|
5394
5428
|
Type.Array(Type.String(), {
|
|
@@ -5535,7 +5569,10 @@ export default function (pi: ExtensionAPI) {
|
|
|
5535
5569
|
label: "Babysit: kill",
|
|
5536
5570
|
description: "Terminate a babysit session (process or subagent).",
|
|
5537
5571
|
promptSnippet: "Terminate a babysit session",
|
|
5538
|
-
parameters: Type.Object({
|
|
5572
|
+
parameters: Type.Object({
|
|
5573
|
+
description: descriptionSchema,
|
|
5574
|
+
id: Type.String({ description: "Session id." }),
|
|
5575
|
+
}),
|
|
5539
5576
|
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
5540
5577
|
await requireBabysit();
|
|
5541
5578
|
// Prevent the exit poller racing a requested kill, but restore delivery
|
package/log-viewer.ts
CHANGED
|
@@ -244,21 +244,18 @@ export function createLogViewer(options: LogViewerOptions) {
|
|
|
244
244
|
const heading = {
|
|
245
245
|
invalidate() {},
|
|
246
246
|
render(width: number) {
|
|
247
|
-
const
|
|
248
|
-
const room = Math.max(0, width - visibleWidth(close) - 1);
|
|
249
|
-
const title = truncateToWidth(sanitize(header).replace(/\n/g, " "), room);
|
|
247
|
+
const title = truncateToWidth(sanitize(header).replace(/\n/g, " "), width);
|
|
250
248
|
return [
|
|
251
249
|
options.getTheme().fg("accent", title) +
|
|
252
250
|
" ".repeat(
|
|
253
|
-
Math.max(0, width - visibleWidth(title)
|
|
254
|
-
)
|
|
255
|
-
options.getTheme().fg("muted", close),
|
|
251
|
+
Math.max(0, width - visibleWidth(title)),
|
|
252
|
+
),
|
|
256
253
|
];
|
|
257
254
|
},
|
|
258
255
|
handleMouse(e: TuiMouseEvent) {
|
|
259
256
|
if (
|
|
260
257
|
e.button !== "left" ||
|
|
261
|
-
e.x <
|
|
258
|
+
e.x < 0 ||
|
|
262
259
|
e.x >= e.width
|
|
263
260
|
)
|
|
264
261
|
return;
|
|
@@ -272,7 +269,7 @@ export function createLogViewer(options: LogViewerOptions) {
|
|
|
272
269
|
const footer: Component = {
|
|
273
270
|
invalidate() {},
|
|
274
271
|
render: (width) => [
|
|
275
|
-
options.getTheme().fg("dim", truncateToWidth(source ? `↑↓ · bytes ${pages[0]?.start ?? 0}–${pages.at(-1)?.end ?? 0}/${source.size} (window)
|
|
272
|
+
options.getTheme().fg("dim", truncateToWidth(source ? `↑↓ · bytes ${pages[0]?.start ?? 0}–${pages.at(-1)?.end ?? 0}/${source.size} (window)` : "↑↓", width)),
|
|
276
273
|
],
|
|
277
274
|
};
|
|
278
275
|
let geometry = {
|
|
@@ -489,10 +486,6 @@ export function createLogViewer(options: LogViewerOptions) {
|
|
|
489
486
|
options.requestRender();
|
|
490
487
|
},
|
|
491
488
|
handleKey(data: string): boolean {
|
|
492
|
-
if (matchesKey(data, Key.escape)) {
|
|
493
|
-
options.onClose();
|
|
494
|
-
return true;
|
|
495
|
-
}
|
|
496
489
|
if (matchesKey(data, Key.up)) scrollView.scrollBy(-1);
|
|
497
490
|
else if (matchesKey(data, Key.down)) scrollView.scrollBy(1);
|
|
498
491
|
else return false;
|