@staff0rd/assist 0.599.0 → 0.601.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 +4 -0
- package/claude/commands/add-rule.md +45 -0
- package/claude/commands/adopt-rules.md +79 -0
- package/dist/commands/sessions/web/bundle.js +397 -393
- package/dist/index.js +705 -508
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Command } from "commander";
|
|
|
6
6
|
// package.json
|
|
7
7
|
var package_default = {
|
|
8
8
|
name: "@staff0rd/assist",
|
|
9
|
-
version: "0.
|
|
9
|
+
version: "0.601.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -187,8 +187,8 @@ function getRemoteOriginUrl(cwd) {
|
|
|
187
187
|
}
|
|
188
188
|
|
|
189
189
|
// src/commands/backlog/getCurrentOrigin.ts
|
|
190
|
-
function stripLeadingSlashes(
|
|
191
|
-
return
|
|
190
|
+
function stripLeadingSlashes(path90) {
|
|
191
|
+
return path90.replace(/^\/+/, "");
|
|
192
192
|
}
|
|
193
193
|
function normalizeOrigin(raw) {
|
|
194
194
|
const trimmed = raw.trim().replace(/\.git$/i, "").replace(/\/+$/, "");
|
|
@@ -238,9 +238,9 @@ function findGitLink(dir) {
|
|
|
238
238
|
}
|
|
239
239
|
return null;
|
|
240
240
|
}
|
|
241
|
-
function isFile(
|
|
241
|
+
function isFile(path90) {
|
|
242
242
|
try {
|
|
243
|
-
return statSync(
|
|
243
|
+
return statSync(path90).isFile();
|
|
244
244
|
} catch {
|
|
245
245
|
return false;
|
|
246
246
|
}
|
|
@@ -259,9 +259,9 @@ function linkedGitDirParent(gitDir) {
|
|
|
259
259
|
const match = /^(.*)[/\\]worktrees[/\\][^/\\]+[/\\]?$/.exec(gitDir);
|
|
260
260
|
return match ? match[1] : null;
|
|
261
261
|
}
|
|
262
|
-
function readTrimmed(
|
|
262
|
+
function readTrimmed(path90) {
|
|
263
263
|
try {
|
|
264
|
-
const content = readFileSync(
|
|
264
|
+
const content = readFileSync(path90, "utf8").trim();
|
|
265
265
|
return content === "" ? null : content;
|
|
266
266
|
} catch {
|
|
267
267
|
return null;
|
|
@@ -274,10 +274,10 @@ function absolute(target, from) {
|
|
|
274
274
|
// src/shared/loadRawYaml.ts
|
|
275
275
|
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
276
276
|
import { parse as parseYaml } from "yaml";
|
|
277
|
-
function loadRawYaml(
|
|
278
|
-
if (!existsSync2(
|
|
277
|
+
function loadRawYaml(path90) {
|
|
278
|
+
if (!existsSync2(path90)) return {};
|
|
279
279
|
try {
|
|
280
|
-
const content = readFileSync2(
|
|
280
|
+
const content = readFileSync2(path90, "utf8");
|
|
281
281
|
return parseYaml(content) || {};
|
|
282
282
|
} catch {
|
|
283
283
|
return {};
|
|
@@ -349,8 +349,8 @@ function mergeRawConfigs(globalRaw, projectRaw) {
|
|
|
349
349
|
// src/commands/backlog/originDisplayName.ts
|
|
350
350
|
function originDisplayName(origin) {
|
|
351
351
|
if (origin.startsWith("local:")) {
|
|
352
|
-
const
|
|
353
|
-
const segments =
|
|
352
|
+
const path90 = origin.slice("local:".length).replace(/\/+$/, "");
|
|
353
|
+
const segments = path90.split("/").filter(Boolean);
|
|
354
354
|
return segments[segments.length - 1] ?? origin;
|
|
355
355
|
}
|
|
356
356
|
const firstSlash = origin.indexOf("/");
|
|
@@ -1785,8 +1785,8 @@ function findUnmergedPaths() {
|
|
|
1785
1785
|
}
|
|
1786
1786
|
const found = /* @__PURE__ */ new Set();
|
|
1787
1787
|
for (const line of output.split("\n")) {
|
|
1788
|
-
const
|
|
1789
|
-
if (
|
|
1788
|
+
const path90 = line.split(" ")[1];
|
|
1789
|
+
if (path90) found.add(path90.trim());
|
|
1790
1790
|
}
|
|
1791
1791
|
return [...found];
|
|
1792
1792
|
}
|
|
@@ -1896,8 +1896,8 @@ function getPreferredRemoteRepo(cwd) {
|
|
|
1896
1896
|
function gitRefUrl(kind, ref, cwd) {
|
|
1897
1897
|
const repo = getPreferredRemoteRepo(cwd);
|
|
1898
1898
|
if (!repo) return void 0;
|
|
1899
|
-
const
|
|
1900
|
-
return `https://github.com/${repo.org}/${repo.repo}/${
|
|
1899
|
+
const path90 = kind === "branch" ? "tree" : "commit";
|
|
1900
|
+
return `https://github.com/${repo.org}/${repo.repo}/${path90}/${ref}`;
|
|
1901
1901
|
}
|
|
1902
1902
|
|
|
1903
1903
|
// src/commands/commit/collectCommitRefs.ts
|
|
@@ -3995,25 +3995,25 @@ function toFindings(file, lines2, raw, exempt) {
|
|
|
3995
3995
|
|
|
3996
3996
|
// src/commands/verify/blockCodeComments/collectFileComments.ts
|
|
3997
3997
|
function collectFileComments(file, lines2, project) {
|
|
3998
|
-
const
|
|
3998
|
+
const read3 = () => fs14.readFileSync(file, "utf8");
|
|
3999
3999
|
if (isYamlFile(file))
|
|
4000
|
-
return toFindings(file, lines2, collectYamlComments(
|
|
4000
|
+
return toFindings(file, lines2, collectYamlComments(read3()), false);
|
|
4001
4001
|
if (isDockerfile(file) || isEnvFile(file) || isShellFile(file))
|
|
4002
4002
|
return toFindings(
|
|
4003
4003
|
file,
|
|
4004
4004
|
lines2,
|
|
4005
|
-
collectHashComments(
|
|
4005
|
+
collectHashComments(read3(), { skipHeader: isShellFile(file) }),
|
|
4006
4006
|
true
|
|
4007
4007
|
);
|
|
4008
4008
|
if (isBicepFile(file))
|
|
4009
|
-
return toFindings(file, lines2, collectBicepComments(
|
|
4009
|
+
return toFindings(file, lines2, collectBicepComments(read3()), true);
|
|
4010
4010
|
if (isCsharpFile(file)) {
|
|
4011
|
-
const content =
|
|
4011
|
+
const content = read3();
|
|
4012
4012
|
if (isGeneratedCsharpFile(file, content)) return [];
|
|
4013
4013
|
return toFindings(file, lines2, collectCsharpComments(content), true);
|
|
4014
4014
|
}
|
|
4015
4015
|
if (isRazorFile(file))
|
|
4016
|
-
return toFindings(file, lines2, extractRazorComments(
|
|
4016
|
+
return toFindings(file, lines2, extractRazorComments(read3()), true);
|
|
4017
4017
|
return collectSourceFindings(file, lines2, project);
|
|
4018
4018
|
}
|
|
4019
4019
|
|
|
@@ -4273,11 +4273,11 @@ function enumValues(node) {
|
|
|
4273
4273
|
function opaqueConfigNode(inner, base) {
|
|
4274
4274
|
return { ...base, kind: "other", type: leafTypeOf(inner) };
|
|
4275
4275
|
}
|
|
4276
|
-
function build(node,
|
|
4276
|
+
function build(node, path90) {
|
|
4277
4277
|
const { inner, defaultValue, optional } = unwrapSchemaNode(node);
|
|
4278
4278
|
const secret = isSecretSchemaNode(node) || isSecretSchemaNode(inner);
|
|
4279
4279
|
const base = {
|
|
4280
|
-
path:
|
|
4280
|
+
path: path90,
|
|
4281
4281
|
...optional ? { optional: true } : {},
|
|
4282
4282
|
...defaultValue === void 0 ? {} : { defaultValue },
|
|
4283
4283
|
...secret ? { secret: true } : {}
|
|
@@ -4296,9 +4296,9 @@ function segmentText(segment) {
|
|
|
4296
4296
|
if (segment.kind === "index") return `[${segment.index}]`;
|
|
4297
4297
|
return "[]";
|
|
4298
4298
|
}
|
|
4299
|
-
function formatConfigPath(
|
|
4299
|
+
function formatConfigPath(path90) {
|
|
4300
4300
|
let text18 = "";
|
|
4301
|
-
for (const segment of
|
|
4301
|
+
for (const segment of path90) {
|
|
4302
4302
|
const dotted = segment.kind === "key" || segment.kind === "entry";
|
|
4303
4303
|
const rendered = segmentText(segment);
|
|
4304
4304
|
text18 += dotted && text18 ? `.${rendered}` : rendered;
|
|
@@ -4946,9 +4946,9 @@ import { existsSync as existsSync13, readFileSync as readFileSync10 } from "fs";
|
|
|
4946
4946
|
|
|
4947
4947
|
// src/commands/verify/forbiddenStrings/findForbiddenStrings.ts
|
|
4948
4948
|
import { minimatch as minimatch2 } from "minimatch";
|
|
4949
|
-
function resolveStringsAtPath(data,
|
|
4949
|
+
function resolveStringsAtPath(data, path90) {
|
|
4950
4950
|
let current = data;
|
|
4951
|
-
for (const segment of
|
|
4951
|
+
for (const segment of path90.split(".")) {
|
|
4952
4952
|
if (current === null || typeof current !== "object") return [];
|
|
4953
4953
|
current = current[segment];
|
|
4954
4954
|
}
|
|
@@ -4961,10 +4961,10 @@ function resolveStringsAtPath(data, path84) {
|
|
|
4961
4961
|
}
|
|
4962
4962
|
function findRuleViolations(data, rule) {
|
|
4963
4963
|
const violations = [];
|
|
4964
|
-
for (const
|
|
4965
|
-
for (const value of resolveStringsAtPath(data,
|
|
4964
|
+
for (const path90 of rule.paths) {
|
|
4965
|
+
for (const value of resolveStringsAtPath(data, path90)) {
|
|
4966
4966
|
if (minimatch2(value, rule.disallowed))
|
|
4967
|
-
violations.push({ file: rule.file, path:
|
|
4967
|
+
violations.push({ file: rule.file, path: path90, value });
|
|
4968
4968
|
}
|
|
4969
4969
|
}
|
|
4970
4970
|
return violations;
|
|
@@ -5003,8 +5003,8 @@ function forbiddenStrings() {
|
|
|
5003
5003
|
process.exit(0);
|
|
5004
5004
|
}
|
|
5005
5005
|
console.log("Forbidden strings found:\n");
|
|
5006
|
-
for (const { file, path:
|
|
5007
|
-
console.log(` ${file} ${
|
|
5006
|
+
for (const { file, path: path90, value } of violations) {
|
|
5007
|
+
console.log(` ${file} ${path90}: ${value}`);
|
|
5008
5008
|
}
|
|
5009
5009
|
console.log(`
|
|
5010
5010
|
Total: ${violations.length} forbidden string(s).`);
|
|
@@ -5319,15 +5319,15 @@ function readBaselineMigrations(repoRelativeDir, ref) {
|
|
|
5319
5319
|
} catch {
|
|
5320
5320
|
return baseline;
|
|
5321
5321
|
}
|
|
5322
|
-
const paths = listing.split("\n").map((line) => line.trim()).filter(Boolean).filter((
|
|
5323
|
-
for (const
|
|
5322
|
+
const paths = listing.split("\n").map((line) => line.trim()).filter(Boolean).filter((path90) => MIGRATION_FILE3.test(basename2(path90)));
|
|
5323
|
+
for (const path90 of paths) {
|
|
5324
5324
|
try {
|
|
5325
|
-
const content = execSync14(`git show "${ref}:${
|
|
5325
|
+
const content = execSync14(`git show "${ref}:${path90}"`, {
|
|
5326
5326
|
encoding: "utf8",
|
|
5327
5327
|
maxBuffer: 16 * 1024 * 1024,
|
|
5328
5328
|
stdio: ["pipe", "pipe", "pipe"]
|
|
5329
5329
|
});
|
|
5330
|
-
baseline.set(basename2(
|
|
5330
|
+
baseline.set(basename2(path90), content);
|
|
5331
5331
|
} catch {
|
|
5332
5332
|
}
|
|
5333
5333
|
}
|
|
@@ -6761,10 +6761,10 @@ var hooksSettings = {
|
|
|
6761
6761
|
}
|
|
6762
6762
|
};
|
|
6763
6763
|
function ensureHooksSettings() {
|
|
6764
|
-
const
|
|
6765
|
-
mkdirSync5(dirname13(
|
|
6766
|
-
writeFileSync15(
|
|
6767
|
-
return
|
|
6764
|
+
const path90 = daemonPaths.hooksSettings;
|
|
6765
|
+
mkdirSync5(dirname13(path90), { recursive: true });
|
|
6766
|
+
writeFileSync15(path90, JSON.stringify(hooksSettings, null, 2));
|
|
6767
|
+
return path90;
|
|
6768
6768
|
}
|
|
6769
6769
|
|
|
6770
6770
|
// src/shared/spawnInherit.ts
|
|
@@ -7062,9 +7062,9 @@ var LOCAL_FILES = ["backlog.jsonl", "backlog.db"];
|
|
|
7062
7062
|
function backupLocalBacklogFiles(dir) {
|
|
7063
7063
|
const moved = [];
|
|
7064
7064
|
for (const name of LOCAL_FILES) {
|
|
7065
|
-
const
|
|
7066
|
-
if (existsSync19(
|
|
7067
|
-
renameSync(
|
|
7065
|
+
const path90 = join15(dir, ".assist", name);
|
|
7066
|
+
if (existsSync19(path90)) {
|
|
7067
|
+
renameSync(path90, `${path90}.bak`);
|
|
7068
7068
|
moved.push(`${name} \u2192 ${name}.bak`);
|
|
7069
7069
|
}
|
|
7070
7070
|
}
|
|
@@ -7544,8 +7544,8 @@ var backlogItemSchema = z4.strictObject({
|
|
|
7544
7544
|
var backlogFileSchema = z4.array(backlogItemSchema);
|
|
7545
7545
|
|
|
7546
7546
|
// src/commands/backlog/parseBacklogJsonl.ts
|
|
7547
|
-
function parseBacklogJsonl(
|
|
7548
|
-
const content = readFileSync15(
|
|
7547
|
+
function parseBacklogJsonl(path90) {
|
|
7548
|
+
const content = readFileSync15(path90, "utf8").trim();
|
|
7549
7549
|
if (content.length === 0) return [];
|
|
7550
7550
|
return content.split("\n").map((line) => line.trim()).filter(Boolean).map((line) => backlogItemSchema.parse(JSON.parse(line)));
|
|
7551
7551
|
}
|
|
@@ -8356,24 +8356,24 @@ function getOwnerPath(itemId2) {
|
|
|
8356
8356
|
function recordSignalOwner(itemId2) {
|
|
8357
8357
|
const sessionId = process.env.ASSIST_SESSION_ID;
|
|
8358
8358
|
if (!sessionId) return;
|
|
8359
|
-
const
|
|
8360
|
-
mkdirSync7(dirname15(
|
|
8361
|
-
writeFileSync17(
|
|
8359
|
+
const path90 = getOwnerPath(itemId2);
|
|
8360
|
+
mkdirSync7(dirname15(path90), { recursive: true });
|
|
8361
|
+
writeFileSync17(path90, JSON.stringify({ sessionId }));
|
|
8362
8362
|
}
|
|
8363
8363
|
function readSignalOwner(itemId2) {
|
|
8364
|
-
const
|
|
8365
|
-
if (!existsSync23(
|
|
8364
|
+
const path90 = getOwnerPath(itemId2);
|
|
8365
|
+
if (!existsSync23(path90)) return void 0;
|
|
8366
8366
|
try {
|
|
8367
|
-
const parsed = JSON.parse(readFileSync16(
|
|
8367
|
+
const parsed = JSON.parse(readFileSync16(path90, "utf8"));
|
|
8368
8368
|
return parsed.sessionId;
|
|
8369
8369
|
} catch {
|
|
8370
8370
|
return void 0;
|
|
8371
8371
|
}
|
|
8372
8372
|
}
|
|
8373
8373
|
function clearSignalOwner(itemId2) {
|
|
8374
|
-
const
|
|
8374
|
+
const path90 = getOwnerPath(itemId2);
|
|
8375
8375
|
try {
|
|
8376
|
-
rmSync(
|
|
8376
|
+
rmSync(path90);
|
|
8377
8377
|
} catch {
|
|
8378
8378
|
}
|
|
8379
8379
|
}
|
|
@@ -8410,19 +8410,19 @@ function resolveSignalTarget(event, data) {
|
|
|
8410
8410
|
function writeSignal(event, data) {
|
|
8411
8411
|
const target = resolveSignalTarget(event, data);
|
|
8412
8412
|
if (!target) return;
|
|
8413
|
-
const
|
|
8414
|
-
if (!
|
|
8413
|
+
const path90 = getSignalPath(target);
|
|
8414
|
+
if (!path90) return;
|
|
8415
8415
|
const signal = { event, sessionId: target, ...data };
|
|
8416
|
-
mkdirSync8(dirname16(
|
|
8417
|
-
writeFileSync18(
|
|
8416
|
+
mkdirSync8(dirname16(path90), { recursive: true });
|
|
8417
|
+
writeFileSync18(path90, JSON.stringify(signal));
|
|
8418
8418
|
}
|
|
8419
8419
|
|
|
8420
8420
|
// src/commands/backlog/readSignal.ts
|
|
8421
8421
|
function readSignal() {
|
|
8422
|
-
const
|
|
8423
|
-
if (!
|
|
8422
|
+
const path90 = getSignalPath();
|
|
8423
|
+
if (!path90 || !existsSync24(path90)) return void 0;
|
|
8424
8424
|
try {
|
|
8425
|
-
return JSON.parse(readFileSync17(
|
|
8425
|
+
return JSON.parse(readFileSync17(path90, "utf8"));
|
|
8426
8426
|
} catch {
|
|
8427
8427
|
return void 0;
|
|
8428
8428
|
}
|
|
@@ -8619,13 +8619,13 @@ function activityPath(sessionId) {
|
|
|
8619
8619
|
function emitActivity(activity2) {
|
|
8620
8620
|
const sessionId = process.env.ASSIST_ACTIVITY_ID;
|
|
8621
8621
|
if (!sessionId) return;
|
|
8622
|
-
const
|
|
8623
|
-
mkdirSync9(dirname17(
|
|
8624
|
-
writeFileSync19(
|
|
8622
|
+
const path90 = activityPath(sessionId);
|
|
8623
|
+
mkdirSync9(dirname17(path90), { recursive: true });
|
|
8624
|
+
writeFileSync19(path90, JSON.stringify({ ...activity2, startedAt: Date.now() }));
|
|
8625
8625
|
}
|
|
8626
|
-
function readActivity(
|
|
8626
|
+
function readActivity(path90) {
|
|
8627
8627
|
try {
|
|
8628
|
-
return JSON.parse(readFileSync18(
|
|
8628
|
+
return JSON.parse(readFileSync18(path90, "utf8"));
|
|
8629
8629
|
} catch {
|
|
8630
8630
|
return void 0;
|
|
8631
8631
|
}
|
|
@@ -8635,9 +8635,9 @@ function reconcileActivity(sessionId, activity2) {
|
|
|
8635
8635
|
removeActivity(sessionId);
|
|
8636
8636
|
return;
|
|
8637
8637
|
}
|
|
8638
|
-
const
|
|
8639
|
-
mkdirSync9(dirname17(
|
|
8640
|
-
writeFileSync19(
|
|
8638
|
+
const path90 = activityPath(sessionId);
|
|
8639
|
+
mkdirSync9(dirname17(path90), { recursive: true });
|
|
8640
|
+
writeFileSync19(path90, JSON.stringify(activity2));
|
|
8641
8641
|
}
|
|
8642
8642
|
function removeActivity(sessionId) {
|
|
8643
8643
|
try {
|
|
@@ -10090,10 +10090,10 @@ function getStorePath(filename) {
|
|
|
10090
10090
|
return join26(getStoreDir(), filename);
|
|
10091
10091
|
}
|
|
10092
10092
|
function loadJson(filename) {
|
|
10093
|
-
const
|
|
10094
|
-
if (existsSync29(
|
|
10093
|
+
const path90 = getStorePath(filename);
|
|
10094
|
+
if (existsSync29(path90)) {
|
|
10095
10095
|
try {
|
|
10096
|
-
return JSON.parse(readFileSync19(
|
|
10096
|
+
return JSON.parse(readFileSync19(path90, "utf8"));
|
|
10097
10097
|
} catch {
|
|
10098
10098
|
return {};
|
|
10099
10099
|
}
|
|
@@ -10112,22 +10112,22 @@ function saveJson(filename, data) {
|
|
|
10112
10112
|
var REGISTRY_FILE = "worktrees.json";
|
|
10113
10113
|
function readWorktreeRegistry() {
|
|
10114
10114
|
const data = loadJson(REGISTRY_FILE);
|
|
10115
|
-
return Object.entries(data).filter(([, record]) => !record.reaped).map(([
|
|
10115
|
+
return Object.entries(data).filter(([, record]) => !record.reaped).map(([path90, record]) => ({ path: path90, ...record }));
|
|
10116
10116
|
}
|
|
10117
|
-
function worktreeAttributionIncludingReaped(
|
|
10118
|
-
const record = loadJson(REGISTRY_FILE)[
|
|
10117
|
+
function worktreeAttributionIncludingReaped(path90) {
|
|
10118
|
+
const record = loadJson(REGISTRY_FILE)[path90];
|
|
10119
10119
|
return record ? { clone: record.clone, origin: record.origin } : void 0;
|
|
10120
10120
|
}
|
|
10121
|
-
function recordWorktree(
|
|
10121
|
+
function recordWorktree(path90, clone, origin) {
|
|
10122
10122
|
const data = loadJson(REGISTRY_FILE);
|
|
10123
|
-
data[
|
|
10123
|
+
data[path90] = { clone, origin };
|
|
10124
10124
|
saveJson(REGISTRY_FILE, data);
|
|
10125
10125
|
}
|
|
10126
|
-
function forgetWorktree(
|
|
10126
|
+
function forgetWorktree(path90) {
|
|
10127
10127
|
const data = loadJson(REGISTRY_FILE);
|
|
10128
|
-
const record = data[
|
|
10128
|
+
const record = data[path90];
|
|
10129
10129
|
if (!record || record.reaped) return;
|
|
10130
|
-
data[
|
|
10130
|
+
data[path90] = { ...record, reaped: true };
|
|
10131
10131
|
saveJson(REGISTRY_FILE, data);
|
|
10132
10132
|
}
|
|
10133
10133
|
|
|
@@ -10878,8 +10878,8 @@ async function loadCommittedPaths(cwd, sessionId) {
|
|
|
10878
10878
|
for (const commit2 of commits2) {
|
|
10879
10879
|
const resolved = await resolveCommit(cwd, commit2.sha);
|
|
10880
10880
|
if (!resolved) continue;
|
|
10881
|
-
for (const
|
|
10882
|
-
if (!bases.has(
|
|
10881
|
+
for (const path90 of resolved.paths) {
|
|
10882
|
+
if (!bases.has(path90)) bases.set(path90, resolved.base);
|
|
10883
10883
|
}
|
|
10884
10884
|
}
|
|
10885
10885
|
return { commits: commits2, bases };
|
|
@@ -10897,16 +10897,16 @@ async function itemChangeSet(cwd, sessionId) {
|
|
|
10897
10897
|
}
|
|
10898
10898
|
function groupByBase(bases) {
|
|
10899
10899
|
const groups = /* @__PURE__ */ new Map();
|
|
10900
|
-
for (const [
|
|
10900
|
+
for (const [path90, base] of bases) {
|
|
10901
10901
|
const paths = groups.get(base);
|
|
10902
|
-
if (paths) paths.push(
|
|
10903
|
-
else groups.set(base, [
|
|
10902
|
+
if (paths) paths.push(path90);
|
|
10903
|
+
else groups.set(base, [path90]);
|
|
10904
10904
|
}
|
|
10905
10905
|
return [...groups].map(([base, paths]) => ({ base, paths: paths.sort() }));
|
|
10906
10906
|
}
|
|
10907
10907
|
async function dirtyPaths(cwd, bases) {
|
|
10908
10908
|
const output = await execGit(cwd, ["diff", "--name-only", "HEAD"]);
|
|
10909
|
-
return output.split("\n").filter((
|
|
10909
|
+
return output.split("\n").filter((path90) => path90 && !bases.has(path90)).sort();
|
|
10910
10910
|
}
|
|
10911
10911
|
|
|
10912
10912
|
// src/commands/sessions/web/scopedDiff.ts
|
|
@@ -10915,8 +10915,8 @@ async function scopedDiff(cwd, session, scope) {
|
|
|
10915
10915
|
if (scope.kind === "commit") return commitDiff(cwd, scope.sha);
|
|
10916
10916
|
return await trackedScopeDiff(cwd, session, scope) + await untrackedDiff(cwd);
|
|
10917
10917
|
}
|
|
10918
|
-
async function untrackedFileDiff(cwd,
|
|
10919
|
-
return execGit(cwd, ["diff", "--no-index", "--", "/dev/null",
|
|
10918
|
+
async function untrackedFileDiff(cwd, path90) {
|
|
10919
|
+
return execGit(cwd, ["diff", "--no-index", "--", "/dev/null", path90], {
|
|
10920
10920
|
maxBuffer: MAX_DIFF_BYTES,
|
|
10921
10921
|
allowFailure: true
|
|
10922
10922
|
});
|
|
@@ -10929,7 +10929,7 @@ async function untrackedDiff(cwd) {
|
|
|
10929
10929
|
]);
|
|
10930
10930
|
const paths = list5.split("\n").filter(Boolean);
|
|
10931
10931
|
const diffs = await Promise.all(
|
|
10932
|
-
paths.map((
|
|
10932
|
+
paths.map((path90) => untrackedFileDiff(cwd, path90))
|
|
10933
10933
|
);
|
|
10934
10934
|
return diffs.join("");
|
|
10935
10935
|
}
|
|
@@ -11022,9 +11022,9 @@ import { isAbsolute as isAbsolute2, relative as relative2, resolve as resolve10
|
|
|
11022
11022
|
function repoRoot(cwd) {
|
|
11023
11023
|
return resolve10(toGitCwd(cwd));
|
|
11024
11024
|
}
|
|
11025
|
-
function resolveWithinCwd(cwd,
|
|
11025
|
+
function resolveWithinCwd(cwd, path90) {
|
|
11026
11026
|
const root = repoRoot(cwd);
|
|
11027
|
-
const target = resolve10(root,
|
|
11027
|
+
const target = resolve10(root, path90);
|
|
11028
11028
|
const rel = relative2(root, target);
|
|
11029
11029
|
if (rel === "" || rel.startsWith("..") || isAbsolute2(rel)) return null;
|
|
11030
11030
|
return target;
|
|
@@ -11034,14 +11034,14 @@ function resolveWithinCwd(cwd, path84) {
|
|
|
11034
11034
|
function getFileTarget(req, res) {
|
|
11035
11035
|
const cwd = getCwdParam(req, res);
|
|
11036
11036
|
if (!cwd) return null;
|
|
11037
|
-
const
|
|
11037
|
+
const path90 = new URL(req.url ?? "/", "http://localhost").searchParams.get(
|
|
11038
11038
|
"path"
|
|
11039
11039
|
);
|
|
11040
|
-
if (!
|
|
11040
|
+
if (!path90) {
|
|
11041
11041
|
respondJson(res, 400, { error: "Missing path" });
|
|
11042
11042
|
return null;
|
|
11043
11043
|
}
|
|
11044
|
-
const target = resolveWithinCwd(cwd,
|
|
11044
|
+
const target = resolveWithinCwd(cwd, path90);
|
|
11045
11045
|
if (!target) {
|
|
11046
11046
|
respondJson(res, 400, { error: "Path outside cwd" });
|
|
11047
11047
|
return null;
|
|
@@ -11116,11 +11116,11 @@ function globalConfigTargetFor(cwd) {
|
|
|
11116
11116
|
|
|
11117
11117
|
// src/commands/config/globalConfigFileLabel.ts
|
|
11118
11118
|
var WINDOWS_MOUNT_PREFIX = "/mnt/";
|
|
11119
|
-
function globalConfigFileLabel(
|
|
11120
|
-
if (
|
|
11121
|
-
if (
|
|
11122
|
-
return `${
|
|
11123
|
-
return
|
|
11119
|
+
function globalConfigFileLabel(path90) {
|
|
11120
|
+
if (path90 === getGlobalConfigPath()) return "~/.assist.yml";
|
|
11121
|
+
if (path90.startsWith(WINDOWS_MOUNT_PREFIX))
|
|
11122
|
+
return `${path90} on the Windows host`;
|
|
11123
|
+
return path90;
|
|
11124
11124
|
}
|
|
11125
11125
|
|
|
11126
11126
|
// src/commands/config/readRawConfigLayers.ts
|
|
@@ -11177,35 +11177,35 @@ function isPlainRecord(value) {
|
|
|
11177
11177
|
}
|
|
11178
11178
|
|
|
11179
11179
|
// src/shared/mapConfigSecrets.ts
|
|
11180
|
-
function mapChildren(value,
|
|
11180
|
+
function mapChildren(value, path90, childNode, map) {
|
|
11181
11181
|
if (!isPlainRecord(value)) return value;
|
|
11182
11182
|
return Object.fromEntries(
|
|
11183
11183
|
Object.entries(value).map(([name, child]) => [
|
|
11184
11184
|
name,
|
|
11185
|
-
walk(child, [...
|
|
11185
|
+
walk(child, [...path90, name], childNode(name), map)
|
|
11186
11186
|
])
|
|
11187
11187
|
);
|
|
11188
11188
|
}
|
|
11189
|
-
function mapItems(value,
|
|
11189
|
+
function mapItems(value, path90, item, map) {
|
|
11190
11190
|
if (!Array.isArray(value)) return value;
|
|
11191
|
-
return value.map((entry, index3) => walk(entry, [...
|
|
11191
|
+
return value.map((entry, index3) => walk(entry, [...path90, index3], item, map));
|
|
11192
11192
|
}
|
|
11193
|
-
function walk(value,
|
|
11193
|
+
function walk(value, path90, node, map) {
|
|
11194
11194
|
if (!node || value === void 0 || value === null) return value;
|
|
11195
|
-
if (node.secret) return map(value,
|
|
11195
|
+
if (node.secret) return map(value, path90);
|
|
11196
11196
|
switch (node.kind) {
|
|
11197
11197
|
case "object":
|
|
11198
11198
|
case "unionOfObjects":
|
|
11199
11199
|
return mapChildren(
|
|
11200
11200
|
value,
|
|
11201
|
-
|
|
11201
|
+
path90,
|
|
11202
11202
|
(name) => configNodeField(node, name),
|
|
11203
11203
|
map
|
|
11204
11204
|
);
|
|
11205
11205
|
case "objectList":
|
|
11206
|
-
return mapItems(value,
|
|
11206
|
+
return mapItems(value, path90, node.item, map);
|
|
11207
11207
|
case "record":
|
|
11208
|
-
return mapChildren(value,
|
|
11208
|
+
return mapChildren(value, path90, () => node.value, map);
|
|
11209
11209
|
default:
|
|
11210
11210
|
return value;
|
|
11211
11211
|
}
|
|
@@ -11230,9 +11230,9 @@ function isTraversable(value) {
|
|
|
11230
11230
|
function stepInto(current, key) {
|
|
11231
11231
|
return isTraversable(current) ? current[key] : void 0;
|
|
11232
11232
|
}
|
|
11233
|
-
function getNestedValue(obj,
|
|
11233
|
+
function getNestedValue(obj, path90) {
|
|
11234
11234
|
let current = obj;
|
|
11235
|
-
for (const key of
|
|
11235
|
+
for (const key of path90.split(".")) current = stepInto(current, key);
|
|
11236
11236
|
return current;
|
|
11237
11237
|
}
|
|
11238
11238
|
|
|
@@ -11282,9 +11282,9 @@ function step(node, segment) {
|
|
|
11282
11282
|
return void 0;
|
|
11283
11283
|
}
|
|
11284
11284
|
}
|
|
11285
|
-
function findConfigNode(root,
|
|
11285
|
+
function findConfigNode(root, path90) {
|
|
11286
11286
|
let current = root;
|
|
11287
|
-
for (const segment of
|
|
11287
|
+
for (const segment of path90) {
|
|
11288
11288
|
if (!current) return void 0;
|
|
11289
11289
|
current = step(current, segment);
|
|
11290
11290
|
}
|
|
@@ -11301,34 +11301,34 @@ function nameSegment(name) {
|
|
|
11301
11301
|
return name === RECORD_ENTRY_TOKEN ? { kind: "entry" } : { kind: "key", name };
|
|
11302
11302
|
}
|
|
11303
11303
|
function parseConfigPath(text18) {
|
|
11304
|
-
const
|
|
11304
|
+
const path90 = [];
|
|
11305
11305
|
let at2 = 0;
|
|
11306
11306
|
while (at2 < text18.length) {
|
|
11307
11307
|
if (text18[at2] === "[") {
|
|
11308
11308
|
const close = text18.indexOf("]", at2);
|
|
11309
11309
|
const segment = close === -1 ? void 0 : bracketSegment(text18.slice(at2 + 1, close));
|
|
11310
11310
|
if (!segment) return void 0;
|
|
11311
|
-
|
|
11311
|
+
path90.push(segment);
|
|
11312
11312
|
at2 = close + 1;
|
|
11313
11313
|
continue;
|
|
11314
11314
|
}
|
|
11315
11315
|
if (text18[at2] === ".") {
|
|
11316
|
-
if (
|
|
11316
|
+
if (path90.length === 0) return void 0;
|
|
11317
11317
|
at2 += 1;
|
|
11318
11318
|
}
|
|
11319
11319
|
const start3 = at2;
|
|
11320
11320
|
while (at2 < text18.length && text18[at2] !== "." && text18[at2] !== "[") at2 += 1;
|
|
11321
11321
|
const name = text18.slice(start3, at2);
|
|
11322
11322
|
if (!name) return void 0;
|
|
11323
|
-
|
|
11323
|
+
path90.push(nameSegment(name));
|
|
11324
11324
|
}
|
|
11325
|
-
return
|
|
11325
|
+
return path90;
|
|
11326
11326
|
}
|
|
11327
11327
|
|
|
11328
11328
|
// src/commands/config/configEntryNode.ts
|
|
11329
11329
|
function configEntryNode(root, key) {
|
|
11330
|
-
const
|
|
11331
|
-
return
|
|
11330
|
+
const path90 = parseConfigPath(key);
|
|
11331
|
+
return path90 ? findConfigNode(root, path90) : void 0;
|
|
11332
11332
|
}
|
|
11333
11333
|
|
|
11334
11334
|
// src/commands/config/configHelpForKey.ts
|
|
@@ -11463,7 +11463,7 @@ function findSynthesisForBranch(repoReviewsDir, branch2) {
|
|
|
11463
11463
|
const parent = dirname21(branchKeyPath);
|
|
11464
11464
|
const branchPrefix = basename8(branchKeyPath);
|
|
11465
11465
|
if (!existsSync32(parent)) return null;
|
|
11466
|
-
const synthesisFiles = readdirSync2(parent).filter((name) => name.startsWith(branchPrefix)).map((name) => join29(parent, name, "synthesis.md")).filter((
|
|
11466
|
+
const synthesisFiles = readdirSync2(parent).filter((name) => name.startsWith(branchPrefix)).map((name) => join29(parent, name, "synthesis.md")).filter((path90) => existsSync32(path90)).map((path90) => ({ path: path90, mtime: statSync4(path90).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
|
|
11467
11467
|
return synthesisFiles[0]?.path ?? null;
|
|
11468
11468
|
}
|
|
11469
11469
|
|
|
@@ -11493,12 +11493,12 @@ async function getReviewSynthesis(req, res) {
|
|
|
11493
11493
|
const cwd = getCwdParam(req, res);
|
|
11494
11494
|
if (!cwd) return;
|
|
11495
11495
|
try {
|
|
11496
|
-
const
|
|
11497
|
-
if (!
|
|
11496
|
+
const path90 = await resolveSynthesisPath(cwd);
|
|
11497
|
+
if (!path90) {
|
|
11498
11498
|
respondJson(res, 404, { error: "No synthesis found" });
|
|
11499
11499
|
return;
|
|
11500
11500
|
}
|
|
11501
|
-
respondJson(res, 200, { synthesis: readFileSync21(
|
|
11501
|
+
respondJson(res, 200, { synthesis: readFileSync21(path90, "utf8") });
|
|
11502
11502
|
} catch {
|
|
11503
11503
|
respondJson(res, 404, { error: "No synthesis found" });
|
|
11504
11504
|
}
|
|
@@ -11581,8 +11581,8 @@ function parseDiffNameStatus(output) {
|
|
|
11581
11581
|
if (!status3 || fields.length < 2) continue;
|
|
11582
11582
|
const category = categorize(status3[0]);
|
|
11583
11583
|
if (!category) continue;
|
|
11584
|
-
const
|
|
11585
|
-
if (
|
|
11584
|
+
const path90 = fields[fields.length - 1];
|
|
11585
|
+
if (path90) result[category].push(path90);
|
|
11586
11586
|
}
|
|
11587
11587
|
return result;
|
|
11588
11588
|
}
|
|
@@ -11718,21 +11718,21 @@ function subsequenceScore(text18, query) {
|
|
|
11718
11718
|
}
|
|
11719
11719
|
return score - Math.min(text18.length, MAX_LENGTH_PENALTY);
|
|
11720
11720
|
}
|
|
11721
|
-
function scoreFilePath(
|
|
11721
|
+
function scoreFilePath(path90, query) {
|
|
11722
11722
|
const needle = query.trim().toLowerCase();
|
|
11723
11723
|
if (!needle) return 0;
|
|
11724
|
-
const basename26 =
|
|
11724
|
+
const basename26 = path90.slice(path90.lastIndexOf("/") + 1);
|
|
11725
11725
|
const inBasename = subsequenceScore(basename26, needle);
|
|
11726
11726
|
if (inBasename !== null) return BASENAME_WEIGHT + inBasename;
|
|
11727
|
-
return subsequenceScore(
|
|
11727
|
+
return subsequenceScore(path90, needle);
|
|
11728
11728
|
}
|
|
11729
11729
|
|
|
11730
11730
|
// src/commands/sessions/web/rankFilePaths.ts
|
|
11731
11731
|
function rankFilePaths(paths, query, limit) {
|
|
11732
11732
|
const scored = [];
|
|
11733
|
-
for (const
|
|
11734
|
-
const score = scoreFilePath(
|
|
11735
|
-
if (score !== null) scored.push({ path:
|
|
11733
|
+
for (const path90 of paths) {
|
|
11734
|
+
const score = scoreFilePath(path90, query);
|
|
11735
|
+
if (score !== null) scored.push({ path: path90, score });
|
|
11736
11736
|
}
|
|
11737
11737
|
scored.sort((a, b) => b.score - a.score || a.path.localeCompare(b.path));
|
|
11738
11738
|
return scored.slice(0, limit).map((entry) => entry.path);
|
|
@@ -11897,17 +11897,33 @@ import path32 from "path";
|
|
|
11897
11897
|
import { existsSync as existsSync34, readFileSync as readFileSync22 } from "fs";
|
|
11898
11898
|
import path31 from "path";
|
|
11899
11899
|
|
|
11900
|
-
// src/commands/rules/
|
|
11900
|
+
// src/commands/rules/rulesSectionRange.ts
|
|
11901
11901
|
var RULES_HEADING = /^##\s+rules\s*$/i;
|
|
11902
11902
|
var SECTION_END = /^#{1,2}\s/;
|
|
11903
11903
|
var RULE_BULLET = /^\s*[-*]\s+\*\*\s*([^*]+?)\s*\*\*\s*(?:[—–:-]\s*)?(.*)$/;
|
|
11904
|
+
function rulesSectionRange(lines2) {
|
|
11905
|
+
const start3 = lines2.findIndex((line) => RULES_HEADING.test(line));
|
|
11906
|
+
if (start3 === -1) return void 0;
|
|
11907
|
+
const offset = lines2.slice(start3 + 1).findIndex((line) => SECTION_END.test(line));
|
|
11908
|
+
return { start: start3, end: offset === -1 ? lines2.length : start3 + 1 + offset };
|
|
11909
|
+
}
|
|
11910
|
+
function contentLines(content) {
|
|
11911
|
+
const trimmed = content.replace(/\s+$/, "");
|
|
11912
|
+
return trimmed === "" ? [] : trimmed.split(/\r?\n/);
|
|
11913
|
+
}
|
|
11914
|
+
function appendRulesSection(lines2, entry) {
|
|
11915
|
+
const preamble = lines2.length === 0 ? [] : [...lines2, ""];
|
|
11916
|
+
return `${[...preamble, "## Rules", "", entry].join("\n")}
|
|
11917
|
+
`;
|
|
11918
|
+
}
|
|
11919
|
+
|
|
11920
|
+
// src/commands/rules/parseRulesSection.ts
|
|
11904
11921
|
function parseRulesSection(content) {
|
|
11905
11922
|
const lines2 = content.split(/\r?\n/);
|
|
11906
|
-
const
|
|
11907
|
-
if (
|
|
11923
|
+
const range = rulesSectionRange(lines2);
|
|
11924
|
+
if (!range) return [];
|
|
11908
11925
|
const rules3 = [];
|
|
11909
|
-
for (const line of lines2.slice(
|
|
11910
|
-
if (SECTION_END.test(line)) break;
|
|
11926
|
+
for (const line of lines2.slice(range.start + 1, range.end)) {
|
|
11911
11927
|
const match = RULE_BULLET.exec(line);
|
|
11912
11928
|
if (!match) continue;
|
|
11913
11929
|
const code = match[1].trim();
|
|
@@ -12282,38 +12298,38 @@ async function restartWeb(req, res, deps2 = {}) {
|
|
|
12282
12298
|
import { relative as relative3 } from "path";
|
|
12283
12299
|
|
|
12284
12300
|
// src/commands/sessions/web/revertPathChanges.ts
|
|
12285
|
-
async function isTracked(cwd,
|
|
12301
|
+
async function isTracked(cwd, path90) {
|
|
12286
12302
|
try {
|
|
12287
|
-
await execGit(cwd, ["ls-files", "--error-unmatch", "--",
|
|
12303
|
+
await execGit(cwd, ["ls-files", "--error-unmatch", "--", path90]);
|
|
12288
12304
|
return true;
|
|
12289
12305
|
} catch {
|
|
12290
12306
|
return false;
|
|
12291
12307
|
}
|
|
12292
12308
|
}
|
|
12293
|
-
async function isInHead(cwd,
|
|
12294
|
-
const listing = await execGit(cwd, ["ls-tree", "HEAD", "--",
|
|
12309
|
+
async function isInHead(cwd, path90) {
|
|
12310
|
+
const listing = await execGit(cwd, ["ls-tree", "HEAD", "--", path90]);
|
|
12295
12311
|
return listing.trim().length > 0;
|
|
12296
12312
|
}
|
|
12297
|
-
async function revertPathChanges(cwd,
|
|
12298
|
-
if (!await isTracked(cwd,
|
|
12299
|
-
await execGit(cwd, ["clean", "-f", "--",
|
|
12313
|
+
async function revertPathChanges(cwd, path90) {
|
|
12314
|
+
if (!await isTracked(cwd, path90)) {
|
|
12315
|
+
await execGit(cwd, ["clean", "-f", "--", path90]);
|
|
12300
12316
|
return;
|
|
12301
12317
|
}
|
|
12302
|
-
if (await isInHead(cwd,
|
|
12303
|
-
await execGit(cwd, ["checkout", "HEAD", "--",
|
|
12318
|
+
if (await isInHead(cwd, path90)) {
|
|
12319
|
+
await execGit(cwd, ["checkout", "HEAD", "--", path90]);
|
|
12304
12320
|
return;
|
|
12305
12321
|
}
|
|
12306
|
-
await execGit(cwd, ["rm", "-f", "--",
|
|
12322
|
+
await execGit(cwd, ["rm", "-f", "--", path90]);
|
|
12307
12323
|
}
|
|
12308
12324
|
|
|
12309
12325
|
// src/commands/sessions/web/revertDiffFile.ts
|
|
12310
12326
|
async function revertDiffFile(req, res) {
|
|
12311
12327
|
const resolved = getFileTarget(req, res);
|
|
12312
12328
|
if (!resolved) return;
|
|
12313
|
-
const
|
|
12329
|
+
const path90 = relative3(repoRoot(resolved.cwd), resolved.target);
|
|
12314
12330
|
try {
|
|
12315
|
-
await revertPathChanges(resolved.cwd,
|
|
12316
|
-
respondJson(res, 200, { reverted:
|
|
12331
|
+
await revertPathChanges(resolved.cwd, path90);
|
|
12332
|
+
respondJson(res, 200, { reverted: path90 });
|
|
12317
12333
|
} catch (error) {
|
|
12318
12334
|
respondJson(res, 500, {
|
|
12319
12335
|
error: error instanceof Error ? error.message : "Failed to revert file"
|
|
@@ -12335,7 +12351,7 @@ async function readJsonBody(req) {
|
|
|
12335
12351
|
function requestedPaths(body) {
|
|
12336
12352
|
const paths = body.paths;
|
|
12337
12353
|
if (!Array.isArray(paths)) return null;
|
|
12338
|
-
if (paths.some((
|
|
12354
|
+
if (paths.some((path90) => typeof path90 !== "string")) return null;
|
|
12339
12355
|
return paths;
|
|
12340
12356
|
}
|
|
12341
12357
|
async function revertDiffPaths(req, res) {
|
|
@@ -12355,10 +12371,10 @@ async function revertDiffPaths(req, res) {
|
|
|
12355
12371
|
const root = repoRoot(cwd);
|
|
12356
12372
|
const reverted = [];
|
|
12357
12373
|
const failed2 = [];
|
|
12358
|
-
for (const
|
|
12359
|
-
const target = resolveWithinCwd(cwd,
|
|
12374
|
+
for (const path90 of paths) {
|
|
12375
|
+
const target = resolveWithinCwd(cwd, path90);
|
|
12360
12376
|
if (!target) {
|
|
12361
|
-
failed2.push({ path:
|
|
12377
|
+
failed2.push({ path: path90, error: "Path outside cwd" });
|
|
12362
12378
|
continue;
|
|
12363
12379
|
}
|
|
12364
12380
|
const relativePath = relative4(root, target);
|
|
@@ -12448,11 +12464,11 @@ function coerceStructuredConfigValue(key, raw) {
|
|
|
12448
12464
|
};
|
|
12449
12465
|
}
|
|
12450
12466
|
function formatIssue(key, issue) {
|
|
12451
|
-
const
|
|
12467
|
+
const path90 = formatConfigPath([
|
|
12452
12468
|
{ kind: "key", name: key },
|
|
12453
12469
|
...issue.path.map(toSegment)
|
|
12454
12470
|
]);
|
|
12455
|
-
return `${
|
|
12471
|
+
return `${path90}: ${issue.message}`;
|
|
12456
12472
|
}
|
|
12457
12473
|
function toSegment(part) {
|
|
12458
12474
|
return typeof part === "number" ? { kind: "index", index: part } : { kind: "key", name: String(part) };
|
|
@@ -12547,9 +12563,9 @@ function coerceUnion(key, raw, types) {
|
|
|
12547
12563
|
}
|
|
12548
12564
|
|
|
12549
12565
|
// src/shared/valueAtConfigPath.ts
|
|
12550
|
-
function valueAtConfigPath(value,
|
|
12566
|
+
function valueAtConfigPath(value, path90) {
|
|
12551
12567
|
let current = value;
|
|
12552
|
-
for (const key of
|
|
12568
|
+
for (const key of path90) {
|
|
12553
12569
|
if (typeof key === "number") {
|
|
12554
12570
|
if (!Array.isArray(current)) return void 0;
|
|
12555
12571
|
current = current[key];
|
|
@@ -12566,7 +12582,7 @@ function restoreConfigSecrets(value, stored, node) {
|
|
|
12566
12582
|
return mapConfigSecrets(
|
|
12567
12583
|
value,
|
|
12568
12584
|
node,
|
|
12569
|
-
(secret,
|
|
12585
|
+
(secret, path90) => isRedactedSecret(secret) ? valueAtConfigPath(stored, path90) : secret
|
|
12570
12586
|
);
|
|
12571
12587
|
}
|
|
12572
12588
|
|
|
@@ -12615,8 +12631,8 @@ function stepIntoNested(container, key, nextKey) {
|
|
|
12615
12631
|
}
|
|
12616
12632
|
return ensureObject(container, resolved);
|
|
12617
12633
|
}
|
|
12618
|
-
function setNestedValue(obj,
|
|
12619
|
-
const keys =
|
|
12634
|
+
function setNestedValue(obj, path90, value) {
|
|
12635
|
+
const keys = path90.split(".");
|
|
12620
12636
|
const result = { ...obj };
|
|
12621
12637
|
let current = result;
|
|
12622
12638
|
for (let i = 0; i < keys.length - 1; i++) {
|
|
@@ -12643,8 +12659,8 @@ function formatIssue2(issue, key) {
|
|
|
12643
12659
|
return issue.keys.map(
|
|
12644
12660
|
(unrecognized) => `${[...issue.path, unrecognized].join(".")}: Unrecognized key`
|
|
12645
12661
|
);
|
|
12646
|
-
const
|
|
12647
|
-
return [`${
|
|
12662
|
+
const path90 = issue.path.length > 0 ? issue.path.join(".") : key;
|
|
12663
|
+
return [`${path90}: ${issue.message}`];
|
|
12648
12664
|
}
|
|
12649
12665
|
|
|
12650
12666
|
// src/commands/config/applyConfigSet.ts
|
|
@@ -12901,8 +12917,8 @@ function removeAt(container, keys) {
|
|
|
12901
12917
|
}
|
|
12902
12918
|
return removeFromChild(container, key, rest);
|
|
12903
12919
|
}
|
|
12904
|
-
function unsetNestedValue(obj,
|
|
12905
|
-
const { container, removed } = removeAt(obj,
|
|
12920
|
+
function unsetNestedValue(obj, path90) {
|
|
12921
|
+
const { container, removed } = removeAt(obj, path90.split("."));
|
|
12906
12922
|
return { config: container, removed };
|
|
12907
12923
|
}
|
|
12908
12924
|
|
|
@@ -14016,9 +14032,9 @@ function originToSshUrl(origin) {
|
|
|
14016
14032
|
const firstSlash = origin.indexOf("/");
|
|
14017
14033
|
if (firstSlash <= 0) return null;
|
|
14018
14034
|
const host = origin.slice(0, firstSlash);
|
|
14019
|
-
const
|
|
14020
|
-
if (!
|
|
14021
|
-
return `git@${host}:${
|
|
14035
|
+
const path90 = origin.slice(firstSlash + 1);
|
|
14036
|
+
if (!path90) return null;
|
|
14037
|
+
return `git@${host}:${path90}.git`;
|
|
14022
14038
|
}
|
|
14023
14039
|
|
|
14024
14040
|
// src/commands/backlog/cloneRepo.ts
|
|
@@ -17046,9 +17062,9 @@ var __dirname4 = dirname23(__filename3);
|
|
|
17046
17062
|
function packageRoot() {
|
|
17047
17063
|
return __dirname4;
|
|
17048
17064
|
}
|
|
17049
|
-
function readLines(
|
|
17050
|
-
if (!existsSync38(
|
|
17051
|
-
return readFileSync26(
|
|
17065
|
+
function readLines(path90) {
|
|
17066
|
+
if (!existsSync38(path90)) return [];
|
|
17067
|
+
return readFileSync26(path90, "utf8").split("\n").filter((line) => line.trim() !== "");
|
|
17052
17068
|
}
|
|
17053
17069
|
var cachedReads;
|
|
17054
17070
|
var cachedWrites;
|
|
@@ -17250,11 +17266,11 @@ function isTruncator(part) {
|
|
|
17250
17266
|
return TRUNCATOR_BINARIES.includes(binary) || PIPED_TRUNCATOR_RE.test(part);
|
|
17251
17267
|
}
|
|
17252
17268
|
function findTruncatedReadDeny(parts) {
|
|
17253
|
-
const
|
|
17254
|
-
if (!
|
|
17269
|
+
const read3 = parts.map(matchUntruncatableRead).find(Boolean);
|
|
17270
|
+
if (!read3 || !parts.some(isTruncator)) return void 0;
|
|
17255
17271
|
return {
|
|
17256
17272
|
permissionDecision: "deny",
|
|
17257
|
-
permissionDecisionReason: `Do not pipe '${
|
|
17273
|
+
permissionDecisionReason: `Do not pipe '${read3}' through head or tail. Plan, Activity and Comments print at the end of the output, so a truncated read drops them and leaves you assuming the item has none. Run '${read3} <id>' bare and read all of it, or use a focused view: 'assist backlog comments <id>' for comments only.`
|
|
17258
17274
|
};
|
|
17259
17275
|
}
|
|
17260
17276
|
|
|
@@ -17569,14 +17585,14 @@ function showProgress(p, label2) {
|
|
|
17569
17585
|
const pct = Math.round(p.done / p.total * 100);
|
|
17570
17586
|
process.stderr.write(`\r\x1B[K[${pct}%] Scanning ${label2}...`);
|
|
17571
17587
|
}
|
|
17572
|
-
async function resolveCommand(cli,
|
|
17573
|
-
showProgress(p,
|
|
17574
|
-
const subHelp = await runHelp([cli, ...
|
|
17588
|
+
async function resolveCommand(cli, path90, description, depth, p) {
|
|
17589
|
+
showProgress(p, path90.join(" "));
|
|
17590
|
+
const subHelp = await runHelp([cli, ...path90]);
|
|
17575
17591
|
if (!subHelp || !hasSubcommands(subHelp)) {
|
|
17576
|
-
return [{ path:
|
|
17592
|
+
return [{ path: path90, description }];
|
|
17577
17593
|
}
|
|
17578
|
-
const children = await discoverAt(cli,
|
|
17579
|
-
return children.length > 0 ? children : [{ path:
|
|
17594
|
+
const children = await discoverAt(cli, path90, depth + 1, p);
|
|
17595
|
+
return children.length > 0 ? children : [{ path: path90, description }];
|
|
17580
17596
|
}
|
|
17581
17597
|
async function discoverAt(cli, parentPath, depth, p) {
|
|
17582
17598
|
if (depth > SAFETY_DEPTH) return [];
|
|
@@ -17724,9 +17740,9 @@ function logPath(cli) {
|
|
|
17724
17740
|
return join39(homedir17(), ".assist", `cli-discover-${safeName}.log`);
|
|
17725
17741
|
}
|
|
17726
17742
|
function readCache(cli) {
|
|
17727
|
-
const
|
|
17728
|
-
if (!existsSync40(
|
|
17729
|
-
return readFileSync28(
|
|
17743
|
+
const path90 = logPath(cli);
|
|
17744
|
+
if (!existsSync40(path90)) return void 0;
|
|
17745
|
+
return readFileSync28(path90, "utf8");
|
|
17730
17746
|
}
|
|
17731
17747
|
function writeCache(cli, output) {
|
|
17732
17748
|
const dir = join39(homedir17(), ".assist");
|
|
@@ -17886,9 +17902,9 @@ function sweepRestrictedDir(dir = getRestrictedDir()) {
|
|
|
17886
17902
|
}
|
|
17887
17903
|
const cutoff = Date.now() - STALE_AFTER_MS;
|
|
17888
17904
|
for (const entry of entries) {
|
|
17889
|
-
const
|
|
17905
|
+
const path90 = join41(dir, entry);
|
|
17890
17906
|
try {
|
|
17891
|
-
if (statSync7(
|
|
17907
|
+
if (statSync7(path90).mtimeMs < cutoff) unlinkSync7(path90);
|
|
17892
17908
|
} catch {
|
|
17893
17909
|
continue;
|
|
17894
17910
|
}
|
|
@@ -17898,10 +17914,10 @@ function sweepRestrictedDir(dir = getRestrictedDir()) {
|
|
|
17898
17914
|
// src/commands/codeComment/readPinState.ts
|
|
17899
17915
|
import { existsSync as existsSync41, readFileSync as readFileSync29 } from "fs";
|
|
17900
17916
|
function readPinState(pin) {
|
|
17901
|
-
const
|
|
17902
|
-
if (!existsSync41(
|
|
17917
|
+
const path90 = getPinStatePath(pin);
|
|
17918
|
+
if (!existsSync41(path90)) return void 0;
|
|
17903
17919
|
try {
|
|
17904
|
-
const state = JSON.parse(readFileSync29(
|
|
17920
|
+
const state = JSON.parse(readFileSync29(path90, "utf8"));
|
|
17905
17921
|
if (state.pin !== pin) return void 0;
|
|
17906
17922
|
return state;
|
|
17907
17923
|
} catch {
|
|
@@ -19040,11 +19056,11 @@ async function loadPath(source) {
|
|
|
19040
19056
|
}
|
|
19041
19057
|
}
|
|
19042
19058
|
async function criteriaExtension() {
|
|
19043
|
-
const
|
|
19059
|
+
const path90 = await loadPath(criteriaExtensionDir());
|
|
19044
19060
|
console.log(
|
|
19045
19061
|
chalk139.bold("acceptance criteria outliner \u2014 GitHub browser extension")
|
|
19046
19062
|
);
|
|
19047
|
-
console.log(chalk139.dim(`load the unpacked extension from ${
|
|
19063
|
+
console.log(chalk139.dim(`load the unpacked extension from ${path90}`));
|
|
19048
19064
|
}
|
|
19049
19065
|
|
|
19050
19066
|
// src/commands/criteriaExtension/signCriteriaExtension.ts
|
|
@@ -19169,10 +19185,10 @@ async function signCriteriaExtension() {
|
|
|
19169
19185
|
process.exitCode = 1;
|
|
19170
19186
|
return;
|
|
19171
19187
|
}
|
|
19172
|
-
const
|
|
19188
|
+
const path90 = await signedAddonInstallPath(
|
|
19173
19189
|
await copySignedXpi(xpi, ARTIFACTS_DIR)
|
|
19174
19190
|
);
|
|
19175
|
-
console.log(chalk141.dim(`install the signed add-on from ${
|
|
19191
|
+
console.log(chalk141.dim(`install the signed add-on from ${path90}`));
|
|
19176
19192
|
}
|
|
19177
19193
|
|
|
19178
19194
|
// src/commands/registerCriteriaExtension.ts
|
|
@@ -19270,10 +19286,10 @@ function getMigrationApprovalPath(migrationId) {
|
|
|
19270
19286
|
// src/commands/dbMigration/readMigrationPinState.ts
|
|
19271
19287
|
import { existsSync as existsSync46, readFileSync as readFileSync31 } from "fs";
|
|
19272
19288
|
function readMigrationPinState(pin) {
|
|
19273
|
-
const
|
|
19274
|
-
if (!existsSync46(
|
|
19289
|
+
const path90 = getMigrationPinPath(pin);
|
|
19290
|
+
if (!existsSync46(path90)) return void 0;
|
|
19275
19291
|
try {
|
|
19276
|
-
const state = JSON.parse(readFileSync31(
|
|
19292
|
+
const state = JSON.parse(readFileSync31(path90, "utf8"));
|
|
19277
19293
|
if (state.pin !== pin) return void 0;
|
|
19278
19294
|
if (!Number.isInteger(state.migrationId)) return void 0;
|
|
19279
19295
|
return state;
|
|
@@ -20703,10 +20719,10 @@ function decideCommentGuard(input, existingContent) {
|
|
|
20703
20719
|
import { existsSync as existsSync52, unlinkSync as unlinkSync11 } from "fs";
|
|
20704
20720
|
function consumeMigrationApproval(migrationId) {
|
|
20705
20721
|
sweepRestrictedDir();
|
|
20706
|
-
const
|
|
20707
|
-
if (!existsSync52(
|
|
20722
|
+
const path90 = getMigrationApprovalPath(migrationId);
|
|
20723
|
+
if (!existsSync52(path90)) return false;
|
|
20708
20724
|
try {
|
|
20709
|
-
unlinkSync11(
|
|
20725
|
+
unlinkSync11(path90);
|
|
20710
20726
|
return true;
|
|
20711
20727
|
} catch {
|
|
20712
20728
|
return false;
|
|
@@ -22400,11 +22416,11 @@ function recentDaemonLogLines() {
|
|
|
22400
22416
|
// src/commands/sessions/daemon/worktree/canonicalTreePath.ts
|
|
22401
22417
|
import { realpathSync as realpathSync2 } from "fs";
|
|
22402
22418
|
import { resolve as resolve14 } from "path";
|
|
22403
|
-
function canonicalTreePath(
|
|
22419
|
+
function canonicalTreePath(path90) {
|
|
22404
22420
|
try {
|
|
22405
|
-
return realpathSync2(
|
|
22421
|
+
return realpathSync2(path90);
|
|
22406
22422
|
} catch {
|
|
22407
|
-
return resolve14(
|
|
22423
|
+
return resolve14(path90);
|
|
22408
22424
|
}
|
|
22409
22425
|
}
|
|
22410
22426
|
|
|
@@ -22457,22 +22473,22 @@ function createWorktree(clone, strategy, boundTreeRoots2, preferredPath) {
|
|
|
22457
22473
|
const registered = new Set(listWorktreePaths(clone));
|
|
22458
22474
|
const branches = new Set(listLocalBranches(clone));
|
|
22459
22475
|
const isTaken = (candidate) => registered.has(candidate) || existsSync55(candidate) || boundTreeRoots2.has(candidate) || branches.has(basename16(candidate));
|
|
22460
|
-
const
|
|
22476
|
+
const path90 = preferredPath && !isTaken(preferredPath) ? preferredPath : nextWorktreePath(clone, base, isTaken);
|
|
22461
22477
|
const start3 = worktreeStartPoint(clone, strategy.trunk);
|
|
22462
22478
|
gitSync(clone, [
|
|
22463
22479
|
"worktree",
|
|
22464
22480
|
"add",
|
|
22465
22481
|
start3.track ? "--track" : "--no-track",
|
|
22466
22482
|
"-b",
|
|
22467
|
-
basename16(
|
|
22468
|
-
|
|
22483
|
+
basename16(path90),
|
|
22484
|
+
path90,
|
|
22469
22485
|
start3.ref
|
|
22470
22486
|
]);
|
|
22471
|
-
recordWorktree(
|
|
22487
|
+
recordWorktree(path90, clone, getCurrentOrigin(clone));
|
|
22472
22488
|
daemonLog(
|
|
22473
|
-
start3.track ? `worktree allocated ${
|
|
22489
|
+
start3.track ? `worktree allocated ${path90} (branch ${basename16(path90)} tracking ${start3.ref}) for clone ${clone}` : `worktree allocated ${path90} (branch ${basename16(path90)} off ${start3.ref}, no mainline tracking) for clone ${clone}`
|
|
22474
22490
|
);
|
|
22475
|
-
return
|
|
22491
|
+
return path90;
|
|
22476
22492
|
}
|
|
22477
22493
|
|
|
22478
22494
|
// src/commands/sessions/daemon/worktree/keptInTree.ts
|
|
@@ -22613,13 +22629,13 @@ function allocateTree(requestedCwd, boundTreeRoots2, options2 = {}) {
|
|
|
22613
22629
|
if (forcedSpill) daemonLog(forcedSpill);
|
|
22614
22630
|
else if (reusesClone(clone, boundTreeRoots2, reuse))
|
|
22615
22631
|
return { cwd: clone, kind: "primary", created: false, clone };
|
|
22616
|
-
const
|
|
22632
|
+
const path90 = createWorktree(
|
|
22617
22633
|
clone,
|
|
22618
22634
|
{ root: cfg.root, trunk: cfg.trunk },
|
|
22619
22635
|
boundTreeRoots2,
|
|
22620
22636
|
options2.replacesTree
|
|
22621
22637
|
);
|
|
22622
|
-
return { cwd:
|
|
22638
|
+
return { cwd: path90, kind: "worktree", created: true, clone };
|
|
22623
22639
|
}
|
|
22624
22640
|
|
|
22625
22641
|
// src/commands/sessions/daemon/describePersistedSession.ts
|
|
@@ -22950,13 +22966,13 @@ function worktreeHoldingBranch(cwd, branch2) {
|
|
|
22950
22966
|
const listing = gitSyncOrNull(cwd, ["worktree", "list", "--porcelain"]);
|
|
22951
22967
|
if (!listing) return null;
|
|
22952
22968
|
const here = gitSyncOrNull(cwd, ["rev-parse", "--show-toplevel"]);
|
|
22953
|
-
let
|
|
22969
|
+
let path90 = null;
|
|
22954
22970
|
for (const line of listing.split("\n")) {
|
|
22955
22971
|
const trimmed = line.trim();
|
|
22956
22972
|
if (trimmed.startsWith("worktree "))
|
|
22957
|
-
|
|
22973
|
+
path90 = trimmed.slice("worktree ".length).trim();
|
|
22958
22974
|
else if (trimmed === `branch refs/heads/${branch2}`)
|
|
22959
|
-
return
|
|
22975
|
+
return path90 && path90 !== here ? path90 : null;
|
|
22960
22976
|
}
|
|
22961
22977
|
return null;
|
|
22962
22978
|
}
|
|
@@ -23998,9 +24014,9 @@ function parseRscRows(flight) {
|
|
|
23998
24014
|
}
|
|
23999
24015
|
function makeRscResolver(rows) {
|
|
24000
24016
|
return (ref) => {
|
|
24001
|
-
const [id, ...
|
|
24017
|
+
const [id, ...path90] = ref.slice(1).replace(/^[L@]/, "").split(":");
|
|
24002
24018
|
let v = rows[id];
|
|
24003
|
-
for (const key of
|
|
24019
|
+
for (const key of path90) {
|
|
24004
24020
|
if (v == null || typeof v !== "object") return void 0;
|
|
24005
24021
|
v = v[key];
|
|
24006
24022
|
}
|
|
@@ -24703,16 +24719,16 @@ function validateLine(line) {
|
|
|
24703
24719
|
process.exit(1);
|
|
24704
24720
|
}
|
|
24705
24721
|
}
|
|
24706
|
-
async function comment2(
|
|
24722
|
+
async function comment2(path90, line, body, startLine) {
|
|
24707
24723
|
validateBody(body);
|
|
24708
24724
|
validateLine(line);
|
|
24709
24725
|
if (startLine !== void 0) validateLine(startLine);
|
|
24710
24726
|
const range = startLine !== void 0 ? `${startLine}-${line}` : `${line}`;
|
|
24711
|
-
await reviewProposedPrComment(`Comment on ${
|
|
24727
|
+
await reviewProposedPrComment(`Comment on ${path90}:${range}`, body, null);
|
|
24712
24728
|
try {
|
|
24713
24729
|
const prId = getCurrentPrNodeId();
|
|
24714
|
-
postReviewComment({ prId, body, path:
|
|
24715
|
-
console.log(`Added review comment on ${
|
|
24730
|
+
postReviewComment({ prId, body, path: path90, line, startLine });
|
|
24731
|
+
console.log(`Added review comment on ${path90}:${range}`);
|
|
24716
24732
|
} catch (error) {
|
|
24717
24733
|
if (isGhNotInstalled(error)) {
|
|
24718
24734
|
console.error("Error: GitHub CLI (gh) is not installed.");
|
|
@@ -25914,9 +25930,9 @@ function registerPrsComments(prsCommand) {
|
|
|
25914
25930
|
});
|
|
25915
25931
|
prsCommand.command("comment <path> <line> <body>").description(
|
|
25916
25932
|
"Add a line comment to the pending review (body of - reads it from stdin)"
|
|
25917
|
-
).action(async (
|
|
25933
|
+
).action(async (path90, line, body) => {
|
|
25918
25934
|
await comment2(
|
|
25919
|
-
|
|
25935
|
+
path90,
|
|
25920
25936
|
Number.parseInt(line, 10),
|
|
25921
25937
|
await readBodyArgument(body)
|
|
25922
25938
|
);
|
|
@@ -26380,10 +26396,10 @@ function resolveOpSecret(reference) {
|
|
|
26380
26396
|
}
|
|
26381
26397
|
|
|
26382
26398
|
// src/commands/ravendb/ravenFetch.ts
|
|
26383
|
-
async function ravenFetch(connection,
|
|
26399
|
+
async function ravenFetch(connection, path90) {
|
|
26384
26400
|
const apiKey = resolveOpSecret(connection.apiKeyRef);
|
|
26385
26401
|
let accessToken = await getAccessToken(apiKey);
|
|
26386
|
-
const url = `${connection.url}${
|
|
26402
|
+
const url = `${connection.url}${path90}`;
|
|
26387
26403
|
const headers = {
|
|
26388
26404
|
Authorization: `Bearer ${accessToken}`,
|
|
26389
26405
|
"Content-Type": "application/json"
|
|
@@ -26473,16 +26489,16 @@ import chalk193 from "chalk";
|
|
|
26473
26489
|
// src/commands/ravendb/buildQueryPath.ts
|
|
26474
26490
|
function buildQueryPath(opts) {
|
|
26475
26491
|
const db = encodeURIComponent(opts.db);
|
|
26476
|
-
let
|
|
26492
|
+
let path90;
|
|
26477
26493
|
if (opts.collection) {
|
|
26478
|
-
|
|
26494
|
+
path90 = `/databases/${db}/indexes/dynamic/${encodeURIComponent(opts.collection)}?start=${opts.start}&pageSize=${opts.pageSize}&sort=${encodeURIComponent(opts.sort)}`;
|
|
26479
26495
|
} else {
|
|
26480
|
-
|
|
26496
|
+
path90 = `/databases/${db}/queries?start=${opts.start}&pageSize=${opts.pageSize}`;
|
|
26481
26497
|
}
|
|
26482
26498
|
if (opts.query) {
|
|
26483
|
-
|
|
26499
|
+
path90 += `&query=${encodeURIComponent(opts.query)}`;
|
|
26484
26500
|
}
|
|
26485
|
-
return
|
|
26501
|
+
return path90;
|
|
26486
26502
|
}
|
|
26487
26503
|
|
|
26488
26504
|
// src/commands/ravendb/fetchAllPages.ts
|
|
@@ -26491,7 +26507,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
26491
26507
|
let start3 = 0;
|
|
26492
26508
|
while (true) {
|
|
26493
26509
|
const effectivePageSize = opts.limit !== void 0 ? Math.min(opts.pageSize, opts.limit - allResults.length) : opts.pageSize;
|
|
26494
|
-
const
|
|
26510
|
+
const path90 = buildQueryPath({
|
|
26495
26511
|
db: connection.database,
|
|
26496
26512
|
collection: opts.collection,
|
|
26497
26513
|
start: start3,
|
|
@@ -26499,7 +26515,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
26499
26515
|
sort: opts.sort,
|
|
26500
26516
|
query: opts.query
|
|
26501
26517
|
});
|
|
26502
|
-
const data = await ravenFetch(connection,
|
|
26518
|
+
const data = await ravenFetch(connection, path90);
|
|
26503
26519
|
const results = data.Results ?? [];
|
|
26504
26520
|
const totalResults = data.TotalResults ?? 0;
|
|
26505
26521
|
if (results.length === 0) break;
|
|
@@ -29107,8 +29123,8 @@ async function handlePostSynthesis(synthesisPath, prInfo, options2) {
|
|
|
29107
29123
|
// src/commands/review/prepareReviewDir.ts
|
|
29108
29124
|
import { existsSync as existsSync61, mkdirSync as mkdirSync21, unlinkSync as unlinkSync17, writeFileSync as writeFileSync38 } from "fs";
|
|
29109
29125
|
function clearReviewFiles(paths) {
|
|
29110
|
-
for (const
|
|
29111
|
-
if (existsSync61(
|
|
29126
|
+
for (const path90 of [paths.claudePath, paths.codexPath, paths.synthesisPath]) {
|
|
29127
|
+
if (existsSync61(path90)) unlinkSync17(path90);
|
|
29112
29128
|
}
|
|
29113
29129
|
}
|
|
29114
29130
|
function prepareReviewDir(paths, requestBody, force) {
|
|
@@ -30156,15 +30172,185 @@ function registerReview(program2) {
|
|
|
30156
30172
|
);
|
|
30157
30173
|
}
|
|
30158
30174
|
|
|
30159
|
-
// src/commands/rules/
|
|
30160
|
-
import
|
|
30175
|
+
// src/commands/rules/addRule.ts
|
|
30176
|
+
import { existsSync as existsSync66, readFileSync as readFileSync50, writeFileSync as writeFileSync41 } from "fs";
|
|
30177
|
+
import path71 from "path";
|
|
30161
30178
|
import chalk209 from "chalk";
|
|
30179
|
+
|
|
30180
|
+
// src/commands/rules/insertRuleBullet.ts
|
|
30181
|
+
function insertRuleBullet(content, code, text18) {
|
|
30182
|
+
const bullet = `- **${code}** \u2014 ${text18}`;
|
|
30183
|
+
const lines2 = contentLines(content);
|
|
30184
|
+
const range = rulesSectionRange(lines2);
|
|
30185
|
+
if (!range) return appendRulesSection(lines2, bullet);
|
|
30186
|
+
const body = lines2.slice(range.start + 1, range.end);
|
|
30187
|
+
const lastBullet = body.reduce(
|
|
30188
|
+
(last, line, index3) => RULE_BULLET.test(line) ? index3 : last,
|
|
30189
|
+
-1
|
|
30190
|
+
);
|
|
30191
|
+
const at2 = lastBullet === -1 ? range.start + 1 : range.start + lastBullet + 2;
|
|
30192
|
+
const inserted = lastBullet === -1 ? ["", bullet] : [bullet];
|
|
30193
|
+
return `${[...lines2.slice(0, at2), ...inserted, ...lines2.slice(at2)].join("\n")}
|
|
30194
|
+
`;
|
|
30195
|
+
}
|
|
30196
|
+
|
|
30197
|
+
// src/commands/rules/nextRuleCode.ts
|
|
30198
|
+
import { readFileSync as readFileSync47 } from "fs";
|
|
30199
|
+
|
|
30200
|
+
// src/commands/rules/findClaudeFiles.ts
|
|
30201
|
+
import { readdirSync as readdirSync13 } from "fs";
|
|
30202
|
+
import path67 from "path";
|
|
30203
|
+
var SKIP_DIRECTORIES = /* @__PURE__ */ new Set(["node_modules", "dist", "build", "coverage"]);
|
|
30204
|
+
function findClaudeFiles(dir) {
|
|
30205
|
+
const results = [];
|
|
30206
|
+
for (const entry of readdirSync13(dir, { withFileTypes: true })) {
|
|
30207
|
+
if (entry.isDirectory()) {
|
|
30208
|
+
if (entry.name.startsWith(".") || SKIP_DIRECTORIES.has(entry.name))
|
|
30209
|
+
continue;
|
|
30210
|
+
results.push(...findClaudeFiles(path67.join(dir, entry.name)));
|
|
30211
|
+
} else if (entry.name === "CLAUDE.md") {
|
|
30212
|
+
results.push(path67.join(dir, entry.name));
|
|
30213
|
+
}
|
|
30214
|
+
}
|
|
30215
|
+
return results;
|
|
30216
|
+
}
|
|
30217
|
+
|
|
30218
|
+
// src/commands/rules/nextRuleCode.ts
|
|
30219
|
+
var CODE_PREFIX = "R";
|
|
30220
|
+
function nextRuleCode(root) {
|
|
30221
|
+
const numbers = findClaudeFiles(root).flatMap(
|
|
30222
|
+
(file) => parseRulesSection(readFileSync47(file, "utf8")).map(
|
|
30223
|
+
(rule) => Number(/(\d+)\s*$/.exec(rule.code)?.[1] ?? 0)
|
|
30224
|
+
)
|
|
30225
|
+
);
|
|
30226
|
+
return `${CODE_PREFIX}${Math.max(0, ...numbers) + 1}`;
|
|
30227
|
+
}
|
|
30228
|
+
|
|
30229
|
+
// src/commands/rules/resolveRuleScope.ts
|
|
30230
|
+
import { existsSync as existsSync64 } from "fs";
|
|
30231
|
+
import path68 from "path";
|
|
30232
|
+
function resolveRuleScope(target) {
|
|
30233
|
+
const resolved = path68.resolve(target);
|
|
30234
|
+
if (path68.basename(resolved) === "CLAUDE.md") return resolved;
|
|
30235
|
+
const startDir = scopeDirectory(resolved);
|
|
30236
|
+
const root = findRepoRoot(startDir) ?? startDir;
|
|
30237
|
+
let current = startDir;
|
|
30238
|
+
while (true) {
|
|
30239
|
+
const candidate = path68.join(current, "CLAUDE.md");
|
|
30240
|
+
if (existsSync64(candidate)) return candidate;
|
|
30241
|
+
if (current === root || current === path68.dirname(current)) break;
|
|
30242
|
+
current = path68.dirname(current);
|
|
30243
|
+
}
|
|
30244
|
+
return path68.join(root, "CLAUDE.md");
|
|
30245
|
+
}
|
|
30246
|
+
|
|
30247
|
+
// src/commands/rules/updateScopedRulesIndex.ts
|
|
30248
|
+
import { existsSync as existsSync65, readFileSync as readFileSync49, writeFileSync as writeFileSync40 } from "fs";
|
|
30249
|
+
import path70 from "path";
|
|
30250
|
+
|
|
30251
|
+
// src/commands/rules/scopedRuleDirectories.ts
|
|
30252
|
+
import { readFileSync as readFileSync48 } from "fs";
|
|
30253
|
+
import path69 from "path";
|
|
30254
|
+
function scopedRuleDirectories(root) {
|
|
30255
|
+
return findClaudeFiles(root).filter(
|
|
30256
|
+
(file) => path69.dirname(file) !== root && parseRulesSection(readFileSync48(file, "utf8")).length > 0
|
|
30257
|
+
).map(
|
|
30258
|
+
(file) => `${path69.relative(root, path69.dirname(file)).split(path69.sep).join("/")}/`
|
|
30259
|
+
).sort();
|
|
30260
|
+
}
|
|
30261
|
+
|
|
30262
|
+
// src/commands/rules/upsertScopedRulesPointer.ts
|
|
30263
|
+
var POINTER_PREFIX = "Directories with their own `## Rules`:";
|
|
30264
|
+
function pointerLine(directories) {
|
|
30265
|
+
return `${POINTER_PREFIX} ${directories.map((dir) => `\`${dir}\``).join(", ")}`;
|
|
30266
|
+
}
|
|
30267
|
+
function upsertScopedRulesPointer(content, directories) {
|
|
30268
|
+
const lines2 = contentLines(content);
|
|
30269
|
+
const range = rulesSectionRange(lines2);
|
|
30270
|
+
const existing = lines2.findIndex(
|
|
30271
|
+
(line, index3) => range !== void 0 && index3 > range.start && index3 < range.end && line.startsWith(POINTER_PREFIX)
|
|
30272
|
+
);
|
|
30273
|
+
if (directories.length === 0) {
|
|
30274
|
+
if (existing === -1) return content;
|
|
30275
|
+
const without = [...lines2.slice(0, existing), ...lines2.slice(existing + 1)];
|
|
30276
|
+
return `${without.join("\n").replace(/\n{3,}/g, "\n\n").trimEnd()}
|
|
30277
|
+
`;
|
|
30278
|
+
}
|
|
30279
|
+
const pointer = pointerLine(directories);
|
|
30280
|
+
if (existing !== -1) {
|
|
30281
|
+
if (lines2[existing] === pointer) return content;
|
|
30282
|
+
const replaced = [...lines2];
|
|
30283
|
+
replaced[existing] = pointer;
|
|
30284
|
+
return `${replaced.join("\n")}
|
|
30285
|
+
`;
|
|
30286
|
+
}
|
|
30287
|
+
if (!range) return appendRulesSection(lines2, pointer);
|
|
30288
|
+
let at2 = range.end;
|
|
30289
|
+
while (at2 > range.start + 1 && (lines2[at2 - 1] ?? "").trim() === "") at2--;
|
|
30290
|
+
return `${[...lines2.slice(0, at2), "", pointer, ...lines2.slice(at2)].join("\n")}
|
|
30291
|
+
`;
|
|
30292
|
+
}
|
|
30293
|
+
|
|
30294
|
+
// src/commands/rules/updateScopedRulesIndex.ts
|
|
30295
|
+
function updateScopedRulesIndex(root) {
|
|
30296
|
+
const directories = scopedRuleDirectories(root);
|
|
30297
|
+
const rootFile = path70.join(root, "CLAUDE.md");
|
|
30298
|
+
const before = existsSync65(rootFile) ? readFileSync49(rootFile, "utf8") : "";
|
|
30299
|
+
const after = upsertScopedRulesPointer(before, directories);
|
|
30300
|
+
if (after !== before) writeFileSync40(rootFile, after);
|
|
30301
|
+
return directories;
|
|
30302
|
+
}
|
|
30303
|
+
|
|
30304
|
+
// src/commands/rules/addRule.ts
|
|
30305
|
+
function read2(file) {
|
|
30306
|
+
return existsSync66(file) ? readFileSync50(file, "utf8") : "";
|
|
30307
|
+
}
|
|
30308
|
+
function addRule(text18, options2) {
|
|
30309
|
+
const rule = text18.trim();
|
|
30310
|
+
if (rule === "") {
|
|
30311
|
+
console.error(chalk209.red("Rule text is required"));
|
|
30312
|
+
process.exitCode = 1;
|
|
30313
|
+
return;
|
|
30314
|
+
}
|
|
30315
|
+
const target = resolveRuleScope(options2.scope ?? process.cwd());
|
|
30316
|
+
const targetDir = path71.dirname(target);
|
|
30317
|
+
const root = findRepoRoot(targetDir) ?? targetDir;
|
|
30318
|
+
const code = nextRuleCode(root);
|
|
30319
|
+
writeFileSync41(target, insertRuleBullet(read2(target), code, rule));
|
|
30320
|
+
updateScopedRulesIndex(root);
|
|
30321
|
+
console.log(
|
|
30322
|
+
`Added ${chalk209.cyan(code)} to ${path71.relative(process.cwd(), target) || target}`
|
|
30323
|
+
);
|
|
30324
|
+
}
|
|
30325
|
+
|
|
30326
|
+
// src/commands/rules/indexRules.ts
|
|
30327
|
+
import path72 from "path";
|
|
30328
|
+
import chalk210 from "chalk";
|
|
30329
|
+
function indexRules(target) {
|
|
30330
|
+
const startDir = scopeDirectory(path72.resolve(target ?? process.cwd()));
|
|
30331
|
+
const root = findRepoRoot(startDir) ?? startDir;
|
|
30332
|
+
const directories = updateScopedRulesIndex(root);
|
|
30333
|
+
const rootFile = path72.relative(process.cwd(), path72.join(root, "CLAUDE.md"));
|
|
30334
|
+
if (directories.length === 0) {
|
|
30335
|
+
console.log(
|
|
30336
|
+
chalk210.gray(`No directories carry their own \`## Rules\` under ${root}`)
|
|
30337
|
+
);
|
|
30338
|
+
return;
|
|
30339
|
+
}
|
|
30340
|
+
console.log(`Recorded in ${rootFile || "CLAUDE.md"}`);
|
|
30341
|
+
for (const directory of directories)
|
|
30342
|
+
console.log(` ${chalk210.cyan(directory)}`);
|
|
30343
|
+
}
|
|
30344
|
+
|
|
30345
|
+
// src/commands/rules/listRules.ts
|
|
30346
|
+
import path73 from "path";
|
|
30347
|
+
import chalk211 from "chalk";
|
|
30162
30348
|
function listRules(target) {
|
|
30163
|
-
const resolved =
|
|
30349
|
+
const resolved = path73.resolve(target ?? process.cwd());
|
|
30164
30350
|
const rules3 = readScopedRules(resolved);
|
|
30165
30351
|
if (rules3.length === 0) {
|
|
30166
|
-
const label2 =
|
|
30167
|
-
console.log(
|
|
30352
|
+
const label2 = path73.relative(process.cwd(), resolved) || ".";
|
|
30353
|
+
console.log(chalk211.gray(`No rules in scope for ${label2}`));
|
|
30168
30354
|
return;
|
|
30169
30355
|
}
|
|
30170
30356
|
const base = findRepoRoot(scopeDirectory(resolved));
|
|
@@ -30174,23 +30360,34 @@ function listRules(target) {
|
|
|
30174
30360
|
if (rule.source !== shown) {
|
|
30175
30361
|
shown = rule.source;
|
|
30176
30362
|
console.log(
|
|
30177
|
-
|
|
30363
|
+
chalk211.dim(base ? path73.relative(base, rule.source) : rule.source)
|
|
30178
30364
|
);
|
|
30179
30365
|
}
|
|
30180
|
-
console.log(` ${
|
|
30366
|
+
console.log(` ${chalk211.cyan(rule.code.padEnd(width))} ${rule.text}`);
|
|
30181
30367
|
}
|
|
30182
30368
|
}
|
|
30183
30369
|
|
|
30184
30370
|
// src/commands/registerRules.ts
|
|
30185
30371
|
function registerRules(program2) {
|
|
30186
|
-
const rulesCommand = program2.command("rules").description("Read the CLAUDE.md rules in scope for a path");
|
|
30372
|
+
const rulesCommand = program2.command("rules").description("Read and write the CLAUDE.md rules in scope for a path");
|
|
30187
30373
|
rulesCommand.command("list [path]").description(
|
|
30188
30374
|
"List the rules from the `## Rules` section of every CLAUDE.md from a path's directory up to the repo root (default: cwd)"
|
|
30189
30375
|
).action((target) => listRules(target));
|
|
30376
|
+
rulesCommand.command("add <text>").description(
|
|
30377
|
+
"Add a rule to the `## Rules` section of the scope's CLAUDE.md, allocating the next repo-wide code and creating the section when absent"
|
|
30378
|
+
).option(
|
|
30379
|
+
"--scope <path>",
|
|
30380
|
+
"File or directory whose nearest CLAUDE.md receives the rule, or a CLAUDE.md path to write to directly (default: cwd)"
|
|
30381
|
+
).action(
|
|
30382
|
+
(text18, options2) => addRule(text18, options2)
|
|
30383
|
+
);
|
|
30384
|
+
rulesCommand.command("index [path]").description(
|
|
30385
|
+
"Record the directories that carry their own `## Rules` in the repo root's CLAUDE.md, so scoped rules are discoverable from the root"
|
|
30386
|
+
).action((target) => indexRules(target));
|
|
30190
30387
|
}
|
|
30191
30388
|
|
|
30192
30389
|
// src/commands/seq/seqAuth.ts
|
|
30193
|
-
import
|
|
30390
|
+
import chalk213 from "chalk";
|
|
30194
30391
|
|
|
30195
30392
|
// src/commands/seq/loadConnections.ts
|
|
30196
30393
|
function loadConnections2() {
|
|
@@ -30219,10 +30416,10 @@ function setDefaultConnection(name) {
|
|
|
30219
30416
|
}
|
|
30220
30417
|
|
|
30221
30418
|
// src/shared/assertUniqueName.ts
|
|
30222
|
-
import
|
|
30419
|
+
import chalk212 from "chalk";
|
|
30223
30420
|
function assertUniqueName(existingNames, name) {
|
|
30224
30421
|
if (existingNames.includes(name)) {
|
|
30225
|
-
console.error(
|
|
30422
|
+
console.error(chalk212.red(`Connection "${name}" already exists.`));
|
|
30226
30423
|
process.exit(1);
|
|
30227
30424
|
}
|
|
30228
30425
|
}
|
|
@@ -30240,18 +30437,18 @@ async function promptConnection2(existingNames) {
|
|
|
30240
30437
|
var seqAuth = createConnectionAuth({
|
|
30241
30438
|
load: loadConnections2,
|
|
30242
30439
|
save: saveConnections2,
|
|
30243
|
-
format: (c) => `${
|
|
30440
|
+
format: (c) => `${chalk213.bold(c.name)} ${c.url}`,
|
|
30244
30441
|
promptNew: promptConnection2,
|
|
30245
30442
|
onFirst: (c) => setDefaultConnection(c.name)
|
|
30246
30443
|
});
|
|
30247
30444
|
|
|
30248
30445
|
// src/commands/seq/seqQuery.ts
|
|
30249
|
-
import
|
|
30446
|
+
import chalk217 from "chalk";
|
|
30250
30447
|
|
|
30251
30448
|
// src/commands/seq/fetchSeq.ts
|
|
30252
|
-
import
|
|
30253
|
-
async function fetchSeq(conn,
|
|
30254
|
-
const url = `${conn.url}${
|
|
30449
|
+
import chalk214 from "chalk";
|
|
30450
|
+
async function fetchSeq(conn, path90, params) {
|
|
30451
|
+
const url = `${conn.url}${path90}?${params}`;
|
|
30255
30452
|
const response = await fetch(url, {
|
|
30256
30453
|
headers: {
|
|
30257
30454
|
Accept: "application/json",
|
|
@@ -30260,7 +30457,7 @@ async function fetchSeq(conn, path84, params) {
|
|
|
30260
30457
|
});
|
|
30261
30458
|
if (!response.ok) {
|
|
30262
30459
|
const body = await response.text();
|
|
30263
|
-
console.error(
|
|
30460
|
+
console.error(chalk214.red(`Seq returned ${response.status}: ${body}`));
|
|
30264
30461
|
process.exit(1);
|
|
30265
30462
|
}
|
|
30266
30463
|
return response;
|
|
@@ -30319,23 +30516,23 @@ async function fetchSeqEvents(conn, params) {
|
|
|
30319
30516
|
}
|
|
30320
30517
|
|
|
30321
30518
|
// src/commands/seq/formatEvent.ts
|
|
30322
|
-
import
|
|
30519
|
+
import chalk215 from "chalk";
|
|
30323
30520
|
function levelColor(level) {
|
|
30324
30521
|
switch (level) {
|
|
30325
30522
|
case "Fatal":
|
|
30326
|
-
return
|
|
30523
|
+
return chalk215.bgRed.white;
|
|
30327
30524
|
case "Error":
|
|
30328
|
-
return
|
|
30525
|
+
return chalk215.red;
|
|
30329
30526
|
case "Warning":
|
|
30330
|
-
return
|
|
30527
|
+
return chalk215.yellow;
|
|
30331
30528
|
case "Information":
|
|
30332
|
-
return
|
|
30529
|
+
return chalk215.cyan;
|
|
30333
30530
|
case "Debug":
|
|
30334
|
-
return
|
|
30531
|
+
return chalk215.gray;
|
|
30335
30532
|
case "Verbose":
|
|
30336
|
-
return
|
|
30533
|
+
return chalk215.dim;
|
|
30337
30534
|
default:
|
|
30338
|
-
return
|
|
30535
|
+
return chalk215.white;
|
|
30339
30536
|
}
|
|
30340
30537
|
}
|
|
30341
30538
|
function levelAbbrev(level) {
|
|
@@ -30376,12 +30573,12 @@ function formatTimestamp(iso) {
|
|
|
30376
30573
|
function formatEvent(event) {
|
|
30377
30574
|
const color = levelColor(event.Level);
|
|
30378
30575
|
const abbrev = levelAbbrev(event.Level);
|
|
30379
|
-
const ts8 =
|
|
30576
|
+
const ts8 = chalk215.dim(formatTimestamp(event.Timestamp));
|
|
30380
30577
|
const msg = renderMessage(event);
|
|
30381
30578
|
const lines2 = [`${ts8} ${color(`[${abbrev}]`)} ${msg}`];
|
|
30382
30579
|
if (event.Exception) {
|
|
30383
30580
|
for (const line of event.Exception.split("\n")) {
|
|
30384
|
-
lines2.push(
|
|
30581
|
+
lines2.push(chalk215.red(` ${line}`));
|
|
30385
30582
|
}
|
|
30386
30583
|
}
|
|
30387
30584
|
return lines2.join("\n");
|
|
@@ -30414,11 +30611,11 @@ function rejectTimestampFilter(filter) {
|
|
|
30414
30611
|
}
|
|
30415
30612
|
|
|
30416
30613
|
// src/shared/resolveNamedConnection.ts
|
|
30417
|
-
import
|
|
30614
|
+
import chalk216 from "chalk";
|
|
30418
30615
|
function resolveNamedConnection(connections, requested, defaultName, kind, authCommand) {
|
|
30419
30616
|
if (connections.length === 0) {
|
|
30420
30617
|
console.error(
|
|
30421
|
-
|
|
30618
|
+
chalk216.red(
|
|
30422
30619
|
`No ${kind} connections configured. Run '${authCommand}' first.`
|
|
30423
30620
|
)
|
|
30424
30621
|
);
|
|
@@ -30427,7 +30624,7 @@ function resolveNamedConnection(connections, requested, defaultName, kind, authC
|
|
|
30427
30624
|
const target = requested ?? defaultName ?? connections[0].name;
|
|
30428
30625
|
const connection = connections.find((c) => c.name === target);
|
|
30429
30626
|
if (!connection) {
|
|
30430
|
-
console.error(
|
|
30627
|
+
console.error(chalk216.red(`${kind} connection "${target}" not found.`));
|
|
30431
30628
|
process.exit(1);
|
|
30432
30629
|
}
|
|
30433
30630
|
return connection;
|
|
@@ -30456,7 +30653,7 @@ async function seqQuery(filter, options2) {
|
|
|
30456
30653
|
new URLSearchParams({ filter, count: String(count8) })
|
|
30457
30654
|
);
|
|
30458
30655
|
if (events.length === 0) {
|
|
30459
|
-
console.log(
|
|
30656
|
+
console.log(chalk217.yellow("No events found."));
|
|
30460
30657
|
return;
|
|
30461
30658
|
}
|
|
30462
30659
|
if (options2.json) {
|
|
@@ -30467,11 +30664,11 @@ async function seqQuery(filter, options2) {
|
|
|
30467
30664
|
for (const event of chronological) {
|
|
30468
30665
|
console.log(formatEvent(event));
|
|
30469
30666
|
}
|
|
30470
|
-
console.log(
|
|
30667
|
+
console.log(chalk217.dim(`
|
|
30471
30668
|
${events.length} events`));
|
|
30472
30669
|
if (events.length >= count8) {
|
|
30473
30670
|
console.log(
|
|
30474
|
-
|
|
30671
|
+
chalk217.yellow(
|
|
30475
30672
|
`Results limited to ${count8}. Use --count to retrieve more.`
|
|
30476
30673
|
)
|
|
30477
30674
|
);
|
|
@@ -30479,10 +30676,10 @@ ${events.length} events`));
|
|
|
30479
30676
|
}
|
|
30480
30677
|
|
|
30481
30678
|
// src/shared/setNamedDefaultConnection.ts
|
|
30482
|
-
import
|
|
30679
|
+
import chalk218 from "chalk";
|
|
30483
30680
|
function setNamedDefaultConnection(connections, name, setDefault, kind) {
|
|
30484
30681
|
if (!connections.find((c) => c.name === name)) {
|
|
30485
|
-
console.error(
|
|
30682
|
+
console.error(chalk218.red(`Connection "${name}" not found.`));
|
|
30486
30683
|
process.exit(1);
|
|
30487
30684
|
}
|
|
30488
30685
|
setDefault(name);
|
|
@@ -30531,7 +30728,7 @@ function registerSignal(program2) {
|
|
|
30531
30728
|
}
|
|
30532
30729
|
|
|
30533
30730
|
// src/commands/sql/sqlAuth.ts
|
|
30534
|
-
import
|
|
30731
|
+
import chalk220 from "chalk";
|
|
30535
30732
|
|
|
30536
30733
|
// src/commands/sql/loadConnections.ts
|
|
30537
30734
|
function loadConnections3() {
|
|
@@ -30560,7 +30757,7 @@ function setDefaultConnection2(name) {
|
|
|
30560
30757
|
}
|
|
30561
30758
|
|
|
30562
30759
|
// src/commands/sql/promptConnection.ts
|
|
30563
|
-
import
|
|
30760
|
+
import chalk219 from "chalk";
|
|
30564
30761
|
async function promptConnection3(existingNames) {
|
|
30565
30762
|
const name = await promptInput("name", "Connection name:", "default");
|
|
30566
30763
|
assertUniqueName(existingNames, name);
|
|
@@ -30568,7 +30765,7 @@ async function promptConnection3(existingNames) {
|
|
|
30568
30765
|
const portStr = await promptInput("port", "Port:", "1433");
|
|
30569
30766
|
const port = Number.parseInt(portStr, 10);
|
|
30570
30767
|
if (!Number.isFinite(port)) {
|
|
30571
|
-
console.error(
|
|
30768
|
+
console.error(chalk219.red(`Invalid port "${portStr}".`));
|
|
30572
30769
|
process.exit(1);
|
|
30573
30770
|
}
|
|
30574
30771
|
const user = await promptInput("user", "User:");
|
|
@@ -30581,13 +30778,13 @@ async function promptConnection3(existingNames) {
|
|
|
30581
30778
|
var sqlAuth = createConnectionAuth({
|
|
30582
30779
|
load: loadConnections3,
|
|
30583
30780
|
save: saveConnections3,
|
|
30584
|
-
format: (c) => `${
|
|
30781
|
+
format: (c) => `${chalk220.bold(c.name)} ${c.server}:${c.port}/${c.database} (${c.user})`,
|
|
30585
30782
|
promptNew: promptConnection3,
|
|
30586
30783
|
onFirst: (c) => setDefaultConnection2(c.name)
|
|
30587
30784
|
});
|
|
30588
30785
|
|
|
30589
30786
|
// src/commands/sql/printTable.ts
|
|
30590
|
-
import
|
|
30787
|
+
import chalk221 from "chalk";
|
|
30591
30788
|
function formatCell(value) {
|
|
30592
30789
|
if (value === null || value === void 0) return "";
|
|
30593
30790
|
if (value instanceof Date) return value.toISOString();
|
|
@@ -30596,7 +30793,7 @@ function formatCell(value) {
|
|
|
30596
30793
|
}
|
|
30597
30794
|
function printTable(rows) {
|
|
30598
30795
|
if (rows.length === 0) {
|
|
30599
|
-
console.log(
|
|
30796
|
+
console.log(chalk221.yellow("(no rows)"));
|
|
30600
30797
|
return;
|
|
30601
30798
|
}
|
|
30602
30799
|
const columns = Object.keys(rows[0]);
|
|
@@ -30604,13 +30801,13 @@ function printTable(rows) {
|
|
|
30604
30801
|
(col) => Math.max(col.length, ...rows.map((r) => formatCell(r[col]).length))
|
|
30605
30802
|
);
|
|
30606
30803
|
const header = columns.map((c, i) => c.padEnd(widths[i])).join(" ");
|
|
30607
|
-
console.log(
|
|
30608
|
-
console.log(
|
|
30804
|
+
console.log(chalk221.dim(header));
|
|
30805
|
+
console.log(chalk221.dim("-".repeat(header.length)));
|
|
30609
30806
|
for (const row of rows) {
|
|
30610
30807
|
const line = columns.map((c, i) => formatCell(row[c]).padEnd(widths[i])).join(" ");
|
|
30611
30808
|
console.log(line);
|
|
30612
30809
|
}
|
|
30613
|
-
console.log(
|
|
30810
|
+
console.log(chalk221.dim(`
|
|
30614
30811
|
${rows.length} row${rows.length === 1 ? "" : "s"}`));
|
|
30615
30812
|
}
|
|
30616
30813
|
|
|
@@ -30670,7 +30867,7 @@ async function sqlColumns(table, connectionName) {
|
|
|
30670
30867
|
}
|
|
30671
30868
|
|
|
30672
30869
|
// src/commands/sql/sqlMutate.ts
|
|
30673
|
-
import
|
|
30870
|
+
import chalk222 from "chalk";
|
|
30674
30871
|
|
|
30675
30872
|
// src/commands/sql/isMutation.ts
|
|
30676
30873
|
var MUTATION_KEYWORDS = [
|
|
@@ -30704,7 +30901,7 @@ function isMutation(sql25) {
|
|
|
30704
30901
|
async function sqlMutate(query, connectionName) {
|
|
30705
30902
|
if (!isMutation(query)) {
|
|
30706
30903
|
console.error(
|
|
30707
|
-
|
|
30904
|
+
chalk222.red(
|
|
30708
30905
|
"assist sql mutate refuses non-mutating statements. Use `assist sql query` instead."
|
|
30709
30906
|
)
|
|
30710
30907
|
);
|
|
@@ -30714,18 +30911,18 @@ async function sqlMutate(query, connectionName) {
|
|
|
30714
30911
|
const pool = await sqlConnect(conn);
|
|
30715
30912
|
try {
|
|
30716
30913
|
const result = await pool.request().query(query);
|
|
30717
|
-
console.log(
|
|
30914
|
+
console.log(chalk222.dim(`${result.rowsAffected.join(", ")} row(s) affected`));
|
|
30718
30915
|
} finally {
|
|
30719
30916
|
await pool.close();
|
|
30720
30917
|
}
|
|
30721
30918
|
}
|
|
30722
30919
|
|
|
30723
30920
|
// src/commands/sql/sqlQuery.ts
|
|
30724
|
-
import
|
|
30921
|
+
import chalk223 from "chalk";
|
|
30725
30922
|
async function sqlQuery(query, connectionName) {
|
|
30726
30923
|
if (isMutation(query)) {
|
|
30727
30924
|
console.error(
|
|
30728
|
-
|
|
30925
|
+
chalk223.red(
|
|
30729
30926
|
"assist sql query refuses mutating statements. Use `assist sql mutate` instead."
|
|
30730
30927
|
)
|
|
30731
30928
|
);
|
|
@@ -30740,7 +30937,7 @@ async function sqlQuery(query, connectionName) {
|
|
|
30740
30937
|
printTable(rows);
|
|
30741
30938
|
} else {
|
|
30742
30939
|
console.log(
|
|
30743
|
-
|
|
30940
|
+
chalk223.dim(`${result.rowsAffected.join(", ")} row(s) affected`)
|
|
30744
30941
|
);
|
|
30745
30942
|
}
|
|
30746
30943
|
} finally {
|
|
@@ -30803,15 +31000,15 @@ function registerSql(program2) {
|
|
|
30803
31000
|
// src/commands/sync.ts
|
|
30804
31001
|
import * as fs48 from "fs";
|
|
30805
31002
|
import * as os5 from "os";
|
|
30806
|
-
import * as
|
|
31003
|
+
import * as path84 from "path";
|
|
30807
31004
|
import { fileURLToPath as fileURLToPath8 } from "url";
|
|
30808
31005
|
|
|
30809
31006
|
// src/commands/sync/pruneCommands.ts
|
|
30810
|
-
import * as
|
|
31007
|
+
import * as path75 from "path";
|
|
30811
31008
|
|
|
30812
31009
|
// src/commands/sync/pruneTarget.ts
|
|
30813
31010
|
import * as fs40 from "fs";
|
|
30814
|
-
import * as
|
|
31011
|
+
import * as path74 from "path";
|
|
30815
31012
|
function pruneTarget(targetDir, keepNames, shape, options2) {
|
|
30816
31013
|
const result = {
|
|
30817
31014
|
orphans: [],
|
|
@@ -30829,7 +31026,7 @@ function pruneTarget(targetDir, keepNames, shape, options2) {
|
|
|
30829
31026
|
}
|
|
30830
31027
|
if (keep.has(name)) continue;
|
|
30831
31028
|
result.orphans.push(entry.name);
|
|
30832
|
-
const entryPath =
|
|
31029
|
+
const entryPath = path74.join(targetDir, entry.name);
|
|
30833
31030
|
const reason4 = shape.blockedBy?.(entryPath);
|
|
30834
31031
|
if (reason4) {
|
|
30835
31032
|
result.skipped.push({ name: entry.name, reason: reason4 });
|
|
@@ -30849,7 +31046,7 @@ function pruneCommands(targetDir, commandNames, options2) {
|
|
|
30849
31046
|
targetDir,
|
|
30850
31047
|
commandNames,
|
|
30851
31048
|
{
|
|
30852
|
-
nameOf: (entry) => entry.isFile() && entry.name.endsWith(".md") ?
|
|
31049
|
+
nameOf: (entry) => entry.isFile() && entry.name.endsWith(".md") ? path75.basename(entry.name, ".md") : void 0
|
|
30853
31050
|
},
|
|
30854
31051
|
options2
|
|
30855
31052
|
);
|
|
@@ -30884,24 +31081,24 @@ function reportPrune(label2, result, force) {
|
|
|
30884
31081
|
|
|
30885
31082
|
// src/commands/sync/syncClaudeMd.ts
|
|
30886
31083
|
import * as fs41 from "fs";
|
|
30887
|
-
import * as
|
|
30888
|
-
import
|
|
31084
|
+
import * as path76 from "path";
|
|
31085
|
+
import chalk224 from "chalk";
|
|
30889
31086
|
async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
30890
|
-
const source =
|
|
30891
|
-
const target =
|
|
31087
|
+
const source = path76.join(claudeDir, "CLAUDE.md");
|
|
31088
|
+
const target = path76.join(targetBase, "CLAUDE.md");
|
|
30892
31089
|
const sourceContent = fs41.readFileSync(source, "utf8");
|
|
30893
31090
|
if (fs41.existsSync(target)) {
|
|
30894
31091
|
const targetContent = fs41.readFileSync(target, "utf8");
|
|
30895
31092
|
if (sourceContent !== targetContent) {
|
|
30896
31093
|
console.log(
|
|
30897
|
-
|
|
31094
|
+
chalk224.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
30898
31095
|
);
|
|
30899
31096
|
console.log();
|
|
30900
31097
|
printDiff(targetContent, sourceContent);
|
|
30901
31098
|
if (!options2?.yes) {
|
|
30902
31099
|
printAutoConfirmHint();
|
|
30903
31100
|
const confirm = await promptConfirm(
|
|
30904
|
-
|
|
31101
|
+
chalk224.red("Overwrite existing CLAUDE.md?"),
|
|
30905
31102
|
false
|
|
30906
31103
|
);
|
|
30907
31104
|
if (!confirm) {
|
|
@@ -30916,13 +31113,13 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
30916
31113
|
}
|
|
30917
31114
|
|
|
30918
31115
|
// src/commands/sync/syncCodex.ts
|
|
30919
|
-
import * as
|
|
31116
|
+
import * as path79 from "path";
|
|
30920
31117
|
|
|
30921
31118
|
// src/commands/sync/installHarnessCommands.ts
|
|
30922
31119
|
import * as fs42 from "fs";
|
|
30923
|
-
import * as
|
|
31120
|
+
import * as path77 from "path";
|
|
30924
31121
|
function installHarnessCommands(claudeDir, harness, transform) {
|
|
30925
|
-
const commandsSource =
|
|
31122
|
+
const commandsSource = path77.join(claudeDir, "commands");
|
|
30926
31123
|
const files = fs42.readdirSync(commandsSource);
|
|
30927
31124
|
const names = [];
|
|
30928
31125
|
let synced = 0;
|
|
@@ -30930,15 +31127,15 @@ function installHarnessCommands(claudeDir, harness, transform) {
|
|
|
30930
31127
|
if (!file.endsWith(".md")) continue;
|
|
30931
31128
|
const name = file.replace(/\.md$/, "");
|
|
30932
31129
|
names.push(name);
|
|
30933
|
-
const content = fs42.readFileSync(
|
|
30934
|
-
const target =
|
|
30935
|
-
fs42.mkdirSync(
|
|
31130
|
+
const content = fs42.readFileSync(path77.join(commandsSource, file), "utf8");
|
|
31131
|
+
const target = path77.join(harness.homeDir, harness.sync.commandDest(name));
|
|
31132
|
+
fs42.mkdirSync(path77.dirname(target), { recursive: true });
|
|
30936
31133
|
fs42.writeFileSync(target, transform(name, content));
|
|
30937
31134
|
synced++;
|
|
30938
31135
|
}
|
|
30939
|
-
const agentsTarget =
|
|
30940
|
-
fs42.mkdirSync(
|
|
30941
|
-
fs42.copyFileSync(
|
|
31136
|
+
const agentsTarget = path77.join(harness.homeDir, harness.sync.agentsFile);
|
|
31137
|
+
fs42.mkdirSync(path77.dirname(agentsTarget), { recursive: true });
|
|
31138
|
+
fs42.copyFileSync(path77.join(claudeDir, "CLAUDE.md"), agentsTarget);
|
|
30942
31139
|
return { total: files.length, synced, names };
|
|
30943
31140
|
}
|
|
30944
31141
|
|
|
@@ -30964,7 +31161,7 @@ function unexpectedContent(skillDir) {
|
|
|
30964
31161
|
|
|
30965
31162
|
// src/commands/sync/syncCodexHooks.ts
|
|
30966
31163
|
import * as fs44 from "fs";
|
|
30967
|
-
import * as
|
|
31164
|
+
import * as path78 from "path";
|
|
30968
31165
|
var BEGIN = "# >>> assist codex hooks (managed) \u2014 do not edit >>>";
|
|
30969
31166
|
var END = "# <<< assist codex hooks (managed) <<<";
|
|
30970
31167
|
function upsertManagedBlock(existing, body) {
|
|
@@ -30995,9 +31192,9 @@ ${rest}
|
|
|
30995
31192
|
}
|
|
30996
31193
|
function syncCodexHooks(sourcePath) {
|
|
30997
31194
|
const body = fs44.readFileSync(sourcePath, "utf8");
|
|
30998
|
-
const configPath =
|
|
31195
|
+
const configPath = path78.join(harnesses.codex.homeDir, "config.toml");
|
|
30999
31196
|
const existing = fs44.existsSync(configPath) ? fs44.readFileSync(configPath, "utf8") : "";
|
|
31000
|
-
fs44.mkdirSync(
|
|
31197
|
+
fs44.mkdirSync(path78.dirname(configPath), { recursive: true });
|
|
31001
31198
|
fs44.writeFileSync(configPath, upsertManagedBlock(existing, body));
|
|
31002
31199
|
console.log(
|
|
31003
31200
|
"Registered assist codex-hook in ~/.codex/config.toml (UserPromptSubmit, PreToolUse, PostToolUse, PermissionRequest, Stop)"
|
|
@@ -31029,7 +31226,7 @@ function syncCodex(claudeDir, options2) {
|
|
|
31029
31226
|
harnesses.codex,
|
|
31030
31227
|
commandToSkill
|
|
31031
31228
|
);
|
|
31032
|
-
syncCodexHooks(
|
|
31229
|
+
syncCodexHooks(path79.join(claudeDir, "..", "codex", "config.toml"));
|
|
31033
31230
|
console.log(
|
|
31034
31231
|
`Synced ${total} skill(s) to ~/.codex/skills and CLAUDE.md to ~/.codex/AGENTS.md`
|
|
31035
31232
|
);
|
|
@@ -31037,42 +31234,42 @@ function syncCodex(claudeDir, options2) {
|
|
|
31037
31234
|
const force = options2.force ?? false;
|
|
31038
31235
|
reportPrune(
|
|
31039
31236
|
"~/.codex/skills",
|
|
31040
|
-
pruneSkills(
|
|
31237
|
+
pruneSkills(path79.join(harnesses.codex.homeDir, "skills"), names, { force }),
|
|
31041
31238
|
force
|
|
31042
31239
|
);
|
|
31043
31240
|
}
|
|
31044
31241
|
|
|
31045
31242
|
// src/commands/sync/syncDesign.ts
|
|
31046
31243
|
import * as fs45 from "fs";
|
|
31047
|
-
import * as
|
|
31244
|
+
import * as path80 from "path";
|
|
31048
31245
|
function syncDesign(claudeDir, targetBase) {
|
|
31049
|
-
const systemPromptSource =
|
|
31050
|
-
const systemPromptTarget =
|
|
31246
|
+
const systemPromptSource = path80.join(claudeDir, "design-system-prompt.md");
|
|
31247
|
+
const systemPromptTarget = path80.join(targetBase, "design-system-prompt.md");
|
|
31051
31248
|
fs45.copyFileSync(systemPromptSource, systemPromptTarget);
|
|
31052
31249
|
console.log(
|
|
31053
31250
|
"Copied design-system-prompt.md to ~/.claude/design-system-prompt.md"
|
|
31054
31251
|
);
|
|
31055
|
-
const skillsSource =
|
|
31056
|
-
const skillsTarget =
|
|
31252
|
+
const skillsSource = path80.join(claudeDir, "skills");
|
|
31253
|
+
const skillsTarget = path80.join(targetBase, "skills");
|
|
31057
31254
|
fs45.mkdirSync(skillsTarget, { recursive: true });
|
|
31058
31255
|
const files = fs45.readdirSync(skillsSource);
|
|
31059
31256
|
for (const file of files) {
|
|
31060
31257
|
fs45.copyFileSync(
|
|
31061
|
-
|
|
31062
|
-
|
|
31258
|
+
path80.join(skillsSource, file),
|
|
31259
|
+
path80.join(skillsTarget, file)
|
|
31063
31260
|
);
|
|
31064
31261
|
}
|
|
31065
31262
|
console.log(`Synced ${files.length} design skill(s) to ~/.claude/skills`);
|
|
31066
31263
|
}
|
|
31067
31264
|
|
|
31068
31265
|
// src/commands/sync/syncPi.ts
|
|
31069
|
-
import * as
|
|
31266
|
+
import * as path82 from "path";
|
|
31070
31267
|
|
|
31071
31268
|
// src/commands/sync/syncPiHooks.ts
|
|
31072
31269
|
import * as fs46 from "fs";
|
|
31073
|
-
import * as
|
|
31270
|
+
import * as path81 from "path";
|
|
31074
31271
|
function piExtensionsDir() {
|
|
31075
|
-
return
|
|
31272
|
+
return path81.join(harnesses.pi.homeDir, "extensions");
|
|
31076
31273
|
}
|
|
31077
31274
|
function syncPiHooks(sourceDir) {
|
|
31078
31275
|
const target = piExtensionsDir();
|
|
@@ -31080,8 +31277,8 @@ function syncPiHooks(sourceDir) {
|
|
|
31080
31277
|
const files = fs46.readdirSync(sourceDir).filter((f) => f.endsWith(".ts"));
|
|
31081
31278
|
for (const file of files) {
|
|
31082
31279
|
fs46.copyFileSync(
|
|
31083
|
-
|
|
31084
|
-
|
|
31280
|
+
path81.join(sourceDir, file),
|
|
31281
|
+
path81.join(target, `assist-${file}`)
|
|
31085
31282
|
);
|
|
31086
31283
|
}
|
|
31087
31284
|
console.log(
|
|
@@ -31118,7 +31315,7 @@ function syncPi(claudeDir, options2) {
|
|
|
31118
31315
|
harnesses.pi,
|
|
31119
31316
|
commandToPrompt
|
|
31120
31317
|
);
|
|
31121
|
-
syncPiHooks(
|
|
31318
|
+
syncPiHooks(path82.join(claudeDir, "..", "pi"));
|
|
31122
31319
|
console.log(
|
|
31123
31320
|
`Synced ${synced} prompt(s) to ~/.pi/agent/prompts and CLAUDE.md to ~/.pi/agent/AGENTS.md`
|
|
31124
31321
|
);
|
|
@@ -31126,18 +31323,18 @@ function syncPi(claudeDir, options2) {
|
|
|
31126
31323
|
const force = options2.force ?? false;
|
|
31127
31324
|
reportPrune(
|
|
31128
31325
|
"~/.pi/agent/prompts",
|
|
31129
|
-
pruneCommands(
|
|
31326
|
+
pruneCommands(path82.join(harnesses.pi.homeDir, "prompts"), names, { force }),
|
|
31130
31327
|
force
|
|
31131
31328
|
);
|
|
31132
31329
|
}
|
|
31133
31330
|
|
|
31134
31331
|
// src/commands/sync/syncSettings.ts
|
|
31135
31332
|
import * as fs47 from "fs";
|
|
31136
|
-
import * as
|
|
31137
|
-
import
|
|
31333
|
+
import * as path83 from "path";
|
|
31334
|
+
import chalk225 from "chalk";
|
|
31138
31335
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
31139
|
-
const source =
|
|
31140
|
-
const target =
|
|
31336
|
+
const source = path83.join(claudeDir, "settings.json");
|
|
31337
|
+
const target = path83.join(targetBase, "settings.json");
|
|
31141
31338
|
const sourceContent = fs47.readFileSync(source, "utf8");
|
|
31142
31339
|
const sourceSettings = JSON.parse(sourceContent);
|
|
31143
31340
|
const targetExists = fs47.existsSync(target);
|
|
@@ -31153,7 +31350,7 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
31153
31350
|
if (mergedContent !== normalizedTarget) {
|
|
31154
31351
|
if (!options2?.yes) {
|
|
31155
31352
|
console.log(
|
|
31156
|
-
|
|
31353
|
+
chalk225.yellow(
|
|
31157
31354
|
"\n\u26A0\uFE0F Warning: settings.json differs from existing file"
|
|
31158
31355
|
)
|
|
31159
31356
|
);
|
|
@@ -31161,7 +31358,7 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
31161
31358
|
printDiff(targetContent, mergedContent);
|
|
31162
31359
|
printAutoConfirmHint();
|
|
31163
31360
|
const confirm = await promptConfirm(
|
|
31164
|
-
|
|
31361
|
+
chalk225.red("Overwrite existing settings.json?"),
|
|
31165
31362
|
false
|
|
31166
31363
|
);
|
|
31167
31364
|
if (!confirm) {
|
|
@@ -31177,13 +31374,13 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
31177
31374
|
|
|
31178
31375
|
// src/commands/sync.ts
|
|
31179
31376
|
var __filename4 = fileURLToPath8(import.meta.url);
|
|
31180
|
-
var __dirname5 =
|
|
31377
|
+
var __dirname5 = path84.dirname(__filename4);
|
|
31181
31378
|
async function sync(options2) {
|
|
31182
31379
|
const config = loadConfig();
|
|
31183
31380
|
const yes = options2?.yes ?? config.sync.autoConfirm;
|
|
31184
31381
|
const prune = { prune: options2?.prune, force: options2?.force };
|
|
31185
|
-
const claudeDir =
|
|
31186
|
-
const targetBase =
|
|
31382
|
+
const claudeDir = path84.join(__dirname5, "..", "claude");
|
|
31383
|
+
const targetBase = path84.join(os5.homedir(), ".claude");
|
|
31187
31384
|
const commandFiles = syncCommands(claudeDir, targetBase);
|
|
31188
31385
|
syncDesign(claudeDir, targetBase);
|
|
31189
31386
|
await syncSettings(claudeDir, targetBase, { yes });
|
|
@@ -31191,21 +31388,21 @@ async function sync(options2) {
|
|
|
31191
31388
|
syncCodex(claudeDir, prune);
|
|
31192
31389
|
syncPi(claudeDir, prune);
|
|
31193
31390
|
if (!options2?.prune) return;
|
|
31194
|
-
const commandNames = commandFiles.filter((file) => file.endsWith(".md")).map((file) =>
|
|
31391
|
+
const commandNames = commandFiles.filter((file) => file.endsWith(".md")).map((file) => path84.basename(file, ".md"));
|
|
31195
31392
|
const force = options2.force ?? false;
|
|
31196
31393
|
reportPrune(
|
|
31197
31394
|
"~/.claude/commands",
|
|
31198
|
-
pruneCommands(
|
|
31395
|
+
pruneCommands(path84.join(targetBase, "commands"), commandNames, { force }),
|
|
31199
31396
|
force
|
|
31200
31397
|
);
|
|
31201
31398
|
}
|
|
31202
31399
|
function syncCommands(claudeDir, targetBase) {
|
|
31203
|
-
const sourceDir =
|
|
31204
|
-
const targetDir =
|
|
31400
|
+
const sourceDir = path84.join(claudeDir, "commands");
|
|
31401
|
+
const targetDir = path84.join(targetBase, "commands");
|
|
31205
31402
|
fs48.mkdirSync(targetDir, { recursive: true });
|
|
31206
31403
|
const files = fs48.readdirSync(sourceDir);
|
|
31207
31404
|
for (const file of files) {
|
|
31208
|
-
fs48.copyFileSync(
|
|
31405
|
+
fs48.copyFileSync(path84.join(sourceDir, file), path84.join(targetDir, file));
|
|
31209
31406
|
console.log(`Copied ${file} to ${targetDir}`);
|
|
31210
31407
|
}
|
|
31211
31408
|
console.log(`Synced ${files.length} command(s) to ~/.claude/commands`);
|
|
@@ -31233,7 +31430,7 @@ function registerSync(program2) {
|
|
|
31233
31430
|
}
|
|
31234
31431
|
|
|
31235
31432
|
// src/commands/transcript/clean.ts
|
|
31236
|
-
import { existsSync as
|
|
31433
|
+
import { existsSync as existsSync71 } from "fs";
|
|
31237
31434
|
|
|
31238
31435
|
// src/commands/transcript/cleanText.ts
|
|
31239
31436
|
function cleanText(text18) {
|
|
@@ -31457,9 +31654,9 @@ function formatVtt(cues) {
|
|
|
31457
31654
|
}
|
|
31458
31655
|
|
|
31459
31656
|
// src/commands/transcript/convert/readCleanedCues.ts
|
|
31460
|
-
import { readFileSync as
|
|
31657
|
+
import { readFileSync as readFileSync55 } from "fs";
|
|
31461
31658
|
function readCleanedCues(inputPath) {
|
|
31462
|
-
return deduplicateCues(parseVtt(
|
|
31659
|
+
return deduplicateCues(parseVtt(readFileSync55(inputPath, "utf8")));
|
|
31463
31660
|
}
|
|
31464
31661
|
|
|
31465
31662
|
// src/commands/transcript/clean.ts
|
|
@@ -31478,7 +31675,7 @@ function clean(file, options2 = {}) {
|
|
|
31478
31675
|
);
|
|
31479
31676
|
process.exit(1);
|
|
31480
31677
|
}
|
|
31481
|
-
if (!
|
|
31678
|
+
if (!existsSync71(file)) {
|
|
31482
31679
|
console.error(`Error: VTT file not found: ${file}`);
|
|
31483
31680
|
process.exit(1);
|
|
31484
31681
|
}
|
|
@@ -31561,12 +31758,12 @@ async function configure() {
|
|
|
31561
31758
|
}
|
|
31562
31759
|
|
|
31563
31760
|
// src/commands/transcript/list.ts
|
|
31564
|
-
import { existsSync as
|
|
31761
|
+
import { existsSync as existsSync72, readdirSync as readdirSync20, statSync as statSync11 } from "fs";
|
|
31565
31762
|
import { join as join83 } from "path";
|
|
31566
31763
|
function list4() {
|
|
31567
31764
|
const { vttDir } = getTranscriptConfig();
|
|
31568
|
-
if (!
|
|
31569
|
-
for (const entry of
|
|
31765
|
+
if (!existsSync72(vttDir)) return;
|
|
31766
|
+
for (const entry of readdirSync20(vttDir)) {
|
|
31570
31767
|
if (!entry.endsWith(".vtt")) continue;
|
|
31571
31768
|
if (statSync11(join83(vttDir, entry)).isDirectory()) continue;
|
|
31572
31769
|
console.log(entry);
|
|
@@ -31574,7 +31771,7 @@ function list4() {
|
|
|
31574
31771
|
}
|
|
31575
31772
|
|
|
31576
31773
|
// src/commands/transcript/move.ts
|
|
31577
|
-
import { existsSync as
|
|
31774
|
+
import { existsSync as existsSync73, mkdirSync as mkdirSync27, renameSync as renameSync2, writeFileSync as writeFileSync45 } from "fs";
|
|
31578
31775
|
import { basename as basename21, join as join84 } from "path";
|
|
31579
31776
|
|
|
31580
31777
|
// src/commands/transcript/convertVttToMarkdown.ts
|
|
@@ -31598,7 +31795,7 @@ function move(file, options2) {
|
|
|
31598
31795
|
const { vttDir, transcriptsDir, summaryDir } = getTranscriptConfig();
|
|
31599
31796
|
const filename = basename21(file);
|
|
31600
31797
|
const sourcePath = join84(vttDir, filename);
|
|
31601
|
-
if (!
|
|
31798
|
+
if (!existsSync73(sourcePath)) {
|
|
31602
31799
|
console.error(`Error: VTT file not found: ${sourcePath}`);
|
|
31603
31800
|
process.exit(1);
|
|
31604
31801
|
}
|
|
@@ -31607,7 +31804,7 @@ function move(file, options2) {
|
|
|
31607
31804
|
const formattedDir = join84(transcriptsDir, client);
|
|
31608
31805
|
mkdirSync27(formattedDir, { recursive: true });
|
|
31609
31806
|
const formattedPath = join84(formattedDir, outputName);
|
|
31610
|
-
|
|
31807
|
+
writeFileSync45(formattedPath, convertVttToMarkdown(sourcePath), "utf8");
|
|
31611
31808
|
archiveRawVtt(vttDir, sourcePath, filename);
|
|
31612
31809
|
const summaryPath = join84(summaryDir, client, outputName);
|
|
31613
31810
|
console.log(`Formatted transcript: ${formattedPath}`);
|
|
@@ -31728,14 +31925,14 @@ function devices() {
|
|
|
31728
31925
|
}
|
|
31729
31926
|
|
|
31730
31927
|
// src/commands/voice/logs.ts
|
|
31731
|
-
import { existsSync as
|
|
31928
|
+
import { existsSync as existsSync74, readFileSync as readFileSync56 } from "fs";
|
|
31732
31929
|
function logs(options2) {
|
|
31733
|
-
if (!
|
|
31930
|
+
if (!existsSync74(voicePaths.log)) {
|
|
31734
31931
|
console.log("No voice log file found");
|
|
31735
31932
|
return;
|
|
31736
31933
|
}
|
|
31737
31934
|
const count8 = Number.parseInt(options2.lines ?? "150", 10);
|
|
31738
|
-
const content =
|
|
31935
|
+
const content = readFileSync56(voicePaths.log, "utf8").trim();
|
|
31739
31936
|
if (!content) {
|
|
31740
31937
|
console.log("Voice log is empty");
|
|
31741
31938
|
return;
|
|
@@ -31762,7 +31959,7 @@ import { join as join88 } from "path";
|
|
|
31762
31959
|
|
|
31763
31960
|
// src/commands/voice/checkLockFile.ts
|
|
31764
31961
|
import { execSync as execSync58 } from "child_process";
|
|
31765
|
-
import { existsSync as
|
|
31962
|
+
import { existsSync as existsSync75, mkdirSync as mkdirSync28, readFileSync as readFileSync57, writeFileSync as writeFileSync46 } from "fs";
|
|
31766
31963
|
import { join as join87 } from "path";
|
|
31767
31964
|
function isProcessAlive2(pid) {
|
|
31768
31965
|
try {
|
|
@@ -31774,9 +31971,9 @@ function isProcessAlive2(pid) {
|
|
|
31774
31971
|
}
|
|
31775
31972
|
function checkLockFile() {
|
|
31776
31973
|
const lockFile = getLockFile();
|
|
31777
|
-
if (!
|
|
31974
|
+
if (!existsSync75(lockFile)) return;
|
|
31778
31975
|
try {
|
|
31779
|
-
const lock2 = JSON.parse(
|
|
31976
|
+
const lock2 = JSON.parse(readFileSync57(lockFile, "utf8"));
|
|
31780
31977
|
if (lock2.pid && isProcessAlive2(lock2.pid)) {
|
|
31781
31978
|
console.error(
|
|
31782
31979
|
`Voice daemon already running (PID ${lock2.pid}, env: ${lock2.env}). Stop it first with: assist voice stop`
|
|
@@ -31787,7 +31984,7 @@ function checkLockFile() {
|
|
|
31787
31984
|
}
|
|
31788
31985
|
}
|
|
31789
31986
|
function bootstrapVenv() {
|
|
31790
|
-
if (
|
|
31987
|
+
if (existsSync75(getVenvPython())) return;
|
|
31791
31988
|
console.log("Setting up Python environment...");
|
|
31792
31989
|
const pythonDir = getPythonDir();
|
|
31793
31990
|
execSync58(
|
|
@@ -31801,7 +31998,7 @@ function bootstrapVenv() {
|
|
|
31801
31998
|
function writeLockFile(pid) {
|
|
31802
31999
|
const lockFile = getLockFile();
|
|
31803
32000
|
mkdirSync28(join87(lockFile, ".."), { recursive: true });
|
|
31804
|
-
|
|
32001
|
+
writeFileSync46(
|
|
31805
32002
|
lockFile,
|
|
31806
32003
|
JSON.stringify({
|
|
31807
32004
|
pid,
|
|
@@ -31829,7 +32026,7 @@ function setup() {
|
|
|
31829
32026
|
|
|
31830
32027
|
// src/commands/voice/start.ts
|
|
31831
32028
|
import { spawn as spawn8 } from "child_process";
|
|
31832
|
-
import { mkdirSync as mkdirSync30, writeFileSync as
|
|
32029
|
+
import { mkdirSync as mkdirSync30, writeFileSync as writeFileSync47 } from "fs";
|
|
31833
32030
|
import { join as join89 } from "path";
|
|
31834
32031
|
|
|
31835
32032
|
// src/commands/voice/buildDaemonEnv.ts
|
|
@@ -31858,7 +32055,7 @@ function spawnBackground(python, script, env) {
|
|
|
31858
32055
|
console.error("Failed to start voice daemon");
|
|
31859
32056
|
process.exit(1);
|
|
31860
32057
|
}
|
|
31861
|
-
|
|
32058
|
+
writeFileSync47(voicePaths.pid, String(pid));
|
|
31862
32059
|
writeLockFile(pid);
|
|
31863
32060
|
console.log(`Voice daemon started (PID ${pid})`);
|
|
31864
32061
|
}
|
|
@@ -31878,7 +32075,7 @@ function start2(options2) {
|
|
|
31878
32075
|
}
|
|
31879
32076
|
|
|
31880
32077
|
// src/commands/voice/status.ts
|
|
31881
|
-
import { existsSync as
|
|
32078
|
+
import { existsSync as existsSync76, readFileSync as readFileSync58 } from "fs";
|
|
31882
32079
|
function isProcessAlive3(pid) {
|
|
31883
32080
|
try {
|
|
31884
32081
|
process.kill(pid, 0);
|
|
@@ -31888,16 +32085,16 @@ function isProcessAlive3(pid) {
|
|
|
31888
32085
|
}
|
|
31889
32086
|
}
|
|
31890
32087
|
function readRecentLogs(count8) {
|
|
31891
|
-
if (!
|
|
31892
|
-
const lines2 =
|
|
32088
|
+
if (!existsSync76(voicePaths.log)) return [];
|
|
32089
|
+
const lines2 = readFileSync58(voicePaths.log, "utf8").trim().split("\n");
|
|
31893
32090
|
return lines2.slice(-count8);
|
|
31894
32091
|
}
|
|
31895
32092
|
function status2() {
|
|
31896
|
-
if (!
|
|
32093
|
+
if (!existsSync76(voicePaths.pid)) {
|
|
31897
32094
|
console.log("Voice daemon: not running (no PID file)");
|
|
31898
32095
|
return;
|
|
31899
32096
|
}
|
|
31900
|
-
const pid = Number.parseInt(
|
|
32097
|
+
const pid = Number.parseInt(readFileSync58(voicePaths.pid, "utf8").trim(), 10);
|
|
31901
32098
|
const alive = isProcessAlive3(pid);
|
|
31902
32099
|
console.log(`Voice daemon: ${alive ? "running" : "dead"} (PID ${pid})`);
|
|
31903
32100
|
const recent = readRecentLogs(5);
|
|
@@ -31916,13 +32113,13 @@ function status2() {
|
|
|
31916
32113
|
}
|
|
31917
32114
|
|
|
31918
32115
|
// src/commands/voice/stop.ts
|
|
31919
|
-
import { existsSync as
|
|
32116
|
+
import { existsSync as existsSync77, readFileSync as readFileSync59, unlinkSync as unlinkSync20 } from "fs";
|
|
31920
32117
|
function stop2() {
|
|
31921
|
-
if (!
|
|
32118
|
+
if (!existsSync77(voicePaths.pid)) {
|
|
31922
32119
|
console.log("Voice daemon is not running (no PID file)");
|
|
31923
32120
|
return;
|
|
31924
32121
|
}
|
|
31925
|
-
const pid = Number.parseInt(
|
|
32122
|
+
const pid = Number.parseInt(readFileSync59(voicePaths.pid, "utf8").trim(), 10);
|
|
31926
32123
|
try {
|
|
31927
32124
|
process.kill(pid, "SIGTERM");
|
|
31928
32125
|
console.log(`Sent SIGTERM to voice daemon (PID ${pid})`);
|
|
@@ -31935,7 +32132,7 @@ function stop2() {
|
|
|
31935
32132
|
}
|
|
31936
32133
|
try {
|
|
31937
32134
|
const lockFile = getLockFile();
|
|
31938
|
-
if (
|
|
32135
|
+
if (existsSync77(lockFile)) unlinkSync20(lockFile);
|
|
31939
32136
|
} catch {
|
|
31940
32137
|
}
|
|
31941
32138
|
console.log("Voice daemon stopped");
|
|
@@ -32060,11 +32257,11 @@ var webUiPrefix = "src/commands/sessions/web/ui/";
|
|
|
32060
32257
|
var sessionsPrefix = "src/commands/sessions/";
|
|
32061
32258
|
var rules = [
|
|
32062
32259
|
{
|
|
32063
|
-
matches: (
|
|
32260
|
+
matches: (path90) => path90.startsWith(webUiPrefix),
|
|
32064
32261
|
advice: "restart the web server, then hard-reload the browser tab"
|
|
32065
32262
|
},
|
|
32066
32263
|
{
|
|
32067
|
-
matches: (
|
|
32264
|
+
matches: (path90) => path90.startsWith(sessionsPrefix) && !path90.startsWith(webUiPrefix),
|
|
32068
32265
|
advice: "restart the daemon"
|
|
32069
32266
|
}
|
|
32070
32267
|
];
|
|
@@ -32075,31 +32272,31 @@ function restartAdvice(paths) {
|
|
|
32075
32272
|
// src/commands/watch/syncAdvice.ts
|
|
32076
32273
|
var rules2 = [
|
|
32077
32274
|
{
|
|
32078
|
-
matches: (
|
|
32275
|
+
matches: (path90) => path90.startsWith("claude/commands/"),
|
|
32079
32276
|
reason: "claude/commands changed"
|
|
32080
32277
|
},
|
|
32081
32278
|
{
|
|
32082
|
-
matches: (
|
|
32279
|
+
matches: (path90) => path90.startsWith("claude/skills/"),
|
|
32083
32280
|
reason: "claude/skills changed"
|
|
32084
32281
|
},
|
|
32085
32282
|
{
|
|
32086
|
-
matches: (
|
|
32283
|
+
matches: (path90) => path90 === "claude/settings.json",
|
|
32087
32284
|
reason: "claude/settings.json changed"
|
|
32088
32285
|
},
|
|
32089
32286
|
{
|
|
32090
|
-
matches: (
|
|
32287
|
+
matches: (path90) => path90 === "claude/CLAUDE.md",
|
|
32091
32288
|
reason: "claude/CLAUDE.md changed"
|
|
32092
32289
|
},
|
|
32093
32290
|
{
|
|
32094
|
-
matches: (
|
|
32291
|
+
matches: (path90) => path90 === "claude/design-system-prompt.md",
|
|
32095
32292
|
reason: "claude/design-system-prompt.md changed"
|
|
32096
32293
|
},
|
|
32097
32294
|
{
|
|
32098
|
-
matches: (
|
|
32295
|
+
matches: (path90) => path90.startsWith("codex/"),
|
|
32099
32296
|
reason: "codex sources changed"
|
|
32100
32297
|
},
|
|
32101
32298
|
{
|
|
32102
|
-
matches: (
|
|
32299
|
+
matches: (path90) => path90.startsWith("pi/"),
|
|
32103
32300
|
reason: "pi sources changed"
|
|
32104
32301
|
}
|
|
32105
32302
|
];
|
|
@@ -32340,7 +32537,7 @@ function resolveParams(params, cliArgs) {
|
|
|
32340
32537
|
}
|
|
32341
32538
|
|
|
32342
32539
|
// src/commands/run/resolveRunCwd.ts
|
|
32343
|
-
import { existsSync as
|
|
32540
|
+
import { existsSync as existsSync78 } from "fs";
|
|
32344
32541
|
import { resolve as resolve19 } from "path";
|
|
32345
32542
|
var MissingRunCwdError = class extends Error {
|
|
32346
32543
|
constructor(runName, cwd) {
|
|
@@ -32353,17 +32550,17 @@ var MissingRunCwdError = class extends Error {
|
|
|
32353
32550
|
function resolveRunCwd(config, baseDir = runConfigBaseDir()) {
|
|
32354
32551
|
if (!config.cwd) return void 0;
|
|
32355
32552
|
const cwd = resolve19(baseDir, config.cwd);
|
|
32356
|
-
if (!
|
|
32553
|
+
if (!existsSync78(cwd)) throw new MissingRunCwdError(config.name, cwd);
|
|
32357
32554
|
return cwd;
|
|
32358
32555
|
}
|
|
32359
32556
|
|
|
32360
32557
|
// src/commands/run/runCommandToCompletion.ts
|
|
32361
32558
|
import { spawn as spawn9 } from "child_process";
|
|
32362
|
-
import { existsSync as
|
|
32559
|
+
import { existsSync as existsSync80 } from "fs";
|
|
32363
32560
|
|
|
32364
32561
|
// src/commands/run/resolveCommand.ts
|
|
32365
32562
|
import { execFileSync as execFileSync16 } from "child_process";
|
|
32366
|
-
import { existsSync as
|
|
32563
|
+
import { existsSync as existsSync79 } from "fs";
|
|
32367
32564
|
import { dirname as dirname37, join as join91, resolve as resolve20 } from "path";
|
|
32368
32565
|
function resolveCommand2(command) {
|
|
32369
32566
|
if (process.platform !== "win32" || command !== "bash") return command;
|
|
@@ -32371,7 +32568,7 @@ function resolveCommand2(command) {
|
|
|
32371
32568
|
const gitPath = execFileSync16("where", ["git"], { encoding: "utf8" }).trim().split("\r\n")[0];
|
|
32372
32569
|
const gitRoot = resolve20(dirname37(gitPath), "..");
|
|
32373
32570
|
const gitBash = join91(gitRoot, "bin", "bash.exe");
|
|
32374
|
-
if (
|
|
32571
|
+
if (existsSync79(gitBash)) return gitBash;
|
|
32375
32572
|
} catch {
|
|
32376
32573
|
return command;
|
|
32377
32574
|
}
|
|
@@ -32381,7 +32578,7 @@ function resolveCommand2(command) {
|
|
|
32381
32578
|
// src/commands/run/runCommandToCompletion.ts
|
|
32382
32579
|
function runCommandToCompletion(command, args, env, cwd, quiet) {
|
|
32383
32580
|
return new Promise((resolveResult) => {
|
|
32384
|
-
if (cwd && !
|
|
32581
|
+
if (cwd && !existsSync80(cwd)) {
|
|
32385
32582
|
resolveResult({
|
|
32386
32583
|
kind: "failed",
|
|
32387
32584
|
message: `Failed to execute command: cwd ${cwd} does not exist`
|
|
@@ -32638,7 +32835,7 @@ function registerWatch(program2) {
|
|
|
32638
32835
|
|
|
32639
32836
|
// src/commands/roam/auth.ts
|
|
32640
32837
|
import { randomBytes } from "crypto";
|
|
32641
|
-
import
|
|
32838
|
+
import chalk226 from "chalk";
|
|
32642
32839
|
|
|
32643
32840
|
// src/commands/roam/waitForCallback.ts
|
|
32644
32841
|
import { createServer as createServer3 } from "http";
|
|
@@ -32769,13 +32966,13 @@ async function auth() {
|
|
|
32769
32966
|
saveGlobalConfig(config);
|
|
32770
32967
|
const state = randomBytes(16).toString("hex");
|
|
32771
32968
|
console.log(
|
|
32772
|
-
|
|
32969
|
+
chalk226.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
|
|
32773
32970
|
);
|
|
32774
|
-
console.log(
|
|
32775
|
-
console.log(
|
|
32776
|
-
console.log(
|
|
32971
|
+
console.log(chalk226.white("http://localhost:14523/callback\n"));
|
|
32972
|
+
console.log(chalk226.blue("Opening browser for authorization..."));
|
|
32973
|
+
console.log(chalk226.dim("Waiting for authorization callback..."));
|
|
32777
32974
|
const { code, redirectUri } = await authorizeInBrowser(clientId, state);
|
|
32778
|
-
console.log(
|
|
32975
|
+
console.log(chalk226.dim("Exchanging code for tokens..."));
|
|
32779
32976
|
const tokens = await exchangeToken({
|
|
32780
32977
|
code,
|
|
32781
32978
|
clientId,
|
|
@@ -32791,25 +32988,25 @@ async function auth() {
|
|
|
32791
32988
|
};
|
|
32792
32989
|
saveGlobalConfig(config);
|
|
32793
32990
|
console.log(
|
|
32794
|
-
|
|
32991
|
+
chalk226.green("Roam credentials and tokens saved to ~/.assist.yml")
|
|
32795
32992
|
);
|
|
32796
32993
|
}
|
|
32797
32994
|
|
|
32798
32995
|
// src/commands/roam/postRoamActivity.ts
|
|
32799
32996
|
import { execFileSync as execFileSync18 } from "child_process";
|
|
32800
|
-
import { readdirSync as
|
|
32997
|
+
import { readdirSync as readdirSync21, readFileSync as readFileSync60, statSync as statSync12 } from "fs";
|
|
32801
32998
|
import { join as join92 } from "path";
|
|
32802
32999
|
function findPortFile(roamDir) {
|
|
32803
33000
|
let entries;
|
|
32804
33001
|
try {
|
|
32805
|
-
entries =
|
|
33002
|
+
entries = readdirSync21(roamDir);
|
|
32806
33003
|
} catch {
|
|
32807
33004
|
return void 0;
|
|
32808
33005
|
}
|
|
32809
33006
|
const candidates = entries.filter((name) => /^roam-local-api(-[^.]+)?\.port$/.test(name)).map((name) => {
|
|
32810
|
-
const
|
|
33007
|
+
const path90 = join92(roamDir, name);
|
|
32811
33008
|
try {
|
|
32812
|
-
return { path:
|
|
33009
|
+
return { path: path90, mtimeMs: statSync12(path90).mtimeMs };
|
|
32813
33010
|
} catch {
|
|
32814
33011
|
return void 0;
|
|
32815
33012
|
}
|
|
@@ -32823,7 +33020,7 @@ function postRoamActivity(app, event) {
|
|
|
32823
33020
|
if (!portFile) return;
|
|
32824
33021
|
let port;
|
|
32825
33022
|
try {
|
|
32826
|
-
port =
|
|
33023
|
+
port = readFileSync60(portFile, "utf8").trim();
|
|
32827
33024
|
} catch {
|
|
32828
33025
|
return;
|
|
32829
33026
|
}
|
|
@@ -32951,7 +33148,7 @@ async function run3(name, args) {
|
|
|
32951
33148
|
}
|
|
32952
33149
|
|
|
32953
33150
|
// src/commands/run/add.ts
|
|
32954
|
-
import { mkdirSync as mkdirSync31, writeFileSync as
|
|
33151
|
+
import { mkdirSync as mkdirSync31, writeFileSync as writeFileSync48 } from "fs";
|
|
32955
33152
|
import { join as join93 } from "path";
|
|
32956
33153
|
|
|
32957
33154
|
// src/commands/run/extractOption.ts
|
|
@@ -33022,7 +33219,7 @@ description: Run ${name}
|
|
|
33022
33219
|
Run \`assist run ${name} $ARGUMENTS 2>&1\`.
|
|
33023
33220
|
`;
|
|
33024
33221
|
const filePath = join93(dir, `${name}.md`);
|
|
33025
|
-
|
|
33222
|
+
writeFileSync48(filePath, content);
|
|
33026
33223
|
console.log(`Created command file: ${filePath}`);
|
|
33027
33224
|
}
|
|
33028
33225
|
function add3() {
|
|
@@ -33045,11 +33242,11 @@ function findLinkIndex() {
|
|
|
33045
33242
|
function parseLinkArgs() {
|
|
33046
33243
|
const idx = findLinkIndex();
|
|
33047
33244
|
if (idx === -1) return null;
|
|
33048
|
-
const
|
|
33245
|
+
const path90 = process.argv[idx + 1];
|
|
33049
33246
|
const rest = process.argv.slice(idx + 2);
|
|
33050
33247
|
const { value: prefix2 } = extractOption(rest, "--prefix");
|
|
33051
33248
|
if (!prefix2) return null;
|
|
33052
|
-
return { path:
|
|
33249
|
+
return { path: path90, prefix: prefix2 };
|
|
33053
33250
|
}
|
|
33054
33251
|
function hasDuplicateLink(runList, linkPath) {
|
|
33055
33252
|
return runList.some(
|
|
@@ -33077,7 +33274,7 @@ function link2() {
|
|
|
33077
33274
|
}
|
|
33078
33275
|
|
|
33079
33276
|
// src/commands/run/remove.ts
|
|
33080
|
-
import { existsSync as
|
|
33277
|
+
import { existsSync as existsSync81, unlinkSync as unlinkSync21 } from "fs";
|
|
33081
33278
|
import { join as join94 } from "path";
|
|
33082
33279
|
function findRemoveIndex() {
|
|
33083
33280
|
const idx = process.argv.indexOf("remove");
|
|
@@ -33094,7 +33291,7 @@ function parseRemoveName() {
|
|
|
33094
33291
|
}
|
|
33095
33292
|
function deleteCommandFile(name) {
|
|
33096
33293
|
const filePath = join94(".claude", "commands", `${name}.md`);
|
|
33097
|
-
if (
|
|
33294
|
+
if (existsSync81(filePath)) {
|
|
33098
33295
|
unlinkSync21(filePath);
|
|
33099
33296
|
console.log(`Deleted command file: ${filePath}`);
|
|
33100
33297
|
}
|
|
@@ -33139,10 +33336,10 @@ function registerRun(program2) {
|
|
|
33139
33336
|
|
|
33140
33337
|
// src/commands/screenshot/index.ts
|
|
33141
33338
|
import { execSync as execSync60 } from "child_process";
|
|
33142
|
-
import { existsSync as
|
|
33339
|
+
import { existsSync as existsSync82, mkdirSync as mkdirSync32, unlinkSync as unlinkSync22, writeFileSync as writeFileSync49 } from "fs";
|
|
33143
33340
|
import { tmpdir as tmpdir9 } from "os";
|
|
33144
33341
|
import { join as join95, resolve as resolve21 } from "path";
|
|
33145
|
-
import
|
|
33342
|
+
import chalk227 from "chalk";
|
|
33146
33343
|
|
|
33147
33344
|
// src/commands/screenshot/captureWindowPs1.ts
|
|
33148
33345
|
var captureWindowPs1 = `
|
|
@@ -33271,7 +33468,7 @@ Write-Output $OutputPath
|
|
|
33271
33468
|
|
|
33272
33469
|
// src/commands/screenshot/index.ts
|
|
33273
33470
|
function buildOutputPath(outputDir, processName) {
|
|
33274
|
-
if (!
|
|
33471
|
+
if (!existsSync82(outputDir)) {
|
|
33275
33472
|
mkdirSync32(outputDir, { recursive: true });
|
|
33276
33473
|
}
|
|
33277
33474
|
const timestamp6 = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
@@ -33279,7 +33476,7 @@ function buildOutputPath(outputDir, processName) {
|
|
|
33279
33476
|
}
|
|
33280
33477
|
function runPowerShellScript(processName, outputPath) {
|
|
33281
33478
|
const scriptPath = join95(tmpdir9(), `assist-screenshot-${Date.now()}.ps1`);
|
|
33282
|
-
|
|
33479
|
+
writeFileSync49(scriptPath, captureWindowPs1, "utf8");
|
|
33283
33480
|
try {
|
|
33284
33481
|
execSync60(
|
|
33285
33482
|
`powershell -NoProfile -ExecutionPolicy Bypass -File "${scriptPath}" -ProcessName "${processName}" -OutputPath "${outputPath}"`,
|
|
@@ -33293,13 +33490,13 @@ function screenshot(processName) {
|
|
|
33293
33490
|
const config = loadConfig();
|
|
33294
33491
|
const outputDir = resolve21(config.screenshot.outputDir);
|
|
33295
33492
|
const outputPath = buildOutputPath(outputDir, processName);
|
|
33296
|
-
console.log(
|
|
33493
|
+
console.log(chalk227.gray(`Capturing window for process "${processName}" ...`));
|
|
33297
33494
|
try {
|
|
33298
33495
|
runPowerShellScript(processName, outputPath);
|
|
33299
|
-
console.log(
|
|
33496
|
+
console.log(chalk227.green(`Screenshot saved: ${outputPath}`));
|
|
33300
33497
|
} catch (error) {
|
|
33301
33498
|
const msg = error instanceof Error ? error.message : String(error);
|
|
33302
|
-
console.error(
|
|
33499
|
+
console.error(chalk227.red(`Failed to capture screenshot: ${msg}`));
|
|
33303
33500
|
process.exit(1);
|
|
33304
33501
|
}
|
|
33305
33502
|
}
|
|
@@ -33355,11 +33552,11 @@ function applyLine(result, pending, line) {
|
|
|
33355
33552
|
}
|
|
33356
33553
|
|
|
33357
33554
|
// src/commands/sessions/daemon/readDaemonPidFile.ts
|
|
33358
|
-
import { readFileSync as
|
|
33555
|
+
import { readFileSync as readFileSync61 } from "fs";
|
|
33359
33556
|
function readDaemonPidFile() {
|
|
33360
33557
|
try {
|
|
33361
33558
|
const pid = Number.parseInt(
|
|
33362
|
-
|
|
33559
|
+
readFileSync61(daemonPaths.pid, "utf8").trim(),
|
|
33363
33560
|
10
|
|
33364
33561
|
);
|
|
33365
33562
|
return Number.isInteger(pid) ? pid : void 0;
|
|
@@ -33616,12 +33813,12 @@ function toSessionRunInfo({
|
|
|
33616
33813
|
}
|
|
33617
33814
|
|
|
33618
33815
|
// src/commands/sessions/daemon/worktree/joinRefusal.ts
|
|
33619
|
-
import { existsSync as
|
|
33816
|
+
import { existsSync as existsSync83 } from "fs";
|
|
33620
33817
|
function joinRefusal(session) {
|
|
33621
33818
|
if (session.commandType === "run") return "a server run has no agent stream";
|
|
33622
33819
|
if (session.closing === true) return "the session is closing";
|
|
33623
33820
|
if (!session.cwd) return "the session has no working directory";
|
|
33624
|
-
if (!
|
|
33821
|
+
if (!existsSync83(session.cwd))
|
|
33625
33822
|
return "the session's workspace no longer exists";
|
|
33626
33823
|
return void 0;
|
|
33627
33824
|
}
|
|
@@ -33785,26 +33982,26 @@ function sessionBase(id, status3) {
|
|
|
33785
33982
|
}
|
|
33786
33983
|
|
|
33787
33984
|
// src/commands/sessions/daemon/spawnPty.ts
|
|
33788
|
-
import { existsSync as
|
|
33985
|
+
import { existsSync as existsSync85 } from "fs";
|
|
33789
33986
|
import * as pty from "node-pty";
|
|
33790
33987
|
|
|
33791
33988
|
// src/commands/sessions/daemon/ensureSpawnHelperExecutable.ts
|
|
33792
|
-
import { chmodSync, existsSync as
|
|
33989
|
+
import { chmodSync, existsSync as existsSync84, statSync as statSync13 } from "fs";
|
|
33793
33990
|
import { createRequire as createRequire3 } from "module";
|
|
33794
|
-
import
|
|
33991
|
+
import path85 from "path";
|
|
33795
33992
|
var require4 = createRequire3(import.meta.url);
|
|
33796
33993
|
var ensured = false;
|
|
33797
33994
|
function ensureSpawnHelperExecutable() {
|
|
33798
33995
|
if (ensured || process.platform !== "darwin") return;
|
|
33799
33996
|
ensured = true;
|
|
33800
|
-
const ptyRoot =
|
|
33801
|
-
const helper =
|
|
33997
|
+
const ptyRoot = path85.join(path85.dirname(require4.resolve("node-pty")), "..");
|
|
33998
|
+
const helper = path85.join(
|
|
33802
33999
|
ptyRoot,
|
|
33803
34000
|
"prebuilds",
|
|
33804
34001
|
`${process.platform}-${process.arch}`,
|
|
33805
34002
|
"spawn-helper"
|
|
33806
34003
|
);
|
|
33807
|
-
if (!
|
|
34004
|
+
if (!existsSync84(helper)) return;
|
|
33808
34005
|
const mode = statSync13(helper).mode;
|
|
33809
34006
|
if ((mode & 73) === 0) chmodSync(helper, mode | 493);
|
|
33810
34007
|
}
|
|
@@ -33840,7 +34037,7 @@ function spawnPty(args, cwd, sessionId, extraEnv) {
|
|
|
33840
34037
|
});
|
|
33841
34038
|
}
|
|
33842
34039
|
function refuseMissingCwd(cwd, sessionId) {
|
|
33843
|
-
if (!cwd ||
|
|
34040
|
+
if (!cwd || existsSync85(cwd)) return;
|
|
33844
34041
|
daemonLog(
|
|
33845
34042
|
`${sessionId ? `session ${sessionId}` : "pty"} not spawned: working directory ${cwd} no longer exists`
|
|
33846
34043
|
);
|
|
@@ -33919,12 +34116,12 @@ function serverRunMeta(runName, cwd) {
|
|
|
33919
34116
|
|
|
33920
34117
|
// src/commands/sessions/daemon/readDesignSystemPrompt.ts
|
|
33921
34118
|
import * as fs49 from "fs";
|
|
33922
|
-
import * as
|
|
34119
|
+
import * as path86 from "path";
|
|
33923
34120
|
import { fileURLToPath as fileURLToPath10 } from "url";
|
|
33924
34121
|
var __filename5 = fileURLToPath10(import.meta.url);
|
|
33925
|
-
var __dirname7 =
|
|
34122
|
+
var __dirname7 = path86.dirname(__filename5);
|
|
33926
34123
|
function readDesignSystemPrompt() {
|
|
33927
|
-
const promptPath =
|
|
34124
|
+
const promptPath = path86.join(
|
|
33928
34125
|
__dirname7,
|
|
33929
34126
|
"..",
|
|
33930
34127
|
"claude",
|
|
@@ -34022,11 +34219,11 @@ function setStatus2(session, newStatus) {
|
|
|
34022
34219
|
}
|
|
34023
34220
|
|
|
34024
34221
|
// src/commands/sessions/daemon/worktree/reapWorktree.ts
|
|
34025
|
-
import { existsSync as
|
|
34222
|
+
import { existsSync as existsSync87 } from "fs";
|
|
34026
34223
|
import { basename as basename22 } from "path";
|
|
34027
34224
|
|
|
34028
34225
|
// src/commands/sessions/daemon/worktree/deleteStrandedTree.ts
|
|
34029
|
-
import { existsSync as
|
|
34226
|
+
import { existsSync as existsSync86 } from "fs";
|
|
34030
34227
|
import { join as join98 } from "path";
|
|
34031
34228
|
|
|
34032
34229
|
// src/commands/sessions/daemon/worktree/deleteTreeDirectly.ts
|
|
@@ -34096,7 +34293,7 @@ async function deleteStrandedTree(clone, worktreePath, cause) {
|
|
|
34096
34293
|
);
|
|
34097
34294
|
}
|
|
34098
34295
|
function strandedReason(worktreePath, cause) {
|
|
34099
|
-
if (!
|
|
34296
|
+
if (!existsSync86(join98(worktreePath, ".git")))
|
|
34100
34297
|
return "its .git link is already gone";
|
|
34101
34298
|
if (/not a working tree|not a git repository/i.test(reason2(cause)))
|
|
34102
34299
|
return "git no longer recognises it as a working tree";
|
|
@@ -34148,7 +34345,7 @@ function reason3(error) {
|
|
|
34148
34345
|
|
|
34149
34346
|
// src/commands/sessions/daemon/worktree/reapWorktree.ts
|
|
34150
34347
|
async function reapWorktree(worktreePath, force = false) {
|
|
34151
|
-
if (!
|
|
34348
|
+
if (!existsSync87(worktreePath)) {
|
|
34152
34349
|
forgetWorktree(worktreePath);
|
|
34153
34350
|
daemonLog(
|
|
34154
34351
|
`worktree ${worktreePath} already gone; its record was forgotten`
|
|
@@ -34173,7 +34370,7 @@ async function reapWorktree(worktreePath, force = false) {
|
|
|
34173
34370
|
}
|
|
34174
34371
|
function owningClone(worktreePath) {
|
|
34175
34372
|
const recorded = worktreeAttributionIncludingReaped(worktreePath)?.clone;
|
|
34176
|
-
if (recorded &&
|
|
34373
|
+
if (recorded && existsSync87(recorded)) return recorded;
|
|
34177
34374
|
const detected = mainWorktree(worktreePath);
|
|
34178
34375
|
if (detected) return detected;
|
|
34179
34376
|
daemonLog(
|
|
@@ -34304,12 +34501,12 @@ function closeGateApplies(sessions, session) {
|
|
|
34304
34501
|
}
|
|
34305
34502
|
|
|
34306
34503
|
// src/commands/sessions/daemon/worktree/watchGitState.ts
|
|
34307
|
-
import { existsSync as
|
|
34504
|
+
import { existsSync as existsSync88, watch } from "fs";
|
|
34308
34505
|
var DEBOUNCE_MS = 500;
|
|
34309
34506
|
var POLL_MS = 3e4;
|
|
34310
34507
|
function watchGitState(cwd, onChange) {
|
|
34311
34508
|
const common = gitCommonDir(cwd);
|
|
34312
|
-
if (!common || !
|
|
34509
|
+
if (!common || !existsSync88(common)) return void 0;
|
|
34313
34510
|
const watchers = [
|
|
34314
34511
|
watchGitDir(common, onChange),
|
|
34315
34512
|
pollGitState(cwd, onChange)
|
|
@@ -34786,10 +34983,10 @@ function emitSessionOutput(session, clients, data) {
|
|
|
34786
34983
|
}
|
|
34787
34984
|
|
|
34788
34985
|
// src/commands/sessions/daemon/exitReason.ts
|
|
34789
|
-
import { existsSync as
|
|
34986
|
+
import { existsSync as existsSync89 } from "fs";
|
|
34790
34987
|
import { resolve as resolve22 } from "path";
|
|
34791
34988
|
function exitDetail(session) {
|
|
34792
|
-
if (session.cwd && !
|
|
34989
|
+
if (session.cwd && !existsSync89(session.cwd))
|
|
34793
34990
|
return `working directory ${session.cwd} no longer exists`;
|
|
34794
34991
|
return missingRunConfigCwd(session);
|
|
34795
34992
|
}
|
|
@@ -34803,7 +35000,7 @@ function missingRunConfigCwd(session) {
|
|
|
34803
35000
|
const config = resolveRunConfig(session.runName, dir);
|
|
34804
35001
|
if (!config?.cwd) return void 0;
|
|
34805
35002
|
const configured = resolve22(runConfigBaseDirFrom(dir), config.cwd);
|
|
34806
|
-
if (
|
|
35003
|
+
if (existsSync89(configured)) return void 0;
|
|
34807
35004
|
return `run config "${config.name}": cwd ${configured} does not exist`;
|
|
34808
35005
|
}
|
|
34809
35006
|
|
|
@@ -34844,7 +35041,7 @@ function handleFailedResume(session, exitCode, onStatusChange) {
|
|
|
34844
35041
|
}
|
|
34845
35042
|
|
|
34846
35043
|
// src/commands/sessions/daemon/watchActivity.ts
|
|
34847
|
-
import { existsSync as
|
|
35044
|
+
import { existsSync as existsSync90, mkdirSync as mkdirSync33, watch as watch2 } from "fs";
|
|
34848
35045
|
import { dirname as dirname39 } from "path";
|
|
34849
35046
|
|
|
34850
35047
|
// src/commands/sessions/daemon/applyActivityToSession.ts
|
|
@@ -34906,8 +35103,8 @@ async function seedRunningMsFromUsage(session, notify2) {
|
|
|
34906
35103
|
var DEBOUNCE_MS2 = 50;
|
|
34907
35104
|
function watchActivity(session, notify2, onClaudeSessionId) {
|
|
34908
35105
|
if (session.commandType !== "assist" || !session.cwd) return;
|
|
34909
|
-
const
|
|
34910
|
-
const dir = dirname39(
|
|
35106
|
+
const path90 = activityPath(session.id);
|
|
35107
|
+
const dir = dirname39(path90);
|
|
34911
35108
|
try {
|
|
34912
35109
|
mkdirSync33(dir, { recursive: true });
|
|
34913
35110
|
} catch {
|
|
@@ -34915,9 +35112,9 @@ function watchActivity(session, notify2, onClaudeSessionId) {
|
|
|
34915
35112
|
}
|
|
34916
35113
|
reconcileActivity(session.id, session.activity);
|
|
34917
35114
|
let timer = null;
|
|
34918
|
-
const
|
|
35115
|
+
const read3 = () => {
|
|
34919
35116
|
timer = null;
|
|
34920
|
-
const activity2 = readActivity(
|
|
35117
|
+
const activity2 = readActivity(path90);
|
|
34921
35118
|
if (!activity2) return;
|
|
34922
35119
|
applyActivityToSession(session, activity2);
|
|
34923
35120
|
if (activity2.claudeSessionId) onClaudeSessionId?.(session);
|
|
@@ -34926,11 +35123,11 @@ function watchActivity(session, notify2, onClaudeSessionId) {
|
|
|
34926
35123
|
notify2();
|
|
34927
35124
|
};
|
|
34928
35125
|
session.activityWatcher = watch2(dir, (_event, filename) => {
|
|
34929
|
-
if (filename && !
|
|
35126
|
+
if (filename && !path90.endsWith(filename)) return;
|
|
34930
35127
|
if (timer) clearTimeout(timer);
|
|
34931
|
-
timer = setTimeout(
|
|
35128
|
+
timer = setTimeout(read3, DEBOUNCE_MS2);
|
|
34932
35129
|
});
|
|
34933
|
-
if (
|
|
35130
|
+
if (existsSync90(path90)) read3();
|
|
34934
35131
|
}
|
|
34935
35132
|
function refreshActivity(session) {
|
|
34936
35133
|
if (session.commandType !== "assist" || !session.cwd) return;
|
|
@@ -35073,12 +35270,12 @@ import { watch as watch3 } from "fs";
|
|
|
35073
35270
|
|
|
35074
35271
|
// src/commands/sessions/shared/findTranscriptPathSync.ts
|
|
35075
35272
|
import * as fs51 from "fs";
|
|
35076
|
-
import * as
|
|
35273
|
+
import * as path87 from "path";
|
|
35077
35274
|
function projectDirForCwd(cwd) {
|
|
35078
|
-
return
|
|
35275
|
+
return path87.join(claudeProjectsRoot(), projectSlug(cwd));
|
|
35079
35276
|
}
|
|
35080
35277
|
function transcriptPathFor(cwd, claudeSessionId) {
|
|
35081
|
-
return
|
|
35278
|
+
return path87.join(projectDirForCwd(cwd), `${claudeSessionId}.jsonl`);
|
|
35082
35279
|
}
|
|
35083
35280
|
function findTranscriptPathSync(cwd, claudeSessionId) {
|
|
35084
35281
|
const direct = transcriptPathFor(cwd, claudeSessionId);
|
|
@@ -35092,8 +35289,8 @@ function findTranscriptPathSync(cwd, claudeSessionId) {
|
|
|
35092
35289
|
}
|
|
35093
35290
|
for (const file of files) {
|
|
35094
35291
|
if (!file.endsWith(".jsonl")) continue;
|
|
35095
|
-
if (headContainsSessionId(
|
|
35096
|
-
return
|
|
35292
|
+
if (headContainsSessionId(path87.join(dir, file), claudeSessionId))
|
|
35293
|
+
return path87.join(dir, file);
|
|
35097
35294
|
}
|
|
35098
35295
|
return null;
|
|
35099
35296
|
}
|
|
@@ -36267,9 +36464,9 @@ function tempRoots() {
|
|
|
36267
36464
|
}
|
|
36268
36465
|
return [...roots];
|
|
36269
36466
|
}
|
|
36270
|
-
function underTempRoot(
|
|
36467
|
+
function underTempRoot(path90) {
|
|
36271
36468
|
return tempRoots().some(
|
|
36272
|
-
(root) =>
|
|
36469
|
+
(root) => path90.startsWith(root.endsWith(sep2) ? root : root + sep2)
|
|
36273
36470
|
);
|
|
36274
36471
|
}
|
|
36275
36472
|
|
|
@@ -36581,7 +36778,7 @@ function rearmStoppedSessions(sessions, notify2) {
|
|
|
36581
36778
|
}
|
|
36582
36779
|
|
|
36583
36780
|
// src/commands/sessions/daemon/worktree/reconcileWorktreesOnRestore.ts
|
|
36584
|
-
import { existsSync as
|
|
36781
|
+
import { existsSync as existsSync93 } from "fs";
|
|
36585
36782
|
import { basename as basename24 } from "path";
|
|
36586
36783
|
|
|
36587
36784
|
// src/commands/sessions/daemon/worktree/accountedTrees.ts
|
|
@@ -36636,18 +36833,18 @@ function bindResumedWorktree(session, cwd, notify2) {
|
|
|
36636
36833
|
}
|
|
36637
36834
|
|
|
36638
36835
|
// src/commands/sessions/daemon/worktree/reclaimVanishedWorktrees.ts
|
|
36639
|
-
import { existsSync as
|
|
36836
|
+
import { existsSync as existsSync92 } from "fs";
|
|
36640
36837
|
async function reclaimVanishedWorktrees(clone, paths) {
|
|
36641
|
-
if (!
|
|
36642
|
-
for (const { path:
|
|
36838
|
+
if (!existsSync92(clone)) {
|
|
36839
|
+
for (const { path: path90 } of paths) forgetWorktree(path90);
|
|
36643
36840
|
daemonLog(
|
|
36644
36841
|
`clone ${clone} is gone; forgot ${paths.length} worktree record(s) it owned`
|
|
36645
36842
|
);
|
|
36646
36843
|
return;
|
|
36647
36844
|
}
|
|
36648
36845
|
await pruneBookkeeping2(clone);
|
|
36649
|
-
for (const { path:
|
|
36650
|
-
if (await reclaimBranch(clone, branch2)) forgetWorktree(
|
|
36846
|
+
for (const { path: path90, branch: branch2 } of paths)
|
|
36847
|
+
if (await reclaimBranch(clone, branch2)) forgetWorktree(path90);
|
|
36651
36848
|
}
|
|
36652
36849
|
async function pruneBookkeeping2(clone) {
|
|
36653
36850
|
try {
|
|
@@ -36674,37 +36871,37 @@ async function reclaimBranch(clone, branch2) {
|
|
|
36674
36871
|
}
|
|
36675
36872
|
|
|
36676
36873
|
// src/commands/sessions/daemon/worktree/logVanishedTree.ts
|
|
36677
|
-
function logVanishedTree(sessions,
|
|
36874
|
+
function logVanishedTree(sessions, path90) {
|
|
36678
36875
|
const claimants = [...sessions.values()].filter(
|
|
36679
|
-
(s) => s.cwd ===
|
|
36876
|
+
(s) => s.cwd === path90 || s.worktree?.path === path90
|
|
36680
36877
|
);
|
|
36681
36878
|
if (claimants.length === 0) {
|
|
36682
|
-
daemonLog(`worktree ${
|
|
36879
|
+
daemonLog(`worktree ${path90} gone from disk and unclaimed; reclaiming it`);
|
|
36683
36880
|
return;
|
|
36684
36881
|
}
|
|
36685
36882
|
for (const s of claimants)
|
|
36686
36883
|
daemonLog(
|
|
36687
|
-
`session ${s.id} ("${s.name}") claims worktree ${
|
|
36884
|
+
`session ${s.id} ("${s.name}") claims worktree ${path90}, which is gone from disk; reclaiming it`
|
|
36688
36885
|
);
|
|
36689
36886
|
}
|
|
36690
36887
|
|
|
36691
36888
|
// src/commands/sessions/daemon/worktree/describeHeldWork.ts
|
|
36692
36889
|
var MAX_ITEMS = 20;
|
|
36693
|
-
async function describeHeldWork(
|
|
36694
|
-
if (reason4.startsWith("uncommitted")) return await changedFiles(
|
|
36695
|
-
if (reason4.startsWith("unpushed")) return await unpushedCommits(
|
|
36890
|
+
async function describeHeldWork(path90, reason4) {
|
|
36891
|
+
if (reason4.startsWith("uncommitted")) return await changedFiles(path90);
|
|
36892
|
+
if (reason4.startsWith("unpushed")) return await unpushedCommits(path90, reason4);
|
|
36696
36893
|
return { summary: reason4, items: [] };
|
|
36697
36894
|
}
|
|
36698
|
-
async function changedFiles(
|
|
36699
|
-
const status3 = await gitResult(
|
|
36895
|
+
async function changedFiles(path90) {
|
|
36896
|
+
const status3 = await gitResult(path90, ["status", "--porcelain"]);
|
|
36700
36897
|
const lines2 = status3.ok ? nonEmptyLines(status3.out) : [];
|
|
36701
36898
|
return {
|
|
36702
36899
|
summary: `${lines2.length} uncommitted ${lines2.length === 1 ? "file" : "files"}`,
|
|
36703
36900
|
items: capped(lines2)
|
|
36704
36901
|
};
|
|
36705
36902
|
}
|
|
36706
|
-
async function unpushedCommits(
|
|
36707
|
-
const log2 = await gitResult(
|
|
36903
|
+
async function unpushedCommits(path90, reason4) {
|
|
36904
|
+
const log2 = await gitResult(path90, ["log", "--oneline", "@{upstream}..HEAD"]);
|
|
36708
36905
|
if (!log2.ok) return { summary: reason4, items: [] };
|
|
36709
36906
|
const lines2 = nonEmptyLines(log2.out);
|
|
36710
36907
|
return {
|
|
@@ -36796,24 +36993,24 @@ function reconcileWorktreesOnRestore(sessions, spawnWith, notify2) {
|
|
|
36796
36993
|
async function recoverOrphanedWorktrees(sessions, spawnWith, notify2) {
|
|
36797
36994
|
const accounted = accountedTrees(sessions);
|
|
36798
36995
|
const vanished = /* @__PURE__ */ new Map();
|
|
36799
|
-
for (const { path:
|
|
36800
|
-
if (underTempRoot(
|
|
36801
|
-
forgetWorktree(
|
|
36996
|
+
for (const { path: path90, clone } of readWorktreeRegistry()) {
|
|
36997
|
+
if (underTempRoot(path90)) {
|
|
36998
|
+
forgetWorktree(path90);
|
|
36802
36999
|
daemonLog(
|
|
36803
|
-
`worktree ${
|
|
37000
|
+
`worktree ${path90} lies outside any project root; pruned from the registry rather than recovered`
|
|
36804
37001
|
);
|
|
36805
37002
|
continue;
|
|
36806
37003
|
}
|
|
36807
|
-
if (!
|
|
36808
|
-
logVanishedTree(sessions,
|
|
37004
|
+
if (!existsSync93(path90)) {
|
|
37005
|
+
logVanishedTree(sessions, path90);
|
|
36809
37006
|
vanished.set(clone, [
|
|
36810
37007
|
...vanished.get(clone) ?? [],
|
|
36811
|
-
{ path:
|
|
37008
|
+
{ path: path90, branch: basename24(path90) }
|
|
36812
37009
|
]);
|
|
36813
37010
|
continue;
|
|
36814
37011
|
}
|
|
36815
|
-
if (accounted.has(
|
|
36816
|
-
await recoverOrphan(sessions, spawnWith, { path:
|
|
37012
|
+
if (accounted.has(path90)) continue;
|
|
37013
|
+
await recoverOrphan(sessions, spawnWith, { path: path90, clone }, notify2);
|
|
36817
37014
|
}
|
|
36818
37015
|
for (const [clone, paths] of vanished)
|
|
36819
37016
|
await reclaimVanishedWorktrees(clone, paths);
|
|
@@ -37421,14 +37618,14 @@ async function defaultConnect() {
|
|
|
37421
37618
|
}
|
|
37422
37619
|
|
|
37423
37620
|
// src/commands/sessions/daemon/hasPersistedWindowsSessions.ts
|
|
37424
|
-
import { existsSync as
|
|
37621
|
+
import { existsSync as existsSync94, readFileSync as readFileSync63 } from "fs";
|
|
37425
37622
|
import { posix as posix3 } from "path";
|
|
37426
37623
|
function hasPersistedWindowsSessions() {
|
|
37427
37624
|
const sessionsFile = windowsSessionsFileFromWsl();
|
|
37428
37625
|
if (!sessionsFile) return false;
|
|
37429
37626
|
try {
|
|
37430
|
-
if (!
|
|
37431
|
-
const data = JSON.parse(
|
|
37627
|
+
if (!existsSync94(sessionsFile)) return false;
|
|
37628
|
+
const data = JSON.parse(readFileSync63(sessionsFile, "utf8"));
|
|
37432
37629
|
return Array.isArray(data) && data.length > 0;
|
|
37433
37630
|
} catch (error) {
|
|
37434
37631
|
const message3 = error instanceof Error ? error.message : String(error);
|
|
@@ -38162,7 +38359,7 @@ function setAutoAdvance(sessions, id, enabled) {
|
|
|
38162
38359
|
}
|
|
38163
38360
|
|
|
38164
38361
|
// src/commands/sessions/daemon/worktree/resumeInTree.ts
|
|
38165
|
-
import { existsSync as
|
|
38362
|
+
import { existsSync as existsSync97 } from "fs";
|
|
38166
38363
|
|
|
38167
38364
|
// src/commands/sessions/daemon/resumeSession.ts
|
|
38168
38365
|
function resumeSession(id, sessionId, cwd, name, holdPty, harness) {
|
|
@@ -38193,10 +38390,10 @@ function resumeSession(id, sessionId, cwd, name, holdPty, harness) {
|
|
|
38193
38390
|
}
|
|
38194
38391
|
|
|
38195
38392
|
// src/commands/sessions/daemon/worktree/resumeInReplacementTree.ts
|
|
38196
|
-
import { existsSync as
|
|
38393
|
+
import { existsSync as existsSync96 } from "fs";
|
|
38197
38394
|
|
|
38198
38395
|
// src/commands/sessions/daemon/worktree/carryTranscriptToTree.ts
|
|
38199
|
-
import { copyFileSync as copyFileSync7, existsSync as
|
|
38396
|
+
import { copyFileSync as copyFileSync7, existsSync as existsSync95, mkdirSync as mkdirSync35 } from "fs";
|
|
38200
38397
|
import { join as join100 } from "path";
|
|
38201
38398
|
function carryTranscriptToTree(claudeSessionId, fromCwd, toCwd) {
|
|
38202
38399
|
const dir = projectDirForCwd(toCwd);
|
|
@@ -38207,7 +38404,7 @@ function carryTranscriptToTree(claudeSessionId, fromCwd, toCwd) {
|
|
|
38207
38404
|
return;
|
|
38208
38405
|
}
|
|
38209
38406
|
const dest = join100(dir, `${claudeSessionId}.jsonl`);
|
|
38210
|
-
if (
|
|
38407
|
+
if (existsSync95(dest)) {
|
|
38211
38408
|
daemonLog(`transcript ${claudeSessionId} already present in ${dir}`);
|
|
38212
38409
|
return;
|
|
38213
38410
|
}
|
|
@@ -38258,7 +38455,7 @@ function resumeInReplacementTree(ctx, claudeSessionId, missingCwd, name, harness
|
|
|
38258
38455
|
}
|
|
38259
38456
|
function cloneForReapedTree(missingCwd) {
|
|
38260
38457
|
const clone = worktreeAttributionIncludingReaped(missingCwd)?.clone;
|
|
38261
|
-
if (!clone || !
|
|
38458
|
+
if (!clone || !existsSync96(clone))
|
|
38262
38459
|
throw new Error(
|
|
38263
38460
|
`working directory no longer exists and no clone is recorded to re-allocate from: ${missingCwd}`
|
|
38264
38461
|
);
|
|
@@ -38267,7 +38464,7 @@ function cloneForReapedTree(missingCwd) {
|
|
|
38267
38464
|
|
|
38268
38465
|
// src/commands/sessions/daemon/worktree/resumeInTree.ts
|
|
38269
38466
|
function resumeInTree(ctx, sessionId, cwd, name, harness) {
|
|
38270
|
-
if (!
|
|
38467
|
+
if (!existsSync97(cwd))
|
|
38271
38468
|
return resumeInReplacementTree(ctx, sessionId, cwd, name, harness);
|
|
38272
38469
|
const id = ctx.spawnWith(
|
|
38273
38470
|
(sid) => resumeSession(sid, sessionId, cwd, name, void 0, harness)
|
|
@@ -38534,12 +38731,12 @@ function handleSetStatus(client, m, d) {
|
|
|
38534
38731
|
import * as fs54 from "fs";
|
|
38535
38732
|
|
|
38536
38733
|
// src/commands/sessions/shared/codex/findCodexRolloutPath.ts
|
|
38537
|
-
import * as
|
|
38734
|
+
import * as path88 from "path";
|
|
38538
38735
|
async function findCodexRolloutPath(sessionId) {
|
|
38539
38736
|
if (!sessionId) return null;
|
|
38540
38737
|
const paths = await discoverCodexRolloutPaths();
|
|
38541
38738
|
const suffix = `-${sessionId}.jsonl`;
|
|
38542
|
-
return paths.find((file) =>
|
|
38739
|
+
return paths.find((file) => path88.basename(file).endsWith(suffix)) ?? null;
|
|
38543
38740
|
}
|
|
38544
38741
|
|
|
38545
38742
|
// src/commands/sessions/shared/codex/codexToolTarget.ts
|
|
@@ -38844,10 +39041,10 @@ function handleConnection(socket, manager) {
|
|
|
38844
39041
|
}
|
|
38845
39042
|
|
|
38846
39043
|
// src/commands/sessions/daemon/onListening.ts
|
|
38847
|
-
import { unlinkSync as unlinkSync23, writeFileSync as
|
|
39044
|
+
import { unlinkSync as unlinkSync23, writeFileSync as writeFileSync50 } from "fs";
|
|
38848
39045
|
|
|
38849
39046
|
// src/commands/sessions/daemon/startPidFileWatchdog.ts
|
|
38850
|
-
import { readFileSync as
|
|
39047
|
+
import { readFileSync as readFileSync64 } from "fs";
|
|
38851
39048
|
var WATCHDOG_INTERVAL_MS = 5e3;
|
|
38852
39049
|
function startPidFileWatchdog(onLost, intervalMs = WATCHDOG_INTERVAL_MS) {
|
|
38853
39050
|
const timer = setInterval(() => {
|
|
@@ -38858,7 +39055,7 @@ function startPidFileWatchdog(onLost, intervalMs = WATCHDOG_INTERVAL_MS) {
|
|
|
38858
39055
|
}
|
|
38859
39056
|
function ownsPidFile() {
|
|
38860
39057
|
try {
|
|
38861
|
-
return
|
|
39058
|
+
return readFileSync64(daemonPaths.pid, "utf8").trim() === String(process.pid);
|
|
38862
39059
|
} catch {
|
|
38863
39060
|
return false;
|
|
38864
39061
|
}
|
|
@@ -38866,7 +39063,7 @@ function ownsPidFile() {
|
|
|
38866
39063
|
|
|
38867
39064
|
// src/commands/sessions/daemon/onListening.ts
|
|
38868
39065
|
function onListening(manager, checkAutoExit) {
|
|
38869
|
-
|
|
39066
|
+
writeFileSync50(daemonPaths.pid, String(process.pid));
|
|
38870
39067
|
startPidFileWatchdog(() => {
|
|
38871
39068
|
daemonLog("lost daemon.pid ownership; shutting down sessions and exiting");
|
|
38872
39069
|
void manager.flushActiveMs().finally(() => {
|
|
@@ -39108,7 +39305,7 @@ function registerSetStatusCommand(cmd) {
|
|
|
39108
39305
|
|
|
39109
39306
|
// src/commands/sessions/summarise/index.ts
|
|
39110
39307
|
import * as fs56 from "fs";
|
|
39111
|
-
import
|
|
39308
|
+
import chalk228 from "chalk";
|
|
39112
39309
|
|
|
39113
39310
|
// src/commands/sessions/summarise/shared.ts
|
|
39114
39311
|
import * as fs55 from "fs";
|
|
@@ -39167,22 +39364,22 @@ ${firstMessage}`);
|
|
|
39167
39364
|
async function summarise2(options2) {
|
|
39168
39365
|
const files = await discoverSessionFiles();
|
|
39169
39366
|
if (files.length === 0) {
|
|
39170
|
-
console.log(
|
|
39367
|
+
console.log(chalk228.yellow("No sessions found."));
|
|
39171
39368
|
return;
|
|
39172
39369
|
}
|
|
39173
39370
|
const toProcess = selectCandidates(files, options2);
|
|
39174
39371
|
if (toProcess.length === 0) {
|
|
39175
|
-
console.log(
|
|
39372
|
+
console.log(chalk228.green("All sessions already summarised."));
|
|
39176
39373
|
return;
|
|
39177
39374
|
}
|
|
39178
39375
|
console.log(
|
|
39179
|
-
|
|
39376
|
+
chalk228.cyan(
|
|
39180
39377
|
`Summarising ${toProcess.length} session(s) (${files.length} total)\u2026`
|
|
39181
39378
|
)
|
|
39182
39379
|
);
|
|
39183
39380
|
const { succeeded, failed: failed2 } = processSessions(toProcess);
|
|
39184
39381
|
console.log(
|
|
39185
|
-
|
|
39382
|
+
chalk228.green(`Done: ${succeeded} summarised`) + (failed2 > 0 ? chalk228.yellow(`, ${failed2} skipped`) : "")
|
|
39186
39383
|
);
|
|
39187
39384
|
}
|
|
39188
39385
|
function selectCandidates(files, options2) {
|
|
@@ -39202,16 +39399,16 @@ function processSessions(files) {
|
|
|
39202
39399
|
let failed2 = 0;
|
|
39203
39400
|
for (let i = 0; i < files.length; i++) {
|
|
39204
39401
|
const file = files[i];
|
|
39205
|
-
process.stdout.write(
|
|
39402
|
+
process.stdout.write(chalk228.dim(` [${i + 1}/${files.length}] `));
|
|
39206
39403
|
const summary = summariseSession(file);
|
|
39207
39404
|
if (summary) {
|
|
39208
39405
|
writeSummary(file, summary);
|
|
39209
39406
|
succeeded++;
|
|
39210
|
-
process.stdout.write(`${
|
|
39407
|
+
process.stdout.write(`${chalk228.green("\u2713")} ${summary}
|
|
39211
39408
|
`);
|
|
39212
39409
|
} else {
|
|
39213
39410
|
failed2++;
|
|
39214
|
-
process.stdout.write(` ${
|
|
39411
|
+
process.stdout.write(` ${chalk228.yellow("skip")}
|
|
39215
39412
|
`);
|
|
39216
39413
|
}
|
|
39217
39414
|
}
|
|
@@ -39232,7 +39429,7 @@ function registerSessions(program2) {
|
|
|
39232
39429
|
}
|
|
39233
39430
|
|
|
39234
39431
|
// src/commands/statusLine.ts
|
|
39235
|
-
import
|
|
39432
|
+
import chalk230 from "chalk";
|
|
39236
39433
|
|
|
39237
39434
|
// src/shared/contextLevel.ts
|
|
39238
39435
|
function contextLevel(pct) {
|
|
@@ -39242,7 +39439,7 @@ function contextLevel(pct) {
|
|
|
39242
39439
|
}
|
|
39243
39440
|
|
|
39244
39441
|
// src/commands/buildLimitsSegment.ts
|
|
39245
|
-
import
|
|
39442
|
+
import chalk229 from "chalk";
|
|
39246
39443
|
|
|
39247
39444
|
// src/shared/rateLimitLevel.ts
|
|
39248
39445
|
var FIVE_HOUR_SECONDS = 5 * 3600;
|
|
@@ -39280,9 +39477,9 @@ function rateLimitLevel(pct, resetsAt, windowSeconds, now) {
|
|
|
39280
39477
|
|
|
39281
39478
|
// src/commands/buildLimitsSegment.ts
|
|
39282
39479
|
var LEVEL_COLOR = {
|
|
39283
|
-
ok:
|
|
39284
|
-
warn:
|
|
39285
|
-
over:
|
|
39480
|
+
ok: chalk229.green,
|
|
39481
|
+
warn: chalk229.yellow,
|
|
39482
|
+
over: chalk229.red
|
|
39286
39483
|
};
|
|
39287
39484
|
function formatLimit(pct, resetsAt, windowSeconds, fallbackLabel, now) {
|
|
39288
39485
|
const level = rateLimitLevel(pct, resetsAt, windowSeconds, now);
|
|
@@ -39313,7 +39510,7 @@ function buildLimitsSegment(rateLimits) {
|
|
|
39313
39510
|
}
|
|
39314
39511
|
|
|
39315
39512
|
// src/commands/readGitBranch.ts
|
|
39316
|
-
import { readFileSync as
|
|
39513
|
+
import { readFileSync as readFileSync66, statSync as statSync16 } from "fs";
|
|
39317
39514
|
import { isAbsolute as isAbsolute5, join as join101, resolve as resolve23 } from "path";
|
|
39318
39515
|
function resolveGitDir(cwd) {
|
|
39319
39516
|
const dotGit = join101(cwd, ".git");
|
|
@@ -39328,7 +39525,7 @@ function resolveGitDir(cwd) {
|
|
|
39328
39525
|
}
|
|
39329
39526
|
let contents;
|
|
39330
39527
|
try {
|
|
39331
|
-
contents =
|
|
39528
|
+
contents = readFileSync66(dotGit, "utf8");
|
|
39332
39529
|
} catch {
|
|
39333
39530
|
return null;
|
|
39334
39531
|
}
|
|
@@ -39346,7 +39543,7 @@ function readGitBranch(cwd) {
|
|
|
39346
39543
|
}
|
|
39347
39544
|
let head;
|
|
39348
39545
|
try {
|
|
39349
|
-
head =
|
|
39546
|
+
head = readFileSync66(join101(gitDir, "HEAD"), "utf8");
|
|
39350
39547
|
} catch {
|
|
39351
39548
|
return null;
|
|
39352
39549
|
}
|
|
@@ -39378,7 +39575,7 @@ async function relayUsage(claudeSessionId, transcriptPath2, usedPct) {
|
|
|
39378
39575
|
}
|
|
39379
39576
|
|
|
39380
39577
|
// src/commands/statusLine.ts
|
|
39381
|
-
|
|
39578
|
+
chalk230.level = 3;
|
|
39382
39579
|
function formatNumber(num) {
|
|
39383
39580
|
return num.toLocaleString("en-US");
|
|
39384
39581
|
}
|
|
@@ -39386,9 +39583,9 @@ function colorizePercent(pct) {
|
|
|
39386
39583
|
const label2 = `${Math.round(pct)}%`;
|
|
39387
39584
|
switch (contextLevel(pct)) {
|
|
39388
39585
|
case "red":
|
|
39389
|
-
return
|
|
39586
|
+
return chalk230.red(label2);
|
|
39390
39587
|
case "yellow":
|
|
39391
|
-
return
|
|
39588
|
+
return chalk230.yellow(label2);
|
|
39392
39589
|
default:
|
|
39393
39590
|
return label2;
|
|
39394
39591
|
}
|
|
@@ -39401,7 +39598,7 @@ async function statusLine() {
|
|
|
39401
39598
|
const usedPct = data.context_window.used_percentage ?? 0;
|
|
39402
39599
|
const dir = data.workspace?.current_dir ?? data.cwd;
|
|
39403
39600
|
const branch2 = dir ? readGitBranch(toGitCwd(dir)) : null;
|
|
39404
|
-
const branchSegment = branch2 ? `\u{1F33F}\uFE0F ${
|
|
39601
|
+
const branchSegment = branch2 ? `\u{1F33F}\uFE0F ${chalk230.cyan(branch2)} | ` : "";
|
|
39405
39602
|
console.log(
|
|
39406
39603
|
`${branchSegment}${model} | Tokens - ${formatNumber(totalIn)} \u2191 : ${formatNumber(totalOut)} \u2193 | Context - ${colorizePercent(usedPct)}${buildLimitsSegment(data.rate_limits)}`
|
|
39407
39604
|
);
|
|
@@ -39415,7 +39612,7 @@ async function statusLine() {
|
|
|
39415
39612
|
|
|
39416
39613
|
// src/commands/update.ts
|
|
39417
39614
|
import { execSync as execSync61 } from "child_process";
|
|
39418
|
-
import * as
|
|
39615
|
+
import * as path89 from "path";
|
|
39419
39616
|
|
|
39420
39617
|
// src/commands/restartDaemonAfterUpdate.ts
|
|
39421
39618
|
async function restartDaemonAfterUpdate() {
|
|
@@ -39434,12 +39631,12 @@ async function restartDaemonAfterUpdate() {
|
|
|
39434
39631
|
// src/commands/update.ts
|
|
39435
39632
|
function isGlobalNpmInstall(dir) {
|
|
39436
39633
|
try {
|
|
39437
|
-
const resolved =
|
|
39438
|
-
if (resolved.split(
|
|
39634
|
+
const resolved = path89.resolve(dir);
|
|
39635
|
+
if (resolved.split(path89.sep).includes("node_modules")) {
|
|
39439
39636
|
return true;
|
|
39440
39637
|
}
|
|
39441
39638
|
const globalPrefix = execSync61("npm prefix -g", { stdio: "pipe" }).toString().trim();
|
|
39442
|
-
return resolved.toLowerCase().startsWith(
|
|
39639
|
+
return resolved.toLowerCase().startsWith(path89.resolve(globalPrefix).toLowerCase());
|
|
39443
39640
|
} catch {
|
|
39444
39641
|
return false;
|
|
39445
39642
|
}
|
|
@@ -39471,10 +39668,10 @@ async function update2() {
|
|
|
39471
39668
|
}
|
|
39472
39669
|
|
|
39473
39670
|
// src/reportCliError.ts
|
|
39474
|
-
import
|
|
39671
|
+
import chalk231 from "chalk";
|
|
39475
39672
|
function reportCliError(error) {
|
|
39476
39673
|
if (error instanceof InvalidItemIdError || error instanceof AmbiguousRepoConfigError || error instanceof UnknownRepoConfigError || error instanceof MissingRunCwdError || error instanceof MiroExtractError) {
|
|
39477
|
-
console.error(
|
|
39674
|
+
console.error(chalk231.red(error.message));
|
|
39478
39675
|
} else {
|
|
39479
39676
|
console.error(error);
|
|
39480
39677
|
}
|