@staff0rd/assist 0.525.0 → 0.527.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.525.0",
9
+ version: "0.527.0",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -4966,6 +4966,65 @@ Total: ${folders.length} venv folder(s)`);
4966
4966
  }
4967
4967
  }
4968
4968
 
4969
+ // src/commands/sessions/daemon/connectToDaemon.ts
4970
+ import * as net from "net";
4971
+
4972
+ // src/commands/sessions/daemon/daemonPaths.ts
4973
+ import { homedir as homedir2 } from "os";
4974
+ import { join as join10 } from "path";
4975
+ var DAEMON_DIR = join10(homedir2(), ".assist", "daemon");
4976
+ var daemonPaths = {
4977
+ dir: DAEMON_DIR,
4978
+ socket: process.platform === "win32" ? String.raw`\\.\pipe\assist-sessions-daemon` : join10(DAEMON_DIR, "daemon.sock"),
4979
+ log: join10(DAEMON_DIR, "daemon.log"),
4980
+ pid: join10(DAEMON_DIR, "daemon.pid"),
4981
+ spawnLock: join10(DAEMON_DIR, "spawn.lock"),
4982
+ hooksSettings: join10(DAEMON_DIR, "hooks-settings.json")
4983
+ };
4984
+
4985
+ // src/commands/sessions/daemon/connectToDaemon.ts
4986
+ function connectToDaemon() {
4987
+ return new Promise((resolve23, reject) => {
4988
+ const socket = net.connect(daemonPaths.socket);
4989
+ socket.once("connect", () => resolve23(socket));
4990
+ socket.once("error", reject);
4991
+ });
4992
+ }
4993
+ async function isDaemonRunning() {
4994
+ try {
4995
+ (await connectToDaemon()).destroy();
4996
+ return true;
4997
+ } catch {
4998
+ return false;
4999
+ }
5000
+ }
5001
+
5002
+ // src/commands/sessions/signalVerifying.ts
5003
+ function signalVerifying() {
5004
+ const sessionId = process.env.ASSIST_SESSION_ID;
5005
+ if (!sessionId) return () => {
5006
+ };
5007
+ let socket;
5008
+ let released = false;
5009
+ connectToDaemon().then((connected) => {
5010
+ if (released) return connected.destroy();
5011
+ socket = connected;
5012
+ connected.on("error", () => {
5013
+ });
5014
+ connected.unref();
5015
+ connected.write(
5016
+ `${JSON.stringify({ type: "verify-started", sessionId })}
5017
+ `
5018
+ );
5019
+ }, ignoreUnreachableDaemon);
5020
+ return () => {
5021
+ released = true;
5022
+ socket?.destroy();
5023
+ };
5024
+ }
5025
+ function ignoreUnreachableDaemon() {
5026
+ }
5027
+
4969
5028
  // src/commands/verify/run/filterByChangedFiles.ts
4970
5029
  import { minimatch as minimatch4 } from "minimatch";
4971
5030
 
@@ -5031,9 +5090,9 @@ function printMeasureTable(records, totalMs) {
5031
5090
  import { spawn } from "child_process";
5032
5091
 
5033
5092
  // src/shared/expandEnv.ts
5034
- import { homedir as homedir2 } from "os";
5093
+ import { homedir as homedir3 } from "os";
5035
5094
  function expandTilde(value) {
5036
- return value.startsWith("~/") ? homedir2() + value.slice(1) : value;
5095
+ return value.startsWith("~/") ? homedir3() + value.slice(1) : value;
5037
5096
  }
5038
5097
  function expandEnv(env) {
5039
5098
  return Object.fromEntries(
@@ -5136,11 +5195,16 @@ async function run(options2 = {}) {
5136
5195
  return;
5137
5196
  }
5138
5197
  printEntryList(entries);
5139
- const { results, totalMs } = await runAllEntries(entries);
5140
- if (options2.measure) {
5141
- printMeasureTable(results, totalMs);
5198
+ const releaseVerifying = signalVerifying();
5199
+ try {
5200
+ const { results, totalMs } = await runAllEntries(entries);
5201
+ if (options2.measure) {
5202
+ printMeasureTable(results, totalMs);
5203
+ }
5204
+ handleResults(results, entries.length);
5205
+ } finally {
5206
+ releaseVerifying();
5142
5207
  }
5143
- handleResults(results, entries.length);
5144
5208
  }
5145
5209
 
5146
5210
  // src/commands/new/registerNew/initGit.ts
@@ -5247,7 +5311,7 @@ import enquirer3 from "enquirer";
5247
5311
 
5248
5312
  // src/commands/deploy/init/updateWorkflow.ts
5249
5313
  import { existsSync as existsSync16, mkdirSync as mkdirSync3, readFileSync as readFileSync12, writeFileSync as writeFileSync12 } from "fs";
5250
- import { dirname as dirname12, join as join10 } from "path";
5314
+ import { dirname as dirname12, join as join11 } from "path";
5251
5315
  import { fileURLToPath as fileURLToPath2 } from "url";
5252
5316
  import chalk28 from "chalk";
5253
5317
  var WORKFLOW_PATH = ".github/workflows/build.yml";
@@ -5261,7 +5325,7 @@ function getExistingSiteId() {
5261
5325
  return match ? match[1] : null;
5262
5326
  }
5263
5327
  function getTemplateContent(siteId) {
5264
- const templatePath = join10(__dirname2, "commands/deploy/build.yml");
5328
+ const templatePath = join11(__dirname2, "commands/deploy/build.yml");
5265
5329
  const template = readFileSync12(templatePath, "utf8");
5266
5330
  return template.replace("{{NETLIFY_SITE_ID}}", siteId);
5267
5331
  }
@@ -5612,7 +5676,7 @@ function registerActivity(program2) {
5612
5676
 
5613
5677
  // src/commands/registerBackup.ts
5614
5678
  import { mkdir as mkdir2, stat } from "fs/promises";
5615
- import { join as join12, resolve as resolve7 } from "path";
5679
+ import { join as join13, resolve as resolve7 } from "path";
5616
5680
  import chalk32 from "chalk";
5617
5681
 
5618
5682
  // src/shared/db/recordBackup.ts
@@ -5625,14 +5689,14 @@ async function recordBackup(db, {
5625
5689
  }
5626
5690
 
5627
5691
  // src/shared/expandTilde.ts
5628
- import { homedir as homedir3 } from "os";
5692
+ import { homedir as homedir4 } from "os";
5629
5693
  function expandTilde2(value) {
5630
- return value.startsWith("~/") ? homedir3() + value.slice(1) : value;
5694
+ return value.startsWith("~/") ? homedir4() + value.slice(1) : value;
5631
5695
  }
5632
5696
 
5633
5697
  // src/commands/backup/scheduleBackup.ts
5634
5698
  import { mkdir } from "fs/promises";
5635
- import { join as join11 } from "path";
5699
+ import { join as join12 } from "path";
5636
5700
  import chalk30 from "chalk";
5637
5701
 
5638
5702
  // src/commands/backup/readCrontab.ts
@@ -5774,7 +5838,7 @@ async function scheduleBackup({
5774
5838
  const cronExpr = durationToCron(every);
5775
5839
  const dir = expandTilde2(loadConfig().backup.dir);
5776
5840
  await mkdir(dir, { recursive: true });
5777
- const logPath2 = join11(dir, "cron.log");
5841
+ const logPath2 = join12(dir, "cron.log");
5778
5842
  const cronLine = `${cronExpr} ${resolveAssistCommand()} backup >> ${logPath2} 2>&1`;
5779
5843
  writeCrontab(upsertScheduleBlock(readCrontab(), every, cronLine));
5780
5844
  console.error(
@@ -5953,7 +6017,7 @@ async function backup({ out }) {
5953
6017
  await mkdir2(dir, { recursive: true });
5954
6018
  const start3 = Date.now();
5955
6019
  const timestamp6 = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
5956
- const filePath = resolve7(join12(dir, `backup-${timestamp6}.dump`));
6020
+ const filePath = resolve7(join13(dir, `backup-${timestamp6}.dump`));
5957
6021
  await exportBacklog(filePath);
5958
6022
  const { size } = await stat(filePath);
5959
6023
  const durationMs = Date.now() - start3;
@@ -6060,13 +6124,13 @@ import {
6060
6124
  unlinkSync as unlinkSync2,
6061
6125
  writeFileSync as writeFileSync14
6062
6126
  } from "fs";
6063
- import { homedir as homedir4 } from "os";
6064
- import { join as join13 } from "path";
6127
+ import { homedir as homedir5 } from "os";
6128
+ import { join as join14 } from "path";
6065
6129
  function getLocksDir() {
6066
- return join13(homedir4(), ".assist", "locks");
6130
+ return join14(homedir5(), ".assist", "locks");
6067
6131
  }
6068
6132
  function getLockPath(itemId2) {
6069
- return join13(getLocksDir(), `lock-${itemId2}.json`);
6133
+ return join14(getLocksDir(), `lock-${itemId2}.json`);
6070
6134
  }
6071
6135
  function isProcessAlive(pid) {
6072
6136
  try {
@@ -6192,21 +6256,6 @@ import chalk46 from "chalk";
6192
6256
  // src/commands/sessions/daemon/ensureHooksSettings.ts
6193
6257
  import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync15 } from "fs";
6194
6258
  import { dirname as dirname13 } from "path";
6195
-
6196
- // src/commands/sessions/daemon/daemonPaths.ts
6197
- import { homedir as homedir5 } from "os";
6198
- import { join as join14 } from "path";
6199
- var DAEMON_DIR = join14(homedir5(), ".assist", "daemon");
6200
- var daemonPaths = {
6201
- dir: DAEMON_DIR,
6202
- socket: process.platform === "win32" ? String.raw`\\.\pipe\assist-sessions-daemon` : join14(DAEMON_DIR, "daemon.sock"),
6203
- log: join14(DAEMON_DIR, "daemon.log"),
6204
- pid: join14(DAEMON_DIR, "daemon.pid"),
6205
- spawnLock: join14(DAEMON_DIR, "spawn.lock"),
6206
- hooksSettings: join14(DAEMON_DIR, "hooks-settings.json")
6207
- };
6208
-
6209
- // src/commands/sessions/daemon/ensureHooksSettings.ts
6210
6259
  var SET_STATUS = "assist sessions set-status";
6211
6260
  function running(source) {
6212
6261
  return `${SET_STATUS} running --source ${source}`;
@@ -7400,24 +7449,6 @@ Failed to launch Claude for ${context}: ${message3}`)
7400
7449
  }
