@jtsang/pi-extensions 0.1.0 → 0.1.1
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 +5 -0
- package/extensions/monitor.ts +74 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,8 +18,13 @@ keeping the model running between events.
|
|
|
18
18
|
- `pi_background_monitor` starts a command in the session working directory.
|
|
19
19
|
Non-persistent monitors time out after five minutes by default; persistent
|
|
20
20
|
monitors run until stopped or the session ends.
|
|
21
|
+
- `pi_background_monitor_list` lists every active monitor with its ID, command,
|
|
22
|
+
working directory, elapsed time, and timeout state.
|
|
21
23
|
- `pi_background_monitor_stop` stops one monitor by ID, or all monitors when no
|
|
22
24
|
ID is provided.
|
|
25
|
+
- Monitors run concurrently with no extension-level limit; operating-system
|
|
26
|
+
process and resource limits still apply. The footer shows the active count,
|
|
27
|
+
and `/monitors` shows the current details without invoking the model.
|
|
23
28
|
- Output from stdout and stderr is batched for 200 ms, stripped of terminal
|
|
24
29
|
control sequences, limited to 16 KB per event, and delivered to the current
|
|
25
30
|
conversation as untrusted data. An idle agent starts a turn immediately; a
|
package/extensions/monitor.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { stripVTControlCharacters } from "node:util";
|
|
|
4
4
|
import {
|
|
5
5
|
createLocalBashOperations,
|
|
6
6
|
formatSize,
|
|
7
|
+
truncateHead,
|
|
7
8
|
truncateTail,
|
|
8
9
|
type ExtensionAPI,
|
|
9
10
|
type ExtensionContext,
|
|
@@ -22,6 +23,11 @@ const CONTROL_CHARACTERS = /[\u0000-\u0008\u000b-\u000d\u000e-\u001f\u007f]/g;
|
|
|
22
23
|
type RunningMonitor = {
|
|
23
24
|
id: string;
|
|
24
25
|
description: string;
|
|
26
|
+
command: string;
|
|
27
|
+
cwd: string;
|
|
28
|
+
persistent: boolean;
|
|
29
|
+
timeoutMs?: number;
|
|
30
|
+
startedAt: number;
|
|
25
31
|
abort: AbortController;
|
|
26
32
|
decoder: StringDecoder;
|
|
27
33
|
partialLine: string;
|
|
@@ -55,6 +61,42 @@ export default function monitorExtension(pi: ExtensionAPI) {
|
|
|
55
61
|
currentContext.ui.setStatus(STATUS_KEY, count ? `${count} monitor${count === 1 ? "" : "s"}` : undefined);
|
|
56
62
|
}
|
|
57
63
|
|
|
64
|
+
function getMonitorDetails() {
|
|
65
|
+
const now = Date.now();
|
|
66
|
+
return [...monitors.values()].map((monitor) => ({
|
|
67
|
+
id: monitor.id,
|
|
68
|
+
description: monitor.description,
|
|
69
|
+
command: monitor.command,
|
|
70
|
+
cwd: monitor.cwd,
|
|
71
|
+
state: monitor.stopping ? "stopping" : "running",
|
|
72
|
+
persistent: monitor.persistent,
|
|
73
|
+
timeoutMs: monitor.timeoutMs,
|
|
74
|
+
startedAt: monitor.startedAt,
|
|
75
|
+
elapsedMs: now - monitor.startedAt,
|
|
76
|
+
}));
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function formatMonitorList(): string {
|
|
80
|
+
const active = getMonitorDetails();
|
|
81
|
+
const lines = [`Active monitors: ${active.length} (no extension limit; system resource limits apply)`];
|
|
82
|
+
for (const monitor of active) {
|
|
83
|
+
lines.push(
|
|
84
|
+
`- ${monitor.id} · ${monitor.state} · elapsed=${(monitor.elapsedMs / 1000).toFixed(1)}s · ${monitor.persistent ? "persistent" : `timeout=${monitor.timeoutMs}ms`}`,
|
|
85
|
+
` description=${JSON.stringify(monitor.description)}`,
|
|
86
|
+
` cwd=${JSON.stringify(monitor.cwd)}`,
|
|
87
|
+
` command=${JSON.stringify(monitor.command)}`,
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const truncated = truncateHead(lines.join("\n"), {
|
|
92
|
+
maxLines: MAX_QUEUED_LINES,
|
|
93
|
+
maxBytes: MAX_EVENT_BYTES - 64,
|
|
94
|
+
});
|
|
95
|
+
return truncated.truncated
|
|
96
|
+
? `${truncated.content}\n[monitor list truncated to ${formatSize(MAX_EVENT_BYTES)}]`
|
|
97
|
+
: truncated.content;
|
|
98
|
+
}
|
|
99
|
+
|
|
58
100
|
function discardQueuedOutput(monitor: RunningMonitor): void {
|
|
59
101
|
if (monitor.flushTimer) clearTimeout(monitor.flushTimer);
|
|
60
102
|
monitor.flushTimer = undefined;
|
|
@@ -194,6 +236,31 @@ export default function monitorExtension(pi: ExtensionAPI) {
|
|
|
194
236
|
currentContext = undefined;
|
|
195
237
|
});
|
|
196
238
|
|
|
239
|
+
pi.registerCommand("monitors", {
|
|
240
|
+
description: "Show active background monitors",
|
|
241
|
+
handler: async (_args, ctx) => {
|
|
242
|
+
ctx.ui.notify(formatMonitorList(), "info");
|
|
243
|
+
},
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
pi.registerTool({
|
|
247
|
+
name: "pi_background_monitor_list",
|
|
248
|
+
label: "List Monitors",
|
|
249
|
+
description:
|
|
250
|
+
"List active background monitors with their IDs, commands, working directories, elapsed time, and timeout state. The extension has no fixed concurrency limit; system resources are the limit.",
|
|
251
|
+
promptSnippet: "List active background monitors and their current state",
|
|
252
|
+
promptGuidelines: [
|
|
253
|
+
"Use pi_background_monitor_list to inspect active monitor count, commands, and runtime state.",
|
|
254
|
+
],
|
|
255
|
+
parameters: Type.Object({}),
|
|
256
|
+
async execute() {
|
|
257
|
+
return {
|
|
258
|
+
content: [{ type: "text", text: formatMonitorList() }],
|
|
259
|
+
details: { monitors: getMonitorDetails(), concurrencyLimit: null },
|
|
260
|
+
};
|
|
261
|
+
},
|
|
262
|
+
});
|
|
263
|
+
|
|
197
264
|
pi.registerTool({
|
|
198
265
|
name: "pi_background_monitor",
|
|
199
266
|
label: "Monitor",
|
|
@@ -231,6 +298,11 @@ export default function monitorExtension(pi: ExtensionAPI) {
|
|
|
231
298
|
const monitor: RunningMonitor = {
|
|
232
299
|
id,
|
|
233
300
|
description: params.description,
|
|
301
|
+
command: params.command,
|
|
302
|
+
cwd: ctx.cwd,
|
|
303
|
+
persistent,
|
|
304
|
+
timeoutMs,
|
|
305
|
+
startedAt: Date.now(),
|
|
234
306
|
abort,
|
|
235
307
|
decoder: new StringDecoder("utf8"),
|
|
236
308
|
partialLine: "",
|
|
@@ -286,8 +358,10 @@ export default function monitorExtension(pi: ExtensionAPI) {
|
|
|
286
358
|
id,
|
|
287
359
|
description: params.description,
|
|
288
360
|
command: params.command,
|
|
361
|
+
cwd: ctx.cwd,
|
|
289
362
|
persistent,
|
|
290
363
|
timeoutMs,
|
|
364
|
+
startedAt: monitor.startedAt,
|
|
291
365
|
},
|
|
292
366
|
};
|
|
293
367
|
},
|