@thurstonsand/pi-agent-switchboard 0.8.0 → 0.9.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/index.js +20 -8
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -89,10 +89,11 @@ class Db {
|
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
// packages/shared/src/index.ts
|
|
92
|
-
var SCHEMA_VERSION =
|
|
92
|
+
var SCHEMA_VERSION = 8;
|
|
93
93
|
var VIEWS = ["agent", "editor", "split"];
|
|
94
94
|
var HARNESSES = ["pi", "claude", "codex"];
|
|
95
95
|
var SNOOZE_PRESETS = ["one_hour", "one_day", "monday", "next_message"];
|
|
96
|
+
var RELOAD_MODES = ["continue", "idle"];
|
|
96
97
|
function stateDir() {
|
|
97
98
|
return join(process.env.XDG_STATE_HOME || join(homedir(), ".local/state"), "agent-switchboard");
|
|
98
99
|
}
|
|
@@ -215,7 +216,8 @@ function settle(db, s) {
|
|
|
215
216
|
harnessTitled(db, s.sessionId, s.title);
|
|
216
217
|
db.run("UPDATE sessions SET phase = 'idle', last_settled_at = ?, cwd = ?, project_root = ?, branch = ?, title = coalesce(?, title) WHERE session_id = ?", Date.now(), s.cwd, projectRoot(s.cwd), branch(s.cwd), s.title, s.sessionId);
|
|
217
218
|
db.run("UPDATE runtimes SET cwd = ?, project_root = ? WHERE tmux_session = ?", s.cwd, projectRoot(s.cwd), s.host);
|
|
218
|
-
|
|
219
|
+
const reloading = db.get("SELECT 1 FROM marks WHERE session_id = ? AND reload IS NOT NULL", s.sessionId);
|
|
220
|
+
return { quit: isArchived(db, s.sessionId) || Boolean(reloading) };
|
|
219
221
|
});
|
|
220
222
|
}
|
|
221
223
|
function turnErrored(db, sessionId) {
|
|
@@ -241,7 +243,10 @@ function titleOf(db, sessionId) {
|
|
|
241
243
|
return row?.title ?? null;
|
|
242
244
|
}
|
|
243
245
|
function endHosting(db, host) {
|
|
244
|
-
recordTx(db, () =>
|
|
246
|
+
recordTx(db, () => {
|
|
247
|
+
db.run("DELETE FROM runtimes WHERE tmux_session = ?", host);
|
|
248
|
+
db.run("DELETE FROM launches WHERE tmux_session = ?", host);
|
|
249
|
+
});
|
|
245
250
|
}
|
|
246
251
|
function isArchived(db, sessionId) {
|
|
247
252
|
return Boolean(db.get("SELECT 1 FROM sessions s JOIN marks m USING (session_id) WHERE s.session_id = ? AND m.archived_at >= s.last_prompt_at", sessionId));
|
|
@@ -251,7 +256,7 @@ function markArchived(db, sessionId) {
|
|
|
251
256
|
return false;
|
|
252
257
|
const now = Date.now();
|
|
253
258
|
db.run(`INSERT INTO marks (session_id, archived_at) VALUES (?, ?)
|
|
254
|
-
ON CONFLICT (session_id) DO UPDATE SET archived_at = excluded.archived_at, snoozed_at = NULL, snoozed_until = NULL`, sessionId, now);
|
|
259
|
+
ON CONFLICT (session_id) DO UPDATE SET archived_at = excluded.archived_at, snoozed_at = NULL, snoozed_until = NULL, reload = NULL`, sessionId, now);
|
|
255
260
|
db.run("UPDATE messages SET cancelled_at = ? WHERE target_id = ? AND delivered_at IS NULL AND cancelled_at IS NULL", now, sessionId);
|
|
256
261
|
db.run("UPDATE schedules SET cancelled_at = ? WHERE target_id = ? AND next_at IS NOT NULL AND cancelled_at IS NULL", now, sessionId);
|
|
257
262
|
return true;
|
|
@@ -436,7 +441,10 @@ var TOOLS = {
|
|
|
436
441
|
"Unarchiving doesn't restart a session; session_send_message wakes it.",
|
|
437
442
|
"Snooze or unsnooze only when the user asks.",
|
|
438
443
|
"Group sessions when the user asks, or to keep sessions you started for one piece of work together. Reuse a Group session_reachable lists in that Project rather than inventing a near-duplicate.",
|
|
439
|
-
"Retitle a session when the user asks, or when its title no longer says what it is working on."
|
|
444
|
+
"Retitle a session when the user asks, or when its title no longer says what it is working on.",
|
|
445
|
+
"Reload a session when the user asks, or when you changed something it reads only at startup (its AGENTS.md or CLAUDE.md, settings, extensions, plugins, skills, or MCP servers) and it needs the change now.",
|
|
446
|
+
"Reloading this session restarts it when this turn ends: call it last, then end with a brief final message. With continue, it starts a turn on its own once it's back; with idle, it waits for the user.",
|
|
447
|
+
"Reloading another session with continue restarts it at once, cutting off a running turn, its tools, and its background work, then picks that turn back up; an idle or dormant one starts a turn."
|
|
440
448
|
],
|
|
441
449
|
parameters: Type.Object({
|
|
442
450
|
session: Type.Optional(session),
|
|
@@ -451,6 +459,9 @@ var TOOLS = {
|
|
|
451
459
|
title: Type.Optional(Type.String({ description: "A new, short title." })),
|
|
452
460
|
snooze: Type.Optional(Type.Union([...[...SNOOZE_PRESETS, "off"].map((preset) => Type.Literal(preset)), Type.Object({ until: Type.String() })], {
|
|
453
461
|
description: 'How long to snooze it, off to unsnooze, or {"until":"2026-11-05T09:00:00-08:00"} for a set time.'
|
|
462
|
+
})),
|
|
463
|
+
reload: Type.Optional(Type.Union(RELOAD_MODES.map((mode) => Type.Literal(mode)), {
|
|
464
|
+
description: "Restart the session's agent process on the same conversation, so it reads its instructions and configuration afresh. continue: it carries on working afterward. idle: it waits for its next prompt."
|
|
454
465
|
}))
|
|
455
466
|
}),
|
|
456
467
|
readOnly: false
|
|
@@ -773,13 +784,13 @@ ${details.body}`, 0, 0);
|
|
|
773
784
|
writeFor(ctx, (db, id) => {
|
|
774
785
|
if (stopReason === "error" && !event.aborted)
|
|
775
786
|
turnErrored(db, id);
|
|
776
|
-
const {
|
|
787
|
+
const { quit } = settle(db, {
|
|
777
788
|
host: proc.launch.tmuxSession,
|
|
778
789
|
sessionId: id,
|
|
779
790
|
cwd: ctx.cwd,
|
|
780
791
|
title: ctx.sessionManager.getSessionName() ?? null
|
|
781
792
|
});
|
|
782
|
-
if (
|
|
793
|
+
if (quit)
|
|
783
794
|
ctx.shutdown();
|
|
784
795
|
});
|
|
785
796
|
});
|
|
@@ -970,7 +981,8 @@ ${details.body}`, 0, 0);
|
|
|
970
981
|
args.archived === false ? "unarchive" : "",
|
|
971
982
|
args.snooze !== undefined ? `snooze ${snoozeText(args.snooze)}` : "",
|
|
972
983
|
args.group === null ? "ungroup" : args.group !== undefined ? `group ${args.group}` : "",
|
|
973
|
-
args.title !== undefined ? `retitle as "${args.title}"` : ""
|
|
984
|
+
args.title !== undefined ? `retitle as "${args.title}"` : "",
|
|
985
|
+
args.reload !== undefined ? `reload · ${args.reload}` : ""
|
|
974
986
|
].filter(Boolean);
|
|
975
987
|
if (args.title !== undefined)
|
|
976
988
|
return parts.join(" · ");
|