@staff0rd/assist 0.318.4 → 0.318.5

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 (2) hide show
  1. package/dist/index.js +109 -119
  2. 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.318.4",
9
+ version: "0.318.5",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -3897,7 +3897,12 @@ var hooksSettings = {
3897
3897
  UserPromptSubmit: on(RUNNING),
3898
3898
  PreToolUse: on(RUNNING),
3899
3899
  Stop: on(WAITING),
3900
- Notification: on(WAITING)
3900
+ Notification: on(WAITING),
3901
+ /* why: a tool/plan approval prompt appears mid-turn, after PreToolUse has
3902
+ * already set running; PermissionRequest fires when the agent blocks on
3903
+ * that decision, so the card shows waiting rather than staying running while
3904
+ * it is genuinely awaiting the user (#449). */
3905
+ PermissionRequest: on(WAITING)
3901
3906
  }
3902
3907
  };
3903
3908
  function ensureHooksSettings() {
@@ -4604,51 +4609,43 @@ Failed to launch Claude for ${context}: ${message}`)
4604
4609
  }
4605
4610
  }
4606
4611
 
4607
- // src/shared/emitActivity.ts
4608
- import { mkdirSync as mkdirSync7, readFileSync as readFileSync14, rmSync, writeFileSync as writeFileSync17 } from "fs";
4609
- import { homedir as homedir7 } from "os";
4610
- import { dirname as dirname14, join as join18 } from "path";
4611
- import { z as z4 } from "zod";
4612
- var activitySchema = z4.object({
4613
- kind: z4.enum(["command", "backlog"]),
4614
- name: z4.string().optional(),
4615
- itemId: z4.number().optional(),
4616
- itemName: z4.string().optional(),
4617
- phase: z4.number().optional(),
4618
- phaseName: z4.string().optional(),
4619
- totalPhases: z4.number().optional(),
4620
- claudeSessionId: z4.string().optional(),
4621
- startedAt: z4.number()
4622
- });
4623
- function activityPath(sessionId) {
4624
- return join18(homedir7(), ".assist", "activity", `activity-${sessionId}.json`);
4625
- }
4626
- function emitActivity(activity2) {
4627
- const sessionId = process.env.ASSIST_ACTIVITY_ID;
4628
- if (!sessionId) return;
4629
- const path57 = activityPath(sessionId);
4630
- mkdirSync7(dirname14(path57), { recursive: true });
4631
- writeFileSync17(path57, JSON.stringify({ ...activity2, startedAt: Date.now() }));
4612
+ // src/commands/sessions/daemon/connectToDaemon.ts
4613
+ import * as net from "net";
4614
+ function connectToDaemon() {
4615
+ return new Promise((resolve17, reject) => {
4616
+ const socket = net.connect(daemonPaths.socket);
4617
+ socket.once("connect", () => resolve17(socket));
4618
+ socket.once("error", reject);
4619
+ });
4632
4620
  }
4633
- function readActivity(path57) {
4621
+ async function isDaemonRunning() {
4634
4622
  try {
4635
- return JSON.parse(readFileSync14(path57, "utf8"));
4623
+ (await connectToDaemon()).destroy();
4624
+ return true;
4636
4625
  } catch {
4637
- return void 0;
4626
+ return false;
4638
4627
  }
4639
4628
  }
4640
- function reconcileActivity(sessionId, activity2) {
4641
- if (!activity2) {
4642
- removeActivity(sessionId);
4643
- return;
4644
- }
4645
- const path57 = activityPath(sessionId);
4646
- mkdirSync7(dirname14(path57), { recursive: true });
4647
- writeFileSync17(path57, JSON.stringify(activity2));
4629
+
4630
+ // src/commands/sessions/daemon/sendToDaemon.ts
4631
+ async function sendToDaemon(message) {
4632
+ const socket = await connectToDaemon();
4633
+ const timer = setTimeout(() => socket.destroy(), 500);
4634
+ socket.on("error", () => {
4635
+ });
4636
+ socket.write(`${JSON.stringify(message)}
4637
+ `, () => {
4638
+ clearTimeout(timer);
4639
+ socket.end();
4640
+ });
4648
4641
  }
4649
- function removeActivity(sessionId) {
4642
+
4643
+ // src/commands/sessions/setSessionStatus.ts
4644
+ async function setSessionStatus(status2) {
4645
+ const sessionId = process.env.ASSIST_SESSION_ID;
4646
+ if (!sessionId) return;
4650
4647
  try {
4651
- rmSync(activityPath(sessionId));
4648
+ await sendToDaemon({ type: "set-status", sessionId, status: status2 });
4652
4649
  } catch {
4653
4650
  }
4654
4651
  }
@@ -4762,6 +4759,69 @@ function buildResumePrompt() {
4762
4759
  return "A restart interrupted this conversation. Continue from where you left off.";
4763
4760
  }
4764
4761
 
4762
+ // src/shared/emitActivity.ts
4763
+ import { mkdirSync as mkdirSync7, readFileSync as readFileSync14, rmSync, writeFileSync as writeFileSync17 } from "fs";
4764
+ import { homedir as homedir7 } from "os";
4765
+ import { dirname as dirname14, join as join18 } from "path";
4766
+ import { z as z4 } from "zod";
4767
+ var activitySchema = z4.object({
4768
+ kind: z4.enum(["command", "backlog"]),
4769
+ name: z4.string().optional(),
4770
+ itemId: z4.number().optional(),
4771
+ itemName: z4.string().optional(),
4772
+ phase: z4.number().optional(),
4773
+ phaseName: z4.string().optional(),
4774
+ totalPhases: z4.number().optional(),
4775
+ claudeSessionId: z4.string().optional(),
4776
+ startedAt: z4.number()
4777
+ });
4778
+ function activityPath(sessionId) {
4779
+ return join18(homedir7(), ".assist", "activity", `activity-${sessionId}.json`);
4780
+ }
4781
+ function emitActivity(activity2) {
4782
+ const sessionId = process.env.ASSIST_ACTIVITY_ID;
4783
+ if (!sessionId) return;
4784
+ const path57 = activityPath(sessionId);
4785
+ mkdirSync7(dirname14(path57), { recursive: true });
4786
+ writeFileSync17(path57, JSON.stringify({ ...activity2, startedAt: Date.now() }));
4787
+ }
4788
+ function readActivity(path57) {
4789
+ try {
4790
+ return JSON.parse(readFileSync14(path57, "utf8"));
4791
+ } catch {
4792
+ return void 0;
4793
+ }
4794
+ }
4795
+ function reconcileActivity(sessionId, activity2) {
4796
+ if (!activity2) {
4797
+ removeActivity(sessionId);
4798
+ return;
4799
+ }
4800
+ const path57 = activityPath(sessionId);
4801
+ mkdirSync7(dirname14(path57), { recursive: true });
4802
+ writeFileSync17(path57, JSON.stringify(activity2));
4803
+ }
4804
+ function removeActivity(sessionId) {
4805
+ try {
4806
+ rmSync(activityPath(sessionId));
4807
+ } catch {
4808
+ }
4809
+ }
4810
+
4811
+ // src/commands/backlog/reportPhaseActivity.ts
4812
+ function reportPhaseActivity(item, phaseNumber, totalPhases, phase, claudeSessionId) {
4813
+ const isReviewPhase = phaseNumber >= totalPhases;
4814
+ emitActivity({
4815
+ kind: "backlog",
4816
+ itemId: item.id,
4817
+ itemName: item.name,
4818
+ phase: phaseNumber,
4819
+ phaseName: isReviewPhase ? REVIEW_PHASE_NAME : phase.name,
4820
+ totalPhases,
4821
+ claudeSessionId
4822
+ });
4823
+ }
4824
+
4765
4825
  // src/commands/backlog/resolvePhaseResult.ts
4766
4826
  import { existsSync as existsSync22, unlinkSync as unlinkSync4 } from "fs";
4767
4827
  import chalk40 from "chalk";
@@ -4875,16 +4935,7 @@ async function executePhase(item, phaseIndex, phases, spawnOptions, totalPhases
4875
4935
  const resumeSessionId = spawnOptions?.resumeSessionId;
4876
4936
  const claudeSessionId = resumeSessionId ?? randomUUID();
4877
4937
  process.env.ASSIST_SESSION_ID ??= String(process.pid);
4878
- const isReviewPhase = phaseNumber >= totalPhases;
4879
- emitActivity({
4880
- kind: "backlog",
4881
- itemId: item.id,
4882
- itemName: item.name,
4883
- phase: phaseNumber,
4884
- phaseName: isReviewPhase ? REVIEW_PHASE_NAME : phase.name,
4885
- totalPhases,
4886
- claudeSessionId
4887
- });
4938
+ reportPhaseActivity(item, phaseNumber, totalPhases, phase, claudeSessionId);
4888
4939
  const { child, done: done2 } = spawnClaude(
4889
4940
  resumeSessionId ? buildResumePrompt() : buildPhasePrompt(item, phaseNumber, phase),
4890
4941
  resumeSessionId ? spawnOptions : { ...spawnOptions, sessionId: claudeSessionId }
@@ -4896,6 +4947,7 @@ async function executePhase(item, phaseIndex, phases, spawnOptions, totalPhases
4896
4947
  );
4897
4948
  stopWatching();
4898
4949
  if (!launched) return -1;
4950
+ void setSessionStatus("running");
4899
4951
  return await resolvePhaseResult(phaseIndex, item.id);
4900
4952
  }
4901
4953
 
@@ -5418,26 +5470,6 @@ import {
5418
5470
  unlinkSync as unlinkSync5,
5419
5471
  writeSync
5420
5472
  } from "fs";
5421
-
5422
- // src/commands/sessions/daemon/connectToDaemon.ts
5423
- import * as net from "net";
5424
- function connectToDaemon() {
5425
- return new Promise((resolve17, reject) => {
5426
- const socket = net.connect(daemonPaths.socket);
5427
- socket.once("connect", () => resolve17(socket));
5428
- socket.once("error", reject);
5429
- });
5430
- }
5431
- async function isDaemonRunning() {
5432
- try {
5433
- (await connectToDaemon()).destroy();
5434
- return true;
5435
- } catch {
5436
- return false;
5437
- }
5438
- }
5439
-
5440
- // src/commands/sessions/daemon/ensureDaemonRunning.ts
5441
5473
  var SPAWN_TIMEOUT_MS = 1e4;
5442
5474
  var RETRY_DELAY_MS = 200;
5443
5475
  var STALE_LOCK_MS = SPAWN_TIMEOUT_MS + 5e3;
@@ -20193,21 +20225,23 @@ function spawnRun(opts) {
20193
20225
  }
20194
20226
 
20195
20227
  // src/commands/sessions/daemon/createSession.ts
20196
- function runningBase(id2) {
20228
+ function sessionBase(id2, status2) {
20197
20229
  const startedAt = Date.now();
20198
20230
  return {
20199
20231
  id: id2,
20200
- status: "running",
20232
+ status: status2,
20201
20233
  startedAt,
20202
20234
  runningMs: 0,
20203
- runningSince: startedAt,
20235
+ /* why: runningMs counts only running stretches, so a session that starts
20236
+ * waiting (idle, awaiting first input) has no open stretch to stamp. */
20237
+ runningSince: status2 === "running" ? startedAt : null,
20204
20238
  scrollback: ""
20205
20239
  };
20206
20240
  }
20207
20241
  function createSession(id2, prompt, cwd) {
20208
20242
  const claudeSessionId = randomUUID4();
20209
20243
  return {
20210
- ...runningBase(id2),
20244
+ ...sessionBase(id2, prompt ? "running" : "waiting"),
20211
20245
  name: prompt?.slice(0, 40) || `Session ${id2}`,
20212
20246
  commandType: "claude",
20213
20247
  pty: spawnClaude2({ prompt, cwd, sessionId: id2, claudeSessionId }),
@@ -20217,7 +20251,7 @@ function createSession(id2, prompt, cwd) {
20217
20251
  }
20218
20252
  function createRunSession(id2, runName, runArgs, cwd) {
20219
20253
  return {
20220
- ...runningBase(id2),
20254
+ ...sessionBase(id2, "running"),
20221
20255
  name: `run: ${runName}`,
20222
20256
  commandType: "run",
20223
20257
  pty: spawnRun({ name: runName, args: runArgs, cwd }),
@@ -20536,26 +20570,6 @@ function refreshActivity(session) {
20536
20570
  session.claudeSessionId = activity2.claudeSessionId;
20537
20571
  }
20538
20572
 
20539
- // src/commands/sessions/daemon/noteOutputForThinking.ts
20540
- var ACTIVATE_MS = 500;
20541
- var GAP_MS = 1e3;
20542
- function noteOutputForThinking(session, onStatusChange) {
20543
- if (session.status !== "waiting") {
20544
- session.thinkingStreakStart = void 0;
20545
- session.thinkingLastOutput = void 0;
20546
- return;
20547
- }
20548
- const now = Date.now();
20549
- const stale = session.thinkingStreakStart == null || session.thinkingLastOutput == null || now - session.thinkingLastOutput > GAP_MS;
20550
- if (stale) session.thinkingStreakStart = now;
20551
- session.thinkingLastOutput = now;
20552
- if (now - (session.thinkingStreakStart ?? now) < ACTIVATE_MS) return;
20553
- session.thinkingStreakStart = void 0;
20554
- session.thinkingLastOutput = void 0;
20555
- daemonLog(`session ${session.id} sustained output while waiting -> running`);
20556
- onStatusChange(session, "running");
20557
- }
20558
-
20559
20573
  // src/commands/sessions/daemon/wirePtyEvents.ts
20560
20574
  var MAX_SCROLLBACK = 256 * 1024;
20561
20575
  function appendScrollback(session, data) {
@@ -20569,7 +20583,6 @@ function wirePtyEvents(session, clients, onStatusChange) {
20569
20583
  session.pty.onData((data) => {
20570
20584
  appendScrollback(session, data);
20571
20585
  noteOutputForEscInterrupt(session, onStatusChange);
20572
- noteOutputForThinking(session, onStatusChange);
20573
20586
  broadcast(clients, { type: "output", sessionId: session.id, data });
20574
20587
  });
20575
20588
  session.pty.onExit(({ exitCode }) => {
@@ -21832,29 +21845,6 @@ function registerDaemon(program2) {
21832
21845
  ).action(restartDaemon);
21833
21846
  }
21834
21847
 
21835
- // src/commands/sessions/daemon/sendToDaemon.ts
21836
- async function sendToDaemon(message) {
21837
- const socket = await connectToDaemon();
21838
- const timer = setTimeout(() => socket.destroy(), 500);
21839
- socket.on("error", () => {
21840
- });
21841
- socket.write(`${JSON.stringify(message)}
21842
- `, () => {
21843
- clearTimeout(timer);
21844
- socket.end();
21845
- });
21846
- }
21847
-
21848
- // src/commands/sessions/setSessionStatus.ts
21849
- async function setSessionStatus(status2) {
21850
- const sessionId = process.env.ASSIST_SESSION_ID;
21851
- if (!sessionId) return;
21852
- try {
21853
- await sendToDaemon({ type: "set-status", sessionId, status: status2 });
21854
- } catch {
21855
- }
21856
- }
21857
-
21858
21848
  // src/commands/sessions/summarise/index.ts
21859
21849
  import * as fs34 from "fs";
21860
21850
  import chalk175 from "chalk";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@staff0rd/assist",
3
- "version": "0.318.4",
3
+ "version": "0.318.5",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "bin": {