@staff0rd/assist 0.244.2 → 0.245.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.
- package/README.md +9 -8
- package/claude/commands/bug.md +6 -0
- package/claude/commands/draft.md +6 -0
- package/claude/commands/refine.md +8 -0
- package/dist/commands/sessions/web/bundle.js +1 -1
- package/dist/index.js +601 -391
- 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.245.1",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -3632,15 +3632,15 @@ Phase ${phaseNumber} completed.`));
|
|
|
3632
3632
|
|
|
3633
3633
|
// src/commands/backlog/watchForMarker.ts
|
|
3634
3634
|
import { existsSync as existsSync20, unwatchFile, watchFile } from "fs";
|
|
3635
|
-
function watchForMarker(child) {
|
|
3635
|
+
function watchForMarker(child, options2) {
|
|
3636
3636
|
const statusPath = getSignalPath();
|
|
3637
3637
|
watchFile(statusPath, { interval: 1e3 }, () => {
|
|
3638
3638
|
if (!existsSync20(statusPath)) return;
|
|
3639
3639
|
const signal = readSignal();
|
|
3640
|
-
if (signal)
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3640
|
+
if (!signal) return;
|
|
3641
|
+
if (signal.event === "done" && !options2?.actOnDone) return;
|
|
3642
|
+
unwatchFile(statusPath);
|
|
3643
|
+
child.kill("SIGTERM");
|
|
3644
3644
|
});
|
|
3645
3645
|
}
|
|
3646
3646
|
function stopWatching() {
|
|
@@ -3809,7 +3809,7 @@ async function next(options2, startId) {
|
|
|
3809
3809
|
firstPick = false;
|
|
3810
3810
|
if (id === void 0) return;
|
|
3811
3811
|
const completed = await run2(id, options2);
|
|
3812
|
-
if (!completed) return;
|
|
3812
|
+
if (!completed || options2?.once) return;
|
|
3813
3813
|
}
|
|
3814
3814
|
}
|
|
3815
3815
|
|
|
@@ -4098,7 +4098,14 @@ function startWebServer(label2, port, handler, initialPath) {
|
|
|
4098
4098
|
|
|
4099
4099
|
// src/commands/sessions/daemon/ensureDaemonRunning.ts
|
|
4100
4100
|
import { spawn as spawn4 } from "child_process";
|
|
4101
|
-
import {
|
|
4101
|
+
import {
|
|
4102
|
+
closeSync,
|
|
4103
|
+
mkdirSync as mkdirSync4,
|
|
4104
|
+
openSync,
|
|
4105
|
+
statSync,
|
|
4106
|
+
unlinkSync as unlinkSync4,
|
|
4107
|
+
writeSync
|
|
4108
|
+
} from "fs";
|
|
4102
4109
|
|
|
4103
4110
|
// src/commands/sessions/daemon/connectToDaemon.ts
|
|
4104
4111
|
import * as net from "net";
|
|
@@ -4111,7 +4118,8 @@ var daemonPaths = {
|
|
|
4111
4118
|
dir: DAEMON_DIR,
|
|
4112
4119
|
socket: process.platform === "win32" ? "\\\\.\\pipe\\assist-sessions-daemon" : join15(DAEMON_DIR, "daemon.sock"),
|
|
4113
4120
|
log: join15(DAEMON_DIR, "daemon.log"),
|
|
4114
|
-
pid: join15(DAEMON_DIR, "daemon.pid")
|
|
4121
|
+
pid: join15(DAEMON_DIR, "daemon.pid"),
|
|
4122
|
+
spawnLock: join15(DAEMON_DIR, "spawn.lock")
|
|
4115
4123
|
};
|
|
4116
4124
|
|
|
4117
4125
|
// src/commands/sessions/daemon/connectToDaemon.ts
|
|
@@ -4134,9 +4142,19 @@ async function isDaemonRunning() {
|
|
|
4134
4142
|
// src/commands/sessions/daemon/ensureDaemonRunning.ts
|
|
4135
4143
|
var SPAWN_TIMEOUT_MS = 1e4;
|
|
4136
4144
|
var RETRY_DELAY_MS = 200;
|
|
4137
|
-
|
|
4145
|
+
var STALE_LOCK_MS = SPAWN_TIMEOUT_MS + 5e3;
|
|
4146
|
+
async function ensureDaemonRunning(reason = "unspecified") {
|
|
4138
4147
|
if (await isDaemonRunning()) return;
|
|
4139
|
-
|
|
4148
|
+
mkdirSync4(daemonPaths.dir, { recursive: true });
|
|
4149
|
+
const holdsLock = acquireSpawnLock();
|
|
4150
|
+
if (holdsLock) spawnDaemon(reason);
|
|
4151
|
+
try {
|
|
4152
|
+
await waitForDaemon();
|
|
4153
|
+
} finally {
|
|
4154
|
+
if (holdsLock) releaseSpawnLock();
|
|
4155
|
+
}
|
|
4156
|
+
}
|
|
4157
|
+
async function waitForDaemon() {
|
|
4140
4158
|
const deadline = Date.now() + SPAWN_TIMEOUT_MS;
|
|
4141
4159
|
while (Date.now() < deadline) {
|
|
4142
4160
|
await delay(RETRY_DELAY_MS);
|
|
@@ -4146,12 +4164,44 @@ async function ensureDaemonRunning() {
|
|
|
4146
4164
|
`Sessions daemon did not start within ${SPAWN_TIMEOUT_MS / 1e3}s; see ${daemonPaths.log}`
|
|
4147
4165
|
);
|
|
4148
4166
|
}
|
|
4149
|
-
function
|
|
4150
|
-
|
|
4167
|
+
function acquireSpawnLock() {
|
|
4168
|
+
if (tryCreateLock()) return true;
|
|
4169
|
+
if (!isLockStale()) return false;
|
|
4170
|
+
try {
|
|
4171
|
+
unlinkSync4(daemonPaths.spawnLock);
|
|
4172
|
+
} catch {
|
|
4173
|
+
}
|
|
4174
|
+
return tryCreateLock();
|
|
4175
|
+
}
|
|
4176
|
+
function tryCreateLock() {
|
|
4177
|
+
try {
|
|
4178
|
+
const fd = openSync(daemonPaths.spawnLock, "wx");
|
|
4179
|
+
writeSync(fd, String(process.pid));
|
|
4180
|
+
closeSync(fd);
|
|
4181
|
+
return true;
|
|
4182
|
+
} catch {
|
|
4183
|
+
return false;
|
|
4184
|
+
}
|
|
4185
|
+
}
|
|
4186
|
+
function isLockStale() {
|
|
4187
|
+
try {
|
|
4188
|
+
return Date.now() - statSync(daemonPaths.spawnLock).mtimeMs > STALE_LOCK_MS;
|
|
4189
|
+
} catch {
|
|
4190
|
+
return true;
|
|
4191
|
+
}
|
|
4192
|
+
}
|
|
4193
|
+
function releaseSpawnLock() {
|
|
4194
|
+
try {
|
|
4195
|
+
unlinkSync4(daemonPaths.spawnLock);
|
|
4196
|
+
} catch {
|
|
4197
|
+
}
|
|
4198
|
+
}
|
|
4199
|
+
function spawnDaemon(reason) {
|
|
4151
4200
|
const log = openSync(daemonPaths.log, "a");
|
|
4152
4201
|
const child = spawn4(process.execPath, [process.argv[1], "daemon", "run"], {
|
|
4153
4202
|
detached: true,
|
|
4154
|
-
stdio: ["ignore", log, log]
|
|
4203
|
+
stdio: ["ignore", log, log],
|
|
4204
|
+
env: { ...process.env, ASSIST_DAEMON_SPAWN_REASON: reason }
|
|
4155
4205
|
});
|
|
4156
4206
|
child.unref();
|
|
4157
4207
|
}
|
|
@@ -4500,7 +4550,7 @@ function handleSocket(ws, ctx) {
|
|
|
4500
4550
|
}
|
|
4501
4551
|
async function openDaemonConnection(ws, ctx) {
|
|
4502
4552
|
try {
|
|
4503
|
-
await ensureDaemonRunning();
|
|
4553
|
+
await ensureDaemonRunning("web socket connection");
|
|
4504
4554
|
const conn = await connectToDaemon();
|
|
4505
4555
|
relayDaemonLines(conn, ws, ctx.repoCwd);
|
|
4506
4556
|
return conn;
|
|
@@ -4554,7 +4604,7 @@ function withRepoCwd(line, repoCwd) {
|
|
|
4554
4604
|
|
|
4555
4605
|
// src/commands/sessions/web/index.ts
|
|
4556
4606
|
async function web(options2) {
|
|
4557
|
-
await ensureDaemonRunning();
|
|
4607
|
+
await ensureDaemonRunning("web server start");
|
|
4558
4608
|
const port = Number.parseInt(options2.port, 10);
|
|
4559
4609
|
const server = startWebServer(
|
|
4560
4610
|
"Assist",
|
|
@@ -4584,117 +4634,27 @@ async function web2(options2) {
|
|
|
4584
4634
|
await web({ port: options2.port, initialPath: "/backlog" });
|
|
4585
4635
|
}
|
|
4586
4636
|
|
|
4587
|
-
// src/commands/backlog/refine.ts
|
|
4588
|
-
import chalk47 from "chalk";
|
|
4589
|
-
import enquirer6 from "enquirer";
|
|
4590
|
-
|
|
4591
|
-
// src/commands/backlog/launchMode.ts
|
|
4592
|
-
import chalk46 from "chalk";
|
|
4593
|
-
|
|
4594
|
-
// src/commands/backlog/tryRunById.ts
|
|
4595
|
-
import chalk45 from "chalk";
|
|
4596
|
-
async function tryRunById(id, options2) {
|
|
4597
|
-
const items2 = await loadBacklog();
|
|
4598
|
-
const numericId = Number.parseInt(id, 10);
|
|
4599
|
-
const item = Number.isNaN(numericId) ? void 0 : items2.find((i) => i.id === numericId);
|
|
4600
|
-
if (!item) {
|
|
4601
|
-
console.log(chalk45.red(`Item #${id} not found.`));
|
|
4602
|
-
return false;
|
|
4603
|
-
}
|
|
4604
|
-
if (item.status === "done") {
|
|
4605
|
-
console.log(chalk45.red(`Item #${id} is already done.`));
|
|
4606
|
-
return false;
|
|
4607
|
-
}
|
|
4608
|
-
if (item.status === "wontdo") {
|
|
4609
|
-
console.log(chalk45.red(`Item #${id} is marked won't do.`));
|
|
4610
|
-
return false;
|
|
4611
|
-
}
|
|
4612
|
-
if (isBlocked(item, items2)) {
|
|
4613
|
-
console.log(
|
|
4614
|
-
chalk45.red(`Item #${id} is blocked by unresolved dependencies.`)
|
|
4615
|
-
);
|
|
4616
|
-
return false;
|
|
4617
|
-
}
|
|
4618
|
-
console.log(chalk45.bold(`
|
|
4619
|
-
Running backlog item #${id}...
|
|
4620
|
-
`));
|
|
4621
|
-
await run2(id, options2);
|
|
4622
|
-
return true;
|
|
4623
|
-
}
|
|
4624
|
-
|
|
4625
|
-
// src/commands/backlog/launchMode.ts
|
|
4626
|
-
async function launchMode(slashCommand) {
|
|
4627
|
-
pullIfConfigured();
|
|
4628
|
-
process.env.ASSIST_SESSION_ID = String(process.pid);
|
|
4629
|
-
const { child, done: done2 } = spawnClaude(`/${slashCommand}`, { allowEdits: true });
|
|
4630
|
-
watchForMarker(child);
|
|
4631
|
-
await done2;
|
|
4632
|
-
stopWatching();
|
|
4633
|
-
const signal = readSignal();
|
|
4634
|
-
cleanupSignal();
|
|
4635
|
-
if (signal?.event === "next") {
|
|
4636
|
-
if (typeof signal.id === "string" && signal.id) {
|
|
4637
|
-
if (await tryRunById(signal.id, { allowEdits: true })) return;
|
|
4638
|
-
}
|
|
4639
|
-
console.log(chalk46.bold("\nChaining into assist next...\n"));
|
|
4640
|
-
await next({ allowEdits: true });
|
|
4641
|
-
}
|
|
4642
|
-
}
|
|
4643
|
-
|
|
4644
|
-
// src/commands/backlog/refine.ts
|
|
4645
|
-
async function pickItemForRefine() {
|
|
4646
|
-
const items2 = await loadBacklog();
|
|
4647
|
-
const active = items2.filter(
|
|
4648
|
-
(i) => i.status === "todo" || i.status === "in-progress"
|
|
4649
|
-
);
|
|
4650
|
-
if (active.length === 0) {
|
|
4651
|
-
console.log(chalk47.yellow("No active backlog items to refine."));
|
|
4652
|
-
return void 0;
|
|
4653
|
-
}
|
|
4654
|
-
if (active.length === 1) {
|
|
4655
|
-
const item = active[0];
|
|
4656
|
-
console.log(chalk47.bold(`Auto-selecting item #${item.id}: ${item.name}`));
|
|
4657
|
-
return String(item.id);
|
|
4658
|
-
}
|
|
4659
|
-
const { selected } = await exitOnCancel(
|
|
4660
|
-
enquirer6.prompt({
|
|
4661
|
-
type: "select",
|
|
4662
|
-
name: "selected",
|
|
4663
|
-
message: "Choose a backlog item to refine:",
|
|
4664
|
-
choices: active.map((item) => ({
|
|
4665
|
-
name: `${typeLabel(item.type)} #${item.id}: ${item.name}`
|
|
4666
|
-
}))
|
|
4667
|
-
})
|
|
4668
|
-
);
|
|
4669
|
-
return selected.match(/#(\d+)/)?.[1] ?? "";
|
|
4670
|
-
}
|
|
4671
|
-
async function refine(id) {
|
|
4672
|
-
const itemId = id ?? await pickItemForRefine();
|
|
4673
|
-
if (!itemId) return;
|
|
4674
|
-
await launchMode(`refine ${itemId}`);
|
|
4675
|
-
}
|
|
4676
|
-
|
|
4677
4637
|
// src/commands/backlog/comment/index.ts
|
|
4678
|
-
import
|
|
4638
|
+
import chalk45 from "chalk";
|
|
4679
4639
|
async function comment(id, text2) {
|
|
4680
4640
|
const found = await findOneItem(id);
|
|
4681
4641
|
if (!found) process.exit(1);
|
|
4682
4642
|
await appendComment(found.orm, found.item.id, text2);
|
|
4683
|
-
console.log(
|
|
4643
|
+
console.log(chalk45.green(`Comment added to item #${id}.`));
|
|
4684
4644
|
}
|
|
4685
4645
|
|
|
4686
4646
|
// src/commands/backlog/comments/index.ts
|
|
4687
|
-
import
|
|
4647
|
+
import chalk46 from "chalk";
|
|
4688
4648
|
async function comments2(id) {
|
|
4689
4649
|
const found = await findOneItem(id);
|
|
4690
4650
|
if (!found) process.exit(1);
|
|
4691
4651
|
const { item } = found;
|
|
4692
4652
|
const entries = item.comments ?? [];
|
|
4693
4653
|
if (entries.length === 0) {
|
|
4694
|
-
console.log(
|
|
4654
|
+
console.log(chalk46.dim(`No comments on item #${id}.`));
|
|
4695
4655
|
return;
|
|
4696
4656
|
}
|
|
4697
|
-
console.log(
|
|
4657
|
+
console.log(chalk46.bold(`Comments for #${id}: ${item.name}
|
|
4698
4658
|
`));
|
|
4699
4659
|
for (const entry of entries) {
|
|
4700
4660
|
console.log(`${formatComment(entry)}
|
|
@@ -4703,7 +4663,7 @@ async function comments2(id) {
|
|
|
4703
4663
|
}
|
|
4704
4664
|
|
|
4705
4665
|
// src/commands/backlog/delete-comment/index.ts
|
|
4706
|
-
import
|
|
4666
|
+
import chalk47 from "chalk";
|
|
4707
4667
|
async function deleteCommentCmd(id, commentId) {
|
|
4708
4668
|
const found = await findOneItem(id);
|
|
4709
4669
|
if (!found) process.exit(1);
|
|
@@ -4715,16 +4675,16 @@ async function deleteCommentCmd(id, commentId) {
|
|
|
4715
4675
|
switch (outcome) {
|
|
4716
4676
|
case "deleted":
|
|
4717
4677
|
console.log(
|
|
4718
|
-
|
|
4678
|
+
chalk47.green(`Comment #${commentId} deleted from item #${id}.`)
|
|
4719
4679
|
);
|
|
4720
4680
|
break;
|
|
4721
4681
|
case "not-found":
|
|
4722
|
-
console.log(
|
|
4682
|
+
console.log(chalk47.red(`Comment #${commentId} not found on item #${id}.`));
|
|
4723
4683
|
process.exit(1);
|
|
4724
4684
|
break;
|
|
4725
4685
|
case "is-summary":
|
|
4726
4686
|
console.log(
|
|
4727
|
-
|
|
4687
|
+
chalk47.red(
|
|
4728
4688
|
`Comment #${commentId} is a phase summary and cannot be deleted.`
|
|
4729
4689
|
)
|
|
4730
4690
|
);
|
|
@@ -4742,7 +4702,7 @@ function registerCommentCommands(cmd) {
|
|
|
4742
4702
|
|
|
4743
4703
|
// src/commands/backlog/export/index.ts
|
|
4744
4704
|
import { writeFile } from "fs/promises";
|
|
4745
|
-
import
|
|
4705
|
+
import chalk48 from "chalk";
|
|
4746
4706
|
|
|
4747
4707
|
// src/commands/backlog/dump/DumpTable.ts
|
|
4748
4708
|
var DUMP_FORMAT = "assist-backlog-dump";
|
|
@@ -4809,7 +4769,7 @@ async function exportBacklog(file) {
|
|
|
4809
4769
|
if (file) {
|
|
4810
4770
|
await writeFile(file, dump);
|
|
4811
4771
|
console.error(
|
|
4812
|
-
|
|
4772
|
+
chalk48.green(`Exported backlog to ${file} (${dump.length} bytes).`)
|
|
4813
4773
|
);
|
|
4814
4774
|
return;
|
|
4815
4775
|
}
|
|
@@ -4825,7 +4785,7 @@ function registerExportCommand(cmd) {
|
|
|
4825
4785
|
|
|
4826
4786
|
// src/commands/backlog/import/index.ts
|
|
4827
4787
|
import { readFile } from "fs/promises";
|
|
4828
|
-
import
|
|
4788
|
+
import chalk50 from "chalk";
|
|
4829
4789
|
|
|
4830
4790
|
// src/commands/backlog/dump/countCopyRows.ts
|
|
4831
4791
|
function countCopyRows(data) {
|
|
@@ -4902,7 +4862,7 @@ function validateDump({ header, sections }) {
|
|
|
4902
4862
|
}
|
|
4903
4863
|
|
|
4904
4864
|
// src/commands/backlog/import/confirmReplace.ts
|
|
4905
|
-
import
|
|
4865
|
+
import chalk49 from "chalk";
|
|
4906
4866
|
async function countRows(client, table) {
|
|
4907
4867
|
const { rows } = await client.query(
|
|
4908
4868
|
`SELECT count(*)::int AS n FROM ${table}`
|
|
@@ -4913,7 +4873,7 @@ function printSummary(current, incoming) {
|
|
|
4913
4873
|
const lines = DUMP_TABLES.map(
|
|
4914
4874
|
(t, i) => ` ${t.name}: ${current[i]} \u2192 ${incoming[i]} rows`
|
|
4915
4875
|
);
|
|
4916
|
-
console.error(
|
|
4876
|
+
console.error(chalk49.bold("\nThis will REPLACE all backlog data:"));
|
|
4917
4877
|
console.error(`${lines.join("\n")}
|
|
4918
4878
|
`);
|
|
4919
4879
|
}
|
|
@@ -4989,13 +4949,13 @@ async function importBacklog(file, options2 = {}) {
|
|
|
4989
4949
|
);
|
|
4990
4950
|
await withBacklogClient(async (client) => {
|
|
4991
4951
|
if (!options2.yes && !await confirmReplace(client, incoming, !file)) {
|
|
4992
|
-
console.error(
|
|
4952
|
+
console.error(chalk50.yellow("Import cancelled; no changes made."));
|
|
4993
4953
|
return;
|
|
4994
4954
|
}
|
|
4995
4955
|
await restore(client, parsed);
|
|
4996
4956
|
const total = incoming.reduce((sum, n) => sum + n, 0);
|
|
4997
4957
|
console.error(
|
|
4998
|
-
|
|
4958
|
+
chalk50.green(
|
|
4999
4959
|
`Imported backlog: ${total} rows restored across ${DUMP_TABLES.length} tables.`
|
|
5000
4960
|
)
|
|
5001
4961
|
);
|
|
@@ -5012,16 +4972,16 @@ function registerImportCommand(cmd) {
|
|
|
5012
4972
|
}
|
|
5013
4973
|
|
|
5014
4974
|
// src/commands/backlog/add/index.ts
|
|
5015
|
-
import
|
|
4975
|
+
import chalk51 from "chalk";
|
|
5016
4976
|
|
|
5017
4977
|
// src/commands/backlog/add/shared.ts
|
|
5018
4978
|
import { spawnSync } from "child_process";
|
|
5019
|
-
import { mkdtempSync, readFileSync as readFileSync14, unlinkSync as
|
|
4979
|
+
import { mkdtempSync, readFileSync as readFileSync14, unlinkSync as unlinkSync5, writeFileSync as writeFileSync13 } from "fs";
|
|
5020
4980
|
import { tmpdir } from "os";
|
|
5021
4981
|
import { join as join17 } from "path";
|
|
5022
|
-
import
|
|
4982
|
+
import enquirer6 from "enquirer";
|
|
5023
4983
|
async function promptType() {
|
|
5024
|
-
const { type } = await
|
|
4984
|
+
const { type } = await enquirer6.prompt({
|
|
5025
4985
|
type: "select",
|
|
5026
4986
|
name: "type",
|
|
5027
4987
|
message: "Type:",
|
|
@@ -5031,7 +4991,7 @@ async function promptType() {
|
|
|
5031
4991
|
return type;
|
|
5032
4992
|
}
|
|
5033
4993
|
async function promptName() {
|
|
5034
|
-
const { name } = await
|
|
4994
|
+
const { name } = await enquirer6.prompt({
|
|
5035
4995
|
type: "input",
|
|
5036
4996
|
name: "name",
|
|
5037
4997
|
message: "Name:",
|
|
@@ -5040,14 +5000,14 @@ async function promptName() {
|
|
|
5040
5000
|
return name.trim();
|
|
5041
5001
|
}
|
|
5042
5002
|
async function promptDescription() {
|
|
5043
|
-
const { useEditor } = await
|
|
5003
|
+
const { useEditor } = await enquirer6.prompt({
|
|
5044
5004
|
type: "confirm",
|
|
5045
5005
|
name: "useEditor",
|
|
5046
5006
|
message: "Open editor for description?",
|
|
5047
5007
|
initial: false
|
|
5048
5008
|
});
|
|
5049
5009
|
if (!useEditor) {
|
|
5050
|
-
const { description } = await
|
|
5010
|
+
const { description } = await enquirer6.prompt({
|
|
5051
5011
|
type: "input",
|
|
5052
5012
|
name: "description",
|
|
5053
5013
|
message: "Description (optional):"
|
|
@@ -5063,17 +5023,17 @@ function openEditor() {
|
|
|
5063
5023
|
writeFileSync13(filePath, "");
|
|
5064
5024
|
const result = spawnSync(editor, [filePath], { stdio: "inherit" });
|
|
5065
5025
|
if (result.status !== 0) {
|
|
5066
|
-
|
|
5026
|
+
unlinkSync5(filePath);
|
|
5067
5027
|
return void 0;
|
|
5068
5028
|
}
|
|
5069
5029
|
const content = readFileSync14(filePath, "utf-8").trim();
|
|
5070
|
-
|
|
5030
|
+
unlinkSync5(filePath);
|
|
5071
5031
|
return content || void 0;
|
|
5072
5032
|
}
|
|
5073
5033
|
async function promptAcceptanceCriteria() {
|
|
5074
5034
|
const criteria = [];
|
|
5075
5035
|
for (; ; ) {
|
|
5076
|
-
const { criterion } = await
|
|
5036
|
+
const { criterion } = await enquirer6.prompt({
|
|
5077
5037
|
type: "input",
|
|
5078
5038
|
name: "criterion",
|
|
5079
5039
|
message: "Acceptance criterion (empty to finish):"
|
|
@@ -5102,11 +5062,11 @@ async function add(options2) {
|
|
|
5102
5062
|
},
|
|
5103
5063
|
getOrigin()
|
|
5104
5064
|
);
|
|
5105
|
-
console.log(
|
|
5065
|
+
console.log(chalk51.green(`Added item #${id}: ${name}`));
|
|
5106
5066
|
}
|
|
5107
5067
|
|
|
5108
5068
|
// src/commands/backlog/addPhase.ts
|
|
5109
|
-
import
|
|
5069
|
+
import chalk53 from "chalk";
|
|
5110
5070
|
|
|
5111
5071
|
// src/commands/backlog/insertPhaseAt.ts
|
|
5112
5072
|
import { count, eq as eq14 } from "drizzle-orm";
|
|
@@ -5139,7 +5099,7 @@ async function insertPhaseAt(orm, itemId, phaseIdx, name, tasks, manualChecks, c
|
|
|
5139
5099
|
}
|
|
5140
5100
|
|
|
5141
5101
|
// src/commands/backlog/resolveInsertPosition.ts
|
|
5142
|
-
import
|
|
5102
|
+
import chalk52 from "chalk";
|
|
5143
5103
|
import { count as count2, eq as eq15 } from "drizzle-orm";
|
|
5144
5104
|
async function resolveInsertPosition(orm, itemId, position) {
|
|
5145
5105
|
const [row] = await orm.select({ cnt: count2() }).from(planPhases).where(eq15(planPhases.itemId, itemId));
|
|
@@ -5148,7 +5108,7 @@ async function resolveInsertPosition(orm, itemId, position) {
|
|
|
5148
5108
|
const pos = Number.parseInt(position, 10);
|
|
5149
5109
|
if (pos < 1 || pos > phaseCount + 1) {
|
|
5150
5110
|
console.log(
|
|
5151
|
-
|
|
5111
|
+
chalk52.red(
|
|
5152
5112
|
`Position ${pos} is out of range. Must be between 1 and ${phaseCount + 1}.`
|
|
5153
5113
|
)
|
|
5154
5114
|
);
|
|
@@ -5169,7 +5129,7 @@ async function addPhase(id, name, options2) {
|
|
|
5169
5129
|
if (!found) return;
|
|
5170
5130
|
const tasks = options2.task ?? [];
|
|
5171
5131
|
if (tasks.length === 0) {
|
|
5172
|
-
console.log(
|
|
5132
|
+
console.log(chalk53.red("At least one --task is required."));
|
|
5173
5133
|
process.exitCode = 1;
|
|
5174
5134
|
return;
|
|
5175
5135
|
}
|
|
@@ -5188,14 +5148,14 @@ async function addPhase(id, name, options2) {
|
|
|
5188
5148
|
);
|
|
5189
5149
|
const verb = options2.position !== void 0 ? "Inserted" : "Added";
|
|
5190
5150
|
console.log(
|
|
5191
|
-
|
|
5151
|
+
chalk53.green(
|
|
5192
5152
|
`${verb} phase ${phaseIdx + 1} "${name}" to item #${itemId} with ${tasks.length} task(s).`
|
|
5193
5153
|
)
|
|
5194
5154
|
);
|
|
5195
5155
|
}
|
|
5196
5156
|
|
|
5197
5157
|
// src/commands/backlog/list/index.ts
|
|
5198
|
-
import
|
|
5158
|
+
import chalk54 from "chalk";
|
|
5199
5159
|
|
|
5200
5160
|
// src/commands/backlog/originDisplayName.ts
|
|
5201
5161
|
function originDisplayName(origin) {
|
|
@@ -5247,7 +5207,7 @@ async function list2(options2) {
|
|
|
5247
5207
|
const allItems = await loadBacklog(options2.allRepos);
|
|
5248
5208
|
const items2 = filterItems(allItems, options2);
|
|
5249
5209
|
if (items2.length === 0) {
|
|
5250
|
-
console.log(
|
|
5210
|
+
console.log(chalk54.dim("Backlog is empty."));
|
|
5251
5211
|
return;
|
|
5252
5212
|
}
|
|
5253
5213
|
const labels = originDisplayLabels(
|
|
@@ -5256,9 +5216,9 @@ async function list2(options2) {
|
|
|
5256
5216
|
const repoNameOf = (item) => item.origin ? labels.get(item.origin) ?? "" : "";
|
|
5257
5217
|
const prefixWidth = options2.allRepos ? Math.max(0, ...items2.map((i) => repoNameOf(i).length)) : 0;
|
|
5258
5218
|
for (const item of items2) {
|
|
5259
|
-
const repoPrefix2 = options2.allRepos ? `${
|
|
5219
|
+
const repoPrefix2 = options2.allRepos ? `${chalk54.dim(repoNameOf(item).padEnd(prefixWidth))} ` : "";
|
|
5260
5220
|
console.log(
|
|
5261
|
-
`${repoPrefix2}${statusIcon(item.status)} ${typeLabel(item.type)} ${
|
|
5221
|
+
`${repoPrefix2}${statusIcon(item.status)} ${typeLabel(item.type)} ${chalk54.dim(`#${item.id}`)} ${item.name}${phaseLabel(item)}${dependencyLabel(item, allItems)}`
|
|
5262
5222
|
);
|
|
5263
5223
|
if (options2.verbose) {
|
|
5264
5224
|
printVerboseDetails(item);
|
|
@@ -5284,7 +5244,7 @@ function registerItemCommands(cmd) {
|
|
|
5284
5244
|
}
|
|
5285
5245
|
|
|
5286
5246
|
// src/commands/backlog/link.ts
|
|
5287
|
-
import
|
|
5247
|
+
import chalk56 from "chalk";
|
|
5288
5248
|
|
|
5289
5249
|
// src/commands/backlog/hasCycle.ts
|
|
5290
5250
|
function hasCycle(adjacency, fromId, toId) {
|
|
@@ -5316,14 +5276,14 @@ async function loadDependencyGraph(orm) {
|
|
|
5316
5276
|
}
|
|
5317
5277
|
|
|
5318
5278
|
// src/commands/backlog/validateLinkTarget.ts
|
|
5319
|
-
import
|
|
5279
|
+
import chalk55 from "chalk";
|
|
5320
5280
|
function validateLinkTarget(fromItem, fromNum, toNum, linkType) {
|
|
5321
5281
|
const duplicate = (fromItem.links ?? []).some(
|
|
5322
5282
|
(l) => l.targetId === toNum && l.type === linkType
|
|
5323
5283
|
);
|
|
5324
5284
|
if (duplicate) {
|
|
5325
5285
|
console.log(
|
|
5326
|
-
|
|
5286
|
+
chalk55.yellow(`Link already exists: #${fromNum} ${linkType} #${toNum}`)
|
|
5327
5287
|
);
|
|
5328
5288
|
return false;
|
|
5329
5289
|
}
|
|
@@ -5332,7 +5292,7 @@ function validateLinkTarget(fromItem, fromNum, toNum, linkType) {
|
|
|
5332
5292
|
|
|
5333
5293
|
// src/commands/backlog/link.ts
|
|
5334
5294
|
function fail(message) {
|
|
5335
|
-
console.log(
|
|
5295
|
+
console.log(chalk56.red(message));
|
|
5336
5296
|
return void 0;
|
|
5337
5297
|
}
|
|
5338
5298
|
function parseLinkType(type) {
|
|
@@ -5362,12 +5322,12 @@ async function link(fromId, toId, opts) {
|
|
|
5362
5322
|
if (await createsCycle(orm, linkType, fromNum, toNum)) return;
|
|
5363
5323
|
await orm.insert(links).values({ itemId: fromNum, type: linkType, targetId: toNum });
|
|
5364
5324
|
console.log(
|
|
5365
|
-
|
|
5325
|
+
chalk56.green(`Linked #${fromNum} ${linkType} #${toNum} (${toItem.name})`)
|
|
5366
5326
|
);
|
|
5367
5327
|
}
|
|
5368
5328
|
|
|
5369
5329
|
// src/commands/backlog/unlink.ts
|
|
5370
|
-
import
|
|
5330
|
+
import chalk57 from "chalk";
|
|
5371
5331
|
import { and as and4, eq as eq17 } from "drizzle-orm";
|
|
5372
5332
|
async function unlink(fromId, toId) {
|
|
5373
5333
|
const fromNum = Number.parseInt(fromId, 10);
|
|
@@ -5375,19 +5335,19 @@ async function unlink(fromId, toId) {
|
|
|
5375
5335
|
const { orm } = await getReady();
|
|
5376
5336
|
const fromItem = await loadItem(orm, fromNum);
|
|
5377
5337
|
if (!fromItem) {
|
|
5378
|
-
console.log(
|
|
5338
|
+
console.log(chalk57.red(`Item #${fromId} not found.`));
|
|
5379
5339
|
return;
|
|
5380
5340
|
}
|
|
5381
5341
|
if (!fromItem.links || fromItem.links.length === 0) {
|
|
5382
|
-
console.log(
|
|
5342
|
+
console.log(chalk57.yellow(`No links found on item #${fromId}.`));
|
|
5383
5343
|
return;
|
|
5384
5344
|
}
|
|
5385
5345
|
if (!fromItem.links.some((l) => l.targetId === toNum)) {
|
|
5386
|
-
console.log(
|
|
5346
|
+
console.log(chalk57.yellow(`No link from #${fromId} to #${toId} found.`));
|
|
5387
5347
|
return;
|
|
5388
5348
|
}
|
|
5389
5349
|
await orm.delete(links).where(and4(eq17(links.itemId, fromNum), eq17(links.targetId, toNum)));
|
|
5390
|
-
console.log(
|
|
5350
|
+
console.log(chalk57.green(`Removed link from #${fromId} to #${toId}.`));
|
|
5391
5351
|
}
|
|
5392
5352
|
|
|
5393
5353
|
// src/commands/backlog/registerLinkCommands.ts
|
|
@@ -5401,17 +5361,17 @@ function registerLinkCommands(cmd) {
|
|
|
5401
5361
|
}
|
|
5402
5362
|
|
|
5403
5363
|
// src/commands/backlog/move-repo/index.ts
|
|
5404
|
-
import
|
|
5364
|
+
import chalk59 from "chalk";
|
|
5405
5365
|
import { eq as eq19 } from "drizzle-orm";
|
|
5406
5366
|
|
|
5407
5367
|
// src/commands/backlog/move-repo/confirmMove.ts
|
|
5408
|
-
import
|
|
5368
|
+
import chalk58 from "chalk";
|
|
5409
5369
|
function pluralItems(n) {
|
|
5410
5370
|
return `${n} item${n === 1 ? "" : "s"}`;
|
|
5411
5371
|
}
|
|
5412
5372
|
async function confirmMove(cnt, oldOrigin, newOrigin) {
|
|
5413
5373
|
console.log(
|
|
5414
|
-
`${pluralItems(cnt)}: ${
|
|
5374
|
+
`${pluralItems(cnt)}: ${chalk58.cyan(oldOrigin)} \u2192 ${chalk58.cyan(newOrigin)}`
|
|
5415
5375
|
);
|
|
5416
5376
|
return promptConfirm(`Retag ${pluralItems(cnt)}?`);
|
|
5417
5377
|
}
|
|
@@ -5443,7 +5403,7 @@ Pass the full origin.`
|
|
|
5443
5403
|
|
|
5444
5404
|
// src/commands/backlog/move-repo/index.ts
|
|
5445
5405
|
function fail2(message) {
|
|
5446
|
-
console.log(
|
|
5406
|
+
console.log(chalk59.red(message));
|
|
5447
5407
|
process.exitCode = 1;
|
|
5448
5408
|
}
|
|
5449
5409
|
async function moveRepo(oldOriginRaw, newOriginRaw, options2 = {}) {
|
|
@@ -5459,12 +5419,12 @@ async function moveRepo(oldOriginRaw, newOriginRaw, options2 = {}) {
|
|
|
5459
5419
|
}
|
|
5460
5420
|
const cnt = await countByOrigin(orm, oldOrigin);
|
|
5461
5421
|
if (!options2.yes && !await confirmMove(cnt, oldOrigin, newOrigin)) {
|
|
5462
|
-
console.log(
|
|
5422
|
+
console.log(chalk59.yellow("Move cancelled; no changes made."));
|
|
5463
5423
|
return;
|
|
5464
5424
|
}
|
|
5465
5425
|
await orm.update(items).set({ origin: newOrigin }).where(eq19(items.origin, oldOrigin));
|
|
5466
5426
|
console.log(
|
|
5467
|
-
|
|
5427
|
+
chalk59.green(
|
|
5468
5428
|
`Moved ${pluralItems(cnt)} from "${oldOrigin}" to "${newOrigin}".`
|
|
5469
5429
|
)
|
|
5470
5430
|
);
|
|
@@ -5479,12 +5439,116 @@ function registerMoveRepoCommand(cmd) {
|
|
|
5479
5439
|
);
|
|
5480
5440
|
}
|
|
5481
5441
|
|
|
5442
|
+
// src/commands/backlog/registerNextCommand.ts
|
|
5443
|
+
function registerNextCommand(cmd) {
|
|
5444
|
+
cmd.command("next").argument("[id]", "Backlog item ID to run first").description("Pick and run the next backlog item, or open /draft if none").option("-w, --write", "Run Claude with auto permission mode (default)").option("--no-write", "Run Claude without auto permission mode").option("--once", "Exit after the first completed item run").action(
|
|
5445
|
+
(id, opts) => next({ allowEdits: opts.write !== false, once: opts.once }, id)
|
|
5446
|
+
);
|
|
5447
|
+
}
|
|
5448
|
+
|
|
5482
5449
|
// src/commands/backlog/registerPlanCommands.ts
|
|
5483
5450
|
function registerPlanCommands(cmd) {
|
|
5484
5451
|
cmd.command("plan <id>").description("Display the plan for a backlog item").action(plan);
|
|
5485
5452
|
cmd.command("phase-done <id> <phase> <summary>").description("Signal that a plan phase is complete").action(phaseDone);
|
|
5486
5453
|
}
|
|
5487
5454
|
|
|
5455
|
+
// src/commands/backlog/refine.ts
|
|
5456
|
+
import chalk62 from "chalk";
|
|
5457
|
+
import enquirer7 from "enquirer";
|
|
5458
|
+
|
|
5459
|
+
// src/commands/backlog/launchMode.ts
|
|
5460
|
+
import chalk61 from "chalk";
|
|
5461
|
+
|
|
5462
|
+
// src/commands/backlog/tryRunById.ts
|
|
5463
|
+
import chalk60 from "chalk";
|
|
5464
|
+
async function tryRunById(id, options2) {
|
|
5465
|
+
const items2 = await loadBacklog();
|
|
5466
|
+
const numericId = Number.parseInt(id, 10);
|
|
5467
|
+
const item = Number.isNaN(numericId) ? void 0 : items2.find((i) => i.id === numericId);
|
|
5468
|
+
if (!item) {
|
|
5469
|
+
console.log(chalk60.red(`Item #${id} not found.`));
|
|
5470
|
+
return false;
|
|
5471
|
+
}
|
|
5472
|
+
if (item.status === "done") {
|
|
5473
|
+
console.log(chalk60.red(`Item #${id} is already done.`));
|
|
5474
|
+
return false;
|
|
5475
|
+
}
|
|
5476
|
+
if (item.status === "wontdo") {
|
|
5477
|
+
console.log(chalk60.red(`Item #${id} is marked won't do.`));
|
|
5478
|
+
return false;
|
|
5479
|
+
}
|
|
5480
|
+
if (isBlocked(item, items2)) {
|
|
5481
|
+
console.log(
|
|
5482
|
+
chalk60.red(`Item #${id} is blocked by unresolved dependencies.`)
|
|
5483
|
+
);
|
|
5484
|
+
return false;
|
|
5485
|
+
}
|
|
5486
|
+
console.log(chalk60.bold(`
|
|
5487
|
+
Running backlog item #${id}...
|
|
5488
|
+
`));
|
|
5489
|
+
await run2(id, options2);
|
|
5490
|
+
return true;
|
|
5491
|
+
}
|
|
5492
|
+
|
|
5493
|
+
// src/commands/backlog/launchMode.ts
|
|
5494
|
+
async function launchMode(slashCommand, options2) {
|
|
5495
|
+
pullIfConfigured();
|
|
5496
|
+
process.env.ASSIST_SESSION_ID = String(process.pid);
|
|
5497
|
+
const { child, done: done2 } = spawnClaude(`/${slashCommand}`, { allowEdits: true });
|
|
5498
|
+
watchForMarker(child, { actOnDone: options2?.once });
|
|
5499
|
+
await done2;
|
|
5500
|
+
stopWatching();
|
|
5501
|
+
const signal = readSignal();
|
|
5502
|
+
cleanupSignal();
|
|
5503
|
+
if (signal?.event === "next") {
|
|
5504
|
+
if (typeof signal.id === "string" && signal.id) {
|
|
5505
|
+
if (await tryRunById(signal.id, { allowEdits: true })) return;
|
|
5506
|
+
}
|
|
5507
|
+
console.log(chalk61.bold("\nChaining into assist next...\n"));
|
|
5508
|
+
await next({ allowEdits: true, once: options2?.once });
|
|
5509
|
+
}
|
|
5510
|
+
}
|
|
5511
|
+
|
|
5512
|
+
// src/commands/backlog/refine.ts
|
|
5513
|
+
async function pickItemForRefine() {
|
|
5514
|
+
const items2 = await loadBacklog();
|
|
5515
|
+
const active = items2.filter(
|
|
5516
|
+
(i) => i.status === "todo" || i.status === "in-progress"
|
|
5517
|
+
);
|
|
5518
|
+
if (active.length === 0) {
|
|
5519
|
+
console.log(chalk62.yellow("No active backlog items to refine."));
|
|
5520
|
+
return void 0;
|
|
5521
|
+
}
|
|
5522
|
+
if (active.length === 1) {
|
|
5523
|
+
const item = active[0];
|
|
5524
|
+
console.log(chalk62.bold(`Auto-selecting item #${item.id}: ${item.name}`));
|
|
5525
|
+
return String(item.id);
|
|
5526
|
+
}
|
|
5527
|
+
const { selected } = await exitOnCancel(
|
|
5528
|
+
enquirer7.prompt({
|
|
5529
|
+
type: "select",
|
|
5530
|
+
name: "selected",
|
|
5531
|
+
message: "Choose a backlog item to refine:",
|
|
5532
|
+
choices: active.map((item) => ({
|
|
5533
|
+
name: `${typeLabel(item.type)} #${item.id}: ${item.name}`
|
|
5534
|
+
}))
|
|
5535
|
+
})
|
|
5536
|
+
);
|
|
5537
|
+
return selected.match(/#(\d+)/)?.[1] ?? "";
|
|
5538
|
+
}
|
|
5539
|
+
async function refine(id, options2) {
|
|
5540
|
+
const itemId = id ?? await pickItemForRefine();
|
|
5541
|
+
if (!itemId) return;
|
|
5542
|
+
await launchMode(`refine ${itemId}`, options2);
|
|
5543
|
+
}
|
|
5544
|
+
|
|
5545
|
+
// src/commands/backlog/registerRefineCommand.ts
|
|
5546
|
+
function registerRefineCommand(cmd) {
|
|
5547
|
+
cmd.command("refine").argument("[id]", "Backlog item ID").description("Alias for refine").option("--once", "Exit when the initial task completes").action(
|
|
5548
|
+
(id, opts) => refine(id, { once: opts.once })
|
|
5549
|
+
);
|
|
5550
|
+
}
|
|
5551
|
+
|
|
5488
5552
|
// src/commands/backlog/rewindPhase.ts
|
|
5489
5553
|
import chalk63 from "chalk";
|
|
5490
5554
|
function validateRewind2(item, phaseNumber) {
|
|
@@ -6021,14 +6085,6 @@ function registerShowCommands(cmd) {
|
|
|
6021
6085
|
function registerWebCommand(cmd) {
|
|
6022
6086
|
cmd.command("web").description("Open the backlog tab in the web dashboard").option("-p, --port <number>", "Port to listen on", "3100").action(web2);
|
|
6023
6087
|
}
|
|
6024
|
-
function registerRefineCommand(cmd) {
|
|
6025
|
-
cmd.command("refine").argument("[id]", "Backlog item ID").description("Alias for refine").action((id) => refine(id));
|
|
6026
|
-
}
|
|
6027
|
-
function registerNextCommand(cmd) {
|
|
6028
|
-
cmd.command("next").argument("[id]", "Backlog item ID to run first").description("Pick and run the next backlog item, or open /draft if none").option("-w, --write", "Run Claude with auto permission mode (default)").option("--no-write", "Run Claude without auto permission mode").action(
|
|
6029
|
-
(id, opts) => next({ allowEdits: opts.write !== false }, id)
|
|
6030
|
-
);
|
|
6031
|
-
}
|
|
6032
6088
|
var registrars = [
|
|
6033
6089
|
registerItemCommands,
|
|
6034
6090
|
registerShowCommands,
|
|
@@ -8300,7 +8356,7 @@ function registerDevlog(program2) {
|
|
|
8300
8356
|
}
|
|
8301
8357
|
|
|
8302
8358
|
// src/commands/dotnet/checkBuildLocks.ts
|
|
8303
|
-
import { closeSync, openSync as openSync2, readdirSync as readdirSync2 } from "fs";
|
|
8359
|
+
import { closeSync as closeSync2, openSync as openSync2, readdirSync as readdirSync2 } from "fs";
|
|
8304
8360
|
import { join as join25 } from "path";
|
|
8305
8361
|
import chalk95 from "chalk";
|
|
8306
8362
|
|
|
@@ -8332,7 +8388,7 @@ function isLockedDll(debugDir) {
|
|
|
8332
8388
|
const dllPath = join25(debugDir, file);
|
|
8333
8389
|
try {
|
|
8334
8390
|
const fd = openSync2(dllPath, "r+");
|
|
8335
|
-
|
|
8391
|
+
closeSync2(fd);
|
|
8336
8392
|
} catch {
|
|
8337
8393
|
return dllPath;
|
|
8338
8394
|
}
|
|
@@ -8422,7 +8478,7 @@ function collectAllDeps(node) {
|
|
|
8422
8478
|
}
|
|
8423
8479
|
|
|
8424
8480
|
// src/commands/dotnet/findContainingSolutions.ts
|
|
8425
|
-
import { readdirSync as readdirSync3, readFileSync as readFileSync22, statSync } from "fs";
|
|
8481
|
+
import { readdirSync as readdirSync3, readFileSync as readFileSync22, statSync as statSync2 } from "fs";
|
|
8426
8482
|
import path22 from "path";
|
|
8427
8483
|
function findSlnFiles(dir, maxDepth, depth = 0) {
|
|
8428
8484
|
if (depth > maxDepth) return [];
|
|
@@ -8438,7 +8494,7 @@ function findSlnFiles(dir, maxDepth, depth = 0) {
|
|
|
8438
8494
|
continue;
|
|
8439
8495
|
const full = path22.join(dir, entry);
|
|
8440
8496
|
try {
|
|
8441
|
-
const stat =
|
|
8497
|
+
const stat = statSync2(full);
|
|
8442
8498
|
if (stat.isFile() && entry.endsWith(".sln")) {
|
|
8443
8499
|
results.push(full);
|
|
8444
8500
|
} else if (stat.isDirectory()) {
|
|
@@ -8775,7 +8831,7 @@ function parseInspectReport(json) {
|
|
|
8775
8831
|
|
|
8776
8832
|
// src/commands/dotnet/runInspectCode.ts
|
|
8777
8833
|
import { execSync as execSync24 } from "child_process";
|
|
8778
|
-
import { existsSync as existsSync29, readFileSync as readFileSync23, unlinkSync as
|
|
8834
|
+
import { existsSync as existsSync29, readFileSync as readFileSync23, unlinkSync as unlinkSync6 } from "fs";
|
|
8779
8835
|
import { tmpdir as tmpdir3 } from "os";
|
|
8780
8836
|
import path25 from "path";
|
|
8781
8837
|
import chalk102 from "chalk";
|
|
@@ -8811,7 +8867,7 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
8811
8867
|
process.exit(1);
|
|
8812
8868
|
}
|
|
8813
8869
|
const xml = readFileSync23(reportPath, "utf-8");
|
|
8814
|
-
|
|
8870
|
+
unlinkSync6(reportPath);
|
|
8815
8871
|
return xml;
|
|
8816
8872
|
}
|
|
8817
8873
|
|
|
@@ -8937,7 +8993,7 @@ function aggregateCommitters(authorLists) {
|
|
|
8937
8993
|
|
|
8938
8994
|
// src/shared/runGhGraphql.ts
|
|
8939
8995
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
8940
|
-
import { unlinkSync as
|
|
8996
|
+
import { unlinkSync as unlinkSync7, writeFileSync as writeFileSync18 } from "fs";
|
|
8941
8997
|
import { tmpdir as tmpdir4 } from "os";
|
|
8942
8998
|
import { join as join27 } from "path";
|
|
8943
8999
|
function buildArgs(queryFile, vars) {
|
|
@@ -8958,7 +9014,7 @@ function runGhGraphql(mutation, vars) {
|
|
|
8958
9014
|
if (result.status !== 0) throw new Error(result.stderr || result.stdout);
|
|
8959
9015
|
return result.stdout;
|
|
8960
9016
|
} finally {
|
|
8961
|
-
|
|
9017
|
+
unlinkSync7(queryFile);
|
|
8962
9018
|
}
|
|
8963
9019
|
}
|
|
8964
9020
|
|
|
@@ -9598,13 +9654,21 @@ async function reviewComments(number) {
|
|
|
9598
9654
|
|
|
9599
9655
|
// src/commands/registerLaunch.ts
|
|
9600
9656
|
function registerLaunch(program2) {
|
|
9601
|
-
program2.command("next").argument("[id]", "Backlog item ID to run first").description("Alias for backlog next").
|
|
9657
|
+
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(
|
|
9658
|
+
(id, opts) => next({ allowEdits: true, once: opts.once }, id)
|
|
9659
|
+
);
|
|
9602
9660
|
program2.command("draft").alias("feat").description(
|
|
9603
9661
|
"Launch Claude in /draft mode, chain into next on /next signal"
|
|
9604
|
-
).
|
|
9605
|
-
|
|
9662
|
+
).option("--once", "Exit when the initial task completes").action(
|
|
9663
|
+
(opts) => launchMode("draft", { once: opts.once })
|
|
9664
|
+
);
|
|
9665
|
+
program2.command("bug").description("Launch Claude in /bug mode, chain into next on /next signal").option("--once", "Exit when the initial task completes").action(
|
|
9666
|
+
(opts) => launchMode("bug", { once: opts.once })
|
|
9667
|
+
);
|
|
9606
9668
|
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));
|
|
9607
|
-
program2.command("refine").argument("[id]", "Backlog item ID").description("Launch Claude in /refine mode to refine a backlog item").
|
|
9669
|
+
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(
|
|
9670
|
+
(id, opts) => refine(id, { once: opts.once })
|
|
9671
|
+
);
|
|
9608
9672
|
}
|
|
9609
9673
|
|
|
9610
9674
|
// src/commands/registerList.ts
|
|
@@ -10244,12 +10308,12 @@ import { execSync as execSync32 } from "child_process";
|
|
|
10244
10308
|
|
|
10245
10309
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
10246
10310
|
import { execSync as execSync31 } from "child_process";
|
|
10247
|
-
import { unlinkSync as
|
|
10311
|
+
import { unlinkSync as unlinkSync9, writeFileSync as writeFileSync21 } from "fs";
|
|
10248
10312
|
import { tmpdir as tmpdir5 } from "os";
|
|
10249
10313
|
import { join as join32 } from "path";
|
|
10250
10314
|
|
|
10251
10315
|
// src/commands/prs/loadCommentsCache.ts
|
|
10252
|
-
import { existsSync as existsSync33, readFileSync as readFileSync28, unlinkSync as
|
|
10316
|
+
import { existsSync as existsSync33, readFileSync as readFileSync28, unlinkSync as unlinkSync8 } from "fs";
|
|
10253
10317
|
import { join as join31 } from "path";
|
|
10254
10318
|
import { parse as parse2 } from "yaml";
|
|
10255
10319
|
function getCachePath(prNumber) {
|
|
@@ -10266,7 +10330,7 @@ function loadCommentsCache(prNumber) {
|
|
|
10266
10330
|
function deleteCommentsCache(prNumber) {
|
|
10267
10331
|
const cachePath = getCachePath(prNumber);
|
|
10268
10332
|
if (existsSync33(cachePath)) {
|
|
10269
|
-
|
|
10333
|
+
unlinkSync8(cachePath);
|
|
10270
10334
|
console.log("No more unresolved line comments. Cache dropped.");
|
|
10271
10335
|
}
|
|
10272
10336
|
}
|
|
@@ -10288,7 +10352,7 @@ function resolveThread(threadId) {
|
|
|
10288
10352
|
{ stdio: ["inherit", "pipe", "inherit"] }
|
|
10289
10353
|
);
|
|
10290
10354
|
} finally {
|
|
10291
|
-
|
|
10355
|
+
unlinkSync9(queryFile);
|
|
10292
10356
|
}
|
|
10293
10357
|
}
|
|
10294
10358
|
function requireCache(prNumber) {
|
|
@@ -10368,7 +10432,7 @@ import { stringify } from "yaml";
|
|
|
10368
10432
|
|
|
10369
10433
|
// src/commands/prs/fetchThreadIds.ts
|
|
10370
10434
|
import { execSync as execSync33 } from "child_process";
|
|
10371
|
-
import { unlinkSync as
|
|
10435
|
+
import { unlinkSync as unlinkSync10, writeFileSync as writeFileSync22 } from "fs";
|
|
10372
10436
|
import { tmpdir as tmpdir6 } from "os";
|
|
10373
10437
|
import { join as join33 } from "path";
|
|
10374
10438
|
var THREAD_QUERY = `query($owner: String!, $repo: String!, $prNumber: Int!) { repository(owner: $owner, name: $repo) { pullRequest(number: $prNumber) { reviewThreads(first: 100) { nodes { id isResolved comments(first: 100) { nodes { databaseId } } } } } } }`;
|
|
@@ -10393,7 +10457,7 @@ function fetchThreadIds(org, repo, prNumber) {
|
|
|
10393
10457
|
}
|
|
10394
10458
|
return { threadMap, resolvedThreadIds };
|
|
10395
10459
|
} finally {
|
|
10396
|
-
|
|
10460
|
+
unlinkSync10(queryFile);
|
|
10397
10461
|
}
|
|
10398
10462
|
}
|
|
10399
10463
|
|
|
@@ -13301,10 +13365,10 @@ async function handlePostSynthesis(synthesisPath, options2) {
|
|
|
13301
13365
|
}
|
|
13302
13366
|
|
|
13303
13367
|
// src/commands/review/prepareReviewDir.ts
|
|
13304
|
-
import { existsSync as existsSync36, mkdirSync as mkdirSync11, unlinkSync as
|
|
13368
|
+
import { existsSync as existsSync36, mkdirSync as mkdirSync11, unlinkSync as unlinkSync11, writeFileSync as writeFileSync25 } from "fs";
|
|
13305
13369
|
function clearReviewFiles(paths) {
|
|
13306
13370
|
for (const path54 of [paths.claudePath, paths.codexPath, paths.synthesisPath]) {
|
|
13307
|
-
if (existsSync36(path54))
|
|
13371
|
+
if (existsSync36(path54)) unlinkSync11(path54);
|
|
13308
13372
|
}
|
|
13309
13373
|
}
|
|
13310
13374
|
function prepareReviewDir(paths, requestBody, force) {
|
|
@@ -13372,11 +13436,11 @@ async function runBacklogSession(synthesisPath) {
|
|
|
13372
13436
|
}
|
|
13373
13437
|
|
|
13374
13438
|
// src/commands/review/cachedReviewerResult.ts
|
|
13375
|
-
import { statSync as
|
|
13439
|
+
import { statSync as statSync3 } from "fs";
|
|
13376
13440
|
function cachedReviewerResult(name, outputPath) {
|
|
13377
13441
|
let size;
|
|
13378
13442
|
try {
|
|
13379
|
-
size =
|
|
13443
|
+
size = statSync3(outputPath).size;
|
|
13380
13444
|
} catch {
|
|
13381
13445
|
return null;
|
|
13382
13446
|
}
|
|
@@ -13589,7 +13653,7 @@ function printReviewerFailures(results) {
|
|
|
13589
13653
|
}
|
|
13590
13654
|
|
|
13591
13655
|
// src/commands/review/runAndSynthesise.ts
|
|
13592
|
-
import { existsSync as existsSync38, unlinkSync as
|
|
13656
|
+
import { existsSync as existsSync38, unlinkSync as unlinkSync13 } from "fs";
|
|
13593
13657
|
|
|
13594
13658
|
// src/commands/review/buildReviewerStdin.ts
|
|
13595
13659
|
var REVIEW_PROMPT = `You are acting as a reviewer for a proposed code change made by another engineer. The full review request \u2014 branch, base, changed files, and unified diff \u2014 is in request.md in the current working directory.
|
|
@@ -14007,7 +14071,7 @@ function resolveClaude(args) {
|
|
|
14007
14071
|
}
|
|
14008
14072
|
|
|
14009
14073
|
// src/commands/review/runCodexReviewer.ts
|
|
14010
|
-
import { existsSync as existsSync37, unlinkSync as
|
|
14074
|
+
import { existsSync as existsSync37, unlinkSync as unlinkSync12 } from "fs";
|
|
14011
14075
|
|
|
14012
14076
|
// src/commands/review/parseCodexEvent.ts
|
|
14013
14077
|
function isItemStarted(value) {
|
|
@@ -14062,7 +14126,7 @@ async function runCodexReviewer(spec) {
|
|
|
14062
14126
|
}
|
|
14063
14127
|
});
|
|
14064
14128
|
if (result.exitCode !== 0 && existsSync37(spec.outputPath)) {
|
|
14065
|
-
|
|
14129
|
+
unlinkSync12(spec.outputPath);
|
|
14066
14130
|
}
|
|
14067
14131
|
return finaliseReviewerRun({ ...spec, command }, spinner, result);
|
|
14068
14132
|
}
|
|
@@ -14210,7 +14274,7 @@ async function runAndSynthesise(args) {
|
|
|
14210
14274
|
return { ok: false, failures };
|
|
14211
14275
|
}
|
|
14212
14276
|
if (anyFresh && existsSync38(paths.synthesisPath)) {
|
|
14213
|
-
|
|
14277
|
+
unlinkSync13(paths.synthesisPath);
|
|
14214
14278
|
}
|
|
14215
14279
|
const synthesisResult = await synthesise(paths, { multi });
|
|
14216
14280
|
if (synthesisResult.exitCode !== 0) failures.push(synthesisResult);
|
|
@@ -14709,6 +14773,10 @@ function registerSignal(program2) {
|
|
|
14709
14773
|
writeSignal("next", id ? { id } : void 0);
|
|
14710
14774
|
console.log("Signal written.");
|
|
14711
14775
|
});
|
|
14776
|
+
signalCommand.command("done").description("Write a done signal to end a --once launch session").action(() => {
|
|
14777
|
+
writeSignal("done");
|
|
14778
|
+
console.log("Signal written.");
|
|
14779
|
+
});
|
|
14712
14780
|
}
|
|
14713
14781
|
|
|
14714
14782
|
// src/commands/sql/sqlAuth.ts
|
|
@@ -14981,7 +15049,7 @@ function registerSql(program2) {
|
|
|
14981
15049
|
}
|
|
14982
15050
|
|
|
14983
15051
|
// src/commands/transcript/shared.ts
|
|
14984
|
-
import { existsSync as existsSync39, readdirSync as readdirSync6, statSync as
|
|
15052
|
+
import { existsSync as existsSync39, readdirSync as readdirSync6, statSync as statSync4 } from "fs";
|
|
14985
15053
|
import { basename as basename6, join as join37, relative as relative2 } from "path";
|
|
14986
15054
|
import * as readline2 from "readline";
|
|
14987
15055
|
var DATE_PREFIX_REGEX = /^\d{4}-\d{2}-\d{2}/;
|
|
@@ -15001,7 +15069,7 @@ function collectFiles(dir, extension) {
|
|
|
15001
15069
|
const results = [];
|
|
15002
15070
|
for (const entry of readdirSync6(dir)) {
|
|
15003
15071
|
const fullPath = join37(dir, entry);
|
|
15004
|
-
if (
|
|
15072
|
+
if (statSync4(fullPath).isDirectory()) {
|
|
15005
15073
|
results.push(...collectFiles(fullPath, extension));
|
|
15006
15074
|
} else if (entry.endsWith(extension)) {
|
|
15007
15075
|
results.push(fullPath);
|
|
@@ -15875,7 +15943,7 @@ function status() {
|
|
|
15875
15943
|
}
|
|
15876
15944
|
|
|
15877
15945
|
// src/commands/voice/stop.ts
|
|
15878
|
-
import { existsSync as existsSync47, readFileSync as readFileSync37, unlinkSync as
|
|
15946
|
+
import { existsSync as existsSync47, readFileSync as readFileSync37, unlinkSync as unlinkSync14 } from "fs";
|
|
15879
15947
|
function stop2() {
|
|
15880
15948
|
if (!existsSync47(voicePaths.pid)) {
|
|
15881
15949
|
console.log("Voice daemon is not running (no PID file)");
|
|
@@ -15889,12 +15957,12 @@ function stop2() {
|
|
|
15889
15957
|
console.log(`Voice daemon (PID ${pid}) is not running`);
|
|
15890
15958
|
}
|
|
15891
15959
|
try {
|
|
15892
|
-
|
|
15960
|
+
unlinkSync14(voicePaths.pid);
|
|
15893
15961
|
} catch {
|
|
15894
15962
|
}
|
|
15895
15963
|
try {
|
|
15896
15964
|
const lockFile = getLockFile();
|
|
15897
|
-
if (existsSync47(lockFile))
|
|
15965
|
+
if (existsSync47(lockFile)) unlinkSync14(lockFile);
|
|
15898
15966
|
} catch {
|
|
15899
15967
|
}
|
|
15900
15968
|
console.log("Voice daemon stopped");
|
|
@@ -16116,7 +16184,7 @@ async function auth() {
|
|
|
16116
16184
|
|
|
16117
16185
|
// src/commands/roam/postRoamActivity.ts
|
|
16118
16186
|
import { execFileSync as execFileSync7 } from "child_process";
|
|
16119
|
-
import { readdirSync as readdirSync7, readFileSync as readFileSync38, statSync as
|
|
16187
|
+
import { readdirSync as readdirSync7, readFileSync as readFileSync38, statSync as statSync5 } from "fs";
|
|
16120
16188
|
import { join as join48 } from "path";
|
|
16121
16189
|
function findPortFile(roamDir) {
|
|
16122
16190
|
let entries;
|
|
@@ -16128,7 +16196,7 @@ function findPortFile(roamDir) {
|
|
|
16128
16196
|
const candidates = entries.filter((name) => /^roam-local-api(-[^.]+)?\.port$/.test(name)).map((name) => {
|
|
16129
16197
|
const path54 = join48(roamDir, name);
|
|
16130
16198
|
try {
|
|
16131
|
-
return { path: path54, mtimeMs:
|
|
16199
|
+
return { path: path54, mtimeMs: statSync5(path54).mtimeMs };
|
|
16132
16200
|
} catch {
|
|
16133
16201
|
return void 0;
|
|
16134
16202
|
}
|
|
@@ -16477,7 +16545,7 @@ function link2() {
|
|
|
16477
16545
|
}
|
|
16478
16546
|
|
|
16479
16547
|
// src/commands/run/remove.ts
|
|
16480
|
-
import { existsSync as existsSync49, unlinkSync as
|
|
16548
|
+
import { existsSync as existsSync49, unlinkSync as unlinkSync15 } from "fs";
|
|
16481
16549
|
import { join as join51 } from "path";
|
|
16482
16550
|
function findRemoveIndex() {
|
|
16483
16551
|
const idx = process.argv.indexOf("remove");
|
|
@@ -16495,7 +16563,7 @@ function parseRemoveName() {
|
|
|
16495
16563
|
function deleteCommandFile(name) {
|
|
16496
16564
|
const filePath = join51(".claude", "commands", `${name}.md`);
|
|
16497
16565
|
if (existsSync49(filePath)) {
|
|
16498
|
-
|
|
16566
|
+
unlinkSync15(filePath);
|
|
16499
16567
|
console.log(`Deleted command file: ${filePath}`);
|
|
16500
16568
|
}
|
|
16501
16569
|
}
|
|
@@ -16530,7 +16598,7 @@ function registerRun(program2) {
|
|
|
16530
16598
|
|
|
16531
16599
|
// src/commands/screenshot/index.ts
|
|
16532
16600
|
import { execSync as execSync47 } from "child_process";
|
|
16533
|
-
import { existsSync as existsSync50, mkdirSync as mkdirSync18, unlinkSync as
|
|
16601
|
+
import { existsSync as existsSync50, mkdirSync as mkdirSync18, unlinkSync as unlinkSync16, writeFileSync as writeFileSync31 } from "fs";
|
|
16534
16602
|
import { tmpdir as tmpdir7 } from "os";
|
|
16535
16603
|
import { join as join52, resolve as resolve13 } from "path";
|
|
16536
16604
|
import chalk156 from "chalk";
|
|
@@ -16677,7 +16745,7 @@ function runPowerShellScript(processName, outputPath) {
|
|
|
16677
16745
|
{ stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }
|
|
16678
16746
|
);
|
|
16679
16747
|
} finally {
|
|
16680
|
-
|
|
16748
|
+
unlinkSync16(scriptPath);
|
|
16681
16749
|
}
|
|
16682
16750
|
}
|
|
16683
16751
|
function screenshot(processName) {
|
|
@@ -16695,51 +16763,108 @@ function screenshot(processName) {
|
|
|
16695
16763
|
}
|
|
16696
16764
|
}
|
|
16697
16765
|
|
|
16698
|
-
// src/commands/sessions/daemon/
|
|
16699
|
-
import {
|
|
16700
|
-
|
|
16701
|
-
|
|
16702
|
-
async function daemonStatus() {
|
|
16703
|
-
let socket;
|
|
16766
|
+
// src/commands/sessions/daemon/listDaemonPids.ts
|
|
16767
|
+
import { execFileSync as execFileSync9 } from "child_process";
|
|
16768
|
+
function listDaemonPids() {
|
|
16769
|
+
if (process.platform === "win32") return [];
|
|
16704
16770
|
try {
|
|
16705
|
-
|
|
16771
|
+
const out = execFileSync9("ps", ["-eo", "pid=,args="], {
|
|
16772
|
+
encoding: "utf-8"
|
|
16773
|
+
});
|
|
16774
|
+
return out.split("\n").filter((line) => line.includes("assist") && / daemon run\b/.test(line)).map((line) => Number.parseInt(line.trim(), 10)).filter((pid) => Number.isInteger(pid));
|
|
16706
16775
|
} catch {
|
|
16707
|
-
|
|
16708
|
-
return;
|
|
16709
|
-
}
|
|
16710
|
-
const sessions = await readSessionList(socket);
|
|
16711
|
-
socket.destroy();
|
|
16712
|
-
console.log(`Sessions daemon is running${describePid()}`);
|
|
16713
|
-
if (sessions.length === 0) {
|
|
16714
|
-
console.log("No sessions");
|
|
16715
|
-
return;
|
|
16776
|
+
return [];
|
|
16716
16777
|
}
|
|
16717
|
-
for (const session of sessions) {
|
|
16718
|
-
const restored = session.restored === false ? " (not restored)" : "";
|
|
16719
|
-
console.log(` [${session.status}] ${session.name}${restored}`);
|
|
16720
|
-
}
|
|
16721
|
-
}
|
|
16722
|
-
function describePid() {
|
|
16723
|
-
if (!existsSync51(daemonPaths.pid)) return "";
|
|
16724
|
-
return ` (PID ${readFileSync39(daemonPaths.pid, "utf-8").trim()})`;
|
|
16725
16778
|
}
|
|
16726
|
-
|
|
16779
|
+
|
|
16780
|
+
// src/commands/sessions/daemon/queryDaemon.ts
|
|
16781
|
+
import { createInterface as createInterface4 } from "readline";
|
|
16782
|
+
var STATUS_TIMEOUT_MS = 5e3;
|
|
16783
|
+
function queryDaemon(socket) {
|
|
16784
|
+
socket.write(`${JSON.stringify({ type: "ping" })}
|
|
16785
|
+
`);
|
|
16727
16786
|
return new Promise((resolve16) => {
|
|
16728
|
-
const
|
|
16787
|
+
const result = { sessions: [] };
|
|
16788
|
+
const pending = /* @__PURE__ */ new Set(["sessions", "pong"]);
|
|
16789
|
+
const timer = setTimeout(() => resolve16(result), STATUS_TIMEOUT_MS);
|
|
16729
16790
|
const lines = createInterface4({ input: socket });
|
|
16730
16791
|
lines.on("error", () => {
|
|
16731
16792
|
});
|
|
16732
16793
|
lines.on("line", (line) => {
|
|
16733
|
-
|
|
16734
|
-
|
|
16735
|
-
if (data.type !== "sessions") return;
|
|
16794
|
+
applyLine(result, pending, line);
|
|
16795
|
+
if (pending.size === 0) {
|
|
16736
16796
|
clearTimeout(timer);
|
|
16737
|
-
resolve16(
|
|
16738
|
-
} catch {
|
|
16797
|
+
resolve16(result);
|
|
16739
16798
|
}
|
|
16740
16799
|
});
|
|
16741
16800
|
});
|
|
16742
16801
|
}
|
|
16802
|
+
function applyLine(result, pending, line) {
|
|
16803
|
+
try {
|
|
16804
|
+
const data = JSON.parse(line);
|
|
16805
|
+
if (data.type === "sessions") {
|
|
16806
|
+
result.sessions = data.sessions ?? [];
|
|
16807
|
+
pending.delete("sessions");
|
|
16808
|
+
} else if (data.type === "pong") {
|
|
16809
|
+
result.pid = data.pid;
|
|
16810
|
+
pending.delete("pong");
|
|
16811
|
+
}
|
|
16812
|
+
} catch {
|
|
16813
|
+
}
|
|
16814
|
+
}
|
|
16815
|
+
|
|
16816
|
+
// src/commands/sessions/daemon/reportStolenSocket.ts
|
|
16817
|
+
import { readFileSync as readFileSync39 } from "fs";
|
|
16818
|
+
function reportStolenSocket(socketPid) {
|
|
16819
|
+
if (!socketPid) return;
|
|
16820
|
+
const filePid = readPidFile();
|
|
16821
|
+
if (filePid === void 0 || filePid === socketPid) return;
|
|
16822
|
+
console.error(
|
|
16823
|
+
`Warning: daemon.pid records PID ${filePid} but the socket is owned by PID ${socketPid} (stolen socket)`
|
|
16824
|
+
);
|
|
16825
|
+
}
|
|
16826
|
+
function readPidFile() {
|
|
16827
|
+
try {
|
|
16828
|
+
const pid = Number.parseInt(
|
|
16829
|
+
readFileSync39(daemonPaths.pid, "utf-8").trim(),
|
|
16830
|
+
10
|
|
16831
|
+
);
|
|
16832
|
+
return Number.isInteger(pid) ? pid : void 0;
|
|
16833
|
+
} catch {
|
|
16834
|
+
return void 0;
|
|
16835
|
+
}
|
|
16836
|
+
}
|
|
16837
|
+
|
|
16838
|
+
// src/commands/sessions/daemon/daemonStatus.ts
|
|
16839
|
+
async function daemonStatus() {
|
|
16840
|
+
let socket;
|
|
16841
|
+
try {
|
|
16842
|
+
socket = await connectToDaemon();
|
|
16843
|
+
} catch {
|
|
16844
|
+
console.log("Sessions daemon is not running");
|
|
16845
|
+
reportStrays(listDaemonPids());
|
|
16846
|
+
return;
|
|
16847
|
+
}
|
|
16848
|
+
const { pid, sessions } = await queryDaemon(socket);
|
|
16849
|
+
socket.destroy();
|
|
16850
|
+
console.log(`Sessions daemon is running${pid ? ` (PID ${pid})` : ""}`);
|
|
16851
|
+
reportStolenSocket(pid);
|
|
16852
|
+
reportStrays(listDaemonPids().filter((p) => p !== pid));
|
|
16853
|
+
if (sessions.length === 0) {
|
|
16854
|
+
console.log("No sessions");
|
|
16855
|
+
return;
|
|
16856
|
+
}
|
|
16857
|
+
for (const session of sessions) {
|
|
16858
|
+
const restored = session.restored === false ? " (not restored)" : "";
|
|
16859
|
+
console.log(` [${session.status}] ${session.name}${restored}`);
|
|
16860
|
+
}
|
|
16861
|
+
}
|
|
16862
|
+
function reportStrays(pids) {
|
|
16863
|
+
if (pids.length === 0) return;
|
|
16864
|
+
console.error(
|
|
16865
|
+
`Warning: stray daemon process(es) detected: ${pids.join(", ")}`
|
|
16866
|
+
);
|
|
16867
|
+
}
|
|
16743
16868
|
|
|
16744
16869
|
// src/commands/sessions/daemon/stopDaemon.ts
|
|
16745
16870
|
var STOP_TIMEOUT_MS = 5e3;
|
|
@@ -16781,15 +16906,14 @@ function closedBeforeTimeout(socket) {
|
|
|
16781
16906
|
// src/commands/sessions/daemon/restartDaemon.ts
|
|
16782
16907
|
async function restartDaemon() {
|
|
16783
16908
|
await stopDaemon();
|
|
16784
|
-
await ensureDaemonRunning();
|
|
16909
|
+
await ensureDaemonRunning("daemon restart");
|
|
16785
16910
|
console.log(
|
|
16786
16911
|
"Sessions daemon restarted; previously running claude sessions will resume"
|
|
16787
16912
|
);
|
|
16788
16913
|
}
|
|
16789
16914
|
|
|
16790
16915
|
// src/commands/sessions/daemon/runDaemon.ts
|
|
16791
|
-
import {
|
|
16792
|
-
import * as net2 from "net";
|
|
16916
|
+
import { mkdirSync as mkdirSync19 } from "fs";
|
|
16793
16917
|
|
|
16794
16918
|
// src/commands/sessions/daemon/createAutoExit.ts
|
|
16795
16919
|
var DEFAULT_GRACE_MS = 6e4;
|
|
@@ -16805,137 +16929,9 @@ function createAutoExit(exit, graceMs = DEFAULT_GRACE_MS) {
|
|
|
16805
16929
|
};
|
|
16806
16930
|
}
|
|
16807
16931
|
|
|
16808
|
-
// src/commands/sessions/daemon/
|
|
16809
|
-
|
|
16810
|
-
|
|
16811
|
-
// src/commands/sessions/daemon/broadcast.ts
|
|
16812
|
-
function sendTo(client, msg) {
|
|
16813
|
-
client.send(JSON.stringify(msg));
|
|
16814
|
-
}
|
|
16815
|
-
function broadcast(clients, msg) {
|
|
16816
|
-
const json = JSON.stringify(msg);
|
|
16817
|
-
for (const client of clients) {
|
|
16818
|
-
client.send(json);
|
|
16819
|
-
}
|
|
16820
|
-
}
|
|
16821
|
-
|
|
16822
|
-
// src/commands/sessions/daemon/handleRunConfigs.ts
|
|
16823
|
-
function handleRunConfigs(client, cwd) {
|
|
16824
|
-
try {
|
|
16825
|
-
const { config, configDir } = loadConfigFrom(cwd);
|
|
16826
|
-
const configs = resolveRunConfigs(config.run, configDir);
|
|
16827
|
-
sendTo(client, {
|
|
16828
|
-
type: "run-configs",
|
|
16829
|
-
configs: configs.map(({ name, params }) => ({ name, params }))
|
|
16830
|
-
});
|
|
16831
|
-
} catch {
|
|
16832
|
-
sendTo(client, { type: "run-configs", configs: [] });
|
|
16833
|
-
}
|
|
16834
|
-
}
|
|
16835
|
-
|
|
16836
|
-
// src/commands/sessions/daemon/dispatchMessage.ts
|
|
16837
|
-
function sendCreated(client, id) {
|
|
16838
|
-
sendTo(client, { type: "created", sessionId: id });
|
|
16839
|
-
}
|
|
16840
|
-
function handleCreate(client, manager, data) {
|
|
16841
|
-
sendCreated(
|
|
16842
|
-
client,
|
|
16843
|
-
manager.spawn(
|
|
16844
|
-
data.prompt,
|
|
16845
|
-
data.cwd
|
|
16846
|
-
)
|
|
16847
|
-
);
|
|
16848
|
-
}
|
|
16849
|
-
function handleCreateRun(client, manager, data) {
|
|
16850
|
-
sendCreated(
|
|
16851
|
-
client,
|
|
16852
|
-
manager.spawnRun(
|
|
16853
|
-
data.runName,
|
|
16854
|
-
data.runArgs ?? [],
|
|
16855
|
-
data.cwd
|
|
16856
|
-
)
|
|
16857
|
-
);
|
|
16858
|
-
}
|
|
16859
|
-
function handleCreateAssist(client, manager, data) {
|
|
16860
|
-
sendCreated(
|
|
16861
|
-
client,
|
|
16862
|
-
manager.spawnAssist(
|
|
16863
|
-
data.assistArgs ?? [],
|
|
16864
|
-
data.cwd
|
|
16865
|
-
)
|
|
16866
|
-
);
|
|
16867
|
-
}
|
|
16868
|
-
function handleResume(client, manager, data) {
|
|
16869
|
-
sendCreated(
|
|
16870
|
-
client,
|
|
16871
|
-
manager.resume(
|
|
16872
|
-
data.sessionId,
|
|
16873
|
-
data.cwd,
|
|
16874
|
-
data.name
|
|
16875
|
-
)
|
|
16876
|
-
);
|
|
16877
|
-
}
|
|
16878
|
-
function runConfigs(client, _manager, data) {
|
|
16879
|
-
handleRunConfigs(client, data.cwd);
|
|
16880
|
-
}
|
|
16881
|
-
function handleHistory(client, manager) {
|
|
16882
|
-
manager.getHistory().then((history) => {
|
|
16883
|
-
sendTo(client, { type: "history", sessions: history });
|
|
16884
|
-
});
|
|
16885
|
-
}
|
|
16886
|
-
function handleShutdown(client, manager) {
|
|
16887
|
-
manager.shutdown();
|
|
16888
|
-
sendTo(client, { type: "shutting-down" });
|
|
16889
|
-
setImmediate(() => process.exit(0));
|
|
16890
|
-
}
|
|
16891
|
-
var handlers = {
|
|
16892
|
-
create: handleCreate,
|
|
16893
|
-
"create-run": handleCreateRun,
|
|
16894
|
-
"create-assist": handleCreateAssist,
|
|
16895
|
-
resume: handleResume,
|
|
16896
|
-
"run-configs": runConfigs,
|
|
16897
|
-
history: handleHistory,
|
|
16898
|
-
shutdown: handleShutdown,
|
|
16899
|
-
input: (_client, m, d) => m.writeToSession(d.sessionId, d.data),
|
|
16900
|
-
resize: (_client, m, d) => m.resizeSession(d.sessionId, d.cols, d.rows),
|
|
16901
|
-
retry: (_client, m, d) => m.retrySession(d.sessionId),
|
|
16902
|
-
dismiss: (_client, m, d) => m.dismissSession(d.sessionId)
|
|
16903
|
-
};
|
|
16904
|
-
function dispatchMessage(client, manager, data) {
|
|
16905
|
-
handlers[data.type]?.(client, manager, data);
|
|
16906
|
-
}
|
|
16907
|
-
|
|
16908
|
-
// src/commands/sessions/daemon/handleConnection.ts
|
|
16909
|
-
function handleConnection(socket, manager) {
|
|
16910
|
-
const client = {
|
|
16911
|
-
send: (data) => {
|
|
16912
|
-
if (socket.writable) socket.write(`${data}
|
|
16913
|
-
`);
|
|
16914
|
-
}
|
|
16915
|
-
};
|
|
16916
|
-
manager.addClient(client);
|
|
16917
|
-
const lines = createInterface5({ input: socket });
|
|
16918
|
-
lines.on("error", () => {
|
|
16919
|
-
});
|
|
16920
|
-
lines.on("line", (line) => {
|
|
16921
|
-
let data;
|
|
16922
|
-
try {
|
|
16923
|
-
data = JSON.parse(line);
|
|
16924
|
-
} catch {
|
|
16925
|
-
return;
|
|
16926
|
-
}
|
|
16927
|
-
try {
|
|
16928
|
-
dispatchMessage(client, manager, data);
|
|
16929
|
-
} catch (e) {
|
|
16930
|
-
sendTo(client, {
|
|
16931
|
-
type: "error",
|
|
16932
|
-
message: `${data.type} failed: ${e instanceof Error ? e.message : String(e)}`
|
|
16933
|
-
});
|
|
16934
|
-
}
|
|
16935
|
-
});
|
|
16936
|
-
socket.on("error", () => {
|
|
16937
|
-
});
|
|
16938
|
-
socket.on("close", () => manager.removeClient(client));
|
|
16932
|
+
// src/commands/sessions/daemon/daemonLog.ts
|
|
16933
|
+
function daemonLog(message) {
|
|
16934
|
+
console.log(`${(/* @__PURE__ */ new Date()).toISOString()} [${process.pid}] ${message}`);
|
|
16939
16935
|
}
|
|
16940
16936
|
|
|
16941
16937
|
// src/commands/sessions/shared/discoverSessions.ts
|
|
@@ -17053,6 +17049,17 @@ async function discoverSessions() {
|
|
|
17053
17049
|
return sessions;
|
|
17054
17050
|
}
|
|
17055
17051
|
|
|
17052
|
+
// src/commands/sessions/daemon/broadcast.ts
|
|
17053
|
+
function sendTo(client, msg) {
|
|
17054
|
+
client.send(JSON.stringify(msg));
|
|
17055
|
+
}
|
|
17056
|
+
function broadcast(clients, msg) {
|
|
17057
|
+
const json = JSON.stringify(msg);
|
|
17058
|
+
for (const client of clients) {
|
|
17059
|
+
client.send(json);
|
|
17060
|
+
}
|
|
17061
|
+
}
|
|
17062
|
+
|
|
17056
17063
|
// src/commands/sessions/daemon/repoPrefix.ts
|
|
17057
17064
|
import * as path47 from "path";
|
|
17058
17065
|
function repoPrefix(cwd) {
|
|
@@ -17064,7 +17071,7 @@ function repoPrefix(cwd) {
|
|
|
17064
17071
|
import * as pty from "node-pty";
|
|
17065
17072
|
|
|
17066
17073
|
// src/commands/sessions/daemon/ensureSpawnHelperExecutable.ts
|
|
17067
|
-
import { chmodSync, existsSync as
|
|
17074
|
+
import { chmodSync, existsSync as existsSync51, statSync as statSync6 } from "fs";
|
|
17068
17075
|
import { createRequire as createRequire3 } from "module";
|
|
17069
17076
|
import path48 from "path";
|
|
17070
17077
|
var require4 = createRequire3(import.meta.url);
|
|
@@ -17079,8 +17086,8 @@ function ensureSpawnHelperExecutable() {
|
|
|
17079
17086
|
`${process.platform}-${process.arch}`,
|
|
17080
17087
|
"spawn-helper"
|
|
17081
17088
|
);
|
|
17082
|
-
if (!
|
|
17083
|
-
const mode =
|
|
17089
|
+
if (!existsSync51(helper)) return;
|
|
17090
|
+
const mode = statSync6(helper).mode;
|
|
17084
17091
|
if ((mode & 73) === 0) chmodSync(helper, mode | 493);
|
|
17085
17092
|
}
|
|
17086
17093
|
|
|
@@ -17474,9 +17481,10 @@ var SessionManager = class {
|
|
|
17474
17481
|
shutdownSessions(this.sessions);
|
|
17475
17482
|
}
|
|
17476
17483
|
restore() {
|
|
17477
|
-
|
|
17484
|
+
return loadPersistedSessions().map((persisted) => {
|
|
17478
17485
|
this.add(restoreSession(String(this.nextId++), persisted));
|
|
17479
|
-
|
|
17486
|
+
return persisted.name;
|
|
17487
|
+
});
|
|
17480
17488
|
}
|
|
17481
17489
|
add(session) {
|
|
17482
17490
|
this.wire(session);
|
|
@@ -17538,31 +17546,231 @@ var SessionManager = class {
|
|
|
17538
17546
|
};
|
|
17539
17547
|
};
|
|
17540
17548
|
|
|
17549
|
+
// src/commands/sessions/daemon/startDaemonServer.ts
|
|
17550
|
+
import { unlinkSync as unlinkSync18 } from "fs";
|
|
17551
|
+
import * as net2 from "net";
|
|
17552
|
+
|
|
17553
|
+
// src/commands/sessions/daemon/handleConnection.ts
|
|
17554
|
+
import { createInterface as createInterface5 } from "readline";
|
|
17555
|
+
|
|
17556
|
+
// src/commands/sessions/daemon/handleRunConfigs.ts
|
|
17557
|
+
function handleRunConfigs(client, cwd) {
|
|
17558
|
+
try {
|
|
17559
|
+
const { config, configDir } = loadConfigFrom(cwd);
|
|
17560
|
+
const configs = resolveRunConfigs(config.run, configDir);
|
|
17561
|
+
sendTo(client, {
|
|
17562
|
+
type: "run-configs",
|
|
17563
|
+
configs: configs.map(({ name, params }) => ({ name, params }))
|
|
17564
|
+
});
|
|
17565
|
+
} catch {
|
|
17566
|
+
sendTo(client, { type: "run-configs", configs: [] });
|
|
17567
|
+
}
|
|
17568
|
+
}
|
|
17569
|
+
|
|
17570
|
+
// src/commands/sessions/daemon/dispatchMessage.ts
|
|
17571
|
+
function sendCreated(client, id) {
|
|
17572
|
+
sendTo(client, { type: "created", sessionId: id });
|
|
17573
|
+
}
|
|
17574
|
+
function handleCreate(client, manager, data) {
|
|
17575
|
+
sendCreated(
|
|
17576
|
+
client,
|
|
17577
|
+
manager.spawn(
|
|
17578
|
+
data.prompt,
|
|
17579
|
+
data.cwd
|
|
17580
|
+
)
|
|
17581
|
+
);
|
|
17582
|
+
}
|
|
17583
|
+
function handleCreateRun(client, manager, data) {
|
|
17584
|
+
sendCreated(
|
|
17585
|
+
client,
|
|
17586
|
+
manager.spawnRun(
|
|
17587
|
+
data.runName,
|
|
17588
|
+
data.runArgs ?? [],
|
|
17589
|
+
data.cwd
|
|
17590
|
+
)
|
|
17591
|
+
);
|
|
17592
|
+
}
|
|
17593
|
+
function handleCreateAssist(client, manager, data) {
|
|
17594
|
+
sendCreated(
|
|
17595
|
+
client,
|
|
17596
|
+
manager.spawnAssist(
|
|
17597
|
+
data.assistArgs ?? [],
|
|
17598
|
+
data.cwd
|
|
17599
|
+
)
|
|
17600
|
+
);
|
|
17601
|
+
}
|
|
17602
|
+
function handleResume(client, manager, data) {
|
|
17603
|
+
sendCreated(
|
|
17604
|
+
client,
|
|
17605
|
+
manager.resume(
|
|
17606
|
+
data.sessionId,
|
|
17607
|
+
data.cwd,
|
|
17608
|
+
data.name
|
|
17609
|
+
)
|
|
17610
|
+
);
|
|
17611
|
+
}
|
|
17612
|
+
function runConfigs(client, _manager, data) {
|
|
17613
|
+
handleRunConfigs(client, data.cwd);
|
|
17614
|
+
}
|
|
17615
|
+
function handleHistory(client, manager) {
|
|
17616
|
+
manager.getHistory().then((history) => {
|
|
17617
|
+
sendTo(client, { type: "history", sessions: history });
|
|
17618
|
+
});
|
|
17619
|
+
}
|
|
17620
|
+
function handleShutdown(client, manager) {
|
|
17621
|
+
manager.shutdown();
|
|
17622
|
+
sendTo(client, { type: "shutting-down" });
|
|
17623
|
+
setImmediate(() => process.exit(0));
|
|
17624
|
+
}
|
|
17625
|
+
var handlers = {
|
|
17626
|
+
ping: (client) => sendTo(client, { type: "pong", pid: process.pid }),
|
|
17627
|
+
create: handleCreate,
|
|
17628
|
+
"create-run": handleCreateRun,
|
|
17629
|
+
"create-assist": handleCreateAssist,
|
|
17630
|
+
resume: handleResume,
|
|
17631
|
+
"run-configs": runConfigs,
|
|
17632
|
+
history: handleHistory,
|
|
17633
|
+
shutdown: handleShutdown,
|
|
17634
|
+
input: (_client, m, d) => m.writeToSession(d.sessionId, d.data),
|
|
17635
|
+
resize: (_client, m, d) => m.resizeSession(d.sessionId, d.cols, d.rows),
|
|
17636
|
+
retry: (_client, m, d) => m.retrySession(d.sessionId),
|
|
17637
|
+
dismiss: (_client, m, d) => m.dismissSession(d.sessionId)
|
|
17638
|
+
};
|
|
17639
|
+
function dispatchMessage(client, manager, data) {
|
|
17640
|
+
handlers[data.type]?.(client, manager, data);
|
|
17641
|
+
}
|
|
17642
|
+
|
|
17643
|
+
// src/commands/sessions/daemon/handleConnection.ts
|
|
17644
|
+
function handleConnection(socket, manager) {
|
|
17645
|
+
const client = {
|
|
17646
|
+
send: (data) => {
|
|
17647
|
+
if (socket.writable) socket.write(`${data}
|
|
17648
|
+
`);
|
|
17649
|
+
}
|
|
17650
|
+
};
|
|
17651
|
+
manager.addClient(client);
|
|
17652
|
+
const lines = createInterface5({ input: socket });
|
|
17653
|
+
lines.on("error", () => {
|
|
17654
|
+
});
|
|
17655
|
+
lines.on("line", (line) => {
|
|
17656
|
+
let data;
|
|
17657
|
+
try {
|
|
17658
|
+
data = JSON.parse(line);
|
|
17659
|
+
} catch {
|
|
17660
|
+
return;
|
|
17661
|
+
}
|
|
17662
|
+
try {
|
|
17663
|
+
dispatchMessage(client, manager, data);
|
|
17664
|
+
} catch (e) {
|
|
17665
|
+
sendTo(client, {
|
|
17666
|
+
type: "error",
|
|
17667
|
+
message: `${data.type} failed: ${e instanceof Error ? e.message : String(e)}`
|
|
17668
|
+
});
|
|
17669
|
+
}
|
|
17670
|
+
});
|
|
17671
|
+
socket.on("error", () => {
|
|
17672
|
+
});
|
|
17673
|
+
socket.on("close", () => manager.removeClient(client));
|
|
17674
|
+
}
|
|
17675
|
+
|
|
17676
|
+
// src/commands/sessions/daemon/onListening.ts
|
|
17677
|
+
import { unlinkSync as unlinkSync17, writeFileSync as writeFileSync32 } from "fs";
|
|
17678
|
+
|
|
17679
|
+
// src/commands/sessions/daemon/startPidFileWatchdog.ts
|
|
17680
|
+
import { readFileSync as readFileSync40 } from "fs";
|
|
17681
|
+
var WATCHDOG_INTERVAL_MS = 5e3;
|
|
17682
|
+
function startPidFileWatchdog(onLost, intervalMs = WATCHDOG_INTERVAL_MS) {
|
|
17683
|
+
const timer = setInterval(() => {
|
|
17684
|
+
if (!ownsPidFile()) onLost();
|
|
17685
|
+
}, intervalMs);
|
|
17686
|
+
timer.unref();
|
|
17687
|
+
return timer;
|
|
17688
|
+
}
|
|
17689
|
+
function ownsPidFile() {
|
|
17690
|
+
try {
|
|
17691
|
+
return readFileSync40(daemonPaths.pid, "utf-8").trim() === String(process.pid);
|
|
17692
|
+
} catch {
|
|
17693
|
+
return false;
|
|
17694
|
+
}
|
|
17695
|
+
}
|
|
17696
|
+
|
|
17697
|
+
// src/commands/sessions/daemon/onListening.ts
|
|
17698
|
+
function onListening(manager, checkAutoExit) {
|
|
17699
|
+
writeFileSync32(daemonPaths.pid, String(process.pid));
|
|
17700
|
+
startPidFileWatchdog(() => {
|
|
17701
|
+
daemonLog("lost daemon.pid ownership; shutting down sessions and exiting");
|
|
17702
|
+
manager.shutdown();
|
|
17703
|
+
process.exit(0);
|
|
17704
|
+
});
|
|
17705
|
+
process.on("exit", cleanupOwnedFiles);
|
|
17706
|
+
const restored = manager.restore();
|
|
17707
|
+
daemonLog(
|
|
17708
|
+
restored.length > 0 ? `restored ${restored.length} session(s): ${restored.join(", ")}` : "no persisted sessions to restore"
|
|
17709
|
+
);
|
|
17710
|
+
daemonLog(`listening on ${daemonPaths.socket}`);
|
|
17711
|
+
checkAutoExit(manager.isIdle());
|
|
17712
|
+
}
|
|
17713
|
+
function cleanupOwnedFiles() {
|
|
17714
|
+
if (!ownsPidFile()) return;
|
|
17715
|
+
try {
|
|
17716
|
+
unlinkSync17(daemonPaths.pid);
|
|
17717
|
+
} catch {
|
|
17718
|
+
}
|
|
17719
|
+
if (process.platform !== "win32") {
|
|
17720
|
+
try {
|
|
17721
|
+
unlinkSync17(daemonPaths.socket);
|
|
17722
|
+
} catch {
|
|
17723
|
+
}
|
|
17724
|
+
}
|
|
17725
|
+
}
|
|
17726
|
+
|
|
17727
|
+
// src/commands/sessions/daemon/startDaemonServer.ts
|
|
17728
|
+
function startDaemonServer(manager, checkAutoExit) {
|
|
17729
|
+
const server = net2.createServer(
|
|
17730
|
+
(socket) => handleConnection(socket, manager)
|
|
17731
|
+
);
|
|
17732
|
+
let retried = false;
|
|
17733
|
+
server.on("error", (e) => {
|
|
17734
|
+
if (e.code !== "EADDRINUSE" || retried) {
|
|
17735
|
+
daemonLog(`server error: ${e.message}; exiting`);
|
|
17736
|
+
process.exit(1);
|
|
17737
|
+
}
|
|
17738
|
+
retried = true;
|
|
17739
|
+
void recoverFromAddrInUse(server, manager, checkAutoExit);
|
|
17740
|
+
});
|
|
17741
|
+
server.listen(daemonPaths.socket, () => onListening(manager, checkAutoExit));
|
|
17742
|
+
}
|
|
17743
|
+
async function recoverFromAddrInUse(server, manager, checkAutoExit) {
|
|
17744
|
+
if (await isDaemonRunning()) {
|
|
17745
|
+
daemonLog("another daemon owns the socket; exiting");
|
|
17746
|
+
process.exit(1);
|
|
17747
|
+
}
|
|
17748
|
+
daemonLog("removing stale socket left by a crashed daemon");
|
|
17749
|
+
if (process.platform !== "win32") {
|
|
17750
|
+
try {
|
|
17751
|
+
unlinkSync18(daemonPaths.socket);
|
|
17752
|
+
} catch {
|
|
17753
|
+
}
|
|
17754
|
+
}
|
|
17755
|
+
server.listen(daemonPaths.socket, () => onListening(manager, checkAutoExit));
|
|
17756
|
+
}
|
|
17757
|
+
|
|
17541
17758
|
// src/commands/sessions/daemon/runDaemon.ts
|
|
17542
17759
|
async function runDaemon() {
|
|
17543
17760
|
mkdirSync19(daemonPaths.dir, { recursive: true });
|
|
17761
|
+
daemonLog(
|
|
17762
|
+
`starting (reason: ${process.env.ASSIST_DAEMON_SPAWN_REASON ?? "manual"})`
|
|
17763
|
+
);
|
|
17544
17764
|
if (await isDaemonRunning()) {
|
|
17545
|
-
|
|
17765
|
+
daemonLog("already running; exiting");
|
|
17546
17766
|
process.exitCode = 1;
|
|
17547
17767
|
return;
|
|
17548
17768
|
}
|
|
17549
|
-
if (process.platform !== "win32" && existsSync53(daemonPaths.socket)) {
|
|
17550
|
-
unlinkSync16(daemonPaths.socket);
|
|
17551
|
-
}
|
|
17552
17769
|
const checkAutoExit = createAutoExit(() => {
|
|
17553
|
-
|
|
17770
|
+
daemonLog("no sessions and no connected server; exiting");
|
|
17554
17771
|
process.exit(0);
|
|
17555
17772
|
});
|
|
17556
|
-
|
|
17557
|
-
manager.restore();
|
|
17558
|
-
const server = net2.createServer(
|
|
17559
|
-
(socket) => handleConnection(socket, manager)
|
|
17560
|
-
);
|
|
17561
|
-
server.listen(daemonPaths.socket, () => {
|
|
17562
|
-
writeFileSync32(daemonPaths.pid, String(process.pid));
|
|
17563
|
-
console.log(`Sessions daemon listening on ${daemonPaths.socket}`);
|
|
17564
|
-
checkAutoExit(manager.isIdle());
|
|
17565
|
-
});
|
|
17773
|
+
startDaemonServer(new SessionManager(checkAutoExit), checkAutoExit);
|
|
17566
17774
|
}
|
|
17567
17775
|
|
|
17568
17776
|
// src/commands/sessions/daemon/registerDaemon.ts
|
|
@@ -17571,7 +17779,9 @@ function registerDaemon(program2) {
|
|
|
17571
17779
|
cmd.command("run").description(
|
|
17572
17780
|
"Run the sessions daemon in the foreground (auto-spawned by assist sessions)"
|
|
17573
17781
|
).action(runDaemon);
|
|
17574
|
-
cmd.command("status").description(
|
|
17782
|
+
cmd.command("status").description(
|
|
17783
|
+
"Show sessions daemon status, live sessions, and any stray daemon processes"
|
|
17784
|
+
).action(daemonStatus);
|
|
17575
17785
|
cmd.command("stop").description(
|
|
17576
17786
|
"Stop the sessions daemon; running claude sessions resume on next start"
|
|
17577
17787
|
).action(stopDaemon);
|
|
@@ -17598,7 +17808,7 @@ function summaryPathFor(jsonlPath2) {
|
|
|
17598
17808
|
}
|
|
17599
17809
|
|
|
17600
17810
|
// src/commands/sessions/summarise/summariseSession.ts
|
|
17601
|
-
import { execFileSync as
|
|
17811
|
+
import { execFileSync as execFileSync10 } from "child_process";
|
|
17602
17812
|
|
|
17603
17813
|
// src/commands/sessions/summarise/iterateUserMessages.ts
|
|
17604
17814
|
import * as fs28 from "fs";
|
|
@@ -17675,7 +17885,7 @@ function summariseSession(jsonlPath2) {
|
|
|
17675
17885
|
}
|
|
17676
17886
|
const prompt = buildPrompt2(firstMessage, backlogIds);
|
|
17677
17887
|
try {
|
|
17678
|
-
const output =
|
|
17888
|
+
const output = execFileSync10("claude", ["-p", "--model", "haiku", prompt], {
|
|
17679
17889
|
encoding: "utf8",
|
|
17680
17890
|
timeout: 3e4,
|
|
17681
17891
|
stdio: ["ignore", "pipe", "ignore"]
|