@staff0rd/assist 0.413.0 → 0.415.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/commands/sessions/web/bundle.js +401 -401
- package/dist/index.js +284 -90
- 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.415.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -134,12 +134,15 @@ import chalk2 from "chalk";
|
|
|
134
134
|
import { Pool } from "pg";
|
|
135
135
|
|
|
136
136
|
// src/shared/loadConfig.ts
|
|
137
|
-
import {
|
|
138
|
-
import { homedir } from "os";
|
|
139
|
-
import { dirname, join } from "path";
|
|
137
|
+
import { writeFileSync } from "fs";
|
|
140
138
|
import chalk from "chalk";
|
|
141
139
|
import { stringify as stringifyYaml } from "yaml";
|
|
142
140
|
|
|
141
|
+
// src/shared/loadConfigFrom.ts
|
|
142
|
+
import { existsSync as existsSync2 } from "fs";
|
|
143
|
+
import { homedir } from "os";
|
|
144
|
+
import { dirname, join } from "path";
|
|
145
|
+
|
|
143
146
|
// src/commands/backlog/getCurrentOrigin.ts
|
|
144
147
|
import { execFileSync } from "child_process";
|
|
145
148
|
function stripLeadingSlashes(path71) {
|
|
@@ -332,7 +335,9 @@ var runConfigSchema = z.strictObject({
|
|
|
332
335
|
filter: z.string().optional(),
|
|
333
336
|
pre: z.array(z.string()).optional(),
|
|
334
337
|
cwd: z.string().optional(),
|
|
335
|
-
quiet: z.boolean().optional()
|
|
338
|
+
quiet: z.boolean().optional(),
|
|
339
|
+
server: z.boolean().optional(),
|
|
340
|
+
port: z.number().optional()
|
|
336
341
|
});
|
|
337
342
|
var runLinkSchema = z.strictObject({
|
|
338
343
|
link: z.string(),
|
|
@@ -506,7 +511,7 @@ var assistConfigSchema = z2.strictObject({
|
|
|
506
511
|
})
|
|
507
512
|
});
|
|
508
513
|
|
|
509
|
-
// src/shared/
|
|
514
|
+
// src/shared/loadConfigFrom.ts
|
|
510
515
|
function findConfigUp(startDir) {
|
|
511
516
|
let current = startDir;
|
|
512
517
|
while (current !== dirname(current)) {
|
|
@@ -519,31 +524,42 @@ function findConfigUp(startDir) {
|
|
|
519
524
|
}
|
|
520
525
|
return null;
|
|
521
526
|
}
|
|
522
|
-
function
|
|
523
|
-
const found = findConfigUp(
|
|
527
|
+
function getConfigPathFrom(cwd) {
|
|
528
|
+
const found = findConfigUp(cwd);
|
|
524
529
|
if (found) return found.configPath;
|
|
525
|
-
return join(
|
|
530
|
+
return join(cwd, "assist.yml");
|
|
526
531
|
}
|
|
527
532
|
function getGlobalConfigPath() {
|
|
528
533
|
return join(homedir(), ".assist.yml");
|
|
529
534
|
}
|
|
530
|
-
function
|
|
531
|
-
return dirname(
|
|
535
|
+
function getConfigDirFrom(cwd) {
|
|
536
|
+
return dirname(getConfigPathFrom(cwd));
|
|
532
537
|
}
|
|
533
|
-
function
|
|
534
|
-
const found = findConfigUp(process.cwd());
|
|
535
|
-
return found?.rootDir ?? process.cwd();
|
|
536
|
-
}
|
|
537
|
-
function loadConfig() {
|
|
538
|
+
function loadConfigFrom(cwd) {
|
|
538
539
|
const globalRaw = loadRawYaml(getGlobalConfigPath());
|
|
539
|
-
const projectRaw = loadRawYaml(
|
|
540
|
-
const repoOverride = globalRaw.repos ? resolveRepoOverride(globalRaw, getCurrentOrigin(
|
|
540
|
+
const projectRaw = loadRawYaml(getConfigPathFrom(cwd));
|
|
541
|
+
const repoOverride = globalRaw.repos ? resolveRepoOverride(globalRaw, getCurrentOrigin(cwd)) : {};
|
|
541
542
|
const globalWithRepo = mergeRawConfigs(globalRaw, repoOverride);
|
|
542
543
|
const merged = mergeRawConfigs(globalWithRepo, projectRaw);
|
|
543
544
|
delete merged.repos;
|
|
544
545
|
delete merged.news;
|
|
545
546
|
return assistConfigSchema.parse(merged);
|
|
546
547
|
}
|
|
548
|
+
|
|
549
|
+
// src/shared/loadConfig.ts
|
|
550
|
+
function getConfigPath() {
|
|
551
|
+
return getConfigPathFrom(process.cwd());
|
|
552
|
+
}
|
|
553
|
+
function getConfigDir() {
|
|
554
|
+
return getConfigDirFrom(process.cwd());
|
|
555
|
+
}
|
|
556
|
+
function getProjectRoot() {
|
|
557
|
+
const found = findConfigUp(process.cwd());
|
|
558
|
+
return found?.rootDir ?? process.cwd();
|
|
559
|
+
}
|
|
560
|
+
function loadConfig() {
|
|
561
|
+
return loadConfigFrom(process.cwd());
|
|
562
|
+
}
|
|
547
563
|
function loadProjectConfig() {
|
|
548
564
|
return loadRawYaml(getConfigPath());
|
|
549
565
|
}
|
|
@@ -3581,9 +3597,9 @@ function forbiddenStrings() {
|
|
|
3581
3597
|
console.log("No forbidden-strings rules configured.");
|
|
3582
3598
|
process.exit(0);
|
|
3583
3599
|
}
|
|
3584
|
-
const
|
|
3600
|
+
const cache2 = /* @__PURE__ */ new Map();
|
|
3585
3601
|
const readJson = (file) => {
|
|
3586
|
-
if (
|
|
3602
|
+
if (cache2.has(file)) return cache2.get(file);
|
|
3587
3603
|
if (!existsSync12(file)) {
|
|
3588
3604
|
console.log(`Forbidden-strings file not found: ${file}`);
|
|
3589
3605
|
process.exit(1);
|
|
@@ -3595,7 +3611,7 @@ function forbiddenStrings() {
|
|
|
3595
3611
|
console.log(`Could not parse ${file}: ${error.message}`);
|
|
3596
3612
|
process.exit(1);
|
|
3597
3613
|
}
|
|
3598
|
-
|
|
3614
|
+
cache2.set(file, parsed);
|
|
3599
3615
|
return parsed;
|
|
3600
3616
|
};
|
|
3601
3617
|
const violations = findForbiddenStrings(rules, readJson);
|
|
@@ -7987,18 +8003,18 @@ import { dirname as dirname19, join as join22 } from "path";
|
|
|
7987
8003
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
7988
8004
|
function createBundleHandler(importMetaUrl, bundlePath) {
|
|
7989
8005
|
const dir = dirname19(fileURLToPath4(importMetaUrl));
|
|
7990
|
-
let
|
|
8006
|
+
let cache2;
|
|
7991
8007
|
return (req, res) => {
|
|
7992
|
-
if (!
|
|
8008
|
+
if (!cache2) {
|
|
7993
8009
|
const body = readFileSync18(join22(dir, bundlePath), "utf8");
|
|
7994
8010
|
const etag = `"${createHash("sha256").update(body).digest("hex").slice(0, 16)}"`;
|
|
7995
|
-
|
|
8011
|
+
cache2 = { body, etag };
|
|
7996
8012
|
}
|
|
7997
8013
|
const headers = {
|
|
7998
|
-
ETag:
|
|
8014
|
+
ETag: cache2.etag,
|
|
7999
8015
|
"Cache-Control": "no-cache"
|
|
8000
8016
|
};
|
|
8001
|
-
if (req.headers["if-none-match"] ===
|
|
8017
|
+
if (req.headers["if-none-match"] === cache2.etag) {
|
|
8002
8018
|
res.writeHead(304, headers);
|
|
8003
8019
|
res.end();
|
|
8004
8020
|
return;
|
|
@@ -8007,7 +8023,7 @@ function createBundleHandler(importMetaUrl, bundlePath) {
|
|
|
8007
8023
|
"Content-Type": "application/javascript",
|
|
8008
8024
|
...headers
|
|
8009
8025
|
});
|
|
8010
|
-
res.end(
|
|
8026
|
+
res.end(cache2.body);
|
|
8011
8027
|
};
|
|
8012
8028
|
}
|
|
8013
8029
|
|
|
@@ -8504,25 +8520,6 @@ function getHtml() {
|
|
|
8504
8520
|
</html>`;
|
|
8505
8521
|
}
|
|
8506
8522
|
|
|
8507
|
-
// src/commands/sessions/web/getReviewSynthesis.ts
|
|
8508
|
-
import { execFile as execFile2 } from "child_process";
|
|
8509
|
-
import { readFileSync as readFileSync19 } from "fs";
|
|
8510
|
-
import { homedir as homedir11 } from "os";
|
|
8511
|
-
import { basename as basename6, join as join25 } from "path";
|
|
8512
|
-
import { promisify as promisify2 } from "util";
|
|
8513
|
-
|
|
8514
|
-
// src/commands/sessions/web/findSynthesisForBranch.ts
|
|
8515
|
-
import { existsSync as existsSync26, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
|
|
8516
|
-
import { basename as basename5, dirname as dirname20, join as join24 } from "path";
|
|
8517
|
-
function findSynthesisForBranch(repoReviewsDir, branch2) {
|
|
8518
|
-
const branchKeyPath = join24(repoReviewsDir, `${branch2}-`);
|
|
8519
|
-
const parent = dirname20(branchKeyPath);
|
|
8520
|
-
const branchPrefix = basename5(branchKeyPath);
|
|
8521
|
-
if (!existsSync26(parent)) return null;
|
|
8522
|
-
const synthesisFiles = readdirSync2(parent).filter((name) => name.startsWith(branchPrefix)).map((name) => join24(parent, name, "synthesis.md")).filter((path71) => existsSync26(path71)).map((path71) => ({ path: path71, mtime: statSync2(path71).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
|
|
8523
|
-
return synthesisFiles[0]?.path ?? null;
|
|
8524
|
-
}
|
|
8525
|
-
|
|
8526
8523
|
// src/commands/sessions/web/getCwdParam.ts
|
|
8527
8524
|
function getCwdParam(req, res) {
|
|
8528
8525
|
const url = new URL(req.url ?? "/", "http://localhost");
|
|
@@ -8548,6 +8545,41 @@ function toGitCwd(cwd) {
|
|
|
8548
8545
|
return detectPlatform() === "wsl" ? windowsCwdToWslPath(cwd) : cwd;
|
|
8549
8546
|
}
|
|
8550
8547
|
|
|
8548
|
+
// src/commands/sessions/web/handleServerRuns.ts
|
|
8549
|
+
function getServerRuns(rawCwd) {
|
|
8550
|
+
try {
|
|
8551
|
+
const cwd = toGitCwd(rawCwd);
|
|
8552
|
+
const { run: run4 } = loadConfigFrom(cwd);
|
|
8553
|
+
return resolveRunConfigs(run4, getConfigDirFrom(cwd)).filter((r) => r.server).map((r) => ({ name: r.name, port: r.port }));
|
|
8554
|
+
} catch {
|
|
8555
|
+
return [];
|
|
8556
|
+
}
|
|
8557
|
+
}
|
|
8558
|
+
function handleServerRuns(req, res) {
|
|
8559
|
+
const cwd = getCwdParam(req, res);
|
|
8560
|
+
if (!cwd) return;
|
|
8561
|
+
respondJson(res, 200, { runs: getServerRuns(cwd) });
|
|
8562
|
+
}
|
|
8563
|
+
|
|
8564
|
+
// src/commands/sessions/web/getReviewSynthesis.ts
|
|
8565
|
+
import { execFile as execFile2 } from "child_process";
|
|
8566
|
+
import { readFileSync as readFileSync19 } from "fs";
|
|
8567
|
+
import { homedir as homedir11 } from "os";
|
|
8568
|
+
import { basename as basename6, join as join25 } from "path";
|
|
8569
|
+
import { promisify as promisify2 } from "util";
|
|
8570
|
+
|
|
8571
|
+
// src/commands/sessions/web/findSynthesisForBranch.ts
|
|
8572
|
+
import { existsSync as existsSync26, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
|
|
8573
|
+
import { basename as basename5, dirname as dirname20, join as join24 } from "path";
|
|
8574
|
+
function findSynthesisForBranch(repoReviewsDir, branch2) {
|
|
8575
|
+
const branchKeyPath = join24(repoReviewsDir, `${branch2}-`);
|
|
8576
|
+
const parent = dirname20(branchKeyPath);
|
|
8577
|
+
const branchPrefix = basename5(branchKeyPath);
|
|
8578
|
+
if (!existsSync26(parent)) return null;
|
|
8579
|
+
const synthesisFiles = readdirSync2(parent).filter((name) => name.startsWith(branchPrefix)).map((name) => join24(parent, name, "synthesis.md")).filter((path71) => existsSync26(path71)).map((path71) => ({ path: path71, mtime: statSync2(path71).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
|
|
8580
|
+
return synthesisFiles[0]?.path ?? null;
|
|
8581
|
+
}
|
|
8582
|
+
|
|
8551
8583
|
// src/commands/sessions/web/getReviewSynthesis.ts
|
|
8552
8584
|
var execFileAsync2 = promisify2(execFile2);
|
|
8553
8585
|
function runGit(cwd, args) {
|
|
@@ -8948,11 +8980,11 @@ var execFileAsync4 = promisify5(execFile4);
|
|
|
8948
8980
|
var CACHE_TTL_MS = 3e4;
|
|
8949
8981
|
function createCachedGhJson(args, parse3, fallback, options2 = {}) {
|
|
8950
8982
|
const { cacheFallback = true } = options2;
|
|
8951
|
-
const
|
|
8983
|
+
const cache2 = /* @__PURE__ */ new Map();
|
|
8952
8984
|
return async (cwd, extraArgs = []) => {
|
|
8953
8985
|
const key = extraArgs.length ? `${cwd}\0${extraArgs.join("\0")}` : cwd;
|
|
8954
8986
|
const now = Date.now();
|
|
8955
|
-
const cached =
|
|
8987
|
+
const cached = cache2.get(key);
|
|
8956
8988
|
if (cached && cached.expires > now) return cached.value;
|
|
8957
8989
|
let value = fallback;
|
|
8958
8990
|
try {
|
|
@@ -8965,7 +8997,7 @@ function createCachedGhJson(args, parse3, fallback, options2 = {}) {
|
|
|
8965
8997
|
value = fallback;
|
|
8966
8998
|
}
|
|
8967
8999
|
if (cacheFallback || value !== fallback)
|
|
8968
|
-
|
|
9000
|
+
cache2.set(key, { value, expires: now + CACHE_TTL_MS });
|
|
8969
9001
|
return value;
|
|
8970
9002
|
};
|
|
8971
9003
|
}
|
|
@@ -9165,22 +9197,22 @@ import { readFileSync as readFileSync21 } from "fs";
|
|
|
9165
9197
|
import { createRequire as createRequire2 } from "module";
|
|
9166
9198
|
var require3 = createRequire2(import.meta.url);
|
|
9167
9199
|
function createCssHandler(packageEntry) {
|
|
9168
|
-
let
|
|
9200
|
+
let cache2;
|
|
9169
9201
|
return (req, res) => {
|
|
9170
|
-
if (!
|
|
9202
|
+
if (!cache2) {
|
|
9171
9203
|
const resolved = require3.resolve(packageEntry);
|
|
9172
9204
|
const body = readFileSync21(resolved, "utf8");
|
|
9173
9205
|
const etag = `"${createHash2("sha256").update(body).digest("hex").slice(0, 16)}"`;
|
|
9174
|
-
|
|
9206
|
+
cache2 = { body, etag };
|
|
9175
9207
|
}
|
|
9176
|
-
const headers = { ETag:
|
|
9177
|
-
if (req.headers["if-none-match"] ===
|
|
9208
|
+
const headers = { ETag: cache2.etag, "Cache-Control": "no-cache" };
|
|
9209
|
+
if (req.headers["if-none-match"] === cache2.etag) {
|
|
9178
9210
|
res.writeHead(304, headers);
|
|
9179
9211
|
res.end();
|
|
9180
9212
|
return;
|
|
9181
9213
|
}
|
|
9182
9214
|
res.writeHead(200, { "Content-Type": "text/css", ...headers });
|
|
9183
|
-
res.end(
|
|
9215
|
+
res.end(cache2.body);
|
|
9184
9216
|
};
|
|
9185
9217
|
}
|
|
9186
9218
|
|
|
@@ -9202,6 +9234,7 @@ var routes2 = {
|
|
|
9202
9234
|
"GET /api/jira-site": jiraSite,
|
|
9203
9235
|
"GET /api/harness": harnessCapabilities,
|
|
9204
9236
|
"GET /api/pr-status": prStatus,
|
|
9237
|
+
"GET /api/server-runs": handleServerRuns,
|
|
9205
9238
|
"GET /api/pr-list": prList,
|
|
9206
9239
|
"GET /api/news/items": listNewsItems,
|
|
9207
9240
|
"GET /api/usage/history": listUsageHistory,
|
|
@@ -17691,20 +17724,20 @@ function resolveThread(threadId) {
|
|
|
17691
17724
|
}
|
|
17692
17725
|
}
|
|
17693
17726
|
function requireCache(prNumber) {
|
|
17694
|
-
const
|
|
17695
|
-
if (!
|
|
17727
|
+
const cache2 = loadCommentsCache(prNumber);
|
|
17728
|
+
if (!cache2) {
|
|
17696
17729
|
console.error(
|
|
17697
17730
|
`Error: No cached comments found for PR #${prNumber}. Run "assist prs list-comments" first.`
|
|
17698
17731
|
);
|
|
17699
17732
|
process.exit(1);
|
|
17700
17733
|
}
|
|
17701
|
-
return
|
|
17734
|
+
return cache2;
|
|
17702
17735
|
}
|
|
17703
17736
|
function findLineComment(comments3, commentId) {
|
|
17704
17737
|
return comments3.find((c) => c.type === "line" && c.id === commentId);
|
|
17705
17738
|
}
|
|
17706
|
-
function requireLineComment(
|
|
17707
|
-
const comment3 = findLineComment(
|
|
17739
|
+
function requireLineComment(cache2, commentId) {
|
|
17740
|
+
const comment3 = findLineComment(cache2.comments, commentId);
|
|
17708
17741
|
if (!comment3 || comment3.type !== "line" || !comment3.threadId) {
|
|
17709
17742
|
console.error(
|
|
17710
17743
|
`Error: Comment #${commentId} not found or has no thread ID.`
|
|
@@ -17713,8 +17746,8 @@ function requireLineComment(cache, commentId) {
|
|
|
17713
17746
|
}
|
|
17714
17747
|
return comment3;
|
|
17715
17748
|
}
|
|
17716
|
-
function cleanupCacheIfDone(
|
|
17717
|
-
const hasRemaining =
|
|
17749
|
+
function cleanupCacheIfDone(cache2, prNumber, commentId) {
|
|
17750
|
+
const hasRemaining = cache2.comments.some(
|
|
17718
17751
|
(c) => c.type === "line" && c.id !== commentId
|
|
17719
17752
|
);
|
|
17720
17753
|
if (!hasRemaining) deleteCommentsCache(prNumber);
|
|
@@ -17722,13 +17755,13 @@ function cleanupCacheIfDone(cache, prNumber, commentId) {
|
|
|
17722
17755
|
function resolveCommentWithReply(commentId, message) {
|
|
17723
17756
|
const prNumber = getCurrentPrNumber();
|
|
17724
17757
|
const { org, repo } = getRepoInfo();
|
|
17725
|
-
const
|
|
17726
|
-
const comment3 = requireLineComment(
|
|
17758
|
+
const cache2 = requireCache(prNumber);
|
|
17759
|
+
const comment3 = requireLineComment(cache2, commentId);
|
|
17727
17760
|
replyToComment(org, repo, prNumber, commentId, message);
|
|
17728
17761
|
console.log("Reply posted successfully.");
|
|
17729
17762
|
resolveThread(comment3.threadId);
|
|
17730
17763
|
console.log("Thread resolved successfully.");
|
|
17731
|
-
cleanupCacheIfDone(
|
|
17764
|
+
cleanupCacheIfDone(cache2, prNumber, commentId);
|
|
17732
17765
|
}
|
|
17733
17766
|
|
|
17734
17767
|
// src/commands/prs/fixed.ts
|
|
@@ -24745,6 +24778,17 @@ function broadcast(clients, msg) {
|
|
|
24745
24778
|
}
|
|
24746
24779
|
}
|
|
24747
24780
|
|
|
24781
|
+
// src/commands/sessions/daemon/originForCwd.ts
|
|
24782
|
+
var cache = /* @__PURE__ */ new Map();
|
|
24783
|
+
function originForCwd(cwd) {
|
|
24784
|
+
if (!cwd) return void 0;
|
|
24785
|
+
const cached = cache.get(cwd);
|
|
24786
|
+
if (cached !== void 0) return cached;
|
|
24787
|
+
const origin = getCurrentOrigin(cwd);
|
|
24788
|
+
cache.set(cwd, origin);
|
|
24789
|
+
return origin;
|
|
24790
|
+
}
|
|
24791
|
+
|
|
24748
24792
|
// src/commands/sessions/daemon/toSessionInfo.ts
|
|
24749
24793
|
function toSessionInfo({
|
|
24750
24794
|
id,
|
|
@@ -24759,6 +24803,9 @@ function toSessionInfo({
|
|
|
24759
24803
|
runningSince,
|
|
24760
24804
|
runName,
|
|
24761
24805
|
runArgs,
|
|
24806
|
+
server,
|
|
24807
|
+
serverPort,
|
|
24808
|
+
serverOrigin,
|
|
24762
24809
|
assistArgs,
|
|
24763
24810
|
cwd,
|
|
24764
24811
|
restored,
|
|
@@ -24784,6 +24831,9 @@ function toSessionInfo({
|
|
|
24784
24831
|
runningSince,
|
|
24785
24832
|
runName,
|
|
24786
24833
|
runArgs,
|
|
24834
|
+
server,
|
|
24835
|
+
port: serverPort,
|
|
24836
|
+
remoteOrigin: serverOrigin ?? originForCwd(cwd),
|
|
24787
24837
|
assistArgs,
|
|
24788
24838
|
cwd,
|
|
24789
24839
|
restored,
|
|
@@ -24957,6 +25007,28 @@ function createAssistSession(id, assistArgs, cwd, meta) {
|
|
|
24957
25007
|
// src/commands/sessions/daemon/createSession.ts
|
|
24958
25008
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
24959
25009
|
|
|
25010
|
+
// src/commands/sessions/daemon/resolveRunConfig.ts
|
|
25011
|
+
function resolveRunConfig(name, cwd) {
|
|
25012
|
+
try {
|
|
25013
|
+
const { run: run4 } = loadConfigFrom(cwd);
|
|
25014
|
+
const configs = resolveRunConfigs(run4, getConfigDirFrom(cwd));
|
|
25015
|
+
const exact = configs.find((r) => r.name === name);
|
|
25016
|
+
if (exact) return exact;
|
|
25017
|
+
const suffixMatches = configs.filter((r) => r.name.endsWith(`:${name}`));
|
|
25018
|
+
return suffixMatches.length === 1 ? suffixMatches[0] : void 0;
|
|
25019
|
+
} catch {
|
|
25020
|
+
return void 0;
|
|
25021
|
+
}
|
|
25022
|
+
}
|
|
25023
|
+
|
|
25024
|
+
// src/commands/sessions/daemon/serverRunMeta.ts
|
|
25025
|
+
function serverRunMeta(runName, cwd) {
|
|
25026
|
+
const dir = cwd ?? process.cwd();
|
|
25027
|
+
const config = resolveRunConfig(runName, dir);
|
|
25028
|
+
if (!config?.server) return { server: false };
|
|
25029
|
+
return { server: true, port: config.port, origin: getCurrentOrigin(dir) };
|
|
25030
|
+
}
|
|
25031
|
+
|
|
24960
25032
|
// src/commands/sessions/daemon/readDesignSystemPrompt.ts
|
|
24961
25033
|
import * as fs35 from "fs";
|
|
24962
25034
|
import * as path59 from "path";
|
|
@@ -25037,7 +25109,7 @@ function createPiSession(id, prompt, cwd) {
|
|
|
25037
25109
|
initialPrompt: prompt
|
|
25038
25110
|
};
|
|
25039
25111
|
}
|
|
25040
|
-
function createRunSession(id, runName, runArgs, cwd) {
|
|
25112
|
+
function createRunSession(id, runName, runArgs, cwd, meta = serverRunMeta(runName, cwd)) {
|
|
25041
25113
|
return {
|
|
25042
25114
|
...sessionBase(id, "running"),
|
|
25043
25115
|
name: `run: ${runName}`,
|
|
@@ -25045,7 +25117,10 @@ function createRunSession(id, runName, runArgs, cwd) {
|
|
|
25045
25117
|
pty: spawnRun({ name: runName, args: runArgs, cwd }),
|
|
25046
25118
|
runName,
|
|
25047
25119
|
runArgs,
|
|
25048
|
-
cwd
|
|
25120
|
+
cwd,
|
|
25121
|
+
server: meta.server || void 0,
|
|
25122
|
+
serverPort: meta.port,
|
|
25123
|
+
serverOrigin: meta.origin
|
|
25049
25124
|
};
|
|
25050
25125
|
}
|
|
25051
25126
|
|
|
@@ -25442,6 +25517,18 @@ function errorTail(scrollback) {
|
|
|
25442
25517
|
return tail.length > MAX_TAIL_CHARS ? tail.slice(-MAX_TAIL_CHARS) : tail;
|
|
25443
25518
|
}
|
|
25444
25519
|
|
|
25520
|
+
// src/commands/sessions/daemon/handleFailedResume.ts
|
|
25521
|
+
function handleFailedResume(session, exitCode, onStatusChange) {
|
|
25522
|
+
const failed2 = session.restored === true && exitCode !== 0 && session.scrollback.length === 0;
|
|
25523
|
+
if (!failed2) return false;
|
|
25524
|
+
session.error = `resume process exited with code ${exitCode} before producing any output`;
|
|
25525
|
+
daemonLog(
|
|
25526
|
+
`could not resume restored session "${session.name}" (id ${session.id}): ${session.error}`
|
|
25527
|
+
);
|
|
25528
|
+
onStatusChange(session, "error", exitCode);
|
|
25529
|
+
return true;
|
|
25530
|
+
}
|
|
25531
|
+
|
|
25445
25532
|
// src/commands/sessions/daemon/watchActivity.ts
|
|
25446
25533
|
import { existsSync as existsSync58, mkdirSync as mkdirSync25, watch } from "fs";
|
|
25447
25534
|
import { dirname as dirname29 } from "path";
|
|
@@ -25535,6 +25622,18 @@ function refreshActivity(session) {
|
|
|
25535
25622
|
session.claudeSessionId = activity2.claudeSessionId;
|
|
25536
25623
|
}
|
|
25537
25624
|
|
|
25625
|
+
// src/commands/sessions/daemon/handleStoppedExit.ts
|
|
25626
|
+
function handleStoppedExit(session, exitCode, onStatusChange) {
|
|
25627
|
+
if (!session.stopping) return false;
|
|
25628
|
+
session.stopping = void 0;
|
|
25629
|
+
refreshActivity(session);
|
|
25630
|
+
daemonLog(
|
|
25631
|
+
`session ${session.id} ("${session.name}") pty exited (code ${exitCode}) after stop request; marking done`
|
|
25632
|
+
);
|
|
25633
|
+
onStatusChange(session, "done", 0);
|
|
25634
|
+
return true;
|
|
25635
|
+
}
|
|
25636
|
+
|
|
25538
25637
|
// src/commands/sessions/daemon/handlePtyExit.ts
|
|
25539
25638
|
function handlePtyExit(session, exitCode, onStatusChange) {
|
|
25540
25639
|
if (session.pendingRestart) {
|
|
@@ -25546,16 +25645,9 @@ function handlePtyExit(session, exitCode, onStatusChange) {
|
|
|
25546
25645
|
resume();
|
|
25547
25646
|
return;
|
|
25548
25647
|
}
|
|
25648
|
+
if (handleStoppedExit(session, exitCode, onStatusChange)) return;
|
|
25549
25649
|
refreshActivity(session);
|
|
25550
|
-
|
|
25551
|
-
if (failedResume) {
|
|
25552
|
-
session.error = `resume process exited with code ${exitCode} before producing any output`;
|
|
25553
|
-
daemonLog(
|
|
25554
|
-
`could not resume restored session "${session.name}" (id ${session.id}): ${session.error}`
|
|
25555
|
-
);
|
|
25556
|
-
onStatusChange(session, "error", exitCode);
|
|
25557
|
-
return;
|
|
25558
|
-
}
|
|
25650
|
+
if (handleFailedResume(session, exitCode, onStatusChange)) return;
|
|
25559
25651
|
const priorStatus = session.status;
|
|
25560
25652
|
if (exitCode !== 0) {
|
|
25561
25653
|
const tail = errorTail(session.scrollback);
|
|
@@ -26170,6 +26262,59 @@ function respawnThunk(session) {
|
|
|
26170
26262
|
return null;
|
|
26171
26263
|
}
|
|
26172
26264
|
|
|
26265
|
+
// src/commands/sessions/daemon/serverConflictInfo.ts
|
|
26266
|
+
function serverConflictInfo(session) {
|
|
26267
|
+
return {
|
|
26268
|
+
id: session.id,
|
|
26269
|
+
name: session.name,
|
|
26270
|
+
cwd: session.cwd,
|
|
26271
|
+
port: session.serverPort
|
|
26272
|
+
};
|
|
26273
|
+
}
|
|
26274
|
+
|
|
26275
|
+
// src/commands/sessions/daemon/liveServerRun.ts
|
|
26276
|
+
function liveServerRun(sessions, origin, excludeId) {
|
|
26277
|
+
for (const s of sessions.values()) {
|
|
26278
|
+
if (s.id === excludeId || !s.server || s.serverOrigin !== origin) continue;
|
|
26279
|
+
if (s.status !== "done" && s.status !== "error") return s;
|
|
26280
|
+
}
|
|
26281
|
+
return void 0;
|
|
26282
|
+
}
|
|
26283
|
+
function stopServerSession(sessions, id) {
|
|
26284
|
+
const s = sessions.get(id);
|
|
26285
|
+
if (!s?.pty || s.status === "done" || s.status === "error") return;
|
|
26286
|
+
s.stopping = true;
|
|
26287
|
+
daemonLog(`session ${id} stopped (${s.name})`);
|
|
26288
|
+
s.pty.kill();
|
|
26289
|
+
}
|
|
26290
|
+
|
|
26291
|
+
// src/commands/sessions/daemon/runRetry.ts
|
|
26292
|
+
function tagServerSession(session, meta) {
|
|
26293
|
+
session.server = meta.server || void 0;
|
|
26294
|
+
session.serverPort = meta.port;
|
|
26295
|
+
session.serverOrigin = meta.origin;
|
|
26296
|
+
}
|
|
26297
|
+
function findRetryConflict(sessions, session, replace, dismiss) {
|
|
26298
|
+
const meta = serverRunMeta(session.runName ?? "", session.cwd);
|
|
26299
|
+
if (meta.server && meta.origin) {
|
|
26300
|
+
const existing = liveServerRun(sessions, meta.origin, session.id);
|
|
26301
|
+
if (existing && !replace) return serverConflictInfo(existing);
|
|
26302
|
+
if (existing) dismiss(existing.id);
|
|
26303
|
+
}
|
|
26304
|
+
tagServerSession(session, meta);
|
|
26305
|
+
return null;
|
|
26306
|
+
}
|
|
26307
|
+
function runRetry(sessions, id, replace, deps2) {
|
|
26308
|
+
const s = sessions.get(id);
|
|
26309
|
+
if (!s) return null;
|
|
26310
|
+
if (s.commandType === "run" && s.runName) {
|
|
26311
|
+
const conflict = findRetryConflict(sessions, s, replace, deps2.dismiss);
|
|
26312
|
+
if (conflict) return conflict;
|
|
26313
|
+
}
|
|
26314
|
+
if (retrySession(s, deps2.clients, deps2.onStatusChange)) deps2.notify();
|
|
26315
|
+
return null;
|
|
26316
|
+
}
|
|
26317
|
+
|
|
26173
26318
|
// src/commands/sessions/daemon/reuseSessionForRun.ts
|
|
26174
26319
|
function reuseSessionForRun(session, itemId2, clients, onStatusChange) {
|
|
26175
26320
|
const assistArgs = ["backlog", "run", String(itemId2)];
|
|
@@ -27044,8 +27189,13 @@ var SessionManager = class {
|
|
|
27044
27189
|
(id) => createSession(id, prompt, cwd, design, harness)
|
|
27045
27190
|
);
|
|
27046
27191
|
}
|
|
27047
|
-
spawnRun(runName, runArgs, cwd) {
|
|
27048
|
-
return this.spawnWith(
|
|
27192
|
+
spawnRun(runName, runArgs, cwd, meta) {
|
|
27193
|
+
return this.spawnWith(
|
|
27194
|
+
(id) => createRunSession(id, runName, runArgs, cwd, meta)
|
|
27195
|
+
);
|
|
27196
|
+
}
|
|
27197
|
+
liveServerRun(origin, excludeId) {
|
|
27198
|
+
return liveServerRun(this.sessions, origin, excludeId);
|
|
27049
27199
|
}
|
|
27050
27200
|
spawnAssist(assistArgs, cwd, meta) {
|
|
27051
27201
|
return this.spawnWith(
|
|
@@ -27071,9 +27221,13 @@ var SessionManager = class {
|
|
|
27071
27221
|
resizeSession(id, cols, rows) {
|
|
27072
27222
|
resizeSession(this.sessions, id, cols, rows);
|
|
27073
27223
|
}
|
|
27074
|
-
retrySession(id) {
|
|
27075
|
-
|
|
27076
|
-
|
|
27224
|
+
retrySession(id, replace = false) {
|
|
27225
|
+
return runRetry(this.sessions, id, replace, {
|
|
27226
|
+
clients: this.clients,
|
|
27227
|
+
onStatusChange: this.onStatusChange,
|
|
27228
|
+
dismiss: this.dismissSession,
|
|
27229
|
+
notify: this.notify
|
|
27230
|
+
});
|
|
27077
27231
|
}
|
|
27078
27232
|
restart(id) {
|
|
27079
27233
|
const result = restartManagedSession(
|
|
@@ -27088,6 +27242,9 @@ var SessionManager = class {
|
|
|
27088
27242
|
dismissSession = (id) => {
|
|
27089
27243
|
if (dismissSession(this.sessions, id)) this.notify();
|
|
27090
27244
|
};
|
|
27245
|
+
stopSession(id) {
|
|
27246
|
+
stopServerSession(this.sessions, id);
|
|
27247
|
+
}
|
|
27091
27248
|
setAutoRun(id, enabled) {
|
|
27092
27249
|
if (setAutoRun(this.sessions, id, enabled)) this.notify();
|
|
27093
27250
|
}
|
|
@@ -27139,6 +27296,41 @@ function creator(isNew, spawn12) {
|
|
|
27139
27296
|
};
|
|
27140
27297
|
}
|
|
27141
27298
|
|
|
27299
|
+
// src/commands/sessions/daemon/handleCreateRun.ts
|
|
27300
|
+
function handleCreateRun(client, m, d) {
|
|
27301
|
+
if (m.windowsProxy.route(client, d)) return;
|
|
27302
|
+
const runName = d.runName;
|
|
27303
|
+
const cwd = d.cwd;
|
|
27304
|
+
const runArgs = d.runArgs ?? [];
|
|
27305
|
+
const meta = serverRunMeta(runName, cwd);
|
|
27306
|
+
if (meta.server && meta.origin) {
|
|
27307
|
+
const existing = m.liveServerRun(meta.origin);
|
|
27308
|
+
if (existing && d.replace !== true) {
|
|
27309
|
+
daemonLog(
|
|
27310
|
+
`create-run ${runName} rejected: server ${existing.id} already live for ${meta.origin}`
|
|
27311
|
+
);
|
|
27312
|
+
sendTo(client, {
|
|
27313
|
+
type: "run-conflict",
|
|
27314
|
+
runName,
|
|
27315
|
+
cwd,
|
|
27316
|
+
existing: serverConflictInfo(existing)
|
|
27317
|
+
});
|
|
27318
|
+
return;
|
|
27319
|
+
}
|
|
27320
|
+
if (existing) {
|
|
27321
|
+
daemonLog(
|
|
27322
|
+
`create-run ${runName} replacing live server ${existing.id} for ${meta.origin}`
|
|
27323
|
+
);
|
|
27324
|
+
m.dismissSession(existing.id);
|
|
27325
|
+
}
|
|
27326
|
+
}
|
|
27327
|
+
sendTo(client, {
|
|
27328
|
+
type: "created",
|
|
27329
|
+
sessionId: m.spawnRun(runName, runArgs, cwd, meta),
|
|
27330
|
+
isNew: true
|
|
27331
|
+
});
|
|
27332
|
+
}
|
|
27333
|
+
|
|
27142
27334
|
// src/commands/sessions/daemon/handleSetStatus.ts
|
|
27143
27335
|
function handleSetStatus(client, m, d) {
|
|
27144
27336
|
daemonLog(
|
|
@@ -27280,14 +27472,7 @@ var messageHandlers = {
|
|
|
27280
27472
|
"subscribe-logs": (client, m, d) => m.clients.subscribeLogs(client, d.replay !== false),
|
|
27281
27473
|
hello: (client) => sendTo(client, buildHello()),
|
|
27282
27474
|
create: creator(true, spawnCreate),
|
|
27283
|
-
"create-run":
|
|
27284
|
-
true,
|
|
27285
|
-
(m, d) => m.spawnRun(
|
|
27286
|
-
d.runName,
|
|
27287
|
-
d.runArgs ?? [],
|
|
27288
|
-
d.cwd
|
|
27289
|
-
)
|
|
27290
|
-
),
|
|
27475
|
+
"create-run": handleCreateRun,
|
|
27291
27476
|
"create-assist": creator(
|
|
27292
27477
|
true,
|
|
27293
27478
|
(m, d) => m.spawnAssist(
|
|
@@ -27321,13 +27506,22 @@ var messageHandlers = {
|
|
|
27321
27506
|
resize: routed(
|
|
27322
27507
|
(_client, m, d) => m.resizeSession(d.sessionId, d.cols, d.rows)
|
|
27323
27508
|
),
|
|
27324
|
-
retry: routed((
|
|
27509
|
+
retry: routed((client, m, d) => {
|
|
27510
|
+
const conflict = m.retrySession(d.sessionId, d.replace === true);
|
|
27511
|
+
if (conflict)
|
|
27512
|
+
sendTo(client, {
|
|
27513
|
+
type: "run-conflict",
|
|
27514
|
+
sessionId: d.sessionId,
|
|
27515
|
+
existing: conflict
|
|
27516
|
+
});
|
|
27517
|
+
}),
|
|
27325
27518
|
restart: routed((client, m, d) => {
|
|
27326
27519
|
const result = m.restart(d.sessionId);
|
|
27327
27520
|
if (!result.ok && result.reason)
|
|
27328
27521
|
sendTo(client, { type: "error", message: result.reason });
|
|
27329
27522
|
}),
|
|
27330
27523
|
dismiss: routed((_client, m, d) => m.dismissSession(d.sessionId)),
|
|
27524
|
+
stop: routed((_client, m, d) => m.stopSession(d.sessionId)),
|
|
27331
27525
|
"set-autorun": routed(
|
|
27332
27526
|
(_client, m, d) => m.setAutoRun(d.sessionId, d.enabled)
|
|
27333
27527
|
),
|