@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/README.md +1 -1
- package/claude/commands/bug.md +5 -4
- package/claude/commands/draft.md +5 -4
- package/dist/commands/sessions/web/bundle.js +62 -62
- package/dist/index.js +180 -118
- 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.
|
|
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/
|
|
17376
|
-
|
|
17377
|
-
|
|
17378
|
-
|
|
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
|
-
|
|
17397
|
-
|
|
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
|
-
|
|
17400
|
-
|
|
17401
|
-
|
|
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
|
-
|
|
17405
|
-
|
|
17406
|
-
|
|
17407
|
-
|
|
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 = (
|
|
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
|
-
|
|
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);
|