7401
7450
  }
7402
7451
 
7403
- // src/commands/sessions/daemon/connectToDaemon.ts
7404
- import * as net from "net";
7405
- function connectToDaemon() {
7406
- return new Promise((resolve23, reject) => {
7407
- const socket = net.connect(daemonPaths.socket);
7408
- socket.once("connect", () => resolve23(socket));
7409
- socket.once("error", reject);
7410
- });
7411
- }
7412
- async function isDaemonRunning() {
7413
- try {
7414
- (await connectToDaemon()).destroy();
7415
- return true;
7416
- } catch {
7417
- return false;
7418
- }
7419
- }
7420
-
7421
7452
  // src/commands/sessions/daemon/sendToDaemon.ts
7422
7453
  var WRITE_TIMEOUT_MS = 500;
7423
7454
  function sendToDaemon(message3) {
@@ -20155,6 +20186,7 @@ var persistedSessionSchema = z8.object({
20155
20186
  autoRun: z8.boolean().optional(),
20156
20187
  autoAdvance: z8.boolean().optional(),
20157
20188
  reviewStarted: z8.boolean().optional(),
20189
+ launchedFrom: z8.string().optional(),
20158
20190
  undurable: z8.object({ reason: z8.string(), removesTree: z8.boolean().optional() }).optional()
20159
20191
  });
20160
20192
 
@@ -20183,6 +20215,7 @@ function toPersistedSession(session) {
20183
20215
  autoRun: session.autoRun,
20184
20216
  autoAdvance: session.autoAdvance,
20185
20217
  reviewStarted: session.reviewStarted,
20218
+ launchedFrom: session.launchedFrom,
20186
20219
  undurable: session.undurable
20187
20220
  };
20188
20221
  }
