@staff0rd/assist 0.260.0 → 0.261.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.260.0",
9
+ version: "0.261.0",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -5648,6 +5648,21 @@ import enquirer7 from "enquirer";
5648
5648
  // src/commands/backlog/launchMode.ts
5649
5649
  import chalk61 from "chalk";
5650
5650
 
5651
+ // src/commands/backlog/surfaceCreatedItem.ts
5652
+ async function surfaceCreatedItem(slashCommand, id) {
5653
+ const numericId = Number.parseInt(id, 10);
5654
+ if (Number.isNaN(numericId)) return;
5655
+ const { orm } = await getReady();
5656
+ const item = await loadItem(orm, numericId);
5657
+ if (!item) return;
5658
+ emitActivity({
5659
+ kind: "command",
5660
+ name: slashCommand,
5661
+ itemId: numericId,
5662
+ itemName: item.name
5663
+ });
5664
+ }
5665
+
5651
5666
  // src/commands/backlog/tryRunById.ts
5652
5667
  import chalk60 from "chalk";
5653
5668
  async function tryRunById(id, options2) {
@@ -5698,6 +5713,9 @@ async function launchMode(slashCommand, options2) {
5698
5713
  stopWatching();
5699
5714
  const signal = readSignal();
5700
5715
  cleanupSignal();
5716
+ if (signal?.event === "done" && typeof signal.id === "string" && signal.id) {
5717
+ await surfaceCreatedItem(slashCommand, signal.id);
5718
+ }
5701
5719
  if (signal?.event === "next") {
5702
5720
  if (typeof signal.id === "string" && signal.id) {
5703
5721
  if (await tryRunById(signal.id, { allowEdits: true })) return;
@@ -14918,8 +14936,8 @@ function registerSignal(program2) {
14918
14936
  writeSignal("next", id ? { id } : void 0);
14919
14937
  console.log("Signal written.");
14920
14938
  });
14921
- signalCommand.command("done").description("Write a done signal to end a --once launch session").action(() => {
14922
- writeSignal("done");
14939
+ signalCommand.command("done").argument("[id]", "Backlog item ID created by the session").description("Write a done signal to end a --once launch session").action((id) => {
14940
+ writeSignal("done", id ? { id } : void 0);
14923
14941
  console.log("Signal written.");
14924
14942
  });
14925
14943
  }
@@ -17223,19 +17241,6 @@ async function discoverSessions() {
17223
17241
  return sessions;
17224
17242
  }
17225
17243
 
17226
- // src/commands/sessions/daemon/shouldAutoDismiss.ts
17227
- function shouldAutoDismiss(session, exitCode) {
17228
- const args = session.assistArgs;
17229
- return session.status === "done" && exitCode === 0 && args !== void 0 && args.includes("--once") && args[0] !== "next";
17230
- }
17231
-
17232
- // src/commands/sessions/daemon/applyStatusChange.ts
17233
- function applyStatusChange(session, status2, exitCode, dismiss, notify2) {
17234
- session.status = status2;
17235
- if (shouldAutoDismiss(session, exitCode)) dismiss(session.id);
17236
- else notify2();
17237
- }
17238
-
17239
17244
  // src/commands/sessions/daemon/broadcast.ts
17240
17245
  function sendTo(client, msg) {
17241
17246
  client.send(JSON.stringify(msg));
@@ -17247,6 +17252,88 @@ function broadcast(clients, msg) {
17247
17252
  }
17248
17253
  }
17249
17254
 
17255
+ // src/commands/sessions/daemon/loadPersistedSessions.ts
17256
+ import { z as z4 } from "zod";
17257
+ var SESSIONS_FILE = "sessions.json";
17258
+ var persistedSessionSchema = z4.object({
17259
+ name: z4.string(),
17260
+ commandType: z4.enum(["claude", "run", "assist"]),
17261
+ cwd: z4.string(),
17262
+ startedAt: z4.number(),
17263
+ claudeSessionId: z4.string().optional(),
17264
+ runName: z4.string().optional(),
17265
+ runArgs: z4.array(z4.string()).optional(),
17266
+ assistArgs: z4.array(z4.string()).optional()
17267
+ });
17268
+ function loadPersistedSessions() {
17269
+ const data = loadJson(SESSIONS_FILE);
17270
+ if (!Array.isArray(data)) return [];
17271
+ return data.flatMap((entry) => {
17272
+ const parsed = persistedSessionSchema.safeParse(entry);
17273
+ return parsed.success ? [parsed.data] : [];
17274
+ });
17275
+ }
17276
+ function savePersistedSessions(sessions) {
17277
+ saveJson(SESSIONS_FILE, sessions);
17278
+ }
17279
+ function persistLiveSessions(sessions) {
17280
+ savePersistedSessions(
17281
+ [...sessions.values()].filter((s) => s.pty && s.status !== "done").map(toPersistedSession)
17282
+ );
17283
+ }
17284
+ function toPersistedSession(session) {
17285
+ return {
17286
+ name: session.name,
17287
+ commandType: session.commandType,
17288
+ cwd: session.cwd ?? process.cwd(),
17289
+ startedAt: session.startedAt,
17290
+ claudeSessionId: session.claudeSessionId,
17291
+ runName: session.runName,
17292
+ runArgs: session.runArgs,
17293
+ assistArgs: session.assistArgs
17294
+ };
17295
+ }
17296
+
17297
+ // src/commands/sessions/daemon/toSessionInfo.ts
17298
+ function toSessionInfo({
17299
+ id,
17300
+ name,
17301
+ commandType,
17302
+ status: status2,
17303
+ startedAt,
17304
+ runName,
17305
+ runArgs,
17306
+ assistArgs,
17307
+ cwd,
17308
+ restored,
17309
+ activity: activity2,
17310
+ autoRun
17311
+ }) {
17312
+ return {
17313
+ id,
17314
+ name,
17315
+ commandType,
17316
+ status: status2,
17317
+ startedAt,
17318
+ runName,
17319
+ runArgs,
17320
+ assistArgs,
17321
+ cwd,
17322
+ restored,
17323
+ activity: activity2,
17324
+ autoRun
17325
+ };
17326
+ }
17327
+
17328
+ // src/commands/sessions/daemon/broadcastSessions.ts
17329
+ function broadcastSessions(sessions, clients) {
17330
+ persistLiveSessions(sessions);
17331
+ broadcast(clients, {
17332
+ type: "sessions",
17333
+ sessions: [...sessions.values()].map(toSessionInfo)
17334
+ });
17335
+ }
17336
+
17250
17337
  // src/commands/sessions/daemon/spawnPty.ts
17251
17338
  import * as pty from "node-pty";
17252
17339
 
@@ -17372,46 +17459,34 @@ function greetClient(client, sessions, list4) {
17372
17459
  replayScrollback(sessions, client);
17373
17460
  }
17374
17461
 
17375
- // src/commands/sessions/daemon/loadPersistedSessions.ts
17376
- import { z as z4 } from "zod";
17377
- var SESSIONS_FILE = "sessions.json";
17378
- var persistedSessionSchema = z4.object({
17379
- name: z4.string(),
17380
- commandType: z4.enum(["claude", "run", "assist"]),
17381
- cwd: z4.string(),
17382
- startedAt: z4.number(),
17383
- claudeSessionId: z4.string().optional(),
17384
- runName: z4.string().optional(),
17385
- runArgs: z4.array(z4.string()).optional(),
17386
- assistArgs: z4.array(z4.string()).optional()
17387
- });
17388
- function loadPersistedSessions() {
17389
- const data = loadJson(SESSIONS_FILE);
17390
- if (!Array.isArray(data)) return [];
17391
- return data.flatMap((entry) => {
17392
- const parsed = persistedSessionSchema.safeParse(entry);
17393
- return parsed.success ? [parsed.data] : [];
17394
- });
17462
+ // src/commands/sessions/daemon/shouldAutoDismiss.ts
17463
+ function shouldAutoDismiss(session, exitCode) {
17464
+ const args = session.assistArgs;
17465
+ return session.status === "done" && exitCode === 0 && args !== void 0 && args.includes("--once") && args[0] !== "next";
17395
17466
  }
17396
- function savePersistedSessions(sessions) {
17397
- saveJson(SESSIONS_FILE, sessions);
17467
+
17468
+ // src/commands/sessions/daemon/shouldAutoRun.ts
17469
+ function shouldAutoRun(session, exitCode) {
17470
+ if (!session.autoRun) return false;
17471
+ if (session.status !== "done" || exitCode !== 0) return false;
17472
+ if (session.commandType !== "assist") return false;
17473
+ const cmd = session.assistArgs?.[0];
17474
+ if (cmd !== "draft" && cmd !== "bug") return false;
17475
+ return session.activity?.itemId != null;
17398
17476
  }
17399
- function persistLiveSessions(sessions) {
17400
- savePersistedSessions(
17401
- [...sessions.values()].filter((s) => s.pty && s.status !== "done").map(toPersistedSession)
17402
- );
17477
+
17478
+ // src/commands/sessions/daemon/applyStatusChange.ts
17479
+ function applyStatusChange(session, status2, exitCode, dismiss, notify2, spawnRun2) {
17480
+ session.status = status2;
17481
+ if (shouldAutoRun(session, exitCode) && session.activity?.itemId != null)
17482
+ spawnRun2(session.activity.itemId, session.cwd);
17483
+ if (shouldAutoDismiss(session, exitCode)) dismiss(session.id);
17484
+ else notify2();
17403
17485
  }
17404
- function toPersistedSession(session) {
17405
- return {
17406
- name: session.name,
17407
- commandType: session.commandType,
17408
- cwd: session.cwd ?? process.cwd(),
17409
- startedAt: session.startedAt,
17410
- claudeSessionId: session.claudeSessionId,
17411
- runName: session.runName,
17412
- runArgs: session.runArgs,
17413
- assistArgs: session.assistArgs
17414
- };
17486
+
17487
+ // src/commands/sessions/daemon/makeStatusChangeHandler.ts
17488
+ function makeStatusChangeHandler(dismiss, notify2, spawnRun2) {
17489
+ return (s, status2, exitCode) => applyStatusChange(s, status2, exitCode, dismiss, notify2, spawnRun2);
17415
17490
  }
17416
17491
 
17417
17492
  // src/commands/sessions/daemon/restoreSession.ts
@@ -17483,6 +17558,40 @@ function clearIdle(session) {
17483
17558
  if (session.idleTimer) clearTimeout(session.idleTimer);
17484
17559
  }
17485
17560
 
17561
+ // src/commands/sessions/daemon/watchActivity.ts
17562
+ import { existsSync as existsSync52, mkdirSync as mkdirSync20, watch } from "fs";
17563
+ import { dirname as dirname27 } from "path";
17564
+ var DEBOUNCE_MS = 50;
17565
+ function watchActivity(session, notify2) {
17566
+ if (session.commandType !== "assist" || !session.cwd) return;
17567
+ const path53 = activityPath(session.cwd, session.id);
17568
+ const dir = dirname27(path53);
17569
+ try {
17570
+ mkdirSync20(dir, { recursive: true });
17571
+ } catch {
17572
+ return;
17573
+ }
17574
+ let timer = null;
17575
+ const read = () => {
17576
+ timer = null;
17577
+ const activity2 = readActivity(path53);
17578
+ if (!activity2) return;
17579
+ session.activity = activity2;
17580
+ notify2();
17581
+ };
17582
+ session.activityWatcher = watch(dir, (_event, filename) => {
17583
+ if (filename && !path53.endsWith(filename)) return;
17584
+ if (timer) clearTimeout(timer);
17585
+ timer = setTimeout(read, DEBOUNCE_MS);
17586
+ });
17587
+ if (existsSync52(path53)) read();
17588
+ }
17589
+ function refreshActivity(session) {
17590
+ if (session.commandType !== "assist" || !session.cwd) return;
17591
+ const activity2 = readActivity(activityPath(session.cwd, session.id));
17592
+ if (activity2) session.activity = activity2;
17593
+ }
17594
+
17486
17595
  // src/commands/sessions/daemon/wirePtyEvents.ts
17487
17596
  var MAX_SCROLLBACK = 256 * 1024;
17488
17597
  var RESIZE_GRACE_MS = 500;
@@ -17505,6 +17614,7 @@ function wirePtyEvents(session, clients, onStatusChange) {
17505
17614
  });
17506
17615
  session.pty.onExit(({ exitCode }) => {
17507
17616
  clearIdle(session);
17617
+ refreshActivity(session);
17508
17618
  onStatusChange(session, "done", exitCode);
17509
17619
  });
17510
17620
  scheduleIdle(session, () => onStatusChange(session, "waiting"));
@@ -17542,64 +17652,6 @@ function shutdownSessions(sessions) {
17542
17652
  }
17543
17653
  }
17544
17654
 
17545
- // src/commands/sessions/daemon/toSessionInfo.ts
17546
- function toSessionInfo({
17547
- id,
17548
- name,
17549
- commandType,
17550
- status: status2,
17551
- startedAt,
17552
- runName,
17553
- runArgs,
17554
- assistArgs,
17555
- cwd,
17556
- restored,
17557
- activity: activity2
17558
- }) {
17559
- return {
17560
- id,
17561
- name,
17562
- commandType,
17563
- status: status2,
17564
- startedAt,
17565
- runName,
17566
- runArgs,
17567
- assistArgs,
17568
- cwd,
17569
- restored,
17570
- activity: activity2
17571
- };
17572
- }
17573
-
17574
- // src/commands/sessions/daemon/watchActivity.ts
17575
- import { existsSync as existsSync52, mkdirSync as mkdirSync20, watch } from "fs";
17576
- import { dirname as dirname27 } from "path";
17577
- var DEBOUNCE_MS = 50;
17578
- function watchActivity(session, notify2) {
17579
- if (session.commandType !== "assist" || !session.cwd) return;
17580
- const path53 = activityPath(session.cwd, session.id);
17581
- const dir = dirname27(path53);
17582
- try {
17583
- mkdirSync20(dir, { recursive: true });
17584
- } catch {
17585
- return;
17586
- }
17587
- let timer = null;
17588
- const read = () => {
17589
- timer = null;
17590
- const activity2 = readActivity(path53);
17591
- if (!activity2) return;
17592
- session.activity = activity2;
17593
- notify2();
17594
- };
17595
- session.activityWatcher = watch(dir, (_event, filename) => {
17596
- if (filename && !path53.endsWith(filename)) return;
17597
- if (timer) clearTimeout(timer);
17598
- timer = setTimeout(read, DEBOUNCE_MS);
17599
- });
17600
- if (existsSync52(path53)) read();
17601
- }
17602
-
17603
17655
  // src/commands/sessions/daemon/discoverClaudeSessionId.ts
17604
17656
  import * as fs26 from "fs";
17605
17657
  import * as path48 from "path";
@@ -17665,6 +17717,12 @@ function resizeSession(sessions, id, cols, rows) {
17665
17717
  s.pty?.resize(cols, rows);
17666
17718
  }
17667
17719
  }
17720
+ function setAutoRun(sessions, id, enabled) {
17721
+ const s = sessions.get(id);
17722
+ if (!s) return false;
17723
+ s.autoRun = enabled;
17724
+ return true;
17725
+ }
17668
17726
  function dismissSession(sessions, id) {
17669
17727
  const s = sessions.get(id);
17670
17728
  if (!s) return false;
@@ -17729,7 +17787,11 @@ var SessionManager = class {
17729
17787
  resume(sessionId, cwd, name) {
17730
17788
  return this.add(resumeSession(String(this.nextId++), sessionId, cwd, name));
17731
17789
  }
17732
- onStatusChange = (s, status2, exitCode) => applyStatusChange(s, status2, exitCode, this.dismissSession, this.notify);
17790
+ onStatusChange = makeStatusChangeHandler(
17791
+ (id) => this.dismissSession(id),
17792
+ () => this.notify(),
17793
+ (itemId, cwd) => this.spawnAssist(["backlog", "run", String(itemId)], cwd)
17794
+ );
17733
17795
  wire(session) {
17734
17796
  this.sessions.set(session.id, session);
17735
17797
  wirePtyEvents(session, this.clients, this.onStatusChange);
@@ -17748,6 +17810,9 @@ var SessionManager = class {
17748
17810
  dismissSession = (id) => {
17749
17811
  if (dismissSession(this.sessions, id)) this.notify();
17750
17812
  };
17813
+ setAutoRun(id, enabled) {
17814
+ if (setAutoRun(this.sessions, id, enabled)) this.notify();
17815
+ }
17751
17816
  listSessions() {
17752
17817
  return [...this.sessions.values()].map(toSessionInfo);
17753
17818
  }
@@ -17756,11 +17821,7 @@ var SessionManager = class {
17756
17821
  }
17757
17822
  notify = () => {
17758
17823
  if (this.shuttingDown) return;
17759
- persistLiveSessions(this.sessions);
17760
- broadcast(this.clients, {
17761
- type: "sessions",
17762
- sessions: this.listSessions()
17763
- });
17824
+ broadcastSessions(this.sessions, this.clients);
17764
17825
  this.onIdleChange?.(this.isIdle());
17765
17826
  };
17766
17827
  };
@@ -17835,7 +17896,8 @@ var handlers = {
17835
17896
  input: (_client, m, d) => m.writeToSession(d.sessionId, d.data),
17836
17897
  resize: (_client, m, d) => m.resizeSession(d.sessionId, d.cols, d.rows),
17837
17898
  retry: (_client, m, d) => m.retrySession(d.sessionId),
17838
- dismiss: (_client, m, d) => m.dismissSession(d.sessionId)
17899
+ dismiss: (_client, m, d) => m.dismissSession(d.sessionId),
17900
+ "set-autorun": (_client, m, d) => m.setAutoRun(d.sessionId, d.enabled)
17839
17901
  };
17840
17902
  function dispatchMessage(client, manager, data) {
17841
17903
  handlers[data.type]?.(client, manager, data);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@staff0rd/assist",
3
- "version": "0.260.0",
3
+ "version": "0.261.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "bin": {