@staff0rd/assist 0.523.0 → 0.525.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/README.md +2 -1
- package/dist/commands/sessions/web/bundle.js +321 -321
- package/dist/index.js +238 -70
- 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.525.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -521,6 +521,7 @@ var assistConfigShape = {
|
|
|
521
521
|
}).optional(),
|
|
522
522
|
worktree: z3.strictObject({
|
|
523
523
|
enabled: z3.boolean().default(false),
|
|
524
|
+
watcher: z3.boolean().default(false),
|
|
524
525
|
trunk: z3.boolean().default(false),
|
|
525
526
|
includeDrafts: z3.boolean().default(false),
|
|
526
527
|
root: z3.string().optional(),
|
|
@@ -4252,6 +4253,11 @@ var sessionsConfigHelp = [
|
|
|
4252
4253
|
setter: "assist config set worktree.enabled true -g --repo",
|
|
4253
4254
|
note: "opt in per repo: spill concurrent sessions into adjacent <clone>-N worktrees (default off)"
|
|
4254
4255
|
},
|
|
4256
|
+
{
|
|
4257
|
+
key: "worktree.watcher",
|
|
4258
|
+
setter: "assist config set worktree.watcher true -g --repo",
|
|
4259
|
+
note: "a backlog run also starts one starred claude session in the clone running /watch, so the built version stays current while the run works in its worktree; requires worktree.enabled and a /watch command in the repo (default off)"
|
|
4260
|
+
},
|
|
4255
4261
|
{
|
|
4256
4262
|
key: "worktree.trunk",
|
|
4257
4263
|
setter: "assist config set worktree.trunk true -g --repo",
|
|
@@ -19959,15 +19965,12 @@ function cloneHead(clone) {
|
|
|
19959
19965
|
}
|
|
19960
19966
|
|
|
19961
19967
|
// src/commands/sessions/daemon/worktree/createWorktree.ts
|
|
19962
|
-
function createWorktree(clone, strategy, boundTreeRoots2) {
|
|
19968
|
+
function createWorktree(clone, strategy, boundTreeRoots2, preferredPath) {
|
|
19963
19969
|
const base = strategy.root ? expandTilde2(strategy.root) : dirname25(clone);
|
|
19964
19970
|
const registered = new Set(listWorktreePaths(clone));
|
|
19965
19971
|
const branches = new Set(listLocalBranches(clone));
|
|
19966
|
-
const
|
|
19967
|
-
|
|
19968
|
-
base,
|
|
19969
|
-
(candidate) => registered.has(candidate) || existsSync45(candidate) || boundTreeRoots2.has(candidate) || branches.has(basename14(candidate))
|
|
19970
|
-
);
|
|
19972
|
+
const isTaken = (candidate) => registered.has(candidate) || existsSync45(candidate) || boundTreeRoots2.has(candidate) || branches.has(basename14(candidate));
|
|
19973
|
+
const path71 = preferredPath && !isTaken(preferredPath) ? preferredPath : nextWorktreePath(clone, base, isTaken);
|
|
19971
19974
|
const start3 = worktreeStartPoint(clone, strategy.trunk);
|
|
19972
19975
|
gitSync(clone, [
|
|
19973
19976
|
"worktree",
|
|
@@ -20055,6 +20058,7 @@ function wouldDisturbWorkInProgress(clone, forCheckout) {
|
|
|
20055
20058
|
// src/commands/sessions/daemon/worktree/worktreeConfigFor.ts
|
|
20056
20059
|
var DISABLED = {
|
|
20057
20060
|
enabled: false,
|
|
20061
|
+
watcher: false,
|
|
20058
20062
|
trunk: false,
|
|
20059
20063
|
includeDrafts: false,
|
|
20060
20064
|
install: true,
|
|
@@ -20069,6 +20073,15 @@ function worktreeConfigFor(cwd) {
|
|
|
20069
20073
|
}
|
|
20070
20074
|
}
|
|
20071
20075
|
|
|
20076
|
+
// src/commands/sessions/daemon/worktree/forcedSpillReason.ts
|
|
20077
|
+
function forcedSpillReason(clone, trunk, options2) {
|
|
20078
|
+
if (options2.replacesTree)
|
|
20079
|
+
return `resumed session spilled out of the clone ${clone}: its worktree ${options2.replacesTree} is gone`;
|
|
20080
|
+
if (trunk === true && options2.commits === true)
|
|
20081
|
+
return `committing session spilled out of the clone ${clone}: worktree.trunk is on, so a commit here would land on the local mainline`;
|
|
20082
|
+
return void 0;
|
|
20083
|
+
}
|
|
20084
|
+
|
|
20072
20085
|
// src/commands/sessions/daemon/worktree/allocateTree.ts
|
|
20073
20086
|
function allocateTree(requestedCwd, boundTreeRoots2, options2 = {}) {
|
|
20074
20087
|
if (!requestedCwd)
|
|
@@ -20080,22 +20093,18 @@ function allocateTree(requestedCwd, boundTreeRoots2, options2 = {}) {
|
|
|
20080
20093
|
return { cwd: requestedCwd, kind: "primary", created: false };
|
|
20081
20094
|
const clone = mainWorktree(repoRoot2) ?? repoRoot2;
|
|
20082
20095
|
const reuse = { ...options2, includeDrafts: cfg.includeDrafts };
|
|
20083
|
-
|
|
20084
|
-
|
|
20085
|
-
`committing session spilled out of the clone ${clone}: worktree.trunk is on, so a commit here would land on the local mainline`
|
|
20086
|
-
);
|
|
20096
|
+
const forcedSpill = forcedSpillReason(clone, cfg.trunk, options2);
|
|
20097
|
+
if (forcedSpill) daemonLog(forcedSpill);
|
|
20087
20098
|
else if (reusesClone(clone, boundTreeRoots2, reuse))
|
|
20088
20099
|
return { cwd: clone, kind: "primary", created: false, clone };
|
|
20089
20100
|
const path71 = createWorktree(
|
|
20090
20101
|
clone,
|
|
20091
20102
|
{ root: cfg.root, trunk: cfg.trunk },
|
|
20092
|
-
boundTreeRoots2
|
|
20103
|
+
boundTreeRoots2,
|
|
20104
|
+
options2.replacesTree
|
|
20093
20105
|
);
|
|
20094
20106
|
return { cwd: path71, kind: "worktree", created: true, clone };
|
|
20095
20107
|
}
|
|
20096
|
-
function mustLeaveTrunk(trunk, options2) {
|
|
20097
|
-
return trunk === true && options2.commits === true;
|
|
20098
|
-
}
|
|
20099
20108
|
function keptInPlace(cwd) {
|
|
20100
20109
|
daemonLog(
|
|
20101
20110
|
`session kept in ${cwd}: launched against work already checked out there`
|
|
@@ -20142,6 +20151,7 @@ var persistedSessionSchema = z8.object({
|
|
|
20142
20151
|
assistArgs: z8.array(z8.string()).optional(),
|
|
20143
20152
|
activity: activitySchema.optional(),
|
|
20144
20153
|
starred: z8.boolean().optional(),
|
|
20154
|
+
watcher: z8.boolean().optional(),
|
|
20145
20155
|
autoRun: z8.boolean().optional(),
|
|
20146
20156
|
autoAdvance: z8.boolean().optional(),
|
|
20147
20157
|
reviewStarted: z8.boolean().optional(),
|
|
@@ -20169,6 +20179,7 @@ function toPersistedSession(session) {
|
|
|
20169
20179
|
assistArgs: session.assistArgs,
|
|
20170
20180
|
activity: session.activity,
|
|
20171
20181
|
starred: session.starred,
|
|
20182
|
+
watcher: session.watcher,
|
|
20172
20183
|
autoRun: session.autoRun,
|
|
20173
20184
|
autoAdvance: session.autoAdvance,
|
|
20174
20185
|
reviewStarted: session.reviewStarted,
|
|
@@ -29594,7 +29605,7 @@ function requestDrain(socket, lines2) {
|
|
|
29594
29605
|
}
|
|
29595
29606
|
|
|
29596
29607
|
// src/commands/sessions/daemon/runDaemon.ts
|
|
29597
|
-
import { mkdirSync as
|
|
29608
|
+
import { mkdirSync as mkdirSync29 } from "fs";
|
|
29598
29609
|
|
|
29599
29610
|
// src/commands/sessions/daemon/createAutoExit.ts
|
|
29600
29611
|
var DEFAULT_GRACE_MS = 6e4;
|
|
@@ -29659,15 +29670,8 @@ function broadcast(clients, msg) {
|
|
|
29659
29670
|
}
|
|
29660
29671
|
}
|
|
29661
29672
|
|
|
29662
|
-
// src/commands/sessions/daemon/
|
|
29663
|
-
function
|
|
29664
|
-
id,
|
|
29665
|
-
name,
|
|
29666
|
-
title,
|
|
29667
|
-
generatedTitle,
|
|
29668
|
-
subtitle,
|
|
29669
|
-
commandType,
|
|
29670
|
-
harness,
|
|
29673
|
+
// src/commands/sessions/daemon/toSessionRunInfo.ts
|
|
29674
|
+
function toSessionRunInfo({
|
|
29671
29675
|
status: status3,
|
|
29672
29676
|
startedAt,
|
|
29673
29677
|
runningMs,
|
|
@@ -29680,27 +29684,12 @@ function toSessionInfo({
|
|
|
29680
29684
|
serverOrigin,
|
|
29681
29685
|
assistArgs,
|
|
29682
29686
|
cwd,
|
|
29683
|
-
claudeSessionId,
|
|
29684
|
-
restored,
|
|
29685
|
-
error,
|
|
29686
29687
|
activity: activity2,
|
|
29687
|
-
autoRun,
|
|
29688
|
-
autoAdvance,
|
|
29689
|
-
starred,
|
|
29690
29688
|
usedPct,
|
|
29691
|
-
|
|
29692
|
-
pendingPrPreview,
|
|
29693
|
-
undurable,
|
|
29689
|
+
error,
|
|
29694
29690
|
closing
|
|
29695
29691
|
}) {
|
|
29696
29692
|
return {
|
|
29697
|
-
id,
|
|
29698
|
-
name,
|
|
29699
|
-
title,
|
|
29700
|
-
generatedTitle,
|
|
29701
|
-
subtitle,
|
|
29702
|
-
commandType,
|
|
29703
|
-
harness,
|
|
29704
29693
|
status: status3,
|
|
29705
29694
|
startedAt,
|
|
29706
29695
|
runningMs,
|
|
@@ -29712,20 +29701,56 @@ function toSessionInfo({
|
|
|
29712
29701
|
port: serverPort,
|
|
29713
29702
|
remoteOrigin: serverOrigin ?? originForCwd(cwd),
|
|
29714
29703
|
assistArgs,
|
|
29704
|
+
activity: activity2,
|
|
29705
|
+
usedPct,
|
|
29706
|
+
error,
|
|
29707
|
+
closing
|
|
29708
|
+
};
|
|
29709
|
+
}
|
|
29710
|
+
|
|
29711
|
+
// src/commands/sessions/daemon/toSessionInfo.ts
|
|
29712
|
+
function toSessionInfo(session) {
|
|
29713
|
+
const {
|
|
29714
|
+
id,
|
|
29715
|
+
name,
|
|
29716
|
+
title,
|
|
29717
|
+
generatedTitle,
|
|
29718
|
+
subtitle,
|
|
29719
|
+
commandType,
|
|
29720
|
+
harness,
|
|
29721
|
+
cwd,
|
|
29722
|
+
launchedFrom,
|
|
29723
|
+
claudeSessionId,
|
|
29724
|
+
restored,
|
|
29725
|
+
autoRun,
|
|
29726
|
+
autoAdvance,
|
|
29727
|
+
starred,
|
|
29728
|
+
watcher,
|
|
29729
|
+
design,
|
|
29730
|
+
pendingPrPreview,
|
|
29731
|
+
undurable
|
|
29732
|
+
} = session;
|
|
29733
|
+
return {
|
|
29734
|
+
...toSessionRunInfo(session),
|
|
29735
|
+
id,
|
|
29736
|
+
name,
|
|
29737
|
+
title,
|
|
29738
|
+
generatedTitle,
|
|
29739
|
+
subtitle,
|
|
29740
|
+
commandType,
|
|
29741
|
+
harness,
|
|
29715
29742
|
cwd,
|
|
29743
|
+
launchedFrom,
|
|
29716
29744
|
claudeSessionId,
|
|
29717
29745
|
repoGroup: repoGroupForCwd(cwd),
|
|
29718
29746
|
restored,
|
|
29719
|
-
error,
|
|
29720
|
-
activity: activity2,
|
|
29721
29747
|
autoRun,
|
|
29722
29748
|
autoAdvance,
|
|
29723
29749
|
starred,
|
|
29724
|
-
|
|
29750
|
+
watcher,
|
|
29725
29751
|
design,
|
|
29726
29752
|
pendingPrPreview,
|
|
29727
|
-
undurable
|
|
29728
|
-
closing
|
|
29753
|
+
undurable
|
|
29729
29754
|
};
|
|
29730
29755
|
}
|
|
29731
29756
|
|
|
@@ -29926,6 +29951,8 @@ function buildArgs3(opts) {
|
|
|
29926
29951
|
if (opts.design) {
|
|
29927
29952
|
base.push("--append-system-prompt", readDesignSystemPrompt());
|
|
29928
29953
|
base.push("--permission-mode", "auto");
|
|
29954
|
+
} else if (opts.auto) {
|
|
29955
|
+
base.push("--permission-mode", "auto");
|
|
29929
29956
|
}
|
|
29930
29957
|
if (opts.resumeSessionId) {
|
|
29931
29958
|
return opts.prompt ? [...base, "--resume", opts.resumeSessionId, opts.prompt] : [...base, "--resume", opts.resumeSessionId];
|
|
@@ -29998,7 +30025,8 @@ function createPiSession(id, prompt, cwd, holdPty) {
|
|
|
29998
30025
|
initialPrompt: prompt
|
|
29999
30026
|
};
|
|
30000
30027
|
}
|
|
30001
|
-
function createRunSession(id, runName, runArgs, cwd, meta
|
|
30028
|
+
function createRunSession(id, { runName, runArgs, cwd, meta, launchedFrom }) {
|
|
30029
|
+
const serverMeta = meta ?? serverRunMeta(runName, cwd);
|
|
30002
30030
|
return {
|
|
30003
30031
|
...sessionBase(id, "running"),
|
|
30004
30032
|
name: `run: ${runName}`,
|
|
@@ -30007,9 +30035,10 @@ function createRunSession(id, runName, runArgs, cwd, meta = serverRunMeta(runNam
|
|
|
30007
30035
|
runName,
|
|
30008
30036
|
runArgs,
|
|
30009
30037
|
cwd,
|
|
30010
|
-
|
|
30011
|
-
|
|
30012
|
-
|
|
30038
|
+
launchedFrom,
|
|
30039
|
+
server: serverMeta.server || void 0,
|
|
30040
|
+
serverPort: serverMeta.port,
|
|
30041
|
+
serverOrigin: serverMeta.origin
|
|
30013
30042
|
};
|
|
30014
30043
|
}
|
|
30015
30044
|
|
|
@@ -30614,8 +30643,9 @@ var PrPreviewCoordinator = class {
|
|
|
30614
30643
|
|
|
30615
30644
|
// src/commands/sessions/daemon/logSpawnedSession.ts
|
|
30616
30645
|
function logSpawnedSession(session) {
|
|
30646
|
+
const launchedFrom = session.launchedFrom ? ` launched from ${session.launchedFrom}` : "";
|
|
30617
30647
|
daemonLog(
|
|
30618
|
-
`session ${session.id} spawned: ${session.name} [${session.commandType}] ${session.cwd ?? ""}`
|
|
30648
|
+
`session ${session.id} spawned: ${session.name} [${session.commandType}] ${session.cwd ?? ""}${launchedFrom}`
|
|
30619
30649
|
);
|
|
30620
30650
|
}
|
|
30621
30651
|
|
|
@@ -31915,6 +31945,7 @@ function restoreBase(id, persisted) {
|
|
|
31915
31945
|
assistArgs: persisted.assistArgs,
|
|
31916
31946
|
initialPrompt: persisted.initialPrompt,
|
|
31917
31947
|
starred: persisted.starred,
|
|
31948
|
+
watcher: persisted.watcher,
|
|
31918
31949
|
autoRun: persisted.autoRun,
|
|
31919
31950
|
autoAdvance: restoredAutoAdvance(id, persisted),
|
|
31920
31951
|
reviewStarted: persisted.reviewStarted
|
|
@@ -32562,6 +32593,14 @@ function startReusedRunPty(session, assistArgs, itemId2, hold, clients, onStatus
|
|
|
32562
32593
|
return true;
|
|
32563
32594
|
}
|
|
32564
32595
|
|
|
32596
|
+
// src/commands/sessions/daemon/worktree/isBacklogRunArgs.ts
|
|
32597
|
+
var ITEM_ID = /^a?\d+$/;
|
|
32598
|
+
function isBacklogRunArgs(args) {
|
|
32599
|
+
const [command, subcommand, ...rest] = args;
|
|
32600
|
+
if (command !== "backlog" || subcommand !== "run") return false;
|
|
32601
|
+
return rest.some((arg) => ITEM_ID.test(arg));
|
|
32602
|
+
}
|
|
32603
|
+
|
|
32565
32604
|
// src/commands/sessions/daemon/worktree/isPrCheckoutArgs.ts
|
|
32566
32605
|
var CHECKOUT_COMMANDS = /* @__PURE__ */ new Set(["review", "review-pr-comments"]);
|
|
32567
32606
|
function isPrCheckoutArgs(args) {
|
|
@@ -32571,12 +32610,8 @@ function isPrCheckoutArgs(args) {
|
|
|
32571
32610
|
}
|
|
32572
32611
|
|
|
32573
32612
|
// src/commands/sessions/daemon/worktree/isCommittingArgs.ts
|
|
32574
|
-
var ITEM_ID = /^a?\d+$/;
|
|
32575
32613
|
function isCommittingArgs(args) {
|
|
32576
|
-
|
|
32577
|
-
const [command, subcommand, ...rest] = args;
|
|
32578
|
-
if (command !== "backlog" || subcommand !== "run") return false;
|
|
32579
|
-
return rest.some((arg) => ITEM_ID.test(arg));
|
|
32614
|
+
return isPrCheckoutArgs(args) || isBacklogRunArgs(args);
|
|
32580
32615
|
}
|
|
32581
32616
|
|
|
32582
32617
|
// src/commands/sessions/daemon/worktree/boundTreeRoots.ts
|
|
@@ -33459,6 +33494,9 @@ function addAgentToStream(ctx, targetId, prompt, harness) {
|
|
|
33459
33494
|
return spawnIntoStream(ctx, joinable.session, prompt, harness);
|
|
33460
33495
|
}
|
|
33461
33496
|
|
|
33497
|
+
// src/commands/sessions/daemon/worktree/spawnInTree.ts
|
|
33498
|
+
import { existsSync as existsSync77 } from "fs";
|
|
33499
|
+
|
|
33462
33500
|
// src/commands/sessions/daemon/createAssistSession.ts
|
|
33463
33501
|
function createAssistSession(id, assistArgs, cwd, meta, holdPty) {
|
|
33464
33502
|
const startedAt = Date.now();
|
|
@@ -33484,7 +33522,7 @@ function createAssistSession(id, assistArgs, cwd, meta, holdPty) {
|
|
|
33484
33522
|
}
|
|
33485
33523
|
|
|
33486
33524
|
// src/commands/sessions/daemon/resumeSession.ts
|
|
33487
|
-
function resumeSession(id, sessionId, cwd, name) {
|
|
33525
|
+
function resumeSession(id, sessionId, cwd, name, holdPty) {
|
|
33488
33526
|
const startedAt = Date.now();
|
|
33489
33527
|
return {
|
|
33490
33528
|
id,
|
|
@@ -33495,7 +33533,10 @@ function resumeSession(id, sessionId, cwd, name) {
|
|
|
33495
33533
|
runningMs: 0,
|
|
33496
33534
|
runningSince: null,
|
|
33497
33535
|
waitingSince: startedAt,
|
|
33498
|
-
|
|
33536
|
+
...startOrHoldPty(
|
|
33537
|
+
() => spawnClaude2({ resumeSessionId: sessionId, cwd, sessionId: id }),
|
|
33538
|
+
holdPty
|
|
33539
|
+
),
|
|
33499
33540
|
scrollback: "",
|
|
33500
33541
|
cwd,
|
|
33501
33542
|
/* why: bind the card to the conversation it is resuming so a daemon restart
|
|
@@ -33514,6 +33555,128 @@ function allocateAndBind(ctx, cwd, create, options2 = {}) {
|
|
|
33514
33555
|
return id;
|
|
33515
33556
|
}
|
|
33516
33557
|
|
|
33558
|
+
// src/commands/sessions/daemon/createWatcherSession.ts
|
|
33559
|
+
import { randomUUID as randomUUID11 } from "crypto";
|
|
33560
|
+
var WATCH_PROMPT = "/watch";
|
|
33561
|
+
function createWatcherSession(id, cwd) {
|
|
33562
|
+
const claudeSessionId = randomUUID11();
|
|
33563
|
+
return {
|
|
33564
|
+
...sessionBase(id, "running"),
|
|
33565
|
+
name: `Session ${id}`,
|
|
33566
|
+
commandType: "claude",
|
|
33567
|
+
pty: spawnClaude2({
|
|
33568
|
+
prompt: WATCH_PROMPT,
|
|
33569
|
+
cwd,
|
|
33570
|
+
sessionId: id,
|
|
33571
|
+
claudeSessionId,
|
|
33572
|
+
auto: true
|
|
33573
|
+
}),
|
|
33574
|
+
cwd,
|
|
33575
|
+
claudeSessionId,
|
|
33576
|
+
initialPrompt: WATCH_PROMPT,
|
|
33577
|
+
starred: true,
|
|
33578
|
+
watcher: true
|
|
33579
|
+
};
|
|
33580
|
+
}
|
|
33581
|
+
|
|
33582
|
+
// src/commands/sessions/daemon/worktree/ensureWatcher.ts
|
|
33583
|
+
function ensureWatcher(ctx, cwd) {
|
|
33584
|
+
if (!cwd) return void 0;
|
|
33585
|
+
const repoRoot2 = findRepoRoot(cwd) ?? cwd;
|
|
33586
|
+
const cfg = worktreeConfigFor(repoRoot2);
|
|
33587
|
+
if (!cfg.enabled || cfg.watcher !== true) return void 0;
|
|
33588
|
+
const clone = mainWorktree(repoRoot2) ?? repoRoot2;
|
|
33589
|
+
const live = liveWatcherFor(ctx.sessions, clone);
|
|
33590
|
+
if (live) {
|
|
33591
|
+
daemonLog(
|
|
33592
|
+
`no watcher spawned for the clone ${clone}: session ${live.id} is already watching it (${live.status})`
|
|
33593
|
+
);
|
|
33594
|
+
return void 0;
|
|
33595
|
+
}
|
|
33596
|
+
const id = allocateAndBind(
|
|
33597
|
+
ctx,
|
|
33598
|
+
clone,
|
|
33599
|
+
(sid, resolvedCwd) => createWatcherSession(sid, resolvedCwd ?? clone),
|
|
33600
|
+
{ inPlace: true }
|
|
33601
|
+
);
|
|
33602
|
+
daemonLog(
|
|
33603
|
+
`spawned watcher session ${id} running /watch in the clone ${clone}`
|
|
33604
|
+
);
|
|
33605
|
+
return id;
|
|
33606
|
+
}
|
|
33607
|
+
function liveWatcherFor(sessions, clone) {
|
|
33608
|
+
for (const session of sessions.values())
|
|
33609
|
+
if (session.watcher === true && session.cwd === clone && session.status !== "stopped" && session.status !== "error")
|
|
33610
|
+
return session;
|
|
33611
|
+
return void 0;
|
|
33612
|
+
}
|
|
33613
|
+
|
|
33614
|
+
// src/commands/sessions/daemon/worktree/resumeInReplacementTree.ts
|
|
33615
|
+
import { existsSync as existsSync76 } from "fs";
|
|
33616
|
+
|
|
33617
|
+
// src/commands/sessions/daemon/worktree/carryTranscriptToTree.ts
|
|
33618
|
+
import { copyFileSync as copyFileSync2, existsSync as existsSync75, mkdirSync as mkdirSync28 } from "fs";
|
|
33619
|
+
import { join as join78 } from "path";
|
|
33620
|
+
function carryTranscriptToTree(claudeSessionId, fromCwd, toCwd) {
|
|
33621
|
+
const dir = projectDirForCwd(toCwd);
|
|
33622
|
+
if (dir === projectDirForCwd(fromCwd)) {
|
|
33623
|
+
daemonLog(
|
|
33624
|
+
`transcript ${claudeSessionId} already lives in ${dir}: resuming in the original worktree path`
|
|
33625
|
+
);
|
|
33626
|
+
return;
|
|
33627
|
+
}
|
|
33628
|
+
const dest = join78(dir, `${claudeSessionId}.jsonl`);
|
|
33629
|
+
if (existsSync75(dest)) {
|
|
33630
|
+
daemonLog(`transcript ${claudeSessionId} already present in ${dir}`);
|
|
33631
|
+
return;
|
|
33632
|
+
}
|
|
33633
|
+
const source = findTranscriptPathSync(fromCwd, claudeSessionId);
|
|
33634
|
+
if (!source) {
|
|
33635
|
+
daemonLog(
|
|
33636
|
+
`transcript ${claudeSessionId} not found under ${projectDirForCwd(fromCwd)}: resuming in ${toCwd} without it`
|
|
33637
|
+
);
|
|
33638
|
+
return;
|
|
33639
|
+
}
|
|
33640
|
+
try {
|
|
33641
|
+
mkdirSync28(dir, { recursive: true });
|
|
33642
|
+
copyFileSync2(source, dest);
|
|
33643
|
+
daemonLog(
|
|
33644
|
+
`transcript ${source} copied to ${dest} so ${toCwd} can resume it`
|
|
33645
|
+
);
|
|
33646
|
+
} catch (error) {
|
|
33647
|
+
daemonLog(
|
|
33648
|
+
`transcript ${claudeSessionId} could not be copied to ${dir}: ${error instanceof Error ? error.message : String(error)}`
|
|
33649
|
+
);
|
|
33650
|
+
}
|
|
33651
|
+
}
|
|
33652
|
+
|
|
33653
|
+
// src/commands/sessions/daemon/worktree/resumeInReplacementTree.ts
|
|
33654
|
+
function resumeInReplacementTree(ctx, claudeSessionId, missingCwd, name) {
|
|
33655
|
+
const clone = cloneForReapedTree(missingCwd);
|
|
33656
|
+
daemonLog(
|
|
33657
|
+
`resuming ${claudeSessionId}: its tree ${missingCwd} is gone, allocating from clone ${clone}`
|
|
33658
|
+
);
|
|
33659
|
+
return allocateAndBind(
|
|
33660
|
+
ctx,
|
|
33661
|
+
clone,
|
|
33662
|
+
(id, resolvedCwd, holdUntilSeeded) => {
|
|
33663
|
+
const cwd = resolvedCwd ?? clone;
|
|
33664
|
+
carryTranscriptToTree(claudeSessionId, missingCwd, cwd);
|
|
33665
|
+
daemonLog(`session ${id} resuming ${claudeSessionId} in ${cwd}`);
|
|
33666
|
+
return resumeSession(id, claudeSessionId, cwd, name, holdUntilSeeded);
|
|
33667
|
+
},
|
|
33668
|
+
{ replacesTree: missingCwd }
|
|
33669
|
+
);
|
|
33670
|
+
}
|
|
33671
|
+
function cloneForReapedTree(missingCwd) {
|
|
33672
|
+
const clone = worktreeAttributionIncludingReaped(missingCwd)?.clone;
|
|
33673
|
+
if (!clone || !existsSync76(clone))
|
|
33674
|
+
throw new Error(
|
|
33675
|
+
`working directory no longer exists and no clone is recorded to re-allocate from: ${missingCwd}`
|
|
33676
|
+
);
|
|
33677
|
+
return clone;
|
|
33678
|
+
}
|
|
33679
|
+
|
|
33517
33680
|
// src/commands/sessions/daemon/worktree/spawnInTree.ts
|
|
33518
33681
|
function spawnInTree(ctx, prompt, cwd, design, harness, inPlace) {
|
|
33519
33682
|
return allocateAndBind(
|
|
@@ -33524,7 +33687,7 @@ function spawnInTree(ctx, prompt, cwd, design, harness, inPlace) {
|
|
|
33524
33687
|
);
|
|
33525
33688
|
}
|
|
33526
33689
|
function spawnAssistInTree(ctx, assistArgs, cwd, meta) {
|
|
33527
|
-
|
|
33690
|
+
const id = allocateAndBind(
|
|
33528
33691
|
ctx,
|
|
33529
33692
|
cwd,
|
|
33530
33693
|
(sid, resolvedCwd, holdUntilSeeded) => createAssistSession(sid, assistArgs, resolvedCwd, meta, holdUntilSeeded),
|
|
@@ -33535,9 +33698,14 @@ function spawnAssistInTree(ctx, assistArgs, cwd, meta) {
|
|
|
33535
33698
|
inPlace: meta?.inPlace
|
|
33536
33699
|
}
|
|
33537
33700
|
);
|
|
33701
|
+
if (isBacklogRunArgs(assistArgs)) ensureWatcher(ctx, cwd);
|
|
33702
|
+
return id;
|
|
33538
33703
|
}
|
|
33539
33704
|
function resumeInTree(ctx, sessionId, cwd, name) {
|
|
33705
|
+
if (!existsSync77(cwd))
|
|
33706
|
+
return resumeInReplacementTree(ctx, sessionId, cwd, name);
|
|
33540
33707
|
const id = ctx.spawnWith((sid) => resumeSession(sid, sessionId, cwd, name));
|
|
33708
|
+
daemonLog(`session ${id} resuming ${sessionId} in ${cwd}`);
|
|
33541
33709
|
bindResumedWorktree(ctx.sessions.get(id), cwd, ctx.notify);
|
|
33542
33710
|
return id;
|
|
33543
33711
|
}
|
|
@@ -33667,10 +33835,8 @@ var SessionManager = class {
|
|
|
33667
33835
|
addAgent(targetId, prompt, harness) {
|
|
33668
33836
|
return addAgentToStream(this.treeCtx(), targetId, prompt, harness);
|
|
33669
33837
|
}
|
|
33670
|
-
spawnRun(
|
|
33671
|
-
return this.spawnWith(
|
|
33672
|
-
(id) => createRunSession(id, runName, runArgs, cwd, meta)
|
|
33673
|
-
);
|
|
33838
|
+
spawnRun(request) {
|
|
33839
|
+
return this.spawnWith((id) => createRunSession(id, request));
|
|
33674
33840
|
}
|
|
33675
33841
|
liveServerRun(origin, excludeId) {
|
|
33676
33842
|
return liveServerRun(this.sessions, origin, excludeId);
|
|
@@ -33783,6 +33949,7 @@ function handleCreateRun(client, m, d) {
|
|
|
33783
33949
|
const runName = d.runName;
|
|
33784
33950
|
const cwd = d.cwd;
|
|
33785
33951
|
const runArgs = d.runArgs ?? [];
|
|
33952
|
+
const launchedFrom = d.launchedFrom;
|
|
33786
33953
|
const meta = serverRunMeta(runName, cwd);
|
|
33787
33954
|
if (meta.server && meta.origin) {
|
|
33788
33955
|
const existing = m.liveServerRun(meta.origin);
|
|
@@ -33794,6 +33961,7 @@ function handleCreateRun(client, m, d) {
|
|
|
33794
33961
|
type: "run-conflict",
|
|
33795
33962
|
runName,
|
|
33796
33963
|
cwd,
|
|
33964
|
+
launchedFrom,
|
|
33797
33965
|
existing: serverConflictInfo(existing)
|
|
33798
33966
|
});
|
|
33799
33967
|
return;
|
|
@@ -33807,7 +33975,7 @@ function handleCreateRun(client, m, d) {
|
|
|
33807
33975
|
}
|
|
33808
33976
|
sendTo(client, {
|
|
33809
33977
|
type: "created",
|
|
33810
|
-
sessionId: m.spawnRun(runName, runArgs, cwd, meta),
|
|
33978
|
+
sessionId: m.spawnRun({ runName, runArgs, cwd, meta, launchedFrom }),
|
|
33811
33979
|
isNew: true
|
|
33812
33980
|
});
|
|
33813
33981
|
}
|
|
@@ -33856,9 +34024,9 @@ function safeParse2(line) {
|
|
|
33856
34024
|
}
|
|
33857
34025
|
|
|
33858
34026
|
// src/commands/sessions/daemon/repoDirExists.ts
|
|
33859
|
-
import { existsSync as
|
|
34027
|
+
import { existsSync as existsSync78 } from "fs";
|
|
33860
34028
|
function repoDirExists(cwd) {
|
|
33861
|
-
return
|
|
34029
|
+
return existsSync78(toGitCwd(cwd));
|
|
33862
34030
|
}
|
|
33863
34031
|
|
|
33864
34032
|
// src/commands/sessions/daemon/withRepoGroups.ts
|
|
@@ -34159,7 +34327,7 @@ async function recoverFromAddrInUse(server, manager, checkAutoExit) {
|
|
|
34159
34327
|
|
|
34160
34328
|
// src/commands/sessions/daemon/runDaemon.ts
|
|
34161
34329
|
async function runDaemon() {
|
|
34162
|
-
|
|
34330
|
+
mkdirSync29(daemonPaths.dir, { recursive: true });
|
|
34163
34331
|
daemonLog(
|
|
34164
34332
|
`starting (reason: ${process.env.ASSIST_DAEMON_SPAWN_REASON ?? "manual"})`
|
|
34165
34333
|
);
|
|
@@ -34418,9 +34586,9 @@ function buildLimitsSegment(rateLimits) {
|
|
|
34418
34586
|
|
|
34419
34587
|
// src/commands/readGitBranch.ts
|
|
34420
34588
|
import { readFileSync as readFileSync54, statSync as statSync14 } from "fs";
|
|
34421
|
-
import { isAbsolute as isAbsolute4, join as
|
|
34589
|
+
import { isAbsolute as isAbsolute4, join as join79, resolve as resolve21 } from "path";
|
|
34422
34590
|
function resolveGitDir(cwd) {
|
|
34423
|
-
const dotGit =
|
|
34591
|
+
const dotGit = join79(cwd, ".git");
|
|
34424
34592
|
let stat4;
|
|
34425
34593
|
try {
|
|
34426
34594
|
stat4 = statSync14(dotGit);
|
|
@@ -34450,7 +34618,7 @@ function readGitBranch(cwd) {
|
|
|
34450
34618
|
}
|
|
34451
34619
|
let head;
|
|
34452
34620
|
try {
|
|
34453
|
-
head = readFileSync54(
|
|
34621
|
+
head = readFileSync54(join79(gitDir, "HEAD"), "utf8");
|
|
34454
34622
|
} catch {
|
|
34455
34623
|
return null;
|
|
34456
34624
|
}
|