@@ -29727,6 +29760,7 @@ function toSessionInfo(session) {
29727
29760
  starred,
29728
29761
  watcher,
29729
29762
  design,
29763
+ verifying,
29730
29764
  pendingPrPreview,
29731
29765
  undurable
29732
29766
  } = session;
@@ -29749,6 +29783,7 @@ function toSessionInfo(session) {
29749
29783
  starred,
29750
29784
  watcher,
29751
29785
  design,
29786
+ verifying,
29752
29787
  pendingPrPreview,
29753
29788
  undurable
29754
29789
  };
@@ -31919,6 +31954,14 @@ function restartManagedSession(sessions, id, clients, onStatusChange) {
31919
31954
  return { ok: true };
31920
31955
  }
31921
31956
 
31957
+ // src/commands/sessions/daemon/releaseClient.ts
31958
+ function releaseClient(client, clients, prPreview, verify) {
31959
+ clients.delete(client);
31960
+ clients.unsubscribeLogs(client);
31961
+ prPreview.clearWaiter(client);
31962
+ verify.clear(client);
31963
+ }
31964
+
31922
31965
  // src/commands/sessions/daemon/restoredAutoAdvance.ts
31923
31966
  function restoredAutoAdvance(id, persisted) {
31924
31967
  const itemId2 = persisted.activity?.itemId;
@@ -31948,7 +31991,8 @@ function restoreBase(id, persisted) {
31948
31991
  watcher: persisted.watcher,
31949
31992
  autoRun: persisted.autoRun,
31950
31993
  autoAdvance: restoredAutoAdvance(id, persisted),
31951
- reviewStarted: persisted.reviewStarted
31994
+ reviewStarted: persisted.reviewStarted,
31995
+ launchedFrom: persisted.launchedFrom
31952
31996
  };
31953
31997
  }
