@staff0rd/assist 0.758.0 → 0.759.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 +1 -1
- package/dist/commands/sessions/web/bundle.js +346 -346
- package/dist/index.js +115 -73
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Command } from "commander";
|
|
|
6
6
|
// package.json
|
|
7
7
|
var package_default = {
|
|
8
8
|
name: "@staff0rd/assist",
|
|
9
|
-
version: "0.
|
|
9
|
+
version: "0.759.1",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -13058,7 +13058,7 @@ var sessionsConfigHelp = [
|
|
|
13058
13058
|
{
|
|
13059
13059
|
key: "worktree.watcher",
|
|
13060
13060
|
setter: "assist config set worktree.watcher true -g --repo",
|
|
13061
|
-
note: "a backlog run also starts one starred
|
|
13061
|
+
note: "a backlog run also starts one starred console session in the clone running assist watch loop (no claude, relaunched after a daemon restart), so the built version stays current while the run works in its worktree; requires worktree.enabled and an auto-build run entry (default off)"
|
|
13062
13062
|
},
|
|
13063
13063
|
{
|
|
13064
13064
|
key: "worktree.trunk",
|
|
@@ -41342,6 +41342,7 @@ function dismissSession(sessions, id) {
|
|
|
41342
41342
|
s.activityWatcher?.close();
|
|
41343
41343
|
s.transcriptWatcher?.close();
|
|
41344
41344
|
s.gitWatcher?.close();
|
|
41345
|
+
s.closeGrace?.cancel();
|
|
41345
41346
|
removeActivity(s.id);
|
|
41346
41347
|
if (s.activity?.itemId != null) releaseLock(s.activity.itemId);
|
|
41347
41348
|
sessions.delete(id);
|
|
@@ -41414,6 +41415,28 @@ function processCwd(link3) {
|
|
|
41414
41415
|
}
|
|
41415
41416
|
}
|
|
41416
41417
|
|
|
41418
|
+
// src/commands/sessions/daemon/worktree/awaitTreeVacated.ts
|
|
41419
|
+
var POLL_MS = 500;
|
|
41420
|
+
var GRACE_MS = 5e3;
|
|
41421
|
+
function awaitTreeVacated(session, treePath) {
|
|
41422
|
+
return new Promise((resolve26) => {
|
|
41423
|
+
let ticks = GRACE_MS / POLL_MS;
|
|
41424
|
+
const settle = (outcome) => {
|
|
41425
|
+
clearTimeout(timer);
|
|
41426
|
+
session.closeGrace = void 0;
|
|
41427
|
+
resolve26(outcome);
|
|
41428
|
+
};
|
|
41429
|
+
const tick = () => {
|
|
41430
|
+
if (liveProcessesInTree(treePath).length === 0) settle("vacated");
|
|
41431
|
+
else if (--ticks <= 0) settle("occupied");
|
|
41432
|
+
else timer = setTimeout(tick, POLL_MS);
|
|
41433
|
+
};
|
|
41434
|
+
let timer = setTimeout(tick, POLL_MS);
|
|
41435
|
+
session.closeGrace?.cancel();
|
|
41436
|
+
session.closeGrace = { cancel: () => settle("cancelled") };
|
|
41437
|
+
});
|
|
41438
|
+
}
|
|
41439
|
+
|
|
41417
41440
|
// src/commands/sessions/daemon/worktree/liveOccupantReason.ts
|
|
41418
41441
|
function liveOccupantReason(treePath) {
|
|
41419
41442
|
stopInstall(treePath);
|
|
@@ -41425,20 +41448,21 @@ function liveOccupantReason(treePath) {
|
|
|
41425
41448
|
// src/commands/sessions/daemon/worktree/closeBlockReason.ts
|
|
41426
41449
|
async function closeBlockReason(sessionId, tree) {
|
|
41427
41450
|
const durability = await checkDurability(tree.path);
|
|
41428
|
-
if (!durability.durable) return durability.reason;
|
|
41451
|
+
if (!durability.durable) return { reason: durability.reason, live: false };
|
|
41429
41452
|
if (durability.gone) {
|
|
41430
41453
|
daemonLog(
|
|
41431
41454
|
`session ${sessionId} closing: worktree ${tree.path} is gone from disk \u2014 released with nothing to land, not landed work`
|
|
41432
41455
|
);
|
|
41433
41456
|
return void 0;
|
|
41434
41457
|
}
|
|
41435
|
-
|
|
41458
|
+
const occupied = tree.removable ? liveOccupantReason(tree.path) : void 0;
|
|
41459
|
+
return occupied ? { reason: occupied, live: true } : void 0;
|
|
41436
41460
|
}
|
|
41437
41461
|
|
|
41438
41462
|
// src/commands/sessions/daemon/worktree/watchGitState.ts
|
|
41439
41463
|
import { existsSync as existsSync87, watch } from "fs";
|
|
41440
41464
|
var DEBOUNCE_MS = 500;
|
|
41441
|
-
var
|
|
41465
|
+
var POLL_MS2 = 3e4;
|
|
41442
41466
|
function watchGitState(cwd, onChange) {
|
|
41443
41467
|
const common = gitCommonDir(cwd);
|
|
41444
41468
|
if (!common || !existsSync87(common)) return void 0;
|
|
@@ -41469,22 +41493,59 @@ function watchGitDir(common, onChange) {
|
|
|
41469
41493
|
}
|
|
41470
41494
|
}
|
|
41471
41495
|
function pollGitState(cwd, onChange) {
|
|
41472
|
-
const timer = setInterval(onChange,
|
|
41496
|
+
const timer = setInterval(onChange, POLL_MS2);
|
|
41473
41497
|
timer.unref?.();
|
|
41474
|
-
daemonLog(`git-state polled every ${
|
|
41498
|
+
daemonLog(`git-state polled every ${POLL_MS2 / 1e3}s for ${cwd}`);
|
|
41475
41499
|
return { close: () => clearInterval(timer) };
|
|
41476
41500
|
}
|
|
41477
41501
|
|
|
41502
|
+
// src/commands/sessions/daemon/worktree/holdStopped.ts
|
|
41503
|
+
function holdStopped(session, tree, reason4, recheck, notify2) {
|
|
41504
|
+
if (session.undurable?.reason !== reason4)
|
|
41505
|
+
daemonLog(
|
|
41506
|
+
`session ${session.id} stopped; ${tree.removable ? "reap" : "close"} blocked in ${tree.path}: ${reason4}`
|
|
41507
|
+
);
|
|
41508
|
+
session.undurable = { reason: reason4, removesTree: tree.removable };
|
|
41509
|
+
session.closing = void 0;
|
|
41510
|
+
setStatus2(session, "stopped");
|
|
41511
|
+
if (!session.gitWatcher) {
|
|
41512
|
+
let rechecking = false;
|
|
41513
|
+
session.gitWatcher = watchGitState(tree.path, () => {
|
|
41514
|
+
if (session.status !== "stopped" || rechecking) return;
|
|
41515
|
+
rechecking = true;
|
|
41516
|
+
void recheck().finally(() => {
|
|
41517
|
+
rechecking = false;
|
|
41518
|
+
});
|
|
41519
|
+
});
|
|
41520
|
+
}
|
|
41521
|
+
notify2();
|
|
41522
|
+
}
|
|
41523
|
+
|
|
41478
41524
|
// src/commands/sessions/daemon/worktree/resolveCloseDurability.ts
|
|
41479
|
-
async function resolveCloseDurability(session, finalize, notify2) {
|
|
41525
|
+
async function resolveCloseDurability(session, finalize, notify2, graceSpent = false) {
|
|
41480
41526
|
const tree = treeUnderClose(session);
|
|
41481
41527
|
if (!tree) {
|
|
41482
41528
|
finalize();
|
|
41483
41529
|
return;
|
|
41484
41530
|
}
|
|
41485
41531
|
const blocked = await closeBlockReason(session.id, tree);
|
|
41532
|
+
if (blocked?.live && session.closing && !graceSpent) {
|
|
41533
|
+
daemonLog(
|
|
41534
|
+
`session ${session.id} closing: waiting for live processes to leave ${tree.path} (${blocked.reason})`
|
|
41535
|
+
);
|
|
41536
|
+
const outcome = await awaitTreeVacated(session, tree.path);
|
|
41537
|
+
daemonLog(`session ${session.id} closing: live-process wait ${outcome}`);
|
|
41538
|
+
if (outcome === "cancelled") return;
|
|
41539
|
+
return resolveCloseDurability(session, finalize, notify2, true);
|
|
41540
|
+
}
|
|
41486
41541
|
if (blocked) {
|
|
41487
|
-
holdStopped(
|
|
41542
|
+
holdStopped(
|
|
41543
|
+
session,
|
|
41544
|
+
tree,
|
|
41545
|
+
blocked.reason,
|
|
41546
|
+
() => resolveCloseDurability(session, finalize, notify2),
|
|
41547
|
+
notify2
|
|
41548
|
+
);
|
|
41488
41549
|
return;
|
|
41489
41550
|
}
|
|
41490
41551
|
if (tree.removable) await reapWorktree(tree.path);
|
|
@@ -41496,26 +41557,6 @@ async function resolveCloseDurability(session, finalize, notify2) {
|
|
|
41496
41557
|
session.gitWatcher = void 0;
|
|
41497
41558
|
finalize();
|
|
41498
41559
|
}
|
|
41499
|
-
function holdStopped(session, tree, reason4, finalize, notify2) {
|
|
41500
|
-
if (session.undurable?.reason !== reason4)
|
|
41501
|
-
daemonLog(
|
|
41502
|
-
`session ${session.id} stopped; ${tree.removable ? "reap" : "close"} blocked in ${tree.path}: ${reason4}`
|
|
41503
|
-
);
|
|
41504
|
-
session.undurable = { reason: reason4, removesTree: tree.removable };
|
|
41505
|
-
session.closing = void 0;
|
|
41506
|
-
setStatus2(session, "stopped");
|
|
41507
|
-
if (!session.gitWatcher) {
|
|
41508
|
-
let rechecking = false;
|
|
41509
|
-
session.gitWatcher = watchGitState(tree.path, () => {
|
|
41510
|
-
if (session.status !== "stopped" || rechecking) return;
|
|
41511
|
-
rechecking = true;
|
|
41512
|
-
void resolveCloseDurability(session, finalize, notify2).finally(() => {
|
|
41513
|
-
rechecking = false;
|
|
41514
|
-
});
|
|
41515
|
-
});
|
|
41516
|
-
}
|
|
41517
|
-
notify2();
|
|
41518
|
-
}
|
|
41519
41560
|
|
|
41520
41561
|
// src/commands/sessions/daemon/dismissSessionGated.ts
|
|
41521
41562
|
function dismissSessionGated(sessions, id, notify2, discard = false) {
|
|
@@ -41529,6 +41570,7 @@ function dismissSessionGated(sessions, id, notify2, discard = false) {
|
|
|
41529
41570
|
if (dismissSession(sessions, id)) notify2();
|
|
41530
41571
|
};
|
|
41531
41572
|
const settle = discard ? () => void discardTree(s, removeCard, notify2) : () => void resolveCloseDurability(s, removeCard, notify2);
|
|
41573
|
+
s.closeGrace?.cancel();
|
|
41532
41574
|
s.closing = true;
|
|
41533
41575
|
daemonLog(
|
|
41534
41576
|
`session ${id} closing: ${discard ? "discarding" : "checking durability of"} ${tree.path}`
|
|
@@ -42237,7 +42279,7 @@ async function touchedSince(file, sinceMs) {
|
|
|
42237
42279
|
}
|
|
42238
42280
|
|
|
42239
42281
|
// src/commands/sessions/daemon/bindCodexSession.ts
|
|
42240
|
-
var
|
|
42282
|
+
var POLL_MS3 = 1e3;
|
|
42241
42283
|
var MAX_ATTEMPTS = 120;
|
|
42242
42284
|
var START_SLACK_MS = 5e3;
|
|
42243
42285
|
function bindCodexSession(session, notify2) {
|
|
@@ -42245,7 +42287,7 @@ function bindCodexSession(session, notify2) {
|
|
|
42245
42287
|
if (session.harness !== "codex" || !cwd || session.harnessSessionId) return;
|
|
42246
42288
|
const since = session.startedAt - START_SLACK_MS;
|
|
42247
42289
|
let attemptsLeft = MAX_ATTEMPTS;
|
|
42248
|
-
const schedule = () => setTimeout(() => void poll(),
|
|
42290
|
+
const schedule = () => setTimeout(() => void poll(), POLL_MS3).unref();
|
|
42249
42291
|
const poll = async () => {
|
|
42250
42292
|
if (session.harnessSessionId) return;
|
|
42251
42293
|
const sessionId = await resolveCodexSessionId(cwd, since);
|
|
@@ -43217,6 +43259,7 @@ function respawnSession(session, respawn, status2, clients, onStatusChange) {
|
|
|
43217
43259
|
session.gitWatcher = void 0;
|
|
43218
43260
|
session.undurable = void 0;
|
|
43219
43261
|
session.pendingDismiss = void 0;
|
|
43262
|
+
session.closeGrace?.cancel();
|
|
43220
43263
|
session.closing = void 0;
|
|
43221
43264
|
session.scrollback = "";
|
|
43222
43265
|
session.startedAt = Date.now();
|
|
@@ -43842,11 +43885,25 @@ function isOnceLaunch(persisted) {
|
|
|
43842
43885
|
return persisted.commandType === "assist" && !!persisted.assistArgs && LAUNCH_COMMANDS.includes(persisted.assistArgs[0]) && persisted.assistArgs.includes("--once");
|
|
43843
43886
|
}
|
|
43844
43887
|
|
|
43888
|
+
// src/commands/sessions/daemon/relaunchConsoleWatcher.ts
|
|
43889
|
+
function isConsoleWatcher(persisted) {
|
|
43890
|
+
return persisted.watcher === true && persisted.commandType === "assist" && !!persisted.assistArgs;
|
|
43891
|
+
}
|
|
43892
|
+
function relaunchConsoleWatcher(id, persisted, base) {
|
|
43893
|
+
const command = ["assist", ...persisted.assistArgs];
|
|
43894
|
+
daemonLog(
|
|
43895
|
+
`relaunching watcher session ${id} running ${command.join(" ")} in ${persisted.cwd ?? "(no cwd)"}`
|
|
43896
|
+
);
|
|
43897
|
+
return runningSession(base, persisted, spawnPty(command, persisted.cwd, id));
|
|
43898
|
+
}
|
|
43899
|
+
|
|
43845
43900
|
// src/commands/sessions/daemon/restoreSession.ts
|
|
43846
43901
|
function restoreSession(id, persisted) {
|
|
43847
43902
|
const base = restoreBase(id, persisted);
|
|
43848
43903
|
if (persisted.status === "stopped") return stoppedSession(base, persisted);
|
|
43849
43904
|
if (isUpdate(persisted)) return updatedSession(id, persisted);
|
|
43905
|
+
if (isConsoleWatcher(persisted))
|
|
43906
|
+
return relaunchConsoleWatcher(id, persisted, base);
|
|
43850
43907
|
const status2 = deriveRestoreStatus(persisted);
|
|
43851
43908
|
if (needsWrapperRelaunch(persisted)) {
|
|
43852
43909
|
const resumesWrittenConversation = hasTranscriptOnDisk(persisted);
|
|
@@ -44337,26 +44394,35 @@ function startReusedRunPty(session, assistArgs, itemId2, hold, clients, onStatus
|
|
|
44337
44394
|
return true;
|
|
44338
44395
|
}
|
|
44339
44396
|
|
|
44397
|
+
// src/commands/sessions/daemon/createAssistSession.ts
|
|
44398
|
+
function createAssistSession(id, assistArgs, cwd, meta, holdPty) {
|
|
44399
|
+
const startedAt = Date.now();
|
|
44400
|
+
return {
|
|
44401
|
+
id,
|
|
44402
|
+
name: `assist ${assistArgs.join(" ")}`,
|
|
44403
|
+
title: meta?.title,
|
|
44404
|
+
subtitle: meta?.subtitle,
|
|
44405
|
+
commandType: "assist",
|
|
44406
|
+
status: "running",
|
|
44407
|
+
startedAt,
|
|
44408
|
+
runningMs: 0,
|
|
44409
|
+
runningSince: startedAt,
|
|
44410
|
+
waitingSince: null,
|
|
44411
|
+
...startOrHoldPty(
|
|
44412
|
+
() => spawnPty(["assist", ...assistArgs], cwd, id),
|
|
44413
|
+
holdPty
|
|
44414
|
+
),
|
|
44415
|
+
scrollback: "",
|
|
44416
|
+
assistArgs,
|
|
44417
|
+
cwd
|
|
44418
|
+
};
|
|
44419
|
+
}
|
|
44420
|
+
|
|
44340
44421
|
// src/commands/sessions/daemon/createWatcherSession.ts
|
|
44341
|
-
|
|
44342
|
-
var WATCH_PROMPT = "/watch";
|
|
44422
|
+
var WATCHER_ARGS = ["watch", "loop"];
|
|
44343
44423
|
function createWatcherSession(id, cwd) {
|
|
44344
|
-
const claudeSessionId = randomUUID24();
|
|
44345
44424
|
return {
|
|
44346
|
-
...
|
|
44347
|
-
name: `Session ${id}`,
|
|
44348
|
-
commandType: "claude",
|
|
44349
|
-
pty: spawnClaude2({
|
|
44350
|
-
prompt: WATCH_PROMPT,
|
|
44351
|
-
cwd,
|
|
44352
|
-
sessionId: id,
|
|
44353
|
-
claudeSessionId,
|
|
44354
|
-
auto: true
|
|
44355
|
-
}),
|
|
44356
|
-
cwd,
|
|
44357
|
-
claudeSessionId,
|
|
44358
|
-
initialPrompt: WATCH_PROMPT,
|
|
44359
|
-
auto: true,
|
|
44425
|
+
...createAssistSession(id, WATCHER_ARGS, cwd),
|
|
44360
44426
|
watcher: true
|
|
44361
44427
|
};
|
|
44362
44428
|
}
|
|
@@ -44424,7 +44490,7 @@ function ensureWatcher(ctx, cwd) {
|
|
|
44424
44490
|
{ inPlace: true }
|
|
44425
44491
|
);
|
|
44426
44492
|
daemonLog(
|
|
44427
|
-
`spawned watcher session ${id} running
|
|
44493
|
+
`spawned watcher session ${id} running assist ${WATCHER_ARGS.join(" ")} in the clone ${clone}`
|
|
44428
44494
|
);
|
|
44429
44495
|
return id;
|
|
44430
44496
|
}
|
|
@@ -45494,30 +45560,6 @@ function addAgentToStream(ctx, targetId, request) {
|
|
|
45494
45560
|
};
|
|
45495
45561
|
}
|
|
45496
45562
|
|
|
45497
|
-
// src/commands/sessions/daemon/createAssistSession.ts
|
|
45498
|
-
function createAssistSession(id, assistArgs, cwd, meta, holdPty) {
|
|
45499
|
-
const startedAt = Date.now();
|
|
45500
|
-
return {
|
|
45501
|
-
id,
|
|
45502
|
-
name: `assist ${assistArgs.join(" ")}`,
|
|
45503
|
-
title: meta?.title,
|
|
45504
|
-
subtitle: meta?.subtitle,
|
|
45505
|
-
commandType: "assist",
|
|
45506
|
-
status: "running",
|
|
45507
|
-
startedAt,
|
|
45508
|
-
runningMs: 0,
|
|
45509
|
-
runningSince: startedAt,
|
|
45510
|
-
waitingSince: null,
|
|
45511
|
-
...startOrHoldPty(
|
|
45512
|
-
() => spawnPty(["assist", ...assistArgs], cwd, id),
|
|
45513
|
-
holdPty
|
|
45514
|
-
),
|
|
45515
|
-
scrollback: "",
|
|
45516
|
-
assistArgs,
|
|
45517
|
-
cwd
|
|
45518
|
-
};
|
|
45519
|
-
}
|
|
45520
|
-
|
|
45521
45563
|
// src/commands/sessions/daemon/worktree/spawnInTree.ts
|
|
45522
45564
|
function spawnInTree(ctx, { prompt, cwd, design, auto, harness, inPlace }, context) {
|
|
45523
45565
|
return allocateAndBind(
|