pi-roundtable 0.19.0 → 0.19.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/CHANGELOG.md +7 -0
- package/docs/plugins.md +1 -1
- package/package.json +1 -1
- package/src/core/http/listeners.ts +15 -2
- package/src/core/runtime/session-factory.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,13 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [0.19.1] - 2026-10-18
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- The core's tests no longer depend on the host's `mktemp` or on a free-port probe. The check that the agents' `bash` writes into the scratch dir ran a bare `mktemp`, which macOS's BSD `mktemp` sends to the user temp dir whatever `TMPDIR` says; it now runs `mktemp -p "$TMPDIR"`, which both implementations honour, and the bare `mktemp` is held to the scratch dir only where GNU `mktemp` is the default. The listener tests found a free port by opening one and closing it, and another process could take it before the listener bound it (`EADDRINUSE`); they now let the listener bind port 0 and ask which port it got.
|
|
13
|
+
- The docs say what the scratch dir promises: the agents' shell runs with `TMPDIR` pointing to it, so tools that read `TMPDIR` and GNU `mktemp` write there, while macOS's BSD `mktemp` ignores `TMPDIR` for a bare `mktemp` and needs `mktemp -p "$TMPDIR"`. The agents' prompt is unchanged: it already sends temporary files to `$TMPDIR` and never asks for a bare `mktemp`.
|
|
14
|
+
|
|
8
15
|
## [0.19.0] - 2026-10-17
|
|
9
16
|
|
|
10
17
|
### Added
|
package/docs/plugins.md
CHANGED
|
@@ -918,7 +918,7 @@ defineTool({
|
|
|
918
918
|
|
|
919
919
|
`shellHoldRule` in `pi-roundtable/kit` judges the agents' `bash`, `write` and `edit` calls; the agent server links it, and a session without a workspace has no shell.
|
|
920
920
|
Its scratch roots are the shared workspace (`HoldContext.workspace`) and the scratch dir (`HoldContext.scratchDir`).
|
|
921
|
-
The scratch dir is the config's `scratchDir`, by default `<os temp dir>/<discord.rootCommand>-scratch` (such as `/tmp/roundtable-scratch`); the agent server creates it with mode 0700 at startup and refuses one that is a symlink or another user's, and the agents' `bash` runs with `TMPDIR` pointing to it, so `
|
|
921
|
+
The scratch dir is the config's `scratchDir`, by default `<os temp dir>/<discord.rootCommand>-scratch` (such as `/tmp/roundtable-scratch`); the agent server creates it with mode 0700 at startup and refuses one that is a symlink or another user's, and the agents' `bash` runs with `TMPDIR` pointing to it, so tools that read `TMPDIR` and GNU `mktemp` write there. macOS's BSD `mktemp` ignores `TMPDIR` for a bare `mktemp`; `mktemp -p "$TMPDIR"` works with both.
|
|
922
922
|
`AgentSessions.scratchDir` carries it to a runtime, and the agents' prompt tells them to write temporary files there, and to show a file with `attach_file` or a `discord_send_message` file `path` rather than reading an image or base64-encoding it.
|
|
923
923
|
|
|
924
924
|
- A `>`, `>>` or `tee` target, and a `write` or `edit` path, inside a scratch root run; anything else, the rest of `/tmp` included, is held.
|
package/package.json
CHANGED
|
@@ -225,6 +225,7 @@ export class HttpListeners {
|
|
|
225
225
|
readonly #sockets: SocketSet;
|
|
226
226
|
readonly #closeTimeoutMs: number;
|
|
227
227
|
#servers: Pick<Server<unknown>, "stop">[] = [];
|
|
228
|
+
readonly #ports = new Map<string, number>();
|
|
228
229
|
|
|
229
230
|
/** Validates every route before any socket opens; `closeTimeoutMs` bounds how long a stop waits on WebSocket handlers. */
|
|
230
231
|
constructor(
|
|
@@ -271,9 +272,15 @@ export class HttpListeners {
|
|
|
271
272
|
);
|
|
272
273
|
chmodSync(listener.socketPath, listener.mode ?? 0o660);
|
|
273
274
|
} else {
|
|
274
|
-
|
|
275
|
-
|
|
275
|
+
const server = serveTcp(
|
|
276
|
+
listener.port,
|
|
277
|
+
listener.hostname,
|
|
278
|
+
handle,
|
|
279
|
+
websocket,
|
|
276
280
|
);
|
|
281
|
+
this.#servers.push(server);
|
|
282
|
+
if (server.port !== undefined)
|
|
283
|
+
this.#ports.set(listener.id, server.port);
|
|
277
284
|
}
|
|
278
285
|
}
|
|
279
286
|
} catch (error) {
|
|
@@ -282,6 +289,11 @@ export class HttpListeners {
|
|
|
282
289
|
}
|
|
283
290
|
}
|
|
284
291
|
|
|
292
|
+
/** The port an open TCP listener is bound to, which differs from the configured one when that was 0. */
|
|
293
|
+
portOf(listener: string): number | undefined {
|
|
294
|
+
return this.#ports.get(listener);
|
|
295
|
+
}
|
|
296
|
+
|
|
285
297
|
/** The listener's WebSocket handler, sized for its largest route limits; none without WebSocket routes. */
|
|
286
298
|
#websocketHandler(
|
|
287
299
|
listener: string,
|
|
@@ -314,6 +326,7 @@ export class HttpListeners {
|
|
|
314
326
|
this.#sockets.closeAll();
|
|
315
327
|
for (const server of this.#servers) void server.stop(true);
|
|
316
328
|
this.#servers = [];
|
|
329
|
+
this.#ports.clear();
|
|
317
330
|
await this.#sockets.drain(this.#closeTimeoutMs);
|
|
318
331
|
}
|
|
319
332
|
}
|
|
@@ -472,7 +472,7 @@ export function imageTools(
|
|
|
472
472
|
return images ? { generateImage: generateImageExtension(images, roots) } : {};
|
|
473
473
|
}
|
|
474
474
|
|
|
475
|
-
/** Pi's bash tool with TMPDIR set to `scratchDir`, so `mktemp`
|
|
475
|
+
/** Pi's bash tool with TMPDIR set to `scratchDir`, so tools that read TMPDIR and GNU `mktemp` write there (BSD `mktemp` needs `-p "$TMPDIR"`). */
|
|
476
476
|
export function scratchBash(cwd: string, scratchDir: string): ToolDefinition {
|
|
477
477
|
// SAFETY: Pi's bash definition is a ToolDefinition typed by its own parameter schema, which the session takes as any custom tool.
|
|
478
478
|
return createBashToolDefinition(cwd, {
|