@staff0rd/assist 0.264.2 → 0.265.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.264.2",
9
+ version: "0.265.0",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -3007,7 +3007,7 @@ function withoutResumeSession(options2) {
3007
3007
  return rest;
3008
3008
  }
3009
3009
  function spawnClaude(prompt, options2 = {}) {
3010
- const args = options2.resumeSessionId ? ["--resume", options2.resumeSessionId] : [prompt];
3010
+ const args = buildArgs(prompt, options2);
3011
3011
  const permissionMode = options2.permissionMode ?? (options2.allowEdits ? "auto" : void 0);
3012
3012
  if (permissionMode) {
3013
3013
  args.push("--permission-mode", permissionMode);
@@ -3023,6 +3023,15 @@ function spawnClaude(prompt, options2 = {}) {
3023
3023
  });
3024
3024
  return { child, done: done2 };
3025
3025
  }
3026
+ function buildArgs(prompt, options2) {
3027
+ if (options2.resumeSessionId) {
3028
+ return ["--resume", options2.resumeSessionId, prompt];
3029
+ }
3030
+ if (options2.sessionId) {
3031
+ return ["--session-id", options2.sessionId, prompt];
3032
+ }
3033
+ return [prompt];
3034
+ }
3026
3035
 
3027
3036
  // src/commands/backlog/prepareRun.ts
3028
3037
  import chalk32 from "chalk";
@@ -3601,6 +3610,7 @@ async function prepareRun(id) {
3601
3610
  }
3602
3611
 
3603
3612
  // src/commands/backlog/executePhase.ts
3613
+ import { randomUUID } from "crypto";
3604
3614
  import chalk34 from "chalk";
3605
3615
 
3606
3616
  // src/shared/emitActivity.ts
@@ -3615,6 +3625,7 @@ var activitySchema = z4.object({
3615
3625
  itemName: z4.string().optional(),
3616
3626
  phase: z4.number().optional(),
3617
3627
  totalPhases: z4.number().optional(),
3628
+ claudeSessionId: z4.string().optional(),
3618
3629
  startedAt: z4.number()
3619
3630
  });
