@staff0rd/assist 0.327.0 → 0.327.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.
Files changed (3) hide show
  1. package/README.md +4 -4
  2. package/dist/index.js +96 -46
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -279,12 +279,12 @@ From WSL, the selector can also surface and drive Windows-host repos (requires `
279
279
  - `sessions.windowsDaemonHost` / `sessions.windowsDaemonPort` — where the WSL daemon reaches the native Windows daemon (defaults `127.0.0.1` / `51764`; set the host to the Windows IP on WSL2 NAT-mode networking).
280
280
  - `sessions.windowsVersionCheck` — how the WSL↔Windows daemon handshake reacts to a protocol-version mismatch: `block` (default) refuses creates and auto-heals the host, `warn` logs and proceeds anyway, `off` skips the check. Use `warn`/`off` to keep working across an unfixable version gap.
281
281
 
282
- When iterating on assist itself: web server changes only need the `assist sessions` process restarted — sessions survive. Daemon/session-core changes need `assist daemon restart` to load the new code; this kills the PTYs, then claude sessions — including assist sessions that wrap claude, like `assist draft` — are auto-respawned via `claude --resume` with scrollback starting fresh, while run sessions (and assist sessions whose claude sessionId was never discovered) reappear as not-restored tiles that can be retried.
282
+ When iterating on assist itself: web server changes only need the `assist sessions` process restarted — sessions survive. Daemon/session-core changes need `assist daemon restart` to load the new code; this kills the PTYs, then claude sessions — including assist sessions that wrap claude, like `assist draft` — are auto-respawned via `claude --resume` with scrollback starting fresh, while run sessions (and assist sessions whose claude sessionId was never discovered) reappear as not-restored tiles that can be retried. A `--once` draft/bug/refine session is respawned through its assist wrapper instead of bare `claude --resume`, so its `assist signal done` watcher is re-established and the card still auto-closes.
283
283
 
284
284
  - `assist next [id] [--once]` - Alias for `backlog next [id]`; `--once` exits after the first completed item run instead of prompting for another
285
- - `assist draft [description] [--once]` (alias: `feat`) - Launch Claude in `/draft` mode, chain into next on `/next` signal; an optional `description` is forwarded as `/draft <description>`; `--once` exits when the done signal arrives after the initial draft completes
286
- - `assist bug [description] [--once]` - Launch Claude in `/bug` mode, chain into next on `/next` signal; an optional `description` is forwarded as `/bug <description>`; `--once` exits when the done signal arrives after the initial bug report completes
287
- - `assist refine [id] [--once]` - Launch Claude in `/refine` mode to refine a backlog item; prompts for selection when no id given; `--once` exits when the done signal arrives after refinement completes
285
+ - `assist draft [description] [--once]` (alias: `feat`) - Launch Claude in `/draft` mode, chain into next on `/next` signal; an optional `description` is forwarded as `/draft <description>`; `--once` exits when the done signal arrives after the initial draft completes; `--resume-session <id>` resumes an interrupted Claude session (used by the sessions daemon when it restarts a running item)
286
+ - `assist bug [description] [--once]` - Launch Claude in `/bug` mode, chain into next on `/next` signal; an optional `description` is forwarded as `/bug <description>`; `--once` exits when the done signal arrives after the initial bug report completes; `--resume-session <id>` resumes an interrupted Claude session (used by the sessions daemon when it restarts a running item)
287
+ - `assist refine [id] [--once]` - Launch Claude in `/refine` mode to refine a backlog item; prompts for selection when no id given; `--once` exits when the done signal arrives after refinement completes; `--resume-session <id>` resumes an interrupted Claude session (used by the sessions daemon when it restarts a running item)
288
288
  - `assist review-comments [number]` - Launch Claude in `/review-comments` mode to process PR review comments (single session, no chaining); when a PR number is supplied, checks out that PR via `gh pr checkout` first
289
289
  - `assist signal next [id]` - Write a next signal to chain into `assist next`; when `id` is supplied, the parent launcher runs that backlog item directly
290
290
  - `assist signal done [id]` - Write a done signal marking the session's initial task complete; an optional `id` surfaces the backlog item the session created onto its session card; `--once` launch sessions exit when it arrives, plain sessions ignore it
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.327.0",
9
+ version: "0.327.1",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -7572,9 +7572,10 @@ function buildSlashCommand(slashCommand, description) {
7572
7572
  return trimmed ? `/${slashCommand} ${trimmed}` : `/${slashCommand}`;
7573
7573
  }
7574
7574
  async function launchMode(slashCommand, options2) {
7575
- pullIfConfigured();
7575
+ const resumeSessionId = options2?.resumeSessionId;
7576
+ if (!resumeSessionId) pullIfConfigured();
7576
7577
  process.env.ASSIST_SESSION_ID ??= String(process.pid);
7577
- const claudeSessionId = randomUUID2();
7578
+ const claudeSessionId = resumeSessionId ?? randomUUID2();
7578
7579
  emitActivity({
7579
7580
  kind: "command",
7580
7581
  name: slashCommand,
@@ -7583,8 +7584,8 @@ async function launchMode(slashCommand, options2) {
7583
7584
  claudeSessionId
7584
7585
  });
7585
7586
  const { child, done: done2 } = spawnClaude(
7586
- buildSlashCommand(slashCommand, options2?.description),
7587
- { allowEdits: true, sessionId: claudeSessionId }
7587
+ resumeSessionId ? buildResumePrompt() : buildSlashCommand(slashCommand, options2?.description),
7588
+ { allowEdits: true, sessionId: claudeSessionId, resumeSessionId }
7588
7589
  );
7589
7590
  watchForMarker(child, { actOnDone: options2?.once });
7590
7591
  const launched = await awaitClaude(done2, `/${slashCommand}`);
@@ -12243,23 +12244,51 @@ async function reviewComments(number) {
12243
12244
  }
12244
12245
 
12245
12246
  // src/commands/registerLaunch.ts
12246
- function registerLaunch(program2) {
12247
+ var RESUME_SESSION_FLAG = "Resume an interrupted Claude session (used by the sessions daemon on restart)";
12248
+ function registerNext(program2) {
12247
12249
  program2.command("next").argument("[id]", "Backlog item ID to run first").description("Alias for backlog next").option("--once", "Exit after the first completed item run").action(
12248
12250
  (id2, opts) => next({ allowEdits: true, once: opts.once }, id2)
12249
12251
  );
12250
- program2.command("draft").alias("feat").argument("[description]", "Text to forward to the /draft slash command").description(
12251
- "Launch Claude in /draft mode, chain into next on /next signal"
12252
- ).option("--once", "Exit when the initial task completes").action(
12253
- (description, opts) => launchMode("draft", { once: opts.once, description })
12254
- );
12255
- program2.command("bug").argument("[description]", "Text to forward to the /bug slash command").description("Launch Claude in /bug mode, chain into next on /next signal").option("--once", "Exit when the initial task completes").action(
12256
- (description, opts) => launchMode("bug", { once: opts.once, description })
12252
+ }
12253
+ function registerDescriptionLaunch(program2, name, slashCommand, description, alias) {
12254
+ const command = program2.command(name).argument(
12255
+ "[description]",
12256
+ `Text to forward to the /${slashCommand} slash command`
12257
+ ).description(description).option("--once", "Exit when the initial task completes").option("--resume-session <id>", RESUME_SESSION_FLAG).action(
12258
+ (text6, opts) => launchMode(slashCommand, {
12259
+ once: opts.once,
12260
+ description: text6,
12261
+ resumeSessionId: opts.resumeSession
12262
+ })
12257
12263
  );
12264
+ if (alias) command.alias(alias);
12265
+ }
12266
+ function registerReviewComments(program2) {
12258
12267
  program2.command("review-comments").argument("[number]", "PR number to check out first").description("Launch Claude in /review-comments mode (single session)").action((number) => reviewComments(number));
12259
- program2.command("refine").argument("[id]", "Backlog item ID").description("Launch Claude in /refine mode to refine a backlog item").option("--once", "Exit when the initial task completes").action(
12260
- (id2, opts) => refine(id2, { once: opts.once })
12268
+ }
12269
+ function registerRefine(program2) {
12270
+ program2.command("refine").argument("[id]", "Backlog item ID").description("Launch Claude in /refine mode to refine a backlog item").option("--once", "Exit when the initial task completes").option("--resume-session <id>", RESUME_SESSION_FLAG).action(
12271
+ (id2, opts) => refine(id2, { once: opts.once, resumeSessionId: opts.resumeSession })
12261
12272
  );
12262
12273
  }
12274
+ function registerLaunch(program2) {
12275
+ registerNext(program2);
12276
+ registerDescriptionLaunch(
12277
+ program2,
12278
+ "draft",
12279
+ "draft",
12280
+ "Launch Claude in /draft mode, chain into next on /next signal",
12281
+ "feat"
12282
+ );
12283
+ registerDescriptionLaunch(
12284
+ program2,
12285
+ "bug",
12286
+ "bug",
12287
+ "Launch Claude in /bug mode, chain into next on /next signal"
12288
+ );
12289
+ registerReviewComments(program2);
12290
+ registerRefine(program2);
12291
+ }
12263
12292
 
12264
12293
  // src/commands/registerList.ts
12265
12294
  function registerList(program2) {
@@ -20883,8 +20912,8 @@ function errorSession(id2, persisted, error) {
20883
20912
  };
20884
20913
  }
20885
20914
 
20886
- // src/commands/sessions/daemon/backlogRunArgs.ts
20887
- function backlogRunArgs(persisted) {
20915
+ // src/commands/sessions/daemon/assistResumeArgs.ts
20916
+ function assistResumeArgs(persisted) {
20888
20917
  const args = ["assist", ...persisted.assistArgs];
20889
20918
  return persisted.claudeSessionId ? [...args, "--resume-session", persisted.claudeSessionId] : args;
20890
20919
  }
@@ -20905,6 +20934,46 @@ function runningSession(base, persisted, pty2) {
20905
20934
  };
20906
20935
  }
20907
20936
 
20937
+ // src/commands/sessions/daemon/restoreInteractiveSession.ts
20938
+ function restoreInteractiveSession(id2, persisted, base) {
20939
+ if (persisted.commandType !== "run" && persisted.claudeSessionId) {
20940
+ return resumeViaClaude(id2, persisted, base);
20941
+ }
20942
+ if (persisted.commandType === "claude") {
20943
+ return unrecoverableClaude(id2, persisted);
20944
+ }
20945
+ return notRestoredStub(base, persisted);
20946
+ }
20947
+ function resumeViaClaude(id2, persisted, base) {
20948
+ const pty2 = spawnClaude2({
20949
+ resumeSessionId: persisted.claudeSessionId,
20950
+ prompt: buildResumePrompt(),
20951
+ cwd: persisted.cwd,
20952
+ sessionId: id2
20953
+ });
20954
+ return runningSession(base, persisted, pty2);
20955
+ }
20956
+ function unrecoverableClaude(id2, persisted) {
20957
+ return errorSession(
20958
+ id2,
20959
+ persisted,
20960
+ "no claude session id was recorded before the daemon stopped, so the conversation cannot be resumed"
20961
+ );
20962
+ }
20963
+ function notRestoredStub(base, persisted) {
20964
+ return {
20965
+ ...base,
20966
+ status: "done",
20967
+ startedAt: persisted.startedAt,
20968
+ runningMs: persisted.runningMs ?? 0,
20969
+ runningSince: null,
20970
+ pty: null,
20971
+ runName: persisted.runName,
20972
+ runArgs: persisted.runArgs,
20973
+ restored: false
20974
+ };
20975
+ }
20976
+
20908
20977
  // src/commands/sessions/daemon/updatedSession.ts
20909
20978
  function updatedSession(id2, persisted) {
20910
20979
  return {
@@ -20924,41 +20993,22 @@ function isUpdate(persisted) {
20924
20993
  function restoreSession(id2, persisted) {
20925
20994
  const base = restoreBase(id2, persisted);
20926
20995
  if (isUpdate(persisted)) return updatedSession(id2, persisted);
20927
- if (isBacklogRun(persisted)) {
20928
- const pty2 = spawnPty(backlogRunArgs(persisted), persisted.cwd, id2);
20996
+ if (needsWrapperRelaunch(persisted)) {
20997
+ const pty2 = spawnPty(assistResumeArgs(persisted), persisted.cwd, id2);
20929
20998
  return runningSession(base, persisted, pty2);
20930
20999
  }
20931
- if (persisted.commandType !== "run" && persisted.claudeSessionId) {
20932
- const pty2 = spawnClaude2({
20933
- resumeSessionId: persisted.claudeSessionId,
20934
- prompt: buildResumePrompt(),
20935
- cwd: persisted.cwd,
20936
- sessionId: id2
20937
- });
20938
- return runningSession(base, persisted, pty2);
20939
- }
20940
- if (persisted.commandType === "claude") {
20941
- return errorSession(
20942
- id2,
20943
- persisted,
20944
- "no claude session id was recorded before the daemon stopped, so the conversation cannot be resumed"
20945
- );
20946
- }
20947
- return {
20948
- ...base,
20949
- status: "done",
20950
- startedAt: persisted.startedAt,
20951
- runningMs: persisted.runningMs ?? 0,
20952
- runningSince: null,
20953
- pty: null,
20954
- runName: persisted.runName,
20955
- runArgs: persisted.runArgs,
20956
- restored: false
20957
- };
21000
+ return restoreInteractiveSession(id2, persisted, base);
21001
+ }
21002
+ function needsWrapperRelaunch(persisted) {
21003
+ return isBacklogRun(persisted) || isOnceLaunch(persisted) && !!persisted.claudeSessionId;
20958
21004
  }
20959
21005
  function isBacklogRun(persisted) {
20960
21006
  return persisted.commandType === "assist" && persisted.assistArgs?.[0] === "backlog" && persisted.assistArgs?.[1] === "run";
20961
21007
  }
21008
+ var LAUNCH_COMMANDS = ["draft", "feat", "bug", "refine"];
21009
+ function isOnceLaunch(persisted) {
21010
+ return persisted.commandType === "assist" && !!persisted.assistArgs && LAUNCH_COMMANDS.includes(persisted.assistArgs[0]) && persisted.assistArgs.includes("--once");
21011
+ }
20962
21012
 
20963
21013
  // src/commands/sessions/daemon/restoreOne.ts
20964
21014
  function restoreOne(persisted, spawn12, sessions) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@staff0rd/assist",
3
- "version": "0.327.0",
3
+ "version": "0.327.1",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "bin": {