31954
31998
 
@@ -31989,6 +32033,22 @@ function logDroppedSession(persisted, error) {
31989
32033
  );
31990
32034
  }
31991
32035
 
32036
+ // src/commands/sessions/daemon/remapLaunchedFrom.ts
32037
+ function remapLaunchedFrom(sessions, restoredIds) {
32038
+ for (const session of sessions.values()) {
32039
+ const persistedLauncherId = session.launchedFrom;
32040
+ if (persistedLauncherId == null) continue;
32041
+ const restoredLauncherId = restoredIds.get(persistedLauncherId);
32042
+ session.launchedFrom = restoredLauncherId === session.id ? void 0 : restoredLauncherId;
32043
+ logRemap(session, persistedLauncherId);
32044
+ }
32045
+ }
32046
+ function logRemap(session, persistedLauncherId) {
32047
+ daemonLog(
32048
+ session.launchedFrom ? `session ${session.id} relinked to launcher ${persistedLauncherId} -> ${session.launchedFrom}` : `session ${session.id} launcher ${persistedLauncherId} was not restored; left at the top level`
32049
+ );
32050
+ }
32051
+
31992
32052
  // src/commands/sessions/daemon/errorSession.ts
31993
32053
  function errorSession(id, persisted, error) {
31994
32054
  return {
@@ -32163,9 +32223,11 @@ function restoreOne(persisted, spawner, sessions) {
32163
32223
  try {
32164
32224
  const id = spawner.spawn((sid) => restoreSession(sid, persisted));
32165
32225
  logUnresumable(persisted.name, id, sessions.get(id));
32226
+ return id;
32166
32227
  } catch (error) {
32167
32228
  const reason4 = logRestoreError(persisted, error);
32168
32229
  spawnErrorCard(persisted, spawner, reason4);
32230
+ return void 0;
32169
32231
  }
32170
32232
  }
32171
32233
  function spawnErrorCard(persisted, spawner, reason4) {
@@ -32193,12 +32255,15 @@ function logRestoreError(persisted, error) {
32193
32255
  function restoreAll(spawner, sessions) {
32194
32256
  const persisted = loadPersistedSessions();
32195
32257
  const cap = sessionLimits.maxRestore();
32258
+ const restoredIds = /* @__PURE__ */ new Map();
32196
32259
  const names = persisted.slice(0, cap).map((entry) => {
32197
- restoreOne(entry, spawner, sessions);
32260
+ const id = restoreOne(entry, spawner, sessions);
32261
+ if (entry.id != null && id != null) restoredIds.set(entry.id, id);
32198
32262
  return entry.name;
32199
32263
  });
32200
32264
  for (const over of persisted.slice(cap))
32201
32265
  deferOne(over, spawner.recoveryCard, cap);
32266
+ remapLaunchedFrom(sessions, restoredIds);
32202
32267
  return names;
32203
32268
  }
32204
32269
  function deferOne(persisted, spawnRecoveryCard, cap) {
@@ -32795,6 +32860,41 @@ function treeSpawnContext(sessions, spawnWith, notify2, clients, onStatusChange)
32795
32860
  };
32796
32861
  }
32797
32862
 
32863
+ // src/commands/sessions/daemon/VerifyTracker.ts
32864
+ var VerifyTracker = class {
32865
+ constructor(sessions, notify2) {
32866
+ this.sessions = sessions;
32867
+ this.notify = notify2;
32868
+ }
32869
+ sessionByClient = /* @__PURE__ */ new Map();
32870
+ start(client, sessionId) {
32871
+ const session = this.sessions.get(sessionId);
32872
+ if (!session) {
32873
+ daemonLog(
32874
+ `verify-started for unknown session id=${sessionId} (ignoring)`
32875
+ );
32876
+ return;
32877
+ }
32878
+ daemonLog(`verify-started received: id=${sessionId}`);
32879
+ this.sessionByClient.set(client, sessionId);
32880
+ session.verifying = true;
32881
+ this.notify();
32882
+ }
32883
+ clear(client) {
32884
+ const sessionId = this.sessionByClient.get(client);
32885
+ if (!sessionId) return;
32886
+ this.sessionByClient.delete(client);
32887
+ if (this.stillVerifying(sessionId)) return;
32888
+ daemonLog(`verify connection closed: id=${sessionId}`);
32889
+ const session = this.sessions.get(sessionId);
32890
+ if (session) session.verifying = false;
32891
+ this.notify();
32892
+ }
32893
+ stillVerifying(sessionId) {
32894
+ return [...this.sessionByClient.values()].includes(sessionId);
32895
+ }
32896
+ };
32897
+
32798
32898
  // src/commands/sessions/daemon/connectToWindowsDaemon.ts
32799
32899
  import * as net2 from "net";
32800
32900
 
@@ -33782,6 +33882,7 @@ var SessionManager = class {
33782
33882
  );
33783
33883
  // why: dispatch calls active.set() on card click; broadcasts include active.toJSON()
33784
33884
  active = new ActiveSelection(() => this.notify());
33885
+ verify = new VerifyTracker(this.sessions, () => this.notify());
33785
33886
  clients = new ClientHub(persistUsagePeak);
33786
33887
  idCounter = { next: 1 };
33787
33888
  shuttingDown = false;
@@ -33793,9 +33894,7 @@ var SessionManager = class {
33793
33894
  greetClient(client, this.sessions, this.windowsProxy);
33794
33895
  }
33795
33896
  removeClient(client) {
33796
- this.clients.delete(client);
33797
- this.clients.unsubscribeLogs(client);
33798
- this.prPreview.clearWaiter(client);
33897
+ releaseClient(client, this.clients, this.prPreview, this.verify);
33799
33898
  this.onIdleChange?.(this.isIdle());
33800
33899
  }
33801
33900
  isIdle = () => this.sessions.size === 0 && this.clients.size === 0;
@@ -34176,6 +34275,7 @@ var messageHandlers = {
34176
34275
  ),
34177
34276
  "set-active": (_client, m, d) => m.active.set(d.cwd, d.sessionId),
34178
34277
  "set-status": handleSetStatus,
34278
+ "verify-started": (client, m, d) => m.verify.start(client, d.sessionId),
34179
34279
  "pr-preview": (client, m, d) => m.prPreview.set(client, d),
34180
34280
  "pr-decision": (_client, m, d) => m.prPreview.decide(d),
34181
34281
  "ui-status": (_client, _m, d) => daemonLog(`ui rendered: id=${d.sessionId} status=${d.status}`)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@staff0rd/assist",
3
- "version": "0.525.0",
3
+ "version": "0.527.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "bin": {