@staff0rd/assist 0.655.0 → 0.657.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 +3 -3
- package/codex/config.toml +7 -1
- package/dist/commands/sessions/web/bundle.js +251 -251
- package/dist/index.js +552 -528
- package/package.json +1 -1
- package/pi/advice.ts +24 -0
- package/claude/CLAUDE.md +0 -45
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.657.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -307,8 +307,8 @@ function getRemoteOriginUrl(cwd) {
|
|
|
307
307
|
}
|
|
308
308
|
|
|
309
309
|
// src/commands/backlog/getCurrentOrigin.ts
|
|
310
|
-
function stripLeadingSlashes(
|
|
311
|
-
return
|
|
310
|
+
function stripLeadingSlashes(path91) {
|
|
311
|
+
return path91.replace(/^\/+/, "");
|
|
312
312
|
}
|
|
313
313
|
function normalizeOrigin(raw) {
|
|
314
314
|
const trimmed = raw.trim().replace(/\.git$/i, "").replace(/\/+$/, "");
|
|
@@ -358,9 +358,9 @@ function findGitLink(dir) {
|
|
|
358
358
|
}
|
|
359
359
|
return null;
|
|
360
360
|
}
|
|
361
|
-
function isFile(
|
|
361
|
+
function isFile(path91) {
|
|
362
362
|
try {
|
|
363
|
-
return statSync(
|
|
363
|
+
return statSync(path91).isFile();
|
|
364
364
|
} catch {
|
|
365
365
|
return false;
|
|
366
366
|
}
|
|
@@ -379,9 +379,9 @@ function linkedGitDirParent(gitDir) {
|
|
|
379
379
|
const match = /^(.*)[/\\]worktrees[/\\][^/\\]+[/\\]?$/.exec(gitDir);
|
|
380
380
|
return match ? match[1] : null;
|
|
381
381
|
}
|
|
382
|
-
function readTrimmed(
|
|
382
|
+
function readTrimmed(path91) {
|
|
383
383
|
try {
|
|
384
|
-
const content = readFileSync2(
|
|
384
|
+
const content = readFileSync2(path91, "utf8").trim();
|
|
385
385
|
return content === "" ? null : content;
|
|
386
386
|
} catch {
|
|
387
387
|
return null;
|
|
@@ -394,10 +394,10 @@ function absolute(target, from) {
|
|
|
394
394
|
// src/shared/loadRawYaml.ts
|
|
395
395
|
import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
|
|
396
396
|
import { parse as parseYaml } from "yaml";
|
|
397
|
-
function loadRawYaml(
|
|
398
|
-
if (!existsSync3(
|
|
397
|
+
function loadRawYaml(path91) {
|
|
398
|
+
if (!existsSync3(path91)) return {};
|
|
399
399
|
try {
|
|
400
|
-
const content = readFileSync3(
|
|
400
|
+
const content = readFileSync3(path91, "utf8");
|
|
401
401
|
return parseYaml(content) || {};
|
|
402
402
|
} catch {
|
|
403
403
|
return {};
|
|
@@ -469,8 +469,8 @@ function mergeRawConfigs(globalRaw, projectRaw) {
|
|
|
469
469
|
// src/commands/backlog/originDisplayName.ts
|
|
470
470
|
function originDisplayName(origin) {
|
|
471
471
|
if (origin.startsWith("local:")) {
|
|
472
|
-
const
|
|
473
|
-
const segments =
|
|
472
|
+
const path91 = origin.slice("local:".length).replace(/\/+$/, "");
|
|
473
|
+
const segments = path91.split("/").filter(Boolean);
|
|
474
474
|
return segments[segments.length - 1] ?? origin;
|
|
475
475
|
}
|
|
476
476
|
const firstSlash = origin.indexOf("/");
|
|
@@ -2874,11 +2874,11 @@ function enumValues(node) {
|
|
|
2874
2874
|
function opaqueConfigNode(inner, base) {
|
|
2875
2875
|
return { ...base, kind: "other", type: leafTypeOf(inner) };
|
|
2876
2876
|
}
|
|
2877
|
-
function build(node,
|
|
2877
|
+
function build(node, path91) {
|
|
2878
2878
|
const { inner, defaultValue, optional } = unwrapSchemaNode(node);
|
|
2879
2879
|
const secret = isSecretSchemaNode(node) || isSecretSchemaNode(inner);
|
|
2880
2880
|
const base = {
|
|
2881
|
-
path:
|
|
2881
|
+
path: path91,
|
|
2882
2882
|
...optional ? { optional: true } : {},
|
|
2883
2883
|
...defaultValue === void 0 ? {} : { defaultValue },
|
|
2884
2884
|
...secret ? { secret: true } : {}
|
|
@@ -2897,9 +2897,9 @@ function segmentText(segment) {
|
|
|
2897
2897
|
if (segment.kind === "index") return `[${segment.index}]`;
|
|
2898
2898
|
return "[]";
|
|
2899
2899
|
}
|
|
2900
|
-
function formatConfigPath(
|
|
2900
|
+
function formatConfigPath(path91) {
|
|
2901
2901
|
let text18 = "";
|
|
2902
|
-
for (const segment of
|
|
2902
|
+
for (const segment of path91) {
|
|
2903
2903
|
const dotted = segment.kind === "key" || segment.kind === "entry";
|
|
2904
2904
|
const rendered = segmentText(segment);
|
|
2905
2905
|
text18 += dotted && text18 ? `.${rendered}` : rendered;
|
|
@@ -3627,9 +3627,9 @@ import { existsSync as existsSync13, readFileSync as readFileSync10 } from "fs";
|
|
|
3627
3627
|
|
|
3628
3628
|
// src/commands/verify/forbiddenStrings/findForbiddenStrings.ts
|
|
3629
3629
|
import { minimatch as minimatch2 } from "minimatch";
|
|
3630
|
-
function resolveStringsAtPath(data,
|
|
3630
|
+
function resolveStringsAtPath(data, path91) {
|
|
3631
3631
|
let current = data;
|
|
3632
|
-
for (const segment of
|
|
3632
|
+
for (const segment of path91.split(".")) {
|
|
3633
3633
|
if (current === null || typeof current !== "object") return [];
|
|
3634
3634
|
current = current[segment];
|
|
3635
3635
|
}
|
|
@@ -3642,10 +3642,10 @@ function resolveStringsAtPath(data, path90) {
|
|
|
3642
3642
|
}
|
|
3643
3643
|
function findRuleViolations(data, rule) {
|
|
3644
3644
|
const violations = [];
|
|
3645
|
-
for (const
|
|
3646
|
-
for (const value of resolveStringsAtPath(data,
|
|
3645
|
+
for (const path91 of rule.paths) {
|
|
3646
|
+
for (const value of resolveStringsAtPath(data, path91)) {
|
|
3647
3647
|
if (minimatch2(value, rule.disallowed))
|
|
3648
|
-
violations.push({ file: rule.file, path:
|
|
3648
|
+
violations.push({ file: rule.file, path: path91, value });
|
|
3649
3649
|
}
|
|
3650
3650
|
}
|
|
3651
3651
|
return violations;
|
|
@@ -3684,8 +3684,8 @@ function forbiddenStrings() {
|
|
|
3684
3684
|
process.exit(0);
|
|
3685
3685
|
}
|
|
3686
3686
|
console.log("Forbidden strings found:\n");
|
|
3687
|
-
for (const { file, path:
|
|
3688
|
-
console.log(` ${file} ${
|
|
3687
|
+
for (const { file, path: path91, value } of violations) {
|
|
3688
|
+
console.log(` ${file} ${path91}: ${value}`);
|
|
3689
3689
|
}
|
|
3690
3690
|
console.log(`
|
|
3691
3691
|
Total: ${violations.length} forbidden string(s).`);
|
|
@@ -4288,15 +4288,15 @@ function readBaselineMigrations(repoRelativeDir, ref) {
|
|
|
4288
4288
|
} catch {
|
|
4289
4289
|
return baseline;
|
|
4290
4290
|
}
|
|
4291
|
-
const paths = listing.split("\n").map((line) => line.trim()).filter(Boolean).filter((
|
|
4292
|
-
for (const
|
|
4291
|
+
const paths = listing.split("\n").map((line) => line.trim()).filter(Boolean).filter((path91) => MIGRATION_FILE3.test(basename2(path91)));
|
|
4292
|
+
for (const path91 of paths) {
|
|
4293
4293
|
try {
|
|
4294
|
-
const content = execSync6(`git show "${ref}:${
|
|
4294
|
+
const content = execSync6(`git show "${ref}:${path91}"`, {
|
|
4295
4295
|
encoding: "utf8",
|
|
4296
4296
|
maxBuffer: 16 * 1024 * 1024,
|
|
4297
4297
|
stdio: ["pipe", "pipe", "pipe"]
|
|
4298
4298
|
});
|
|
4299
|
-
baseline.set(basename2(
|
|
4299
|
+
baseline.set(basename2(path91), content);
|
|
4300
4300
|
} catch {
|
|
4301
4301
|
}
|
|
4302
4302
|
}
|
|
@@ -5281,6 +5281,18 @@ ${extra}`);
|
|
|
5281
5281
|
return [heading, ...sections].join("\n\n");
|
|
5282
5282
|
}
|
|
5283
5283
|
|
|
5284
|
+
// src/commands/advise/adviceHookPayload.ts
|
|
5285
|
+
function adviceHookPayload(cwd) {
|
|
5286
|
+
const markdown = composeAdvice(adviceContextFor(cwd));
|
|
5287
|
+
if (!markdown) return void 0;
|
|
5288
|
+
return {
|
|
5289
|
+
hookSpecificOutput: {
|
|
5290
|
+
hookEventName: "SessionStart",
|
|
5291
|
+
additionalContext: markdown
|
|
5292
|
+
}
|
|
5293
|
+
};
|
|
5294
|
+
}
|
|
5295
|
+
|
|
5284
5296
|
// src/commands/advise/explainAdvice.ts
|
|
5285
5297
|
import chalk28 from "chalk";
|
|
5286
5298
|
function explainAdvice(context, fragments = loadAdviceFragments()) {
|
|
@@ -5308,22 +5320,22 @@ async function hookCwd(options2) {
|
|
|
5308
5320
|
async function advise(options2 = {}) {
|
|
5309
5321
|
const fallback = options2.cwdFallback ?? process.cwd();
|
|
5310
5322
|
const cwd = options2.hook ? await hookCwd(options2) ?? fallback : fallback;
|
|
5311
|
-
const context = adviceContextFor(cwd);
|
|
5312
5323
|
if (options2.explain) {
|
|
5313
|
-
const explanation = explainAdvice(
|
|
5324
|
+
const explanation = explainAdvice(adviceContextFor(cwd));
|
|
5314
5325
|
console.log(explanation);
|
|
5315
5326
|
return explanation;
|
|
5316
5327
|
}
|
|
5317
|
-
|
|
5328
|
+
if (options2.hook) {
|
|
5329
|
+
const payload = adviceHookPayload(cwd);
|
|
5330
|
+
if (!payload) return "";
|
|
5331
|
+
const output = JSON.stringify(payload);
|
|
5332
|
+
console.log(output);
|
|
5333
|
+
return output;
|
|
5334
|
+
}
|
|
5335
|
+
const markdown = composeAdvice(adviceContextFor(cwd));
|
|
5318
5336
|
if (!markdown) return "";
|
|
5319
|
-
|
|
5320
|
-
|
|
5321
|
-
hookEventName: "SessionStart",
|
|
5322
|
-
additionalContext: markdown
|
|
5323
|
-
}
|
|
5324
|
-
}) : markdown;
|
|
5325
|
-
console.log(output);
|
|
5326
|
-
return output;
|
|
5337
|
+
console.log(markdown);
|
|
5338
|
+
return markdown;
|
|
5327
5339
|
}
|
|
5328
5340
|
|
|
5329
5341
|
// src/commands/registerAdvise.ts
|
|
@@ -6568,10 +6580,10 @@ var hooksSettings = {
|
|
|
6568
6580
|
}
|
|
6569
6581
|
};
|
|
6570
6582
|
function ensureHooksSettings() {
|
|
6571
|
-
const
|
|
6572
|
-
mkdirSync5(dirname14(
|
|
6573
|
-
writeFileSync15(
|
|
6574
|
-
return
|
|
6583
|
+
const path91 = daemonPaths.hooksSettings;
|
|
6584
|
+
mkdirSync5(dirname14(path91), { recursive: true });
|
|
6585
|
+
writeFileSync15(path91, JSON.stringify(hooksSettings, null, 2));
|
|
6586
|
+
return path91;
|
|
6575
6587
|
}
|
|
6576
6588
|
|
|
6577
6589
|
// src/shared/spawnInherit.ts
|
|
@@ -6749,8 +6761,8 @@ function getPreferredRemoteRepo(cwd) {
|
|
|
6749
6761
|
function gitRefUrl(kind, ref, cwd) {
|
|
6750
6762
|
const repo = getPreferredRemoteRepo(cwd);
|
|
6751
6763
|
if (!repo) return void 0;
|
|
6752
|
-
const
|
|
6753
|
-
return `https://github.com/${repo.org}/${repo.repo}/${
|
|
6764
|
+
const path91 = kind === "branch" ? "tree" : "commit";
|
|
6765
|
+
return `https://github.com/${repo.org}/${repo.repo}/${path91}/${ref}`;
|
|
6754
6766
|
}
|
|
6755
6767
|
|
|
6756
6768
|
// src/commands/branch/buildBranchName.ts
|
|
@@ -6993,9 +7005,9 @@ var LOCAL_FILES = ["backlog.jsonl", "backlog.db"];
|
|
|
6993
7005
|
function backupLocalBacklogFiles(dir) {
|
|
6994
7006
|
const moved = [];
|
|
6995
7007
|
for (const name of LOCAL_FILES) {
|
|
6996
|
-
const
|
|
6997
|
-
if (existsSync21(
|
|
6998
|
-
renameSync(
|
|
7008
|
+
const path91 = join18(dir, ".assist", name);
|
|
7009
|
+
if (existsSync21(path91)) {
|
|
7010
|
+
renameSync(path91, `${path91}.bak`);
|
|
6999
7011
|
moved.push(`${name} \u2192 ${name}.bak`);
|
|
7000
7012
|
}
|
|
7001
7013
|
}
|
|
@@ -7479,8 +7491,8 @@ var backlogItemSchema = z4.strictObject({
|
|
|
7479
7491
|
var backlogFileSchema = z4.array(backlogItemSchema);
|
|
7480
7492
|
|
|
7481
7493
|
// src/commands/backlog/parseBacklogJsonl.ts
|
|
7482
|
-
function parseBacklogJsonl(
|
|
7483
|
-
const content = readFileSync16(
|
|
7494
|
+
function parseBacklogJsonl(path91) {
|
|
7495
|
+
const content = readFileSync16(path91, "utf8").trim();
|
|
7484
7496
|
if (content.length === 0) return [];
|
|
7485
7497
|
return content.split("\n").map((line) => line.trim()).filter(Boolean).map((line) => backlogItemSchema.parse(JSON.parse(line)));
|
|
7486
7498
|
}
|
|
@@ -8200,7 +8212,6 @@ var harnesses = {
|
|
|
8200
8212
|
command: "claude",
|
|
8201
8213
|
homeDir: path23.join(os.homedir(), ".claude"),
|
|
8202
8214
|
sync: {
|
|
8203
|
-
agentsFile: "CLAUDE.md",
|
|
8204
8215
|
commandDest: (name) => path23.join("commands", `${name}.md`)
|
|
8205
8216
|
}
|
|
8206
8217
|
},
|
|
@@ -8209,7 +8220,6 @@ var harnesses = {
|
|
|
8209
8220
|
command: "codex",
|
|
8210
8221
|
homeDir: path23.join(os.homedir(), ".codex"),
|
|
8211
8222
|
sync: {
|
|
8212
|
-
agentsFile: "AGENTS.md",
|
|
8213
8223
|
commandDest: (name) => path23.join("skills", name, "SKILL.md")
|
|
8214
8224
|
}
|
|
8215
8225
|
},
|
|
@@ -8218,7 +8228,6 @@ var harnesses = {
|
|
|
8218
8228
|
command: "pi",
|
|
8219
8229
|
homeDir: path23.join(os.homedir(), ".pi", "agent"),
|
|
8220
8230
|
sync: {
|
|
8221
|
-
agentsFile: "AGENTS.md",
|
|
8222
8231
|
commandDest: (name) => path23.join("prompts", `${name}.md`)
|
|
8223
8232
|
}
|
|
8224
8233
|
}
|
|
@@ -8291,24 +8300,24 @@ function getOwnerPath(itemId2) {
|
|
|
8291
8300
|
function recordSignalOwner(itemId2) {
|
|
8292
8301
|
const sessionId = process.env.ASSIST_SESSION_ID;
|
|
8293
8302
|
if (!sessionId) return;
|
|
8294
|
-
const
|
|
8295
|
-
mkdirSync7(dirname16(
|
|
8296
|
-
writeFileSync17(
|
|
8303
|
+
const path91 = getOwnerPath(itemId2);
|
|
8304
|
+
mkdirSync7(dirname16(path91), { recursive: true });
|
|
8305
|
+
writeFileSync17(path91, JSON.stringify({ sessionId }));
|
|
8297
8306
|
}
|
|
8298
8307
|
function readSignalOwner(itemId2) {
|
|
8299
|
-
const
|
|
8300
|
-
if (!existsSync25(
|
|
8308
|
+
const path91 = getOwnerPath(itemId2);
|
|
8309
|
+
if (!existsSync25(path91)) return void 0;
|
|
8301
8310
|
try {
|
|
8302
|
-
const parsed = JSON.parse(readFileSync17(
|
|
8311
|
+
const parsed = JSON.parse(readFileSync17(path91, "utf8"));
|
|
8303
8312
|
return parsed.sessionId;
|
|
8304
8313
|
} catch {
|
|
8305
8314
|
return void 0;
|
|
8306
8315
|
}
|
|
8307
8316
|
}
|
|
8308
8317
|
function clearSignalOwner(itemId2) {
|
|
8309
|
-
const
|
|
8318
|
+
const path91 = getOwnerPath(itemId2);
|
|
8310
8319
|
try {
|
|
8311
|
-
rmSync(
|
|
8320
|
+
rmSync(path91);
|
|
8312
8321
|
} catch {
|
|
8313
8322
|
}
|
|
8314
8323
|
}
|
|
@@ -8345,19 +8354,19 @@ function resolveSignalTarget(event, data) {
|
|
|
8345
8354
|
function writeSignal(event, data) {
|
|
8346
8355
|
const target = resolveSignalTarget(event, data);
|
|
8347
8356
|
if (!target) return;
|
|
8348
|
-
const
|
|
8349
|
-
if (!
|
|
8357
|
+
const path91 = getSignalPath(target);
|
|
8358
|
+
if (!path91) return;
|
|
8350
8359
|
const signal = { event, sessionId: target, ...data };
|
|
8351
|
-
mkdirSync8(dirname17(
|
|
8352
|
-
writeFileSync18(
|
|
8360
|
+
mkdirSync8(dirname17(path91), { recursive: true });
|
|
8361
|
+
writeFileSync18(path91, JSON.stringify(signal));
|
|
8353
8362
|
}
|
|
8354
8363
|
|
|
8355
8364
|
// src/commands/backlog/readSignal.ts
|
|
8356
8365
|
function readSignal() {
|
|
8357
|
-
const
|
|
8358
|
-
if (!
|
|
8366
|
+
const path91 = getSignalPath();
|
|
8367
|
+
if (!path91 || !existsSync26(path91)) return void 0;
|
|
8359
8368
|
try {
|
|
8360
|
-
return JSON.parse(readFileSync18(
|
|
8369
|
+
return JSON.parse(readFileSync18(path91, "utf8"));
|
|
8361
8370
|
} catch {
|
|
8362
8371
|
return void 0;
|
|
8363
8372
|
}
|
|
@@ -8555,13 +8564,13 @@ function activityPath(sessionId) {
|
|
|
8555
8564
|
function emitActivity(activity2) {
|
|
8556
8565
|
const sessionId = process.env.ASSIST_ACTIVITY_ID;
|
|
8557
8566
|
if (!sessionId) return;
|
|
8558
|
-
const
|
|
8559
|
-
mkdirSync9(dirname18(
|
|
8560
|
-
writeFileSync19(
|
|
8567
|
+
const path91 = activityPath(sessionId);
|
|
8568
|
+
mkdirSync9(dirname18(path91), { recursive: true });
|
|
8569
|
+
writeFileSync19(path91, JSON.stringify({ ...activity2, startedAt: Date.now() }));
|
|
8561
8570
|
}
|
|
8562
|
-
function readActivity(
|
|
8571
|
+
function readActivity(path91) {
|
|
8563
8572
|
try {
|
|
8564
|
-
return JSON.parse(readFileSync19(
|
|
8573
|
+
return JSON.parse(readFileSync19(path91, "utf8"));
|
|
8565
8574
|
} catch {
|
|
8566
8575
|
return void 0;
|
|
8567
8576
|
}
|
|
@@ -8571,9 +8580,9 @@ function reconcileActivity(sessionId, activity2) {
|
|
|
8571
8580
|
removeActivity(sessionId);
|
|
8572
8581
|
return;
|
|
8573
8582
|
}
|
|
8574
|
-
const
|
|
8575
|
-
mkdirSync9(dirname18(
|
|
8576
|
-
writeFileSync19(
|
|
8583
|
+
const path91 = activityPath(sessionId);
|
|
8584
|
+
mkdirSync9(dirname18(path91), { recursive: true });
|
|
8585
|
+
writeFileSync19(path91, JSON.stringify(activity2));
|
|
8577
8586
|
}
|
|
8578
8587
|
function removeActivity(sessionId) {
|
|
8579
8588
|
try {
|
|
@@ -10038,10 +10047,10 @@ function getStorePath(filename) {
|
|
|
10038
10047
|
return join29(getStoreDir(), filename);
|
|
10039
10048
|
}
|
|
10040
10049
|
function loadJson(filename) {
|
|
10041
|
-
const
|
|
10042
|
-
if (existsSync31(
|
|
10050
|
+
const path91 = getStorePath(filename);
|
|
10051
|
+
if (existsSync31(path91)) {
|
|
10043
10052
|
try {
|
|
10044
|
-
return JSON.parse(readFileSync20(
|
|
10053
|
+
return JSON.parse(readFileSync20(path91, "utf8"));
|
|
10045
10054
|
} catch {
|
|
10046
10055
|
return {};
|
|
10047
10056
|
}
|
|
@@ -10060,22 +10069,22 @@ function saveJson(filename, data) {
|
|
|
10060
10069
|
var REGISTRY_FILE = "worktrees.json";
|
|
10061
10070
|
function readWorktreeRegistry() {
|
|
10062
10071
|
const data = loadJson(REGISTRY_FILE);
|
|
10063
|
-
return Object.entries(data).filter(([, record]) => !record.reaped).map(([
|
|
10072
|
+
return Object.entries(data).filter(([, record]) => !record.reaped).map(([path91, record]) => ({ path: path91, ...record }));
|
|
10064
10073
|
}
|
|
10065
|
-
function worktreeAttributionIncludingReaped(
|
|
10066
|
-
const record = loadJson(REGISTRY_FILE)[
|
|
10074
|
+
function worktreeAttributionIncludingReaped(path91) {
|
|
10075
|
+
const record = loadJson(REGISTRY_FILE)[path91];
|
|
10067
10076
|
return record ? { clone: record.clone, origin: record.origin } : void 0;
|
|
10068
10077
|
}
|
|
10069
|
-
function recordWorktree(
|
|
10078
|
+
function recordWorktree(path91, clone, origin) {
|
|
10070
10079
|
const data = loadJson(REGISTRY_FILE);
|
|
10071
|
-
data[
|
|
10080
|
+
data[path91] = { clone, origin };
|
|
10072
10081
|
saveJson(REGISTRY_FILE, data);
|
|
10073
10082
|
}
|
|
10074
|
-
function forgetWorktree(
|
|
10083
|
+
function forgetWorktree(path91) {
|
|
10075
10084
|
const data = loadJson(REGISTRY_FILE);
|
|
10076
|
-
const record = data[
|
|
10085
|
+
const record = data[path91];
|
|
10077
10086
|
if (!record || record.reaped) return;
|
|
10078
|
-
data[
|
|
10087
|
+
data[path91] = { ...record, reaped: true };
|
|
10079
10088
|
saveJson(REGISTRY_FILE, data);
|
|
10080
10089
|
}
|
|
10081
10090
|
|
|
@@ -10903,8 +10912,8 @@ async function loadCommittedPaths(cwd, sessionId) {
|
|
|
10903
10912
|
for (const commit2 of commits2) {
|
|
10904
10913
|
const resolved = await resolveCommit(cwd, commit2.sha);
|
|
10905
10914
|
if (!resolved) continue;
|
|
10906
|
-
for (const
|
|
10907
|
-
if (!bases.has(
|
|
10915
|
+
for (const path91 of resolved.paths) {
|
|
10916
|
+
if (!bases.has(path91)) bases.set(path91, resolved.base);
|
|
10908
10917
|
}
|
|
10909
10918
|
}
|
|
10910
10919
|
return { commits: commits2, bases };
|
|
@@ -10922,16 +10931,16 @@ async function itemChangeSet(cwd, sessionId) {
|
|
|
10922
10931
|
}
|
|
10923
10932
|
function groupByBase(bases) {
|
|
10924
10933
|
const groups = /* @__PURE__ */ new Map();
|
|
10925
|
-
for (const [
|
|
10934
|
+
for (const [path91, base] of bases) {
|
|
10926
10935
|
const paths = groups.get(base);
|
|
10927
|
-
if (paths) paths.push(
|
|
10928
|
-
else groups.set(base, [
|
|
10936
|
+
if (paths) paths.push(path91);
|
|
10937
|
+
else groups.set(base, [path91]);
|
|
10929
10938
|
}
|
|
10930
10939
|
return [...groups].map(([base, paths]) => ({ base, paths: paths.sort() }));
|
|
10931
10940
|
}
|
|
10932
10941
|
async function dirtyPaths(cwd, bases) {
|
|
10933
10942
|
const output = await execGit(cwd, ["diff", "--name-only", "HEAD"]);
|
|
10934
|
-
return output.split("\n").filter((
|
|
10943
|
+
return output.split("\n").filter((path91) => path91 && !bases.has(path91)).sort();
|
|
10935
10944
|
}
|
|
10936
10945
|
|
|
10937
10946
|
// src/commands/sessions/web/scopedDiff.ts
|
|
@@ -10940,8 +10949,8 @@ async function scopedDiff(cwd, session, scope) {
|
|
|
10940
10949
|
if (scope.kind === "commit") return commitDiff(cwd, scope.sha);
|
|
10941
10950
|
return await trackedScopeDiff(cwd, session, scope) + await untrackedDiff(cwd);
|
|
10942
10951
|
}
|
|
10943
|
-
async function untrackedFileDiff(cwd,
|
|
10944
|
-
return execGit(cwd, ["diff", "--no-index", "--", "/dev/null",
|
|
10952
|
+
async function untrackedFileDiff(cwd, path91) {
|
|
10953
|
+
return execGit(cwd, ["diff", "--no-index", "--", "/dev/null", path91], {
|
|
10945
10954
|
maxBuffer: MAX_DIFF_BYTES,
|
|
10946
10955
|
allowFailure: true
|
|
10947
10956
|
});
|
|
@@ -10954,7 +10963,7 @@ async function untrackedDiff(cwd) {
|
|
|
10954
10963
|
]);
|
|
10955
10964
|
const paths = list5.split("\n").filter(Boolean);
|
|
10956
10965
|
const diffs = await Promise.all(
|
|
10957
|
-
paths.map((
|
|
10966
|
+
paths.map((path91) => untrackedFileDiff(cwd, path91))
|
|
10958
10967
|
);
|
|
10959
10968
|
return diffs.join("");
|
|
10960
10969
|
}
|
|
@@ -11047,9 +11056,9 @@ import { isAbsolute as isAbsolute2, relative as relative2, resolve as resolve10
|
|
|
11047
11056
|
function repoRoot(cwd) {
|
|
11048
11057
|
return resolve10(toGitCwd(cwd));
|
|
11049
11058
|
}
|
|
11050
|
-
function resolveWithinCwd(cwd,
|
|
11059
|
+
function resolveWithinCwd(cwd, path91) {
|
|
11051
11060
|
const root = repoRoot(cwd);
|
|
11052
|
-
const target = resolve10(root,
|
|
11061
|
+
const target = resolve10(root, path91);
|
|
11053
11062
|
const rel = relative2(root, target);
|
|
11054
11063
|
if (rel === "" || rel.startsWith("..") || isAbsolute2(rel)) return null;
|
|
11055
11064
|
return target;
|
|
@@ -11059,14 +11068,14 @@ function resolveWithinCwd(cwd, path90) {
|
|
|
11059
11068
|
function getFileTarget(req, res) {
|
|
11060
11069
|
const cwd = getCwdParam(req, res);
|
|
11061
11070
|
if (!cwd) return null;
|
|
11062
|
-
const
|
|
11071
|
+
const path91 = new URL(req.url ?? "/", "http://localhost").searchParams.get(
|
|
11063
11072
|
"path"
|
|
11064
11073
|
);
|
|
11065
|
-
if (!
|
|
11074
|
+
if (!path91) {
|
|
11066
11075
|
respondJson(res, 400, { error: "Missing path" });
|
|
11067
11076
|
return null;
|
|
11068
11077
|
}
|
|
11069
|
-
const target = resolveWithinCwd(cwd,
|
|
11078
|
+
const target = resolveWithinCwd(cwd, path91);
|
|
11070
11079
|
if (!target) {
|
|
11071
11080
|
respondJson(res, 400, { error: "Path outside cwd" });
|
|
11072
11081
|
return null;
|
|
@@ -11141,11 +11150,11 @@ function globalConfigTargetFor(cwd) {
|
|
|
11141
11150
|
|
|
11142
11151
|
// src/commands/config/globalConfigFileLabel.ts
|
|
11143
11152
|
var WINDOWS_MOUNT_PREFIX = "/mnt/";
|
|
11144
|
-
function globalConfigFileLabel(
|
|
11145
|
-
if (
|
|
11146
|
-
if (
|
|
11147
|
-
return `${
|
|
11148
|
-
return
|
|
11153
|
+
function globalConfigFileLabel(path91) {
|
|
11154
|
+
if (path91 === getGlobalConfigPath()) return "~/.assist.yml";
|
|
11155
|
+
if (path91.startsWith(WINDOWS_MOUNT_PREFIX))
|
|
11156
|
+
return `${path91} on the Windows host`;
|
|
11157
|
+
return path91;
|
|
11149
11158
|
}
|
|
11150
11159
|
|
|
11151
11160
|
// src/commands/config/readRawConfigLayers.ts
|
|
@@ -11202,35 +11211,35 @@ function isPlainRecord(value) {
|
|
|
11202
11211
|
}
|
|
11203
11212
|
|
|
11204
11213
|
// src/shared/mapConfigSecrets.ts
|
|
11205
|
-
function mapChildren(value,
|
|
11214
|
+
function mapChildren(value, path91, childNode, map) {
|
|
11206
11215
|
if (!isPlainRecord(value)) return value;
|
|
11207
11216
|
return Object.fromEntries(
|
|
11208
11217
|
Object.entries(value).map(([name, child]) => [
|
|
11209
11218
|
name,
|
|
11210
|
-
walk(child, [...
|
|
11219
|
+
walk(child, [...path91, name], childNode(name), map)
|
|
11211
11220
|
])
|
|
11212
11221
|
);
|
|
11213
11222
|
}
|
|
11214
|
-
function mapItems(value,
|
|
11223
|
+
function mapItems(value, path91, item, map) {
|
|
11215
11224
|
if (!Array.isArray(value)) return value;
|
|
11216
|
-
return value.map((entry, index3) => walk(entry, [...
|
|
11225
|
+
return value.map((entry, index3) => walk(entry, [...path91, index3], item, map));
|
|
11217
11226
|
}
|
|
11218
|
-
function walk(value,
|
|
11227
|
+
function walk(value, path91, node, map) {
|
|
11219
11228
|
if (!node || value === void 0 || value === null) return value;
|
|
11220
|
-
if (node.secret) return map(value,
|
|
11229
|
+
if (node.secret) return map(value, path91);
|
|
11221
11230
|
switch (node.kind) {
|
|
11222
11231
|
case "object":
|
|
11223
11232
|
case "unionOfObjects":
|
|
11224
11233
|
return mapChildren(
|
|
11225
11234
|
value,
|
|
11226
|
-
|
|
11235
|
+
path91,
|
|
11227
11236
|
(name) => configNodeField(node, name),
|
|
11228
11237
|
map
|
|
11229
11238
|
);
|
|
11230
11239
|
case "objectList":
|
|
11231
|
-
return mapItems(value,
|
|
11240
|
+
return mapItems(value, path91, node.item, map);
|
|
11232
11241
|
case "record":
|
|
11233
|
-
return mapChildren(value,
|
|
11242
|
+
return mapChildren(value, path91, () => node.value, map);
|
|
11234
11243
|
default:
|
|
11235
11244
|
return value;
|
|
11236
11245
|
}
|
|
@@ -11255,9 +11264,9 @@ function isTraversable(value) {
|
|
|
11255
11264
|
function stepInto(current, key) {
|
|
11256
11265
|
return isTraversable(current) ? current[key] : void 0;
|
|
11257
11266
|
}
|
|
11258
|
-
function getNestedValue(obj,
|
|
11267
|
+
function getNestedValue(obj, path91) {
|
|
11259
11268
|
let current = obj;
|
|
11260
|
-
for (const key of
|
|
11269
|
+
for (const key of path91.split(".")) current = stepInto(current, key);
|
|
11261
11270
|
return current;
|
|
11262
11271
|
}
|
|
11263
11272
|
|
|
@@ -11307,9 +11316,9 @@ function step(node, segment) {
|
|
|
11307
11316
|
return void 0;
|
|
11308
11317
|
}
|
|
11309
11318
|
}
|
|
11310
|
-
function findConfigNode(root,
|
|
11319
|
+
function findConfigNode(root, path91) {
|
|
11311
11320
|
let current = root;
|
|
11312
|
-
for (const segment of
|
|
11321
|
+
for (const segment of path91) {
|
|
11313
11322
|
if (!current) return void 0;
|
|
11314
11323
|
current = step(current, segment);
|
|
11315
11324
|
}
|
|
@@ -11326,34 +11335,34 @@ function nameSegment(name) {
|
|
|
11326
11335
|
return name === RECORD_ENTRY_TOKEN ? { kind: "entry" } : { kind: "key", name };
|
|
11327
11336
|
}
|
|
11328
11337
|
function parseConfigPath(text18) {
|
|
11329
|
-
const
|
|
11338
|
+
const path91 = [];
|
|
11330
11339
|
let at2 = 0;
|
|
11331
11340
|
while (at2 < text18.length) {
|
|
11332
11341
|
if (text18[at2] === "[") {
|
|
11333
11342
|
const close = text18.indexOf("]", at2);
|
|
11334
11343
|
const segment = close === -1 ? void 0 : bracketSegment(text18.slice(at2 + 1, close));
|
|
11335
11344
|
if (!segment) return void 0;
|
|
11336
|
-
|
|
11345
|
+
path91.push(segment);
|
|
11337
11346
|
at2 = close + 1;
|
|
11338
11347
|
continue;
|
|
11339
11348
|
}
|
|
11340
11349
|
if (text18[at2] === ".") {
|
|
11341
|
-
if (
|
|
11350
|
+
if (path91.length === 0) return void 0;
|
|
11342
11351
|
at2 += 1;
|
|
11343
11352
|
}
|
|
11344
11353
|
const start3 = at2;
|
|
11345
11354
|
while (at2 < text18.length && text18[at2] !== "." && text18[at2] !== "[") at2 += 1;
|
|
11346
11355
|
const name = text18.slice(start3, at2);
|
|
11347
11356
|
if (!name) return void 0;
|
|
11348
|
-
|
|
11357
|
+
path91.push(nameSegment(name));
|
|
11349
11358
|
}
|
|
11350
|
-
return
|
|
11359
|
+
return path91;
|
|
11351
11360
|
}
|
|
11352
11361
|
|
|
11353
11362
|
// src/commands/config/configEntryNode.ts
|
|
11354
11363
|
function configEntryNode(root, key) {
|
|
11355
|
-
const
|
|
11356
|
-
return
|
|
11364
|
+
const path91 = parseConfigPath(key);
|
|
11365
|
+
return path91 ? findConfigNode(root, path91) : void 0;
|
|
11357
11366
|
}
|
|
11358
11367
|
|
|
11359
11368
|
// src/commands/config/configHelpForKey.ts
|
|
@@ -11488,7 +11497,7 @@ function findSynthesisForBranch(repoReviewsDir, branch2) {
|
|
|
11488
11497
|
const parent = dirname22(branchKeyPath);
|
|
11489
11498
|
const branchPrefix = basename10(branchKeyPath);
|
|
11490
11499
|
if (!existsSync34(parent)) return null;
|
|
11491
|
-
const synthesisFiles = readdirSync3(parent).filter((name) => name.startsWith(branchPrefix)).map((name) => join32(parent, name, "synthesis.md")).filter((
|
|
11500
|
+
const synthesisFiles = readdirSync3(parent).filter((name) => name.startsWith(branchPrefix)).map((name) => join32(parent, name, "synthesis.md")).filter((path91) => existsSync34(path91)).map((path91) => ({ path: path91, mtime: statSync4(path91).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
|
|
11492
11501
|
return synthesisFiles[0]?.path ?? null;
|
|
11493
11502
|
}
|
|
11494
11503
|
|
|
@@ -11518,12 +11527,12 @@ async function getReviewSynthesis(req, res) {
|
|
|
11518
11527
|
const cwd = getCwdParam(req, res);
|
|
11519
11528
|
if (!cwd) return;
|
|
11520
11529
|
try {
|
|
11521
|
-
const
|
|
11522
|
-
if (!
|
|
11530
|
+
const path91 = await resolveSynthesisPath(cwd);
|
|
11531
|
+
if (!path91) {
|
|
11523
11532
|
respondJson(res, 404, { error: "No synthesis found" });
|
|
11524
11533
|
return;
|
|
11525
11534
|
}
|
|
11526
|
-
respondJson(res, 200, { synthesis: readFileSync22(
|
|
11535
|
+
respondJson(res, 200, { synthesis: readFileSync22(path91, "utf8") });
|
|
11527
11536
|
} catch {
|
|
11528
11537
|
respondJson(res, 404, { error: "No synthesis found" });
|
|
11529
11538
|
}
|
|
@@ -11606,8 +11615,8 @@ function parseDiffNameStatus(output) {
|
|
|
11606
11615
|
if (!status3 || fields.length < 2) continue;
|
|
11607
11616
|
const category = categorize(status3[0]);
|
|
11608
11617
|
if (!category) continue;
|
|
11609
|
-
const
|
|
11610
|
-
if (
|
|
11618
|
+
const path91 = fields[fields.length - 1];
|
|
11619
|
+
if (path91) result[category].push(path91);
|
|
11611
11620
|
}
|
|
11612
11621
|
return result;
|
|
11613
11622
|
}
|
|
@@ -11743,21 +11752,21 @@ function subsequenceScore(text18, query) {
|
|
|
11743
11752
|
}
|
|
11744
11753
|
return score - Math.min(text18.length, MAX_LENGTH_PENALTY);
|
|
11745
11754
|
}
|
|
11746
|
-
function scoreFilePath(
|
|
11755
|
+
function scoreFilePath(path91, query) {
|
|
11747
11756
|
const needle = query.trim().toLowerCase();
|
|
11748
11757
|
if (!needle) return 0;
|
|
11749
|
-
const basename29 =
|
|
11758
|
+
const basename29 = path91.slice(path91.lastIndexOf("/") + 1);
|
|
11750
11759
|
const inBasename = subsequenceScore(basename29, needle);
|
|
11751
11760
|
if (inBasename !== null) return BASENAME_WEIGHT + inBasename;
|
|
11752
|
-
return subsequenceScore(
|
|
11761
|
+
return subsequenceScore(path91, needle);
|
|
11753
11762
|
}
|
|
11754
11763
|
|
|
11755
11764
|
// src/commands/sessions/web/rankFilePaths.ts
|
|
11756
11765
|
function rankFilePaths(paths, query, limit) {
|
|
11757
11766
|
const scored = [];
|
|
11758
|
-
for (const
|
|
11759
|
-
const score = scoreFilePath(
|
|
11760
|
-
if (score !== null) scored.push({ path:
|
|
11767
|
+
for (const path91 of paths) {
|
|
11768
|
+
const score = scoreFilePath(path91, query);
|
|
11769
|
+
if (score !== null) scored.push({ path: path91, score });
|
|
11761
11770
|
}
|
|
11762
11771
|
scored.sort((a, b) => b.score - a.score || a.path.localeCompare(b.path));
|
|
11763
11772
|
return scored.slice(0, limit).map((entry) => entry.path);
|
|
@@ -12498,38 +12507,38 @@ async function restartWeb(req, res, deps2 = {}) {
|
|
|
12498
12507
|
import { relative as relative3 } from "path";
|
|
12499
12508
|
|
|
12500
12509
|
// src/commands/sessions/web/revertPathChanges.ts
|
|
12501
|
-
async function isTracked(cwd,
|
|
12510
|
+
async function isTracked(cwd, path91) {
|
|
12502
12511
|
try {
|
|
12503
|
-
await execGit(cwd, ["ls-files", "--error-unmatch", "--",
|
|
12512
|
+
await execGit(cwd, ["ls-files", "--error-unmatch", "--", path91]);
|
|
12504
12513
|
return true;
|
|
12505
12514
|
} catch {
|
|
12506
12515
|
return false;
|
|
12507
12516
|
}
|
|
12508
12517
|
}
|
|
12509
|
-
async function isInHead(cwd,
|
|
12510
|
-
const listing = await execGit(cwd, ["ls-tree", "HEAD", "--",
|
|
12518
|
+
async function isInHead(cwd, path91) {
|
|
12519
|
+
const listing = await execGit(cwd, ["ls-tree", "HEAD", "--", path91]);
|
|
12511
12520
|
return listing.trim().length > 0;
|
|
12512
12521
|
}
|
|
12513
|
-
async function revertPathChanges(cwd,
|
|
12514
|
-
if (!await isTracked(cwd,
|
|
12515
|
-
await execGit(cwd, ["clean", "-f", "--",
|
|
12522
|
+
async function revertPathChanges(cwd, path91) {
|
|
12523
|
+
if (!await isTracked(cwd, path91)) {
|
|
12524
|
+
await execGit(cwd, ["clean", "-f", "--", path91]);
|
|
12516
12525
|
return;
|
|
12517
12526
|
}
|
|
12518
|
-
if (await isInHead(cwd,
|
|
12519
|
-
await execGit(cwd, ["checkout", "HEAD", "--",
|
|
12527
|
+
if (await isInHead(cwd, path91)) {
|
|
12528
|
+
await execGit(cwd, ["checkout", "HEAD", "--", path91]);
|
|
12520
12529
|
return;
|
|
12521
12530
|
}
|
|
12522
|
-
await execGit(cwd, ["rm", "-f", "--",
|
|
12531
|
+
await execGit(cwd, ["rm", "-f", "--", path91]);
|
|
12523
12532
|
}
|
|
12524
12533
|
|
|
12525
12534
|
// src/commands/sessions/web/revertDiffFile.ts
|
|
12526
12535
|
async function revertDiffFile(req, res) {
|
|
12527
12536
|
const resolved = getFileTarget(req, res);
|
|
12528
12537
|
if (!resolved) return;
|
|
12529
|
-
const
|
|
12538
|
+
const path91 = relative3(repoRoot(resolved.cwd), resolved.target);
|
|
12530
12539
|
try {
|
|
12531
|
-
await revertPathChanges(resolved.cwd,
|
|
12532
|
-
respondJson(res, 200, { reverted:
|
|
12540
|
+
await revertPathChanges(resolved.cwd, path91);
|
|
12541
|
+
respondJson(res, 200, { reverted: path91 });
|
|
12533
12542
|
} catch (error) {
|
|
12534
12543
|
respondJson(res, 500, {
|
|
12535
12544
|
error: error instanceof Error ? error.message : "Failed to revert file"
|
|
@@ -12551,7 +12560,7 @@ async function readJsonBody(req) {
|
|
|
12551
12560
|
function requestedPaths(body) {
|
|
12552
12561
|
const paths = body.paths;
|
|
12553
12562
|
if (!Array.isArray(paths)) return null;
|
|
12554
|
-
if (paths.some((
|
|
12563
|
+
if (paths.some((path91) => typeof path91 !== "string")) return null;
|
|
12555
12564
|
return paths;
|
|
12556
12565
|
}
|
|
12557
12566
|
async function revertDiffPaths(req, res) {
|
|
@@ -12571,10 +12580,10 @@ async function revertDiffPaths(req, res) {
|
|
|
12571
12580
|
const root = repoRoot(cwd);
|
|
12572
12581
|
const reverted = [];
|
|
12573
12582
|
const failed2 = [];
|
|
12574
|
-
for (const
|
|
12575
|
-
const target = resolveWithinCwd(cwd,
|
|
12583
|
+
for (const path91 of paths) {
|
|
12584
|
+
const target = resolveWithinCwd(cwd, path91);
|
|
12576
12585
|
if (!target) {
|
|
12577
|
-
failed2.push({ path:
|
|
12586
|
+
failed2.push({ path: path91, error: "Path outside cwd" });
|
|
12578
12587
|
continue;
|
|
12579
12588
|
}
|
|
12580
12589
|
const relativePath = relative4(root, target);
|
|
@@ -12664,11 +12673,11 @@ function coerceStructuredConfigValue(key, raw) {
|
|
|
12664
12673
|
};
|
|
12665
12674
|
}
|
|
12666
12675
|
function formatIssue(key, issue) {
|
|
12667
|
-
const
|
|
12676
|
+
const path91 = formatConfigPath([
|
|
12668
12677
|
{ kind: "key", name: key },
|
|
12669
12678
|
...issue.path.map(toSegment)
|
|
12670
12679
|
]);
|
|
12671
|
-
return `${
|
|
12680
|
+
return `${path91}: ${issue.message}`;
|
|
12672
12681
|
}
|
|
12673
12682
|
function toSegment(part) {
|
|
12674
12683
|
return typeof part === "number" ? { kind: "index", index: part } : { kind: "key", name: String(part) };
|
|
@@ -12763,9 +12772,9 @@ function coerceUnion(key, raw, types) {
|
|
|
12763
12772
|
}
|
|
12764
12773
|
|
|
12765
12774
|
// src/shared/valueAtConfigPath.ts
|
|
12766
|
-
function valueAtConfigPath(value,
|
|
12775
|
+
function valueAtConfigPath(value, path91) {
|
|
12767
12776
|
let current = value;
|
|
12768
|
-
for (const key of
|
|
12777
|
+
for (const key of path91) {
|
|
12769
12778
|
if (typeof key === "number") {
|
|
12770
12779
|
if (!Array.isArray(current)) return void 0;
|
|
12771
12780
|
current = current[key];
|
|
@@ -12782,7 +12791,7 @@ function restoreConfigSecrets(value, stored, node) {
|
|
|
12782
12791
|
return mapConfigSecrets(
|
|
12783
12792
|
value,
|
|
12784
12793
|
node,
|
|
12785
|
-
(secret,
|
|
12794
|
+
(secret, path91) => isRedactedSecret(secret) ? valueAtConfigPath(stored, path91) : secret
|
|
12786
12795
|
);
|
|
12787
12796
|
}
|
|
12788
12797
|
|
|
@@ -12831,8 +12840,8 @@ function stepIntoNested(container, key, nextKey) {
|
|
|
12831
12840
|
}
|
|
12832
12841
|
return ensureObject(container, resolved);
|
|
12833
12842
|
}
|
|
12834
|
-
function setNestedValue(obj,
|
|
12835
|
-
const keys =
|
|
12843
|
+
function setNestedValue(obj, path91, value) {
|
|
12844
|
+
const keys = path91.split(".");
|
|
12836
12845
|
const result = { ...obj };
|
|
12837
12846
|
let current = result;
|
|
12838
12847
|
for (let i = 0; i < keys.length - 1; i++) {
|
|
@@ -12859,8 +12868,8 @@ function formatIssue2(issue, key) {
|
|
|
12859
12868
|
return issue.keys.map(
|
|
12860
12869
|
(unrecognized) => `${[...issue.path, unrecognized].join(".")}: Unrecognized key`
|
|
12861
12870
|
);
|
|
12862
|
-
const
|
|
12863
|
-
return [`${
|
|
12871
|
+
const path91 = issue.path.length > 0 ? issue.path.join(".") : key;
|
|
12872
|
+
return [`${path91}: ${issue.message}`];
|
|
12864
12873
|
}
|
|
12865
12874
|
|
|
12866
12875
|
// src/commands/config/applyConfigSet.ts
|
|
@@ -13117,8 +13126,8 @@ function removeAt(container, keys) {
|
|
|
13117
13126
|
}
|
|
13118
13127
|
return removeFromChild(container, key, rest);
|
|
13119
13128
|
}
|
|
13120
|
-
function unsetNestedValue(obj,
|
|
13121
|
-
const { container, removed } = removeAt(obj,
|
|
13129
|
+
function unsetNestedValue(obj, path91) {
|
|
13130
|
+
const { container, removed } = removeAt(obj, path91.split("."));
|
|
13122
13131
|
return { config: container, removed };
|
|
13123
13132
|
}
|
|
13124
13133
|
|
|
@@ -14278,9 +14287,9 @@ function originToSshUrl(origin) {
|
|
|
14278
14287
|
const firstSlash = origin.indexOf("/");
|
|
14279
14288
|
if (firstSlash <= 0) return null;
|
|
14280
14289
|
const host = origin.slice(0, firstSlash);
|
|
14281
|
-
const
|
|
14282
|
-
if (!
|
|
14283
|
-
return `git@${host}:${
|
|
14290
|
+
const path91 = origin.slice(firstSlash + 1);
|
|
14291
|
+
if (!path91) return null;
|
|
14292
|
+
return `git@${host}:${path91}.git`;
|
|
14284
14293
|
}
|
|
14285
14294
|
|
|
14286
14295
|
// src/commands/backlog/cloneRepo.ts
|
|
@@ -17318,13 +17327,13 @@ function findBuiltinDenyRaw(rawCommand) {
|
|
|
17318
17327
|
|
|
17319
17328
|
// src/commands/cliHook/findRestrictedPathDeny.ts
|
|
17320
17329
|
var RESTRICTED_PATHS = [".assist/restricted"];
|
|
17321
|
-
function restrictedPathRegex(
|
|
17322
|
-
const pattern2 =
|
|
17330
|
+
function restrictedPathRegex(path91) {
|
|
17331
|
+
const pattern2 = path91.split("/").map((segment) => segment.replace(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`)).join(String.raw`[/\\]`);
|
|
17323
17332
|
return new RegExp(pattern2);
|
|
17324
17333
|
}
|
|
17325
|
-
var RESTRICTED_PATH_RULES = RESTRICTED_PATHS.map((
|
|
17326
|
-
path:
|
|
17327
|
-
regex: restrictedPathRegex(
|
|
17334
|
+
var RESTRICTED_PATH_RULES = RESTRICTED_PATHS.map((path91) => ({
|
|
17335
|
+
path: path91,
|
|
17336
|
+
regex: restrictedPathRegex(path91)
|
|
17328
17337
|
}));
|
|
17329
17338
|
function findRestrictedPathDenyRaw(rawCommand) {
|
|
17330
17339
|
const rule = RESTRICTED_PATH_RULES.find(
|
|
@@ -17495,9 +17504,9 @@ var __dirname4 = dirname24(__filename3);
|
|
|
17495
17504
|
function packageRoot() {
|
|
17496
17505
|
return __dirname4;
|
|
17497
17506
|
}
|
|
17498
|
-
function readLines(
|
|
17499
|
-
if (!existsSync40(
|
|
17500
|
-
return readFileSync27(
|
|
17507
|
+
function readLines(path91) {
|
|
17508
|
+
if (!existsSync40(path91)) return [];
|
|
17509
|
+
return readFileSync27(path91, "utf8").split("\n").filter((line) => line.trim() !== "");
|
|
17501
17510
|
}
|
|
17502
17511
|
var cachedReads;
|
|
17503
17512
|
var cachedWrites;
|
|
@@ -18021,14 +18030,14 @@ function showProgress(p, label2) {
|
|
|
18021
18030
|
const pct = Math.round(p.done / p.total * 100);
|
|
18022
18031
|
process.stderr.write(`\r\x1B[K[${pct}%] Scanning ${label2}...`);
|
|
18023
18032
|
}
|
|
18024
|
-
async function resolveCommand(cli,
|
|
18025
|
-
showProgress(p,
|
|
18026
|
-
const subHelp = await runHelp([cli, ...
|
|
18033
|
+
async function resolveCommand(cli, path91, description, depth, p) {
|
|
18034
|
+
showProgress(p, path91.join(" "));
|
|
18035
|
+
const subHelp = await runHelp([cli, ...path91]);
|
|
18027
18036
|
if (!subHelp || !hasSubcommands(subHelp)) {
|
|
18028
|
-
return [{ path:
|
|
18037
|
+
return [{ path: path91, description }];
|
|
18029
18038
|
}
|
|
18030
|
-
const children = await discoverAt(cli,
|
|
18031
|
-
return children.length > 0 ? children : [{ path:
|
|
18039
|
+
const children = await discoverAt(cli, path91, depth + 1, p);
|
|
18040
|
+
return children.length > 0 ? children : [{ path: path91, description }];
|
|
18032
18041
|
}
|
|
18033
18042
|
async function discoverAt(cli, parentPath, depth, p) {
|
|
18034
18043
|
if (depth > SAFETY_DEPTH) return [];
|
|
@@ -18176,9 +18185,9 @@ function logPath(cli) {
|
|
|
18176
18185
|
return join42(homedir17(), ".assist", `cli-discover-${safeName}.log`);
|
|
18177
18186
|
}
|
|
18178
18187
|
function readCache(cli) {
|
|
18179
|
-
const
|
|
18180
|
-
if (!existsSync42(
|
|
18181
|
-
return readFileSync29(
|
|
18188
|
+
const path91 = logPath(cli);
|
|
18189
|
+
if (!existsSync42(path91)) return void 0;
|
|
18190
|
+
return readFileSync29(path91, "utf8");
|
|
18182
18191
|
}
|
|
18183
18192
|
function writeCache(cli, output) {
|
|
18184
18193
|
const dir = join42(homedir17(), ".assist");
|
|
@@ -18338,9 +18347,9 @@ function sweepRestrictedDir(dir = getRestrictedDir()) {
|
|
|
18338
18347
|
}
|
|
18339
18348
|
const cutoff = Date.now() - STALE_AFTER_MS;
|
|
18340
18349
|
for (const entry of entries) {
|
|
18341
|
-
const
|
|
18350
|
+
const path91 = join44(dir, entry);
|
|
18342
18351
|
try {
|
|
18343
|
-
if (statSync7(
|
|
18352
|
+
if (statSync7(path91).mtimeMs < cutoff) unlinkSync7(path91);
|
|
18344
18353
|
} catch {
|
|
18345
18354
|
continue;
|
|
18346
18355
|
}
|
|
@@ -18350,10 +18359,10 @@ function sweepRestrictedDir(dir = getRestrictedDir()) {
|
|
|
18350
18359
|
// src/commands/codeComment/readPinState.ts
|
|
18351
18360
|
import { existsSync as existsSync43, readFileSync as readFileSync30 } from "fs";
|
|
18352
18361
|
function readPinState(pin) {
|
|
18353
|
-
const
|
|
18354
|
-
if (!existsSync43(
|
|
18362
|
+
const path91 = getPinStatePath(pin);
|
|
18363
|
+
if (!existsSync43(path91)) return void 0;
|
|
18355
18364
|
try {
|
|
18356
|
-
const state = JSON.parse(readFileSync30(
|
|
18365
|
+
const state = JSON.parse(readFileSync30(path91, "utf8"));
|
|
18357
18366
|
if (state.pin !== pin) return void 0;
|
|
18358
18367
|
return state;
|
|
18359
18368
|
} catch {
|
|
@@ -18502,6 +18511,23 @@ function registerCodeComment(parent) {
|
|
|
18502
18511
|
codeComment.command("confirm").description("Confirm a pin to insert its comment and clear the pin state").argument("<pin>", "Pin issued by 'code-comment set'").action(codeCommentConfirm);
|
|
18503
18512
|
}
|
|
18504
18513
|
|
|
18514
|
+
// src/commands/codexHook/parseCodexHookInput.ts
|
|
18515
|
+
var SUPPORTED_TOOLS = /* @__PURE__ */ new Set(["Bash", "PowerShell"]);
|
|
18516
|
+
function parseCodexHookInput(raw) {
|
|
18517
|
+
try {
|
|
18518
|
+
const data = JSON.parse(raw);
|
|
18519
|
+
const event = data.hook_event_name ?? "PreToolUse";
|
|
18520
|
+
const cwd = typeof data.cwd === "string" ? data.cwd : void 0;
|
|
18521
|
+
const command = data.tool_input?.command;
|
|
18522
|
+
if (typeof command !== "string" || !command.trim()) return { event, cwd };
|
|
18523
|
+
if (!data.tool_name || !SUPPORTED_TOOLS.has(data.tool_name))
|
|
18524
|
+
return { event, cwd };
|
|
18525
|
+
return { event, cwd, toolName: data.tool_name, command: command.trim() };
|
|
18526
|
+
} catch {
|
|
18527
|
+
return void 0;
|
|
18528
|
+
}
|
|
18529
|
+
}
|
|
18530
|
+
|
|
18505
18531
|
// src/commands/codexHook/codexStatusFor.ts
|
|
18506
18532
|
function codexStatusFor(event, autoDecided) {
|
|
18507
18533
|
if (event === "UserPromptSubmit")
|
|
@@ -18521,20 +18547,6 @@ async function reportCodexStatus(event, autoDecided) {
|
|
|
18521
18547
|
}
|
|
18522
18548
|
|
|
18523
18549
|
// src/commands/codexHook/index.ts
|
|
18524
|
-
var SUPPORTED_TOOLS = /* @__PURE__ */ new Set(["Bash", "PowerShell"]);
|
|
18525
|
-
function parseInput(raw) {
|
|
18526
|
-
try {
|
|
18527
|
-
const data = JSON.parse(raw);
|
|
18528
|
-
const event = data.hook_event_name ?? "PreToolUse";
|
|
18529
|
-
const command = data.tool_input?.command;
|
|
18530
|
-
if (typeof command !== "string" || !command.trim()) return { event };
|
|
18531
|
-
if (!data.tool_name || !SUPPORTED_TOOLS.has(data.tool_name))
|
|
18532
|
-
return { event };
|
|
18533
|
-
return { event, toolName: data.tool_name, command: command.trim() };
|
|
18534
|
-
} catch {
|
|
18535
|
-
return void 0;
|
|
18536
|
-
}
|
|
18537
|
-
}
|
|
18538
18550
|
function preToolUseOutput(decision) {
|
|
18539
18551
|
if (decision.permissionDecision === "allow") return void 0;
|
|
18540
18552
|
return {
|
|
@@ -18560,16 +18572,19 @@ function decide2(input) {
|
|
|
18560
18572
|
if (!input.toolName || !input.command) return void 0;
|
|
18561
18573
|
return decideCommand(input.toolName, input.command);
|
|
18562
18574
|
}
|
|
18563
|
-
function outputFor(
|
|
18575
|
+
function outputFor(input, decision) {
|
|
18576
|
+
if (input.event === "SessionStart")
|
|
18577
|
+
return adviceHookPayload(input.cwd ?? process.cwd());
|
|
18564
18578
|
if (!decision) return void 0;
|
|
18565
|
-
if (event === "PermissionRequest")
|
|
18579
|
+
if (input.event === "PermissionRequest")
|
|
18580
|
+
return permissionRequestOutput(decision);
|
|
18566
18581
|
return preToolUseOutput(decision);
|
|
18567
18582
|
}
|
|
18568
18583
|
async function codexHook() {
|
|
18569
|
-
const input =
|
|
18584
|
+
const input = parseCodexHookInput(await readStdin());
|
|
18570
18585
|
if (!input) return;
|
|
18571
18586
|
const decision = decide2(input);
|
|
18572
|
-
const output = outputFor(input
|
|
18587
|
+
const output = outputFor(input, decision);
|
|
18573
18588
|
if (output) console.log(JSON.stringify(output));
|
|
18574
18589
|
await reportCodexStatus(input.event, decision !== void 0);
|
|
18575
18590
|
}
|
|
@@ -18685,8 +18700,8 @@ function findUnmergedPaths() {
|
|
|
18685
18700
|
}
|
|
18686
18701
|
const found = /* @__PURE__ */ new Set();
|
|
18687
18702
|
for (const line of output.split("\n")) {
|
|
18688
|
-
const
|
|
18689
|
-
if (
|
|
18703
|
+
const path91 = line.split(" ")[1];
|
|
18704
|
+
if (path91) found.add(path91.trim());
|
|
18690
18705
|
}
|
|
18691
18706
|
return [...found];
|
|
18692
18707
|
}
|
|
@@ -19911,11 +19926,11 @@ async function loadPath(source) {
|
|
|
19911
19926
|
}
|
|
19912
19927
|
}
|
|
19913
19928
|
async function criteriaExtension() {
|
|
19914
|
-
const
|
|
19929
|
+
const path91 = await loadPath(criteriaExtensionDir());
|
|
19915
19930
|
console.log(
|
|
19916
19931
|
chalk140.bold("acceptance criteria outliner \u2014 GitHub browser extension")
|
|
19917
19932
|
);
|
|
19918
|
-
console.log(chalk140.dim(`load the unpacked extension from ${
|
|
19933
|
+
console.log(chalk140.dim(`load the unpacked extension from ${path91}`));
|
|
19919
19934
|
}
|
|
19920
19935
|
|
|
19921
19936
|
// src/commands/criteriaExtension/signCriteriaExtension.ts
|
|
@@ -20040,10 +20055,10 @@ async function signCriteriaExtension() {
|
|
|
20040
20055
|
process.exitCode = 1;
|
|
20041
20056
|
return;
|
|
20042
20057
|
}
|
|
20043
|
-
const
|
|
20058
|
+
const path91 = await signedAddonInstallPath(
|
|
20044
20059
|
await copySignedXpi(xpi, ARTIFACTS_DIR)
|
|
20045
20060
|
);
|
|
20046
|
-
console.log(chalk142.dim(`install the signed add-on from ${
|
|
20061
|
+
console.log(chalk142.dim(`install the signed add-on from ${path91}`));
|
|
20047
20062
|
}
|
|
20048
20063
|
|
|
20049
20064
|
// src/commands/registerCriteriaExtension.ts
|
|
@@ -20141,10 +20156,10 @@ function getMigrationApprovalPath(migrationId) {
|
|
|
20141
20156
|
// src/commands/dbMigration/readMigrationPinState.ts
|
|
20142
20157
|
import { existsSync as existsSync48, readFileSync as readFileSync32 } from "fs";
|
|
20143
20158
|
function readMigrationPinState(pin) {
|
|
20144
|
-
const
|
|
20145
|
-
if (!existsSync48(
|
|
20159
|
+
const path91 = getMigrationPinPath(pin);
|
|
20160
|
+
if (!existsSync48(path91)) return void 0;
|
|
20146
20161
|
try {
|
|
20147
|
-
const state = JSON.parse(readFileSync32(
|
|
20162
|
+
const state = JSON.parse(readFileSync32(path91, "utf8"));
|
|
20148
20163
|
if (state.pin !== pin) return void 0;
|
|
20149
20164
|
if (!Number.isInteger(state.migrationId)) return void 0;
|
|
20150
20165
|
return state;
|
|
@@ -21574,10 +21589,10 @@ function decideCommentGuard(input, existingContent) {
|
|
|
21574
21589
|
import { existsSync as existsSync54, unlinkSync as unlinkSync11 } from "fs";
|
|
21575
21590
|
function consumeMigrationApproval(migrationId) {
|
|
21576
21591
|
sweepRestrictedDir();
|
|
21577
|
-
const
|
|
21578
|
-
if (!existsSync54(
|
|
21592
|
+
const path91 = getMigrationApprovalPath(migrationId);
|
|
21593
|
+
if (!existsSync54(path91)) return false;
|
|
21579
21594
|
try {
|
|
21580
|
-
unlinkSync11(
|
|
21595
|
+
unlinkSync11(path91);
|
|
21581
21596
|
return true;
|
|
21582
21597
|
} catch {
|
|
21583
21598
|
return false;
|
|
@@ -23813,11 +23828,11 @@ function recentDaemonLogLines() {
|
|
|
23813
23828
|
// src/commands/sessions/daemon/worktree/canonicalTreePath.ts
|
|
23814
23829
|
import { realpathSync as realpathSync2 } from "fs";
|
|
23815
23830
|
import { resolve as resolve14 } from "path";
|
|
23816
|
-
function canonicalTreePath(
|
|
23831
|
+
function canonicalTreePath(path91) {
|
|
23817
23832
|
try {
|
|
23818
|
-
return realpathSync2(
|
|
23833
|
+
return realpathSync2(path91);
|
|
23819
23834
|
} catch {
|
|
23820
|
-
return resolve14(
|
|
23835
|
+
return resolve14(path91);
|
|
23821
23836
|
}
|
|
23822
23837
|
}
|
|
23823
23838
|
|
|
@@ -23870,22 +23885,22 @@ function createWorktree(clone, strategy, boundTreeRoots2, preferredPath) {
|
|
|
23870
23885
|
const registered = new Set(listWorktreePaths(clone));
|
|
23871
23886
|
const branches = new Set(listLocalBranches(clone));
|
|
23872
23887
|
const isTaken = (candidate) => registered.has(candidate) || existsSync57(candidate) || boundTreeRoots2.has(candidate) || branches.has(basename18(candidate));
|
|
23873
|
-
const
|
|
23888
|
+
const path91 = preferredPath && !isTaken(preferredPath) ? preferredPath : nextWorktreePath(clone, base, isTaken);
|
|
23874
23889
|
const start3 = worktreeStartPoint(clone, strategy.trunk);
|
|
23875
23890
|
gitSync(clone, [
|
|
23876
23891
|
"worktree",
|
|
23877
23892
|
"add",
|
|
23878
23893
|
start3.track ? "--track" : "--no-track",
|
|
23879
23894
|
"-b",
|
|
23880
|
-
basename18(
|
|
23881
|
-
|
|
23895
|
+
basename18(path91),
|
|
23896
|
+
path91,
|
|
23882
23897
|
start3.ref
|
|
23883
23898
|
]);
|
|
23884
|
-
recordWorktree(
|
|
23899
|
+
recordWorktree(path91, clone, getCurrentOrigin(clone));
|
|
23885
23900
|
daemonLog(
|
|
23886
|
-
start3.track ? `worktree allocated ${
|
|
23901
|
+
start3.track ? `worktree allocated ${path91} (branch ${basename18(path91)} tracking ${start3.ref}) for clone ${clone}` : `worktree allocated ${path91} (branch ${basename18(path91)} off ${start3.ref}, no mainline tracking) for clone ${clone}`
|
|
23887
23902
|
);
|
|
23888
|
-
return
|
|
23903
|
+
return path91;
|
|
23889
23904
|
}
|
|
23890
23905
|
|
|
23891
23906
|
// src/commands/sessions/daemon/worktree/keptInTree.ts
|
|
@@ -24026,13 +24041,13 @@ function allocateTree(requestedCwd, boundTreeRoots2, options2 = {}) {
|
|
|
24026
24041
|
if (forcedSpill) daemonLog(forcedSpill);
|
|
24027
24042
|
else if (reusesClone(clone, boundTreeRoots2, reuse))
|
|
24028
24043
|
return { cwd: clone, kind: "primary", created: false, clone };
|
|
24029
|
-
const
|
|
24044
|
+
const path91 = createWorktree(
|
|
24030
24045
|
clone,
|
|
24031
24046
|
{ root: cfg.root, trunk: cfg.trunk },
|
|
24032
24047
|
boundTreeRoots2,
|
|
24033
24048
|
options2.replacesTree
|
|
24034
24049
|
);
|
|
24035
|
-
return { cwd:
|
|
24050
|
+
return { cwd: path91, kind: "worktree", created: true, clone };
|
|
24036
24051
|
}
|
|
24037
24052
|
|
|
24038
24053
|
// src/commands/sessions/daemon/describePersistedSession.ts
|
|
@@ -24365,13 +24380,13 @@ function worktreeHoldingBranch(cwd, branch2) {
|
|
|
24365
24380
|
const listing = gitSyncOrNull(cwd, ["worktree", "list", "--porcelain"]);
|
|
24366
24381
|
if (!listing) return null;
|
|
24367
24382
|
const here = gitSyncOrNull(cwd, ["rev-parse", "--show-toplevel"]);
|
|
24368
|
-
let
|
|
24383
|
+
let path91 = null;
|
|
24369
24384
|
for (const line of listing.split("\n")) {
|
|
24370
24385
|
const trimmed = line.trim();
|
|
24371
24386
|
if (trimmed.startsWith("worktree "))
|
|
24372
|
-
|
|
24387
|
+
path91 = trimmed.slice("worktree ".length).trim();
|
|
24373
24388
|
else if (trimmed === `branch refs/heads/${branch2}`)
|
|
24374
|
-
return
|
|
24389
|
+
return path91 && path91 !== here ? path91 : null;
|
|
24375
24390
|
}
|
|
24376
24391
|
return null;
|
|
24377
24392
|
}
|
|
@@ -25489,9 +25504,9 @@ function parseRscRows(flight) {
|
|
|
25489
25504
|
}
|
|
25490
25505
|
function makeRscResolver(rows) {
|
|
25491
25506
|
return (ref) => {
|
|
25492
|
-
const [id, ...
|
|
25507
|
+
const [id, ...path91] = ref.slice(1).replace(/^[L@]/, "").split(":");
|
|
25493
25508
|
let v = rows[id];
|
|
25494
|
-
for (const key of
|
|
25509
|
+
for (const key of path91) {
|
|
25495
25510
|
if (v == null || typeof v !== "object") return void 0;
|
|
25496
25511
|
v = v[key];
|
|
25497
25512
|
}
|
|
@@ -25973,7 +25988,7 @@ var TOOL_MAP = {
|
|
|
25973
25988
|
bash: "Bash",
|
|
25974
25989
|
powershell: "PowerShell"
|
|
25975
25990
|
};
|
|
25976
|
-
function
|
|
25991
|
+
function parseInput(raw) {
|
|
25977
25992
|
try {
|
|
25978
25993
|
const data = JSON.parse(raw);
|
|
25979
25994
|
const command = data.command;
|
|
@@ -25986,7 +26001,7 @@ function parseInput2(raw) {
|
|
|
25986
26001
|
}
|
|
25987
26002
|
}
|
|
25988
26003
|
async function piHook() {
|
|
25989
|
-
const input =
|
|
26004
|
+
const input = parseInput(await readStdin());
|
|
25990
26005
|
if (!input) return;
|
|
25991
26006
|
const decision = decideCommand(input.toolName, input.command);
|
|
25992
26007
|
const output = decision ? {
|
|
@@ -26111,18 +26126,18 @@ function validateLine(line) {
|
|
|
26111
26126
|
process.exit(1);
|
|
26112
26127
|
}
|
|
26113
26128
|
}
|
|
26114
|
-
async function comment2(
|
|
26129
|
+
async function comment2(path91, line, body, options2 = {}) {
|
|
26115
26130
|
const { startLine, skipPreview } = options2;
|
|
26116
26131
|
validateBody(body);
|
|
26117
26132
|
validateLine(line);
|
|
26118
26133
|
if (startLine !== void 0) validateLine(startLine);
|
|
26119
26134
|
const range = startLine !== void 0 ? `${startLine}-${line}` : `${line}`;
|
|
26120
26135
|
if (!skipPreview)
|
|
26121
|
-
await reviewProposedPrComment(`Comment on ${
|
|
26136
|
+
await reviewProposedPrComment(`Comment on ${path91}:${range}`, body, null);
|
|
26122
26137
|
try {
|
|
26123
26138
|
const prId = getCurrentPrNodeId();
|
|
26124
|
-
postReviewComment({ prId, body, path:
|
|
26125
|
-
console.log(`Added review comment on ${
|
|
26139
|
+
postReviewComment({ prId, body, path: path91, line, startLine });
|
|
26140
|
+
console.log(`Added review comment on ${path91}:${range}`);
|
|
26126
26141
|
} catch (error) {
|
|
26127
26142
|
if (isGhNotInstalled(error)) {
|
|
26128
26143
|
console.error("Error: GitHub CLI (gh) is not installed.");
|
|
@@ -27339,9 +27354,9 @@ function registerPrsComments(prsCommand) {
|
|
|
27339
27354
|
});
|
|
27340
27355
|
prsCommand.command("comment <path> <line> <body>").description(
|
|
27341
27356
|
"Add a line comment to the pending review (body of - reads it from stdin)"
|
|
27342
|
-
).action(async (
|
|
27357
|
+
).action(async (path91, line, body) => {
|
|
27343
27358
|
await comment2(
|
|
27344
|
-
|
|
27359
|
+
path91,
|
|
27345
27360
|
Number.parseInt(line, 10),
|
|
27346
27361
|
await readBodyArgument(body)
|
|
27347
27362
|
);
|
|
@@ -27733,11 +27748,11 @@ async function loadBody(target) {
|
|
|
27733
27748
|
if (target.kind === "file") return readDraftFile(target.path);
|
|
27734
27749
|
return fetchPrBody(target.number, target.repo);
|
|
27735
27750
|
}
|
|
27736
|
-
function readDraftFile(
|
|
27751
|
+
function readDraftFile(path91) {
|
|
27737
27752
|
try {
|
|
27738
|
-
return readFileSync46(
|
|
27753
|
+
return readFileSync46(path91, "utf8");
|
|
27739
27754
|
} catch {
|
|
27740
|
-
console.error(`Error: Could not read \`${
|
|
27755
|
+
console.error(`Error: Could not read \`${path91}\`.`);
|
|
27741
27756
|
console.error(
|
|
27742
27757
|
"Pass a pull request number, a GitHub pull request URL, - for stdin, or a path to a file."
|
|
27743
27758
|
);
|
|
@@ -28016,10 +28031,10 @@ function resolveOpSecret(reference) {
|
|
|
28016
28031
|
}
|
|
28017
28032
|
|
|
28018
28033
|
// src/commands/ravendb/ravenFetch.ts
|
|
28019
|
-
async function ravenFetch(connection,
|
|
28034
|
+
async function ravenFetch(connection, path91) {
|
|
28020
28035
|
const apiKey = resolveOpSecret(connection.apiKeyRef);
|
|
28021
28036
|
let accessToken = await getAccessToken(apiKey);
|
|
28022
|
-
const url = `${connection.url}${
|
|
28037
|
+
const url = `${connection.url}${path91}`;
|
|
28023
28038
|
const headers = {
|
|
28024
28039
|
Authorization: `Bearer ${accessToken}`,
|
|
28025
28040
|
"Content-Type": "application/json"
|
|
@@ -28109,16 +28124,16 @@ import chalk196 from "chalk";
|
|
|
28109
28124
|
// src/commands/ravendb/buildQueryPath.ts
|
|
28110
28125
|
function buildQueryPath(opts) {
|
|
28111
28126
|
const db = encodeURIComponent(opts.db);
|
|
28112
|
-
let
|
|
28127
|
+
let path91;
|
|
28113
28128
|
if (opts.collection) {
|
|
28114
|
-
|
|
28129
|
+
path91 = `/databases/${db}/indexes/dynamic/${encodeURIComponent(opts.collection)}?start=${opts.start}&pageSize=${opts.pageSize}&sort=${encodeURIComponent(opts.sort)}`;
|
|
28115
28130
|
} else {
|
|
28116
|
-
|
|
28131
|
+
path91 = `/databases/${db}/queries?start=${opts.start}&pageSize=${opts.pageSize}`;
|
|
28117
28132
|
}
|
|
28118
28133
|
if (opts.query) {
|
|
28119
|
-
|
|
28134
|
+
path91 += `&query=${encodeURIComponent(opts.query)}`;
|
|
28120
28135
|
}
|
|
28121
|
-
return
|
|
28136
|
+
return path91;
|
|
28122
28137
|
}
|
|
28123
28138
|
|
|
28124
28139
|
// src/commands/ravendb/fetchAllPages.ts
|
|
@@ -28127,7 +28142,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
28127
28142
|
let start3 = 0;
|
|
28128
28143
|
while (true) {
|
|
28129
28144
|
const effectivePageSize = opts.limit !== void 0 ? Math.min(opts.pageSize, opts.limit - allResults.length) : opts.pageSize;
|
|
28130
|
-
const
|
|
28145
|
+
const path91 = buildQueryPath({
|
|
28131
28146
|
db: connection.database,
|
|
28132
28147
|
collection: opts.collection,
|
|
28133
28148
|
start: start3,
|
|
@@ -28135,7 +28150,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
28135
28150
|
sort: opts.sort,
|
|
28136
28151
|
query: opts.query
|
|
28137
28152
|
});
|
|
28138
|
-
const data = await ravenFetch(connection,
|
|
28153
|
+
const data = await ravenFetch(connection, path91);
|
|
28139
28154
|
const results = data.Results ?? [];
|
|
28140
28155
|
const totalResults = data.TotalResults ?? 0;
|
|
28141
28156
|
if (results.length === 0) break;
|
|
@@ -30746,8 +30761,8 @@ async function handlePostSynthesis(synthesisPath, prInfo, options2) {
|
|
|
30746
30761
|
// src/commands/review/prepareReviewDir.ts
|
|
30747
30762
|
import { existsSync as existsSync63, mkdirSync as mkdirSync21, unlinkSync as unlinkSync17, writeFileSync as writeFileSync38 } from "fs";
|
|
30748
30763
|
function clearReviewFiles(paths) {
|
|
30749
|
-
for (const
|
|
30750
|
-
if (existsSync63(
|
|
30764
|
+
for (const path91 of [paths.claudePath, paths.codexPath, paths.synthesisPath]) {
|
|
30765
|
+
if (existsSync63(path91)) unlinkSync17(path91);
|
|
30751
30766
|
}
|
|
30752
30767
|
}
|
|
30753
30768
|
function prepareReviewDir(paths, requestBody, force) {
|
|
@@ -32227,8 +32242,8 @@ import chalk220 from "chalk";
|
|
|
32227
32242
|
|
|
32228
32243
|
// src/commands/seq/fetchSeq.ts
|
|
32229
32244
|
import chalk217 from "chalk";
|
|
32230
|
-
async function fetchSeq(conn,
|
|
32231
|
-
const url = `${conn.url}${
|
|
32245
|
+
async function fetchSeq(conn, path91, params) {
|
|
32246
|
+
const url = `${conn.url}${path91}?${params}`;
|
|
32232
32247
|
const response = await fetch(url, {
|
|
32233
32248
|
headers: {
|
|
32234
32249
|
Accept: "application/json",
|
|
@@ -32878,9 +32893,9 @@ function registerSql(program2) {
|
|
|
32878
32893
|
}
|
|
32879
32894
|
|
|
32880
32895
|
// src/commands/sync.ts
|
|
32881
|
-
import * as
|
|
32896
|
+
import * as fs48 from "fs";
|
|
32882
32897
|
import * as os5 from "os";
|
|
32883
|
-
import * as
|
|
32898
|
+
import * as path85 from "path";
|
|
32884
32899
|
import { fileURLToPath as fileURLToPath9 } from "url";
|
|
32885
32900
|
|
|
32886
32901
|
// src/commands/sync/pruneCommands.ts
|
|
@@ -32959,35 +32974,52 @@ function reportPrune(label2, result, force) {
|
|
|
32959
32974
|
}
|
|
32960
32975
|
}
|
|
32961
32976
|
|
|
32977
|
+
// src/commands/sync/reportRetiredAgentsFiles.ts
|
|
32978
|
+
import * as fs41 from "fs";
|
|
32979
|
+
import * as path77 from "path";
|
|
32980
|
+
var retired = [
|
|
32981
|
+
path77.join(harnesses.claude.homeDir, "CLAUDE.md"),
|
|
32982
|
+
path77.join(harnesses.codex.homeDir, "AGENTS.md"),
|
|
32983
|
+
path77.join(harnesses.pi.homeDir, "AGENTS.md")
|
|
32984
|
+
];
|
|
32985
|
+
function reportRetiredAgentsFiles() {
|
|
32986
|
+
const leftovers = retired.filter((file) => fs41.existsSync(file));
|
|
32987
|
+
if (leftovers.length === 0) return;
|
|
32988
|
+
console.log(
|
|
32989
|
+
"No longer written by sync \u2014 each harness now composes its own advice at session start:"
|
|
32990
|
+
);
|
|
32991
|
+
for (const file of leftovers) console.log(` ${file}`);
|
|
32992
|
+
console.log(
|
|
32993
|
+
" Delete them, or they keep injecting the retired global instructions."
|
|
32994
|
+
);
|
|
32995
|
+
}
|
|
32996
|
+
|
|
32962
32997
|
// src/commands/sync/syncCodex.ts
|
|
32963
|
-
import * as
|
|
32998
|
+
import * as path80 from "path";
|
|
32964
32999
|
|
|
32965
33000
|
// src/commands/sync/installHarnessCommands.ts
|
|
32966
|
-
import * as
|
|
32967
|
-
import * as
|
|
33001
|
+
import * as fs42 from "fs";
|
|
33002
|
+
import * as path78 from "path";
|
|
32968
33003
|
function installHarnessCommands(claudeDir, harness, transform) {
|
|
32969
|
-
const commandsSource =
|
|
32970
|
-
const files =
|
|
33004
|
+
const commandsSource = path78.join(claudeDir, "commands");
|
|
33005
|
+
const files = fs42.readdirSync(commandsSource);
|
|
32971
33006
|
const names = [];
|
|
32972
33007
|
let synced = 0;
|
|
32973
33008
|
for (const file of files) {
|
|
32974
33009
|
if (!file.endsWith(".md")) continue;
|
|
32975
33010
|
const name = file.replace(/\.md$/, "");
|
|
32976
33011
|
names.push(name);
|
|
32977
|
-
const content =
|
|
32978
|
-
const target =
|
|
32979
|
-
|
|
32980
|
-
|
|
33012
|
+
const content = fs42.readFileSync(path78.join(commandsSource, file), "utf8");
|
|
33013
|
+
const target = path78.join(harness.homeDir, harness.sync.commandDest(name));
|
|
33014
|
+
fs42.mkdirSync(path78.dirname(target), { recursive: true });
|
|
33015
|
+
fs42.writeFileSync(target, transform(name, content));
|
|
32981
33016
|
synced++;
|
|
32982
33017
|
}
|
|
32983
|
-
const agentsTarget = path77.join(harness.homeDir, harness.sync.agentsFile);
|
|
32984
|
-
fs41.mkdirSync(path77.dirname(agentsTarget), { recursive: true });
|
|
32985
|
-
fs41.copyFileSync(path77.join(claudeDir, "CLAUDE.md"), agentsTarget);
|
|
32986
33018
|
return { total: files.length, synced, names };
|
|
32987
33019
|
}
|
|
32988
33020
|
|
|
32989
33021
|
// src/commands/sync/pruneSkills.ts
|
|
32990
|
-
import * as
|
|
33022
|
+
import * as fs43 from "fs";
|
|
32991
33023
|
function pruneSkills(targetDir, skillNames, options2) {
|
|
32992
33024
|
return pruneTarget(
|
|
32993
33025
|
targetDir,
|
|
@@ -33000,15 +33032,15 @@ function pruneSkills(targetDir, skillNames, options2) {
|
|
|
33000
33032
|
);
|
|
33001
33033
|
}
|
|
33002
33034
|
function unexpectedContent(skillDir) {
|
|
33003
|
-
const entries =
|
|
33035
|
+
const entries = fs43.readdirSync(skillDir);
|
|
33004
33036
|
const others = entries.filter((entry) => entry !== "SKILL.md");
|
|
33005
33037
|
if (others.length > 0) return `contains ${others.sort().join(", ")}`;
|
|
33006
33038
|
return entries.length === 0 ? "no SKILL.md" : void 0;
|
|
33007
33039
|
}
|
|
33008
33040
|
|
|
33009
33041
|
// src/commands/sync/syncCodexHooks.ts
|
|
33010
|
-
import * as
|
|
33011
|
-
import * as
|
|
33042
|
+
import * as fs44 from "fs";
|
|
33043
|
+
import * as path79 from "path";
|
|
33012
33044
|
var BEGIN = "# >>> assist codex hooks (managed) \u2014 do not edit >>>";
|
|
33013
33045
|
var END = "# <<< assist codex hooks (managed) <<<";
|
|
33014
33046
|
function upsertManagedBlock(existing, body) {
|
|
@@ -33038,13 +33070,13 @@ ${rest}
|
|
|
33038
33070
|
`;
|
|
33039
33071
|
}
|
|
33040
33072
|
function syncCodexHooks(sourcePath) {
|
|
33041
|
-
const body =
|
|
33042
|
-
const configPath =
|
|
33043
|
-
const existing =
|
|
33044
|
-
|
|
33045
|
-
|
|
33073
|
+
const body = fs44.readFileSync(sourcePath, "utf8");
|
|
33074
|
+
const configPath = path79.join(harnesses.codex.homeDir, "config.toml");
|
|
33075
|
+
const existing = fs44.existsSync(configPath) ? fs44.readFileSync(configPath, "utf8") : "";
|
|
33076
|
+
fs44.mkdirSync(path79.dirname(configPath), { recursive: true });
|
|
33077
|
+
fs44.writeFileSync(configPath, upsertManagedBlock(existing, body));
|
|
33046
33078
|
console.log(
|
|
33047
|
-
"Registered assist codex-hook in ~/.codex/config.toml (UserPromptSubmit, PreToolUse, PostToolUse, PermissionRequest, Stop)"
|
|
33079
|
+
"Registered assist codex-hook in ~/.codex/config.toml (SessionStart, UserPromptSubmit, PreToolUse, PostToolUse, PermissionRequest, Stop)"
|
|
33048
33080
|
);
|
|
33049
33081
|
}
|
|
33050
33082
|
|
|
@@ -33073,59 +33105,57 @@ function syncCodex(claudeDir, options2) {
|
|
|
33073
33105
|
harnesses.codex,
|
|
33074
33106
|
commandToSkill
|
|
33075
33107
|
);
|
|
33076
|
-
syncCodexHooks(
|
|
33077
|
-
console.log(
|
|
33078
|
-
`Synced ${total} skill(s) to ~/.codex/skills and CLAUDE.md to ~/.codex/AGENTS.md`
|
|
33079
|
-
);
|
|
33108
|
+
syncCodexHooks(path80.join(claudeDir, "..", "codex", "config.toml"));
|
|
33109
|
+
console.log(`Synced ${total} skill(s) to ~/.codex/skills`);
|
|
33080
33110
|
if (!options2?.prune) return;
|
|
33081
33111
|
const force = options2.force ?? false;
|
|
33082
33112
|
reportPrune(
|
|
33083
33113
|
"~/.codex/skills",
|
|
33084
|
-
pruneSkills(
|
|
33114
|
+
pruneSkills(path80.join(harnesses.codex.homeDir, "skills"), names, { force }),
|
|
33085
33115
|
force
|
|
33086
33116
|
);
|
|
33087
33117
|
}
|
|
33088
33118
|
|
|
33089
33119
|
// src/commands/sync/syncDesign.ts
|
|
33090
|
-
import * as
|
|
33091
|
-
import * as
|
|
33120
|
+
import * as fs45 from "fs";
|
|
33121
|
+
import * as path81 from "path";
|
|
33092
33122
|
function syncDesign(claudeDir, targetBase) {
|
|
33093
|
-
const systemPromptSource =
|
|
33094
|
-
const systemPromptTarget =
|
|
33095
|
-
|
|
33123
|
+
const systemPromptSource = path81.join(claudeDir, "design-system-prompt.md");
|
|
33124
|
+
const systemPromptTarget = path81.join(targetBase, "design-system-prompt.md");
|
|
33125
|
+
fs45.copyFileSync(systemPromptSource, systemPromptTarget);
|
|
33096
33126
|
console.log(
|
|
33097
33127
|
"Copied design-system-prompt.md to ~/.claude/design-system-prompt.md"
|
|
33098
33128
|
);
|
|
33099
|
-
const skillsSource =
|
|
33100
|
-
const skillsTarget =
|
|
33101
|
-
|
|
33102
|
-
const files =
|
|
33129
|
+
const skillsSource = path81.join(claudeDir, "skills");
|
|
33130
|
+
const skillsTarget = path81.join(targetBase, "skills");
|
|
33131
|
+
fs45.mkdirSync(skillsTarget, { recursive: true });
|
|
33132
|
+
const files = fs45.readdirSync(skillsSource);
|
|
33103
33133
|
for (const file of files) {
|
|
33104
|
-
|
|
33105
|
-
|
|
33106
|
-
|
|
33134
|
+
fs45.copyFileSync(
|
|
33135
|
+
path81.join(skillsSource, file),
|
|
33136
|
+
path81.join(skillsTarget, file)
|
|
33107
33137
|
);
|
|
33108
33138
|
}
|
|
33109
33139
|
console.log(`Synced ${files.length} design skill(s) to ~/.claude/skills`);
|
|
33110
33140
|
}
|
|
33111
33141
|
|
|
33112
33142
|
// src/commands/sync/syncPi.ts
|
|
33113
|
-
import * as
|
|
33143
|
+
import * as path83 from "path";
|
|
33114
33144
|
|
|
33115
33145
|
// src/commands/sync/syncPiHooks.ts
|
|
33116
|
-
import * as
|
|
33117
|
-
import * as
|
|
33146
|
+
import * as fs46 from "fs";
|
|
33147
|
+
import * as path82 from "path";
|
|
33118
33148
|
function piExtensionsDir() {
|
|
33119
|
-
return
|
|
33149
|
+
return path82.join(harnesses.pi.homeDir, "extensions");
|
|
33120
33150
|
}
|
|
33121
33151
|
function syncPiHooks(sourceDir) {
|
|
33122
33152
|
const target = piExtensionsDir();
|
|
33123
|
-
|
|
33124
|
-
const files =
|
|
33153
|
+
fs46.mkdirSync(target, { recursive: true });
|
|
33154
|
+
const files = fs46.readdirSync(sourceDir).filter((f) => f.endsWith(".ts"));
|
|
33125
33155
|
for (const file of files) {
|
|
33126
|
-
|
|
33127
|
-
|
|
33128
|
-
|
|
33156
|
+
fs46.copyFileSync(
|
|
33157
|
+
path82.join(sourceDir, file),
|
|
33158
|
+
path82.join(target, `assist-${file}`)
|
|
33129
33159
|
);
|
|
33130
33160
|
}
|
|
33131
33161
|
console.log(
|
|
@@ -33162,30 +33192,28 @@ function syncPi(claudeDir, options2) {
|
|
|
33162
33192
|
harnesses.pi,
|
|
33163
33193
|
commandToPrompt
|
|
33164
33194
|
);
|
|
33165
|
-
syncPiHooks(
|
|
33166
|
-
console.log(
|
|
33167
|
-
`Synced ${synced} prompt(s) to ~/.pi/agent/prompts and CLAUDE.md to ~/.pi/agent/AGENTS.md`
|
|
33168
|
-
);
|
|
33195
|
+
syncPiHooks(path83.join(claudeDir, "..", "pi"));
|
|
33196
|
+
console.log(`Synced ${synced} prompt(s) to ~/.pi/agent/prompts`);
|
|
33169
33197
|
if (!options2?.prune) return;
|
|
33170
33198
|
const force = options2.force ?? false;
|
|
33171
33199
|
reportPrune(
|
|
33172
33200
|
"~/.pi/agent/prompts",
|
|
33173
|
-
pruneCommands(
|
|
33201
|
+
pruneCommands(path83.join(harnesses.pi.homeDir, "prompts"), names, { force }),
|
|
33174
33202
|
force
|
|
33175
33203
|
);
|
|
33176
33204
|
}
|
|
33177
33205
|
|
|
33178
33206
|
// src/commands/sync/syncSettings.ts
|
|
33179
|
-
import * as
|
|
33180
|
-
import * as
|
|
33207
|
+
import * as fs47 from "fs";
|
|
33208
|
+
import * as path84 from "path";
|
|
33181
33209
|
import chalk227 from "chalk";
|
|
33182
33210
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
33183
|
-
const source =
|
|
33184
|
-
const target =
|
|
33185
|
-
const sourceContent =
|
|
33211
|
+
const source = path84.join(claudeDir, "settings.json");
|
|
33212
|
+
const target = path84.join(targetBase, "settings.json");
|
|
33213
|
+
const sourceContent = fs47.readFileSync(source, "utf8");
|
|
33186
33214
|
const sourceSettings = JSON.parse(sourceContent);
|
|
33187
|
-
const targetExists =
|
|
33188
|
-
const targetContent = targetExists ?
|
|
33215
|
+
const targetExists = fs47.existsSync(target);
|
|
33216
|
+
const targetContent = targetExists ? fs47.readFileSync(target, "utf8") : "";
|
|
33189
33217
|
const preservedUserSettings = targetExists ? JSON.parse(targetContent) : {};
|
|
33190
33218
|
const mergedContent = JSON.stringify(
|
|
33191
33219
|
{ ...preservedUserSettings, ...sourceSettings },
|
|
@@ -33215,40 +33243,41 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
33215
33243
|
}
|
|
33216
33244
|
}
|
|
33217
33245
|
}
|
|
33218
|
-
|
|
33246
|
+
fs47.writeFileSync(target, mergedContent);
|
|
33219
33247
|
console.log("Copied settings.json to ~/.claude/settings.json");
|
|
33220
33248
|
}
|
|
33221
33249
|
|
|
33222
33250
|
// src/commands/sync.ts
|
|
33223
33251
|
var __filename4 = fileURLToPath9(import.meta.url);
|
|
33224
|
-
var __dirname5 =
|
|
33252
|
+
var __dirname5 = path85.dirname(__filename4);
|
|
33225
33253
|
async function sync(options2) {
|
|
33226
33254
|
const config = loadConfig();
|
|
33227
33255
|
const yes = options2?.yes ?? config.sync.autoConfirm;
|
|
33228
33256
|
const prune = { prune: options2?.prune, force: options2?.force };
|
|
33229
|
-
const claudeDir =
|
|
33230
|
-
const targetBase =
|
|
33257
|
+
const claudeDir = path85.join(__dirname5, "..", "claude");
|
|
33258
|
+
const targetBase = path85.join(os5.homedir(), ".claude");
|
|
33231
33259
|
const commandFiles = syncCommands(claudeDir, targetBase);
|
|
33232
33260
|
syncDesign(claudeDir, targetBase);
|
|
33233
33261
|
await syncSettings(claudeDir, targetBase, { yes });
|
|
33234
33262
|
syncCodex(claudeDir, prune);
|
|
33235
33263
|
syncPi(claudeDir, prune);
|
|
33264
|
+
reportRetiredAgentsFiles();
|
|
33236
33265
|
if (!options2?.prune) return;
|
|
33237
|
-
const commandNames = commandFiles.filter((file) => file.endsWith(".md")).map((file) =>
|
|
33266
|
+
const commandNames = commandFiles.filter((file) => file.endsWith(".md")).map((file) => path85.basename(file, ".md"));
|
|
33238
33267
|
const force = options2.force ?? false;
|
|
33239
33268
|
reportPrune(
|
|
33240
33269
|
"~/.claude/commands",
|
|
33241
|
-
pruneCommands(
|
|
33270
|
+
pruneCommands(path85.join(targetBase, "commands"), commandNames, { force }),
|
|
33242
33271
|
force
|
|
33243
33272
|
);
|
|
33244
33273
|
}
|
|
33245
33274
|
function syncCommands(claudeDir, targetBase) {
|
|
33246
|
-
const sourceDir =
|
|
33247
|
-
const targetDir =
|
|
33248
|
-
|
|
33249
|
-
const files =
|
|
33275
|
+
const sourceDir = path85.join(claudeDir, "commands");
|
|
33276
|
+
const targetDir = path85.join(targetBase, "commands");
|
|
33277
|
+
fs48.mkdirSync(targetDir, { recursive: true });
|
|
33278
|
+
const files = fs48.readdirSync(sourceDir);
|
|
33250
33279
|
for (const file of files) {
|
|
33251
|
-
|
|
33280
|
+
fs48.copyFileSync(path85.join(sourceDir, file), path85.join(targetDir, file));
|
|
33252
33281
|
console.log(`Copied ${file} to ${targetDir}`);
|
|
33253
33282
|
}
|
|
33254
33283
|
console.log(`Synced ${files.length} command(s) to ~/.claude/commands`);
|
|
@@ -33258,7 +33287,7 @@ function syncCommands(claudeDir, targetBase) {
|
|
|
33258
33287
|
// src/commands/registerSync.ts
|
|
33259
33288
|
function registerSync(program2) {
|
|
33260
33289
|
const syncCommand = program2.command("sync").description(
|
|
33261
|
-
"Copy command files to ~/.claude/commands; when codex is detected, also install commands as ~/.codex/skills/<name>/SKILL.md
|
|
33290
|
+
"Copy command files to ~/.claude/commands; when codex is detected, also install commands as ~/.codex/skills/<name>/SKILL.md and register the assist codex-hook in ~/.codex/config.toml, which auto-approves read-only commands and injects the repo's composed advice on SessionStart; when pi is detected, also install commands as ~/.pi/agent/prompts/<name>.md and install the assist extensions into ~/.pi/agent/extensions, which gate permissions and inject the same advice. No global instructions file is written \u2014 every harness composes its own from assist advise at session start, and any ~/.claude/CLAUDE.md, ~/.codex/AGENTS.md or ~/.pi/agent/AGENTS.md an earlier sync left behind is named so you can remove it. With --prune, also report commands in those target dirs that sync did not write, and with --prune --force remove them"
|
|
33262
33291
|
).option("-y, --yes", "Overwrite settings.json without prompting").option(
|
|
33263
33292
|
"--prune",
|
|
33264
33293
|
"After syncing, list commands in the target dirs whose name is not in the repo's claude/commands/*.md set; subdirectories and non-.md files are listed separately and never removed"
|
|
@@ -33276,7 +33305,7 @@ function registerSync(program2) {
|
|
|
33276
33305
|
}
|
|
33277
33306
|
|
|
33278
33307
|
// src/commands/transcript/clean.ts
|
|
33279
|
-
import { existsSync as
|
|
33308
|
+
import { existsSync as existsSync73 } from "fs";
|
|
33280
33309
|
|
|
33281
33310
|
// src/commands/transcript/convert/formatTimestamp.ts
|
|
33282
33311
|
function pad(value, width) {
|
|
@@ -33554,7 +33583,7 @@ function clean(file, options2 = {}) {
|
|
|
33554
33583
|
);
|
|
33555
33584
|
process.exit(1);
|
|
33556
33585
|
}
|
|
33557
|
-
if (!
|
|
33586
|
+
if (!existsSync73(file)) {
|
|
33558
33587
|
console.error(`Error: VTT file not found: ${file}`);
|
|
33559
33588
|
process.exit(1);
|
|
33560
33589
|
}
|
|
@@ -33637,21 +33666,21 @@ async function configure() {
|
|
|
33637
33666
|
}
|
|
33638
33667
|
|
|
33639
33668
|
// src/commands/transcript/list.ts
|
|
33640
|
-
import { existsSync as
|
|
33641
|
-
import { join as
|
|
33669
|
+
import { existsSync as existsSync74, readdirSync as readdirSync21, statSync as statSync11 } from "fs";
|
|
33670
|
+
import { join as join88 } from "path";
|
|
33642
33671
|
function list4() {
|
|
33643
33672
|
const { vttDir } = getTranscriptConfig();
|
|
33644
|
-
if (!
|
|
33673
|
+
if (!existsSync74(vttDir)) return;
|
|
33645
33674
|
for (const entry of readdirSync21(vttDir)) {
|
|
33646
33675
|
if (!entry.endsWith(".vtt")) continue;
|
|
33647
|
-
if (statSync11(
|
|
33676
|
+
if (statSync11(join88(vttDir, entry)).isDirectory()) continue;
|
|
33648
33677
|
console.log(entry);
|
|
33649
33678
|
}
|
|
33650
33679
|
}
|
|
33651
33680
|
|
|
33652
33681
|
// src/commands/transcript/move.ts
|
|
33653
|
-
import { existsSync as
|
|
33654
|
-
import { basename as basename23, join as
|
|
33682
|
+
import { existsSync as existsSync75, mkdirSync as mkdirSync29, renameSync as renameSync2, writeFileSync as writeFileSync46 } from "fs";
|
|
33683
|
+
import { basename as basename23, join as join89 } from "path";
|
|
33655
33684
|
|
|
33656
33685
|
// src/commands/transcript/convertVttToMarkdown.ts
|
|
33657
33686
|
function convertVttToMarkdown(inputPath) {
|
|
@@ -33661,9 +33690,9 @@ function convertVttToMarkdown(inputPath) {
|
|
|
33661
33690
|
// src/commands/transcript/move.ts
|
|
33662
33691
|
var DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/;
|
|
33663
33692
|
function archiveRawVtt(vttDir, sourcePath, filename) {
|
|
33664
|
-
const processedDir =
|
|
33693
|
+
const processedDir = join89(vttDir, "processed");
|
|
33665
33694
|
mkdirSync29(processedDir, { recursive: true });
|
|
33666
|
-
renameSync2(sourcePath,
|
|
33695
|
+
renameSync2(sourcePath, join89(processedDir, filename));
|
|
33667
33696
|
}
|
|
33668
33697
|
function move(file, options2) {
|
|
33669
33698
|
const { date, client } = options2;
|
|
@@ -33673,25 +33702,25 @@ function move(file, options2) {
|
|
|
33673
33702
|
}
|
|
33674
33703
|
const { vttDir, transcriptsDir, summaryDir } = getTranscriptConfig();
|
|
33675
33704
|
const filename = basename23(file);
|
|
33676
|
-
const sourcePath =
|
|
33677
|
-
if (!
|
|
33705
|
+
const sourcePath = join89(vttDir, filename);
|
|
33706
|
+
if (!existsSync75(sourcePath)) {
|
|
33678
33707
|
console.error(`Error: VTT file not found: ${sourcePath}`);
|
|
33679
33708
|
process.exit(1);
|
|
33680
33709
|
}
|
|
33681
33710
|
const base = basename23(filename, ".vtt").replace(/ Transcription$/, "");
|
|
33682
33711
|
const outputName = `${date} ${base}.md`;
|
|
33683
|
-
const formattedDir =
|
|
33712
|
+
const formattedDir = join89(transcriptsDir, client);
|
|
33684
33713
|
mkdirSync29(formattedDir, { recursive: true });
|
|
33685
|
-
const formattedPath =
|
|
33714
|
+
const formattedPath = join89(formattedDir, outputName);
|
|
33686
33715
|
writeFileSync46(formattedPath, convertVttToMarkdown(sourcePath), "utf8");
|
|
33687
33716
|
archiveRawVtt(vttDir, sourcePath, filename);
|
|
33688
|
-
const summaryPath =
|
|
33717
|
+
const summaryPath = join89(summaryDir, client, outputName);
|
|
33689
33718
|
console.log(`Formatted transcript: ${formattedPath}`);
|
|
33690
33719
|
console.log(`Summary target: ${summaryPath}`);
|
|
33691
33720
|
}
|
|
33692
33721
|
|
|
33693
33722
|
// src/commands/transcript/merge.ts
|
|
33694
|
-
import { existsSync as
|
|
33723
|
+
import { existsSync as existsSync76, writeFileSync as writeFileSync47 } from "fs";
|
|
33695
33724
|
import { basename as basename24 } from "path";
|
|
33696
33725
|
|
|
33697
33726
|
// src/commands/transcript/failTranscript.ts
|
|
@@ -33835,7 +33864,7 @@ function widenAudience(passages) {
|
|
|
33835
33864
|
|
|
33836
33865
|
// src/commands/transcript/merge.ts
|
|
33837
33866
|
function readSource2(file) {
|
|
33838
|
-
if (!
|
|
33867
|
+
if (!existsSync76(file)) failTranscript(`VTT file not found: ${file}`);
|
|
33839
33868
|
const cues = readCleanedCues(file);
|
|
33840
33869
|
if (cues.length === 0) failTranscript(`no cues found in: ${file}`);
|
|
33841
33870
|
return { path: file, name: basename24(file), cues };
|
|
@@ -33999,45 +34028,45 @@ function registerVerify(program2) {
|
|
|
33999
34028
|
|
|
34000
34029
|
// src/commands/voice/devices.ts
|
|
34001
34030
|
import { spawnSync as spawnSync9 } from "child_process";
|
|
34002
|
-
import { join as
|
|
34031
|
+
import { join as join91 } from "path";
|
|
34003
34032
|
|
|
34004
34033
|
// src/commands/voice/shared.ts
|
|
34005
34034
|
import { homedir as homedir25 } from "os";
|
|
34006
|
-
import { dirname as dirname37, join as
|
|
34035
|
+
import { dirname as dirname37, join as join90 } from "path";
|
|
34007
34036
|
import { fileURLToPath as fileURLToPath10 } from "url";
|
|
34008
34037
|
var __dirname6 = dirname37(fileURLToPath10(import.meta.url));
|
|
34009
|
-
var VOICE_DIR =
|
|
34038
|
+
var VOICE_DIR = join90(homedir25(), ".assist", "voice");
|
|
34010
34039
|
var voicePaths = {
|
|
34011
34040
|
dir: VOICE_DIR,
|
|
34012
|
-
pid:
|
|
34013
|
-
log:
|
|
34014
|
-
venv:
|
|
34015
|
-
lock:
|
|
34041
|
+
pid: join90(VOICE_DIR, "voice.pid"),
|
|
34042
|
+
log: join90(VOICE_DIR, "voice.log"),
|
|
34043
|
+
venv: join90(VOICE_DIR, ".venv"),
|
|
34044
|
+
lock: join90(VOICE_DIR, "voice.lock")
|
|
34016
34045
|
};
|
|
34017
34046
|
function getPythonDir() {
|
|
34018
|
-
return
|
|
34047
|
+
return join90(__dirname6, "commands", "voice", "python");
|
|
34019
34048
|
}
|
|
34020
34049
|
function getVenvPython() {
|
|
34021
|
-
return process.platform === "win32" ?
|
|
34050
|
+
return process.platform === "win32" ? join90(voicePaths.venv, "Scripts", "python.exe") : join90(voicePaths.venv, "bin", "python");
|
|
34022
34051
|
}
|
|
34023
34052
|
function getLockDir() {
|
|
34024
34053
|
const config = loadConfig();
|
|
34025
34054
|
return config.voice?.lockDir ?? VOICE_DIR;
|
|
34026
34055
|
}
|
|
34027
34056
|
function getLockFile() {
|
|
34028
|
-
return
|
|
34057
|
+
return join90(getLockDir(), "voice.lock");
|
|
34029
34058
|
}
|
|
34030
34059
|
|
|
34031
34060
|
// src/commands/voice/devices.ts
|
|
34032
34061
|
function devices() {
|
|
34033
|
-
const script =
|
|
34062
|
+
const script = join91(getPythonDir(), "list_devices.py");
|
|
34034
34063
|
spawnSync9(getVenvPython(), [script], { stdio: "inherit" });
|
|
34035
34064
|
}
|
|
34036
34065
|
|
|
34037
34066
|
// src/commands/voice/logs.ts
|
|
34038
|
-
import { existsSync as
|
|
34067
|
+
import { existsSync as existsSync77, readFileSync as readFileSync57 } from "fs";
|
|
34039
34068
|
function logs(options2) {
|
|
34040
|
-
if (!
|
|
34069
|
+
if (!existsSync77(voicePaths.log)) {
|
|
34041
34070
|
console.log("No voice log file found");
|
|
34042
34071
|
return;
|
|
34043
34072
|
}
|
|
@@ -34065,12 +34094,12 @@ function logs(options2) {
|
|
|
34065
34094
|
// src/commands/voice/setup.ts
|
|
34066
34095
|
import { spawnSync as spawnSync10 } from "child_process";
|
|
34067
34096
|
import { mkdirSync as mkdirSync31 } from "fs";
|
|
34068
|
-
import { join as
|
|
34097
|
+
import { join as join93 } from "path";
|
|
34069
34098
|
|
|
34070
34099
|
// src/commands/voice/checkLockFile.ts
|
|
34071
34100
|
import { execSync as execSync60 } from "child_process";
|
|
34072
|
-
import { existsSync as
|
|
34073
|
-
import { join as
|
|
34101
|
+
import { existsSync as existsSync78, mkdirSync as mkdirSync30, readFileSync as readFileSync58, writeFileSync as writeFileSync48 } from "fs";
|
|
34102
|
+
import { join as join92 } from "path";
|
|
34074
34103
|
function isProcessAlive2(pid) {
|
|
34075
34104
|
try {
|
|
34076
34105
|
process.kill(pid, 0);
|
|
@@ -34081,7 +34110,7 @@ function isProcessAlive2(pid) {
|
|
|
34081
34110
|
}
|
|
34082
34111
|
function checkLockFile() {
|
|
34083
34112
|
const lockFile = getLockFile();
|
|
34084
|
-
if (!
|
|
34113
|
+
if (!existsSync78(lockFile)) return;
|
|
34085
34114
|
try {
|
|
34086
34115
|
const lock2 = JSON.parse(readFileSync58(lockFile, "utf8"));
|
|
34087
34116
|
if (lock2.pid && isProcessAlive2(lock2.pid)) {
|
|
@@ -34094,7 +34123,7 @@ function checkLockFile() {
|
|
|
34094
34123
|
}
|
|
34095
34124
|
}
|
|
34096
34125
|
function bootstrapVenv() {
|
|
34097
|
-
if (
|
|
34126
|
+
if (existsSync78(getVenvPython())) return;
|
|
34098
34127
|
console.log("Setting up Python environment...");
|
|
34099
34128
|
const pythonDir = getPythonDir();
|
|
34100
34129
|
execSync60(
|
|
@@ -34107,7 +34136,7 @@ function bootstrapVenv() {
|
|
|
34107
34136
|
}
|
|
34108
34137
|
function writeLockFile(pid) {
|
|
34109
34138
|
const lockFile = getLockFile();
|
|
34110
|
-
mkdirSync30(
|
|
34139
|
+
mkdirSync30(join92(lockFile, ".."), { recursive: true });
|
|
34111
34140
|
writeFileSync48(
|
|
34112
34141
|
lockFile,
|
|
34113
34142
|
JSON.stringify({
|
|
@@ -34123,7 +34152,7 @@ function setup() {
|
|
|
34123
34152
|
mkdirSync31(voicePaths.dir, { recursive: true });
|
|
34124
34153
|
bootstrapVenv();
|
|
34125
34154
|
console.log("\nDownloading models...\n");
|
|
34126
|
-
const script =
|
|
34155
|
+
const script = join93(getPythonDir(), "setup_models.py");
|
|
34127
34156
|
const result = spawnSync10(getVenvPython(), [script], {
|
|
34128
34157
|
stdio: "inherit",
|
|
34129
34158
|
env: { ...process.env, VOICE_LOG_FILE: voicePaths.log }
|
|
@@ -34137,7 +34166,7 @@ function setup() {
|
|
|
34137
34166
|
// src/commands/voice/start.ts
|
|
34138
34167
|
import { spawn as spawn8 } from "child_process";
|
|
34139
34168
|
import { mkdirSync as mkdirSync32, writeFileSync as writeFileSync49 } from "fs";
|
|
34140
|
-
import { join as
|
|
34169
|
+
import { join as join94 } from "path";
|
|
34141
34170
|
|
|
34142
34171
|
// src/commands/voice/buildDaemonEnv.ts
|
|
34143
34172
|
function buildDaemonEnv(options2) {
|
|
@@ -34175,7 +34204,7 @@ function start2(options2) {
|
|
|
34175
34204
|
bootstrapVenv();
|
|
34176
34205
|
const debug = options2.debug || options2.foreground || process.platform === "win32";
|
|
34177
34206
|
const env = buildDaemonEnv({ debug });
|
|
34178
|
-
const script =
|
|
34207
|
+
const script = join94(getPythonDir(), "voice_daemon.py");
|
|
34179
34208
|
const python = getVenvPython();
|
|
34180
34209
|
if (options2.foreground) {
|
|
34181
34210
|
spawnForeground(python, script, env);
|
|
@@ -34185,7 +34214,7 @@ function start2(options2) {
|
|
|
34185
34214
|
}
|
|
34186
34215
|
|
|
34187
34216
|
// src/commands/voice/status.ts
|
|
34188
|
-
import { existsSync as
|
|
34217
|
+
import { existsSync as existsSync79, readFileSync as readFileSync59 } from "fs";
|
|
34189
34218
|
function isProcessAlive3(pid) {
|
|
34190
34219
|
try {
|
|
34191
34220
|
process.kill(pid, 0);
|
|
@@ -34195,12 +34224,12 @@ function isProcessAlive3(pid) {
|
|
|
34195
34224
|
}
|
|
34196
34225
|
}
|
|
34197
34226
|
function readRecentLogs(count8) {
|
|
34198
|
-
if (!
|
|
34227
|
+
if (!existsSync79(voicePaths.log)) return [];
|
|
34199
34228
|
const lines2 = readFileSync59(voicePaths.log, "utf8").trim().split("\n");
|
|
34200
34229
|
return lines2.slice(-count8);
|
|
34201
34230
|
}
|
|
34202
34231
|
function status2() {
|
|
34203
|
-
if (!
|
|
34232
|
+
if (!existsSync79(voicePaths.pid)) {
|
|
34204
34233
|
console.log("Voice daemon: not running (no PID file)");
|
|
34205
34234
|
return;
|
|
34206
34235
|
}
|
|
@@ -34223,9 +34252,9 @@ function status2() {
|
|
|
34223
34252
|
}
|
|
34224
34253
|
|
|
34225
34254
|
// src/commands/voice/stop.ts
|
|
34226
|
-
import { existsSync as
|
|
34255
|
+
import { existsSync as existsSync80, readFileSync as readFileSync60, unlinkSync as unlinkSync20 } from "fs";
|
|
34227
34256
|
function stop2() {
|
|
34228
|
-
if (!
|
|
34257
|
+
if (!existsSync80(voicePaths.pid)) {
|
|
34229
34258
|
console.log("Voice daemon is not running (no PID file)");
|
|
34230
34259
|
return;
|
|
34231
34260
|
}
|
|
@@ -34242,7 +34271,7 @@ function stop2() {
|
|
|
34242
34271
|
}
|
|
34243
34272
|
try {
|
|
34244
34273
|
const lockFile = getLockFile();
|
|
34245
|
-
if (
|
|
34274
|
+
if (existsSync80(lockFile)) unlinkSync20(lockFile);
|
|
34246
34275
|
} catch {
|
|
34247
34276
|
}
|
|
34248
34277
|
console.log("Voice daemon stopped");
|
|
@@ -34306,11 +34335,11 @@ function changedPaths(from, cwd) {
|
|
|
34306
34335
|
}
|
|
34307
34336
|
|
|
34308
34337
|
// src/commands/watch/readBuiltVersion.ts
|
|
34309
|
-
import { join as
|
|
34338
|
+
import { join as join95 } from "path";
|
|
34310
34339
|
function readBuiltVersion(cwd) {
|
|
34311
34340
|
try {
|
|
34312
34341
|
const root = runGit3(["rev-parse", "--show-toplevel"], cwd);
|
|
34313
|
-
return readPackageJson(
|
|
34342
|
+
return readPackageJson(join95(root, "package.json")).version ?? "unknown";
|
|
34314
34343
|
} catch {
|
|
34315
34344
|
return "unknown";
|
|
34316
34345
|
}
|
|
@@ -34367,11 +34396,11 @@ var webUiPrefix = "src/commands/sessions/web/ui/";
|
|
|
34367
34396
|
var sessionsPrefix = "src/commands/sessions/";
|
|
34368
34397
|
var rules = [
|
|
34369
34398
|
{
|
|
34370
|
-
matches: (
|
|
34399
|
+
matches: (path91) => path91.startsWith(webUiPrefix),
|
|
34371
34400
|
advice: "restart the web server, then hard-reload the browser tab"
|
|
34372
34401
|
},
|
|
34373
34402
|
{
|
|
34374
|
-
matches: (
|
|
34403
|
+
matches: (path91) => path91.startsWith(sessionsPrefix) && !path91.startsWith(webUiPrefix),
|
|
34375
34404
|
advice: "restart the daemon"
|
|
34376
34405
|
}
|
|
34377
34406
|
];
|
|
@@ -34382,31 +34411,27 @@ function restartAdvice(paths) {
|
|
|
34382
34411
|
// src/commands/watch/syncAdvice.ts
|
|
34383
34412
|
var rules2 = [
|
|
34384
34413
|
{
|
|
34385
|
-
matches: (
|
|
34414
|
+
matches: (path91) => path91.startsWith("claude/commands/"),
|
|
34386
34415
|
reason: "claude/commands changed"
|
|
34387
34416
|
},
|
|
34388
34417
|
{
|
|
34389
|
-
matches: (
|
|
34418
|
+
matches: (path91) => path91.startsWith("claude/skills/"),
|
|
34390
34419
|
reason: "claude/skills changed"
|
|
34391
34420
|
},
|
|
34392
34421
|
{
|
|
34393
|
-
matches: (
|
|
34422
|
+
matches: (path91) => path91 === "claude/settings.json",
|
|
34394
34423
|
reason: "claude/settings.json changed"
|
|
34395
34424
|
},
|
|
34396
34425
|
{
|
|
34397
|
-
matches: (
|
|
34398
|
-
reason: "claude/CLAUDE.md changed"
|
|
34399
|
-
},
|
|
34400
|
-
{
|
|
34401
|
-
matches: (path90) => path90 === "claude/design-system-prompt.md",
|
|
34426
|
+
matches: (path91) => path91 === "claude/design-system-prompt.md",
|
|
34402
34427
|
reason: "claude/design-system-prompt.md changed"
|
|
34403
34428
|
},
|
|
34404
34429
|
{
|
|
34405
|
-
matches: (
|
|
34430
|
+
matches: (path91) => path91.startsWith("codex/"),
|
|
34406
34431
|
reason: "codex sources changed"
|
|
34407
34432
|
},
|
|
34408
34433
|
{
|
|
34409
|
-
matches: (
|
|
34434
|
+
matches: (path91) => path91.startsWith("pi/"),
|
|
34410
34435
|
reason: "pi sources changed"
|
|
34411
34436
|
}
|
|
34412
34437
|
];
|
|
@@ -34647,7 +34672,7 @@ function resolveParams(params, cliArgs) {
|
|
|
34647
34672
|
}
|
|
34648
34673
|
|
|
34649
34674
|
// src/commands/run/resolveRunCwd.ts
|
|
34650
|
-
import { existsSync as
|
|
34675
|
+
import { existsSync as existsSync81 } from "fs";
|
|
34651
34676
|
import { resolve as resolve19 } from "path";
|
|
34652
34677
|
var MissingRunCwdError = class extends Error {
|
|
34653
34678
|
constructor(runName, cwd) {
|
|
@@ -34660,25 +34685,25 @@ var MissingRunCwdError = class extends Error {
|
|
|
34660
34685
|
function resolveRunCwd(config, baseDir = runConfigBaseDir()) {
|
|
34661
34686
|
if (!config.cwd) return void 0;
|
|
34662
34687
|
const cwd = resolve19(baseDir, config.cwd);
|
|
34663
|
-
if (!
|
|
34688
|
+
if (!existsSync81(cwd)) throw new MissingRunCwdError(config.name, cwd);
|
|
34664
34689
|
return cwd;
|
|
34665
34690
|
}
|
|
34666
34691
|
|
|
34667
34692
|
// src/commands/run/runCommandToCompletion.ts
|
|
34668
34693
|
import { spawn as spawn9 } from "child_process";
|
|
34669
|
-
import { existsSync as
|
|
34694
|
+
import { existsSync as existsSync83 } from "fs";
|
|
34670
34695
|
|
|
34671
34696
|
// src/commands/run/resolveCommand.ts
|
|
34672
34697
|
import { execFileSync as execFileSync18 } from "child_process";
|
|
34673
|
-
import { existsSync as
|
|
34674
|
-
import { dirname as dirname38, join as
|
|
34698
|
+
import { existsSync as existsSync82 } from "fs";
|
|
34699
|
+
import { dirname as dirname38, join as join96, resolve as resolve20 } from "path";
|
|
34675
34700
|
function resolveCommand2(command) {
|
|
34676
34701
|
if (process.platform !== "win32" || command !== "bash") return command;
|
|
34677
34702
|
try {
|
|
34678
34703
|
const gitPath = execFileSync18("where", ["git"], { encoding: "utf8" }).trim().split("\r\n")[0];
|
|
34679
34704
|
const gitRoot = resolve20(dirname38(gitPath), "..");
|
|
34680
|
-
const gitBash =
|
|
34681
|
-
if (
|
|
34705
|
+
const gitBash = join96(gitRoot, "bin", "bash.exe");
|
|
34706
|
+
if (existsSync82(gitBash)) return gitBash;
|
|
34682
34707
|
} catch {
|
|
34683
34708
|
return command;
|
|
34684
34709
|
}
|
|
@@ -34688,7 +34713,7 @@ function resolveCommand2(command) {
|
|
|
34688
34713
|
// src/commands/run/runCommandToCompletion.ts
|
|
34689
34714
|
function runCommandToCompletion(command, args, env, cwd, quiet) {
|
|
34690
34715
|
return new Promise((resolveResult) => {
|
|
34691
|
-
if (cwd && !
|
|
34716
|
+
if (cwd && !existsSync83(cwd)) {
|
|
34692
34717
|
resolveResult({
|
|
34693
34718
|
kind: "failed",
|
|
34694
34719
|
message: `Failed to execute command: cwd ${cwd} does not exist`
|
|
@@ -35105,7 +35130,7 @@ async function auth() {
|
|
|
35105
35130
|
// src/commands/roam/postRoamActivity.ts
|
|
35106
35131
|
import { execFileSync as execFileSync20 } from "child_process";
|
|
35107
35132
|
import { readdirSync as readdirSync22, readFileSync as readFileSync61, statSync as statSync12 } from "fs";
|
|
35108
|
-
import { join as
|
|
35133
|
+
import { join as join97 } from "path";
|
|
35109
35134
|
function findPortFile(roamDir) {
|
|
35110
35135
|
let entries;
|
|
35111
35136
|
try {
|
|
@@ -35114,9 +35139,9 @@ function findPortFile(roamDir) {
|
|
|
35114
35139
|
return void 0;
|
|
35115
35140
|
}
|
|
35116
35141
|
const candidates = entries.filter((name) => /^roam-local-api(-[^.]+)?\.port$/.test(name)).map((name) => {
|
|
35117
|
-
const
|
|
35142
|
+
const path91 = join97(roamDir, name);
|
|
35118
35143
|
try {
|
|
35119
|
-
return { path:
|
|
35144
|
+
return { path: path91, mtimeMs: statSync12(path91).mtimeMs };
|
|
35120
35145
|
} catch {
|
|
35121
35146
|
return void 0;
|
|
35122
35147
|
}
|
|
@@ -35131,7 +35156,7 @@ var PID_BY_APP = {
|
|
|
35131
35156
|
function postRoamActivity(app, event) {
|
|
35132
35157
|
const appData = process.env.APPDATA;
|
|
35133
35158
|
if (!appData) return;
|
|
35134
|
-
const portFile = findPortFile(
|
|
35159
|
+
const portFile = findPortFile(join97(appData, "Roam"));
|
|
35135
35160
|
if (!portFile) return;
|
|
35136
35161
|
let port;
|
|
35137
35162
|
try {
|
|
@@ -35267,7 +35292,7 @@ async function run3(name, args) {
|
|
|
35267
35292
|
|
|
35268
35293
|
// src/commands/run/add.ts
|
|
35269
35294
|
import { mkdirSync as mkdirSync33, writeFileSync as writeFileSync50 } from "fs";
|
|
35270
|
-
import { join as
|
|
35295
|
+
import { join as join98 } from "path";
|
|
35271
35296
|
|
|
35272
35297
|
// src/commands/run/extractOption.ts
|
|
35273
35298
|
function extractOption(args, flag) {
|
|
@@ -35328,7 +35353,7 @@ function saveNewRunConfig(name, command, args, cwd) {
|
|
|
35328
35353
|
saveConfig(config);
|
|
35329
35354
|
}
|
|
35330
35355
|
function createCommandFile(name) {
|
|
35331
|
-
const dir =
|
|
35356
|
+
const dir = join98(".claude", "commands");
|
|
35332
35357
|
mkdirSync33(dir, { recursive: true });
|
|
35333
35358
|
const content = `---
|
|
35334
35359
|
description: Run ${name}
|
|
@@ -35336,7 +35361,7 @@ description: Run ${name}
|
|
|
35336
35361
|
|
|
35337
35362
|
Run \`assist run ${name} $ARGUMENTS 2>&1\`.
|
|
35338
35363
|
`;
|
|
35339
|
-
const filePath =
|
|
35364
|
+
const filePath = join98(dir, `${name}.md`);
|
|
35340
35365
|
writeFileSync50(filePath, content);
|
|
35341
35366
|
console.log(`Created command file: ${filePath}`);
|
|
35342
35367
|
}
|
|
@@ -35360,11 +35385,11 @@ function findLinkIndex() {
|
|
|
35360
35385
|
function parseLinkArgs() {
|
|
35361
35386
|
const idx = findLinkIndex();
|
|
35362
35387
|
if (idx === -1) return null;
|
|
35363
|
-
const
|
|
35388
|
+
const path91 = process.argv[idx + 1];
|
|
35364
35389
|
const rest = process.argv.slice(idx + 2);
|
|
35365
35390
|
const { value: prefix2 } = extractOption(rest, "--prefix");
|
|
35366
35391
|
if (!prefix2) return null;
|
|
35367
|
-
return { path:
|
|
35392
|
+
return { path: path91, prefix: prefix2 };
|
|
35368
35393
|
}
|
|
35369
35394
|
function hasDuplicateLink(runList, linkPath) {
|
|
35370
35395
|
return runList.some(
|
|
@@ -35392,8 +35417,8 @@ function link2() {
|
|
|
35392
35417
|
}
|
|
35393
35418
|
|
|
35394
35419
|
// src/commands/run/remove.ts
|
|
35395
|
-
import { existsSync as
|
|
35396
|
-
import { join as
|
|
35420
|
+
import { existsSync as existsSync84, unlinkSync as unlinkSync21 } from "fs";
|
|
35421
|
+
import { join as join99 } from "path";
|
|
35397
35422
|
function findRemoveIndex() {
|
|
35398
35423
|
const idx = process.argv.indexOf("remove");
|
|
35399
35424
|
if (idx === -1 || idx + 1 >= process.argv.length) return -1;
|
|
@@ -35408,8 +35433,8 @@ function parseRemoveName() {
|
|
|
35408
35433
|
return process.argv[idx + 1];
|
|
35409
35434
|
}
|
|
35410
35435
|
function deleteCommandFile(name) {
|
|
35411
|
-
const filePath =
|
|
35412
|
-
if (
|
|
35436
|
+
const filePath = join99(".claude", "commands", `${name}.md`);
|
|
35437
|
+
if (existsSync84(filePath)) {
|
|
35413
35438
|
unlinkSync21(filePath);
|
|
35414
35439
|
console.log(`Deleted command file: ${filePath}`);
|
|
35415
35440
|
}
|
|
@@ -35454,9 +35479,9 @@ function registerRun(program2) {
|
|
|
35454
35479
|
|
|
35455
35480
|
// src/commands/screenshot/index.ts
|
|
35456
35481
|
import { execSync as execSync62 } from "child_process";
|
|
35457
|
-
import { existsSync as
|
|
35482
|
+
import { existsSync as existsSync85, mkdirSync as mkdirSync34, unlinkSync as unlinkSync22, writeFileSync as writeFileSync51 } from "fs";
|
|
35458
35483
|
import { tmpdir as tmpdir9 } from "os";
|
|
35459
|
-
import { join as
|
|
35484
|
+
import { join as join100, resolve as resolve21 } from "path";
|
|
35460
35485
|
import chalk229 from "chalk";
|
|
35461
35486
|
|
|
35462
35487
|
// src/commands/screenshot/captureWindowPs1.ts
|
|
@@ -35586,14 +35611,14 @@ Write-Output $OutputPath
|
|
|
35586
35611
|
|
|
35587
35612
|
// src/commands/screenshot/index.ts
|
|
35588
35613
|
function buildOutputPath(outputDir, processName) {
|
|
35589
|
-
if (!
|
|
35614
|
+
if (!existsSync85(outputDir)) {
|
|
35590
35615
|
mkdirSync34(outputDir, { recursive: true });
|
|
35591
35616
|
}
|
|
35592
35617
|
const timestamp6 = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
35593
35618
|
return resolve21(outputDir, `${processName}-${timestamp6}.png`);
|
|
35594
35619
|
}
|
|
35595
35620
|
function runPowerShellScript(processName, outputPath) {
|
|
35596
|
-
const scriptPath =
|
|
35621
|
+
const scriptPath = join100(tmpdir9(), `assist-screenshot-${Date.now()}.ps1`);
|
|
35597
35622
|
writeFileSync51(scriptPath, captureWindowPs1, "utf8");
|
|
35598
35623
|
try {
|
|
35599
35624
|
execSync62(
|
|
@@ -35937,12 +35962,12 @@ function toSessionRunInfo({
|
|
|
35937
35962
|
}
|
|
35938
35963
|
|
|
35939
35964
|
// src/commands/sessions/daemon/worktree/joinRefusal.ts
|
|
35940
|
-
import { existsSync as
|
|
35965
|
+
import { existsSync as existsSync86 } from "fs";
|
|
35941
35966
|
function joinRefusal(session) {
|
|
35942
35967
|
if (session.commandType === "run") return "a server run has no agent stream";
|
|
35943
35968
|
if (session.closing === true) return "the session is closing";
|
|
35944
35969
|
if (!session.cwd) return "the session has no working directory";
|
|
35945
|
-
if (!
|
|
35970
|
+
if (!existsSync86(session.cwd))
|
|
35946
35971
|
return "the session's workspace no longer exists";
|
|
35947
35972
|
return void 0;
|
|
35948
35973
|
}
|
|
@@ -36106,26 +36131,26 @@ function sessionBase(id, status3) {
|
|
|
36106
36131
|
}
|
|
36107
36132
|
|
|
36108
36133
|
// src/commands/sessions/daemon/spawnPty.ts
|
|
36109
|
-
import { existsSync as
|
|
36134
|
+
import { existsSync as existsSync88 } from "fs";
|
|
36110
36135
|
import * as pty from "node-pty";
|
|
36111
36136
|
|
|
36112
36137
|
// src/commands/sessions/daemon/ensureSpawnHelperExecutable.ts
|
|
36113
|
-
import { chmodSync, existsSync as
|
|
36138
|
+
import { chmodSync, existsSync as existsSync87, statSync as statSync13 } from "fs";
|
|
36114
36139
|
import { createRequire as createRequire3 } from "module";
|
|
36115
|
-
import
|
|
36140
|
+
import path86 from "path";
|
|
36116
36141
|
var require4 = createRequire3(import.meta.url);
|
|
36117
36142
|
var ensured = false;
|
|
36118
36143
|
function ensureSpawnHelperExecutable() {
|
|
36119
36144
|
if (ensured || process.platform !== "darwin") return;
|
|
36120
36145
|
ensured = true;
|
|
36121
|
-
const ptyRoot =
|
|
36122
|
-
const helper =
|
|
36146
|
+
const ptyRoot = path86.join(path86.dirname(require4.resolve("node-pty")), "..");
|
|
36147
|
+
const helper = path86.join(
|
|
36123
36148
|
ptyRoot,
|
|
36124
36149
|
"prebuilds",
|
|
36125
36150
|
`${process.platform}-${process.arch}`,
|
|
36126
36151
|
"spawn-helper"
|
|
36127
36152
|
);
|
|
36128
|
-
if (!
|
|
36153
|
+
if (!existsSync87(helper)) return;
|
|
36129
36154
|
const mode = statSync13(helper).mode;
|
|
36130
36155
|
if ((mode & 73) === 0) chmodSync(helper, mode | 493);
|
|
36131
36156
|
}
|
|
@@ -36161,7 +36186,7 @@ function spawnPty(args, cwd, sessionId, extraEnv) {
|
|
|
36161
36186
|
});
|
|
36162
36187
|
}
|
|
36163
36188
|
function refuseMissingCwd(cwd, sessionId) {
|
|
36164
|
-
if (!cwd ||
|
|
36189
|
+
if (!cwd || existsSync88(cwd)) return;
|
|
36165
36190
|
daemonLog(
|
|
36166
36191
|
`${sessionId ? `session ${sessionId}` : "pty"} not spawned: working directory ${cwd} no longer exists`
|
|
36167
36192
|
);
|
|
@@ -36239,19 +36264,19 @@ function serverRunMeta(runName, cwd) {
|
|
|
36239
36264
|
}
|
|
36240
36265
|
|
|
36241
36266
|
// src/commands/sessions/daemon/readDesignSystemPrompt.ts
|
|
36242
|
-
import * as
|
|
36243
|
-
import * as
|
|
36267
|
+
import * as fs49 from "fs";
|
|
36268
|
+
import * as path87 from "path";
|
|
36244
36269
|
import { fileURLToPath as fileURLToPath11 } from "url";
|
|
36245
36270
|
var __filename5 = fileURLToPath11(import.meta.url);
|
|
36246
|
-
var __dirname7 =
|
|
36271
|
+
var __dirname7 = path87.dirname(__filename5);
|
|
36247
36272
|
function readDesignSystemPrompt() {
|
|
36248
|
-
const promptPath =
|
|
36273
|
+
const promptPath = path87.join(
|
|
36249
36274
|
__dirname7,
|
|
36250
36275
|
"..",
|
|
36251
36276
|
"claude",
|
|
36252
36277
|
"design-system-prompt.md"
|
|
36253
36278
|
);
|
|
36254
|
-
return
|
|
36279
|
+
return fs49.readFileSync(promptPath, "utf8");
|
|
36255
36280
|
}
|
|
36256
36281
|
|
|
36257
36282
|
// src/commands/sessions/daemon/spawnClaude.ts
|
|
@@ -36343,17 +36368,17 @@ function setStatus2(session, newStatus) {
|
|
|
36343
36368
|
}
|
|
36344
36369
|
|
|
36345
36370
|
// src/commands/sessions/daemon/worktree/reapWorktree.ts
|
|
36346
|
-
import { existsSync as
|
|
36371
|
+
import { existsSync as existsSync90 } from "fs";
|
|
36347
36372
|
import { basename as basename25 } from "path";
|
|
36348
36373
|
|
|
36349
36374
|
// src/commands/sessions/daemon/worktree/deleteStrandedTree.ts
|
|
36350
|
-
import { existsSync as
|
|
36351
|
-
import { join as
|
|
36375
|
+
import { existsSync as existsSync89 } from "fs";
|
|
36376
|
+
import { join as join103 } from "path";
|
|
36352
36377
|
|
|
36353
36378
|
// src/commands/sessions/daemon/worktree/deleteTreeDirectly.ts
|
|
36354
36379
|
import { statSync as statSync14 } from "fs";
|
|
36355
36380
|
import { rm as rm4 } from "fs/promises";
|
|
36356
|
-
import { join as
|
|
36381
|
+
import { join as join102 } from "path";
|
|
36357
36382
|
async function deleteTreeDirectly(clone, worktreePath, why) {
|
|
36358
36383
|
if (holdsAGitDirectoryRatherThanALink(worktreePath)) {
|
|
36359
36384
|
const refusal = "it is a clone of its own, not a linked worktree";
|
|
@@ -36381,7 +36406,7 @@ async function deleteTreeDirectly(clone, worktreePath, why) {
|
|
|
36381
36406
|
return { removed: true };
|
|
36382
36407
|
}
|
|
36383
36408
|
function holdsAGitDirectoryRatherThanALink(worktreePath) {
|
|
36384
|
-
return statSync14(
|
|
36409
|
+
return statSync14(join102(worktreePath, ".git"), {
|
|
36385
36410
|
throwIfNoEntry: false
|
|
36386
36411
|
})?.isDirectory() === true;
|
|
36387
36412
|
}
|
|
@@ -36417,7 +36442,7 @@ async function deleteStrandedTree(clone, worktreePath, cause) {
|
|
|
36417
36442
|
);
|
|
36418
36443
|
}
|
|
36419
36444
|
function strandedReason(worktreePath, cause) {
|
|
36420
|
-
if (!
|
|
36445
|
+
if (!existsSync89(join103(worktreePath, ".git")))
|
|
36421
36446
|
return "its .git link is already gone";
|
|
36422
36447
|
if (/not a working tree|not a git repository/i.test(reason2(cause)))
|
|
36423
36448
|
return "git no longer recognises it as a working tree";
|
|
@@ -36469,7 +36494,7 @@ function reason3(error) {
|
|
|
36469
36494
|
|
|
36470
36495
|
// src/commands/sessions/daemon/worktree/reapWorktree.ts
|
|
36471
36496
|
async function reapWorktree(worktreePath, force = false) {
|
|
36472
|
-
if (!
|
|
36497
|
+
if (!existsSync90(worktreePath)) {
|
|
36473
36498
|
forgetWorktree(worktreePath);
|
|
36474
36499
|
daemonLog(
|
|
36475
36500
|
`worktree ${worktreePath} already gone; its record was forgotten`
|
|
@@ -36494,7 +36519,7 @@ async function reapWorktree(worktreePath, force = false) {
|
|
|
36494
36519
|
}
|
|
36495
36520
|
function owningClone(worktreePath) {
|
|
36496
36521
|
const recorded = worktreeAttributionIncludingReaped(worktreePath)?.clone;
|
|
36497
|
-
if (recorded &&
|
|
36522
|
+
if (recorded && existsSync90(recorded)) return recorded;
|
|
36498
36523
|
const detected = mainWorktree(worktreePath);
|
|
36499
36524
|
if (detected) return detected;
|
|
36500
36525
|
daemonLog(
|
|
@@ -36625,12 +36650,12 @@ function closeGateApplies(sessions, session) {
|
|
|
36625
36650
|
}
|
|
36626
36651
|
|
|
36627
36652
|
// src/commands/sessions/daemon/worktree/watchGitState.ts
|
|
36628
|
-
import { existsSync as
|
|
36653
|
+
import { existsSync as existsSync91, watch } from "fs";
|
|
36629
36654
|
var DEBOUNCE_MS = 500;
|
|
36630
36655
|
var POLL_MS = 3e4;
|
|
36631
36656
|
function watchGitState(cwd, onChange) {
|
|
36632
36657
|
const common = gitCommonDir(cwd);
|
|
36633
|
-
if (!common || !
|
|
36658
|
+
if (!common || !existsSync91(common)) return void 0;
|
|
36634
36659
|
const watchers = [
|
|
36635
36660
|
watchGitDir(common, onChange),
|
|
36636
36661
|
pollGitState(cwd, onChange)
|
|
@@ -37121,10 +37146,10 @@ function emitSessionOutput(session, clients, data) {
|
|
|
37121
37146
|
}
|
|
37122
37147
|
|
|
37123
37148
|
// src/commands/sessions/daemon/exitReason.ts
|
|
37124
|
-
import { existsSync as
|
|
37149
|
+
import { existsSync as existsSync92 } from "fs";
|
|
37125
37150
|
import { resolve as resolve22 } from "path";
|
|
37126
37151
|
function exitDetail(session) {
|
|
37127
|
-
if (session.cwd && !
|
|
37152
|
+
if (session.cwd && !existsSync92(session.cwd))
|
|
37128
37153
|
return `working directory ${session.cwd} no longer exists`;
|
|
37129
37154
|
return missingRunConfigCwd(session);
|
|
37130
37155
|
}
|
|
@@ -37138,7 +37163,7 @@ function missingRunConfigCwd(session) {
|
|
|
37138
37163
|
const config = resolveRunConfig(session.runName, dir);
|
|
37139
37164
|
if (!config?.cwd) return void 0;
|
|
37140
37165
|
const configured = resolve22(runConfigBaseDirFrom(dir), config.cwd);
|
|
37141
|
-
if (
|
|
37166
|
+
if (existsSync92(configured)) return void 0;
|
|
37142
37167
|
return `run config "${config.name}": cwd ${configured} does not exist`;
|
|
37143
37168
|
}
|
|
37144
37169
|
|
|
@@ -37175,7 +37200,7 @@ function handleFailedResume(session, exitCode, onStatusChange) {
|
|
|
37175
37200
|
}
|
|
37176
37201
|
|
|
37177
37202
|
// src/commands/sessions/daemon/watchActivity.ts
|
|
37178
|
-
import { existsSync as
|
|
37203
|
+
import { existsSync as existsSync93, mkdirSync as mkdirSync35, watch as watch2 } from "fs";
|
|
37179
37204
|
import { dirname as dirname40 } from "path";
|
|
37180
37205
|
|
|
37181
37206
|
// src/commands/sessions/daemon/applyActivityToSession.ts
|
|
@@ -37237,8 +37262,8 @@ async function seedRunningMsFromUsage(session, notify2) {
|
|
|
37237
37262
|
var DEBOUNCE_MS2 = 50;
|
|
37238
37263
|
function watchActivity(session, notify2, onClaudeSessionId) {
|
|
37239
37264
|
if (session.commandType !== "assist" || !session.cwd) return;
|
|
37240
|
-
const
|
|
37241
|
-
const dir = dirname40(
|
|
37265
|
+
const path91 = activityPath(session.id);
|
|
37266
|
+
const dir = dirname40(path91);
|
|
37242
37267
|
try {
|
|
37243
37268
|
mkdirSync35(dir, { recursive: true });
|
|
37244
37269
|
} catch {
|
|
@@ -37248,7 +37273,7 @@ function watchActivity(session, notify2, onClaudeSessionId) {
|
|
|
37248
37273
|
let timer = null;
|
|
37249
37274
|
const read3 = () => {
|
|
37250
37275
|
timer = null;
|
|
37251
|
-
const activity2 = readActivity(
|
|
37276
|
+
const activity2 = readActivity(path91);
|
|
37252
37277
|
if (!activity2) return;
|
|
37253
37278
|
applyActivityToSession(session, activity2);
|
|
37254
37279
|
if (activity2.claudeSessionId) onClaudeSessionId?.(session);
|
|
@@ -37257,11 +37282,11 @@ function watchActivity(session, notify2, onClaudeSessionId) {
|
|
|
37257
37282
|
notify2();
|
|
37258
37283
|
};
|
|
37259
37284
|
session.activityWatcher = watch2(dir, (_event, filename) => {
|
|
37260
|
-
if (filename && !
|
|
37285
|
+
if (filename && !path91.endsWith(filename)) return;
|
|
37261
37286
|
if (timer) clearTimeout(timer);
|
|
37262
37287
|
timer = setTimeout(read3, DEBOUNCE_MS2);
|
|
37263
37288
|
});
|
|
37264
|
-
if (
|
|
37289
|
+
if (existsSync93(path91)) read3();
|
|
37265
37290
|
}
|
|
37266
37291
|
function refreshActivity(session) {
|
|
37267
37292
|
if (session.commandType !== "assist" || !session.cwd) return;
|
|
@@ -37340,7 +37365,7 @@ function reportSilentFailure(session, clients) {
|
|
|
37340
37365
|
}
|
|
37341
37366
|
|
|
37342
37367
|
// src/commands/sessions/shared/codex/resolveCodexSessionId.ts
|
|
37343
|
-
import * as
|
|
37368
|
+
import * as fs50 from "fs";
|
|
37344
37369
|
var META_LINES = 5;
|
|
37345
37370
|
async function resolveCodexSessionId(cwd, sinceMs) {
|
|
37346
37371
|
if (!cwd) return null;
|
|
@@ -37369,7 +37394,7 @@ async function startedIn(file, cwd, sinceMs) {
|
|
|
37369
37394
|
}
|
|
37370
37395
|
async function touchedSince(file, sinceMs) {
|
|
37371
37396
|
try {
|
|
37372
|
-
return (await
|
|
37397
|
+
return (await fs50.promises.stat(file)).mtimeMs >= sinceMs;
|
|
37373
37398
|
} catch {
|
|
37374
37399
|
return false;
|
|
37375
37400
|
}
|
|
@@ -37403,42 +37428,42 @@ function bindCodexSession(session, notify2) {
|
|
|
37403
37428
|
import { watch as watch3 } from "fs";
|
|
37404
37429
|
|
|
37405
37430
|
// src/commands/sessions/shared/findTranscriptPathSync.ts
|
|
37406
|
-
import * as
|
|
37407
|
-
import * as
|
|
37431
|
+
import * as fs51 from "fs";
|
|
37432
|
+
import * as path88 from "path";
|
|
37408
37433
|
function projectDirForCwd(cwd) {
|
|
37409
|
-
return
|
|
37434
|
+
return path88.join(claudeProjectsRoot(), projectSlug(cwd));
|
|
37410
37435
|
}
|
|
37411
37436
|
function transcriptPathFor(cwd, claudeSessionId) {
|
|
37412
|
-
return
|
|
37437
|
+
return path88.join(projectDirForCwd(cwd), `${claudeSessionId}.jsonl`);
|
|
37413
37438
|
}
|
|
37414
37439
|
function findTranscriptPathSync(cwd, claudeSessionId) {
|
|
37415
37440
|
const direct = transcriptPathFor(cwd, claudeSessionId);
|
|
37416
|
-
if (
|
|
37441
|
+
if (fs51.existsSync(direct)) return direct;
|
|
37417
37442
|
const dir = projectDirForCwd(cwd);
|
|
37418
37443
|
let files;
|
|
37419
37444
|
try {
|
|
37420
|
-
files =
|
|
37445
|
+
files = fs51.readdirSync(dir);
|
|
37421
37446
|
} catch {
|
|
37422
37447
|
return null;
|
|
37423
37448
|
}
|
|
37424
37449
|
for (const file of files) {
|
|
37425
37450
|
if (!file.endsWith(".jsonl")) continue;
|
|
37426
|
-
if (headContainsSessionId(
|
|
37427
|
-
return
|
|
37451
|
+
if (headContainsSessionId(path88.join(dir, file), claudeSessionId))
|
|
37452
|
+
return path88.join(dir, file);
|
|
37428
37453
|
}
|
|
37429
37454
|
return null;
|
|
37430
37455
|
}
|
|
37431
37456
|
function headContainsSessionId(filePath, claudeSessionId) {
|
|
37432
37457
|
let fd;
|
|
37433
37458
|
try {
|
|
37434
|
-
fd =
|
|
37459
|
+
fd = fs51.openSync(filePath, "r");
|
|
37435
37460
|
const buf = Buffer.alloc(16384);
|
|
37436
|
-
const bytesRead =
|
|
37461
|
+
const bytesRead = fs51.readSync(fd, buf, 0, buf.length, 0);
|
|
37437
37462
|
return buf.toString("utf8", 0, bytesRead).includes(claudeSessionId);
|
|
37438
37463
|
} catch {
|
|
37439
37464
|
return false;
|
|
37440
37465
|
} finally {
|
|
37441
|
-
if (fd !== void 0)
|
|
37466
|
+
if (fd !== void 0) fs51.closeSync(fd);
|
|
37442
37467
|
}
|
|
37443
37468
|
}
|
|
37444
37469
|
|
|
@@ -37608,7 +37633,7 @@ function asRecord3(value) {
|
|
|
37608
37633
|
}
|
|
37609
37634
|
|
|
37610
37635
|
// src/commands/sessions/shared/readTranscriptTail.ts
|
|
37611
|
-
import * as
|
|
37636
|
+
import * as fs52 from "fs";
|
|
37612
37637
|
var DEFAULT_MAX_BYTES = 256 * 1024;
|
|
37613
37638
|
function parseTailEntries(raw) {
|
|
37614
37639
|
const entries = [];
|
|
@@ -37632,7 +37657,7 @@ function dropPartialFirstLine(raw, sliced) {
|
|
|
37632
37657
|
async function readTranscriptTail(filePath, maxBytes = DEFAULT_MAX_BYTES) {
|
|
37633
37658
|
let handle;
|
|
37634
37659
|
try {
|
|
37635
|
-
handle = await
|
|
37660
|
+
handle = await fs52.promises.open(filePath, "r");
|
|
37636
37661
|
const { size } = await handle.stat();
|
|
37637
37662
|
const start3 = Math.max(0, size - maxBytes);
|
|
37638
37663
|
const length = size - start3;
|
|
@@ -37651,20 +37676,20 @@ async function readTranscriptTail(filePath, maxBytes = DEFAULT_MAX_BYTES) {
|
|
|
37651
37676
|
function readTranscriptTailSync(filePath, maxBytes = DEFAULT_MAX_BYTES) {
|
|
37652
37677
|
let fd;
|
|
37653
37678
|
try {
|
|
37654
|
-
fd =
|
|
37655
|
-
const { size } =
|
|
37679
|
+
fd = fs52.openSync(filePath, "r");
|
|
37680
|
+
const { size } = fs52.fstatSync(fd);
|
|
37656
37681
|
const start3 = Math.max(0, size - maxBytes);
|
|
37657
37682
|
const length = size - start3;
|
|
37658
37683
|
if (length === 0) return [];
|
|
37659
37684
|
const buf = Buffer.alloc(length);
|
|
37660
|
-
|
|
37685
|
+
fs52.readSync(fd, buf, 0, length, start3);
|
|
37661
37686
|
return parseTailEntries(
|
|
37662
37687
|
dropPartialFirstLine(buf.toString("utf8"), start3 > 0)
|
|
37663
37688
|
);
|
|
37664
37689
|
} catch {
|
|
37665
37690
|
return [];
|
|
37666
37691
|
} finally {
|
|
37667
|
-
if (fd !== void 0)
|
|
37692
|
+
if (fd !== void 0) fs52.closeSync(fd);
|
|
37668
37693
|
}
|
|
37669
37694
|
}
|
|
37670
37695
|
|
|
@@ -38043,7 +38068,7 @@ async function recordWindowTokens(db, window, resetsAt, tokensUp, tokensDown) {
|
|
|
38043
38068
|
}
|
|
38044
38069
|
|
|
38045
38070
|
// src/commands/sessions/shared/transcriptUsage.ts
|
|
38046
|
-
import * as
|
|
38071
|
+
import * as fs53 from "fs";
|
|
38047
38072
|
function transcriptUsage(lines2) {
|
|
38048
38073
|
const byId = /* @__PURE__ */ new Map();
|
|
38049
38074
|
for (const line of lines2) {
|
|
@@ -38067,7 +38092,7 @@ function transcriptUsage(lines2) {
|
|
|
38067
38092
|
return [...byId.values()];
|
|
38068
38093
|
}
|
|
38069
38094
|
async function readTranscriptUsage(transcriptPath2) {
|
|
38070
|
-
const content = await
|
|
38095
|
+
const content = await fs53.promises.readFile(transcriptPath2, "utf8");
|
|
38071
38096
|
return transcriptUsage(content.split("\n"));
|
|
38072
38097
|
}
|
|
38073
38098
|
|
|
@@ -38598,9 +38623,9 @@ function tempRoots() {
|
|
|
38598
38623
|
}
|
|
38599
38624
|
return [...roots];
|
|
38600
38625
|
}
|
|
38601
|
-
function underTempRoot(
|
|
38626
|
+
function underTempRoot(path91) {
|
|
38602
38627
|
return tempRoots().some(
|
|
38603
|
-
(root) =>
|
|
38628
|
+
(root) => path91.startsWith(root.endsWith(sep2) ? root : root + sep2)
|
|
38604
38629
|
);
|
|
38605
38630
|
}
|
|
38606
38631
|
|
|
@@ -38984,7 +39009,7 @@ function rearmStoppedSessions(sessions, notify2) {
|
|
|
38984
39009
|
}
|
|
38985
39010
|
|
|
38986
39011
|
// src/commands/sessions/daemon/worktree/reconcileWorktreesOnRestore.ts
|
|
38987
|
-
import { existsSync as
|
|
39012
|
+
import { existsSync as existsSync96 } from "fs";
|
|
38988
39013
|
import { basename as basename27 } from "path";
|
|
38989
39014
|
|
|
38990
39015
|
// src/commands/sessions/daemon/worktree/accountedTrees.ts
|
|
@@ -39039,18 +39064,18 @@ function bindResumedWorktree(session, cwd, notify2) {
|
|
|
39039
39064
|
}
|
|
39040
39065
|
|
|
39041
39066
|
// src/commands/sessions/daemon/worktree/reclaimVanishedWorktrees.ts
|
|
39042
|
-
import { existsSync as
|
|
39067
|
+
import { existsSync as existsSync95 } from "fs";
|
|
39043
39068
|
async function reclaimVanishedWorktrees(clone, paths) {
|
|
39044
|
-
if (!
|
|
39045
|
-
for (const { path:
|
|
39069
|
+
if (!existsSync95(clone)) {
|
|
39070
|
+
for (const { path: path91 } of paths) forgetWorktree(path91);
|
|
39046
39071
|
daemonLog(
|
|
39047
39072
|
`clone ${clone} is gone; forgot ${paths.length} worktree record(s) it owned`
|
|
39048
39073
|
);
|
|
39049
39074
|
return;
|
|
39050
39075
|
}
|
|
39051
39076
|
await pruneBookkeeping2(clone);
|
|
39052
|
-
for (const { path:
|
|
39053
|
-
if (await reclaimBranch(clone, branch2)) forgetWorktree(
|
|
39077
|
+
for (const { path: path91, branch: branch2 } of paths)
|
|
39078
|
+
if (await reclaimBranch(clone, branch2)) forgetWorktree(path91);
|
|
39054
39079
|
}
|
|
39055
39080
|
async function pruneBookkeeping2(clone) {
|
|
39056
39081
|
try {
|
|
@@ -39077,37 +39102,37 @@ async function reclaimBranch(clone, branch2) {
|
|
|
39077
39102
|
}
|
|
39078
39103
|
|
|
39079
39104
|
// src/commands/sessions/daemon/worktree/logVanishedTree.ts
|
|
39080
|
-
function logVanishedTree(sessions,
|
|
39105
|
+
function logVanishedTree(sessions, path91) {
|
|
39081
39106
|
const claimants = [...sessions.values()].filter(
|
|
39082
|
-
(s) => s.cwd ===
|
|
39107
|
+
(s) => s.cwd === path91 || s.worktree?.path === path91
|
|
39083
39108
|
);
|
|
39084
39109
|
if (claimants.length === 0) {
|
|
39085
|
-
daemonLog(`worktree ${
|
|
39110
|
+
daemonLog(`worktree ${path91} gone from disk and unclaimed; reclaiming it`);
|
|
39086
39111
|
return;
|
|
39087
39112
|
}
|
|
39088
39113
|
for (const s of claimants)
|
|
39089
39114
|
daemonLog(
|
|
39090
|
-
`session ${s.id} ("${s.name}") claims worktree ${
|
|
39115
|
+
`session ${s.id} ("${s.name}") claims worktree ${path91}, which is gone from disk; reclaiming it`
|
|
39091
39116
|
);
|
|
39092
39117
|
}
|
|
39093
39118
|
|
|
39094
39119
|
// src/commands/sessions/daemon/worktree/describeHeldWork.ts
|
|
39095
39120
|
var MAX_ITEMS = 20;
|
|
39096
|
-
async function describeHeldWork(
|
|
39097
|
-
if (reason4.startsWith("uncommitted")) return await changedFiles(
|
|
39098
|
-
if (reason4.startsWith("unpushed")) return await unpushedCommits(
|
|
39121
|
+
async function describeHeldWork(path91, reason4) {
|
|
39122
|
+
if (reason4.startsWith("uncommitted")) return await changedFiles(path91);
|
|
39123
|
+
if (reason4.startsWith("unpushed")) return await unpushedCommits(path91, reason4);
|
|
39099
39124
|
return { summary: reason4, items: [] };
|
|
39100
39125
|
}
|
|
39101
|
-
async function changedFiles(
|
|
39102
|
-
const status3 = await gitResult(
|
|
39126
|
+
async function changedFiles(path91) {
|
|
39127
|
+
const status3 = await gitResult(path91, ["status", "--porcelain"]);
|
|
39103
39128
|
const lines2 = status3.ok ? nonEmptyLines(status3.out) : [];
|
|
39104
39129
|
return {
|
|
39105
39130
|
summary: `${lines2.length} uncommitted ${lines2.length === 1 ? "file" : "files"}`,
|
|
39106
39131
|
items: capped(lines2)
|
|
39107
39132
|
};
|
|
39108
39133
|
}
|
|
39109
|
-
async function unpushedCommits(
|
|
39110
|
-
const log2 = await gitResult(
|
|
39134
|
+
async function unpushedCommits(path91, reason4) {
|
|
39135
|
+
const log2 = await gitResult(path91, ["log", "--oneline", "@{upstream}..HEAD"]);
|
|
39111
39136
|
if (!log2.ok) return { summary: reason4, items: [] };
|
|
39112
39137
|
const lines2 = nonEmptyLines(log2.out);
|
|
39113
39138
|
return {
|
|
@@ -39199,24 +39224,24 @@ function reconcileWorktreesOnRestore(sessions, spawnWith, notify2) {
|
|
|
39199
39224
|
async function recoverOrphanedWorktrees(sessions, spawnWith, notify2) {
|
|
39200
39225
|
const accounted = accountedTrees(sessions);
|
|
39201
39226
|
const vanished = /* @__PURE__ */ new Map();
|
|
39202
|
-
for (const { path:
|
|
39203
|
-
if (underTempRoot(
|
|
39204
|
-
forgetWorktree(
|
|
39227
|
+
for (const { path: path91, clone } of readWorktreeRegistry()) {
|
|
39228
|
+
if (underTempRoot(path91)) {
|
|
39229
|
+
forgetWorktree(path91);
|
|
39205
39230
|
daemonLog(
|
|
39206
|
-
`worktree ${
|
|
39231
|
+
`worktree ${path91} lies outside any project root; pruned from the registry rather than recovered`
|
|
39207
39232
|
);
|
|
39208
39233
|
continue;
|
|
39209
39234
|
}
|
|
39210
|
-
if (!
|
|
39211
|
-
logVanishedTree(sessions,
|
|
39235
|
+
if (!existsSync96(path91)) {
|
|
39236
|
+
logVanishedTree(sessions, path91);
|
|
39212
39237
|
vanished.set(clone, [
|
|
39213
39238
|
...vanished.get(clone) ?? [],
|
|
39214
|
-
{ path:
|
|
39239
|
+
{ path: path91, branch: basename27(path91) }
|
|
39215
39240
|
]);
|
|
39216
39241
|
continue;
|
|
39217
39242
|
}
|
|
39218
|
-
if (accounted.has(
|
|
39219
|
-
await recoverOrphan(sessions, spawnWith, { path:
|
|
39243
|
+
if (accounted.has(path91)) continue;
|
|
39244
|
+
await recoverOrphan(sessions, spawnWith, { path: path91, clone }, notify2);
|
|
39220
39245
|
}
|
|
39221
39246
|
for (const [clone, paths] of vanished)
|
|
39222
39247
|
await reclaimVanishedWorktrees(clone, paths);
|
|
@@ -39391,7 +39416,6 @@ function createWatcherSession(id, cwd) {
|
|
|
39391
39416
|
claudeSessionId,
|
|
39392
39417
|
initialPrompt: WATCH_PROMPT,
|
|
39393
39418
|
auto: true,
|
|
39394
|
-
starred: true,
|
|
39395
39419
|
watcher: true
|
|
39396
39420
|
};
|
|
39397
39421
|
}
|
|
@@ -39852,13 +39876,13 @@ async function defaultConnect() {
|
|
|
39852
39876
|
}
|
|
39853
39877
|
|
|
39854
39878
|
// src/commands/sessions/daemon/hasPersistedWindowsSessions.ts
|
|
39855
|
-
import { existsSync as
|
|
39879
|
+
import { existsSync as existsSync97, readFileSync as readFileSync64 } from "fs";
|
|
39856
39880
|
import { posix as posix3 } from "path";
|
|
39857
39881
|
function hasPersistedWindowsSessions() {
|
|
39858
39882
|
const sessionsFile = windowsSessionsFileFromWsl();
|
|
39859
39883
|
if (!sessionsFile) return false;
|
|
39860
39884
|
try {
|
|
39861
|
-
if (!
|
|
39885
|
+
if (!existsSync97(sessionsFile)) return false;
|
|
39862
39886
|
const data = JSON.parse(readFileSync64(sessionsFile, "utf8"));
|
|
39863
39887
|
return Array.isArray(data) && data.length > 0;
|
|
39864
39888
|
} catch (error) {
|
|
@@ -40593,7 +40617,7 @@ function setAutoAdvance(sessions, id, enabled) {
|
|
|
40593
40617
|
}
|
|
40594
40618
|
|
|
40595
40619
|
// src/commands/sessions/daemon/worktree/resumeInTree.ts
|
|
40596
|
-
import { existsSync as
|
|
40620
|
+
import { existsSync as existsSync100 } from "fs";
|
|
40597
40621
|
|
|
40598
40622
|
// src/commands/sessions/daemon/resumeSession.ts
|
|
40599
40623
|
function resumeSession(id, sessionId, cwd, name, holdPty, harness) {
|
|
@@ -40624,11 +40648,11 @@ function resumeSession(id, sessionId, cwd, name, holdPty, harness) {
|
|
|
40624
40648
|
}
|
|
40625
40649
|
|
|
40626
40650
|
// src/commands/sessions/daemon/worktree/resumeInReplacementTree.ts
|
|
40627
|
-
import { existsSync as
|
|
40651
|
+
import { existsSync as existsSync99 } from "fs";
|
|
40628
40652
|
|
|
40629
40653
|
// src/commands/sessions/daemon/worktree/carryTranscriptToTree.ts
|
|
40630
|
-
import { copyFileSync as
|
|
40631
|
-
import { join as
|
|
40654
|
+
import { copyFileSync as copyFileSync5, existsSync as existsSync98, mkdirSync as mkdirSync37 } from "fs";
|
|
40655
|
+
import { join as join105 } from "path";
|
|
40632
40656
|
function carryTranscriptToTree(claudeSessionId, fromCwd, toCwd) {
|
|
40633
40657
|
const dir = projectDirForCwd(toCwd);
|
|
40634
40658
|
if (dir === projectDirForCwd(fromCwd)) {
|
|
@@ -40637,8 +40661,8 @@ function carryTranscriptToTree(claudeSessionId, fromCwd, toCwd) {
|
|
|
40637
40661
|
);
|
|
40638
40662
|
return;
|
|
40639
40663
|
}
|
|
40640
|
-
const dest =
|
|
40641
|
-
if (
|
|
40664
|
+
const dest = join105(dir, `${claudeSessionId}.jsonl`);
|
|
40665
|
+
if (existsSync98(dest)) {
|
|
40642
40666
|
daemonLog(`transcript ${claudeSessionId} already present in ${dir}`);
|
|
40643
40667
|
return;
|
|
40644
40668
|
}
|
|
@@ -40651,7 +40675,7 @@ function carryTranscriptToTree(claudeSessionId, fromCwd, toCwd) {
|
|
|
40651
40675
|
}
|
|
40652
40676
|
try {
|
|
40653
40677
|
mkdirSync37(dir, { recursive: true });
|
|
40654
|
-
|
|
40678
|
+
copyFileSync5(source, dest);
|
|
40655
40679
|
daemonLog(
|
|
40656
40680
|
`transcript ${source} copied to ${dest} so ${toCwd} can resume it`
|
|
40657
40681
|
);
|
|
@@ -40689,7 +40713,7 @@ function resumeInReplacementTree(ctx, claudeSessionId, missingCwd, name, harness
|
|
|
40689
40713
|
}
|
|
40690
40714
|
function cloneForReapedTree(missingCwd) {
|
|
40691
40715
|
const clone = worktreeAttributionIncludingReaped(missingCwd)?.clone;
|
|
40692
|
-
if (!clone || !
|
|
40716
|
+
if (!clone || !existsSync99(clone))
|
|
40693
40717
|
throw new Error(
|
|
40694
40718
|
`working directory no longer exists and no clone is recorded to re-allocate from: ${missingCwd}`
|
|
40695
40719
|
);
|
|
@@ -40698,7 +40722,7 @@ function cloneForReapedTree(missingCwd) {
|
|
|
40698
40722
|
|
|
40699
40723
|
// src/commands/sessions/daemon/worktree/resumeInTree.ts
|
|
40700
40724
|
function resumeInTree(ctx, sessionId, cwd, name, harness) {
|
|
40701
|
-
if (!
|
|
40725
|
+
if (!existsSync100(cwd))
|
|
40702
40726
|
return resumeInReplacementTree(ctx, sessionId, cwd, name, harness);
|
|
40703
40727
|
const id = ctx.spawnWith(
|
|
40704
40728
|
(sid) => resumeSession(sid, sessionId, cwd, name, void 0, harness)
|
|
@@ -40965,15 +40989,15 @@ function handleSetStatus(client, m, d) {
|
|
|
40965
40989
|
}
|
|
40966
40990
|
|
|
40967
40991
|
// src/commands/sessions/shared/parseTranscript.ts
|
|
40968
|
-
import * as
|
|
40992
|
+
import * as fs54 from "fs";
|
|
40969
40993
|
|
|
40970
40994
|
// src/commands/sessions/shared/codex/findCodexRolloutPath.ts
|
|
40971
|
-
import * as
|
|
40995
|
+
import * as path89 from "path";
|
|
40972
40996
|
async function findCodexRolloutPath(sessionId) {
|
|
40973
40997
|
if (!sessionId) return null;
|
|
40974
40998
|
const paths = await discoverCodexRolloutPaths();
|
|
40975
40999
|
const suffix = `-${sessionId}.jsonl`;
|
|
40976
|
-
return paths.find((file) =>
|
|
41000
|
+
return paths.find((file) => path89.basename(file).endsWith(suffix)) ?? null;
|
|
40977
41001
|
}
|
|
40978
41002
|
|
|
40979
41003
|
// src/commands/sessions/shared/codex/codexToolTarget.ts
|
|
@@ -41048,7 +41072,7 @@ async function parseTranscript(sessionId) {
|
|
|
41048
41072
|
}
|
|
41049
41073
|
async function readMessages(filePath, parse4) {
|
|
41050
41074
|
try {
|
|
41051
|
-
const raw = await
|
|
41075
|
+
const raw = await fs54.promises.readFile(filePath, "utf8");
|
|
41052
41076
|
return parse4(raw.split("\n"));
|
|
41053
41077
|
} catch {
|
|
41054
41078
|
return [];
|
|
@@ -41576,17 +41600,17 @@ async function renameSession(title) {
|
|
|
41576
41600
|
}
|
|
41577
41601
|
|
|
41578
41602
|
// src/commands/sessions/summarise/index.ts
|
|
41579
|
-
import * as
|
|
41603
|
+
import * as fs56 from "fs";
|
|
41580
41604
|
import chalk230 from "chalk";
|
|
41581
41605
|
|
|
41582
41606
|
// src/commands/sessions/summarise/shared.ts
|
|
41583
|
-
import * as
|
|
41607
|
+
import * as fs55 from "fs";
|
|
41584
41608
|
function writeSummary(jsonlPath2, summary) {
|
|
41585
|
-
|
|
41609
|
+
fs55.writeFileSync(summaryPathFor(jsonlPath2), `${summary.trim()}
|
|
41586
41610
|
`, "utf8");
|
|
41587
41611
|
}
|
|
41588
41612
|
function hasSummary(jsonlPath2) {
|
|
41589
|
-
return
|
|
41613
|
+
return fs55.existsSync(summaryPathFor(jsonlPath2));
|
|
41590
41614
|
}
|
|
41591
41615
|
function summaryPathFor(jsonlPath2) {
|
|
41592
41616
|
return jsonlPath2.replace(/\.jsonl$/, ".summary");
|
|
@@ -41658,7 +41682,7 @@ function selectCandidates(files, options2) {
|
|
|
41658
41682
|
const candidates = options2.force ? files : files.filter((f) => !hasSummary(f));
|
|
41659
41683
|
candidates.sort((a, b) => {
|
|
41660
41684
|
try {
|
|
41661
|
-
return
|
|
41685
|
+
return fs56.statSync(b).mtimeMs - fs56.statSync(a).mtimeMs;
|
|
41662
41686
|
} catch {
|
|
41663
41687
|
return 0;
|
|
41664
41688
|
}
|
|
@@ -41789,9 +41813,9 @@ function buildLimitsSegment(rateLimits) {
|
|
|
41789
41813
|
|
|
41790
41814
|
// src/commands/readGitBranch.ts
|
|
41791
41815
|
import { readFileSync as readFileSync67, statSync as statSync16 } from "fs";
|
|
41792
|
-
import { isAbsolute as isAbsolute5, join as
|
|
41816
|
+
import { isAbsolute as isAbsolute5, join as join106, resolve as resolve23 } from "path";
|
|
41793
41817
|
function resolveGitDir(cwd) {
|
|
41794
|
-
const dotGit =
|
|
41818
|
+
const dotGit = join106(cwd, ".git");
|
|
41795
41819
|
let stat4;
|
|
41796
41820
|
try {
|
|
41797
41821
|
stat4 = statSync16(dotGit);
|
|
@@ -41821,7 +41845,7 @@ function readGitBranch(cwd) {
|
|
|
41821
41845
|
}
|
|
41822
41846
|
let head;
|
|
41823
41847
|
try {
|
|
41824
|
-
head = readFileSync67(
|
|
41848
|
+
head = readFileSync67(join106(gitDir, "HEAD"), "utf8");
|
|
41825
41849
|
} catch {
|
|
41826
41850
|
return null;
|
|
41827
41851
|
}
|
|
@@ -41890,7 +41914,7 @@ async function statusLine() {
|
|
|
41890
41914
|
|
|
41891
41915
|
// src/commands/update.ts
|
|
41892
41916
|
import { execSync as execSync63 } from "child_process";
|
|
41893
|
-
import * as
|
|
41917
|
+
import * as path90 from "path";
|
|
41894
41918
|
|
|
41895
41919
|
// src/commands/restartDaemonAfterUpdate.ts
|
|
41896
41920
|
async function restartDaemonAfterUpdate() {
|
|
@@ -41909,12 +41933,12 @@ async function restartDaemonAfterUpdate() {
|
|
|
41909
41933
|
// src/commands/update.ts
|
|
41910
41934
|
function isGlobalNpmInstall(dir) {
|
|
41911
41935
|
try {
|
|
41912
|
-
const resolved =
|
|
41913
|
-
if (resolved.split(
|
|
41936
|
+
const resolved = path90.resolve(dir);
|
|
41937
|
+
if (resolved.split(path90.sep).includes("node_modules")) {
|
|
41914
41938
|
return true;
|
|
41915
41939
|
}
|
|
41916
41940
|
const globalPrefix = execSync63("npm prefix -g", { stdio: "pipe" }).toString().trim();
|
|
41917
|
-
return resolved.toLowerCase().startsWith(
|
|
41941
|
+
return resolved.toLowerCase().startsWith(path90.resolve(globalPrefix).toLowerCase());
|
|
41918
41942
|
} catch {
|
|
41919
41943
|
return false;
|
|
41920
41944
|
}
|