@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/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.523.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 path71 = nextWorktreePath(
19967
- clone,
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
- if (mustLeaveTrunk(cfg.trunk, options2))
20084
- daemonLog(
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 mkdirSync28 } from "fs";
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/toSessionInfo.ts
29663
- function toSessionInfo({
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
- design,
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
- usedPct,
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 = serverRunMeta(runName, cwd)) {
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
- server: meta.server || void 0,
30011
- serverPort: meta.port,
30012
- serverOrigin: meta.origin
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
- if (isPrCheckoutArgs(args)) return true;
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
- pty: spawnClaude2({ resumeSessionId: sessionId, cwd, sessionId: id }),
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
- return allocateAndBind(
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(runName, runArgs, cwd, meta) {
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 existsSync75 } from "fs";
34027
+ import { existsSync as existsSync78 } from "fs";
33860
34028
  function repoDirExists(cwd) {
33861
- return existsSync75(toGitCwd(cwd));
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
- mkdirSync28(daemonPaths.dir, { recursive: true });
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 join78, resolve as resolve21 } from "path";
34589
+ import { isAbsolute as isAbsolute4, join as join79, resolve as resolve21 } from "path";
34422
34590
  function resolveGitDir(cwd) {
34423
- const dotGit = join78(cwd, ".git");
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(join78(gitDir, "HEAD"), "utf8");
34621
+ head = readFileSync54(join79(gitDir, "HEAD"), "utf8");
34454
34622
  } catch {
34455
34623
  return null;
34456
34624
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@staff0rd/assist",
3
- "version": "0.523.0",
3
+ "version": "0.525.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "bin": {