@staff0rd/assist 0.598.0 → 0.600.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/claude/commands/add-rule.md +45 -0
- package/dist/commands/criteriaExtension/criteria-extension/content.js +48 -48
- package/dist/commands/sessions/web/bundle.js +397 -393
- package/dist/index.js +672 -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.600.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(path88) {
|
|
191
|
+
return path88.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(path88) {
|
|
242
242
|
try {
|
|
243
|
-
return statSync(
|
|
243
|
+
return statSync(path88).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(path88) {
|
|
263
263
|
try {
|
|
264
|
-
const content = readFileSync(
|
|
264
|
+
const content = readFileSync(path88, "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(path88) {
|
|
278
|
+
if (!existsSync2(path88)) return {};
|
|
279
279
|
try {
|
|
280
|
-
const content = readFileSync2(
|
|
280
|
+
const content = readFileSync2(path88, "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 path88 = origin.slice("local:".length).replace(/\/+$/, "");
|
|
353
|
+
const segments = path88.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 path88 = line.split(" ")[1];
|
|
1789
|
+
if (path88) found.add(path88.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 path88 = kind === "branch" ? "tree" : "commit";
|
|
1900
|
+
return `https://github.com/${repo.org}/${repo.repo}/${path88}/${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, path88) {
|
|
4277
4277
|
const { inner, defaultValue, optional } = unwrapSchemaNode(node);
|
|
4278
4278
|
const secret = isSecretSchemaNode(node) || isSecretSchemaNode(inner);
|
|
4279
4279
|
const base = {
|
|
4280
|
-
path:
|
|
4280
|
+
path: path88,
|
|
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(path88) {
|
|
4300
4300
|
let text18 = "";
|
|
4301
|
-
for (const segment of
|
|
4301
|
+
for (const segment of path88) {
|
|
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, path88) {
|
|
4950
4950
|
let current = data;
|
|
4951
|
-
for (const segment of
|
|
4951
|
+
for (const segment of path88.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 path88 of rule.paths) {
|
|
4965
|
+
for (const value of resolveStringsAtPath(data, path88)) {
|
|
4966
4966
|
if (minimatch2(value, rule.disallowed))
|
|
4967
|
-
violations.push({ file: rule.file, path:
|
|
4967
|
+
violations.push({ file: rule.file, path: path88, 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: path88, value } of violations) {
|
|
5007
|
+
console.log(` ${file} ${path88}: ${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((path88) => MIGRATION_FILE3.test(basename2(path88)));
|
|
5323
|
+
for (const path88 of paths) {
|
|
5324
5324
|
try {
|
|
5325
|
-
const content = execSync14(`git show "${ref}:${
|
|
5325
|
+
const content = execSync14(`git show "${ref}:${path88}"`, {
|
|
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(path88), 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 path88 = daemonPaths.hooksSettings;
|
|
6765
|
+
mkdirSync5(dirname13(path88), { recursive: true });
|
|
6766
|
+
writeFileSync15(path88, JSON.stringify(hooksSettings, null, 2));
|
|
6767
|
+
return path88;
|
|
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 path88 = join15(dir, ".assist", name);
|
|
7066
|
+
if (existsSync19(path88)) {
|
|
7067
|
+
renameSync(path88, `${path88}.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(path88) {
|
|
7548
|
+
const content = readFileSync15(path88, "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 path88 = getOwnerPath(itemId2);
|
|
8360
|
+
mkdirSync7(dirname15(path88), { recursive: true });
|
|
8361
|
+
writeFileSync17(path88, JSON.stringify({ sessionId }));
|
|
8362
8362
|
}
|
|
8363
8363
|
function readSignalOwner(itemId2) {
|
|
8364
|
-
const
|
|
8365
|
-
if (!existsSync23(
|
|
8364
|
+
const path88 = getOwnerPath(itemId2);
|
|
8365
|
+
if (!existsSync23(path88)) return void 0;
|
|
8366
8366
|
try {
|
|
8367
|
-
const parsed = JSON.parse(readFileSync16(
|
|
8367
|
+
const parsed = JSON.parse(readFileSync16(path88, "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 path88 = getOwnerPath(itemId2);
|
|
8375
8375
|
try {
|
|
8376
|
-
rmSync(
|
|
8376
|
+
rmSync(path88);
|
|
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 path88 = getSignalPath(target);
|
|
8414
|
+
if (!path88) return;
|
|
8415
8415
|
const signal = { event, sessionId: target, ...data };
|
|
8416
|
-
mkdirSync8(dirname16(
|
|
8417
|
-
writeFileSync18(
|
|
8416
|
+
mkdirSync8(dirname16(path88), { recursive: true });
|
|
8417
|
+
writeFileSync18(path88, JSON.stringify(signal));
|
|
8418
8418
|
}
|
|
8419
8419
|
|
|
8420
8420
|
// src/commands/backlog/readSignal.ts
|
|
8421
8421
|
function readSignal() {
|
|
8422
|
-
const
|
|
8423
|
-
if (!
|
|
8422
|
+
const path88 = getSignalPath();
|
|
8423
|
+
if (!path88 || !existsSync24(path88)) return void 0;
|
|
8424
8424
|
try {
|
|
8425
|
-
return JSON.parse(readFileSync17(
|
|
8425
|
+
return JSON.parse(readFileSync17(path88, "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 path88 = activityPath(sessionId);
|
|
8623
|
+
mkdirSync9(dirname17(path88), { recursive: true });
|
|
8624
|
+
writeFileSync19(path88, JSON.stringify({ ...activity2, startedAt: Date.now() }));
|
|
8625
8625
|
}
|
|
8626
|
-
function readActivity(
|
|
8626
|
+
function readActivity(path88) {
|
|
8627
8627
|
try {
|
|
8628
|
-
return JSON.parse(readFileSync18(
|
|
8628
|
+
return JSON.parse(readFileSync18(path88, "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 path88 = activityPath(sessionId);
|
|
8639
|
+
mkdirSync9(dirname17(path88), { recursive: true });
|
|
8640
|
+
writeFileSync19(path88, 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 path88 = getStorePath(filename);
|
|
10094
|
+
if (existsSync29(path88)) {
|
|
10095
10095
|
try {
|
|
10096
|
-
return JSON.parse(readFileSync19(
|
|
10096
|
+
return JSON.parse(readFileSync19(path88, "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(([path88, record]) => ({ path: path88, ...record }));
|
|
10116
10116
|
}
|
|
10117
|
-
function worktreeAttributionIncludingReaped(
|
|
10118
|
-
const record = loadJson(REGISTRY_FILE)[
|
|
10117
|
+
function worktreeAttributionIncludingReaped(path88) {
|
|
10118
|
+
const record = loadJson(REGISTRY_FILE)[path88];
|
|
10119
10119
|
return record ? { clone: record.clone, origin: record.origin } : void 0;
|
|
10120
10120
|
}
|
|
10121
|
-
function recordWorktree(
|
|
10121
|
+
function recordWorktree(path88, clone, origin) {
|
|
10122
10122
|
const data = loadJson(REGISTRY_FILE);
|
|
10123
|
-
data[
|
|
10123
|
+
data[path88] = { clone, origin };
|
|
10124
10124
|
saveJson(REGISTRY_FILE, data);
|
|
10125
10125
|
}
|
|
10126
|
-
function forgetWorktree(
|
|
10126
|
+
function forgetWorktree(path88) {
|
|
10127
10127
|
const data = loadJson(REGISTRY_FILE);
|
|
10128
|
-
const record = data[
|
|
10128
|
+
const record = data[path88];
|
|
10129
10129
|
if (!record || record.reaped) return;
|
|
10130
|
-
data[
|
|
10130
|
+
data[path88] = { ...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 path88 of resolved.paths) {
|
|
10882
|
+
if (!bases.has(path88)) bases.set(path88, 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 [path88, 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(path88);
|
|
10903
|
+
else groups.set(base, [path88]);
|
|
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((path88) => path88 && !bases.has(path88)).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, path88) {
|
|
10919
|
+
return execGit(cwd, ["diff", "--no-index", "--", "/dev/null", path88], {
|
|
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((path88) => untrackedFileDiff(cwd, path88))
|
|
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, path88) {
|
|
11026
11026
|
const root = repoRoot(cwd);
|
|
11027
|
-
const target = resolve10(root,
|
|
11027
|
+
const target = resolve10(root, path88);
|
|
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 path88 = new URL(req.url ?? "/", "http://localhost").searchParams.get(
|
|
11038
11038
|
"path"
|
|
11039
11039
|
);
|
|
11040
|
-
if (!
|
|
11040
|
+
if (!path88) {
|
|
11041
11041
|
respondJson(res, 400, { error: "Missing path" });
|
|
11042
11042
|
return null;
|
|
11043
11043
|
}
|
|
11044
|
-
const target = resolveWithinCwd(cwd,
|
|
11044
|
+
const target = resolveWithinCwd(cwd, path88);
|
|
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(path88) {
|
|
11120
|
+
if (path88 === getGlobalConfigPath()) return "~/.assist.yml";
|
|
11121
|
+
if (path88.startsWith(WINDOWS_MOUNT_PREFIX))
|
|
11122
|
+
return `${path88} on the Windows host`;
|
|
11123
|
+
return path88;
|
|
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, path88, 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, [...path88, name], childNode(name), map)
|
|
11186
11186
|
])
|
|
11187
11187
|
);
|
|
11188
11188
|
}
|
|
11189
|
-
function mapItems(value,
|
|
11189
|
+
function mapItems(value, path88, 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, [...path88, index3], item, map));
|
|
11192
11192
|
}
|
|
11193
|
-
function walk(value,
|
|
11193
|
+
function walk(value, path88, 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, path88);
|
|
11196
11196
|
switch (node.kind) {
|
|
11197
11197
|
case "object":
|
|
11198
11198
|
case "unionOfObjects":
|
|
11199
11199
|
return mapChildren(
|
|
11200
11200
|
value,
|
|
11201
|
-
|
|
11201
|
+
path88,
|
|
11202
11202
|
(name) => configNodeField(node, name),
|
|
11203
11203
|
map
|
|
11204
11204
|
);
|
|
11205
11205
|
case "objectList":
|
|
11206
|
-
return mapItems(value,
|
|
11206
|
+
return mapItems(value, path88, node.item, map);
|
|
11207
11207
|
case "record":
|
|
11208
|
-
return mapChildren(value,
|
|
11208
|
+
return mapChildren(value, path88, () => 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, path88) {
|
|
11234
11234
|
let current = obj;
|
|
11235
|
-
for (const key of
|
|
11235
|
+
for (const key of path88.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, path88) {
|
|
11286
11286
|
let current = root;
|
|
11287
|
-
for (const segment of
|
|
11287
|
+
for (const segment of path88) {
|
|
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 path88 = [];
|
|
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
|
+
path88.push(segment);
|
|
11312
11312
|
at2 = close + 1;
|
|
11313
11313
|
continue;
|
|
11314
11314
|
}
|
|
11315
11315
|
if (text18[at2] === ".") {
|
|
11316
|
-
if (
|
|
11316
|
+
if (path88.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
|
+
path88.push(nameSegment(name));
|
|
11324
11324
|
}
|
|
11325
|
-
return
|
|
11325
|
+
return path88;
|
|
11326
11326
|
}
|
|
11327
11327
|
|
|
11328
11328
|
// src/commands/config/configEntryNode.ts
|
|
11329
11329
|
function configEntryNode(root, key) {
|
|
11330
|
-
const
|
|
11331
|
-
return
|
|
11330
|
+
const path88 = parseConfigPath(key);
|
|
11331
|
+
return path88 ? findConfigNode(root, path88) : 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((path88) => existsSync32(path88)).map((path88) => ({ path: path88, mtime: statSync4(path88).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 path88 = await resolveSynthesisPath(cwd);
|
|
11497
|
+
if (!path88) {
|
|
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(path88, "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 path88 = fields[fields.length - 1];
|
|
11585
|
+
if (path88) result[category].push(path88);
|
|
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(path88, query) {
|
|
11722
11722
|
const needle = query.trim().toLowerCase();
|
|
11723
11723
|
if (!needle) return 0;
|
|
11724
|
-
const basename26 =
|
|
11724
|
+
const basename26 = path88.slice(path88.lastIndexOf("/") + 1);
|
|
11725
11725
|
const inBasename = subsequenceScore(basename26, needle);
|
|
11726
11726
|
if (inBasename !== null) return BASENAME_WEIGHT + inBasename;
|
|
11727
|
-
return subsequenceScore(
|
|
11727
|
+
return subsequenceScore(path88, 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 path88 of paths) {
|
|
11734
|
+
const score = scoreFilePath(path88, query);
|
|
11735
|
+
if (score !== null) scored.push({ path: path88, 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, path88) {
|
|
12286
12302
|
try {
|
|
12287
|
-
await execGit(cwd, ["ls-files", "--error-unmatch", "--",
|
|
12303
|
+
await execGit(cwd, ["ls-files", "--error-unmatch", "--", path88]);
|
|
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, path88) {
|
|
12310
|
+
const listing = await execGit(cwd, ["ls-tree", "HEAD", "--", path88]);
|
|
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, path88) {
|
|
12314
|
+
if (!await isTracked(cwd, path88)) {
|
|
12315
|
+
await execGit(cwd, ["clean", "-f", "--", path88]);
|
|
12300
12316
|
return;
|
|
12301
12317
|
}
|
|
12302
|
-
if (await isInHead(cwd,
|
|
12303
|
-
await execGit(cwd, ["checkout", "HEAD", "--",
|
|
12318
|
+
if (await isInHead(cwd, path88)) {
|
|
12319
|
+
await execGit(cwd, ["checkout", "HEAD", "--", path88]);
|
|
12304
12320
|
return;
|
|
12305
12321
|
}
|
|
12306
|
-
await execGit(cwd, ["rm", "-f", "--",
|
|
12322
|
+
await execGit(cwd, ["rm", "-f", "--", path88]);
|
|
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 path88 = relative3(repoRoot(resolved.cwd), resolved.target);
|
|
12314
12330
|
try {
|
|
12315
|
-
await revertPathChanges(resolved.cwd,
|
|
12316
|
-
respondJson(res, 200, { reverted:
|
|
12331
|
+
await revertPathChanges(resolved.cwd, path88);
|
|
12332
|
+
respondJson(res, 200, { reverted: path88 });
|
|
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((path88) => typeof path88 !== "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 path88 of paths) {
|
|
12375
|
+
const target = resolveWithinCwd(cwd, path88);
|
|
12360
12376
|
if (!target) {
|
|
12361
|
-
failed2.push({ path:
|
|
12377
|
+
failed2.push({ path: path88, 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 path88 = formatConfigPath([
|
|
12452
12468
|
{ kind: "key", name: key },
|
|
12453
12469
|
...issue.path.map(toSegment)
|
|
12454
12470
|
]);
|
|
12455
|
-
return `${
|
|
12471
|
+
return `${path88}: ${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, path88) {
|
|
12551
12567
|
let current = value;
|
|
12552
|
-
for (const key of
|
|
12568
|
+
for (const key of path88) {
|
|
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, path88) => isRedactedSecret(secret) ? valueAtConfigPath(stored, path88) : 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, path88, value) {
|
|
12635
|
+
const keys = path88.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 path88 = issue.path.length > 0 ? issue.path.join(".") : key;
|
|
12663
|
+
return [`${path88}: ${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, path88) {
|
|
12921
|
+
const { container, removed } = removeAt(obj, path88.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 path88 = origin.slice(firstSlash + 1);
|
|
14036
|
+
if (!path88) return null;
|
|
14037
|
+
return `git@${host}:${path88}.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(path88) {
|
|
17066
|
+
if (!existsSync38(path88)) return [];
|
|
17067
|
+
return readFileSync26(path88, "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, path88, description, depth, p) {
|
|
17589
|
+
showProgress(p, path88.join(" "));
|
|
17590
|
+
const subHelp = await runHelp([cli, ...path88]);
|
|
17575
17591
|
if (!subHelp || !hasSubcommands(subHelp)) {
|
|
17576
|
-
return [{ path:
|
|
17592
|
+
return [{ path: path88, description }];
|
|
17577
17593
|
}
|
|
17578
|
-
const children = await discoverAt(cli,
|
|
17579
|
-
return children.length > 0 ? children : [{ path:
|
|
17594
|
+
const children = await discoverAt(cli, path88, depth + 1, p);
|
|
17595
|
+
return children.length > 0 ? children : [{ path: path88, 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 path88 = logPath(cli);
|
|
17744
|
+
if (!existsSync40(path88)) return void 0;
|
|
17745
|
+
return readFileSync28(path88, "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 path88 = join41(dir, entry);
|
|
17890
17906
|
try {
|
|
17891
|
-
if (statSync7(
|
|
17907
|
+
if (statSync7(path88).mtimeMs < cutoff) unlinkSync7(path88);
|
|
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 path88 = getPinStatePath(pin);
|
|
17918
|
+
if (!existsSync41(path88)) return void 0;
|
|
17903
17919
|
try {
|
|
17904
|
-
const state = JSON.parse(readFileSync29(
|
|
17920
|
+
const state = JSON.parse(readFileSync29(path88, "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 path88 = 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 ${path88}`));
|
|
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 path88 = 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 ${path88}`));
|
|
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 path88 = getMigrationPinPath(pin);
|
|
19290
|
+
if (!existsSync46(path88)) return void 0;
|
|
19275
19291
|
try {
|
|
19276
|
-
const state = JSON.parse(readFileSync31(
|
|
19292
|
+
const state = JSON.parse(readFileSync31(path88, "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 path88 = getMigrationApprovalPath(migrationId);
|
|
20723
|
+
if (!existsSync52(path88)) return false;
|
|
20708
20724
|
try {
|
|
20709
|
-
unlinkSync11(
|
|
20725
|
+
unlinkSync11(path88);
|
|
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(path88) {
|
|
22404
22420
|
try {
|
|
22405
|
-
return realpathSync2(
|
|
22421
|
+
return realpathSync2(path88);
|
|
22406
22422
|
} catch {
|
|
22407
|
-
return resolve14(
|
|
22423
|
+
return resolve14(path88);
|
|
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 path88 = 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(path88),
|
|
22484
|
+
path88,
|
|
22469
22485
|
start3.ref
|
|
22470
22486
|
]);
|
|
22471
|
-
recordWorktree(
|
|
22487
|
+
recordWorktree(path88, clone, getCurrentOrigin(clone));
|
|
22472
22488
|
daemonLog(
|
|
22473
|
-
start3.track ? `worktree allocated ${
|
|
22489
|
+
start3.track ? `worktree allocated ${path88} (branch ${basename16(path88)} tracking ${start3.ref}) for clone ${clone}` : `worktree allocated ${path88} (branch ${basename16(path88)} off ${start3.ref}, no mainline tracking) for clone ${clone}`
|
|
22474
22490
|
);
|
|
22475
|
-
return
|
|
22491
|
+
return path88;
|
|
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 path88 = 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: path88, 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 path88 = null;
|
|
22954
22970
|
for (const line of listing.split("\n")) {
|
|
22955
22971
|
const trimmed = line.trim();
|
|
22956
22972
|
if (trimmed.startsWith("worktree "))
|
|
22957
|
-
|
|
22973
|
+
path88 = trimmed.slice("worktree ".length).trim();
|
|
22958
22974
|
else if (trimmed === `branch refs/heads/${branch2}`)
|
|
22959
|
-
return
|
|
22975
|
+
return path88 && path88 !== here ? path88 : 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, ...path88] = ref.slice(1).replace(/^[L@]/, "").split(":");
|
|
24002
24018
|
let v = rows[id];
|
|
24003
|
-
for (const key of
|
|
24019
|
+
for (const key of path88) {
|
|
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(path88, 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 ${path88}:${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: path88, line, startLine });
|
|
24731
|
+
console.log(`Added review comment on ${path88}:${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 (path88, line, body) => {
|
|
25918
25934
|
await comment2(
|
|
25919
|
-
|
|
25935
|
+
path88,
|
|
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, path88) {
|
|
26384
26400
|
const apiKey = resolveOpSecret(connection.apiKeyRef);
|
|
26385
26401
|
let accessToken = await getAccessToken(apiKey);
|
|
26386
|
-
const url = `${connection.url}${
|
|
26402
|
+
const url = `${connection.url}${path88}`;
|
|
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 path88;
|
|
26477
26493
|
if (opts.collection) {
|
|
26478
|
-
|
|
26494
|
+
path88 = `/databases/${db}/indexes/dynamic/${encodeURIComponent(opts.collection)}?start=${opts.start}&pageSize=${opts.pageSize}&sort=${encodeURIComponent(opts.sort)}`;
|
|
26479
26495
|
} else {
|
|
26480
|
-
|
|
26496
|
+
path88 = `/databases/${db}/queries?start=${opts.start}&pageSize=${opts.pageSize}`;
|
|
26481
26497
|
}
|
|
26482
26498
|
if (opts.query) {
|
|
26483
|
-
|
|
26499
|
+
path88 += `&query=${encodeURIComponent(opts.query)}`;
|
|
26484
26500
|
}
|
|
26485
|
-
return
|
|
26501
|
+
return path88;
|
|
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 path88 = 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, path88);
|
|
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 path88 of [paths.claudePath, paths.codexPath, paths.synthesisPath]) {
|
|
29127
|
+
if (existsSync61(path88)) unlinkSync17(path88);
|
|
29112
29128
|
}
|
|
29113
29129
|
}
|
|
29114
29130
|
function prepareReviewDir(paths, requestBody, force) {
|
|
@@ -30156,15 +30172,155 @@ 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 existsSync65, readFileSync as readFileSync49, writeFileSync as writeFileSync40 } from "fs";
|
|
30177
|
+
import path70 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/scopedRuleDirectories.ts
|
|
30248
|
+
import { readFileSync as readFileSync48 } from "fs";
|
|
30249
|
+
import path69 from "path";
|
|
30250
|
+
function scopedRuleDirectories(root) {
|
|
30251
|
+
return findClaudeFiles(root).filter(
|
|
30252
|
+
(file) => path69.dirname(file) !== root && parseRulesSection(readFileSync48(file, "utf8")).length > 0
|
|
30253
|
+
).map(
|
|
30254
|
+
(file) => `${path69.relative(root, path69.dirname(file)).split(path69.sep).join("/")}/`
|
|
30255
|
+
).sort();
|
|
30256
|
+
}
|
|
30257
|
+
|
|
30258
|
+
// src/commands/rules/upsertScopedRulesPointer.ts
|
|
30259
|
+
var POINTER_PREFIX = "Directories with their own `## Rules`:";
|
|
30260
|
+
function pointerLine(directories) {
|
|
30261
|
+
return `${POINTER_PREFIX} ${directories.map((dir) => `\`${dir}\``).join(", ")}`;
|
|
30262
|
+
}
|
|
30263
|
+
function upsertScopedRulesPointer(content, directories) {
|
|
30264
|
+
const lines2 = contentLines(content);
|
|
30265
|
+
const range = rulesSectionRange(lines2);
|
|
30266
|
+
const existing = lines2.findIndex(
|
|
30267
|
+
(line, index3) => range !== void 0 && index3 > range.start && index3 < range.end && line.startsWith(POINTER_PREFIX)
|
|
30268
|
+
);
|
|
30269
|
+
if (directories.length === 0) {
|
|
30270
|
+
if (existing === -1) return content;
|
|
30271
|
+
const without = [...lines2.slice(0, existing), ...lines2.slice(existing + 1)];
|
|
30272
|
+
return `${without.join("\n").replace(/\n{3,}/g, "\n\n").trimEnd()}
|
|
30273
|
+
`;
|
|
30274
|
+
}
|
|
30275
|
+
const pointer = pointerLine(directories);
|
|
30276
|
+
if (existing !== -1) {
|
|
30277
|
+
if (lines2[existing] === pointer) return content;
|
|
30278
|
+
const replaced = [...lines2];
|
|
30279
|
+
replaced[existing] = pointer;
|
|
30280
|
+
return `${replaced.join("\n")}
|
|
30281
|
+
`;
|
|
30282
|
+
}
|
|
30283
|
+
if (!range) return appendRulesSection(lines2, pointer);
|
|
30284
|
+
let at2 = range.end;
|
|
30285
|
+
while (at2 > range.start + 1 && (lines2[at2 - 1] ?? "").trim() === "") at2--;
|
|
30286
|
+
return `${[...lines2.slice(0, at2), "", pointer, ...lines2.slice(at2)].join("\n")}
|
|
30287
|
+
`;
|
|
30288
|
+
}
|
|
30289
|
+
|
|
30290
|
+
// src/commands/rules/addRule.ts
|
|
30291
|
+
function read2(file) {
|
|
30292
|
+
return existsSync65(file) ? readFileSync49(file, "utf8") : "";
|
|
30293
|
+
}
|
|
30294
|
+
function addRule(text18, options2) {
|
|
30295
|
+
const rule = text18.trim();
|
|
30296
|
+
if (rule === "") {
|
|
30297
|
+
console.error(chalk209.red("Rule text is required"));
|
|
30298
|
+
process.exitCode = 1;
|
|
30299
|
+
return;
|
|
30300
|
+
}
|
|
30301
|
+
const target = resolveRuleScope(options2.scope ?? process.cwd());
|
|
30302
|
+
const targetDir = path70.dirname(target);
|
|
30303
|
+
const root = findRepoRoot(targetDir) ?? targetDir;
|
|
30304
|
+
const code = nextRuleCode(root);
|
|
30305
|
+
writeFileSync40(target, insertRuleBullet(read2(target), code, rule));
|
|
30306
|
+
const rootFile = path70.join(root, "CLAUDE.md");
|
|
30307
|
+
const before = read2(rootFile);
|
|
30308
|
+
const after = upsertScopedRulesPointer(before, scopedRuleDirectories(root));
|
|
30309
|
+
if (after !== before) writeFileSync40(rootFile, after);
|
|
30310
|
+
console.log(
|
|
30311
|
+
`Added ${chalk209.cyan(code)} to ${path70.relative(process.cwd(), target) || target}`
|
|
30312
|
+
);
|
|
30313
|
+
}
|
|
30314
|
+
|
|
30315
|
+
// src/commands/rules/listRules.ts
|
|
30316
|
+
import path71 from "path";
|
|
30317
|
+
import chalk210 from "chalk";
|
|
30162
30318
|
function listRules(target) {
|
|
30163
|
-
const resolved =
|
|
30319
|
+
const resolved = path71.resolve(target ?? process.cwd());
|
|
30164
30320
|
const rules3 = readScopedRules(resolved);
|
|
30165
30321
|
if (rules3.length === 0) {
|
|
30166
|
-
const label2 =
|
|
30167
|
-
console.log(
|
|
30322
|
+
const label2 = path71.relative(process.cwd(), resolved) || ".";
|
|
30323
|
+
console.log(chalk210.gray(`No rules in scope for ${label2}`));
|
|
30168
30324
|
return;
|
|
30169
30325
|
}
|
|
30170
30326
|
const base = findRepoRoot(scopeDirectory(resolved));
|
|
@@ -30174,23 +30330,31 @@ function listRules(target) {
|
|
|
30174
30330
|
if (rule.source !== shown) {
|
|
30175
30331
|
shown = rule.source;
|
|
30176
30332
|
console.log(
|
|
30177
|
-
|
|
30333
|
+
chalk210.dim(base ? path71.relative(base, rule.source) : rule.source)
|
|
30178
30334
|
);
|
|
30179
30335
|
}
|
|
30180
|
-
console.log(` ${
|
|
30336
|
+
console.log(` ${chalk210.cyan(rule.code.padEnd(width))} ${rule.text}`);
|
|
30181
30337
|
}
|
|
30182
30338
|
}
|
|
30183
30339
|
|
|
30184
30340
|
// src/commands/registerRules.ts
|
|
30185
30341
|
function registerRules(program2) {
|
|
30186
|
-
const rulesCommand = program2.command("rules").description("Read the CLAUDE.md rules in scope for a path");
|
|
30342
|
+
const rulesCommand = program2.command("rules").description("Read and write the CLAUDE.md rules in scope for a path");
|
|
30187
30343
|
rulesCommand.command("list [path]").description(
|
|
30188
30344
|
"List the rules from the `## Rules` section of every CLAUDE.md from a path's directory up to the repo root (default: cwd)"
|
|
30189
30345
|
).action((target) => listRules(target));
|
|
30346
|
+
rulesCommand.command("add <text>").description(
|
|
30347
|
+
"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"
|
|
30348
|
+
).option(
|
|
30349
|
+
"--scope <path>",
|
|
30350
|
+
"File or directory whose nearest CLAUDE.md receives the rule, or a CLAUDE.md path to write to directly (default: cwd)"
|
|
30351
|
+
).action(
|
|
30352
|
+
(text18, options2) => addRule(text18, options2)
|
|
30353
|
+
);
|
|
30190
30354
|
}
|
|
30191
30355
|
|
|
30192
30356
|
// src/commands/seq/seqAuth.ts
|
|
30193
|
-
import
|
|
30357
|
+
import chalk212 from "chalk";
|
|
30194
30358
|
|
|
30195
30359
|
// src/commands/seq/loadConnections.ts
|
|
30196
30360
|
function loadConnections2() {
|
|
@@ -30219,10 +30383,10 @@ function setDefaultConnection(name) {
|
|
|
30219
30383
|
}
|
|
30220
30384
|
|
|
30221
30385
|
// src/shared/assertUniqueName.ts
|
|
30222
|
-
import
|
|
30386
|
+
import chalk211 from "chalk";
|
|
30223
30387
|
function assertUniqueName(existingNames, name) {
|
|
30224
30388
|
if (existingNames.includes(name)) {
|
|
30225
|
-
console.error(
|
|
30389
|
+
console.error(chalk211.red(`Connection "${name}" already exists.`));
|
|
30226
30390
|
process.exit(1);
|
|
30227
30391
|
}
|
|
30228
30392
|
}
|
|
@@ -30240,18 +30404,18 @@ async function promptConnection2(existingNames) {
|
|
|
30240
30404
|
var seqAuth = createConnectionAuth({
|
|
30241
30405
|
load: loadConnections2,
|
|
30242
30406
|
save: saveConnections2,
|
|
30243
|
-
format: (c) => `${
|
|
30407
|
+
format: (c) => `${chalk212.bold(c.name)} ${c.url}`,
|
|
30244
30408
|
promptNew: promptConnection2,
|
|
30245
30409
|
onFirst: (c) => setDefaultConnection(c.name)
|
|
30246
30410
|
});
|
|
30247
30411
|
|
|
30248
30412
|
// src/commands/seq/seqQuery.ts
|
|
30249
|
-
import
|
|
30413
|
+
import chalk216 from "chalk";
|
|
30250
30414
|
|
|
30251
30415
|
// src/commands/seq/fetchSeq.ts
|
|
30252
|
-
import
|
|
30253
|
-
async function fetchSeq(conn,
|
|
30254
|
-
const url = `${conn.url}${
|
|
30416
|
+
import chalk213 from "chalk";
|
|
30417
|
+
async function fetchSeq(conn, path88, params) {
|
|
30418
|
+
const url = `${conn.url}${path88}?${params}`;
|
|
30255
30419
|
const response = await fetch(url, {
|
|
30256
30420
|
headers: {
|
|
30257
30421
|
Accept: "application/json",
|
|
@@ -30260,7 +30424,7 @@ async function fetchSeq(conn, path84, params) {
|
|
|
30260
30424
|
});
|
|
30261
30425
|
if (!response.ok) {
|
|
30262
30426
|
const body = await response.text();
|
|
30263
|
-
console.error(
|
|
30427
|
+
console.error(chalk213.red(`Seq returned ${response.status}: ${body}`));
|
|
30264
30428
|
process.exit(1);
|
|
30265
30429
|
}
|
|
30266
30430
|
return response;
|
|
@@ -30319,23 +30483,23 @@ async function fetchSeqEvents(conn, params) {
|
|
|
30319
30483
|
}
|
|
30320
30484
|
|
|
30321
30485
|
// src/commands/seq/formatEvent.ts
|
|
30322
|
-
import
|
|
30486
|
+
import chalk214 from "chalk";
|
|
30323
30487
|
function levelColor(level) {
|
|
30324
30488
|
switch (level) {
|
|
30325
30489
|
case "Fatal":
|
|
30326
|
-
return
|
|
30490
|
+
return chalk214.bgRed.white;
|
|
30327
30491
|
case "Error":
|
|
30328
|
-
return
|
|
30492
|
+
return chalk214.red;
|
|
30329
30493
|
case "Warning":
|
|
30330
|
-
return
|
|
30494
|
+
return chalk214.yellow;
|
|
30331
30495
|
case "Information":
|
|
30332
|
-
return
|
|
30496
|
+
return chalk214.cyan;
|
|
30333
30497
|
case "Debug":
|
|
30334
|
-
return
|
|
30498
|
+
return chalk214.gray;
|
|
30335
30499
|
case "Verbose":
|
|
30336
|
-
return
|
|
30500
|
+
return chalk214.dim;
|
|
30337
30501
|
default:
|
|
30338
|
-
return
|
|
30502
|
+
return chalk214.white;
|
|
30339
30503
|
}
|
|
30340
30504
|
}
|
|
30341
30505
|
function levelAbbrev(level) {
|
|
@@ -30376,12 +30540,12 @@ function formatTimestamp(iso) {
|
|
|
30376
30540
|
function formatEvent(event) {
|
|
30377
30541
|
const color = levelColor(event.Level);
|
|
30378
30542
|
const abbrev = levelAbbrev(event.Level);
|
|
30379
|
-
const ts8 =
|
|
30543
|
+
const ts8 = chalk214.dim(formatTimestamp(event.Timestamp));
|
|
30380
30544
|
const msg = renderMessage(event);
|
|
30381
30545
|
const lines2 = [`${ts8} ${color(`[${abbrev}]`)} ${msg}`];
|
|
30382
30546
|
if (event.Exception) {
|
|
30383
30547
|
for (const line of event.Exception.split("\n")) {
|
|
30384
|
-
lines2.push(
|
|
30548
|
+
lines2.push(chalk214.red(` ${line}`));
|
|
30385
30549
|
}
|
|
30386
30550
|
}
|
|
30387
30551
|
return lines2.join("\n");
|
|
@@ -30414,11 +30578,11 @@ function rejectTimestampFilter(filter) {
|
|
|
30414
30578
|
}
|
|
30415
30579
|
|
|
30416
30580
|
// src/shared/resolveNamedConnection.ts
|
|
30417
|
-
import
|
|
30581
|
+
import chalk215 from "chalk";
|
|
30418
30582
|
function resolveNamedConnection(connections, requested, defaultName, kind, authCommand) {
|
|
30419
30583
|
if (connections.length === 0) {
|
|
30420
30584
|
console.error(
|
|
30421
|
-
|
|
30585
|
+
chalk215.red(
|
|
30422
30586
|
`No ${kind} connections configured. Run '${authCommand}' first.`
|
|
30423
30587
|
)
|
|
30424
30588
|
);
|
|
@@ -30427,7 +30591,7 @@ function resolveNamedConnection(connections, requested, defaultName, kind, authC
|
|
|
30427
30591
|
const target = requested ?? defaultName ?? connections[0].name;
|
|
30428
30592
|
const connection = connections.find((c) => c.name === target);
|
|
30429
30593
|
if (!connection) {
|
|
30430
|
-
console.error(
|
|
30594
|
+
console.error(chalk215.red(`${kind} connection "${target}" not found.`));
|
|
30431
30595
|
process.exit(1);
|
|
30432
30596
|
}
|
|
30433
30597
|
return connection;
|
|
@@ -30456,7 +30620,7 @@ async function seqQuery(filter, options2) {
|
|
|
30456
30620
|
new URLSearchParams({ filter, count: String(count8) })
|
|
30457
30621
|
);
|
|
30458
30622
|
if (events.length === 0) {
|
|
30459
|
-
console.log(
|
|
30623
|
+
console.log(chalk216.yellow("No events found."));
|
|
30460
30624
|
return;
|
|
30461
30625
|
}
|
|
30462
30626
|
if (options2.json) {
|
|
@@ -30467,11 +30631,11 @@ async function seqQuery(filter, options2) {
|
|
|
30467
30631
|
for (const event of chronological) {
|
|
30468
30632
|
console.log(formatEvent(event));
|
|
30469
30633
|
}
|
|
30470
|
-
console.log(
|
|
30634
|
+
console.log(chalk216.dim(`
|
|
30471
30635
|
${events.length} events`));
|
|
30472
30636
|
if (events.length >= count8) {
|
|
30473
30637
|
console.log(
|
|
30474
|
-
|
|
30638
|
+
chalk216.yellow(
|
|
30475
30639
|
`Results limited to ${count8}. Use --count to retrieve more.`
|
|
30476
30640
|
)
|
|
30477
30641
|
);
|
|
@@ -30479,10 +30643,10 @@ ${events.length} events`));
|
|
|
30479
30643
|
}
|
|
30480
30644
|
|
|
30481
30645
|
// src/shared/setNamedDefaultConnection.ts
|
|
30482
|
-
import
|
|
30646
|
+
import chalk217 from "chalk";
|
|
30483
30647
|
function setNamedDefaultConnection(connections, name, setDefault, kind) {
|
|
30484
30648
|
if (!connections.find((c) => c.name === name)) {
|
|
30485
|
-
console.error(
|
|
30649
|
+
console.error(chalk217.red(`Connection "${name}" not found.`));
|
|
30486
30650
|
process.exit(1);
|
|
30487
30651
|
}
|
|
30488
30652
|
setDefault(name);
|
|
@@ -30531,7 +30695,7 @@ function registerSignal(program2) {
|
|
|
30531
30695
|
}
|
|
30532
30696
|
|
|
30533
30697
|
// src/commands/sql/sqlAuth.ts
|
|
30534
|
-
import
|
|
30698
|
+
import chalk219 from "chalk";
|
|
30535
30699
|
|
|
30536
30700
|
// src/commands/sql/loadConnections.ts
|
|
30537
30701
|
function loadConnections3() {
|
|
@@ -30560,7 +30724,7 @@ function setDefaultConnection2(name) {
|
|
|
30560
30724
|
}
|
|
30561
30725
|
|
|
30562
30726
|
// src/commands/sql/promptConnection.ts
|
|
30563
|
-
import
|
|
30727
|
+
import chalk218 from "chalk";
|
|
30564
30728
|
async function promptConnection3(existingNames) {
|
|
30565
30729
|
const name = await promptInput("name", "Connection name:", "default");
|
|
30566
30730
|
assertUniqueName(existingNames, name);
|
|
@@ -30568,7 +30732,7 @@ async function promptConnection3(existingNames) {
|
|
|
30568
30732
|
const portStr = await promptInput("port", "Port:", "1433");
|
|
30569
30733
|
const port = Number.parseInt(portStr, 10);
|
|
30570
30734
|
if (!Number.isFinite(port)) {
|
|
30571
|
-
console.error(
|
|
30735
|
+
console.error(chalk218.red(`Invalid port "${portStr}".`));
|
|
30572
30736
|
process.exit(1);
|
|
30573
30737
|
}
|
|
30574
30738
|
const user = await promptInput("user", "User:");
|
|
@@ -30581,13 +30745,13 @@ async function promptConnection3(existingNames) {
|
|
|
30581
30745
|
var sqlAuth = createConnectionAuth({
|
|
30582
30746
|
load: loadConnections3,
|
|
30583
30747
|
save: saveConnections3,
|
|
30584
|
-
format: (c) => `${
|
|
30748
|
+
format: (c) => `${chalk219.bold(c.name)} ${c.server}:${c.port}/${c.database} (${c.user})`,
|
|
30585
30749
|
promptNew: promptConnection3,
|
|
30586
30750
|
onFirst: (c) => setDefaultConnection2(c.name)
|
|
30587
30751
|
});
|
|
30588
30752
|
|
|
30589
30753
|
// src/commands/sql/printTable.ts
|
|
30590
|
-
import
|
|
30754
|
+
import chalk220 from "chalk";
|
|
30591
30755
|
function formatCell(value) {
|
|
30592
30756
|
if (value === null || value === void 0) return "";
|
|
30593
30757
|
if (value instanceof Date) return value.toISOString();
|
|
@@ -30596,7 +30760,7 @@ function formatCell(value) {
|
|
|
30596
30760
|
}
|
|
30597
30761
|
function printTable(rows) {
|
|
30598
30762
|
if (rows.length === 0) {
|
|
30599
|
-
console.log(
|
|
30763
|
+
console.log(chalk220.yellow("(no rows)"));
|
|
30600
30764
|
return;
|
|
30601
30765
|
}
|
|
30602
30766
|
const columns = Object.keys(rows[0]);
|
|
@@ -30604,13 +30768,13 @@ function printTable(rows) {
|
|
|
30604
30768
|
(col) => Math.max(col.length, ...rows.map((r) => formatCell(r[col]).length))
|
|
30605
30769
|
);
|
|
30606
30770
|
const header = columns.map((c, i) => c.padEnd(widths[i])).join(" ");
|
|
30607
|
-
console.log(
|
|
30608
|
-
console.log(
|
|
30771
|
+
console.log(chalk220.dim(header));
|
|
30772
|
+
console.log(chalk220.dim("-".repeat(header.length)));
|
|
30609
30773
|
for (const row of rows) {
|
|
30610
30774
|
const line = columns.map((c, i) => formatCell(row[c]).padEnd(widths[i])).join(" ");
|
|
30611
30775
|
console.log(line);
|
|
30612
30776
|
}
|
|
30613
|
-
console.log(
|
|
30777
|
+
console.log(chalk220.dim(`
|
|
30614
30778
|
${rows.length} row${rows.length === 1 ? "" : "s"}`));
|
|
30615
30779
|
}
|
|
30616
30780
|
|
|
@@ -30670,7 +30834,7 @@ async function sqlColumns(table, connectionName) {
|
|
|
30670
30834
|
}
|
|
30671
30835
|
|
|
30672
30836
|
// src/commands/sql/sqlMutate.ts
|
|
30673
|
-
import
|
|
30837
|
+
import chalk221 from "chalk";
|
|
30674
30838
|
|
|
30675
30839
|
// src/commands/sql/isMutation.ts
|
|
30676
30840
|
var MUTATION_KEYWORDS = [
|
|
@@ -30704,7 +30868,7 @@ function isMutation(sql25) {
|
|
|
30704
30868
|
async function sqlMutate(query, connectionName) {
|
|
30705
30869
|
if (!isMutation(query)) {
|
|
30706
30870
|
console.error(
|
|
30707
|
-
|
|
30871
|
+
chalk221.red(
|
|
30708
30872
|
"assist sql mutate refuses non-mutating statements. Use `assist sql query` instead."
|
|
30709
30873
|
)
|
|
30710
30874
|
);
|
|
@@ -30714,18 +30878,18 @@ async function sqlMutate(query, connectionName) {
|
|
|
30714
30878
|
const pool = await sqlConnect(conn);
|
|
30715
30879
|
try {
|
|
30716
30880
|
const result = await pool.request().query(query);
|
|
30717
|
-
console.log(
|
|
30881
|
+
console.log(chalk221.dim(`${result.rowsAffected.join(", ")} row(s) affected`));
|
|
30718
30882
|
} finally {
|
|
30719
30883
|
await pool.close();
|
|
30720
30884
|
}
|
|
30721
30885
|
}
|
|
30722
30886
|
|
|
30723
30887
|
// src/commands/sql/sqlQuery.ts
|
|
30724
|
-
import
|
|
30888
|
+
import chalk222 from "chalk";
|
|
30725
30889
|
async function sqlQuery(query, connectionName) {
|
|
30726
30890
|
if (isMutation(query)) {
|
|
30727
30891
|
console.error(
|
|
30728
|
-
|
|
30892
|
+
chalk222.red(
|
|
30729
30893
|
"assist sql query refuses mutating statements. Use `assist sql mutate` instead."
|
|
30730
30894
|
)
|
|
30731
30895
|
);
|
|
@@ -30740,7 +30904,7 @@ async function sqlQuery(query, connectionName) {
|
|
|
30740
30904
|
printTable(rows);
|
|
30741
30905
|
} else {
|
|
30742
30906
|
console.log(
|
|
30743
|
-
|
|
30907
|
+
chalk222.dim(`${result.rowsAffected.join(", ")} row(s) affected`)
|
|
30744
30908
|
);
|
|
30745
30909
|
}
|
|
30746
30910
|
} finally {
|
|
@@ -30803,15 +30967,15 @@ function registerSql(program2) {
|
|
|
30803
30967
|
// src/commands/sync.ts
|
|
30804
30968
|
import * as fs48 from "fs";
|
|
30805
30969
|
import * as os5 from "os";
|
|
30806
|
-
import * as
|
|
30970
|
+
import * as path82 from "path";
|
|
30807
30971
|
import { fileURLToPath as fileURLToPath8 } from "url";
|
|
30808
30972
|
|
|
30809
30973
|
// src/commands/sync/pruneCommands.ts
|
|
30810
|
-
import * as
|
|
30974
|
+
import * as path73 from "path";
|
|
30811
30975
|
|
|
30812
30976
|
// src/commands/sync/pruneTarget.ts
|
|
30813
30977
|
import * as fs40 from "fs";
|
|
30814
|
-
import * as
|
|
30978
|
+
import * as path72 from "path";
|
|
30815
30979
|
function pruneTarget(targetDir, keepNames, shape, options2) {
|
|
30816
30980
|
const result = {
|
|
30817
30981
|
orphans: [],
|
|
@@ -30829,7 +30993,7 @@ function pruneTarget(targetDir, keepNames, shape, options2) {
|
|
|
30829
30993
|
}
|
|
30830
30994
|
if (keep.has(name)) continue;
|
|
30831
30995
|
result.orphans.push(entry.name);
|
|
30832
|
-
const entryPath =
|
|
30996
|
+
const entryPath = path72.join(targetDir, entry.name);
|
|
30833
30997
|
const reason4 = shape.blockedBy?.(entryPath);
|
|
30834
30998
|
if (reason4) {
|
|
30835
30999
|
result.skipped.push({ name: entry.name, reason: reason4 });
|
|
@@ -30849,7 +31013,7 @@ function pruneCommands(targetDir, commandNames, options2) {
|
|
|
30849
31013
|
targetDir,
|
|
30850
31014
|
commandNames,
|
|
30851
31015
|
{
|
|
30852
|
-
nameOf: (entry) => entry.isFile() && entry.name.endsWith(".md") ?
|
|
31016
|
+
nameOf: (entry) => entry.isFile() && entry.name.endsWith(".md") ? path73.basename(entry.name, ".md") : void 0
|
|
30853
31017
|
},
|
|
30854
31018
|
options2
|
|
30855
31019
|
);
|
|
@@ -30884,24 +31048,24 @@ function reportPrune(label2, result, force) {
|
|
|
30884
31048
|
|
|
30885
31049
|
// src/commands/sync/syncClaudeMd.ts
|
|
30886
31050
|
import * as fs41 from "fs";
|
|
30887
|
-
import * as
|
|
30888
|
-
import
|
|
31051
|
+
import * as path74 from "path";
|
|
31052
|
+
import chalk223 from "chalk";
|
|
30889
31053
|
async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
30890
|
-
const source =
|
|
30891
|
-
const target =
|
|
31054
|
+
const source = path74.join(claudeDir, "CLAUDE.md");
|
|
31055
|
+
const target = path74.join(targetBase, "CLAUDE.md");
|
|
30892
31056
|
const sourceContent = fs41.readFileSync(source, "utf8");
|
|
30893
31057
|
if (fs41.existsSync(target)) {
|
|
30894
31058
|
const targetContent = fs41.readFileSync(target, "utf8");
|
|
30895
31059
|
if (sourceContent !== targetContent) {
|
|
30896
31060
|
console.log(
|
|
30897
|
-
|
|
31061
|
+
chalk223.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
30898
31062
|
);
|
|
30899
31063
|
console.log();
|
|
30900
31064
|
printDiff(targetContent, sourceContent);
|
|
30901
31065
|
if (!options2?.yes) {
|
|
30902
31066
|
printAutoConfirmHint();
|
|
30903
31067
|
const confirm = await promptConfirm(
|
|
30904
|
-
|
|
31068
|
+
chalk223.red("Overwrite existing CLAUDE.md?"),
|
|
30905
31069
|
false
|
|
30906
31070
|
);
|
|
30907
31071
|
if (!confirm) {
|
|
@@ -30916,13 +31080,13 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
30916
31080
|
}
|
|
30917
31081
|
|
|
30918
31082
|
// src/commands/sync/syncCodex.ts
|
|
30919
|
-
import * as
|
|
31083
|
+
import * as path77 from "path";
|
|
30920
31084
|
|
|
30921
31085
|
// src/commands/sync/installHarnessCommands.ts
|
|
30922
31086
|
import * as fs42 from "fs";
|
|
30923
|
-
import * as
|
|
31087
|
+
import * as path75 from "path";
|
|
30924
31088
|
function installHarnessCommands(claudeDir, harness, transform) {
|
|
30925
|
-
const commandsSource =
|
|
31089
|
+
const commandsSource = path75.join(claudeDir, "commands");
|
|
30926
31090
|
const files = fs42.readdirSync(commandsSource);
|
|
30927
31091
|
const names = [];
|
|
30928
31092
|
let synced = 0;
|
|
@@ -30930,15 +31094,15 @@ function installHarnessCommands(claudeDir, harness, transform) {
|
|
|
30930
31094
|
if (!file.endsWith(".md")) continue;
|
|
30931
31095
|
const name = file.replace(/\.md$/, "");
|
|
30932
31096
|
names.push(name);
|
|
30933
|
-
const content = fs42.readFileSync(
|
|
30934
|
-
const target =
|
|
30935
|
-
fs42.mkdirSync(
|
|
31097
|
+
const content = fs42.readFileSync(path75.join(commandsSource, file), "utf8");
|
|
31098
|
+
const target = path75.join(harness.homeDir, harness.sync.commandDest(name));
|
|
31099
|
+
fs42.mkdirSync(path75.dirname(target), { recursive: true });
|
|
30936
31100
|
fs42.writeFileSync(target, transform(name, content));
|
|
30937
31101
|
synced++;
|
|
30938
31102
|
}
|
|
30939
|
-
const agentsTarget =
|
|
30940
|
-
fs42.mkdirSync(
|
|
30941
|
-
fs42.copyFileSync(
|
|
31103
|
+
const agentsTarget = path75.join(harness.homeDir, harness.sync.agentsFile);
|
|
31104
|
+
fs42.mkdirSync(path75.dirname(agentsTarget), { recursive: true });
|
|
31105
|
+
fs42.copyFileSync(path75.join(claudeDir, "CLAUDE.md"), agentsTarget);
|
|
30942
31106
|
return { total: files.length, synced, names };
|
|
30943
31107
|
}
|
|
30944
31108
|
|
|
@@ -30964,7 +31128,7 @@ function unexpectedContent(skillDir) {
|
|
|
30964
31128
|
|
|
30965
31129
|
// src/commands/sync/syncCodexHooks.ts
|
|
30966
31130
|
import * as fs44 from "fs";
|
|
30967
|
-
import * as
|
|
31131
|
+
import * as path76 from "path";
|
|
30968
31132
|
var BEGIN = "# >>> assist codex hooks (managed) \u2014 do not edit >>>";
|
|
30969
31133
|
var END = "# <<< assist codex hooks (managed) <<<";
|
|
30970
31134
|
function upsertManagedBlock(existing, body) {
|
|
@@ -30995,9 +31159,9 @@ ${rest}
|
|
|
30995
31159
|
}
|
|
30996
31160
|
function syncCodexHooks(sourcePath) {
|
|
30997
31161
|
const body = fs44.readFileSync(sourcePath, "utf8");
|
|
30998
|
-
const configPath =
|
|
31162
|
+
const configPath = path76.join(harnesses.codex.homeDir, "config.toml");
|
|
30999
31163
|
const existing = fs44.existsSync(configPath) ? fs44.readFileSync(configPath, "utf8") : "";
|
|
31000
|
-
fs44.mkdirSync(
|
|
31164
|
+
fs44.mkdirSync(path76.dirname(configPath), { recursive: true });
|
|
31001
31165
|
fs44.writeFileSync(configPath, upsertManagedBlock(existing, body));
|
|
31002
31166
|
console.log(
|
|
31003
31167
|
"Registered assist codex-hook in ~/.codex/config.toml (UserPromptSubmit, PreToolUse, PostToolUse, PermissionRequest, Stop)"
|
|
@@ -31029,7 +31193,7 @@ function syncCodex(claudeDir, options2) {
|
|
|
31029
31193
|
harnesses.codex,
|
|
31030
31194
|
commandToSkill
|
|
31031
31195
|
);
|
|
31032
|
-
syncCodexHooks(
|
|
31196
|
+
syncCodexHooks(path77.join(claudeDir, "..", "codex", "config.toml"));
|
|
31033
31197
|
console.log(
|
|
31034
31198
|
`Synced ${total} skill(s) to ~/.codex/skills and CLAUDE.md to ~/.codex/AGENTS.md`
|
|
31035
31199
|
);
|
|
@@ -31037,42 +31201,42 @@ function syncCodex(claudeDir, options2) {
|
|
|
31037
31201
|
const force = options2.force ?? false;
|
|
31038
31202
|
reportPrune(
|
|
31039
31203
|
"~/.codex/skills",
|
|
31040
|
-
pruneSkills(
|
|
31204
|
+
pruneSkills(path77.join(harnesses.codex.homeDir, "skills"), names, { force }),
|
|
31041
31205
|
force
|
|
31042
31206
|
);
|
|
31043
31207
|
}
|
|
31044
31208
|
|
|
31045
31209
|
// src/commands/sync/syncDesign.ts
|
|
31046
31210
|
import * as fs45 from "fs";
|
|
31047
|
-
import * as
|
|
31211
|
+
import * as path78 from "path";
|
|
31048
31212
|
function syncDesign(claudeDir, targetBase) {
|
|
31049
|
-
const systemPromptSource =
|
|
31050
|
-
const systemPromptTarget =
|
|
31213
|
+
const systemPromptSource = path78.join(claudeDir, "design-system-prompt.md");
|
|
31214
|
+
const systemPromptTarget = path78.join(targetBase, "design-system-prompt.md");
|
|
31051
31215
|
fs45.copyFileSync(systemPromptSource, systemPromptTarget);
|
|
31052
31216
|
console.log(
|
|
31053
31217
|
"Copied design-system-prompt.md to ~/.claude/design-system-prompt.md"
|
|
31054
31218
|
);
|
|
31055
|
-
const skillsSource =
|
|
31056
|
-
const skillsTarget =
|
|
31219
|
+
const skillsSource = path78.join(claudeDir, "skills");
|
|
31220
|
+
const skillsTarget = path78.join(targetBase, "skills");
|
|
31057
31221
|
fs45.mkdirSync(skillsTarget, { recursive: true });
|
|
31058
31222
|
const files = fs45.readdirSync(skillsSource);
|
|
31059
31223
|
for (const file of files) {
|
|
31060
31224
|
fs45.copyFileSync(
|
|
31061
|
-
|
|
31062
|
-
|
|
31225
|
+
path78.join(skillsSource, file),
|
|
31226
|
+
path78.join(skillsTarget, file)
|
|
31063
31227
|
);
|
|
31064
31228
|
}
|
|
31065
31229
|
console.log(`Synced ${files.length} design skill(s) to ~/.claude/skills`);
|
|
31066
31230
|
}
|
|
31067
31231
|
|
|
31068
31232
|
// src/commands/sync/syncPi.ts
|
|
31069
|
-
import * as
|
|
31233
|
+
import * as path80 from "path";
|
|
31070
31234
|
|
|
31071
31235
|
// src/commands/sync/syncPiHooks.ts
|
|
31072
31236
|
import * as fs46 from "fs";
|
|
31073
|
-
import * as
|
|
31237
|
+
import * as path79 from "path";
|
|
31074
31238
|
function piExtensionsDir() {
|
|
31075
|
-
return
|
|
31239
|
+
return path79.join(harnesses.pi.homeDir, "extensions");
|
|
31076
31240
|
}
|
|
31077
31241
|
function syncPiHooks(sourceDir) {
|
|
31078
31242
|
const target = piExtensionsDir();
|
|
@@ -31080,8 +31244,8 @@ function syncPiHooks(sourceDir) {
|
|
|
31080
31244
|
const files = fs46.readdirSync(sourceDir).filter((f) => f.endsWith(".ts"));
|
|
31081
31245
|
for (const file of files) {
|
|
31082
31246
|
fs46.copyFileSync(
|
|
31083
|
-
|
|
31084
|
-
|
|
31247
|
+
path79.join(sourceDir, file),
|
|
31248
|
+
path79.join(target, `assist-${file}`)
|
|
31085
31249
|
);
|
|
31086
31250
|
}
|
|
31087
31251
|
console.log(
|
|
@@ -31118,7 +31282,7 @@ function syncPi(claudeDir, options2) {
|
|
|
31118
31282
|
harnesses.pi,
|
|
31119
31283
|
commandToPrompt
|
|
31120
31284
|
);
|
|
31121
|
-
syncPiHooks(
|
|
31285
|
+
syncPiHooks(path80.join(claudeDir, "..", "pi"));
|
|
31122
31286
|
console.log(
|
|
31123
31287
|
`Synced ${synced} prompt(s) to ~/.pi/agent/prompts and CLAUDE.md to ~/.pi/agent/AGENTS.md`
|
|
31124
31288
|
);
|
|
@@ -31126,18 +31290,18 @@ function syncPi(claudeDir, options2) {
|
|
|
31126
31290
|
const force = options2.force ?? false;
|
|
31127
31291
|
reportPrune(
|
|
31128
31292
|
"~/.pi/agent/prompts",
|
|
31129
|
-
pruneCommands(
|
|
31293
|
+
pruneCommands(path80.join(harnesses.pi.homeDir, "prompts"), names, { force }),
|
|
31130
31294
|
force
|
|
31131
31295
|
);
|
|
31132
31296
|
}
|
|
31133
31297
|
|
|
31134
31298
|
// src/commands/sync/syncSettings.ts
|
|
31135
31299
|
import * as fs47 from "fs";
|
|
31136
|
-
import * as
|
|
31137
|
-
import
|
|
31300
|
+
import * as path81 from "path";
|
|
31301
|
+
import chalk224 from "chalk";
|
|
31138
31302
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
31139
|
-
const source =
|
|
31140
|
-
const target =
|
|
31303
|
+
const source = path81.join(claudeDir, "settings.json");
|
|
31304
|
+
const target = path81.join(targetBase, "settings.json");
|
|
31141
31305
|
const sourceContent = fs47.readFileSync(source, "utf8");
|
|
31142
31306
|
const sourceSettings = JSON.parse(sourceContent);
|
|
31143
31307
|
const targetExists = fs47.existsSync(target);
|
|
@@ -31153,7 +31317,7 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
31153
31317
|
if (mergedContent !== normalizedTarget) {
|
|
31154
31318
|
if (!options2?.yes) {
|
|
31155
31319
|
console.log(
|
|
31156
|
-
|
|
31320
|
+
chalk224.yellow(
|
|
31157
31321
|
"\n\u26A0\uFE0F Warning: settings.json differs from existing file"
|
|
31158
31322
|
)
|
|
31159
31323
|
);
|
|
@@ -31161,7 +31325,7 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
31161
31325
|
printDiff(targetContent, mergedContent);
|
|
31162
31326
|
printAutoConfirmHint();
|
|
31163
31327
|
const confirm = await promptConfirm(
|
|
31164
|
-
|
|
31328
|
+
chalk224.red("Overwrite existing settings.json?"),
|
|
31165
31329
|
false
|
|
31166
31330
|
);
|
|
31167
31331
|
if (!confirm) {
|
|
@@ -31177,13 +31341,13 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
31177
31341
|
|
|
31178
31342
|
// src/commands/sync.ts
|
|
31179
31343
|
var __filename4 = fileURLToPath8(import.meta.url);
|
|
31180
|
-
var __dirname5 =
|
|
31344
|
+
var __dirname5 = path82.dirname(__filename4);
|
|
31181
31345
|
async function sync(options2) {
|
|
31182
31346
|
const config = loadConfig();
|
|
31183
31347
|
const yes = options2?.yes ?? config.sync.autoConfirm;
|
|
31184
31348
|
const prune = { prune: options2?.prune, force: options2?.force };
|
|
31185
|
-
const claudeDir =
|
|
31186
|
-
const targetBase =
|
|
31349
|
+
const claudeDir = path82.join(__dirname5, "..", "claude");
|
|
31350
|
+
const targetBase = path82.join(os5.homedir(), ".claude");
|
|
31187
31351
|
const commandFiles = syncCommands(claudeDir, targetBase);
|
|
31188
31352
|
syncDesign(claudeDir, targetBase);
|
|
31189
31353
|
await syncSettings(claudeDir, targetBase, { yes });
|
|
@@ -31191,21 +31355,21 @@ async function sync(options2) {
|
|
|
31191
31355
|
syncCodex(claudeDir, prune);
|
|
31192
31356
|
syncPi(claudeDir, prune);
|
|
31193
31357
|
if (!options2?.prune) return;
|
|
31194
|
-
const commandNames = commandFiles.filter((file) => file.endsWith(".md")).map((file) =>
|
|
31358
|
+
const commandNames = commandFiles.filter((file) => file.endsWith(".md")).map((file) => path82.basename(file, ".md"));
|
|
31195
31359
|
const force = options2.force ?? false;
|
|
31196
31360
|
reportPrune(
|
|
31197
31361
|
"~/.claude/commands",
|
|
31198
|
-
pruneCommands(
|
|
31362
|
+
pruneCommands(path82.join(targetBase, "commands"), commandNames, { force }),
|
|
31199
31363
|
force
|
|
31200
31364
|
);
|
|
31201
31365
|
}
|
|
31202
31366
|
function syncCommands(claudeDir, targetBase) {
|
|
31203
|
-
const sourceDir =
|
|
31204
|
-
const targetDir =
|
|
31367
|
+
const sourceDir = path82.join(claudeDir, "commands");
|
|
31368
|
+
const targetDir = path82.join(targetBase, "commands");
|
|
31205
31369
|
fs48.mkdirSync(targetDir, { recursive: true });
|
|
31206
31370
|
const files = fs48.readdirSync(sourceDir);
|
|
31207
31371
|
for (const file of files) {
|
|
31208
|
-
fs48.copyFileSync(
|
|
31372
|
+
fs48.copyFileSync(path82.join(sourceDir, file), path82.join(targetDir, file));
|
|
31209
31373
|
console.log(`Copied ${file} to ${targetDir}`);
|
|
31210
31374
|
}
|
|
31211
31375
|
console.log(`Synced ${files.length} command(s) to ~/.claude/commands`);
|
|
@@ -31233,7 +31397,7 @@ function registerSync(program2) {
|
|
|
31233
31397
|
}
|
|
31234
31398
|
|
|
31235
31399
|
// src/commands/transcript/clean.ts
|
|
31236
|
-
import { existsSync as
|
|
31400
|
+
import { existsSync as existsSync70 } from "fs";
|
|
31237
31401
|
|
|
31238
31402
|
// src/commands/transcript/cleanText.ts
|
|
31239
31403
|
function cleanText(text18) {
|
|
@@ -31457,9 +31621,9 @@ function formatVtt(cues) {
|
|
|
31457
31621
|
}
|
|
31458
31622
|
|
|
31459
31623
|
// src/commands/transcript/convert/readCleanedCues.ts
|
|
31460
|
-
import { readFileSync as
|
|
31624
|
+
import { readFileSync as readFileSync54 } from "fs";
|
|
31461
31625
|
function readCleanedCues(inputPath) {
|
|
31462
|
-
return deduplicateCues(parseVtt(
|
|
31626
|
+
return deduplicateCues(parseVtt(readFileSync54(inputPath, "utf8")));
|
|
31463
31627
|
}
|
|
31464
31628
|
|
|
31465
31629
|
// src/commands/transcript/clean.ts
|
|
@@ -31478,7 +31642,7 @@ function clean(file, options2 = {}) {
|
|
|
31478
31642
|
);
|
|
31479
31643
|
process.exit(1);
|
|
31480
31644
|
}
|
|
31481
|
-
if (!
|
|
31645
|
+
if (!existsSync70(file)) {
|
|
31482
31646
|
console.error(`Error: VTT file not found: ${file}`);
|
|
31483
31647
|
process.exit(1);
|
|
31484
31648
|
}
|
|
@@ -31561,12 +31725,12 @@ async function configure() {
|
|
|
31561
31725
|
}
|
|
31562
31726
|
|
|
31563
31727
|
// src/commands/transcript/list.ts
|
|
31564
|
-
import { existsSync as
|
|
31728
|
+
import { existsSync as existsSync71, readdirSync as readdirSync20, statSync as statSync11 } from "fs";
|
|
31565
31729
|
import { join as join83 } from "path";
|
|
31566
31730
|
function list4() {
|
|
31567
31731
|
const { vttDir } = getTranscriptConfig();
|
|
31568
|
-
if (!
|
|
31569
|
-
for (const entry of
|
|
31732
|
+
if (!existsSync71(vttDir)) return;
|
|
31733
|
+
for (const entry of readdirSync20(vttDir)) {
|
|
31570
31734
|
if (!entry.endsWith(".vtt")) continue;
|
|
31571
31735
|
if (statSync11(join83(vttDir, entry)).isDirectory()) continue;
|
|
31572
31736
|
console.log(entry);
|
|
@@ -31574,7 +31738,7 @@ function list4() {
|
|
|
31574
31738
|
}
|
|
31575
31739
|
|
|
31576
31740
|
// src/commands/transcript/move.ts
|
|
31577
|
-
import { existsSync as
|
|
31741
|
+
import { existsSync as existsSync72, mkdirSync as mkdirSync27, renameSync as renameSync2, writeFileSync as writeFileSync44 } from "fs";
|
|
31578
31742
|
import { basename as basename21, join as join84 } from "path";
|
|
31579
31743
|
|
|
31580
31744
|
// src/commands/transcript/convertVttToMarkdown.ts
|
|
@@ -31598,7 +31762,7 @@ function move(file, options2) {
|
|
|
31598
31762
|
const { vttDir, transcriptsDir, summaryDir } = getTranscriptConfig();
|
|
31599
31763
|
const filename = basename21(file);
|
|
31600
31764
|
const sourcePath = join84(vttDir, filename);
|
|
31601
|
-
if (!
|
|
31765
|
+
if (!existsSync72(sourcePath)) {
|
|
31602
31766
|
console.error(`Error: VTT file not found: ${sourcePath}`);
|
|
31603
31767
|
process.exit(1);
|
|
31604
31768
|
}
|
|
@@ -31607,7 +31771,7 @@ function move(file, options2) {
|
|
|
31607
31771
|
const formattedDir = join84(transcriptsDir, client);
|
|
31608
31772
|
mkdirSync27(formattedDir, { recursive: true });
|
|
31609
31773
|
const formattedPath = join84(formattedDir, outputName);
|
|
31610
|
-
|
|
31774
|
+
writeFileSync44(formattedPath, convertVttToMarkdown(sourcePath), "utf8");
|
|
31611
31775
|
archiveRawVtt(vttDir, sourcePath, filename);
|
|
31612
31776
|
const summaryPath = join84(summaryDir, client, outputName);
|
|
31613
31777
|
console.log(`Formatted transcript: ${formattedPath}`);
|
|
@@ -31728,14 +31892,14 @@ function devices() {
|
|
|
31728
31892
|
}
|
|
31729
31893
|
|
|
31730
31894
|
// src/commands/voice/logs.ts
|
|
31731
|
-
import { existsSync as
|
|
31895
|
+
import { existsSync as existsSync73, readFileSync as readFileSync55 } from "fs";
|
|
31732
31896
|
function logs(options2) {
|
|
31733
|
-
if (!
|
|
31897
|
+
if (!existsSync73(voicePaths.log)) {
|
|
31734
31898
|
console.log("No voice log file found");
|
|
31735
31899
|
return;
|
|
31736
31900
|
}
|
|
31737
31901
|
const count8 = Number.parseInt(options2.lines ?? "150", 10);
|
|
31738
|
-
const content =
|
|
31902
|
+
const content = readFileSync55(voicePaths.log, "utf8").trim();
|
|
31739
31903
|
if (!content) {
|
|
31740
31904
|
console.log("Voice log is empty");
|
|
31741
31905
|
return;
|
|
@@ -31762,7 +31926,7 @@ import { join as join88 } from "path";
|
|
|
31762
31926
|
|
|
31763
31927
|
// src/commands/voice/checkLockFile.ts
|
|
31764
31928
|
import { execSync as execSync58 } from "child_process";
|
|
31765
|
-
import { existsSync as
|
|
31929
|
+
import { existsSync as existsSync74, mkdirSync as mkdirSync28, readFileSync as readFileSync56, writeFileSync as writeFileSync45 } from "fs";
|
|
31766
31930
|
import { join as join87 } from "path";
|
|
31767
31931
|
function isProcessAlive2(pid) {
|
|
31768
31932
|
try {
|
|
@@ -31774,9 +31938,9 @@ function isProcessAlive2(pid) {
|
|
|
31774
31938
|
}
|
|
31775
31939
|
function checkLockFile() {
|
|
31776
31940
|
const lockFile = getLockFile();
|
|
31777
|
-
if (!
|
|
31941
|
+
if (!existsSync74(lockFile)) return;
|
|
31778
31942
|
try {
|
|
31779
|
-
const lock2 = JSON.parse(
|
|
31943
|
+
const lock2 = JSON.parse(readFileSync56(lockFile, "utf8"));
|
|
31780
31944
|
if (lock2.pid && isProcessAlive2(lock2.pid)) {
|
|
31781
31945
|
console.error(
|
|
31782
31946
|
`Voice daemon already running (PID ${lock2.pid}, env: ${lock2.env}). Stop it first with: assist voice stop`
|
|
@@ -31787,7 +31951,7 @@ function checkLockFile() {
|
|
|
31787
31951
|
}
|
|
31788
31952
|
}
|
|
31789
31953
|
function bootstrapVenv() {
|
|
31790
|
-
if (
|
|
31954
|
+
if (existsSync74(getVenvPython())) return;
|
|
31791
31955
|
console.log("Setting up Python environment...");
|
|
31792
31956
|
const pythonDir = getPythonDir();
|
|
31793
31957
|
execSync58(
|
|
@@ -31801,7 +31965,7 @@ function bootstrapVenv() {
|
|
|
31801
31965
|
function writeLockFile(pid) {
|
|
31802
31966
|
const lockFile = getLockFile();
|
|
31803
31967
|
mkdirSync28(join87(lockFile, ".."), { recursive: true });
|
|
31804
|
-
|
|
31968
|
+
writeFileSync45(
|
|
31805
31969
|
lockFile,
|
|
31806
31970
|
JSON.stringify({
|
|
31807
31971
|
pid,
|
|
@@ -31829,7 +31993,7 @@ function setup() {
|
|
|
31829
31993
|
|
|
31830
31994
|
// src/commands/voice/start.ts
|
|
31831
31995
|
import { spawn as spawn8 } from "child_process";
|
|
31832
|
-
import { mkdirSync as mkdirSync30, writeFileSync as
|
|
31996
|
+
import { mkdirSync as mkdirSync30, writeFileSync as writeFileSync46 } from "fs";
|
|
31833
31997
|
import { join as join89 } from "path";
|
|
31834
31998
|
|
|
31835
31999
|
// src/commands/voice/buildDaemonEnv.ts
|
|
@@ -31858,7 +32022,7 @@ function spawnBackground(python, script, env) {
|
|
|
31858
32022
|
console.error("Failed to start voice daemon");
|
|
31859
32023
|
process.exit(1);
|
|
31860
32024
|
}
|
|
31861
|
-
|
|
32025
|
+
writeFileSync46(voicePaths.pid, String(pid));
|
|
31862
32026
|
writeLockFile(pid);
|
|
31863
32027
|
console.log(`Voice daemon started (PID ${pid})`);
|
|
31864
32028
|
}
|
|
@@ -31878,7 +32042,7 @@ function start2(options2) {
|
|
|
31878
32042
|
}
|
|
31879
32043
|
|
|
31880
32044
|
// src/commands/voice/status.ts
|
|
31881
|
-
import { existsSync as
|
|
32045
|
+
import { existsSync as existsSync75, readFileSync as readFileSync57 } from "fs";
|
|
31882
32046
|
function isProcessAlive3(pid) {
|
|
31883
32047
|
try {
|
|
31884
32048
|
process.kill(pid, 0);
|
|
@@ -31888,16 +32052,16 @@ function isProcessAlive3(pid) {
|
|
|
31888
32052
|
}
|
|
31889
32053
|
}
|
|
31890
32054
|
function readRecentLogs(count8) {
|
|
31891
|
-
if (!
|
|
31892
|
-
const lines2 =
|
|
32055
|
+
if (!existsSync75(voicePaths.log)) return [];
|
|
32056
|
+
const lines2 = readFileSync57(voicePaths.log, "utf8").trim().split("\n");
|
|
31893
32057
|
return lines2.slice(-count8);
|
|
31894
32058
|
}
|
|
31895
32059
|
function status2() {
|
|
31896
|
-
if (!
|
|
32060
|
+
if (!existsSync75(voicePaths.pid)) {
|
|
31897
32061
|
console.log("Voice daemon: not running (no PID file)");
|
|
31898
32062
|
return;
|
|
31899
32063
|
}
|
|
31900
|
-
const pid = Number.parseInt(
|
|
32064
|
+
const pid = Number.parseInt(readFileSync57(voicePaths.pid, "utf8").trim(), 10);
|
|
31901
32065
|
const alive = isProcessAlive3(pid);
|
|
31902
32066
|
console.log(`Voice daemon: ${alive ? "running" : "dead"} (PID ${pid})`);
|
|
31903
32067
|
const recent = readRecentLogs(5);
|
|
@@ -31916,13 +32080,13 @@ function status2() {
|
|
|
31916
32080
|
}
|
|
31917
32081
|
|
|
31918
32082
|
// src/commands/voice/stop.ts
|
|
31919
|
-
import { existsSync as
|
|
32083
|
+
import { existsSync as existsSync76, readFileSync as readFileSync58, unlinkSync as unlinkSync20 } from "fs";
|
|
31920
32084
|
function stop2() {
|
|
31921
|
-
if (!
|
|
32085
|
+
if (!existsSync76(voicePaths.pid)) {
|
|
31922
32086
|
console.log("Voice daemon is not running (no PID file)");
|
|
31923
32087
|
return;
|
|
31924
32088
|
}
|
|
31925
|
-
const pid = Number.parseInt(
|
|
32089
|
+
const pid = Number.parseInt(readFileSync58(voicePaths.pid, "utf8").trim(), 10);
|
|
31926
32090
|
try {
|
|
31927
32091
|
process.kill(pid, "SIGTERM");
|
|
31928
32092
|
console.log(`Sent SIGTERM to voice daemon (PID ${pid})`);
|
|
@@ -31935,7 +32099,7 @@ function stop2() {
|
|
|
31935
32099
|
}
|
|
31936
32100
|
try {
|
|
31937
32101
|
const lockFile = getLockFile();
|
|
31938
|
-
if (
|
|
32102
|
+
if (existsSync76(lockFile)) unlinkSync20(lockFile);
|
|
31939
32103
|
} catch {
|
|
31940
32104
|
}
|
|
31941
32105
|
console.log("Voice daemon stopped");
|
|
@@ -32060,11 +32224,11 @@ var webUiPrefix = "src/commands/sessions/web/ui/";
|
|
|
32060
32224
|
var sessionsPrefix = "src/commands/sessions/";
|
|
32061
32225
|
var rules = [
|
|
32062
32226
|
{
|
|
32063
|
-
matches: (
|
|
32227
|
+
matches: (path88) => path88.startsWith(webUiPrefix),
|
|
32064
32228
|
advice: "restart the web server, then hard-reload the browser tab"
|
|
32065
32229
|
},
|
|
32066
32230
|
{
|
|
32067
|
-
matches: (
|
|
32231
|
+
matches: (path88) => path88.startsWith(sessionsPrefix) && !path88.startsWith(webUiPrefix),
|
|
32068
32232
|
advice: "restart the daemon"
|
|
32069
32233
|
}
|
|
32070
32234
|
];
|
|
@@ -32075,31 +32239,31 @@ function restartAdvice(paths) {
|
|
|
32075
32239
|
// src/commands/watch/syncAdvice.ts
|
|
32076
32240
|
var rules2 = [
|
|
32077
32241
|
{
|
|
32078
|
-
matches: (
|
|
32242
|
+
matches: (path88) => path88.startsWith("claude/commands/"),
|
|
32079
32243
|
reason: "claude/commands changed"
|
|
32080
32244
|
},
|
|
32081
32245
|
{
|
|
32082
|
-
matches: (
|
|
32246
|
+
matches: (path88) => path88.startsWith("claude/skills/"),
|
|
32083
32247
|
reason: "claude/skills changed"
|
|
32084
32248
|
},
|
|
32085
32249
|
{
|
|
32086
|
-
matches: (
|
|
32250
|
+
matches: (path88) => path88 === "claude/settings.json",
|
|
32087
32251
|
reason: "claude/settings.json changed"
|
|
32088
32252
|
},
|
|
32089
32253
|
{
|
|
32090
|
-
matches: (
|
|
32254
|
+
matches: (path88) => path88 === "claude/CLAUDE.md",
|
|
32091
32255
|
reason: "claude/CLAUDE.md changed"
|
|
32092
32256
|
},
|
|
32093
32257
|
{
|
|
32094
|
-
matches: (
|
|
32258
|
+
matches: (path88) => path88 === "claude/design-system-prompt.md",
|
|
32095
32259
|
reason: "claude/design-system-prompt.md changed"
|
|
32096
32260
|
},
|
|
32097
32261
|
{
|
|
32098
|
-
matches: (
|
|
32262
|
+
matches: (path88) => path88.startsWith("codex/"),
|
|
32099
32263
|
reason: "codex sources changed"
|
|
32100
32264
|
},
|
|
32101
32265
|
{
|
|
32102
|
-
matches: (
|
|
32266
|
+
matches: (path88) => path88.startsWith("pi/"),
|
|
32103
32267
|
reason: "pi sources changed"
|
|
32104
32268
|
}
|
|
32105
32269
|
];
|
|
@@ -32340,7 +32504,7 @@ function resolveParams(params, cliArgs) {
|
|
|
32340
32504
|
}
|
|
32341
32505
|
|
|
32342
32506
|
// src/commands/run/resolveRunCwd.ts
|
|
32343
|
-
import { existsSync as
|
|
32507
|
+
import { existsSync as existsSync77 } from "fs";
|
|
32344
32508
|
import { resolve as resolve19 } from "path";
|
|
32345
32509
|
var MissingRunCwdError = class extends Error {
|
|
32346
32510
|
constructor(runName, cwd) {
|
|
@@ -32353,17 +32517,17 @@ var MissingRunCwdError = class extends Error {
|
|
|
32353
32517
|
function resolveRunCwd(config, baseDir = runConfigBaseDir()) {
|
|
32354
32518
|
if (!config.cwd) return void 0;
|
|
32355
32519
|
const cwd = resolve19(baseDir, config.cwd);
|
|
32356
|
-
if (!
|
|
32520
|
+
if (!existsSync77(cwd)) throw new MissingRunCwdError(config.name, cwd);
|
|
32357
32521
|
return cwd;
|
|
32358
32522
|
}
|
|
32359
32523
|
|
|
32360
32524
|
// src/commands/run/runCommandToCompletion.ts
|
|
32361
32525
|
import { spawn as spawn9 } from "child_process";
|
|
32362
|
-
import { existsSync as
|
|
32526
|
+
import { existsSync as existsSync79 } from "fs";
|
|
32363
32527
|
|
|
32364
32528
|
// src/commands/run/resolveCommand.ts
|
|
32365
32529
|
import { execFileSync as execFileSync16 } from "child_process";
|
|
32366
|
-
import { existsSync as
|
|
32530
|
+
import { existsSync as existsSync78 } from "fs";
|
|
32367
32531
|
import { dirname as dirname37, join as join91, resolve as resolve20 } from "path";
|
|
32368
32532
|
function resolveCommand2(command) {
|
|
32369
32533
|
if (process.platform !== "win32" || command !== "bash") return command;
|
|
@@ -32371,7 +32535,7 @@ function resolveCommand2(command) {
|
|
|
32371
32535
|
const gitPath = execFileSync16("where", ["git"], { encoding: "utf8" }).trim().split("\r\n")[0];
|
|
32372
32536
|
const gitRoot = resolve20(dirname37(gitPath), "..");
|
|
32373
32537
|
const gitBash = join91(gitRoot, "bin", "bash.exe");
|
|
32374
|
-
if (
|
|
32538
|
+
if (existsSync78(gitBash)) return gitBash;
|
|
32375
32539
|
} catch {
|
|
32376
32540
|
return command;
|
|
32377
32541
|
}
|
|
@@ -32381,7 +32545,7 @@ function resolveCommand2(command) {
|
|
|
32381
32545
|
// src/commands/run/runCommandToCompletion.ts
|
|
32382
32546
|
function runCommandToCompletion(command, args, env, cwd, quiet) {
|
|
32383
32547
|
return new Promise((resolveResult) => {
|
|
32384
|
-
if (cwd && !
|
|
32548
|
+
if (cwd && !existsSync79(cwd)) {
|
|
32385
32549
|
resolveResult({
|
|
32386
32550
|
kind: "failed",
|
|
32387
32551
|
message: `Failed to execute command: cwd ${cwd} does not exist`
|
|
@@ -32638,7 +32802,7 @@ function registerWatch(program2) {
|
|
|
32638
32802
|
|
|
32639
32803
|
// src/commands/roam/auth.ts
|
|
32640
32804
|
import { randomBytes } from "crypto";
|
|
32641
|
-
import
|
|
32805
|
+
import chalk225 from "chalk";
|
|
32642
32806
|
|
|
32643
32807
|
// src/commands/roam/waitForCallback.ts
|
|
32644
32808
|
import { createServer as createServer3 } from "http";
|
|
@@ -32769,13 +32933,13 @@ async function auth() {
|
|
|
32769
32933
|
saveGlobalConfig(config);
|
|
32770
32934
|
const state = randomBytes(16).toString("hex");
|
|
32771
32935
|
console.log(
|
|
32772
|
-
|
|
32936
|
+
chalk225.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
|
|
32773
32937
|
);
|
|
32774
|
-
console.log(
|
|
32775
|
-
console.log(
|
|
32776
|
-
console.log(
|
|
32938
|
+
console.log(chalk225.white("http://localhost:14523/callback\n"));
|
|
32939
|
+
console.log(chalk225.blue("Opening browser for authorization..."));
|
|
32940
|
+
console.log(chalk225.dim("Waiting for authorization callback..."));
|
|
32777
32941
|
const { code, redirectUri } = await authorizeInBrowser(clientId, state);
|
|
32778
|
-
console.log(
|
|
32942
|
+
console.log(chalk225.dim("Exchanging code for tokens..."));
|
|
32779
32943
|
const tokens = await exchangeToken({
|
|
32780
32944
|
code,
|
|
32781
32945
|
clientId,
|
|
@@ -32791,25 +32955,25 @@ async function auth() {
|
|
|
32791
32955
|
};
|
|
32792
32956
|
saveGlobalConfig(config);
|
|
32793
32957
|
console.log(
|
|
32794
|
-
|
|
32958
|
+
chalk225.green("Roam credentials and tokens saved to ~/.assist.yml")
|
|
32795
32959
|
);
|
|
32796
32960
|
}
|
|
32797
32961
|
|
|
32798
32962
|
// src/commands/roam/postRoamActivity.ts
|
|
32799
32963
|
import { execFileSync as execFileSync18 } from "child_process";
|
|
32800
|
-
import { readdirSync as
|
|
32964
|
+
import { readdirSync as readdirSync21, readFileSync as readFileSync59, statSync as statSync12 } from "fs";
|
|
32801
32965
|
import { join as join92 } from "path";
|
|
32802
32966
|
function findPortFile(roamDir) {
|
|
32803
32967
|
let entries;
|
|
32804
32968
|
try {
|
|
32805
|
-
entries =
|
|
32969
|
+
entries = readdirSync21(roamDir);
|
|
32806
32970
|
} catch {
|
|
32807
32971
|
return void 0;
|
|
32808
32972
|
}
|
|
32809
32973
|
const candidates = entries.filter((name) => /^roam-local-api(-[^.]+)?\.port$/.test(name)).map((name) => {
|
|
32810
|
-
const
|
|
32974
|
+
const path88 = join92(roamDir, name);
|
|
32811
32975
|
try {
|
|
32812
|
-
return { path:
|
|
32976
|
+
return { path: path88, mtimeMs: statSync12(path88).mtimeMs };
|
|
32813
32977
|
} catch {
|
|
32814
32978
|
return void 0;
|
|
32815
32979
|
}
|
|
@@ -32823,7 +32987,7 @@ function postRoamActivity(app, event) {
|
|
|
32823
32987
|
if (!portFile) return;
|
|
32824
32988
|
let port;
|
|
32825
32989
|
try {
|
|
32826
|
-
port =
|
|
32990
|
+
port = readFileSync59(portFile, "utf8").trim();
|
|
32827
32991
|
} catch {
|
|
32828
32992
|
return;
|
|
32829
32993
|
}
|
|
@@ -32951,7 +33115,7 @@ async function run3(name, args) {
|
|
|
32951
33115
|
}
|
|
32952
33116
|
|
|
32953
33117
|
// src/commands/run/add.ts
|
|
32954
|
-
import { mkdirSync as mkdirSync31, writeFileSync as
|
|
33118
|
+
import { mkdirSync as mkdirSync31, writeFileSync as writeFileSync47 } from "fs";
|
|
32955
33119
|
import { join as join93 } from "path";
|
|
32956
33120
|
|
|
32957
33121
|
// src/commands/run/extractOption.ts
|
|
@@ -33022,7 +33186,7 @@ description: Run ${name}
|
|
|
33022
33186
|
Run \`assist run ${name} $ARGUMENTS 2>&1\`.
|
|
33023
33187
|
`;
|
|
33024
33188
|
const filePath = join93(dir, `${name}.md`);
|
|
33025
|
-
|
|
33189
|
+
writeFileSync47(filePath, content);
|
|
33026
33190
|
console.log(`Created command file: ${filePath}`);
|
|
33027
33191
|
}
|
|
33028
33192
|
function add3() {
|
|
@@ -33045,11 +33209,11 @@ function findLinkIndex() {
|
|
|
33045
33209
|
function parseLinkArgs() {
|
|
33046
33210
|
const idx = findLinkIndex();
|
|
33047
33211
|
if (idx === -1) return null;
|
|
33048
|
-
const
|
|
33212
|
+
const path88 = process.argv[idx + 1];
|
|
33049
33213
|
const rest = process.argv.slice(idx + 2);
|
|
33050
33214
|
const { value: prefix2 } = extractOption(rest, "--prefix");
|
|
33051
33215
|
if (!prefix2) return null;
|
|
33052
|
-
return { path:
|
|
33216
|
+
return { path: path88, prefix: prefix2 };
|
|
33053
33217
|
}
|
|
33054
33218
|
function hasDuplicateLink(runList, linkPath) {
|
|
33055
33219
|
return runList.some(
|
|
@@ -33077,7 +33241,7 @@ function link2() {
|
|
|
33077
33241
|
}
|
|
33078
33242
|
|
|
33079
33243
|
// src/commands/run/remove.ts
|
|
33080
|
-
import { existsSync as
|
|
33244
|
+
import { existsSync as existsSync80, unlinkSync as unlinkSync21 } from "fs";
|
|
33081
33245
|
import { join as join94 } from "path";
|
|
33082
33246
|
function findRemoveIndex() {
|
|
33083
33247
|
const idx = process.argv.indexOf("remove");
|
|
@@ -33094,7 +33258,7 @@ function parseRemoveName() {
|
|
|
33094
33258
|
}
|
|
33095
33259
|
function deleteCommandFile(name) {
|
|
33096
33260
|
const filePath = join94(".claude", "commands", `${name}.md`);
|
|
33097
|
-
if (
|
|
33261
|
+
if (existsSync80(filePath)) {
|
|
33098
33262
|
unlinkSync21(filePath);
|
|
33099
33263
|
console.log(`Deleted command file: ${filePath}`);
|
|
33100
33264
|
}
|
|
@@ -33139,10 +33303,10 @@ function registerRun(program2) {
|
|
|
33139
33303
|
|
|
33140
33304
|
// src/commands/screenshot/index.ts
|
|
33141
33305
|
import { execSync as execSync60 } from "child_process";
|
|
33142
|
-
import { existsSync as
|
|
33306
|
+
import { existsSync as existsSync81, mkdirSync as mkdirSync32, unlinkSync as unlinkSync22, writeFileSync as writeFileSync48 } from "fs";
|
|
33143
33307
|
import { tmpdir as tmpdir9 } from "os";
|
|
33144
33308
|
import { join as join95, resolve as resolve21 } from "path";
|
|
33145
|
-
import
|
|
33309
|
+
import chalk226 from "chalk";
|
|
33146
33310
|
|
|
33147
33311
|
// src/commands/screenshot/captureWindowPs1.ts
|
|
33148
33312
|
var captureWindowPs1 = `
|
|
@@ -33271,7 +33435,7 @@ Write-Output $OutputPath
|
|
|
33271
33435
|
|
|
33272
33436
|
// src/commands/screenshot/index.ts
|
|
33273
33437
|
function buildOutputPath(outputDir, processName) {
|
|
33274
|
-
if (!
|
|
33438
|
+
if (!existsSync81(outputDir)) {
|
|
33275
33439
|
mkdirSync32(outputDir, { recursive: true });
|
|
33276
33440
|
}
|
|
33277
33441
|
const timestamp6 = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
@@ -33279,7 +33443,7 @@ function buildOutputPath(outputDir, processName) {
|
|
|
33279
33443
|
}
|
|
33280
33444
|
function runPowerShellScript(processName, outputPath) {
|
|
33281
33445
|
const scriptPath = join95(tmpdir9(), `assist-screenshot-${Date.now()}.ps1`);
|
|
33282
|
-
|
|
33446
|
+
writeFileSync48(scriptPath, captureWindowPs1, "utf8");
|
|
33283
33447
|
try {
|
|
33284
33448
|
execSync60(
|
|
33285
33449
|
`powershell -NoProfile -ExecutionPolicy Bypass -File "${scriptPath}" -ProcessName "${processName}" -OutputPath "${outputPath}"`,
|
|
@@ -33293,13 +33457,13 @@ function screenshot(processName) {
|
|
|
33293
33457
|
const config = loadConfig();
|
|
33294
33458
|
const outputDir = resolve21(config.screenshot.outputDir);
|
|
33295
33459
|
const outputPath = buildOutputPath(outputDir, processName);
|
|
33296
|
-
console.log(
|
|
33460
|
+
console.log(chalk226.gray(`Capturing window for process "${processName}" ...`));
|
|
33297
33461
|
try {
|
|
33298
33462
|
runPowerShellScript(processName, outputPath);
|
|
33299
|
-
console.log(
|
|
33463
|
+
console.log(chalk226.green(`Screenshot saved: ${outputPath}`));
|
|
33300
33464
|
} catch (error) {
|
|
33301
33465
|
const msg = error instanceof Error ? error.message : String(error);
|
|
33302
|
-
console.error(
|
|
33466
|
+
console.error(chalk226.red(`Failed to capture screenshot: ${msg}`));
|
|
33303
33467
|
process.exit(1);
|
|
33304
33468
|
}
|
|
33305
33469
|
}
|
|
@@ -33355,11 +33519,11 @@ function applyLine(result, pending, line) {
|
|
|
33355
33519
|
}
|
|
33356
33520
|
|
|
33357
33521
|
// src/commands/sessions/daemon/readDaemonPidFile.ts
|
|
33358
|
-
import { readFileSync as
|
|
33522
|
+
import { readFileSync as readFileSync60 } from "fs";
|
|
33359
33523
|
function readDaemonPidFile() {
|
|
33360
33524
|
try {
|
|
33361
33525
|
const pid = Number.parseInt(
|
|
33362
|
-
|
|
33526
|
+
readFileSync60(daemonPaths.pid, "utf8").trim(),
|
|
33363
33527
|
10
|
|
33364
33528
|
);
|
|
33365
33529
|
return Number.isInteger(pid) ? pid : void 0;
|
|
@@ -33616,12 +33780,12 @@ function toSessionRunInfo({
|
|
|
33616
33780
|
}
|
|
33617
33781
|
|
|
33618
33782
|
// src/commands/sessions/daemon/worktree/joinRefusal.ts
|
|
33619
|
-
import { existsSync as
|
|
33783
|
+
import { existsSync as existsSync82 } from "fs";
|
|
33620
33784
|
function joinRefusal(session) {
|
|
33621
33785
|
if (session.commandType === "run") return "a server run has no agent stream";
|
|
33622
33786
|
if (session.closing === true) return "the session is closing";
|
|
33623
33787
|
if (!session.cwd) return "the session has no working directory";
|
|
33624
|
-
if (!
|
|
33788
|
+
if (!existsSync82(session.cwd))
|
|
33625
33789
|
return "the session's workspace no longer exists";
|
|
33626
33790
|
return void 0;
|
|
33627
33791
|
}
|
|
@@ -33785,26 +33949,26 @@ function sessionBase(id, status3) {
|
|
|
33785
33949
|
}
|
|
33786
33950
|
|
|
33787
33951
|
// src/commands/sessions/daemon/spawnPty.ts
|
|
33788
|
-
import { existsSync as
|
|
33952
|
+
import { existsSync as existsSync84 } from "fs";
|
|
33789
33953
|
import * as pty from "node-pty";
|
|
33790
33954
|
|
|
33791
33955
|
// src/commands/sessions/daemon/ensureSpawnHelperExecutable.ts
|
|
33792
|
-
import { chmodSync, existsSync as
|
|
33956
|
+
import { chmodSync, existsSync as existsSync83, statSync as statSync13 } from "fs";
|
|
33793
33957
|
import { createRequire as createRequire3 } from "module";
|
|
33794
|
-
import
|
|
33958
|
+
import path83 from "path";
|
|
33795
33959
|
var require4 = createRequire3(import.meta.url);
|
|
33796
33960
|
var ensured = false;
|
|
33797
33961
|
function ensureSpawnHelperExecutable() {
|
|
33798
33962
|
if (ensured || process.platform !== "darwin") return;
|
|
33799
33963
|
ensured = true;
|
|
33800
|
-
const ptyRoot =
|
|
33801
|
-
const helper =
|
|
33964
|
+
const ptyRoot = path83.join(path83.dirname(require4.resolve("node-pty")), "..");
|
|
33965
|
+
const helper = path83.join(
|
|
33802
33966
|
ptyRoot,
|
|
33803
33967
|
"prebuilds",
|
|
33804
33968
|
`${process.platform}-${process.arch}`,
|
|
33805
33969
|
"spawn-helper"
|
|
33806
33970
|
);
|
|
33807
|
-
if (!
|
|
33971
|
+
if (!existsSync83(helper)) return;
|
|
33808
33972
|
const mode = statSync13(helper).mode;
|
|
33809
33973
|
if ((mode & 73) === 0) chmodSync(helper, mode | 493);
|
|
33810
33974
|
}
|
|
@@ -33840,7 +34004,7 @@ function spawnPty(args, cwd, sessionId, extraEnv) {
|
|
|
33840
34004
|
});
|
|
33841
34005
|
}
|
|
33842
34006
|
function refuseMissingCwd(cwd, sessionId) {
|
|
33843
|
-
if (!cwd ||
|
|
34007
|
+
if (!cwd || existsSync84(cwd)) return;
|
|
33844
34008
|
daemonLog(
|
|
33845
34009
|
`${sessionId ? `session ${sessionId}` : "pty"} not spawned: working directory ${cwd} no longer exists`
|
|
33846
34010
|
);
|
|
@@ -33919,12 +34083,12 @@ function serverRunMeta(runName, cwd) {
|
|
|
33919
34083
|
|
|
33920
34084
|
// src/commands/sessions/daemon/readDesignSystemPrompt.ts
|
|
33921
34085
|
import * as fs49 from "fs";
|
|
33922
|
-
import * as
|
|
34086
|
+
import * as path84 from "path";
|
|
33923
34087
|
import { fileURLToPath as fileURLToPath10 } from "url";
|
|
33924
34088
|
var __filename5 = fileURLToPath10(import.meta.url);
|
|
33925
|
-
var __dirname7 =
|
|
34089
|
+
var __dirname7 = path84.dirname(__filename5);
|
|
33926
34090
|
function readDesignSystemPrompt() {
|
|
33927
|
-
const promptPath =
|
|
34091
|
+
const promptPath = path84.join(
|
|
33928
34092
|
__dirname7,
|
|
33929
34093
|
"..",
|
|
33930
34094
|
"claude",
|
|
@@ -34022,11 +34186,11 @@ function setStatus2(session, newStatus) {
|
|
|
34022
34186
|
}
|
|
34023
34187
|
|
|
34024
34188
|
// src/commands/sessions/daemon/worktree/reapWorktree.ts
|
|
34025
|
-
import { existsSync as
|
|
34189
|
+
import { existsSync as existsSync86 } from "fs";
|
|
34026
34190
|
import { basename as basename22 } from "path";
|
|
34027
34191
|
|
|
34028
34192
|
// src/commands/sessions/daemon/worktree/deleteStrandedTree.ts
|
|
34029
|
-
import { existsSync as
|
|
34193
|
+
import { existsSync as existsSync85 } from "fs";
|
|
34030
34194
|
import { join as join98 } from "path";
|
|
34031
34195
|
|
|
34032
34196
|
// src/commands/sessions/daemon/worktree/deleteTreeDirectly.ts
|
|
@@ -34096,7 +34260,7 @@ async function deleteStrandedTree(clone, worktreePath, cause) {
|
|
|
34096
34260
|
);
|
|
34097
34261
|
}
|
|
34098
34262
|
function strandedReason(worktreePath, cause) {
|
|
34099
|
-
if (!
|
|
34263
|
+
if (!existsSync85(join98(worktreePath, ".git")))
|
|
34100
34264
|
return "its .git link is already gone";
|
|
34101
34265
|
if (/not a working tree|not a git repository/i.test(reason2(cause)))
|
|
34102
34266
|
return "git no longer recognises it as a working tree";
|
|
@@ -34148,7 +34312,7 @@ function reason3(error) {
|
|
|
34148
34312
|
|
|
34149
34313
|
// src/commands/sessions/daemon/worktree/reapWorktree.ts
|
|
34150
34314
|
async function reapWorktree(worktreePath, force = false) {
|
|
34151
|
-
if (!
|
|
34315
|
+
if (!existsSync86(worktreePath)) {
|
|
34152
34316
|
forgetWorktree(worktreePath);
|
|
34153
34317
|
daemonLog(
|
|
34154
34318
|
`worktree ${worktreePath} already gone; its record was forgotten`
|
|
@@ -34173,7 +34337,7 @@ async function reapWorktree(worktreePath, force = false) {
|
|
|
34173
34337
|
}
|
|
34174
34338
|
function owningClone(worktreePath) {
|
|
34175
34339
|
const recorded = worktreeAttributionIncludingReaped(worktreePath)?.clone;
|
|
34176
|
-
if (recorded &&
|
|
34340
|
+
if (recorded && existsSync86(recorded)) return recorded;
|
|
34177
34341
|
const detected = mainWorktree(worktreePath);
|
|
34178
34342
|
if (detected) return detected;
|
|
34179
34343
|
daemonLog(
|
|
@@ -34304,12 +34468,12 @@ function closeGateApplies(sessions, session) {
|
|
|
34304
34468
|
}
|
|
34305
34469
|
|
|
34306
34470
|
// src/commands/sessions/daemon/worktree/watchGitState.ts
|
|
34307
|
-
import { existsSync as
|
|
34471
|
+
import { existsSync as existsSync87, watch } from "fs";
|
|
34308
34472
|
var DEBOUNCE_MS = 500;
|
|
34309
34473
|
var POLL_MS = 3e4;
|
|
34310
34474
|
function watchGitState(cwd, onChange) {
|
|
34311
34475
|
const common = gitCommonDir(cwd);
|
|
34312
|
-
if (!common || !
|
|
34476
|
+
if (!common || !existsSync87(common)) return void 0;
|
|
34313
34477
|
const watchers = [
|
|
34314
34478
|
watchGitDir(common, onChange),
|
|
34315
34479
|
pollGitState(cwd, onChange)
|
|
@@ -34786,10 +34950,10 @@ function emitSessionOutput(session, clients, data) {
|
|
|
34786
34950
|
}
|
|
34787
34951
|
|
|
34788
34952
|
// src/commands/sessions/daemon/exitReason.ts
|
|
34789
|
-
import { existsSync as
|
|
34953
|
+
import { existsSync as existsSync88 } from "fs";
|
|
34790
34954
|
import { resolve as resolve22 } from "path";
|
|
34791
34955
|
function exitDetail(session) {
|
|
34792
|
-
if (session.cwd && !
|
|
34956
|
+
if (session.cwd && !existsSync88(session.cwd))
|
|
34793
34957
|
return `working directory ${session.cwd} no longer exists`;
|
|
34794
34958
|
return missingRunConfigCwd(session);
|
|
34795
34959
|
}
|
|
@@ -34803,7 +34967,7 @@ function missingRunConfigCwd(session) {
|
|
|
34803
34967
|
const config = resolveRunConfig(session.runName, dir);
|
|
34804
34968
|
if (!config?.cwd) return void 0;
|
|
34805
34969
|
const configured = resolve22(runConfigBaseDirFrom(dir), config.cwd);
|
|
34806
|
-
if (
|
|
34970
|
+
if (existsSync88(configured)) return void 0;
|
|
34807
34971
|
return `run config "${config.name}": cwd ${configured} does not exist`;
|
|
34808
34972
|
}
|
|
34809
34973
|
|
|
@@ -34844,7 +35008,7 @@ function handleFailedResume(session, exitCode, onStatusChange) {
|
|
|
34844
35008
|
}
|
|
34845
35009
|
|
|
34846
35010
|
// src/commands/sessions/daemon/watchActivity.ts
|
|
34847
|
-
import { existsSync as
|
|
35011
|
+
import { existsSync as existsSync89, mkdirSync as mkdirSync33, watch as watch2 } from "fs";
|
|
34848
35012
|
import { dirname as dirname39 } from "path";
|
|
34849
35013
|
|
|
34850
35014
|
// src/commands/sessions/daemon/applyActivityToSession.ts
|
|
@@ -34906,8 +35070,8 @@ async function seedRunningMsFromUsage(session, notify2) {
|
|
|
34906
35070
|
var DEBOUNCE_MS2 = 50;
|
|
34907
35071
|
function watchActivity(session, notify2, onClaudeSessionId) {
|
|
34908
35072
|
if (session.commandType !== "assist" || !session.cwd) return;
|
|
34909
|
-
const
|
|
34910
|
-
const dir = dirname39(
|
|
35073
|
+
const path88 = activityPath(session.id);
|
|
35074
|
+
const dir = dirname39(path88);
|
|
34911
35075
|
try {
|
|
34912
35076
|
mkdirSync33(dir, { recursive: true });
|
|
34913
35077
|
} catch {
|
|
@@ -34915,9 +35079,9 @@ function watchActivity(session, notify2, onClaudeSessionId) {
|
|
|
34915
35079
|
}
|
|
34916
35080
|
reconcileActivity(session.id, session.activity);
|
|
34917
35081
|
let timer = null;
|
|
34918
|
-
const
|
|
35082
|
+
const read3 = () => {
|
|
34919
35083
|
timer = null;
|
|
34920
|
-
const activity2 = readActivity(
|
|
35084
|
+
const activity2 = readActivity(path88);
|
|
34921
35085
|
if (!activity2) return;
|
|
34922
35086
|
applyActivityToSession(session, activity2);
|
|
34923
35087
|
if (activity2.claudeSessionId) onClaudeSessionId?.(session);
|
|
@@ -34926,11 +35090,11 @@ function watchActivity(session, notify2, onClaudeSessionId) {
|
|
|
34926
35090
|
notify2();
|
|
34927
35091
|
};
|
|
34928
35092
|
session.activityWatcher = watch2(dir, (_event, filename) => {
|
|
34929
|
-
if (filename && !
|
|
35093
|
+
if (filename && !path88.endsWith(filename)) return;
|
|
34930
35094
|
if (timer) clearTimeout(timer);
|
|
34931
|
-
timer = setTimeout(
|
|
35095
|
+
timer = setTimeout(read3, DEBOUNCE_MS2);
|
|
34932
35096
|
});
|
|
34933
|
-
if (
|
|
35097
|
+
if (existsSync89(path88)) read3();
|
|
34934
35098
|
}
|
|
34935
35099
|
function refreshActivity(session) {
|
|
34936
35100
|
if (session.commandType !== "assist" || !session.cwd) return;
|
|
@@ -35073,12 +35237,12 @@ import { watch as watch3 } from "fs";
|
|
|
35073
35237
|
|
|
35074
35238
|
// src/commands/sessions/shared/findTranscriptPathSync.ts
|
|
35075
35239
|
import * as fs51 from "fs";
|
|
35076
|
-
import * as
|
|
35240
|
+
import * as path85 from "path";
|
|
35077
35241
|
function projectDirForCwd(cwd) {
|
|
35078
|
-
return
|
|
35242
|
+
return path85.join(claudeProjectsRoot(), projectSlug(cwd));
|
|
35079
35243
|
}
|
|
35080
35244
|
function transcriptPathFor(cwd, claudeSessionId) {
|
|
35081
|
-
return
|
|
35245
|
+
return path85.join(projectDirForCwd(cwd), `${claudeSessionId}.jsonl`);
|
|
35082
35246
|
}
|
|
35083
35247
|
function findTranscriptPathSync(cwd, claudeSessionId) {
|
|
35084
35248
|
const direct = transcriptPathFor(cwd, claudeSessionId);
|
|
@@ -35092,8 +35256,8 @@ function findTranscriptPathSync(cwd, claudeSessionId) {
|
|
|
35092
35256
|
}
|
|
35093
35257
|
for (const file of files) {
|
|
35094
35258
|
if (!file.endsWith(".jsonl")) continue;
|
|
35095
|
-
if (headContainsSessionId(
|
|
35096
|
-
return
|
|
35259
|
+
if (headContainsSessionId(path85.join(dir, file), claudeSessionId))
|
|
35260
|
+
return path85.join(dir, file);
|
|
35097
35261
|
}
|
|
35098
35262
|
return null;
|
|
35099
35263
|
}
|
|
@@ -36267,9 +36431,9 @@ function tempRoots() {
|
|
|
36267
36431
|
}
|
|
36268
36432
|
return [...roots];
|
|
36269
36433
|
}
|
|
36270
|
-
function underTempRoot(
|
|
36434
|
+
function underTempRoot(path88) {
|
|
36271
36435
|
return tempRoots().some(
|
|
36272
|
-
(root) =>
|
|
36436
|
+
(root) => path88.startsWith(root.endsWith(sep2) ? root : root + sep2)
|
|
36273
36437
|
);
|
|
36274
36438
|
}
|
|
36275
36439
|
|
|
@@ -36581,7 +36745,7 @@ function rearmStoppedSessions(sessions, notify2) {
|
|
|
36581
36745
|
}
|
|
36582
36746
|
|
|
36583
36747
|
// src/commands/sessions/daemon/worktree/reconcileWorktreesOnRestore.ts
|
|
36584
|
-
import { existsSync as
|
|
36748
|
+
import { existsSync as existsSync92 } from "fs";
|
|
36585
36749
|
import { basename as basename24 } from "path";
|
|
36586
36750
|
|
|
36587
36751
|
// src/commands/sessions/daemon/worktree/accountedTrees.ts
|
|
@@ -36636,18 +36800,18 @@ function bindResumedWorktree(session, cwd, notify2) {
|
|
|
36636
36800
|
}
|
|
36637
36801
|
|
|
36638
36802
|
// src/commands/sessions/daemon/worktree/reclaimVanishedWorktrees.ts
|
|
36639
|
-
import { existsSync as
|
|
36803
|
+
import { existsSync as existsSync91 } from "fs";
|
|
36640
36804
|
async function reclaimVanishedWorktrees(clone, paths) {
|
|
36641
|
-
if (!
|
|
36642
|
-
for (const { path:
|
|
36805
|
+
if (!existsSync91(clone)) {
|
|
36806
|
+
for (const { path: path88 } of paths) forgetWorktree(path88);
|
|
36643
36807
|
daemonLog(
|
|
36644
36808
|
`clone ${clone} is gone; forgot ${paths.length} worktree record(s) it owned`
|
|
36645
36809
|
);
|
|
36646
36810
|
return;
|
|
36647
36811
|
}
|
|
36648
36812
|
await pruneBookkeeping2(clone);
|
|
36649
|
-
for (const { path:
|
|
36650
|
-
if (await reclaimBranch(clone, branch2)) forgetWorktree(
|
|
36813
|
+
for (const { path: path88, branch: branch2 } of paths)
|
|
36814
|
+
if (await reclaimBranch(clone, branch2)) forgetWorktree(path88);
|
|
36651
36815
|
}
|
|
36652
36816
|
async function pruneBookkeeping2(clone) {
|
|
36653
36817
|
try {
|
|
@@ -36674,37 +36838,37 @@ async function reclaimBranch(clone, branch2) {
|
|
|
36674
36838
|
}
|
|
36675
36839
|
|
|
36676
36840
|
// src/commands/sessions/daemon/worktree/logVanishedTree.ts
|
|
36677
|
-
function logVanishedTree(sessions,
|
|
36841
|
+
function logVanishedTree(sessions, path88) {
|
|
36678
36842
|
const claimants = [...sessions.values()].filter(
|
|
36679
|
-
(s) => s.cwd ===
|
|
36843
|
+
(s) => s.cwd === path88 || s.worktree?.path === path88
|
|
36680
36844
|
);
|
|
36681
36845
|
if (claimants.length === 0) {
|
|
36682
|
-
daemonLog(`worktree ${
|
|
36846
|
+
daemonLog(`worktree ${path88} gone from disk and unclaimed; reclaiming it`);
|
|
36683
36847
|
return;
|
|
36684
36848
|
}
|
|
36685
36849
|
for (const s of claimants)
|
|
36686
36850
|
daemonLog(
|
|
36687
|
-
`session ${s.id} ("${s.name}") claims worktree ${
|
|
36851
|
+
`session ${s.id} ("${s.name}") claims worktree ${path88}, which is gone from disk; reclaiming it`
|
|
36688
36852
|
);
|
|
36689
36853
|
}
|
|
36690
36854
|
|
|
36691
36855
|
// src/commands/sessions/daemon/worktree/describeHeldWork.ts
|
|
36692
36856
|
var MAX_ITEMS = 20;
|
|
36693
|
-
async function describeHeldWork(
|
|
36694
|
-
if (reason4.startsWith("uncommitted")) return await changedFiles(
|
|
36695
|
-
if (reason4.startsWith("unpushed")) return await unpushedCommits(
|
|
36857
|
+
async function describeHeldWork(path88, reason4) {
|
|
36858
|
+
if (reason4.startsWith("uncommitted")) return await changedFiles(path88);
|
|
36859
|
+
if (reason4.startsWith("unpushed")) return await unpushedCommits(path88, reason4);
|
|
36696
36860
|
return { summary: reason4, items: [] };
|
|
36697
36861
|
}
|
|
36698
|
-
async function changedFiles(
|
|
36699
|
-
const status3 = await gitResult(
|
|
36862
|
+
async function changedFiles(path88) {
|
|
36863
|
+
const status3 = await gitResult(path88, ["status", "--porcelain"]);
|
|
36700
36864
|
const lines2 = status3.ok ? nonEmptyLines(status3.out) : [];
|
|
36701
36865
|
return {
|
|
36702
36866
|
summary: `${lines2.length} uncommitted ${lines2.length === 1 ? "file" : "files"}`,
|
|
36703
36867
|
items: capped(lines2)
|
|
36704
36868
|
};
|
|
36705
36869
|
}
|
|
36706
|
-
async function unpushedCommits(
|
|
36707
|
-
const log2 = await gitResult(
|
|
36870
|
+
async function unpushedCommits(path88, reason4) {
|
|
36871
|
+
const log2 = await gitResult(path88, ["log", "--oneline", "@{upstream}..HEAD"]);
|
|
36708
36872
|
if (!log2.ok) return { summary: reason4, items: [] };
|
|
36709
36873
|
const lines2 = nonEmptyLines(log2.out);
|
|
36710
36874
|
return {
|
|
@@ -36796,24 +36960,24 @@ function reconcileWorktreesOnRestore(sessions, spawnWith, notify2) {
|
|
|
36796
36960
|
async function recoverOrphanedWorktrees(sessions, spawnWith, notify2) {
|
|
36797
36961
|
const accounted = accountedTrees(sessions);
|
|
36798
36962
|
const vanished = /* @__PURE__ */ new Map();
|
|
36799
|
-
for (const { path:
|
|
36800
|
-
if (underTempRoot(
|
|
36801
|
-
forgetWorktree(
|
|
36963
|
+
for (const { path: path88, clone } of readWorktreeRegistry()) {
|
|
36964
|
+
if (underTempRoot(path88)) {
|
|
36965
|
+
forgetWorktree(path88);
|
|
36802
36966
|
daemonLog(
|
|
36803
|
-
`worktree ${
|
|
36967
|
+
`worktree ${path88} lies outside any project root; pruned from the registry rather than recovered`
|
|
36804
36968
|
);
|
|
36805
36969
|
continue;
|
|
36806
36970
|
}
|
|
36807
|
-
if (!
|
|
36808
|
-
logVanishedTree(sessions,
|
|
36971
|
+
if (!existsSync92(path88)) {
|
|
36972
|
+
logVanishedTree(sessions, path88);
|
|
36809
36973
|
vanished.set(clone, [
|
|
36810
36974
|
...vanished.get(clone) ?? [],
|
|
36811
|
-
{ path:
|
|
36975
|
+
{ path: path88, branch: basename24(path88) }
|
|
36812
36976
|
]);
|
|
36813
36977
|
continue;
|
|
36814
36978
|
}
|
|
36815
|
-
if (accounted.has(
|
|
36816
|
-
await recoverOrphan(sessions, spawnWith, { path:
|
|
36979
|
+
if (accounted.has(path88)) continue;
|
|
36980
|
+
await recoverOrphan(sessions, spawnWith, { path: path88, clone }, notify2);
|
|
36817
36981
|
}
|
|
36818
36982
|
for (const [clone, paths] of vanished)
|
|
36819
36983
|
await reclaimVanishedWorktrees(clone, paths);
|
|
@@ -37421,14 +37585,14 @@ async function defaultConnect() {
|
|
|
37421
37585
|
}
|
|
37422
37586
|
|
|
37423
37587
|
// src/commands/sessions/daemon/hasPersistedWindowsSessions.ts
|
|
37424
|
-
import { existsSync as
|
|
37588
|
+
import { existsSync as existsSync93, readFileSync as readFileSync62 } from "fs";
|
|
37425
37589
|
import { posix as posix3 } from "path";
|
|
37426
37590
|
function hasPersistedWindowsSessions() {
|
|
37427
37591
|
const sessionsFile = windowsSessionsFileFromWsl();
|
|
37428
37592
|
if (!sessionsFile) return false;
|
|
37429
37593
|
try {
|
|
37430
|
-
if (!
|
|
37431
|
-
const data = JSON.parse(
|
|
37594
|
+
if (!existsSync93(sessionsFile)) return false;
|
|
37595
|
+
const data = JSON.parse(readFileSync62(sessionsFile, "utf8"));
|
|
37432
37596
|
return Array.isArray(data) && data.length > 0;
|
|
37433
37597
|
} catch (error) {
|
|
37434
37598
|
const message3 = error instanceof Error ? error.message : String(error);
|
|
@@ -38162,7 +38326,7 @@ function setAutoAdvance(sessions, id, enabled) {
|
|
|
38162
38326
|
}
|
|
38163
38327
|
|
|
38164
38328
|
// src/commands/sessions/daemon/worktree/resumeInTree.ts
|
|
38165
|
-
import { existsSync as
|
|
38329
|
+
import { existsSync as existsSync96 } from "fs";
|
|
38166
38330
|
|
|
38167
38331
|
// src/commands/sessions/daemon/resumeSession.ts
|
|
38168
38332
|
function resumeSession(id, sessionId, cwd, name, holdPty, harness) {
|
|
@@ -38193,10 +38357,10 @@ function resumeSession(id, sessionId, cwd, name, holdPty, harness) {
|
|
|
38193
38357
|
}
|
|
38194
38358
|
|
|
38195
38359
|
// src/commands/sessions/daemon/worktree/resumeInReplacementTree.ts
|
|
38196
|
-
import { existsSync as
|
|
38360
|
+
import { existsSync as existsSync95 } from "fs";
|
|
38197
38361
|
|
|
38198
38362
|
// src/commands/sessions/daemon/worktree/carryTranscriptToTree.ts
|
|
38199
|
-
import { copyFileSync as copyFileSync7, existsSync as
|
|
38363
|
+
import { copyFileSync as copyFileSync7, existsSync as existsSync94, mkdirSync as mkdirSync35 } from "fs";
|
|
38200
38364
|
import { join as join100 } from "path";
|
|
38201
38365
|
function carryTranscriptToTree(claudeSessionId, fromCwd, toCwd) {
|
|
38202
38366
|
const dir = projectDirForCwd(toCwd);
|
|
@@ -38207,7 +38371,7 @@ function carryTranscriptToTree(claudeSessionId, fromCwd, toCwd) {
|
|
|
38207
38371
|
return;
|
|
38208
38372
|
}
|
|
38209
38373
|
const dest = join100(dir, `${claudeSessionId}.jsonl`);
|
|
38210
|
-
if (
|
|
38374
|
+
if (existsSync94(dest)) {
|
|
38211
38375
|
daemonLog(`transcript ${claudeSessionId} already present in ${dir}`);
|
|
38212
38376
|
return;
|
|
38213
38377
|
}
|
|
@@ -38258,7 +38422,7 @@ function resumeInReplacementTree(ctx, claudeSessionId, missingCwd, name, harness
|
|
|
38258
38422
|
}
|
|
38259
38423
|
function cloneForReapedTree(missingCwd) {
|
|
38260
38424
|
const clone = worktreeAttributionIncludingReaped(missingCwd)?.clone;
|
|
38261
|
-
if (!clone || !
|
|
38425
|
+
if (!clone || !existsSync95(clone))
|
|
38262
38426
|
throw new Error(
|
|
38263
38427
|
`working directory no longer exists and no clone is recorded to re-allocate from: ${missingCwd}`
|
|
38264
38428
|
);
|
|
@@ -38267,7 +38431,7 @@ function cloneForReapedTree(missingCwd) {
|
|
|
38267
38431
|
|
|
38268
38432
|
// src/commands/sessions/daemon/worktree/resumeInTree.ts
|
|
38269
38433
|
function resumeInTree(ctx, sessionId, cwd, name, harness) {
|
|
38270
|
-
if (!
|
|
38434
|
+
if (!existsSync96(cwd))
|
|
38271
38435
|
return resumeInReplacementTree(ctx, sessionId, cwd, name, harness);
|
|
38272
38436
|
const id = ctx.spawnWith(
|
|
38273
38437
|
(sid) => resumeSession(sid, sessionId, cwd, name, void 0, harness)
|
|
@@ -38534,12 +38698,12 @@ function handleSetStatus(client, m, d) {
|
|
|
38534
38698
|
import * as fs54 from "fs";
|
|
38535
38699
|
|
|
38536
38700
|
// src/commands/sessions/shared/codex/findCodexRolloutPath.ts
|
|
38537
|
-
import * as
|
|
38701
|
+
import * as path86 from "path";
|
|
38538
38702
|
async function findCodexRolloutPath(sessionId) {
|
|
38539
38703
|
if (!sessionId) return null;
|
|
38540
38704
|
const paths = await discoverCodexRolloutPaths();
|
|
38541
38705
|
const suffix = `-${sessionId}.jsonl`;
|
|
38542
|
-
return paths.find((file) =>
|
|
38706
|
+
return paths.find((file) => path86.basename(file).endsWith(suffix)) ?? null;
|
|
38543
38707
|
}
|
|
38544
38708
|
|
|
38545
38709
|
// src/commands/sessions/shared/codex/codexToolTarget.ts
|
|
@@ -38844,10 +39008,10 @@ function handleConnection(socket, manager) {
|
|
|
38844
39008
|
}
|
|
38845
39009
|
|
|
38846
39010
|
// src/commands/sessions/daemon/onListening.ts
|
|
38847
|
-
import { unlinkSync as unlinkSync23, writeFileSync as
|
|
39011
|
+
import { unlinkSync as unlinkSync23, writeFileSync as writeFileSync49 } from "fs";
|
|
38848
39012
|
|
|
38849
39013
|
// src/commands/sessions/daemon/startPidFileWatchdog.ts
|
|
38850
|
-
import { readFileSync as
|
|
39014
|
+
import { readFileSync as readFileSync63 } from "fs";
|
|
38851
39015
|
var WATCHDOG_INTERVAL_MS = 5e3;
|
|
38852
39016
|
function startPidFileWatchdog(onLost, intervalMs = WATCHDOG_INTERVAL_MS) {
|
|
38853
39017
|
const timer = setInterval(() => {
|
|
@@ -38858,7 +39022,7 @@ function startPidFileWatchdog(onLost, intervalMs = WATCHDOG_INTERVAL_MS) {
|
|
|
38858
39022
|
}
|
|
38859
39023
|
function ownsPidFile() {
|
|
38860
39024
|
try {
|
|
38861
|
-
return
|
|
39025
|
+
return readFileSync63(daemonPaths.pid, "utf8").trim() === String(process.pid);
|
|
38862
39026
|
} catch {
|
|
38863
39027
|
return false;
|
|
38864
39028
|
}
|
|
@@ -38866,7 +39030,7 @@ function ownsPidFile() {
|
|
|
38866
39030
|
|
|
38867
39031
|
// src/commands/sessions/daemon/onListening.ts
|
|
38868
39032
|
function onListening(manager, checkAutoExit) {
|
|
38869
|
-
|
|
39033
|
+
writeFileSync49(daemonPaths.pid, String(process.pid));
|
|
38870
39034
|
startPidFileWatchdog(() => {
|
|
38871
39035
|
daemonLog("lost daemon.pid ownership; shutting down sessions and exiting");
|
|
38872
39036
|
void manager.flushActiveMs().finally(() => {
|
|
@@ -39108,7 +39272,7 @@ function registerSetStatusCommand(cmd) {
|
|
|
39108
39272
|
|
|
39109
39273
|
// src/commands/sessions/summarise/index.ts
|
|
39110
39274
|
import * as fs56 from "fs";
|
|
39111
|
-
import
|
|
39275
|
+
import chalk227 from "chalk";
|
|
39112
39276
|
|
|
39113
39277
|
// src/commands/sessions/summarise/shared.ts
|
|
39114
39278
|
import * as fs55 from "fs";
|
|
@@ -39167,22 +39331,22 @@ ${firstMessage}`);
|
|
|
39167
39331
|
async function summarise2(options2) {
|
|
39168
39332
|
const files = await discoverSessionFiles();
|
|
39169
39333
|
if (files.length === 0) {
|
|
39170
|
-
console.log(
|
|
39334
|
+
console.log(chalk227.yellow("No sessions found."));
|
|
39171
39335
|
return;
|
|
39172
39336
|
}
|
|
39173
39337
|
const toProcess = selectCandidates(files, options2);
|
|
39174
39338
|
if (toProcess.length === 0) {
|
|
39175
|
-
console.log(
|
|
39339
|
+
console.log(chalk227.green("All sessions already summarised."));
|
|
39176
39340
|
return;
|
|
39177
39341
|
}
|
|
39178
39342
|
console.log(
|
|
39179
|
-
|
|
39343
|
+
chalk227.cyan(
|
|
39180
39344
|
`Summarising ${toProcess.length} session(s) (${files.length} total)\u2026`
|
|
39181
39345
|
)
|
|
39182
39346
|
);
|
|
39183
39347
|
const { succeeded, failed: failed2 } = processSessions(toProcess);
|
|
39184
39348
|
console.log(
|
|
39185
|
-
|
|
39349
|
+
chalk227.green(`Done: ${succeeded} summarised`) + (failed2 > 0 ? chalk227.yellow(`, ${failed2} skipped`) : "")
|
|
39186
39350
|
);
|
|
39187
39351
|
}
|
|
39188
39352
|
function selectCandidates(files, options2) {
|
|
@@ -39202,16 +39366,16 @@ function processSessions(files) {
|
|
|
39202
39366
|
let failed2 = 0;
|
|
39203
39367
|
for (let i = 0; i < files.length; i++) {
|
|
39204
39368
|
const file = files[i];
|
|
39205
|
-
process.stdout.write(
|
|
39369
|
+
process.stdout.write(chalk227.dim(` [${i + 1}/${files.length}] `));
|
|
39206
39370
|
const summary = summariseSession(file);
|
|
39207
39371
|
if (summary) {
|
|
39208
39372
|
writeSummary(file, summary);
|
|
39209
39373
|
succeeded++;
|
|
39210
|
-
process.stdout.write(`${
|
|
39374
|
+
process.stdout.write(`${chalk227.green("\u2713")} ${summary}
|
|
39211
39375
|
`);
|
|
39212
39376
|
} else {
|
|
39213
39377
|
failed2++;
|
|
39214
|
-
process.stdout.write(` ${
|
|
39378
|
+
process.stdout.write(` ${chalk227.yellow("skip")}
|
|
39215
39379
|
`);
|
|
39216
39380
|
}
|
|
39217
39381
|
}
|
|
@@ -39232,7 +39396,7 @@ function registerSessions(program2) {
|
|
|
39232
39396
|
}
|
|
39233
39397
|
|
|
39234
39398
|
// src/commands/statusLine.ts
|
|
39235
|
-
import
|
|
39399
|
+
import chalk229 from "chalk";
|
|
39236
39400
|
|
|
39237
39401
|
// src/shared/contextLevel.ts
|
|
39238
39402
|
function contextLevel(pct) {
|
|
@@ -39242,7 +39406,7 @@ function contextLevel(pct) {
|
|
|
39242
39406
|
}
|
|
39243
39407
|
|
|
39244
39408
|
// src/commands/buildLimitsSegment.ts
|
|
39245
|
-
import
|
|
39409
|
+
import chalk228 from "chalk";
|
|
39246
39410
|
|
|
39247
39411
|
// src/shared/rateLimitLevel.ts
|
|
39248
39412
|
var FIVE_HOUR_SECONDS = 5 * 3600;
|
|
@@ -39280,9 +39444,9 @@ function rateLimitLevel(pct, resetsAt, windowSeconds, now) {
|
|
|
39280
39444
|
|
|
39281
39445
|
// src/commands/buildLimitsSegment.ts
|
|
39282
39446
|
var LEVEL_COLOR = {
|
|
39283
|
-
ok:
|
|
39284
|
-
warn:
|
|
39285
|
-
over:
|
|
39447
|
+
ok: chalk228.green,
|
|
39448
|
+
warn: chalk228.yellow,
|
|
39449
|
+
over: chalk228.red
|
|
39286
39450
|
};
|
|
39287
39451
|
function formatLimit(pct, resetsAt, windowSeconds, fallbackLabel, now) {
|
|
39288
39452
|
const level = rateLimitLevel(pct, resetsAt, windowSeconds, now);
|
|
@@ -39313,7 +39477,7 @@ function buildLimitsSegment(rateLimits) {
|
|
|
39313
39477
|
}
|
|
39314
39478
|
|
|
39315
39479
|
// src/commands/readGitBranch.ts
|
|
39316
|
-
import { readFileSync as
|
|
39480
|
+
import { readFileSync as readFileSync65, statSync as statSync16 } from "fs";
|
|
39317
39481
|
import { isAbsolute as isAbsolute5, join as join101, resolve as resolve23 } from "path";
|
|
39318
39482
|
function resolveGitDir(cwd) {
|
|
39319
39483
|
const dotGit = join101(cwd, ".git");
|
|
@@ -39328,7 +39492,7 @@ function resolveGitDir(cwd) {
|
|
|
39328
39492
|
}
|
|
39329
39493
|
let contents;
|
|
39330
39494
|
try {
|
|
39331
|
-
contents =
|
|
39495
|
+
contents = readFileSync65(dotGit, "utf8");
|
|
39332
39496
|
} catch {
|
|
39333
39497
|
return null;
|
|
39334
39498
|
}
|
|
@@ -39346,7 +39510,7 @@ function readGitBranch(cwd) {
|
|
|
39346
39510
|
}
|
|
39347
39511
|
let head;
|
|
39348
39512
|
try {
|
|
39349
|
-
head =
|
|
39513
|
+
head = readFileSync65(join101(gitDir, "HEAD"), "utf8");
|
|
39350
39514
|
} catch {
|
|
39351
39515
|
return null;
|
|
39352
39516
|
}
|
|
@@ -39378,7 +39542,7 @@ async function relayUsage(claudeSessionId, transcriptPath2, usedPct) {
|
|
|
39378
39542
|
}
|
|
39379
39543
|
|
|
39380
39544
|
// src/commands/statusLine.ts
|
|
39381
|
-
|
|
39545
|
+
chalk229.level = 3;
|
|
39382
39546
|
function formatNumber(num) {
|
|
39383
39547
|
return num.toLocaleString("en-US");
|
|
39384
39548
|
}
|
|
@@ -39386,9 +39550,9 @@ function colorizePercent(pct) {
|
|
|
39386
39550
|
const label2 = `${Math.round(pct)}%`;
|
|
39387
39551
|
switch (contextLevel(pct)) {
|
|
39388
39552
|
case "red":
|
|
39389
|
-
return
|
|
39553
|
+
return chalk229.red(label2);
|
|
39390
39554
|
case "yellow":
|
|
39391
|
-
return
|
|
39555
|
+
return chalk229.yellow(label2);
|
|
39392
39556
|
default:
|
|
39393
39557
|
return label2;
|
|
39394
39558
|
}
|
|
@@ -39401,7 +39565,7 @@ async function statusLine() {
|
|
|
39401
39565
|
const usedPct = data.context_window.used_percentage ?? 0;
|
|
39402
39566
|
const dir = data.workspace?.current_dir ?? data.cwd;
|
|
39403
39567
|
const branch2 = dir ? readGitBranch(toGitCwd(dir)) : null;
|
|
39404
|
-
const branchSegment = branch2 ? `\u{1F33F}\uFE0F ${
|
|
39568
|
+
const branchSegment = branch2 ? `\u{1F33F}\uFE0F ${chalk229.cyan(branch2)} | ` : "";
|
|
39405
39569
|
console.log(
|
|
39406
39570
|
`${branchSegment}${model} | Tokens - ${formatNumber(totalIn)} \u2191 : ${formatNumber(totalOut)} \u2193 | Context - ${colorizePercent(usedPct)}${buildLimitsSegment(data.rate_limits)}`
|
|
39407
39571
|
);
|
|
@@ -39415,7 +39579,7 @@ async function statusLine() {
|
|
|
39415
39579
|
|
|
39416
39580
|
// src/commands/update.ts
|
|
39417
39581
|
import { execSync as execSync61 } from "child_process";
|
|
39418
|
-
import * as
|
|
39582
|
+
import * as path87 from "path";
|
|
39419
39583
|
|
|
39420
39584
|
// src/commands/restartDaemonAfterUpdate.ts
|
|
39421
39585
|
async function restartDaemonAfterUpdate() {
|
|
@@ -39434,12 +39598,12 @@ async function restartDaemonAfterUpdate() {
|
|
|
39434
39598
|
// src/commands/update.ts
|
|
39435
39599
|
function isGlobalNpmInstall(dir) {
|
|
39436
39600
|
try {
|
|
39437
|
-
const resolved =
|
|
39438
|
-
if (resolved.split(
|
|
39601
|
+
const resolved = path87.resolve(dir);
|
|
39602
|
+
if (resolved.split(path87.sep).includes("node_modules")) {
|
|
39439
39603
|
return true;
|
|
39440
39604
|
}
|
|
39441
39605
|
const globalPrefix = execSync61("npm prefix -g", { stdio: "pipe" }).toString().trim();
|
|
39442
|
-
return resolved.toLowerCase().startsWith(
|
|
39606
|
+
return resolved.toLowerCase().startsWith(path87.resolve(globalPrefix).toLowerCase());
|
|
39443
39607
|
} catch {
|
|
39444
39608
|
return false;
|
|
39445
39609
|
}
|
|
@@ -39471,10 +39635,10 @@ async function update2() {
|
|
|
39471
39635
|
}
|
|
39472
39636
|
|
|
39473
39637
|
// src/reportCliError.ts
|
|
39474
|
-
import
|
|
39638
|
+
import chalk230 from "chalk";
|
|
39475
39639
|
function reportCliError(error) {
|
|
39476
39640
|
if (error instanceof InvalidItemIdError || error instanceof AmbiguousRepoConfigError || error instanceof UnknownRepoConfigError || error instanceof MissingRunCwdError || error instanceof MiroExtractError) {
|
|
39477
|
-
console.error(
|
|
39641
|
+
console.error(chalk230.red(error.message));
|
|
39478
39642
|
} else {
|
|
39479
39643
|
console.error(error);
|
|
39480
39644
|
}
|