@staff0rd/assist 0.245.0 → 0.245.2
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 +2 -2
- package/dist/commands/sessions/web/bundle.js +40 -40
- package/dist/index.js +419 -227
- 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.245.
|
|
9
|
+
version: "0.245.2",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -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",
|
|
@@ -4926,7 +4976,7 @@ import chalk51 from "chalk";
|
|
|
4926
4976
|
|
|
4927
4977
|
// src/commands/backlog/add/shared.ts
|
|
4928
4978
|
import { spawnSync } from "child_process";
|
|
4929
|
-
import { mkdtempSync, readFileSync as readFileSync14, unlinkSync as
|
|
4979
|
+
import { mkdtempSync, readFileSync as readFileSync14, unlinkSync as unlinkSync5, writeFileSync as writeFileSync13 } from "fs";
|
|
4930
4980
|
import { tmpdir } from "os";
|
|
4931
4981
|
import { join as join17 } from "path";
|
|
4932
4982
|
import enquirer6 from "enquirer";
|
|
@@ -4973,11 +5023,11 @@ function openEditor() {
|
|
|
4973
5023
|
writeFileSync13(filePath, "");
|
|
4974
5024
|
const result = spawnSync(editor, [filePath], { stdio: "inherit" });
|
|
4975
5025
|
if (result.status !== 0) {
|
|
4976
|
-
|
|
5026
|
+
unlinkSync5(filePath);
|
|
4977
5027
|
return void 0;
|
|
4978
5028
|
}
|
|
4979
5029
|
const content = readFileSync14(filePath, "utf-8").trim();
|
|
4980
|
-
|
|
5030
|
+
unlinkSync5(filePath);
|
|
4981
5031
|
return content || void 0;
|
|
4982
5032
|
}
|
|
4983
5033
|
async function promptAcceptanceCriteria() {
|
|
@@ -8306,7 +8356,7 @@ function registerDevlog(program2) {
|
|
|
8306
8356
|
}
|
|
8307
8357
|
|
|
8308
8358
|
// src/commands/dotnet/checkBuildLocks.ts
|
|
8309
|
-
import { closeSync, openSync as openSync2, readdirSync as readdirSync2 } from "fs";
|
|
8359
|
+
import { closeSync as closeSync2, openSync as openSync2, readdirSync as readdirSync2 } from "fs";
|
|
8310
8360
|
import { join as join25 } from "path";
|
|
8311
8361
|
import chalk95 from "chalk";
|
|
8312
8362
|
|
|
@@ -8338,7 +8388,7 @@ function isLockedDll(debugDir) {
|
|
|
8338
8388
|
const dllPath = join25(debugDir, file);
|
|
8339
8389
|
try {
|
|
8340
8390
|
const fd = openSync2(dllPath, "r+");
|
|
8341
|
-
|
|
8391
|
+
closeSync2(fd);
|
|
8342
8392
|
} catch {
|
|
8343
8393
|
return dllPath;
|
|
8344
8394
|
}
|
|
@@ -8428,7 +8478,7 @@ function collectAllDeps(node) {
|
|
|
8428
8478
|
}
|
|
8429
8479
|
|
|
8430
8480
|
// src/commands/dotnet/findContainingSolutions.ts
|
|
8431
|
-
import { readdirSync as readdirSync3, readFileSync as readFileSync22, statSync } from "fs";
|
|
8481
|
+
import { readdirSync as readdirSync3, readFileSync as readFileSync22, statSync as statSync2 } from "fs";
|
|
8432
8482
|
import path22 from "path";
|
|
8433
8483
|
function findSlnFiles(dir, maxDepth, depth = 0) {
|
|
8434
8484
|
if (depth > maxDepth) return [];
|
|
@@ -8444,7 +8494,7 @@ function findSlnFiles(dir, maxDepth, depth = 0) {
|
|
|
8444
8494
|
continue;
|
|
8445
8495
|
const full = path22.join(dir, entry);
|
|
8446
8496
|
try {
|
|
8447
|
-
const stat =
|
|
8497
|
+
const stat = statSync2(full);
|
|
8448
8498
|
if (stat.isFile() && entry.endsWith(".sln")) {
|
|
8449
8499
|
results.push(full);
|
|
8450
8500
|
} else if (stat.isDirectory()) {
|
|
@@ -8781,7 +8831,7 @@ function parseInspectReport(json) {
|
|
|
8781
8831
|
|
|
8782
8832
|
// src/commands/dotnet/runInspectCode.ts
|
|
8783
8833
|
import { execSync as execSync24 } from "child_process";
|
|
8784
|
-
import { existsSync as existsSync29, readFileSync as readFileSync23, unlinkSync as
|
|
8834
|
+
import { existsSync as existsSync29, readFileSync as readFileSync23, unlinkSync as unlinkSync6 } from "fs";
|
|
8785
8835
|
import { tmpdir as tmpdir3 } from "os";
|
|
8786
8836
|
import path25 from "path";
|
|
8787
8837
|
import chalk102 from "chalk";
|
|
@@ -8817,7 +8867,7 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
8817
8867
|
process.exit(1);
|
|
8818
8868
|
}
|
|
8819
8869
|
const xml = readFileSync23(reportPath, "utf-8");
|
|
8820
|
-
|
|
8870
|
+
unlinkSync6(reportPath);
|
|
8821
8871
|
return xml;
|
|
8822
8872
|
}
|
|
8823
8873
|
|
|
@@ -8943,7 +8993,7 @@ function aggregateCommitters(authorLists) {
|
|
|
8943
8993
|
|
|
8944
8994
|
// src/shared/runGhGraphql.ts
|
|
8945
8995
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
8946
|
-
import { unlinkSync as
|
|
8996
|
+
import { unlinkSync as unlinkSync7, writeFileSync as writeFileSync18 } from "fs";
|
|
8947
8997
|
import { tmpdir as tmpdir4 } from "os";
|
|
8948
8998
|
import { join as join27 } from "path";
|
|
8949
8999
|
function buildArgs(queryFile, vars) {
|
|
@@ -8964,7 +9014,7 @@ function runGhGraphql(mutation, vars) {
|
|
|
8964
9014
|
if (result.status !== 0) throw new Error(result.stderr || result.stdout);
|
|
8965
9015
|
return result.stdout;
|
|
8966
9016
|
} finally {
|
|
8967
|
-
|
|
9017
|
+
unlinkSync7(queryFile);
|
|
8968
9018
|
}
|
|
8969
9019
|
}
|
|
8970
9020
|
|
|
@@ -10258,12 +10308,12 @@ import { execSync as execSync32 } from "child_process";
|
|
|
10258
10308
|
|
|
10259
10309
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
10260
10310
|
import { execSync as execSync31 } from "child_process";
|
|
10261
|
-
import { unlinkSync as
|
|
10311
|
+
import { unlinkSync as unlinkSync9, writeFileSync as writeFileSync21 } from "fs";
|
|
10262
10312
|
import { tmpdir as tmpdir5 } from "os";
|
|
10263
10313
|
import { join as join32 } from "path";
|
|
10264
10314
|
|
|
10265
10315
|
// src/commands/prs/loadCommentsCache.ts
|
|
10266
|
-
import { existsSync as existsSync33, readFileSync as readFileSync28, unlinkSync as
|
|
10316
|
+
import { existsSync as existsSync33, readFileSync as readFileSync28, unlinkSync as unlinkSync8 } from "fs";
|
|
10267
10317
|
import { join as join31 } from "path";
|
|
10268
10318
|
import { parse as parse2 } from "yaml";
|
|
10269
10319
|
function getCachePath(prNumber) {
|
|
@@ -10280,7 +10330,7 @@ function loadCommentsCache(prNumber) {
|
|
|
10280
10330
|
function deleteCommentsCache(prNumber) {
|
|
10281
10331
|
const cachePath = getCachePath(prNumber);
|
|
10282
10332
|
if (existsSync33(cachePath)) {
|
|
10283
|
-
|
|
10333
|
+
unlinkSync8(cachePath);
|
|
10284
10334
|
console.log("No more unresolved line comments. Cache dropped.");
|
|
10285
10335
|
}
|
|
10286
10336
|
}
|
|
@@ -10302,7 +10352,7 @@ function resolveThread(threadId) {
|
|
|
10302
10352
|
{ stdio: ["inherit", "pipe", "inherit"] }
|
|
10303
10353
|
);
|
|
10304
10354
|
} finally {
|
|
10305
|
-
|
|
10355
|
+
unlinkSync9(queryFile);
|
|
10306
10356
|
}
|
|
10307
10357
|
}
|
|
10308
10358
|
function requireCache(prNumber) {
|
|
@@ -10382,7 +10432,7 @@ import { stringify } from "yaml";
|
|
|
10382
10432
|
|
|
10383
10433
|
// src/commands/prs/fetchThreadIds.ts
|
|
10384
10434
|
import { execSync as execSync33 } from "child_process";
|
|
10385
|
-
import { unlinkSync as
|
|
10435
|
+
import { unlinkSync as unlinkSync10, writeFileSync as writeFileSync22 } from "fs";
|
|
10386
10436
|
import { tmpdir as tmpdir6 } from "os";
|
|
10387
10437
|
import { join as join33 } from "path";
|
|
10388
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 } } } } } } }`;
|
|
@@ -10407,7 +10457,7 @@ function fetchThreadIds(org, repo, prNumber) {
|
|
|
10407
10457
|
}
|
|
10408
10458
|
return { threadMap, resolvedThreadIds };
|
|
10409
10459
|
} finally {
|
|
10410
|
-
|
|
10460
|
+
unlinkSync10(queryFile);
|
|
10411
10461
|
}
|
|
10412
10462
|
}
|
|
10413
10463
|
|
|
@@ -13315,10 +13365,10 @@ async function handlePostSynthesis(synthesisPath, options2) {
|
|
|
13315
13365
|
}
|
|
13316
13366
|
|
|
13317
13367
|
// src/commands/review/prepareReviewDir.ts
|
|
13318
|
-
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";
|
|
13319
13369
|
function clearReviewFiles(paths) {
|
|
13320
13370
|
for (const path54 of [paths.claudePath, paths.codexPath, paths.synthesisPath]) {
|
|
13321
|
-
if (existsSync36(path54))
|
|
13371
|
+
if (existsSync36(path54)) unlinkSync11(path54);
|
|
13322
13372
|
}
|
|
13323
13373
|
}
|
|
13324
13374
|
function prepareReviewDir(paths, requestBody, force) {
|
|
@@ -13386,11 +13436,11 @@ async function runBacklogSession(synthesisPath) {
|
|
|
13386
13436
|
}
|
|
13387
13437
|
|
|
13388
13438
|
// src/commands/review/cachedReviewerResult.ts
|
|
13389
|
-
import { statSync as
|
|
13439
|
+
import { statSync as statSync3 } from "fs";
|
|
13390
13440
|
function cachedReviewerResult(name, outputPath) {
|
|
13391
13441
|
let size;
|
|
13392
13442
|
try {
|
|
13393
|
-
size =
|
|
13443
|
+
size = statSync3(outputPath).size;
|
|
13394
13444
|
} catch {
|
|
13395
13445
|
return null;
|
|
13396
13446
|
}
|
|
@@ -13603,7 +13653,7 @@ function printReviewerFailures(results) {
|
|
|
13603
13653
|
}
|
|
13604
13654
|
|
|
13605
13655
|
// src/commands/review/runAndSynthesise.ts
|
|
13606
|
-
import { existsSync as existsSync38, unlinkSync as
|
|
13656
|
+
import { existsSync as existsSync38, unlinkSync as unlinkSync13 } from "fs";
|
|
13607
13657
|
|
|
13608
13658
|
// src/commands/review/buildReviewerStdin.ts
|
|
13609
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.
|
|
@@ -14021,7 +14071,7 @@ function resolveClaude(args) {
|
|
|
14021
14071
|
}
|
|
14022
14072
|
|
|
14023
14073
|
// src/commands/review/runCodexReviewer.ts
|
|
14024
|
-
import { existsSync as existsSync37, unlinkSync as
|
|
14074
|
+
import { existsSync as existsSync37, unlinkSync as unlinkSync12 } from "fs";
|
|
14025
14075
|
|
|
14026
14076
|
// src/commands/review/parseCodexEvent.ts
|
|
14027
14077
|
function isItemStarted(value) {
|
|
@@ -14076,7 +14126,7 @@ async function runCodexReviewer(spec) {
|
|
|
14076
14126
|
}
|
|
14077
14127
|
});
|
|
14078
14128
|
if (result.exitCode !== 0 && existsSync37(spec.outputPath)) {
|
|
14079
|
-
|
|
14129
|
+
unlinkSync12(spec.outputPath);
|
|
14080
14130
|
}
|
|
14081
14131
|
return finaliseReviewerRun({ ...spec, command }, spinner, result);
|
|
14082
14132
|
}
|
|
@@ -14224,7 +14274,7 @@ async function runAndSynthesise(args) {
|
|
|
14224
14274
|
return { ok: false, failures };
|
|
14225
14275
|
}
|
|
14226
14276
|
if (anyFresh && existsSync38(paths.synthesisPath)) {
|
|
14227
|
-
|
|
14277
|
+
unlinkSync13(paths.synthesisPath);
|
|
14228
14278
|
}
|
|
14229
14279
|
const synthesisResult = await synthesise(paths, { multi });
|
|
14230
14280
|
if (synthesisResult.exitCode !== 0) failures.push(synthesisResult);
|
|
@@ -14999,7 +15049,7 @@ function registerSql(program2) {
|
|
|
14999
15049
|
}
|
|
15000
15050
|
|
|
15001
15051
|
// src/commands/transcript/shared.ts
|
|
15002
|
-
import { existsSync as existsSync39, readdirSync as readdirSync6, statSync as
|
|
15052
|
+
import { existsSync as existsSync39, readdirSync as readdirSync6, statSync as statSync4 } from "fs";
|
|
15003
15053
|
import { basename as basename6, join as join37, relative as relative2 } from "path";
|
|
15004
15054
|
import * as readline2 from "readline";
|
|
15005
15055
|
var DATE_PREFIX_REGEX = /^\d{4}-\d{2}-\d{2}/;
|
|
@@ -15019,7 +15069,7 @@ function collectFiles(dir, extension) {
|
|
|
15019
15069
|
const results = [];
|
|
15020
15070
|
for (const entry of readdirSync6(dir)) {
|
|
15021
15071
|
const fullPath = join37(dir, entry);
|
|
15022
|
-
if (
|
|
15072
|
+
if (statSync4(fullPath).isDirectory()) {
|
|
15023
15073
|
results.push(...collectFiles(fullPath, extension));
|
|
15024
15074
|
} else if (entry.endsWith(extension)) {
|
|
15025
15075
|
results.push(fullPath);
|
|
@@ -15893,7 +15943,7 @@ function status() {
|
|
|
15893
15943
|
}
|
|
15894
15944
|
|
|
15895
15945
|
// src/commands/voice/stop.ts
|
|
15896
|
-
import { existsSync as existsSync47, readFileSync as readFileSync37, unlinkSync as
|
|
15946
|
+
import { existsSync as existsSync47, readFileSync as readFileSync37, unlinkSync as unlinkSync14 } from "fs";
|
|
15897
15947
|
function stop2() {
|
|
15898
15948
|
if (!existsSync47(voicePaths.pid)) {
|
|
15899
15949
|
console.log("Voice daemon is not running (no PID file)");
|
|
@@ -15907,12 +15957,12 @@ function stop2() {
|
|
|
15907
15957
|
console.log(`Voice daemon (PID ${pid}) is not running`);
|
|
15908
15958
|
}
|
|
15909
15959
|
try {
|
|
15910
|
-
|
|
15960
|
+
unlinkSync14(voicePaths.pid);
|
|
15911
15961
|
} catch {
|
|
15912
15962
|
}
|
|
15913
15963
|
try {
|
|
15914
15964
|
const lockFile = getLockFile();
|
|
15915
|
-
if (existsSync47(lockFile))
|
|
15965
|
+
if (existsSync47(lockFile)) unlinkSync14(lockFile);
|
|
15916
15966
|
} catch {
|
|
15917
15967
|
}
|
|
15918
15968
|
console.log("Voice daemon stopped");
|
|
@@ -16134,7 +16184,7 @@ async function auth() {
|
|
|
16134
16184
|
|
|
16135
16185
|
// src/commands/roam/postRoamActivity.ts
|
|
16136
16186
|
import { execFileSync as execFileSync7 } from "child_process";
|
|
16137
|
-
import { readdirSync as readdirSync7, readFileSync as readFileSync38, statSync as
|
|
16187
|
+
import { readdirSync as readdirSync7, readFileSync as readFileSync38, statSync as statSync5 } from "fs";
|
|
16138
16188
|
import { join as join48 } from "path";
|
|
16139
16189
|
function findPortFile(roamDir) {
|
|
16140
16190
|
let entries;
|
|
@@ -16146,7 +16196,7 @@ function findPortFile(roamDir) {
|
|
|
16146
16196
|
const candidates = entries.filter((name) => /^roam-local-api(-[^.]+)?\.port$/.test(name)).map((name) => {
|
|
16147
16197
|
const path54 = join48(roamDir, name);
|
|
16148
16198
|
try {
|
|
16149
|
-
return { path: path54, mtimeMs:
|
|
16199
|
+
return { path: path54, mtimeMs: statSync5(path54).mtimeMs };
|
|
16150
16200
|
} catch {
|
|
16151
16201
|
return void 0;
|
|
16152
16202
|
}
|
|
@@ -16495,7 +16545,7 @@ function link2() {
|
|
|
16495
16545
|
}
|
|
16496
16546
|
|
|
16497
16547
|
// src/commands/run/remove.ts
|
|
16498
|
-
import { existsSync as existsSync49, unlinkSync as
|
|
16548
|
+
import { existsSync as existsSync49, unlinkSync as unlinkSync15 } from "fs";
|
|
16499
16549
|
import { join as join51 } from "path";
|
|
16500
16550
|
function findRemoveIndex() {
|
|
16501
16551
|
const idx = process.argv.indexOf("remove");
|
|
@@ -16513,7 +16563,7 @@ function parseRemoveName() {
|
|
|
16513
16563
|
function deleteCommandFile(name) {
|
|
16514
16564
|
const filePath = join51(".claude", "commands", `${name}.md`);
|
|
16515
16565
|
if (existsSync49(filePath)) {
|
|
16516
|
-
|
|
16566
|
+
unlinkSync15(filePath);
|
|
16517
16567
|
console.log(`Deleted command file: ${filePath}`);
|
|
16518
16568
|
}
|
|
16519
16569
|
}
|
|
@@ -16548,7 +16598,7 @@ function registerRun(program2) {
|
|
|
16548
16598
|
|
|
16549
16599
|
// src/commands/screenshot/index.ts
|
|
16550
16600
|
import { execSync as execSync47 } from "child_process";
|
|
16551
|
-
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";
|
|
16552
16602
|
import { tmpdir as tmpdir7 } from "os";
|
|
16553
16603
|
import { join as join52, resolve as resolve13 } from "path";
|
|
16554
16604
|
import chalk156 from "chalk";
|
|
@@ -16695,7 +16745,7 @@ function runPowerShellScript(processName, outputPath) {
|
|
|
16695
16745
|
{ stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }
|
|
16696
16746
|
);
|
|
16697
16747
|
} finally {
|
|
16698
|
-
|
|
16748
|
+
unlinkSync16(scriptPath);
|
|
16699
16749
|
}
|
|
16700
16750
|
}
|
|
16701
16751
|
function screenshot(processName) {
|
|
@@ -16713,21 +16763,93 @@ function screenshot(processName) {
|
|
|
16713
16763
|
}
|
|
16714
16764
|
}
|
|
16715
16765
|
|
|
16716
|
-
// src/commands/sessions/daemon/
|
|
16717
|
-
import {
|
|
16766
|
+
// src/commands/sessions/daemon/listDaemonPids.ts
|
|
16767
|
+
import { execFileSync as execFileSync9 } from "child_process";
|
|
16768
|
+
function listDaemonPids() {
|
|
16769
|
+
if (process.platform === "win32") return [];
|
|
16770
|
+
try {
|
|
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));
|
|
16775
|
+
} catch {
|
|
16776
|
+
return [];
|
|
16777
|
+
}
|
|
16778
|
+
}
|
|
16779
|
+
|
|
16780
|
+
// src/commands/sessions/daemon/queryDaemon.ts
|
|
16718
16781
|
import { createInterface as createInterface4 } from "readline";
|
|
16719
16782
|
var STATUS_TIMEOUT_MS = 5e3;
|
|
16783
|
+
function queryDaemon(socket) {
|
|
16784
|
+
socket.write(`${JSON.stringify({ type: "ping" })}
|
|
16785
|
+
`);
|
|
16786
|
+
return new Promise((resolve16) => {
|
|
16787
|
+
const result = { sessions: [] };
|
|
16788
|
+
const pending = /* @__PURE__ */ new Set(["sessions", "pong"]);
|
|
16789
|
+
const timer = setTimeout(() => resolve16(result), STATUS_TIMEOUT_MS);
|
|
16790
|
+
const lines = createInterface4({ input: socket });
|
|
16791
|
+
lines.on("error", () => {
|
|
16792
|
+
});
|
|
16793
|
+
lines.on("line", (line) => {
|
|
16794
|
+
applyLine(result, pending, line);
|
|
16795
|
+
if (pending.size === 0) {
|
|
16796
|
+
clearTimeout(timer);
|
|
16797
|
+
resolve16(result);
|
|
16798
|
+
}
|
|
16799
|
+
});
|
|
16800
|
+
});
|
|
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
|
|
16720
16839
|
async function daemonStatus() {
|
|
16721
16840
|
let socket;
|
|
16722
16841
|
try {
|
|
16723
16842
|
socket = await connectToDaemon();
|
|
16724
16843
|
} catch {
|
|
16725
16844
|
console.log("Sessions daemon is not running");
|
|
16845
|
+
reportStrays(listDaemonPids());
|
|
16726
16846
|
return;
|
|
16727
16847
|
}
|
|
16728
|
-
const sessions = await
|
|
16848
|
+
const { pid, sessions } = await queryDaemon(socket);
|
|
16729
16849
|
socket.destroy();
|
|
16730
|
-
console.log(`Sessions daemon is running${
|
|
16850
|
+
console.log(`Sessions daemon is running${pid ? ` (PID ${pid})` : ""}`);
|
|
16851
|
+
reportStolenSocket(pid);
|
|
16852
|
+
reportStrays(listDaemonPids().filter((p) => p !== pid));
|
|
16731
16853
|
if (sessions.length === 0) {
|
|
16732
16854
|
console.log("No sessions");
|
|
16733
16855
|
return;
|
|
@@ -16737,26 +16859,11 @@ async function daemonStatus() {
|
|
|
16737
16859
|
console.log(` [${session.status}] ${session.name}${restored}`);
|
|
16738
16860
|
}
|
|
16739
16861
|
}
|
|
16740
|
-
function
|
|
16741
|
-
if (
|
|
16742
|
-
|
|
16743
|
-
}
|
|
16744
|
-
|
|
16745
|
-
return new Promise((resolve16) => {
|
|
16746
|
-
const timer = setTimeout(() => resolve16([]), STATUS_TIMEOUT_MS);
|
|
16747
|
-
const lines = createInterface4({ input: socket });
|
|
16748
|
-
lines.on("error", () => {
|
|
16749
|
-
});
|
|
16750
|
-
lines.on("line", (line) => {
|
|
16751
|
-
try {
|
|
16752
|
-
const data = JSON.parse(line);
|
|
16753
|
-
if (data.type !== "sessions") return;
|
|
16754
|
-
clearTimeout(timer);
|
|
16755
|
-
resolve16(data.sessions ?? []);
|
|
16756
|
-
} catch {
|
|
16757
|
-
}
|
|
16758
|
-
});
|
|
16759
|
-
});
|
|
16862
|
+
function reportStrays(pids) {
|
|
16863
|
+
if (pids.length === 0) return;
|
|
16864
|
+
console.error(
|
|
16865
|
+
`Warning: stray daemon process(es) detected: ${pids.join(", ")}`
|
|
16866
|
+
);
|
|
16760
16867
|
}
|
|
16761
16868
|
|
|
16762
16869
|
// src/commands/sessions/daemon/stopDaemon.ts
|
|
@@ -16799,15 +16906,14 @@ function closedBeforeTimeout(socket) {
|
|
|
16799
16906
|
// src/commands/sessions/daemon/restartDaemon.ts
|
|
16800
16907
|
async function restartDaemon() {
|
|
16801
16908
|
await stopDaemon();
|
|
16802
|
-
await ensureDaemonRunning();
|
|
16909
|
+
await ensureDaemonRunning("daemon restart");
|
|
16803
16910
|
console.log(
|
|
16804
16911
|
"Sessions daemon restarted; previously running claude sessions will resume"
|
|
16805
16912
|
);
|
|
16806
16913
|
}
|
|
16807
16914
|
|
|
16808
16915
|
// src/commands/sessions/daemon/runDaemon.ts
|
|
16809
|
-
import {
|
|
16810
|
-
import * as net2 from "net";
|
|
16916
|
+
import { mkdirSync as mkdirSync19 } from "fs";
|
|
16811
16917
|
|
|
16812
16918
|
// src/commands/sessions/daemon/createAutoExit.ts
|
|
16813
16919
|
var DEFAULT_GRACE_MS = 6e4;
|
|
@@ -16823,137 +16929,9 @@ function createAutoExit(exit, graceMs = DEFAULT_GRACE_MS) {
|
|
|
16823
16929
|
};
|
|
16824
16930
|
}
|
|
16825
16931
|
|
|
16826
|
-
// src/commands/sessions/daemon/
|
|
16827
|
-
|
|
16828
|
-
|
|
16829
|
-
// src/commands/sessions/daemon/broadcast.ts
|
|
16830
|
-
function sendTo(client, msg) {
|
|
16831
|
-
client.send(JSON.stringify(msg));
|
|
16832
|
-
}
|
|
16833
|
-
function broadcast(clients, msg) {
|
|
16834
|
-
const json = JSON.stringify(msg);
|
|
16835
|
-
for (const client of clients) {
|
|
16836
|
-
client.send(json);
|
|
16837
|
-
}
|
|
16838
|
-
}
|
|
16839
|
-
|
|
16840
|
-
// src/commands/sessions/daemon/handleRunConfigs.ts
|
|
16841
|
-
function handleRunConfigs(client, cwd) {
|
|
16842
|
-
try {
|
|
16843
|
-
const { config, configDir } = loadConfigFrom(cwd);
|
|
16844
|
-
const configs = resolveRunConfigs(config.run, configDir);
|
|
16845
|
-
sendTo(client, {
|
|
16846
|
-
type: "run-configs",
|
|
16847
|
-
configs: configs.map(({ name, params }) => ({ name, params }))
|
|
16848
|
-
});
|
|
16849
|
-
} catch {
|
|
16850
|
-
sendTo(client, { type: "run-configs", configs: [] });
|
|
16851
|
-
}
|
|
16852
|
-
}
|
|
16853
|
-
|
|
16854
|
-
// src/commands/sessions/daemon/dispatchMessage.ts
|
|
16855
|
-
function sendCreated(client, id) {
|
|
16856
|
-
sendTo(client, { type: "created", sessionId: id });
|
|
16857
|
-
}
|
|
16858
|
-
function handleCreate(client, manager, data) {
|
|
16859
|
-
sendCreated(
|
|
16860
|
-
client,
|
|
16861
|
-
manager.spawn(
|
|
16862
|
-
data.prompt,
|
|
16863
|
-
data.cwd
|
|
16864
|
-
)
|
|
16865
|
-
);
|
|
16866
|
-
}
|
|
16867
|
-
function handleCreateRun(client, manager, data) {
|
|
16868
|
-
sendCreated(
|
|
16869
|
-
client,
|
|
16870
|
-
manager.spawnRun(
|
|
16871
|
-
data.runName,
|
|
16872
|
-
data.runArgs ?? [],
|
|
16873
|
-
data.cwd
|
|
16874
|
-
)
|
|
16875
|
-
);
|
|
16876
|
-
}
|
|
16877
|
-
function handleCreateAssist(client, manager, data) {
|
|
16878
|
-
sendCreated(
|
|
16879
|
-
client,
|
|
16880
|
-
manager.spawnAssist(
|
|
16881
|
-
data.assistArgs ?? [],
|
|
16882
|
-
data.cwd
|
|
16883
|
-
)
|
|
16884
|
-
);
|
|
16885
|
-
}
|
|
16886
|
-
function handleResume(client, manager, data) {
|
|
16887
|
-
sendCreated(
|
|
16888
|
-
client,
|
|
16889
|
-
manager.resume(
|
|
16890
|
-
data.sessionId,
|
|
16891
|
-
data.cwd,
|
|
16892
|
-
data.name
|
|
16893
|
-
)
|
|
16894
|
-
);
|
|
16895
|
-
}
|
|
16896
|
-
function runConfigs(client, _manager, data) {
|
|
16897
|
-
handleRunConfigs(client, data.cwd);
|
|
16898
|
-
}
|
|
16899
|
-
function handleHistory(client, manager) {
|
|
16900
|
-
manager.getHistory().then((history) => {
|
|
16901
|
-
sendTo(client, { type: "history", sessions: history });
|
|
16902
|
-
});
|
|
16903
|
-
}
|
|
16904
|
-
function handleShutdown(client, manager) {
|
|
16905
|
-
manager.shutdown();
|
|
16906
|
-
sendTo(client, { type: "shutting-down" });
|
|
16907
|
-
setImmediate(() => process.exit(0));
|
|
16908
|
-
}
|
|
16909
|
-
var handlers = {
|
|
16910
|
-
create: handleCreate,
|
|
16911
|
-
"create-run": handleCreateRun,
|
|
16912
|
-
"create-assist": handleCreateAssist,
|
|
16913
|
-
resume: handleResume,
|
|
16914
|
-
"run-configs": runConfigs,
|
|
16915
|
-
history: handleHistory,
|
|
16916
|
-
shutdown: handleShutdown,
|
|
16917
|
-
input: (_client, m, d) => m.writeToSession(d.sessionId, d.data),
|
|
16918
|
-
resize: (_client, m, d) => m.resizeSession(d.sessionId, d.cols, d.rows),
|
|
16919
|
-
retry: (_client, m, d) => m.retrySession(d.sessionId),
|
|
16920
|
-
dismiss: (_client, m, d) => m.dismissSession(d.sessionId)
|
|
16921
|
-
};
|
|
16922
|
-
function dispatchMessage(client, manager, data) {
|
|
16923
|
-
handlers[data.type]?.(client, manager, data);
|
|
16924
|
-
}
|
|
16925
|
-
|
|
16926
|
-
// src/commands/sessions/daemon/handleConnection.ts
|
|
16927
|
-
function handleConnection(socket, manager) {
|
|
16928
|
-
const client = {
|
|
16929
|
-
send: (data) => {
|
|
16930
|
-
if (socket.writable) socket.write(`${data}
|
|
16931
|
-
`);
|
|
16932
|
-
}
|
|
16933
|
-
};
|
|
16934
|
-
manager.addClient(client);
|
|
16935
|
-
const lines = createInterface5({ input: socket });
|
|
16936
|
-
lines.on("error", () => {
|
|
16937
|
-
});
|
|
16938
|
-
lines.on("line", (line) => {
|
|
16939
|
-
let data;
|
|
16940
|
-
try {
|
|
16941
|
-
data = JSON.parse(line);
|
|
16942
|
-
} catch {
|
|
16943
|
-
return;
|
|
16944
|
-
}
|
|
16945
|
-
try {
|
|
16946
|
-
dispatchMessage(client, manager, data);
|
|
16947
|
-
} catch (e) {
|
|
16948
|
-
sendTo(client, {
|
|
16949
|
-
type: "error",
|
|
16950
|
-
message: `${data.type} failed: ${e instanceof Error ? e.message : String(e)}`
|
|
16951
|
-
});
|
|
16952
|
-
}
|
|
16953
|
-
});
|
|
16954
|
-
socket.on("error", () => {
|
|
16955
|
-
});
|
|
16956
|
-
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}`);
|
|
16957
16935
|
}
|
|
16958
16936
|
|
|
16959
16937
|
// src/commands/sessions/shared/discoverSessions.ts
|
|
@@ -17071,6 +17049,17 @@ async function discoverSessions() {
|
|
|
17071
17049
|
return sessions;
|
|
17072
17050
|
}
|
|
17073
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
|
+
|
|
17074
17063
|
// src/commands/sessions/daemon/repoPrefix.ts
|
|
17075
17064
|
import * as path47 from "path";
|
|
17076
17065
|
function repoPrefix(cwd) {
|
|
@@ -17082,7 +17071,7 @@ function repoPrefix(cwd) {
|
|
|
17082
17071
|
import * as pty from "node-pty";
|
|
17083
17072
|
|
|
17084
17073
|
// src/commands/sessions/daemon/ensureSpawnHelperExecutable.ts
|
|
17085
|
-
import { chmodSync, existsSync as
|
|
17074
|
+
import { chmodSync, existsSync as existsSync51, statSync as statSync6 } from "fs";
|
|
17086
17075
|
import { createRequire as createRequire3 } from "module";
|
|
17087
17076
|
import path48 from "path";
|
|
17088
17077
|
var require4 = createRequire3(import.meta.url);
|
|
@@ -17097,8 +17086,8 @@ function ensureSpawnHelperExecutable() {
|
|
|
17097
17086
|
`${process.platform}-${process.arch}`,
|
|
17098
17087
|
"spawn-helper"
|
|
17099
17088
|
);
|
|
17100
|
-
if (!
|
|
17101
|
-
const mode =
|
|
17089
|
+
if (!existsSync51(helper)) return;
|
|
17090
|
+
const mode = statSync6(helper).mode;
|
|
17102
17091
|
if ((mode & 73) === 0) chmodSync(helper, mode | 493);
|
|
17103
17092
|
}
|
|
17104
17093
|
|
|
@@ -17492,9 +17481,10 @@ var SessionManager = class {
|
|
|
17492
17481
|
shutdownSessions(this.sessions);
|
|
17493
17482
|
}
|
|
17494
17483
|
restore() {
|
|
17495
|
-
|
|
17484
|
+
return loadPersistedSessions().map((persisted) => {
|
|
17496
17485
|
this.add(restoreSession(String(this.nextId++), persisted));
|
|
17497
|
-
|
|
17486
|
+
return persisted.name;
|
|
17487
|
+
});
|
|
17498
17488
|
}
|
|
17499
17489
|
add(session) {
|
|
17500
17490
|
this.wire(session);
|
|
@@ -17556,31 +17546,231 @@ var SessionManager = class {
|
|
|
17556
17546
|
};
|
|
17557
17547
|
};
|
|
17558
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
|
+
|
|
17559
17758
|
// src/commands/sessions/daemon/runDaemon.ts
|
|
17560
17759
|
async function runDaemon() {
|
|
17561
17760
|
mkdirSync19(daemonPaths.dir, { recursive: true });
|
|
17761
|
+
daemonLog(
|
|
17762
|
+
`starting (reason: ${process.env.ASSIST_DAEMON_SPAWN_REASON ?? "manual"})`
|
|
17763
|
+
);
|
|
17562
17764
|
if (await isDaemonRunning()) {
|
|
17563
|
-
|
|
17765
|
+
daemonLog("already running; exiting");
|
|
17564
17766
|
process.exitCode = 1;
|
|
17565
17767
|
return;
|
|
17566
17768
|
}
|
|
17567
|
-
if (process.platform !== "win32" && existsSync53(daemonPaths.socket)) {
|
|
17568
|
-
unlinkSync16(daemonPaths.socket);
|
|
17569
|
-
}
|
|
17570
17769
|
const checkAutoExit = createAutoExit(() => {
|
|
17571
|
-
|
|
17770
|
+
daemonLog("no sessions and no connected server; exiting");
|
|
17572
17771
|
process.exit(0);
|
|
17573
17772
|
});
|
|
17574
|
-
|
|
17575
|
-
manager.restore();
|
|
17576
|
-
const server = net2.createServer(
|
|
17577
|
-
(socket) => handleConnection(socket, manager)
|
|
17578
|
-
);
|
|
17579
|
-
server.listen(daemonPaths.socket, () => {
|
|
17580
|
-
writeFileSync32(daemonPaths.pid, String(process.pid));
|
|
17581
|
-
console.log(`Sessions daemon listening on ${daemonPaths.socket}`);
|
|
17582
|
-
checkAutoExit(manager.isIdle());
|
|
17583
|
-
});
|
|
17773
|
+
startDaemonServer(new SessionManager(checkAutoExit), checkAutoExit);
|
|
17584
17774
|
}
|
|
17585
17775
|
|
|
17586
17776
|
// src/commands/sessions/daemon/registerDaemon.ts
|
|
@@ -17589,7 +17779,9 @@ function registerDaemon(program2) {
|
|
|
17589
17779
|
cmd.command("run").description(
|
|
17590
17780
|
"Run the sessions daemon in the foreground (auto-spawned by assist sessions)"
|
|
17591
17781
|
).action(runDaemon);
|
|
17592
|
-
cmd.command("status").description(
|
|
17782
|
+
cmd.command("status").description(
|
|
17783
|
+
"Show sessions daemon status, live sessions, and any stray daemon processes"
|
|
17784
|
+
).action(daemonStatus);
|
|
17593
17785
|
cmd.command("stop").description(
|
|
17594
17786
|
"Stop the sessions daemon; running claude sessions resume on next start"
|
|
17595
17787
|
).action(stopDaemon);
|
|
@@ -17616,7 +17808,7 @@ function summaryPathFor(jsonlPath2) {
|
|
|
17616
17808
|
}
|
|
17617
17809
|
|
|
17618
17810
|
// src/commands/sessions/summarise/summariseSession.ts
|
|
17619
|
-
import { execFileSync as
|
|
17811
|
+
import { execFileSync as execFileSync10 } from "child_process";
|
|
17620
17812
|
|
|
17621
17813
|
// src/commands/sessions/summarise/iterateUserMessages.ts
|
|
17622
17814
|
import * as fs28 from "fs";
|
|
@@ -17693,7 +17885,7 @@ function summariseSession(jsonlPath2) {
|
|
|
17693
17885
|
}
|
|
17694
17886
|
const prompt = buildPrompt2(firstMessage, backlogIds);
|
|
17695
17887
|
try {
|
|
17696
|
-
const output =
|
|
17888
|
+
const output = execFileSync10("claude", ["-p", "--model", "haiku", prompt], {
|
|
17697
17889
|
encoding: "utf8",
|
|
17698
17890
|
timeout: 3e4,
|
|
17699
17891
|
stdio: ["ignore", "pipe", "ignore"]
|