3620
3631
  function activityPath(sessionId) {
@@ -3745,6 +3756,15 @@ function buildPhasePrompt(item, phaseNumber, phase) {
3745
3756
  return buildAuthoredPhasePrompt(item, phaseNumber, phase);
3746
3757
  }
3747
3758
 
3759
+ // src/commands/backlog/buildResumePrompt.ts
3760
+ function buildResumePrompt(phaseNumber, totalPhases) {
3761
+ return [
3762
+ `This conversation was interrupted partway through phase ${phaseNumber}/${totalPhases} by a restart.`,
3763
+ "Review what you already did earlier in this conversation and continue from where you left off to finish the phase. Do not start the phase over.",
3764
+ "When the phase is complete, run /verify and then the `assist backlog phase-done` command exactly as instructed earlier in this conversation."
3765
+ ].join("\n");
3766
+ }
3767
+
3748
3768
  // src/commands/backlog/resolvePhaseResult.ts
3749
3769
  import { existsSync as existsSync19, unlinkSync as unlinkSync3 } from "fs";
3750
3770
  import chalk33 from "chalk";
@@ -3855,17 +3875,20 @@ async function executePhase(item, phaseIndex, phases, spawnOptions, totalPhases
3855
3875
  `
3856
3876
  )
3857
3877
  );
3878
+ const resumeSessionId = spawnOptions?.resumeSessionId;
3879
+ const claudeSessionId = resumeSessionId ?? randomUUID();
3858
3880
  process.env.ASSIST_SESSION_ID ??= String(process.pid);
3859
3881
  emitActivity({
3860
3882
  kind: "backlog",
3861
3883
  itemId: item.id,
3862
3884
  itemName: item.name,
3863
3885
  phase: phaseNumber,
3864
- totalPhases
3886
+ totalPhases,
3887
+ claudeSessionId
3865
3888
  });
3866
3889
  const { child, done: done2 } = spawnClaude(
3867
- buildPhasePrompt(item, phaseNumber, phase),
3868
- spawnOptions
3890
+ resumeSessionId ? buildResumePrompt(phaseNumber, totalPhases) : buildPhasePrompt(item, phaseNumber, phase),
3891
+ resumeSessionId ? spawnOptions : { ...spawnOptions, sessionId: claudeSessionId }
3869
3892
  );
3870
3893
  watchForMarker(child);
3871
3894
  await done2;
@@ -3931,6 +3954,14 @@ async function runReview(item, fallbackPlan, spawnOptions) {
3931
3954
  return { kind: "done" };
3932
3955
  }
3933
3956
 
3957
+ // src/commands/backlog/runOnce.ts
3958
+ async function runOnce(item, startPhase, plan2, spawnOptions) {
3959
+ const reviewOptions = startPhase >= plan2.length ? spawnOptions : withoutResumeSession(spawnOptions);
3960
+ if (!await runPhases(item, startPhase, plan2, spawnOptions))
3961
+ return { kind: "fail" };
3962
+ return runReview(item, plan2, reviewOptions);
3963
+ }
3964
+
3934
3965
  // src/commands/backlog/run.ts
3935
3966
  async function run2(id, spawnOptions) {
3936
3967
  if (blockedByHandover()) return false;
@@ -3946,10 +3977,9 @@ async function runPrepared(id, prepared, spawnOptions) {
3946
3977
  acquireLock(item.id);
3947
3978
  try {
3948
3979
  while (true) {
3949
- if (!await runPhases(item, startPhase, plan2, spawnOptions))
3950
- return false;
3980
+ const review2 = await runOnce(item, startPhase, plan2, spawnOptions);
3951
3981
  spawnOptions = withoutResumeSession(spawnOptions);
3952
- const review2 = await runReview(item, plan2, spawnOptions);
3982
+ if (review2.kind === "fail") return false;
3953
3983
  if (review2.kind === "abort") return false;
3954
3984
  if (review2.kind === "rewind") {
3955
3985
  startPhase = review2.targetPhase;
@@ -3965,14 +3995,15 @@ async function runPrepared(id, prepared, spawnOptions) {
3965
3995
  }
3966
3996
  function logProgress(id, { plan: plan2, startPhase, item }) {
3967
3997
  console.log(chalk35.bold(`Running plan for #${id}: ${item.name}`));
3998
+ const totalPhases = plan2.length + 1;
3968
3999
  if (startPhase > 0) {
3969
4000
  const phaseNumber = startPhase + 1;
3970
4001
  console.log(
3971
- chalk35.dim(`Resuming from phase ${phaseNumber}/${plan2.length}
4002
+ chalk35.dim(`Resuming from phase ${phaseNumber}/${totalPhases}
3972
4003
  `)
3973
4004
  );
3974
4005
  } else {
3975
- console.log(chalk35.dim(`${plan2.length} phase(s)
4006
+ console.log(chalk35.dim(`${totalPhases} phase(s)
3976
4007
  `));
3977
4008
  }
3978
4009
  }
@@ -6003,7 +6034,7 @@ function registerRunCommand(cmd) {
6003
6034
  "Resume an interrupted Claude session for the current phase (used by the sessions daemon on restart)"
6004
6035
  ).action(
6005
6036
  async (id, opts) => {
6006
- pullIfConfigured();
6037
+ if (!opts.resumeSession) pullIfConfigured();
6007
6038
  await run2(id, {
6008
6039
  allowEdits: opts.write !== false,
6009
6040
  resumeSessionId: opts.resumeSession
@@ -9406,7 +9437,7 @@ import { spawnSync as spawnSync2 } from "child_process";
9406
9437
  import { unlinkSync as unlinkSync7, writeFileSync as writeFileSync19 } from "fs";
9407
9438
  import { tmpdir as tmpdir4 } from "os";
9408
9439
  import { join as join28 } from "path";
9409
- function buildArgs(queryFile, vars) {
9440
+ function buildArgs2(queryFile, vars) {
9410
9441
  const args = ["api", "graphql", "-F", `query=@${queryFile}`];
9411
9442
  for (const [key, value] of Object.entries(vars)) {
9412
9443
  const flag = typeof value === "number" ? "-F" : "-f";
@@ -9418,7 +9449,7 @@ function runGhGraphql(mutation, vars) {
9418
9449
  const queryFile = join28(tmpdir4(), `gh-query-${Date.now()}.graphql`);
9419
9450
  writeFileSync19(queryFile, mutation);
9420
9451
  try {
9421
- const result = spawnSync2("gh", buildArgs(queryFile, vars), {
9452
+ const result = spawnSync2("gh", buildArgs2(queryFile, vars), {
9422
9453
  encoding: "utf-8"
9423
9454
  });
9424
9455
  if (result.status !== 0) throw new Error(result.stderr || result.stdout);
@@ -17591,9 +17622,9 @@ function createAssistSession(id, assistArgs, cwd) {
17591
17622
 
17592
17623
  // src/commands/sessions/daemon/spawnClaude.ts
17593
17624
  function spawnClaude2(opts = {}) {
17594
- return spawnPty(buildArgs2(opts), opts.cwd);
17625
+ return spawnPty(buildArgs3(opts), opts.cwd);
17595
17626
  }
17596
- function buildArgs2(opts) {
17627
+ function buildArgs3(opts) {
17597
17628
  if (opts.resumeSessionId) return ["claude", "--resume", opts.resumeSessionId];
17598
17629
  if (opts.prompt) return ["claude", opts.prompt];
17599
17630
  return ["claude"];
@@ -17789,6 +17820,8 @@ function watchActivity(session, notify2) {
17789
17820
  const activity2 = readActivity(path53);
17790
17821
  if (!activity2) return;
17791
17822
  session.activity = activity2;
17823
+ if (activity2.claudeSessionId)
17824
+ session.claudeSessionId = activity2.claudeSessionId;
17792
17825
  notify2();
17793
17826
  };
17794
17827
  session.activityWatcher = watch(dir, (_event, filename) => {
@@ -17801,7 +17834,10 @@ function watchActivity(session, notify2) {
17801
17834
  function refreshActivity(session) {
17802
17835
  if (session.commandType !== "assist" || !session.cwd) return;
17803
17836
  const activity2 = readActivity(activityPath(session.id));
17804
- if (activity2) session.activity = activity2;
17837
+ if (!activity2) return;
17838
+ session.activity = activity2;
17839
+ if (activity2.claudeSessionId)
17840
+ session.claudeSessionId = activity2.claudeSessionId;
17805
17841
  }
17806
17842
 
17807
17843
  // src/commands/sessions/daemon/wirePtyEvents.ts
@@ -17909,6 +17945,7 @@ function sleep(ms) {
17909
17945
  // src/commands/sessions/daemon/watchForClaudeSessionId.ts
17910
17946
  function watchForClaudeSessionId(session, sessions, onDiscovered) {
17911
17947
  if (session.commandType === "run" || !session.pty) return;
17948
+ if (isBacklogRun2(session)) return;
17912
17949
  void watchClaudeSessionId({
17913
17950
  cwd: session.cwd ?? process.cwd(),
17914
17951
  sinceMs: session.startedAt,
@@ -17924,6 +17961,9 @@ function watchForClaudeSessionId(session, sessions, onDiscovered) {
17924
17961
  }
17925
17962
  });
17926
17963
  }
17964
+ function isBacklogRun2(session) {
17965
+ return session.commandType === "assist" && session.assistArgs?.[0] === "backlog" && session.assistArgs?.[1] === "run";
17966
+ }
17927
17967
 
17928
17968
  // src/commands/sessions/daemon/writeToSession.ts
17929
17969
  function writeToSession(sessions, id, data) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@staff0rd/assist",
3
- "version": "0.264.2",
3
+ "version": "0.265.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "bin": {