@staff0rd/assist 0.411.0 → 0.413.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 -2
- package/dist/commands/sessions/web/bundle.js +1 -1
- package/dist/index.js +1327 -883
- 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.413.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -140,13 +140,68 @@ import { dirname, join } from "path";
|
|
|
140
140
|
import chalk from "chalk";
|
|
141
141
|
import { stringify as stringifyYaml } from "yaml";
|
|
142
142
|
|
|
143
|
+
// src/commands/backlog/getCurrentOrigin.ts
|
|
144
|
+
import { execFileSync } from "child_process";
|
|
145
|
+
function stripLeadingSlashes(path71) {
|
|
146
|
+
return path71.replace(/^\/+/, "");
|
|
147
|
+
}
|
|
148
|
+
function normalizeOrigin(raw) {
|
|
149
|
+
const trimmed = raw.trim().replace(/\.git$/i, "").replace(/\/+$/, "");
|
|
150
|
+
const url = trimmed.match(
|
|
151
|
+
/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\/(?:[^@/]+@)?([^/:]+)(?::\d+)?\/(.+)$/
|
|
152
|
+
);
|
|
153
|
+
if (url) {
|
|
154
|
+
return `${url[1].toLowerCase()}/${stripLeadingSlashes(url[2])}`;
|
|
155
|
+
}
|
|
156
|
+
if (!trimmed.includes("://")) {
|
|
157
|
+
const scp = trimmed.match(/^(?:[^@/]+@)?([^/:]+):(.+)$/);
|
|
158
|
+
if (scp) {
|
|
159
|
+
return `${scp[1].toLowerCase()}/${stripLeadingSlashes(scp[2])}`;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return trimmed.toLowerCase();
|
|
163
|
+
}
|
|
164
|
+
function tryGit(cwd, args) {
|
|
165
|
+
const windows = /^[A-Za-z]:[\\/]/.test(cwd);
|
|
166
|
+
const file = windows ? "git.exe" : "git";
|
|
167
|
+
const argv = windows ? ["-C", cwd, ...args] : args;
|
|
168
|
+
try {
|
|
169
|
+
const out = execFileSync(file, argv, {
|
|
170
|
+
encoding: "utf8",
|
|
171
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
172
|
+
...windows ? {} : { cwd }
|
|
173
|
+
}).trim();
|
|
174
|
+
return out || null;
|
|
175
|
+
} catch {
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
function firstRemoteUrl(cwd) {
|
|
180
|
+
const remotes = tryGit(cwd, ["remote"]);
|
|
181
|
+
if (!remotes) return null;
|
|
182
|
+
for (const remote of remotes.split("\n").map((r) => r.trim()).filter(Boolean)) {
|
|
183
|
+
const url = tryGit(cwd, ["remote", "get-url", remote]);
|
|
184
|
+
if (url) return url;
|
|
185
|
+
}
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
function getRemoteOriginUrl(cwd) {
|
|
189
|
+
return tryGit(cwd, ["remote", "get-url", "origin"]) ?? firstRemoteUrl(cwd);
|
|
190
|
+
}
|
|
191
|
+
function getCurrentOrigin(cwd) {
|
|
192
|
+
const url = getRemoteOriginUrl(cwd);
|
|
193
|
+
if (url) return normalizeOrigin(url);
|
|
194
|
+
const root = tryGit(cwd, ["rev-parse", "--show-toplevel"]);
|
|
195
|
+
return `local:${root ?? cwd}`;
|
|
196
|
+
}
|
|
197
|
+
|
|
143
198
|
// src/shared/loadRawYaml.ts
|
|
144
199
|
import { existsSync, readFileSync } from "fs";
|
|
145
200
|
import { parse as parseYaml } from "yaml";
|
|
146
|
-
function loadRawYaml(
|
|
147
|
-
if (!existsSync(
|
|
201
|
+
function loadRawYaml(path71) {
|
|
202
|
+
if (!existsSync(path71)) return {};
|
|
148
203
|
try {
|
|
149
|
-
const content = readFileSync(
|
|
204
|
+
const content = readFileSync(path71, "utf8");
|
|
150
205
|
return parseYaml(content) || {};
|
|
151
206
|
} catch {
|
|
152
207
|
return {};
|
|
@@ -179,6 +234,84 @@ function mergeRawConfigs(globalRaw, projectRaw) {
|
|
|
179
234
|
return merged;
|
|
180
235
|
}
|
|
181
236
|
|
|
237
|
+
// src/commands/backlog/originDisplayName.ts
|
|
238
|
+
function originDisplayName(origin) {
|
|
239
|
+
if (origin.startsWith("local:")) {
|
|
240
|
+
const path71 = origin.slice("local:".length).replace(/\/+$/, "");
|
|
241
|
+
const segments = path71.split("/").filter(Boolean);
|
|
242
|
+
return segments[segments.length - 1] ?? origin;
|
|
243
|
+
}
|
|
244
|
+
const firstSlash = origin.indexOf("/");
|
|
245
|
+
if (firstSlash === -1) return origin;
|
|
246
|
+
return origin.slice(firstSlash + 1);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// src/commands/backlog/originDisplayLabels.ts
|
|
250
|
+
function originDisplayLabels(origins) {
|
|
251
|
+
const isLocal = (origin) => origin.startsWith("local:");
|
|
252
|
+
const bareName = (origin) => {
|
|
253
|
+
const full = originDisplayName(origin);
|
|
254
|
+
const segments = full.split("/");
|
|
255
|
+
return segments[segments.length - 1] ?? full;
|
|
256
|
+
};
|
|
257
|
+
const remoteCounts = /* @__PURE__ */ new Map();
|
|
258
|
+
for (const origin of new Set(origins)) {
|
|
259
|
+
if (isLocal(origin)) continue;
|
|
260
|
+
const name = bareName(origin);
|
|
261
|
+
remoteCounts.set(name, (remoteCounts.get(name) ?? 0) + 1);
|
|
262
|
+
}
|
|
263
|
+
const labels = /* @__PURE__ */ new Map();
|
|
264
|
+
for (const origin of origins) {
|
|
265
|
+
if (isLocal(origin)) {
|
|
266
|
+
labels.set(origin, originDisplayName(origin));
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
const name = bareName(origin);
|
|
270
|
+
const collides = (remoteCounts.get(name) ?? 0) > 1;
|
|
271
|
+
labels.set(origin, collides ? originDisplayName(origin) : name);
|
|
272
|
+
}
|
|
273
|
+
return labels;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// src/shared/resolveRepoOverride.ts
|
|
277
|
+
var AmbiguousRepoConfigError = class extends Error {
|
|
278
|
+
name = "AmbiguousRepoConfigError";
|
|
279
|
+
};
|
|
280
|
+
function originKeyCandidates(origin) {
|
|
281
|
+
const displayName = originDisplayName(origin);
|
|
282
|
+
const segments = displayName.split("/");
|
|
283
|
+
const bare = segments[segments.length - 1] ?? displayName;
|
|
284
|
+
return /* @__PURE__ */ new Set([origin, displayName, bare]);
|
|
285
|
+
}
|
|
286
|
+
function resolveRepoOverride(globalRaw, origin) {
|
|
287
|
+
const repos2 = globalRaw.repos;
|
|
288
|
+
if (!repos2 || typeof repos2 !== "object" || Array.isArray(repos2)) return {};
|
|
289
|
+
const entries = repos2;
|
|
290
|
+
const candidates = originKeyCandidates(origin);
|
|
291
|
+
const matches = Object.keys(entries).filter((key) => candidates.has(key));
|
|
292
|
+
if (matches.length === 0) return {};
|
|
293
|
+
if (matches.length > 1) {
|
|
294
|
+
throw new AmbiguousRepoConfigError(
|
|
295
|
+
`Ambiguous repos config in ~/.assist.yml: keys ${matches.map((m) => `"${m}"`).join(", ")} all match the current repository (${origin}). Keep a single key per repository.`
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
const override = entries[matches[0]];
|
|
299
|
+
if (!override || typeof override !== "object" || Array.isArray(override))
|
|
300
|
+
return {};
|
|
301
|
+
return override;
|
|
302
|
+
}
|
|
303
|
+
function resolveRepoWriteLabel(globalRaw, origin) {
|
|
304
|
+
const repos2 = globalRaw.repos;
|
|
305
|
+
if (repos2 && typeof repos2 === "object" && !Array.isArray(repos2)) {
|
|
306
|
+
const candidates = originKeyCandidates(origin);
|
|
307
|
+
const existing = Object.keys(repos2).find(
|
|
308
|
+
(key) => candidates.has(key)
|
|
309
|
+
);
|
|
310
|
+
if (existing) return existing;
|
|
311
|
+
}
|
|
312
|
+
return originDisplayLabels([origin]).get(origin) ?? origin;
|
|
313
|
+
}
|
|
314
|
+
|
|
182
315
|
// src/shared/types.ts
|
|
183
316
|
import { z as z2 } from "zod";
|
|
184
317
|
|
|
@@ -267,6 +400,7 @@ var assistConfigSchema = z2.strictObject({
|
|
|
267
400
|
slack: z2.string().optional(),
|
|
268
401
|
required: z2.boolean().default(false)
|
|
269
402
|
}).optional(),
|
|
403
|
+
repos: z2.record(z2.string(), z2.record(z2.string(), z2.unknown())).optional(),
|
|
270
404
|
run: z2.array(z2.union([runConfigSchema, runLinkSchema])).optional(),
|
|
271
405
|
subtasks: z2.array(
|
|
272
406
|
z2.strictObject({
|
|
@@ -403,7 +537,10 @@ function getProjectRoot() {
|
|
|
403
537
|
function loadConfig() {
|
|
404
538
|
const globalRaw = loadRawYaml(getGlobalConfigPath());
|
|
405
539
|
const projectRaw = loadRawYaml(getConfigPath());
|
|
406
|
-
const
|
|
540
|
+
const repoOverride = globalRaw.repos ? resolveRepoOverride(globalRaw, getCurrentOrigin(process.cwd())) : {};
|
|
541
|
+
const globalWithRepo = mergeRawConfigs(globalRaw, repoOverride);
|
|
542
|
+
const merged = mergeRawConfigs(globalWithRepo, projectRaw);
|
|
543
|
+
delete merged.repos;
|
|
407
544
|
delete merged.news;
|
|
408
545
|
return assistConfigSchema.parse(merged);
|
|
409
546
|
}
|
|
@@ -1442,8 +1579,8 @@ function findUnmergedPaths() {
|
|
|
1442
1579
|
}
|
|
1443
1580
|
const found = /* @__PURE__ */ new Set();
|
|
1444
1581
|
for (const line of output.split("\n")) {
|
|
1445
|
-
const
|
|
1446
|
-
if (
|
|
1582
|
+
const path71 = line.split(" ")[1];
|
|
1583
|
+
if (path71) found.add(path71.trim());
|
|
1447
1584
|
}
|
|
1448
1585
|
return [...found];
|
|
1449
1586
|
}
|
|
@@ -1542,8 +1679,8 @@ function getPreferredRemoteRepo(cwd) {
|
|
|
1542
1679
|
function gitRefUrl(kind, ref, cwd) {
|
|
1543
1680
|
const repo = getPreferredRemoteRepo(cwd);
|
|
1544
1681
|
if (!repo) return void 0;
|
|
1545
|
-
const
|
|
1546
|
-
return `https://github.com/${repo.org}/${repo.repo}/${
|
|
1682
|
+
const path71 = kind === "branch" ? "tree" : "commit";
|
|
1683
|
+
return `https://github.com/${repo.org}/${repo.repo}/${path71}/${ref}`;
|
|
1547
1684
|
}
|
|
1548
1685
|
|
|
1549
1686
|
// src/commands/commit/collectCommitRefs.ts
|
|
@@ -3362,7 +3499,7 @@ function enumerateConfigLeafKeys(schema2) {
|
|
|
3362
3499
|
}
|
|
3363
3500
|
|
|
3364
3501
|
// src/commands/verify/pendingConfigDocumentation.ts
|
|
3365
|
-
var pendingConfigDocumentation = /* @__PURE__ */ new Set();
|
|
3502
|
+
var pendingConfigDocumentation = /* @__PURE__ */ new Set(["repos"]);
|
|
3366
3503
|
|
|
3367
3504
|
// src/commands/verify/configKeys.ts
|
|
3368
3505
|
function section(label2, keys) {
|
|
@@ -3410,9 +3547,9 @@ import { existsSync as existsSync12, readFileSync as readFileSync9 } from "fs";
|
|
|
3410
3547
|
|
|
3411
3548
|
// src/commands/verify/forbiddenStrings/findForbiddenStrings.ts
|
|
3412
3549
|
import { minimatch as minimatch2 } from "minimatch";
|
|
3413
|
-
function resolveStringsAtPath(data,
|
|
3550
|
+
function resolveStringsAtPath(data, path71) {
|
|
3414
3551
|
let current = data;
|
|
3415
|
-
for (const segment of
|
|
3552
|
+
for (const segment of path71.split(".")) {
|
|
3416
3553
|
if (current === null || typeof current !== "object") return [];
|
|
3417
3554
|
current = current[segment];
|
|
3418
3555
|
}
|
|
@@ -3425,10 +3562,10 @@ function resolveStringsAtPath(data, path70) {
|
|
|
3425
3562
|
}
|
|
3426
3563
|
function findRuleViolations(data, rule) {
|
|
3427
3564
|
const violations = [];
|
|
3428
|
-
for (const
|
|
3429
|
-
for (const value of resolveStringsAtPath(data,
|
|
3565
|
+
for (const path71 of rule.paths) {
|
|
3566
|
+
for (const value of resolveStringsAtPath(data, path71)) {
|
|
3430
3567
|
if (minimatch2(value, rule.disallowed))
|
|
3431
|
-
violations.push({ file: rule.file, path:
|
|
3568
|
+
violations.push({ file: rule.file, path: path71, value });
|
|
3432
3569
|
}
|
|
3433
3570
|
}
|
|
3434
3571
|
return violations;
|
|
@@ -3467,8 +3604,8 @@ function forbiddenStrings() {
|
|
|
3467
3604
|
process.exit(0);
|
|
3468
3605
|
}
|
|
3469
3606
|
console.log("Forbidden strings found:\n");
|
|
3470
|
-
for (const { file, path:
|
|
3471
|
-
console.log(` ${file} ${
|
|
3607
|
+
for (const { file, path: path71, value } of violations) {
|
|
3608
|
+
console.log(` ${file} ${path71}: ${value}`);
|
|
3472
3609
|
}
|
|
3473
3610
|
console.log(`
|
|
3474
3611
|
Total: ${violations.length} forbidden string(s).`);
|
|
@@ -3760,15 +3897,15 @@ function readBaselineMigrations(repoRelativeDir, ref) {
|
|
|
3760
3897
|
} catch {
|
|
3761
3898
|
return baseline;
|
|
3762
3899
|
}
|
|
3763
|
-
const paths = listing.split("\n").map((line) => line.trim()).filter(Boolean).filter((
|
|
3764
|
-
for (const
|
|
3900
|
+
const paths = listing.split("\n").map((line) => line.trim()).filter(Boolean).filter((path71) => MIGRATION_FILE3.test(basename(path71)));
|
|
3901
|
+
for (const path71 of paths) {
|
|
3765
3902
|
try {
|
|
3766
|
-
const content = execSync12(`git show "${ref}:${
|
|
3903
|
+
const content = execSync12(`git show "${ref}:${path71}"`, {
|
|
3767
3904
|
encoding: "utf8",
|
|
3768
3905
|
maxBuffer: 16 * 1024 * 1024,
|
|
3769
3906
|
stdio: ["pipe", "pipe", "pipe"]
|
|
3770
3907
|
});
|
|
3771
|
-
baseline.set(basename(
|
|
3908
|
+
baseline.set(basename(path71), content);
|
|
3772
3909
|
} catch {
|
|
3773
3910
|
}
|
|
3774
3911
|
}
|
|
@@ -5106,8 +5243,16 @@ var daemonPaths = {
|
|
|
5106
5243
|
};
|
|
5107
5244
|
|
|
5108
5245
|
// src/commands/sessions/daemon/ensureHooksSettings.ts
|
|
5109
|
-
var
|
|
5110
|
-
|
|
5246
|
+
var SET_STATUS = "assist sessions set-status";
|
|
5247
|
+
function running(source) {
|
|
5248
|
+
return `${SET_STATUS} running --source ${source}`;
|
|
5249
|
+
}
|
|
5250
|
+
function waiting(source) {
|
|
5251
|
+
return `${SET_STATUS} waiting --source ${source}`;
|
|
5252
|
+
}
|
|
5253
|
+
function ackWaiting(source) {
|
|
5254
|
+
return `${SET_STATUS} waiting --source ${source} --ack`;
|
|
5255
|
+
}
|
|
5111
5256
|
function on(command, matcher) {
|
|
5112
5257
|
const hooks = [{ type: "command", command }];
|
|
5113
5258
|
return [matcher == null ? { hooks } : { matcher, hooks }];
|
|
@@ -5116,27 +5261,22 @@ var ASK_USER_QUESTION = "AskUserQuestion";
|
|
|
5116
5261
|
var NOT_ASK_USER_QUESTION = `^(?!${ASK_USER_QUESTION}$).*`;
|
|
5117
5262
|
var hooksSettings = {
|
|
5118
5263
|
hooks: {
|
|
5119
|
-
UserPromptSubmit: on(
|
|
5264
|
+
UserPromptSubmit: on(running("prompt")),
|
|
5120
5265
|
PreToolUse: [
|
|
5121
|
-
...on(
|
|
5122
|
-
...on(
|
|
5266
|
+
...on(waiting("pretool"), ASK_USER_QUESTION),
|
|
5267
|
+
...on(running("pretool"), NOT_ASK_USER_QUESTION)
|
|
5123
5268
|
],
|
|
5124
|
-
|
|
5125
|
-
|
|
5126
|
-
|
|
5127
|
-
|
|
5128
|
-
/* why: a tool/plan approval prompt appears mid-turn, after PreToolUse has
|
|
5129
|
-
* already set running; PermissionRequest fires when the agent blocks on
|
|
5130
|
-
* that decision, so the card shows waiting rather than staying running while
|
|
5131
|
-
* it is genuinely awaiting the user (#449). */
|
|
5132
|
-
PermissionRequest: on(WAITING)
|
|
5269
|
+
PostToolUse: on(running("posttool")),
|
|
5270
|
+
Stop: on(ackWaiting("stop")),
|
|
5271
|
+
Notification: on(ackWaiting("notification")),
|
|
5272
|
+
PermissionRequest: on(ackWaiting("permission"))
|
|
5133
5273
|
}
|
|
5134
5274
|
};
|
|
5135
5275
|
function ensureHooksSettings() {
|
|
5136
|
-
const
|
|
5137
|
-
mkdirSync5(dirname12(
|
|
5138
|
-
writeFileSync15(
|
|
5139
|
-
return
|
|
5276
|
+
const path71 = daemonPaths.hooksSettings;
|
|
5277
|
+
mkdirSync5(dirname12(path71), { recursive: true });
|
|
5278
|
+
writeFileSync15(path71, JSON.stringify(hooksSettings, null, 2));
|
|
5279
|
+
return path71;
|
|
5140
5280
|
}
|
|
5141
5281
|
|
|
5142
5282
|
// src/shared/spawnInherit.ts
|
|
@@ -5401,9 +5541,9 @@ var LOCAL_FILES = ["backlog.jsonl", "backlog.db"];
|
|
|
5401
5541
|
function backupLocalBacklogFiles(dir) {
|
|
5402
5542
|
const moved = [];
|
|
5403
5543
|
for (const name of LOCAL_FILES) {
|
|
5404
|
-
const
|
|
5405
|
-
if (existsSync18(
|
|
5406
|
-
renameSync(
|
|
5544
|
+
const path71 = join15(dir, ".assist", name);
|
|
5545
|
+
if (existsSync18(path71)) {
|
|
5546
|
+
renameSync(path71, `${path71}.bak`);
|
|
5407
5547
|
moved.push(`${name} \u2192 ${name}.bak`);
|
|
5408
5548
|
}
|
|
5409
5549
|
}
|
|
@@ -5875,8 +6015,8 @@ var backlogItemSchema = z3.strictObject({
|
|
|
5875
6015
|
var backlogFileSchema = z3.array(backlogItemSchema);
|
|
5876
6016
|
|
|
5877
6017
|
// src/commands/backlog/parseBacklogJsonl.ts
|
|
5878
|
-
function parseBacklogJsonl(
|
|
5879
|
-
const content = readFileSync14(
|
|
6018
|
+
function parseBacklogJsonl(path71) {
|
|
6019
|
+
const content = readFileSync14(path71, "utf8").trim();
|
|
5880
6020
|
if (content.length === 0) return [];
|
|
5881
6021
|
return content.split("\n").map((line) => line.trim()).filter(Boolean).map((line) => backlogItemSchema.parse(JSON.parse(line)));
|
|
5882
6022
|
}
|
|
@@ -5956,61 +6096,6 @@ function findBacklogUp(startDir) {
|
|
|
5956
6096
|
return null;
|
|
5957
6097
|
}
|
|
5958
6098
|
|
|
5959
|
-
// src/commands/backlog/getCurrentOrigin.ts
|
|
5960
|
-
import { execFileSync } from "child_process";
|
|
5961
|
-
function stripLeadingSlashes(path70) {
|
|
5962
|
-
return path70.replace(/^\/+/, "");
|
|
5963
|
-
}
|
|
5964
|
-
function normalizeOrigin(raw) {
|
|
5965
|
-
const trimmed = raw.trim().replace(/\.git$/i, "").replace(/\/+$/, "");
|
|
5966
|
-
const url = trimmed.match(
|
|
5967
|
-
/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\/(?:[^@/]+@)?([^/:]+)(?::\d+)?\/(.+)$/
|
|
5968
|
-
);
|
|
5969
|
-
if (url) {
|
|
5970
|
-
return `${url[1].toLowerCase()}/${stripLeadingSlashes(url[2])}`;
|
|
5971
|
-
}
|
|
5972
|
-
if (!trimmed.includes("://")) {
|
|
5973
|
-
const scp = trimmed.match(/^(?:[^@/]+@)?([^/:]+):(.+)$/);
|
|
5974
|
-
if (scp) {
|
|
5975
|
-
return `${scp[1].toLowerCase()}/${stripLeadingSlashes(scp[2])}`;
|
|
5976
|
-
}
|
|
5977
|
-
}
|
|
5978
|
-
return trimmed.toLowerCase();
|
|
5979
|
-
}
|
|
5980
|
-
function tryGit(cwd, args) {
|
|
5981
|
-
const windows = /^[A-Za-z]:[\\/]/.test(cwd);
|
|
5982
|
-
const file = windows ? "git.exe" : "git";
|
|
5983
|
-
const argv = windows ? ["-C", cwd, ...args] : args;
|
|
5984
|
-
try {
|
|
5985
|
-
const out = execFileSync(file, argv, {
|
|
5986
|
-
encoding: "utf8",
|
|
5987
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
5988
|
-
...windows ? {} : { cwd }
|
|
5989
|
-
}).trim();
|
|
5990
|
-
return out || null;
|
|
5991
|
-
} catch {
|
|
5992
|
-
return null;
|
|
5993
|
-
}
|
|
5994
|
-
}
|
|
5995
|
-
function firstRemoteUrl(cwd) {
|
|
5996
|
-
const remotes = tryGit(cwd, ["remote"]);
|
|
5997
|
-
if (!remotes) return null;
|
|
5998
|
-
for (const remote of remotes.split("\n").map((r) => r.trim()).filter(Boolean)) {
|
|
5999
|
-
const url = tryGit(cwd, ["remote", "get-url", remote]);
|
|
6000
|
-
if (url) return url;
|
|
6001
|
-
}
|
|
6002
|
-
return null;
|
|
6003
|
-
}
|
|
6004
|
-
function getRemoteOriginUrl(cwd) {
|
|
6005
|
-
return tryGit(cwd, ["remote", "get-url", "origin"]) ?? firstRemoteUrl(cwd);
|
|
6006
|
-
}
|
|
6007
|
-
function getCurrentOrigin(cwd) {
|
|
6008
|
-
const url = getRemoteOriginUrl(cwd);
|
|
6009
|
-
if (url) return normalizeOrigin(url);
|
|
6010
|
-
const root = tryGit(cwd, ["rev-parse", "--show-toplevel"]);
|
|
6011
|
-
return `local:${root ?? cwd}`;
|
|
6012
|
-
}
|
|
6013
|
-
|
|
6014
6099
|
// src/commands/backlog/loadItem.ts
|
|
6015
6100
|
import { eq as eq5 } from "drizzle-orm";
|
|
6016
6101
|
async function loadItem(orm, id) {
|
|
@@ -6307,20 +6392,87 @@ function sendToDaemon(message) {
|
|
|
6307
6392
|
});
|
|
6308
6393
|
}
|
|
6309
6394
|
|
|
6395
|
+
// src/commands/sessions/daemon/sendToDaemonAwaitAck.ts
|
|
6396
|
+
var ACK_TIMEOUT_MS = 1e3;
|
|
6397
|
+
function sendToDaemonAwaitAck(message) {
|
|
6398
|
+
return new Promise((resolve19, reject) => {
|
|
6399
|
+
connectToDaemon().then((socket) => {
|
|
6400
|
+
let settled = false;
|
|
6401
|
+
const finish = (error) => {
|
|
6402
|
+
if (settled) return;
|
|
6403
|
+
settled = true;
|
|
6404
|
+
clearTimeout(timer);
|
|
6405
|
+
socket.destroy();
|
|
6406
|
+
if (error) reject(error);
|
|
6407
|
+
else resolve19();
|
|
6408
|
+
};
|
|
6409
|
+
const timer = setTimeout(
|
|
6410
|
+
() => finish(new Error("timed out awaiting daemon ack")),
|
|
6411
|
+
ACK_TIMEOUT_MS
|
|
6412
|
+
);
|
|
6413
|
+
let buffer = "";
|
|
6414
|
+
socket.on("data", (chunk) => {
|
|
6415
|
+
buffer += chunk.toString("utf8");
|
|
6416
|
+
let newline = buffer.indexOf("\n");
|
|
6417
|
+
while (newline !== -1) {
|
|
6418
|
+
const line = buffer.slice(0, newline);
|
|
6419
|
+
buffer = buffer.slice(newline + 1);
|
|
6420
|
+
if (isAck(line)) return finish();
|
|
6421
|
+
newline = buffer.indexOf("\n");
|
|
6422
|
+
}
|
|
6423
|
+
});
|
|
6424
|
+
socket.on("error", (error) => finish(error));
|
|
6425
|
+
socket.on(
|
|
6426
|
+
"close",
|
|
6427
|
+
() => finish(new Error("daemon closed before acknowledging"))
|
|
6428
|
+
);
|
|
6429
|
+
socket.write(`${JSON.stringify(message)}
|
|
6430
|
+
`);
|
|
6431
|
+
}, reject);
|
|
6432
|
+
});
|
|
6433
|
+
}
|
|
6434
|
+
function isAck(line) {
|
|
6435
|
+
try {
|
|
6436
|
+
return JSON.parse(line).type === "ack";
|
|
6437
|
+
} catch {
|
|
6438
|
+
return false;
|
|
6439
|
+
}
|
|
6440
|
+
}
|
|
6441
|
+
|
|
6310
6442
|
// src/commands/sessions/setSessionStatus.ts
|
|
6311
6443
|
var DELIVERY_ATTEMPTS = 3;
|
|
6312
6444
|
var RETRY_DELAY_MS = 100;
|
|
6313
|
-
async function setSessionStatus(status3) {
|
|
6445
|
+
async function setSessionStatus(status3, opts = {}) {
|
|
6314
6446
|
const sessionId = process.env.ASSIST_SESSION_ID;
|
|
6315
|
-
logHookFired(status3, sessionId);
|
|
6447
|
+
logHookFired(status3, sessionId, opts.source);
|
|
6316
6448
|
if (!sessionId) return;
|
|
6317
|
-
|
|
6449
|
+
const payload = buildPayload(sessionId, status3, opts);
|
|
6450
|
+
if (opts.ack) await deliverReliably(sessionId, status3, payload);
|
|
6451
|
+
else await deliverBestEffort(sessionId, status3, payload);
|
|
6452
|
+
}
|
|
6453
|
+
function buildPayload(sessionId, status3, opts) {
|
|
6454
|
+
const payload = {
|
|
6455
|
+
type: "set-status",
|
|
6456
|
+
sessionId,
|
|
6457
|
+
status: status3
|
|
6458
|
+
};
|
|
6459
|
+
if (opts.source) payload.source = opts.source;
|
|
6460
|
+
if (opts.ack) payload.ack = true;
|
|
6461
|
+
return payload;
|
|
6462
|
+
}
|
|
6463
|
+
async function deliverBestEffort(sessionId, status3, payload) {
|
|
6464
|
+
try {
|
|
6465
|
+
await sendToDaemon(payload);
|
|
6466
|
+
} catch (error) {
|
|
6467
|
+
appendDaemonLog(
|
|
6468
|
+
`set-status best-effort send failed: id=${sessionId} status=${status3}: ${describeError(error)}`
|
|
6469
|
+
);
|
|
6470
|
+
}
|
|
6318
6471
|
}
|
|
6319
|
-
async function
|
|
6320
|
-
const payload = { type: "set-status", sessionId, status: status3 };
|
|
6472
|
+
async function deliverReliably(sessionId, status3, payload) {
|
|
6321
6473
|
for (let attempt = 1; attempt <= DELIVERY_ATTEMPTS; attempt++) {
|
|
6322
6474
|
try {
|
|
6323
|
-
await
|
|
6475
|
+
await sendToDaemonAwaitAck(payload);
|
|
6324
6476
|
return;
|
|
6325
6477
|
} catch (error) {
|
|
6326
6478
|
if (attempt < DELIVERY_ATTEMPTS) {
|
|
@@ -6328,7 +6480,7 @@ async function deliverStatus(sessionId, status3) {
|
|
|
6328
6480
|
continue;
|
|
6329
6481
|
}
|
|
6330
6482
|
appendDaemonLog(
|
|
6331
|
-
`set-status delivery failed after ${DELIVERY_ATTEMPTS} attempts: id=${sessionId} status=${status3}: ${describeError(error)}`
|
|
6483
|
+
`set-status ack'd delivery failed after ${DELIVERY_ATTEMPTS} attempts: id=${sessionId} status=${status3}: ${describeError(error)}`
|
|
6332
6484
|
);
|
|
6333
6485
|
}
|
|
6334
6486
|
}
|
|
@@ -6339,9 +6491,9 @@ function sleep(ms) {
|
|
|
6339
6491
|
function describeError(error) {
|
|
6340
6492
|
return error instanceof Error ? error.message : String(error);
|
|
6341
6493
|
}
|
|
6342
|
-
function logHookFired(status3, sessionId) {
|
|
6494
|
+
function logHookFired(status3, sessionId, source) {
|
|
6343
6495
|
appendDaemonLog(
|
|
6344
|
-
`set-status hook fired: id=${sessionId ?? "none"} status=${status3}`
|
|
6496
|
+
`set-status hook fired: id=${sessionId ?? "none"} status=${status3}${source ? ` source=${source}` : ""}`
|
|
6345
6497
|
);
|
|
6346
6498
|
}
|
|
6347
6499
|
|
|
@@ -6499,24 +6651,24 @@ function getOwnerPath(itemId2) {
|
|
|
6499
6651
|
function recordSignalOwner(itemId2) {
|
|
6500
6652
|
const sessionId = process.env.ASSIST_SESSION_ID;
|
|
6501
6653
|
if (!sessionId) return;
|
|
6502
|
-
const
|
|
6503
|
-
mkdirSync7(dirname14(
|
|
6504
|
-
writeFileSync17(
|
|
6654
|
+
const path71 = getOwnerPath(itemId2);
|
|
6655
|
+
mkdirSync7(dirname14(path71), { recursive: true });
|
|
6656
|
+
writeFileSync17(path71, JSON.stringify({ sessionId }));
|
|
6505
6657
|
}
|
|
6506
6658
|
function readSignalOwner(itemId2) {
|
|
6507
|
-
const
|
|
6508
|
-
if (!existsSync21(
|
|
6659
|
+
const path71 = getOwnerPath(itemId2);
|
|
6660
|
+
if (!existsSync21(path71)) return void 0;
|
|
6509
6661
|
try {
|
|
6510
|
-
const parsed = JSON.parse(readFileSync15(
|
|
6662
|
+
const parsed = JSON.parse(readFileSync15(path71, "utf8"));
|
|
6511
6663
|
return parsed.sessionId;
|
|
6512
6664
|
} catch {
|
|
6513
6665
|
return void 0;
|
|
6514
6666
|
}
|
|
6515
6667
|
}
|
|
6516
6668
|
function clearSignalOwner(itemId2) {
|
|
6517
|
-
const
|
|
6669
|
+
const path71 = getOwnerPath(itemId2);
|
|
6518
6670
|
try {
|
|
6519
|
-
rmSync(
|
|
6671
|
+
rmSync(path71);
|
|
6520
6672
|
} catch {
|
|
6521
6673
|
}
|
|
6522
6674
|
}
|
|
@@ -6553,19 +6705,19 @@ function resolveSignalTarget(event, data) {
|
|
|
6553
6705
|
function writeSignal(event, data) {
|
|
6554
6706
|
const target = resolveSignalTarget(event, data);
|
|
6555
6707
|
if (!target) return;
|
|
6556
|
-
const
|
|
6557
|
-
if (!
|
|
6708
|
+
const path71 = getSignalPath(target);
|
|
6709
|
+
if (!path71) return;
|
|
6558
6710
|
const signal = { event, sessionId: target, ...data };
|
|
6559
|
-
mkdirSync8(dirname15(
|
|
6560
|
-
writeFileSync18(
|
|
6711
|
+
mkdirSync8(dirname15(path71), { recursive: true });
|
|
6712
|
+
writeFileSync18(path71, JSON.stringify(signal));
|
|
6561
6713
|
}
|
|
6562
6714
|
|
|
6563
6715
|
// src/commands/backlog/readSignal.ts
|
|
6564
6716
|
function readSignal() {
|
|
6565
|
-
const
|
|
6566
|
-
if (!
|
|
6717
|
+
const path71 = getSignalPath();
|
|
6718
|
+
if (!path71 || !existsSync22(path71)) return void 0;
|
|
6567
6719
|
try {
|
|
6568
|
-
return JSON.parse(readFileSync16(
|
|
6720
|
+
return JSON.parse(readFileSync16(path71, "utf8"));
|
|
6569
6721
|
} catch {
|
|
6570
6722
|
return void 0;
|
|
6571
6723
|
}
|
|
@@ -6698,13 +6850,13 @@ function activityPath(sessionId) {
|
|
|
6698
6850
|
function emitActivity(activity2) {
|
|
6699
6851
|
const sessionId = process.env.ASSIST_ACTIVITY_ID;
|
|
6700
6852
|
if (!sessionId) return;
|
|
6701
|
-
const
|
|
6702
|
-
mkdirSync9(dirname16(
|
|
6703
|
-
writeFileSync19(
|
|
6853
|
+
const path71 = activityPath(sessionId);
|
|
6854
|
+
mkdirSync9(dirname16(path71), { recursive: true });
|
|
6855
|
+
writeFileSync19(path71, JSON.stringify({ ...activity2, startedAt: Date.now() }));
|
|
6704
6856
|
}
|
|
6705
|
-
function readActivity(
|
|
6857
|
+
function readActivity(path71) {
|
|
6706
6858
|
try {
|
|
6707
|
-
return JSON.parse(readFileSync17(
|
|
6859
|
+
return JSON.parse(readFileSync17(path71, "utf8"));
|
|
6708
6860
|
} catch {
|
|
6709
6861
|
return void 0;
|
|
6710
6862
|
}
|
|
@@ -6714,9 +6866,9 @@ function reconcileActivity(sessionId, activity2) {
|
|
|
6714
6866
|
removeActivity(sessionId);
|
|
6715
6867
|
return;
|
|
6716
6868
|
}
|
|
6717
|
-
const
|
|
6718
|
-
mkdirSync9(dirname16(
|
|
6719
|
-
writeFileSync19(
|
|
6869
|
+
const path71 = activityPath(sessionId);
|
|
6870
|
+
mkdirSync9(dirname16(path71), { recursive: true });
|
|
6871
|
+
writeFileSync19(path71, JSON.stringify(activity2));
|
|
6720
6872
|
}
|
|
6721
6873
|
function removeActivity(sessionId) {
|
|
6722
6874
|
try {
|
|
@@ -7966,45 +8118,6 @@ async function loadItemSummaries(orm, origin) {
|
|
|
7966
8118
|
return rows.map(rowToItemSummary);
|
|
7967
8119
|
}
|
|
7968
8120
|
|
|
7969
|
-
// src/commands/backlog/originDisplayName.ts
|
|
7970
|
-
function originDisplayName(origin) {
|
|
7971
|
-
if (origin.startsWith("local:")) {
|
|
7972
|
-
const path70 = origin.slice("local:".length).replace(/\/+$/, "");
|
|
7973
|
-
const segments = path70.split("/").filter(Boolean);
|
|
7974
|
-
return segments[segments.length - 1] ?? origin;
|
|
7975
|
-
}
|
|
7976
|
-
const firstSlash = origin.indexOf("/");
|
|
7977
|
-
if (firstSlash === -1) return origin;
|
|
7978
|
-
return origin.slice(firstSlash + 1);
|
|
7979
|
-
}
|
|
7980
|
-
|
|
7981
|
-
// src/commands/backlog/originDisplayLabels.ts
|
|
7982
|
-
function originDisplayLabels(origins) {
|
|
7983
|
-
const isLocal = (origin) => origin.startsWith("local:");
|
|
7984
|
-
const bareName = (origin) => {
|
|
7985
|
-
const full = originDisplayName(origin);
|
|
7986
|
-
const segments = full.split("/");
|
|
7987
|
-
return segments[segments.length - 1] ?? full;
|
|
7988
|
-
};
|
|
7989
|
-
const remoteCounts = /* @__PURE__ */ new Map();
|
|
7990
|
-
for (const origin of new Set(origins)) {
|
|
7991
|
-
if (isLocal(origin)) continue;
|
|
7992
|
-
const name = bareName(origin);
|
|
7993
|
-
remoteCounts.set(name, (remoteCounts.get(name) ?? 0) + 1);
|
|
7994
|
-
}
|
|
7995
|
-
const labels = /* @__PURE__ */ new Map();
|
|
7996
|
-
for (const origin of origins) {
|
|
7997
|
-
if (isLocal(origin)) {
|
|
7998
|
-
labels.set(origin, originDisplayName(origin));
|
|
7999
|
-
continue;
|
|
8000
|
-
}
|
|
8001
|
-
const name = bareName(origin);
|
|
8002
|
-
const collides = (remoteCounts.get(name) ?? 0) > 1;
|
|
8003
|
-
labels.set(origin, collides ? originDisplayName(origin) : name);
|
|
8004
|
-
}
|
|
8005
|
-
return labels;
|
|
8006
|
-
}
|
|
8007
|
-
|
|
8008
8121
|
// src/commands/backlog/resolveRepoLocation.ts
|
|
8009
8122
|
import { existsSync as existsSync25 } from "fs";
|
|
8010
8123
|
|
|
@@ -8406,7 +8519,7 @@ function findSynthesisForBranch(repoReviewsDir, branch2) {
|
|
|
8406
8519
|
const parent = dirname20(branchKeyPath);
|
|
8407
8520
|
const branchPrefix = basename5(branchKeyPath);
|
|
8408
8521
|
if (!existsSync26(parent)) return null;
|
|
8409
|
-
const synthesisFiles = readdirSync2(parent).filter((name) => name.startsWith(branchPrefix)).map((name) => join24(parent, name, "synthesis.md")).filter((
|
|
8522
|
+
const synthesisFiles = readdirSync2(parent).filter((name) => name.startsWith(branchPrefix)).map((name) => join24(parent, name, "synthesis.md")).filter((path71) => existsSync26(path71)).map((path71) => ({ path: path71, mtime: statSync2(path71).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
|
|
8410
8523
|
return synthesisFiles[0]?.path ?? null;
|
|
8411
8524
|
}
|
|
8412
8525
|
|
|
@@ -8460,12 +8573,12 @@ async function getReviewSynthesis(req, res) {
|
|
|
8460
8573
|
const cwd = getCwdParam(req, res);
|
|
8461
8574
|
if (!cwd) return;
|
|
8462
8575
|
try {
|
|
8463
|
-
const
|
|
8464
|
-
if (!
|
|
8576
|
+
const path71 = await resolveSynthesisPath(cwd);
|
|
8577
|
+
if (!path71) {
|
|
8465
8578
|
respondJson(res, 404, { error: "No synthesis found" });
|
|
8466
8579
|
return;
|
|
8467
8580
|
}
|
|
8468
|
-
respondJson(res, 200, { synthesis: readFileSync19(
|
|
8581
|
+
respondJson(res, 200, { synthesis: readFileSync19(path71, "utf8") });
|
|
8469
8582
|
} catch {
|
|
8470
8583
|
respondJson(res, 404, { error: "No synthesis found" });
|
|
8471
8584
|
}
|
|
@@ -8612,10 +8725,10 @@ function getStorePath(filename) {
|
|
|
8612
8725
|
return join27(getStoreDir(), filename);
|
|
8613
8726
|
}
|
|
8614
8727
|
function loadJson(filename) {
|
|
8615
|
-
const
|
|
8616
|
-
if (existsSync27(
|
|
8728
|
+
const path71 = getStorePath(filename);
|
|
8729
|
+
if (existsSync27(path71)) {
|
|
8617
8730
|
try {
|
|
8618
|
-
return JSON.parse(readFileSync20(
|
|
8731
|
+
return JSON.parse(readFileSync20(path71, "utf8"));
|
|
8619
8732
|
} catch {
|
|
8620
8733
|
return {};
|
|
8621
8734
|
}
|
|
@@ -9725,9 +9838,9 @@ function originToSshUrl(origin) {
|
|
|
9725
9838
|
const firstSlash = origin.indexOf("/");
|
|
9726
9839
|
if (firstSlash <= 0) return null;
|
|
9727
9840
|
const host = origin.slice(0, firstSlash);
|
|
9728
|
-
const
|
|
9729
|
-
if (!
|
|
9730
|
-
return `git@${host}:${
|
|
9841
|
+
const path71 = origin.slice(firstSlash + 1);
|
|
9842
|
+
if (!path71) return null;
|
|
9843
|
+
return `git@${host}:${path71}.git`;
|
|
9731
9844
|
}
|
|
9732
9845
|
|
|
9733
9846
|
// src/commands/backlog/cloneRepo.ts
|
|
@@ -12036,9 +12149,9 @@ var __dirname4 = dirname21(__filename3);
|
|
|
12036
12149
|
function packageRoot() {
|
|
12037
12150
|
return __dirname4;
|
|
12038
12151
|
}
|
|
12039
|
-
function readLines(
|
|
12040
|
-
if (!existsSync29(
|
|
12041
|
-
return readFileSync23(
|
|
12152
|
+
function readLines(path71) {
|
|
12153
|
+
if (!existsSync29(path71)) return [];
|
|
12154
|
+
return readFileSync23(path71, "utf8").split("\n").filter((line) => line.trim() !== "");
|
|
12042
12155
|
}
|
|
12043
12156
|
var cachedReads;
|
|
12044
12157
|
var cachedWrites;
|
|
@@ -12530,14 +12643,14 @@ function showProgress(p, label2) {
|
|
|
12530
12643
|
const pct = Math.round(p.done / p.total * 100);
|
|
12531
12644
|
process.stderr.write(`\r\x1B[K[${pct}%] Scanning ${label2}...`);
|
|
12532
12645
|
}
|
|
12533
|
-
async function resolveCommand(cli,
|
|
12534
|
-
showProgress(p,
|
|
12535
|
-
const subHelp = await runHelp([cli, ...
|
|
12646
|
+
async function resolveCommand(cli, path71, description, depth, p) {
|
|
12647
|
+
showProgress(p, path71.join(" "));
|
|
12648
|
+
const subHelp = await runHelp([cli, ...path71]);
|
|
12536
12649
|
if (!subHelp || !hasSubcommands(subHelp)) {
|
|
12537
|
-
return [{ path:
|
|
12650
|
+
return [{ path: path71, description }];
|
|
12538
12651
|
}
|
|
12539
|
-
const children = await discoverAt(cli,
|
|
12540
|
-
return children.length > 0 ? children : [{ path:
|
|
12652
|
+
const children = await discoverAt(cli, path71, depth + 1, p);
|
|
12653
|
+
return children.length > 0 ? children : [{ path: path71, description }];
|
|
12541
12654
|
}
|
|
12542
12655
|
async function discoverAt(cli, parentPath, depth, p) {
|
|
12543
12656
|
if (depth > SAFETY_DEPTH) return [];
|
|
@@ -12685,9 +12798,9 @@ function logPath(cli) {
|
|
|
12685
12798
|
return join31(homedir16(), ".assist", `cli-discover-${safeName}.log`);
|
|
12686
12799
|
}
|
|
12687
12800
|
function readCache(cli) {
|
|
12688
|
-
const
|
|
12689
|
-
if (!existsSync31(
|
|
12690
|
-
return readFileSync25(
|
|
12801
|
+
const path71 = logPath(cli);
|
|
12802
|
+
if (!existsSync31(path71)) return void 0;
|
|
12803
|
+
return readFileSync25(path71, "utf8");
|
|
12691
12804
|
}
|
|
12692
12805
|
function writeCache(cli, output) {
|
|
12693
12806
|
const dir = join31(homedir16(), ".assist");
|
|
@@ -12859,9 +12972,9 @@ function sweepRestrictedDir(dir = getRestrictedDir()) {
|
|
|
12859
12972
|
}
|
|
12860
12973
|
const cutoff = Date.now() - STALE_AFTER_MS;
|
|
12861
12974
|
for (const entry of entries) {
|
|
12862
|
-
const
|
|
12975
|
+
const path71 = join33(dir, entry);
|
|
12863
12976
|
try {
|
|
12864
|
-
if (statSync3(
|
|
12977
|
+
if (statSync3(path71).mtimeMs < cutoff) unlinkSync7(path71);
|
|
12865
12978
|
} catch {
|
|
12866
12979
|
continue;
|
|
12867
12980
|
}
|
|
@@ -12871,10 +12984,10 @@ function sweepRestrictedDir(dir = getRestrictedDir()) {
|
|
|
12871
12984
|
// src/commands/codeComment/readPinState.ts
|
|
12872
12985
|
import { existsSync as existsSync32, readFileSync as readFileSync26 } from "fs";
|
|
12873
12986
|
function readPinState(pin) {
|
|
12874
|
-
const
|
|
12875
|
-
if (!existsSync32(
|
|
12987
|
+
const path71 = getPinStatePath(pin);
|
|
12988
|
+
if (!existsSync32(path71)) return void 0;
|
|
12876
12989
|
try {
|
|
12877
|
-
const state = JSON.parse(readFileSync26(
|
|
12990
|
+
const state = JSON.parse(readFileSync26(path71, "utf8"));
|
|
12878
12991
|
if (state.pin !== pin) return void 0;
|
|
12879
12992
|
return state;
|
|
12880
12993
|
} catch {
|
|
@@ -13730,26 +13843,69 @@ function registerComplexity(program2) {
|
|
|
13730
13843
|
}
|
|
13731
13844
|
|
|
13732
13845
|
// src/commands/config/index.ts
|
|
13733
|
-
import chalk122 from "chalk";
|
|
13734
13846
|
import { stringify as stringifyYaml2 } from "yaml";
|
|
13847
|
+
function configList() {
|
|
13848
|
+
const config = loadConfig();
|
|
13849
|
+
console.log(stringifyYaml2(config, { lineWidth: 0 }).trimEnd());
|
|
13850
|
+
}
|
|
13735
13851
|
|
|
13736
|
-
// src/commands/config/
|
|
13737
|
-
|
|
13738
|
-
|
|
13852
|
+
// src/commands/config/configGet.ts
|
|
13853
|
+
import chalk122 from "chalk";
|
|
13854
|
+
|
|
13855
|
+
// src/commands/config/getNestedValue.ts
|
|
13856
|
+
function isTraversable(value) {
|
|
13857
|
+
return value !== null && value !== void 0 && typeof value === "object";
|
|
13739
13858
|
}
|
|
13740
|
-
function
|
|
13741
|
-
return
|
|
13859
|
+
function stepInto(current, key) {
|
|
13860
|
+
return isTraversable(current) ? current[key] : void 0;
|
|
13742
13861
|
}
|
|
13743
|
-
function
|
|
13744
|
-
|
|
13862
|
+
function getNestedValue(obj, path71) {
|
|
13863
|
+
let current = obj;
|
|
13864
|
+
for (const key of path71.split(".")) current = stepInto(current, key);
|
|
13865
|
+
return current;
|
|
13745
13866
|
}
|
|
13746
|
-
|
|
13747
|
-
|
|
13748
|
-
|
|
13867
|
+
|
|
13868
|
+
// src/commands/config/configGet.ts
|
|
13869
|
+
function configGet(key) {
|
|
13870
|
+
console.log(
|
|
13871
|
+
formatOutput(
|
|
13872
|
+
requireNestedValue(loadConfig(), key)
|
|
13873
|
+
)
|
|
13874
|
+
);
|
|
13749
13875
|
}
|
|
13750
|
-
function
|
|
13751
|
-
|
|
13752
|
-
|
|
13876
|
+
function formatOutput(value) {
|
|
13877
|
+
return typeof value === "object" && value !== null ? JSON.stringify(value, null, 2) : String(value);
|
|
13878
|
+
}
|
|
13879
|
+
function requireNestedValue(config, key) {
|
|
13880
|
+
const value = getNestedValue(config, key);
|
|
13881
|
+
if (value === void 0) return exitKeyNotSet(key);
|
|
13882
|
+
return value;
|
|
13883
|
+
}
|
|
13884
|
+
function exitKeyNotSet(key) {
|
|
13885
|
+
console.error(chalk122.red(`Key "${key}" is not set`));
|
|
13886
|
+
process.exit(1);
|
|
13887
|
+
}
|
|
13888
|
+
|
|
13889
|
+
// src/commands/config/configSet.ts
|
|
13890
|
+
import chalk124 from "chalk";
|
|
13891
|
+
|
|
13892
|
+
// src/commands/config/setNestedValue.ts
|
|
13893
|
+
function isPlainObject(val) {
|
|
13894
|
+
return val !== null && typeof val === "object" && !Array.isArray(val);
|
|
13895
|
+
}
|
|
13896
|
+
function isNumericKey(key) {
|
|
13897
|
+
return /^\d+$/.test(key);
|
|
13898
|
+
}
|
|
13899
|
+
function resolveKey(key) {
|
|
13900
|
+
return isNumericKey(key) ? Number.parseInt(key, 10) : key;
|
|
13901
|
+
}
|
|
13902
|
+
function getItem(container, key) {
|
|
13903
|
+
if (Array.isArray(container)) return container[key];
|
|
13904
|
+
return container[key];
|
|
13905
|
+
}
|
|
13906
|
+
function setItem(container, key, value) {
|
|
13907
|
+
if (Array.isArray(container)) container[key] = value;
|
|
13908
|
+
else container[key] = value;
|
|
13753
13909
|
}
|
|
13754
13910
|
function ensureArray(container, key) {
|
|
13755
13911
|
const existing = getItem(container, key);
|
|
@@ -13770,8 +13926,8 @@ function stepIntoNested(container, key, nextKey) {
|
|
|
13770
13926
|
}
|
|
13771
13927
|
return ensureObject(container, resolved);
|
|
13772
13928
|
}
|
|
13773
|
-
function setNestedValue(obj,
|
|
13774
|
-
const keys =
|
|
13929
|
+
function setNestedValue(obj, path71, value) {
|
|
13930
|
+
const keys = path71.split(".");
|
|
13775
13931
|
const result = { ...obj };
|
|
13776
13932
|
let current = result;
|
|
13777
13933
|
for (let i = 0; i < keys.length - 1; i++) {
|
|
@@ -13781,41 +13937,64 @@ function setNestedValue(obj, path70, value) {
|
|
|
13781
13937
|
return result;
|
|
13782
13938
|
}
|
|
13783
13939
|
|
|
13784
|
-
// src/commands/config/
|
|
13785
|
-
|
|
13786
|
-
|
|
13787
|
-
|
|
13788
|
-
return
|
|
13940
|
+
// src/commands/config/validateConfig.ts
|
|
13941
|
+
import chalk123 from "chalk";
|
|
13942
|
+
function validateConfig(updated, key) {
|
|
13943
|
+
const result = assistConfigSchema.safeParse(updated);
|
|
13944
|
+
if (!result.success) return exitValidationFailed(result.error.issues, key);
|
|
13945
|
+
return updated;
|
|
13789
13946
|
}
|
|
13790
|
-
function
|
|
13791
|
-
|
|
13947
|
+
function exitValidationFailed(issues, key) {
|
|
13948
|
+
printValidationErrors(issues, key);
|
|
13949
|
+
process.exit(1);
|
|
13792
13950
|
}
|
|
13793
13951
|
function printValidationErrors(issues, key) {
|
|
13794
13952
|
for (const issue of issues) {
|
|
13795
13953
|
console.error(
|
|
13796
|
-
|
|
13954
|
+
chalk123.red(`${formatIssuePath(issue, key)}: ${issue.message}`)
|
|
13797
13955
|
);
|
|
13798
13956
|
}
|
|
13799
13957
|
}
|
|
13800
|
-
function
|
|
13801
|
-
|
|
13802
|
-
process.exit(1);
|
|
13958
|
+
function formatIssuePath(issue, key) {
|
|
13959
|
+
return issue.path.length > 0 ? issue.path.join(".") : key;
|
|
13803
13960
|
}
|
|
13804
|
-
|
|
13805
|
-
|
|
13806
|
-
|
|
13807
|
-
|
|
13961
|
+
|
|
13962
|
+
// src/commands/config/applyRepoConfigSet.ts
|
|
13963
|
+
function applyRepoConfigSet(key, coerced) {
|
|
13964
|
+
const globalRaw = loadGlobalConfigRaw();
|
|
13965
|
+
const label2 = resolveRepoWriteLabel(
|
|
13966
|
+
globalRaw,
|
|
13967
|
+
getCurrentOrigin(process.cwd())
|
|
13968
|
+
);
|
|
13969
|
+
const repos2 = isPlainObject2(globalRaw.repos) ? { ...globalRaw.repos } : {};
|
|
13970
|
+
const existingBlock = isPlainObject2(repos2[label2]) ? repos2[label2] : {};
|
|
13971
|
+
const updatedBlock = setNestedValue(existingBlock, key, coerced);
|
|
13972
|
+
validateConfig(updatedBlock, key);
|
|
13973
|
+
repos2[label2] = updatedBlock;
|
|
13974
|
+
saveGlobalConfig({ ...globalRaw, repos: repos2 });
|
|
13975
|
+
return label2;
|
|
13808
13976
|
}
|
|
13977
|
+
function isPlainObject2(value) {
|
|
13978
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
13979
|
+
}
|
|
13980
|
+
|
|
13981
|
+
// src/commands/config/configSet.ts
|
|
13809
13982
|
var GLOBAL_ONLY_KEYS = ["sync.autoConfirm"];
|
|
13810
|
-
function
|
|
13811
|
-
|
|
13812
|
-
|
|
13813
|
-
|
|
13814
|
-
`"${key}" is a global-only key. Use --global to set it in ~/.assist.yml`
|
|
13815
|
-
)
|
|
13816
|
-
);
|
|
13983
|
+
function configSet(key, value, options2 = {}) {
|
|
13984
|
+
const coerced = coerceValue(value);
|
|
13985
|
+
if (options2.repo && options2.global) {
|
|
13986
|
+
console.error(chalk124.red("Use either --repo or --global, not both"));
|
|
13817
13987
|
process.exit(1);
|
|
13818
13988
|
}
|
|
13989
|
+
const target = options2.repo ? `repo: ${applyRepoConfigSet(key, coerced)}` : applyConfigSet(key, coerced, options2.global ?? false);
|
|
13990
|
+
console.log(
|
|
13991
|
+
chalk124.green(`Set ${key} = ${JSON.stringify(coerced)} (${target})`)
|
|
13992
|
+
);
|
|
13993
|
+
}
|
|
13994
|
+
function coerceValue(value) {
|
|
13995
|
+
if (value === "true") return true;
|
|
13996
|
+
if (value === "false") return false;
|
|
13997
|
+
return value;
|
|
13819
13998
|
}
|
|
13820
13999
|
function applyConfigSet(key, coerced, global) {
|
|
13821
14000
|
assertNotGlobalOnly(key, global);
|
|
@@ -13824,103 +14003,68 @@ function applyConfigSet(key, coerced, global) {
|
|
|
13824
14003
|
validateConfig(updated, key);
|
|
13825
14004
|
if (global) {
|
|
13826
14005
|
saveGlobalConfig(updated);
|
|
13827
|
-
|
|
13828
|
-
saveConfig(updated);
|
|
14006
|
+
return "global";
|
|
13829
14007
|
}
|
|
14008
|
+
saveConfig(updated);
|
|
14009
|
+
return "project";
|
|
13830
14010
|
}
|
|
13831
|
-
function
|
|
13832
|
-
|
|
13833
|
-
|
|
13834
|
-
|
|
13835
|
-
|
|
13836
|
-
|
|
13837
|
-
|
|
13838
|
-
|
|
13839
|
-
|
|
13840
|
-
const config = loadConfig();
|
|
13841
|
-
console.log(stringifyYaml2(config, { lineWidth: 0 }).trimEnd());
|
|
13842
|
-
}
|
|
13843
|
-
|
|
13844
|
-
// src/commands/config/configGet.ts
|
|
13845
|
-
import chalk123 from "chalk";
|
|
13846
|
-
|
|
13847
|
-
// src/commands/config/getNestedValue.ts
|
|
13848
|
-
function isTraversable(value) {
|
|
13849
|
-
return value !== null && value !== void 0 && typeof value === "object";
|
|
13850
|
-
}
|
|
13851
|
-
function stepInto(current, key) {
|
|
13852
|
-
return isTraversable(current) ? current[key] : void 0;
|
|
13853
|
-
}
|
|
13854
|
-
function getNestedValue(obj, path70) {
|
|
13855
|
-
let current = obj;
|
|
13856
|
-
for (const key of path70.split(".")) current = stepInto(current, key);
|
|
13857
|
-
return current;
|
|
13858
|
-
}
|
|
13859
|
-
|
|
13860
|
-
// src/commands/config/configGet.ts
|
|
13861
|
-
function configGet(key) {
|
|
13862
|
-
console.log(
|
|
13863
|
-
formatOutput(
|
|
13864
|
-
requireNestedValue(loadConfig(), key)
|
|
13865
|
-
)
|
|
13866
|
-
);
|
|
13867
|
-
}
|
|
13868
|
-
function formatOutput(value) {
|
|
13869
|
-
return typeof value === "object" && value !== null ? JSON.stringify(value, null, 2) : String(value);
|
|
13870
|
-
}
|
|
13871
|
-
function requireNestedValue(config, key) {
|
|
13872
|
-
const value = getNestedValue(config, key);
|
|
13873
|
-
if (value === void 0) return exitKeyNotSet(key);
|
|
13874
|
-
return value;
|
|
13875
|
-
}
|
|
13876
|
-
function exitKeyNotSet(key) {
|
|
13877
|
-
console.error(chalk123.red(`Key "${key}" is not set`));
|
|
13878
|
-
process.exit(1);
|
|
14011
|
+
function assertNotGlobalOnly(key, global) {
|
|
14012
|
+
if (!global && GLOBAL_ONLY_KEYS.some((k) => key.startsWith(k))) {
|
|
14013
|
+
console.error(
|
|
14014
|
+
chalk124.red(
|
|
14015
|
+
`"${key}" is a global-only key. Use --global to set it in ~/.assist.yml`
|
|
14016
|
+
)
|
|
14017
|
+
);
|
|
14018
|
+
process.exit(1);
|
|
14019
|
+
}
|
|
13879
14020
|
}
|
|
13880
14021
|
|
|
13881
14022
|
// src/commands/registerConfig.ts
|
|
13882
14023
|
function registerConfig(program2) {
|
|
13883
14024
|
const configCommand = program2.command("config").description("View and modify assist.yml configuration");
|
|
13884
|
-
configCommand.command("set <key> <value>").description("Set a config value (e.g. commit.push true)").option("-g, --global", "Write to global ~/.assist.yml").
|
|
14025
|
+
configCommand.command("set <key> <value>").description("Set a config value (e.g. commit.push true)").option("-g, --global", "Write to global ~/.assist.yml").option(
|
|
14026
|
+
"-r, --repo",
|
|
14027
|
+
"Write to ~/.assist.yml under the current repo's identity"
|
|
14028
|
+
).action((key, value, options2) => configSet(key, value, options2));
|
|
13885
14029
|
configCommand.command("get <key>").description("Get a config value").action(configGet);
|
|
13886
14030
|
configCommand.command("list").description("List all config values").action(configList);
|
|
13887
14031
|
}
|
|
13888
14032
|
|
|
13889
14033
|
// src/commands/db/reportMigrationStatus.ts
|
|
13890
|
-
import
|
|
14034
|
+
import chalk125 from "chalk";
|
|
13891
14035
|
function reportApplied(applied) {
|
|
13892
14036
|
if (applied.length === 0) {
|
|
13893
|
-
console.error(
|
|
14037
|
+
console.error(chalk125.green("Database is up to date; nothing to apply."));
|
|
13894
14038
|
return;
|
|
13895
14039
|
}
|
|
13896
14040
|
for (const migration of applied) {
|
|
13897
14041
|
console.error(
|
|
13898
|
-
|
|
14042
|
+
chalk125.green(`Applied migration ${migration.id} (${migration.name}).`)
|
|
13899
14043
|
);
|
|
13900
14044
|
}
|
|
13901
14045
|
}
|
|
13902
14046
|
function reportMigrationStatus(status3) {
|
|
13903
14047
|
if (status3.state === "in-sync") {
|
|
13904
14048
|
console.error(
|
|
13905
|
-
|
|
14049
|
+
chalk125.green(`In sync at migration ${status3.version} (latest).`)
|
|
13906
14050
|
);
|
|
13907
14051
|
return;
|
|
13908
14052
|
}
|
|
13909
14053
|
if (status3.state === "behind") {
|
|
13910
14054
|
console.error(
|
|
13911
|
-
|
|
14055
|
+
chalk125.yellow(
|
|
13912
14056
|
`Behind: applied ${status3.applied}, build expects ${status3.expected}.`
|
|
13913
14057
|
)
|
|
13914
14058
|
);
|
|
13915
14059
|
console.error(
|
|
13916
|
-
|
|
14060
|
+
chalk125.yellow(
|
|
13917
14061
|
`Pending: ${status3.pending.join(", ")}. Run \`assist db migrate\`.`
|
|
13918
14062
|
)
|
|
13919
14063
|
);
|
|
13920
14064
|
return;
|
|
13921
14065
|
}
|
|
13922
14066
|
console.error(
|
|
13923
|
-
|
|
14067
|
+
chalk125.red(
|
|
13924
14068
|
`Ahead: applied ${status3.applied}, build knows ${status3.expected}. Update assist.`
|
|
13925
14069
|
)
|
|
13926
14070
|
);
|
|
@@ -13955,7 +14099,7 @@ function registerDb(program2) {
|
|
|
13955
14099
|
|
|
13956
14100
|
// src/commands/dbMigration/dbMigrationConfirm.ts
|
|
13957
14101
|
import { unlinkSync as unlinkSync9, writeFileSync as writeFileSync26 } from "fs";
|
|
13958
|
-
import
|
|
14102
|
+
import chalk126 from "chalk";
|
|
13959
14103
|
|
|
13960
14104
|
// src/commands/dbMigration/getMigrationPinPath.ts
|
|
13961
14105
|
import { join as join34 } from "path";
|
|
@@ -13969,10 +14113,10 @@ function getMigrationApprovalPath(migrationId) {
|
|
|
13969
14113
|
// src/commands/dbMigration/readMigrationPinState.ts
|
|
13970
14114
|
import { existsSync as existsSync34, readFileSync as readFileSync28 } from "fs";
|
|
13971
14115
|
function readMigrationPinState(pin) {
|
|
13972
|
-
const
|
|
13973
|
-
if (!existsSync34(
|
|
14116
|
+
const path71 = getMigrationPinPath(pin);
|
|
14117
|
+
if (!existsSync34(path71)) return void 0;
|
|
13974
14118
|
try {
|
|
13975
|
-
const state = JSON.parse(readFileSync28(
|
|
14119
|
+
const state = JSON.parse(readFileSync28(path71, "utf8"));
|
|
13976
14120
|
if (state.pin !== pin) return void 0;
|
|
13977
14121
|
if (!Number.isInteger(state.migrationId)) return void 0;
|
|
13978
14122
|
return state;
|
|
@@ -13986,7 +14130,7 @@ function dbMigrationConfirm(pin) {
|
|
|
13986
14130
|
sweepRestrictedDir();
|
|
13987
14131
|
const state = readMigrationPinState(pin);
|
|
13988
14132
|
if (!state) {
|
|
13989
|
-
console.error(
|
|
14133
|
+
console.error(chalk126.red(`No pending migration unlock for pin: ${pin}`));
|
|
13990
14134
|
process.exitCode = 1;
|
|
13991
14135
|
return;
|
|
13992
14136
|
}
|
|
@@ -13996,7 +14140,7 @@ function dbMigrationConfirm(pin) {
|
|
|
13996
14140
|
);
|
|
13997
14141
|
unlinkSync9(getMigrationPinPath(pin));
|
|
13998
14142
|
console.log(
|
|
13999
|
-
|
|
14143
|
+
chalk126.green(
|
|
14000
14144
|
`Approved creation of migration ${state.migrationId}. The next write of that migration module will be allowed once.`
|
|
14001
14145
|
)
|
|
14002
14146
|
);
|
|
@@ -14005,7 +14149,7 @@ function dbMigrationConfirm(pin) {
|
|
|
14005
14149
|
// src/commands/dbMigration/dbMigrationUnlock.ts
|
|
14006
14150
|
import { mkdirSync as mkdirSync15, writeFileSync as writeFileSync27 } from "fs";
|
|
14007
14151
|
import { randomInt as randomInt2 } from "crypto";
|
|
14008
|
-
import
|
|
14152
|
+
import chalk127 from "chalk";
|
|
14009
14153
|
|
|
14010
14154
|
// src/commands/dbMigration/nextMigrationId.ts
|
|
14011
14155
|
function nextMigrationId() {
|
|
@@ -14020,7 +14164,7 @@ function dbMigrationUnlock() {
|
|
|
14020
14164
|
sweepRestrictedDir();
|
|
14021
14165
|
writeFileSync27(getMigrationPinPath(pin), JSON.stringify({ pin, migrationId }));
|
|
14022
14166
|
console.error(
|
|
14023
|
-
|
|
14167
|
+
chalk127.yellow.bold(
|
|
14024
14168
|
"THIS IS YOUR LAST CHANCE TO RECONSIDER BEFORE INVOLVING A HUMAN.\nRequesting this pin pages a real person to approve a new database migration.\nA schema change is hard to reverse once shipped. You had BETTER have confirmed\nthe change with the user and be certain this migration is genuinely necessary."
|
|
14025
14169
|
)
|
|
14026
14170
|
);
|
|
@@ -14030,7 +14174,7 @@ function dbMigrationUnlock() {
|
|
|
14030
14174
|
});
|
|
14031
14175
|
if (!delivered) {
|
|
14032
14176
|
console.error(
|
|
14033
|
-
|
|
14177
|
+
chalk127.red(
|
|
14034
14178
|
"Could not deliver the confirmation pin via notification.\nThe migration cannot be approved until the notification channel works."
|
|
14035
14179
|
)
|
|
14036
14180
|
);
|
|
@@ -14040,7 +14184,7 @@ function dbMigrationUnlock() {
|
|
|
14040
14184
|
console.log(
|
|
14041
14185
|
`A confirmation pin was sent to your desktop notifications.
|
|
14042
14186
|
To approve creating migration ${migrationId}, run:
|
|
14043
|
-
${
|
|
14187
|
+
${chalk127.cyan(" assist db-migration confirm <PIN>")}
|
|
14044
14188
|
using the pin from that notification.`
|
|
14045
14189
|
);
|
|
14046
14190
|
}
|
|
@@ -14060,7 +14204,7 @@ function registerDbMigration(parent) {
|
|
|
14060
14204
|
|
|
14061
14205
|
// src/commands/deploy/redirect.ts
|
|
14062
14206
|
import { existsSync as existsSync35, readFileSync as readFileSync29, writeFileSync as writeFileSync28 } from "fs";
|
|
14063
|
-
import
|
|
14207
|
+
import chalk128 from "chalk";
|
|
14064
14208
|
var TRAILING_SLASH_SCRIPT = ` <script>
|
|
14065
14209
|
if (!window.location.pathname.endsWith('/')) {
|
|
14066
14210
|
window.location.href = \`\${window.location.pathname}/\${window.location.search}\${window.location.hash}\`;
|
|
@@ -14069,23 +14213,23 @@ var TRAILING_SLASH_SCRIPT = ` <script>
|
|
|
14069
14213
|
function redirect() {
|
|
14070
14214
|
const indexPath = "index.html";
|
|
14071
14215
|
if (!existsSync35(indexPath)) {
|
|
14072
|
-
console.log(
|
|
14216
|
+
console.log(chalk128.yellow("No index.html found"));
|
|
14073
14217
|
return;
|
|
14074
14218
|
}
|
|
14075
14219
|
const content = readFileSync29(indexPath, "utf8");
|
|
14076
14220
|
if (content.includes("window.location.pathname.endsWith('/')")) {
|
|
14077
|
-
console.log(
|
|
14221
|
+
console.log(chalk128.dim("Trailing slash script already present"));
|
|
14078
14222
|
return;
|
|
14079
14223
|
}
|
|
14080
14224
|
const headCloseIndex = content.indexOf("</head>");
|
|
14081
14225
|
if (headCloseIndex === -1) {
|
|
14082
|
-
console.log(
|
|
14226
|
+
console.log(chalk128.red("Could not find </head> tag in index.html"));
|
|
14083
14227
|
return;
|
|
14084
14228
|
}
|
|
14085
14229
|
const newContent = `${content.slice(0, headCloseIndex) + TRAILING_SLASH_SCRIPT}
|
|
14086
14230
|
${content.slice(headCloseIndex)}`;
|
|
14087
14231
|
writeFileSync28(indexPath, newContent);
|
|
14088
|
-
console.log(
|
|
14232
|
+
console.log(chalk128.green("Added trailing slash redirect to index.html"));
|
|
14089
14233
|
}
|
|
14090
14234
|
|
|
14091
14235
|
// src/commands/registerDeploy.ts
|
|
@@ -14112,7 +14256,7 @@ function loadBlogSkipDays(repoName) {
|
|
|
14112
14256
|
|
|
14113
14257
|
// src/commands/devlog/shared.ts
|
|
14114
14258
|
import { execSync as execSync33 } from "child_process";
|
|
14115
|
-
import
|
|
14259
|
+
import chalk129 from "chalk";
|
|
14116
14260
|
|
|
14117
14261
|
// src/shared/getRepoName.ts
|
|
14118
14262
|
import { existsSync as existsSync36, readFileSync as readFileSync30 } from "fs";
|
|
@@ -14221,13 +14365,13 @@ function shouldIgnoreCommit(files, ignorePaths) {
|
|
|
14221
14365
|
}
|
|
14222
14366
|
function printCommitsWithFiles(commits2, ignore3, verbose) {
|
|
14223
14367
|
for (const commit2 of commits2) {
|
|
14224
|
-
console.log(` ${
|
|
14368
|
+
console.log(` ${chalk129.yellow(commit2.hash)} ${commit2.message}`);
|
|
14225
14369
|
if (verbose) {
|
|
14226
14370
|
const visibleFiles = commit2.files.filter(
|
|
14227
14371
|
(file) => !ignore3.some((p) => file.startsWith(p))
|
|
14228
14372
|
);
|
|
14229
14373
|
for (const file of visibleFiles) {
|
|
14230
|
-
console.log(` ${
|
|
14374
|
+
console.log(` ${chalk129.dim(file)}`);
|
|
14231
14375
|
}
|
|
14232
14376
|
}
|
|
14233
14377
|
}
|
|
@@ -14252,15 +14396,15 @@ function parseGitLogCommits(output, ignore3, afterDate) {
|
|
|
14252
14396
|
}
|
|
14253
14397
|
|
|
14254
14398
|
// src/commands/devlog/list/printDateHeader.ts
|
|
14255
|
-
import
|
|
14399
|
+
import chalk130 from "chalk";
|
|
14256
14400
|
function printDateHeader(date, isSkipped, entries) {
|
|
14257
14401
|
if (isSkipped) {
|
|
14258
|
-
console.log(`${
|
|
14402
|
+
console.log(`${chalk130.bold.blue(date)} ${chalk130.dim("skipped")}`);
|
|
14259
14403
|
} else if (entries && entries.length > 0) {
|
|
14260
|
-
const entryInfo = entries.map((e) => `${
|
|
14261
|
-
console.log(`${
|
|
14404
|
+
const entryInfo = entries.map((e) => `${chalk130.green(e.version)} ${e.title}`).join(" | ");
|
|
14405
|
+
console.log(`${chalk130.bold.blue(date)} ${entryInfo}`);
|
|
14262
14406
|
} else {
|
|
14263
|
-
console.log(`${
|
|
14407
|
+
console.log(`${chalk130.bold.blue(date)} ${chalk130.red("\u26A0 devlog missing")}`);
|
|
14264
14408
|
}
|
|
14265
14409
|
}
|
|
14266
14410
|
|
|
@@ -14364,24 +14508,24 @@ function bumpVersion(version2, type) {
|
|
|
14364
14508
|
|
|
14365
14509
|
// src/commands/devlog/next/displayNextEntry/index.ts
|
|
14366
14510
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
14367
|
-
import
|
|
14511
|
+
import chalk132 from "chalk";
|
|
14368
14512
|
|
|
14369
14513
|
// src/commands/devlog/next/displayNextEntry/displayVersion.ts
|
|
14370
|
-
import
|
|
14514
|
+
import chalk131 from "chalk";
|
|
14371
14515
|
function displayVersion(conventional, firstHash, patchVersion, minorVersion) {
|
|
14372
14516
|
if (conventional && firstHash) {
|
|
14373
14517
|
const version2 = getVersionAtCommit(firstHash);
|
|
14374
14518
|
if (version2) {
|
|
14375
|
-
console.log(`${
|
|
14519
|
+
console.log(`${chalk131.bold("version:")} ${stripToMinor(version2)}`);
|
|
14376
14520
|
} else {
|
|
14377
|
-
console.log(`${
|
|
14521
|
+
console.log(`${chalk131.bold("version:")} ${chalk131.red("unknown")}`);
|
|
14378
14522
|
}
|
|
14379
14523
|
} else if (patchVersion && minorVersion) {
|
|
14380
14524
|
console.log(
|
|
14381
|
-
`${
|
|
14525
|
+
`${chalk131.bold("version:")} ${patchVersion} (patch) or ${minorVersion} (minor)`
|
|
14382
14526
|
);
|
|
14383
14527
|
} else {
|
|
14384
|
-
console.log(`${
|
|
14528
|
+
console.log(`${chalk131.bold("version:")} v0.1 (initial)`);
|
|
14385
14529
|
}
|
|
14386
14530
|
}
|
|
14387
14531
|
|
|
@@ -14429,16 +14573,16 @@ function noCommitsMessage(hasLastInfo) {
|
|
|
14429
14573
|
return hasLastInfo ? "No commits after last versioned entry" : "No commits found";
|
|
14430
14574
|
}
|
|
14431
14575
|
function logName(repoName) {
|
|
14432
|
-
console.log(`${
|
|
14576
|
+
console.log(`${chalk132.bold("name:")} ${repoName}`);
|
|
14433
14577
|
}
|
|
14434
14578
|
function displayNextEntry(ctx, targetDate, commits2) {
|
|
14435
14579
|
logName(ctx.repoName);
|
|
14436
14580
|
printVersionInfo(ctx.config, ctx.lastInfo, commits2[0]?.hash);
|
|
14437
|
-
console.log(
|
|
14581
|
+
console.log(chalk132.bold.blue(targetDate));
|
|
14438
14582
|
printCommitsWithFiles(commits2, ctx.ignore, ctx.verbose);
|
|
14439
14583
|
}
|
|
14440
14584
|
function logNoCommits(lastInfo) {
|
|
14441
|
-
console.log(
|
|
14585
|
+
console.log(chalk132.dim(noCommitsMessage(!!lastInfo)));
|
|
14442
14586
|
}
|
|
14443
14587
|
|
|
14444
14588
|
// src/commands/devlog/next/index.ts
|
|
@@ -14479,11 +14623,11 @@ function next2(options2) {
|
|
|
14479
14623
|
import { execSync as execSync35 } from "child_process";
|
|
14480
14624
|
|
|
14481
14625
|
// src/commands/devlog/repos/printReposTable.ts
|
|
14482
|
-
import
|
|
14626
|
+
import chalk133 from "chalk";
|
|
14483
14627
|
function colorStatus(status3) {
|
|
14484
|
-
if (status3 === "missing") return
|
|
14485
|
-
if (status3 === "outdated") return
|
|
14486
|
-
return
|
|
14628
|
+
if (status3 === "missing") return chalk133.red(status3);
|
|
14629
|
+
if (status3 === "outdated") return chalk133.yellow(status3);
|
|
14630
|
+
return chalk133.green(status3);
|
|
14487
14631
|
}
|
|
14488
14632
|
function formatRow(row, nameWidth) {
|
|
14489
14633
|
const devlog = (row.lastDevlog ?? "-").padEnd(11);
|
|
@@ -14497,8 +14641,8 @@ function printReposTable(rows) {
|
|
|
14497
14641
|
"Last Devlog".padEnd(11),
|
|
14498
14642
|
"Status"
|
|
14499
14643
|
].join(" ");
|
|
14500
|
-
console.log(
|
|
14501
|
-
console.log(
|
|
14644
|
+
console.log(chalk133.dim(header));
|
|
14645
|
+
console.log(chalk133.dim("-".repeat(header.length)));
|
|
14502
14646
|
for (const row of rows) {
|
|
14503
14647
|
console.log(formatRow(row, nameWidth));
|
|
14504
14648
|
}
|
|
@@ -14556,14 +14700,14 @@ function repos(options2) {
|
|
|
14556
14700
|
// src/commands/devlog/skip.ts
|
|
14557
14701
|
import { writeFileSync as writeFileSync29 } from "fs";
|
|
14558
14702
|
import { join as join38 } from "path";
|
|
14559
|
-
import
|
|
14703
|
+
import chalk134 from "chalk";
|
|
14560
14704
|
import { stringify as stringifyYaml3 } from "yaml";
|
|
14561
14705
|
function getBlogConfigPath() {
|
|
14562
14706
|
return join38(BLOG_REPO_ROOT, "assist.yml");
|
|
14563
14707
|
}
|
|
14564
14708
|
function skip(date) {
|
|
14565
14709
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
|
|
14566
|
-
console.log(
|
|
14710
|
+
console.log(chalk134.red("Invalid date format. Use YYYY-MM-DD"));
|
|
14567
14711
|
process.exit(1);
|
|
14568
14712
|
}
|
|
14569
14713
|
const repoName = getRepoName();
|
|
@@ -14574,7 +14718,7 @@ function skip(date) {
|
|
|
14574
14718
|
const skipDays = skip2[repoName] ?? [];
|
|
14575
14719
|
if (skipDays.includes(date)) {
|
|
14576
14720
|
console.log(
|
|
14577
|
-
|
|
14721
|
+
chalk134.yellow(`${date} is already in skip list for ${repoName}`)
|
|
14578
14722
|
);
|
|
14579
14723
|
return;
|
|
14580
14724
|
}
|
|
@@ -14584,20 +14728,20 @@ function skip(date) {
|
|
|
14584
14728
|
devlog.skip = skip2;
|
|
14585
14729
|
config.devlog = devlog;
|
|
14586
14730
|
writeFileSync29(configPath, stringifyYaml3(config, { lineWidth: 0 }));
|
|
14587
|
-
console.log(
|
|
14731
|
+
console.log(chalk134.green(`Added ${date} to skip list for ${repoName}`));
|
|
14588
14732
|
}
|
|
14589
14733
|
|
|
14590
14734
|
// src/commands/devlog/version.ts
|
|
14591
|
-
import
|
|
14735
|
+
import chalk135 from "chalk";
|
|
14592
14736
|
function version() {
|
|
14593
14737
|
const config = loadConfig();
|
|
14594
14738
|
const name = getRepoName();
|
|
14595
14739
|
const lastInfo = getLastVersionInfo(name, config);
|
|
14596
14740
|
const lastVersion = lastInfo?.version ?? null;
|
|
14597
14741
|
const nextVersion = lastVersion ? bumpVersion(lastVersion, "patch") : null;
|
|
14598
|
-
console.log(`${
|
|
14599
|
-
console.log(`${
|
|
14600
|
-
console.log(`${
|
|
14742
|
+
console.log(`${chalk135.bold("name:")} ${name}`);
|
|
14743
|
+
console.log(`${chalk135.bold("last:")} ${lastVersion ?? chalk135.dim("none")}`);
|
|
14744
|
+
console.log(`${chalk135.bold("next:")} ${nextVersion ?? chalk135.dim("none")}`);
|
|
14601
14745
|
}
|
|
14602
14746
|
|
|
14603
14747
|
// src/commands/devlog/devlogConfigHelp.ts
|
|
@@ -14641,7 +14785,7 @@ function registerDevlog(program2) {
|
|
|
14641
14785
|
// src/commands/dotnet/checkBuildLocks.ts
|
|
14642
14786
|
import { closeSync as closeSync3, openSync as openSync3, readdirSync as readdirSync5 } from "fs";
|
|
14643
14787
|
import { join as join39 } from "path";
|
|
14644
|
-
import
|
|
14788
|
+
import chalk136 from "chalk";
|
|
14645
14789
|
|
|
14646
14790
|
// src/shared/findRepoRoot.ts
|
|
14647
14791
|
import { existsSync as existsSync37 } from "fs";
|
|
@@ -14704,14 +14848,14 @@ function checkBuildLocks(startDir) {
|
|
|
14704
14848
|
const locked = findFirstLockedDll(startDir ?? getSearchRoot());
|
|
14705
14849
|
if (locked) {
|
|
14706
14850
|
console.error(
|
|
14707
|
-
|
|
14851
|
+
chalk136.red("Build output locked (is VS debugging?): ") + locked
|
|
14708
14852
|
);
|
|
14709
14853
|
process.exit(1);
|
|
14710
14854
|
}
|
|
14711
14855
|
}
|
|
14712
14856
|
async function checkBuildLocksCommand() {
|
|
14713
14857
|
checkBuildLocks();
|
|
14714
|
-
console.log(
|
|
14858
|
+
console.log(chalk136.green("No build locks detected"));
|
|
14715
14859
|
}
|
|
14716
14860
|
|
|
14717
14861
|
// src/commands/dotnet/buildTree.ts
|
|
@@ -14810,30 +14954,30 @@ function escapeRegex(s) {
|
|
|
14810
14954
|
}
|
|
14811
14955
|
|
|
14812
14956
|
// src/commands/dotnet/printTree.ts
|
|
14813
|
-
import
|
|
14957
|
+
import chalk137 from "chalk";
|
|
14814
14958
|
function printNodes(nodes, prefix2) {
|
|
14815
14959
|
for (let i = 0; i < nodes.length; i++) {
|
|
14816
14960
|
const isLast = i === nodes.length - 1;
|
|
14817
14961
|
const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
|
|
14818
14962
|
const childPrefix = isLast ? " " : "\u2502 ";
|
|
14819
14963
|
const isMissing = nodes[i].relativePath.startsWith("[MISSING]");
|
|
14820
|
-
const label2 = isMissing ?
|
|
14964
|
+
const label2 = isMissing ? chalk137.red(nodes[i].relativePath) : nodes[i].relativePath;
|
|
14821
14965
|
console.log(`${prefix2}${connector}${label2}`);
|
|
14822
14966
|
printNodes(nodes[i].children, prefix2 + childPrefix);
|
|
14823
14967
|
}
|
|
14824
14968
|
}
|
|
14825
14969
|
function printTree(tree, totalCount, solutions) {
|
|
14826
|
-
console.log(
|
|
14827
|
-
console.log(
|
|
14970
|
+
console.log(chalk137.bold("\nProject Dependency Tree"));
|
|
14971
|
+
console.log(chalk137.cyan(tree.relativePath));
|
|
14828
14972
|
printNodes(tree.children, "");
|
|
14829
|
-
console.log(
|
|
14973
|
+
console.log(chalk137.dim(`
|
|
14830
14974
|
${totalCount} projects total (including root)`));
|
|
14831
|
-
console.log(
|
|
14975
|
+
console.log(chalk137.bold("\nSolution Membership"));
|
|
14832
14976
|
if (solutions.length === 0) {
|
|
14833
|
-
console.log(
|
|
14977
|
+
console.log(chalk137.yellow(" Not found in any .sln"));
|
|
14834
14978
|
} else {
|
|
14835
14979
|
for (const sln of solutions) {
|
|
14836
|
-
console.log(` ${
|
|
14980
|
+
console.log(` ${chalk137.green(sln)}`);
|
|
14837
14981
|
}
|
|
14838
14982
|
}
|
|
14839
14983
|
console.log();
|
|
@@ -14862,16 +15006,16 @@ function printJson(tree, totalCount, solutions) {
|
|
|
14862
15006
|
// src/commands/dotnet/resolveCsproj.ts
|
|
14863
15007
|
import { existsSync as existsSync38 } from "fs";
|
|
14864
15008
|
import path33 from "path";
|
|
14865
|
-
import
|
|
15009
|
+
import chalk138 from "chalk";
|
|
14866
15010
|
function resolveCsproj(csprojPath) {
|
|
14867
15011
|
const resolved = path33.resolve(csprojPath);
|
|
14868
15012
|
if (!existsSync38(resolved)) {
|
|
14869
|
-
console.error(
|
|
15013
|
+
console.error(chalk138.red(`File not found: ${resolved}`));
|
|
14870
15014
|
process.exit(1);
|
|
14871
15015
|
}
|
|
14872
15016
|
const repoRoot = findRepoRoot(path33.dirname(resolved));
|
|
14873
15017
|
if (!repoRoot) {
|
|
14874
|
-
console.error(
|
|
15018
|
+
console.error(chalk138.red("Could not find git repository root"));
|
|
14875
15019
|
process.exit(1);
|
|
14876
15020
|
}
|
|
14877
15021
|
return { resolved, repoRoot };
|
|
@@ -14921,12 +15065,12 @@ function getChangedCsFiles(scope) {
|
|
|
14921
15065
|
}
|
|
14922
15066
|
|
|
14923
15067
|
// src/commands/dotnet/inSln.ts
|
|
14924
|
-
import
|
|
15068
|
+
import chalk139 from "chalk";
|
|
14925
15069
|
async function inSln(csprojPath) {
|
|
14926
15070
|
const { resolved, repoRoot } = resolveCsproj(csprojPath);
|
|
14927
15071
|
const solutions = findContainingSolutions(resolved, repoRoot);
|
|
14928
15072
|
if (solutions.length === 0) {
|
|
14929
|
-
console.log(
|
|
15073
|
+
console.log(chalk139.yellow("Not found in any .sln file"));
|
|
14930
15074
|
process.exit(1);
|
|
14931
15075
|
}
|
|
14932
15076
|
for (const sln of solutions) {
|
|
@@ -14935,7 +15079,7 @@ async function inSln(csprojPath) {
|
|
|
14935
15079
|
}
|
|
14936
15080
|
|
|
14937
15081
|
// src/commands/dotnet/inspect.ts
|
|
14938
|
-
import
|
|
15082
|
+
import chalk145 from "chalk";
|
|
14939
15083
|
|
|
14940
15084
|
// src/shared/formatElapsed.ts
|
|
14941
15085
|
function formatElapsed(ms) {
|
|
@@ -14947,12 +15091,12 @@ function formatElapsed(ms) {
|
|
|
14947
15091
|
}
|
|
14948
15092
|
|
|
14949
15093
|
// src/commands/dotnet/displayIssues.ts
|
|
14950
|
-
import
|
|
15094
|
+
import chalk140 from "chalk";
|
|
14951
15095
|
var SEVERITY_COLOR = {
|
|
14952
|
-
ERROR:
|
|
14953
|
-
WARNING:
|
|
14954
|
-
SUGGESTION:
|
|
14955
|
-
HINT:
|
|
15096
|
+
ERROR: chalk140.red,
|
|
15097
|
+
WARNING: chalk140.yellow,
|
|
15098
|
+
SUGGESTION: chalk140.cyan,
|
|
15099
|
+
HINT: chalk140.dim
|
|
14956
15100
|
};
|
|
14957
15101
|
function groupByFile(issues) {
|
|
14958
15102
|
const byFile = /* @__PURE__ */ new Map();
|
|
@@ -14968,15 +15112,15 @@ function groupByFile(issues) {
|
|
|
14968
15112
|
}
|
|
14969
15113
|
function displayIssues(issues) {
|
|
14970
15114
|
for (const [file, fileIssues] of groupByFile(issues)) {
|
|
14971
|
-
console.log(
|
|
15115
|
+
console.log(chalk140.bold(file));
|
|
14972
15116
|
for (const issue of fileIssues.sort((a, b) => a.line - b.line)) {
|
|
14973
|
-
const color = SEVERITY_COLOR[issue.severity] ??
|
|
15117
|
+
const color = SEVERITY_COLOR[issue.severity] ?? chalk140.white;
|
|
14974
15118
|
console.log(
|
|
14975
|
-
` ${
|
|
15119
|
+
` ${chalk140.dim(`${issue.line}:`)} ${color(issue.severity)} [${issue.typeId}] ${issue.message}`
|
|
14976
15120
|
);
|
|
14977
15121
|
}
|
|
14978
15122
|
}
|
|
14979
|
-
console.log(
|
|
15123
|
+
console.log(chalk140.dim(`
|
|
14980
15124
|
${issues.length} issue(s) found`));
|
|
14981
15125
|
}
|
|
14982
15126
|
|
|
@@ -15035,12 +15179,12 @@ function filterIssues(issues, all, cliOnly, cliSuppress) {
|
|
|
15035
15179
|
// src/commands/dotnet/resolveSolution.ts
|
|
15036
15180
|
import { existsSync as existsSync39 } from "fs";
|
|
15037
15181
|
import path34 from "path";
|
|
15038
|
-
import
|
|
15182
|
+
import chalk142 from "chalk";
|
|
15039
15183
|
|
|
15040
15184
|
// src/commands/dotnet/findSolution.ts
|
|
15041
15185
|
import { readdirSync as readdirSync7 } from "fs";
|
|
15042
15186
|
import { dirname as dirname22, join as join40 } from "path";
|
|
15043
|
-
import
|
|
15187
|
+
import chalk141 from "chalk";
|
|
15044
15188
|
function findSlnInDir(dir) {
|
|
15045
15189
|
try {
|
|
15046
15190
|
return readdirSync7(dir).filter((f) => f.endsWith(".sln")).map((f) => join40(dir, f));
|
|
@@ -15056,17 +15200,17 @@ function findSolution() {
|
|
|
15056
15200
|
const slnFiles = findSlnInDir(current);
|
|
15057
15201
|
if (slnFiles.length === 1) return slnFiles[0];
|
|
15058
15202
|
if (slnFiles.length > 1) {
|
|
15059
|
-
console.error(
|
|
15203
|
+
console.error(chalk141.red(`Multiple .sln files found in ${current}:`));
|
|
15060
15204
|
for (const f of slnFiles) console.error(` ${f}`);
|
|
15061
15205
|
console.error(
|
|
15062
|
-
|
|
15206
|
+
chalk141.yellow("Specify which one: assist dotnet inspect <sln>")
|
|
15063
15207
|
);
|
|
15064
15208
|
process.exit(1);
|
|
15065
15209
|
}
|
|
15066
15210
|
if (current === ceiling) break;
|
|
15067
15211
|
current = dirname22(current);
|
|
15068
15212
|
}
|
|
15069
|
-
console.error(
|
|
15213
|
+
console.error(chalk141.red("No .sln file found between cwd and repo root"));
|
|
15070
15214
|
process.exit(1);
|
|
15071
15215
|
}
|
|
15072
15216
|
|
|
@@ -15075,7 +15219,7 @@ function resolveSolution(sln) {
|
|
|
15075
15219
|
if (sln) {
|
|
15076
15220
|
const resolved = path34.resolve(sln);
|
|
15077
15221
|
if (!existsSync39(resolved)) {
|
|
15078
|
-
console.error(
|
|
15222
|
+
console.error(chalk142.red(`Solution file not found: ${resolved}`));
|
|
15079
15223
|
process.exit(1);
|
|
15080
15224
|
}
|
|
15081
15225
|
return resolved;
|
|
@@ -15117,14 +15261,14 @@ import { execSync as execSync37 } from "child_process";
|
|
|
15117
15261
|
import { existsSync as existsSync40, readFileSync as readFileSync34, unlinkSync as unlinkSync10 } from "fs";
|
|
15118
15262
|
import { tmpdir as tmpdir3 } from "os";
|
|
15119
15263
|
import path35 from "path";
|
|
15120
|
-
import
|
|
15264
|
+
import chalk143 from "chalk";
|
|
15121
15265
|
function assertJbInstalled() {
|
|
15122
15266
|
try {
|
|
15123
15267
|
execSync37("jb inspectcode --version", { stdio: "pipe" });
|
|
15124
15268
|
} catch {
|
|
15125
|
-
console.error(
|
|
15269
|
+
console.error(chalk143.red("jb is not installed. Install with:"));
|
|
15126
15270
|
console.error(
|
|
15127
|
-
|
|
15271
|
+
chalk143.yellow(" dotnet tool install -g JetBrains.ReSharper.GlobalTools")
|
|
15128
15272
|
);
|
|
15129
15273
|
process.exit(1);
|
|
15130
15274
|
}
|
|
@@ -15142,11 +15286,11 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
15142
15286
|
if (error && typeof error === "object" && "stderr" in error) {
|
|
15143
15287
|
process.stderr.write(error.stderr);
|
|
15144
15288
|
}
|
|
15145
|
-
console.error(
|
|
15289
|
+
console.error(chalk143.red("jb inspectcode failed"));
|
|
15146
15290
|
process.exit(1);
|
|
15147
15291
|
}
|
|
15148
15292
|
if (!existsSync40(reportPath)) {
|
|
15149
|
-
console.error(
|
|
15293
|
+
console.error(chalk143.red("Report file not generated"));
|
|
15150
15294
|
process.exit(1);
|
|
15151
15295
|
}
|
|
15152
15296
|
const xml = readFileSync34(reportPath, "utf8");
|
|
@@ -15156,7 +15300,7 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
15156
15300
|
|
|
15157
15301
|
// src/commands/dotnet/runRoslynInspect.ts
|
|
15158
15302
|
import { execSync as execSync38 } from "child_process";
|
|
15159
|
-
import
|
|
15303
|
+
import chalk144 from "chalk";
|
|
15160
15304
|
function resolveMsbuildPath() {
|
|
15161
15305
|
const { run: run4 } = loadConfig();
|
|
15162
15306
|
const configs = resolveRunConfigs(run4, getConfigDir());
|
|
@@ -15168,9 +15312,9 @@ function assertMsbuildInstalled() {
|
|
|
15168
15312
|
try {
|
|
15169
15313
|
execSync38(`"${msbuild}" -version`, { stdio: "pipe" });
|
|
15170
15314
|
} catch {
|
|
15171
|
-
console.error(
|
|
15315
|
+
console.error(chalk144.red(`msbuild not found at: ${msbuild}`));
|
|
15172
15316
|
console.error(
|
|
15173
|
-
|
|
15317
|
+
chalk144.yellow(
|
|
15174
15318
|
"Configure it via a 'build' run entry in .claude/assist.yml or add msbuild to PATH."
|
|
15175
15319
|
)
|
|
15176
15320
|
);
|
|
@@ -15217,17 +15361,17 @@ function runEngine(resolved, changedFiles, options2) {
|
|
|
15217
15361
|
// src/commands/dotnet/inspect.ts
|
|
15218
15362
|
function logScope(changedFiles) {
|
|
15219
15363
|
if (changedFiles === null) {
|
|
15220
|
-
console.log(
|
|
15364
|
+
console.log(chalk145.dim("Inspecting full solution..."));
|
|
15221
15365
|
} else {
|
|
15222
15366
|
console.log(
|
|
15223
|
-
|
|
15367
|
+
chalk145.dim(`Inspecting ${changedFiles.length} changed file(s)...`)
|
|
15224
15368
|
);
|
|
15225
15369
|
}
|
|
15226
15370
|
}
|
|
15227
15371
|
function reportResults(issues, elapsed) {
|
|
15228
15372
|
if (issues.length > 0) displayIssues(issues);
|
|
15229
|
-
else console.log(
|
|
15230
|
-
console.log(
|
|
15373
|
+
else console.log(chalk145.green("No issues found"));
|
|
15374
|
+
console.log(chalk145.dim(`Completed in ${formatElapsed(elapsed)}`));
|
|
15231
15375
|
if (issues.length > 0) process.exit(1);
|
|
15232
15376
|
}
|
|
15233
15377
|
async function inspect(sln, options2) {
|
|
@@ -15238,7 +15382,7 @@ async function inspect(sln, options2) {
|
|
|
15238
15382
|
const scope = parseScope(options2.scope);
|
|
15239
15383
|
const changedFiles = getChangedCsFiles(scope);
|
|
15240
15384
|
if (changedFiles !== null && changedFiles.length === 0) {
|
|
15241
|
-
console.log(
|
|
15385
|
+
console.log(chalk145.green("No changed .cs files found"));
|
|
15242
15386
|
return;
|
|
15243
15387
|
}
|
|
15244
15388
|
logScope(changedFiles);
|
|
@@ -15411,10 +15555,10 @@ function decideCommentGuard(input, existingContent) {
|
|
|
15411
15555
|
import { existsSync as existsSync41, unlinkSync as unlinkSync11 } from "fs";
|
|
15412
15556
|
function consumeMigrationApproval(migrationId) {
|
|
15413
15557
|
sweepRestrictedDir();
|
|
15414
|
-
const
|
|
15415
|
-
if (!existsSync41(
|
|
15558
|
+
const path71 = getMigrationApprovalPath(migrationId);
|
|
15559
|
+
if (!existsSync41(path71)) return false;
|
|
15416
15560
|
try {
|
|
15417
|
-
unlinkSync11(
|
|
15561
|
+
unlinkSync11(path71);
|
|
15418
15562
|
return true;
|
|
15419
15563
|
} catch {
|
|
15420
15564
|
return false;
|
|
@@ -15621,25 +15765,25 @@ function fetchRepoCommitAuthors(org, repo, since) {
|
|
|
15621
15765
|
}
|
|
15622
15766
|
|
|
15623
15767
|
// src/commands/github/printCountTable.ts
|
|
15624
|
-
import
|
|
15768
|
+
import chalk146 from "chalk";
|
|
15625
15769
|
function printCountTable(labelHeader, rows) {
|
|
15626
15770
|
const labelWidth = Math.max(
|
|
15627
15771
|
labelHeader.length,
|
|
15628
15772
|
...rows.map((row) => row.label.length)
|
|
15629
15773
|
);
|
|
15630
15774
|
const header = `${labelHeader.padEnd(labelWidth)} Commits`;
|
|
15631
|
-
console.log(
|
|
15632
|
-
console.log(
|
|
15775
|
+
console.log(chalk146.dim(header));
|
|
15776
|
+
console.log(chalk146.dim("-".repeat(header.length)));
|
|
15633
15777
|
for (const row of rows) {
|
|
15634
15778
|
console.log(`${row.label.padEnd(labelWidth)} ${row.count}`);
|
|
15635
15779
|
}
|
|
15636
15780
|
}
|
|
15637
15781
|
|
|
15638
15782
|
// src/commands/github/printRepoAuthorBreakdown.ts
|
|
15639
|
-
import
|
|
15783
|
+
import chalk147 from "chalk";
|
|
15640
15784
|
function printRepoAuthorBreakdown(repos2) {
|
|
15641
15785
|
for (const repo of repos2) {
|
|
15642
|
-
console.log(
|
|
15786
|
+
console.log(chalk147.bold(repo.name));
|
|
15643
15787
|
const authorWidth = Math.max(
|
|
15644
15788
|
0,
|
|
15645
15789
|
...repo.authors.map((a) => a.author.length)
|
|
@@ -15957,7 +16101,7 @@ function registerHandover(program2) {
|
|
|
15957
16101
|
}
|
|
15958
16102
|
|
|
15959
16103
|
// src/commands/jira/acceptanceCriteria.ts
|
|
15960
|
-
import
|
|
16104
|
+
import chalk148 from "chalk";
|
|
15961
16105
|
|
|
15962
16106
|
// src/commands/jira/adfToText.ts
|
|
15963
16107
|
function renderInline(node) {
|
|
@@ -16024,7 +16168,7 @@ function acceptanceCriteria(issueKey) {
|
|
|
16024
16168
|
const parsed = fetchIssue(issueKey, field);
|
|
16025
16169
|
const acValue = parsed?.fields?.[field];
|
|
16026
16170
|
if (!acValue) {
|
|
16027
|
-
console.log(
|
|
16171
|
+
console.log(chalk148.yellow(`No acceptance criteria found on ${issueKey}.`));
|
|
16028
16172
|
return;
|
|
16029
16173
|
}
|
|
16030
16174
|
if (typeof acValue === "string") {
|
|
@@ -16090,14 +16234,14 @@ async function jiraAuth() {
|
|
|
16090
16234
|
}
|
|
16091
16235
|
|
|
16092
16236
|
// src/commands/jira/viewIssue.ts
|
|
16093
|
-
import
|
|
16237
|
+
import chalk149 from "chalk";
|
|
16094
16238
|
function viewIssue(issueKey) {
|
|
16095
16239
|
const parsed = fetchIssue(issueKey, "summary,description");
|
|
16096
16240
|
const fields = parsed?.fields;
|
|
16097
16241
|
const summary = fields?.summary;
|
|
16098
16242
|
const description = fields?.description;
|
|
16099
16243
|
if (summary) {
|
|
16100
|
-
console.log(
|
|
16244
|
+
console.log(chalk149.bold(summary));
|
|
16101
16245
|
}
|
|
16102
16246
|
if (description) {
|
|
16103
16247
|
if (summary) console.log();
|
|
@@ -16111,7 +16255,7 @@ function viewIssue(issueKey) {
|
|
|
16111
16255
|
}
|
|
16112
16256
|
if (!summary && !description) {
|
|
16113
16257
|
console.log(
|
|
16114
|
-
|
|
16258
|
+
chalk149.yellow(`No summary or description found on ${issueKey}.`)
|
|
16115
16259
|
);
|
|
16116
16260
|
}
|
|
16117
16261
|
}
|
|
@@ -16167,13 +16311,13 @@ function registerRefineLaunch(program2, resumeFlag) {
|
|
|
16167
16311
|
// src/commands/reviewPrComments.ts
|
|
16168
16312
|
import { execFileSync as execFileSync5 } from "child_process";
|
|
16169
16313
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
16170
|
-
import
|
|
16314
|
+
import chalk150 from "chalk";
|
|
16171
16315
|
async function reviewPrComments(number) {
|
|
16172
16316
|
if (number) {
|
|
16173
16317
|
try {
|
|
16174
16318
|
execFileSync5("gh", ["pr", "checkout", number], { stdio: "inherit" });
|
|
16175
16319
|
} catch {
|
|
16176
|
-
console.error(
|
|
16320
|
+
console.error(chalk150.red(`gh pr checkout ${number} failed; aborting.`));
|
|
16177
16321
|
process.exit(1);
|
|
16178
16322
|
}
|
|
16179
16323
|
}
|
|
@@ -16246,15 +16390,15 @@ function registerList(program2) {
|
|
|
16246
16390
|
// src/commands/mermaid/index.ts
|
|
16247
16391
|
import { mkdirSync as mkdirSync16, readdirSync as readdirSync9 } from "fs";
|
|
16248
16392
|
import { resolve as resolve12 } from "path";
|
|
16249
|
-
import
|
|
16393
|
+
import chalk153 from "chalk";
|
|
16250
16394
|
|
|
16251
16395
|
// src/commands/mermaid/exportFile.ts
|
|
16252
16396
|
import { readFileSync as readFileSync36, writeFileSync as writeFileSync31 } from "fs";
|
|
16253
16397
|
import { basename as basename11, extname, resolve as resolve11 } from "path";
|
|
16254
|
-
import
|
|
16398
|
+
import chalk152 from "chalk";
|
|
16255
16399
|
|
|
16256
16400
|
// src/commands/mermaid/renderBlock.ts
|
|
16257
|
-
import
|
|
16401
|
+
import chalk151 from "chalk";
|
|
16258
16402
|
async function renderBlock(krokiUrl, source) {
|
|
16259
16403
|
const response = await fetch(`${krokiUrl}/mermaid/svg`, {
|
|
16260
16404
|
method: "POST",
|
|
@@ -16263,7 +16407,7 @@ async function renderBlock(krokiUrl, source) {
|
|
|
16263
16407
|
});
|
|
16264
16408
|
if (!response.ok) {
|
|
16265
16409
|
console.error(
|
|
16266
|
-
|
|
16410
|
+
chalk151.red(
|
|
16267
16411
|
`Kroki request failed: ${response.status} ${response.statusText}`
|
|
16268
16412
|
)
|
|
16269
16413
|
);
|
|
@@ -16281,19 +16425,19 @@ async function exportFile(file, outDir, krokiUrl, onlyIndex) {
|
|
|
16281
16425
|
if (onlyIndex !== void 0) {
|
|
16282
16426
|
if (onlyIndex < 1 || onlyIndex > blocks.length) {
|
|
16283
16427
|
console.error(
|
|
16284
|
-
|
|
16428
|
+
chalk152.red(
|
|
16285
16429
|
`${file}: --index ${onlyIndex} out of range (file has ${blocks.length} diagram(s))`
|
|
16286
16430
|
)
|
|
16287
16431
|
);
|
|
16288
16432
|
process.exit(1);
|
|
16289
16433
|
}
|
|
16290
16434
|
console.log(
|
|
16291
|
-
|
|
16435
|
+
chalk152.gray(
|
|
16292
16436
|
`${file} \u2014 rendering diagram ${onlyIndex} of ${blocks.length}`
|
|
16293
16437
|
)
|
|
16294
16438
|
);
|
|
16295
16439
|
} else {
|
|
16296
|
-
console.log(
|
|
16440
|
+
console.log(chalk152.gray(`${file} \u2014 ${blocks.length} diagram(s)`));
|
|
16297
16441
|
}
|
|
16298
16442
|
for (const [i, source] of blocks.entries()) {
|
|
16299
16443
|
const idx = i + 1;
|
|
@@ -16301,7 +16445,7 @@ async function exportFile(file, outDir, krokiUrl, onlyIndex) {
|
|
|
16301
16445
|
const outPath = resolve11(outDir, `${stem}-${idx}.svg`);
|
|
16302
16446
|
const svg = await renderBlock(krokiUrl, source);
|
|
16303
16447
|
writeFileSync31(outPath, svg, "utf8");
|
|
16304
|
-
console.log(
|
|
16448
|
+
console.log(chalk152.green(` \u2192 ${outPath}`));
|
|
16305
16449
|
}
|
|
16306
16450
|
}
|
|
16307
16451
|
function extractMermaidBlocks(markdown) {
|
|
@@ -16317,18 +16461,18 @@ async function mermaidExport(file, options2 = {}) {
|
|
|
16317
16461
|
if (options2.index !== void 0) {
|
|
16318
16462
|
if (!Number.isInteger(options2.index) || options2.index < 1) {
|
|
16319
16463
|
console.error(
|
|
16320
|
-
|
|
16464
|
+
chalk153.red(`--index must be a positive integer (got ${options2.index})`)
|
|
16321
16465
|
);
|
|
16322
16466
|
process.exit(1);
|
|
16323
16467
|
}
|
|
16324
16468
|
if (!file) {
|
|
16325
|
-
console.error(
|
|
16469
|
+
console.error(chalk153.red("--index requires a file argument"));
|
|
16326
16470
|
process.exit(1);
|
|
16327
16471
|
}
|
|
16328
16472
|
}
|
|
16329
16473
|
const files = file ? [file] : readdirSync9(process.cwd()).filter((name) => name.toLowerCase().endsWith(".md")).sort();
|
|
16330
16474
|
if (files.length === 0) {
|
|
16331
|
-
console.log(
|
|
16475
|
+
console.log(chalk153.gray("No markdown files found in current directory."));
|
|
16332
16476
|
return;
|
|
16333
16477
|
}
|
|
16334
16478
|
for (const f of files) {
|
|
@@ -16361,7 +16505,7 @@ function registerMermaid(program2) {
|
|
|
16361
16505
|
import { mkdir as mkdir4 } from "fs/promises";
|
|
16362
16506
|
import { createServer as createServer2 } from "http";
|
|
16363
16507
|
import { dirname as dirname24 } from "path";
|
|
16364
|
-
import
|
|
16508
|
+
import chalk155 from "chalk";
|
|
16365
16509
|
|
|
16366
16510
|
// src/commands/netcap/corsHeaders.ts
|
|
16367
16511
|
var corsHeaders = {
|
|
@@ -16440,7 +16584,7 @@ function createNetcapHandler(options2) {
|
|
|
16440
16584
|
import { cp, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
|
|
16441
16585
|
import { networkInterfaces } from "os";
|
|
16442
16586
|
import { join as join46 } from "path";
|
|
16443
|
-
import
|
|
16587
|
+
import chalk154 from "chalk";
|
|
16444
16588
|
|
|
16445
16589
|
// src/commands/netcap/netcapExtensionDir.ts
|
|
16446
16590
|
import { dirname as dirname23, join as join45 } from "path";
|
|
@@ -16484,7 +16628,7 @@ async function prepareExtensionForLoad(port, filter = "") {
|
|
|
16484
16628
|
const host = lanIPv4();
|
|
16485
16629
|
if (!host) {
|
|
16486
16630
|
console.log(
|
|
16487
|
-
|
|
16631
|
+
chalk154.yellow("could not determine the WSL IP for the extension")
|
|
16488
16632
|
);
|
|
16489
16633
|
await configureBackground(source, "127.0.0.1", port, filter);
|
|
16490
16634
|
return source;
|
|
@@ -16495,7 +16639,7 @@ async function prepareExtensionForLoad(port, filter = "") {
|
|
|
16495
16639
|
return WSL_WINDOWS_PATH;
|
|
16496
16640
|
} catch {
|
|
16497
16641
|
console.log(
|
|
16498
|
-
|
|
16642
|
+
chalk154.yellow(`could not copy extension to ${WSL_WINDOWS_PATH}`)
|
|
16499
16643
|
);
|
|
16500
16644
|
return source;
|
|
16501
16645
|
}
|
|
@@ -16528,30 +16672,30 @@ async function netcap(options2) {
|
|
|
16528
16672
|
let count7 = 0;
|
|
16529
16673
|
const handler = createNetcapHandler({
|
|
16530
16674
|
outPath,
|
|
16531
|
-
onPing: () => console.log(
|
|
16675
|
+
onPing: () => console.log(chalk155.dim("ping from extension")),
|
|
16532
16676
|
onCapture: (entry) => {
|
|
16533
16677
|
count7 += 1;
|
|
16534
16678
|
console.log(
|
|
16535
|
-
|
|
16536
|
-
|
|
16679
|
+
chalk155.green(`captured #${count7}`),
|
|
16680
|
+
chalk155.dim(`${entry.method ?? "?"} ${entry.url ?? "?"}`)
|
|
16537
16681
|
);
|
|
16538
16682
|
}
|
|
16539
16683
|
});
|
|
16540
16684
|
const server = createServer2(handler);
|
|
16541
16685
|
server.listen(port, () => {
|
|
16542
16686
|
console.log(
|
|
16543
|
-
|
|
16687
|
+
chalk155.bold(`netcap receiver listening on http://127.0.0.1:${port}`)
|
|
16544
16688
|
);
|
|
16545
|
-
console.log(
|
|
16689
|
+
console.log(chalk155.dim(`appending captures to ${outPath}`));
|
|
16546
16690
|
if (filter)
|
|
16547
|
-
console.log(
|
|
16548
|
-
console.log(
|
|
16549
|
-
console.log(
|
|
16691
|
+
console.log(chalk155.dim(`forwarding only URLs matching "${filter}"`));
|
|
16692
|
+
console.log(chalk155.dim(`load the unpacked extension from ${extensionPath}`));
|
|
16693
|
+
console.log(chalk155.dim("press Ctrl-C to stop"));
|
|
16550
16694
|
});
|
|
16551
16695
|
process.on("SIGINT", () => {
|
|
16552
16696
|
server.close();
|
|
16553
16697
|
console.log(
|
|
16554
|
-
|
|
16698
|
+
chalk155.bold(
|
|
16555
16699
|
`
|
|
16556
16700
|
netcap stopped \u2014 captured ${count7} ${count7 === 1 ? "entry" : "entries"} to ${outPath}`
|
|
16557
16701
|
)
|
|
@@ -16563,7 +16707,7 @@ netcap stopped \u2014 captured ${count7} ${count7 === 1 ? "entry" : "entries"} t
|
|
|
16563
16707
|
// src/commands/netcap/netcapExtract.ts
|
|
16564
16708
|
import { writeFileSync as writeFileSync32 } from "fs";
|
|
16565
16709
|
import { join as join49 } from "path";
|
|
16566
|
-
import
|
|
16710
|
+
import chalk156 from "chalk";
|
|
16567
16711
|
|
|
16568
16712
|
// src/commands/netcap/extractPostsFromCapture.ts
|
|
16569
16713
|
import { readFileSync as readFileSync37 } from "fs";
|
|
@@ -16588,9 +16732,9 @@ function parseRscRows(flight) {
|
|
|
16588
16732
|
}
|
|
16589
16733
|
function makeRscResolver(rows) {
|
|
16590
16734
|
return (ref) => {
|
|
16591
|
-
const [id, ...
|
|
16735
|
+
const [id, ...path71] = ref.slice(1).replace(/^[L@]/, "").split(":");
|
|
16592
16736
|
let v = rows[id];
|
|
16593
|
-
for (const key of
|
|
16737
|
+
for (const key of path71) {
|
|
16594
16738
|
if (v == null || typeof v !== "object") return void 0;
|
|
16595
16739
|
v = v[key];
|
|
16596
16740
|
}
|
|
@@ -17011,8 +17155,8 @@ function netcapExtract(file) {
|
|
|
17011
17155
|
writeFileSync32(outFile, `${JSON.stringify(posts, null, 2)}
|
|
17012
17156
|
`);
|
|
17013
17157
|
console.log(
|
|
17014
|
-
|
|
17015
|
-
|
|
17158
|
+
chalk156.green(`extracted ${posts.length} posts`),
|
|
17159
|
+
chalk156.dim(`-> ${outFile}`)
|
|
17016
17160
|
);
|
|
17017
17161
|
}
|
|
17018
17162
|
|
|
@@ -17033,7 +17177,7 @@ function registerNetcap(program2) {
|
|
|
17033
17177
|
}
|
|
17034
17178
|
|
|
17035
17179
|
// src/commands/news/add/index.ts
|
|
17036
|
-
import
|
|
17180
|
+
import chalk157 from "chalk";
|
|
17037
17181
|
import enquirer8 from "enquirer";
|
|
17038
17182
|
async function add2(url) {
|
|
17039
17183
|
if (!url) {
|
|
@@ -17055,10 +17199,10 @@ async function add2(url) {
|
|
|
17055
17199
|
const { orm } = await getReady();
|
|
17056
17200
|
const added = await addFeed(orm, url);
|
|
17057
17201
|
if (!added) {
|
|
17058
|
-
console.log(
|
|
17202
|
+
console.log(chalk157.yellow("Feed already exists"));
|
|
17059
17203
|
return;
|
|
17060
17204
|
}
|
|
17061
|
-
console.log(
|
|
17205
|
+
console.log(chalk157.green(`Added feed: ${url}`));
|
|
17062
17206
|
}
|
|
17063
17207
|
|
|
17064
17208
|
// src/commands/registerNews.ts
|
|
@@ -17105,7 +17249,7 @@ function registerPiHook(program2) {
|
|
|
17105
17249
|
}
|
|
17106
17250
|
|
|
17107
17251
|
// src/commands/prompts/printPromptsTable.ts
|
|
17108
|
-
import
|
|
17252
|
+
import chalk158 from "chalk";
|
|
17109
17253
|
function truncate(str, max) {
|
|
17110
17254
|
if (str.length <= max) return str;
|
|
17111
17255
|
return `${str.slice(0, max - 1)}\u2026`;
|
|
@@ -17123,14 +17267,14 @@ function printPromptsTable(rows) {
|
|
|
17123
17267
|
"Command".padEnd(commandWidth),
|
|
17124
17268
|
"Repos"
|
|
17125
17269
|
].join(" ");
|
|
17126
|
-
console.log(
|
|
17127
|
-
console.log(
|
|
17270
|
+
console.log(chalk158.dim(header));
|
|
17271
|
+
console.log(chalk158.dim("-".repeat(header.length)));
|
|
17128
17272
|
for (const row of rows) {
|
|
17129
17273
|
const count7 = String(row.count).padStart(countWidth);
|
|
17130
17274
|
const tool = row.tool.padEnd(toolWidth);
|
|
17131
17275
|
const command = truncate(row.command, 60).padEnd(commandWidth);
|
|
17132
17276
|
console.log(
|
|
17133
|
-
`${
|
|
17277
|
+
`${chalk158.yellow(count7)} ${tool} ${command} ${chalk158.dim(row.repos)}`
|
|
17134
17278
|
);
|
|
17135
17279
|
}
|
|
17136
17280
|
}
|
|
@@ -17274,15 +17418,15 @@ function postComment(vars) {
|
|
|
17274
17418
|
const stdout = startLine === void 0 ? runGhGraphql(MUTATION_SINGLE, base) : runGhGraphql(MUTATION_MULTI, { ...base, startLine });
|
|
17275
17419
|
assertThreadCreated(stdout);
|
|
17276
17420
|
}
|
|
17277
|
-
function comment2(
|
|
17421
|
+
function comment2(path71, line, body, startLine) {
|
|
17278
17422
|
validateBody(body);
|
|
17279
17423
|
validateLine(line);
|
|
17280
17424
|
if (startLine !== void 0) validateLine(startLine);
|
|
17281
17425
|
try {
|
|
17282
17426
|
const prId = getCurrentPrNodeId();
|
|
17283
|
-
postComment({ prId, body, path:
|
|
17427
|
+
postComment({ prId, body, path: path71, line, startLine });
|
|
17284
17428
|
const range = startLine !== void 0 ? `${startLine}-${line}` : `${line}`;
|
|
17285
|
-
console.log(`Added review comment on ${
|
|
17429
|
+
console.log(`Added review comment on ${path71}:${range}`);
|
|
17286
17430
|
} catch (error) {
|
|
17287
17431
|
if (isGhNotInstalled(error)) {
|
|
17288
17432
|
console.error("Error: GitHub CLI (gh) is not installed.");
|
|
@@ -17697,20 +17841,20 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
|
|
|
17697
17841
|
}
|
|
17698
17842
|
|
|
17699
17843
|
// src/commands/prs/listComments/printComments.ts
|
|
17700
|
-
import
|
|
17844
|
+
import chalk159 from "chalk";
|
|
17701
17845
|
function formatForHuman(comment3) {
|
|
17702
17846
|
if (comment3.type === "review") {
|
|
17703
|
-
const stateColor = comment3.state === "APPROVED" ?
|
|
17847
|
+
const stateColor = comment3.state === "APPROVED" ? chalk159.green : comment3.state === "CHANGES_REQUESTED" ? chalk159.red : chalk159.yellow;
|
|
17704
17848
|
return [
|
|
17705
|
-
`${
|
|
17849
|
+
`${chalk159.cyan("Review")} by ${chalk159.bold(comment3.user)} ${stateColor(`[${comment3.state}]`)}`,
|
|
17706
17850
|
comment3.body,
|
|
17707
17851
|
""
|
|
17708
17852
|
].join("\n");
|
|
17709
17853
|
}
|
|
17710
17854
|
const location = comment3.line ? `:${comment3.line}` : "";
|
|
17711
17855
|
return [
|
|
17712
|
-
`${
|
|
17713
|
-
|
|
17856
|
+
`${chalk159.cyan("Line comment")} by ${chalk159.bold(comment3.user)} on ${chalk159.dim(`${comment3.path}${location}`)}`,
|
|
17857
|
+
chalk159.dim(comment3.diff_hunk.split("\n").slice(-3).join("\n")),
|
|
17714
17858
|
comment3.body,
|
|
17715
17859
|
""
|
|
17716
17860
|
].join("\n");
|
|
@@ -17800,13 +17944,13 @@ import { execSync as execSync46 } from "child_process";
|
|
|
17800
17944
|
import enquirer9 from "enquirer";
|
|
17801
17945
|
|
|
17802
17946
|
// src/commands/prs/prs/displayPaginated/printPr.ts
|
|
17803
|
-
import
|
|
17947
|
+
import chalk160 from "chalk";
|
|
17804
17948
|
var STATUS_MAP = {
|
|
17805
|
-
MERGED: (pr) => pr.mergedAt ? { label:
|
|
17806
|
-
CLOSED: (pr) => pr.closedAt ? { label:
|
|
17949
|
+
MERGED: (pr) => pr.mergedAt ? { label: chalk160.magenta("merged"), date: pr.mergedAt } : null,
|
|
17950
|
+
CLOSED: (pr) => pr.closedAt ? { label: chalk160.red("closed"), date: pr.closedAt } : null
|
|
17807
17951
|
};
|
|
17808
17952
|
function defaultStatus(pr) {
|
|
17809
|
-
return { label:
|
|
17953
|
+
return { label: chalk160.green("opened"), date: pr.createdAt };
|
|
17810
17954
|
}
|
|
17811
17955
|
function getStatus2(pr) {
|
|
17812
17956
|
return STATUS_MAP[pr.state]?.(pr) ?? defaultStatus(pr);
|
|
@@ -17815,11 +17959,11 @@ function formatDate(dateStr) {
|
|
|
17815
17959
|
return new Date(dateStr).toISOString().split("T")[0];
|
|
17816
17960
|
}
|
|
17817
17961
|
function formatPrHeader(pr, status3) {
|
|
17818
|
-
return `${
|
|
17962
|
+
return `${chalk160.cyan(`#${pr.number}`)} ${pr.title} ${chalk160.dim(`(${pr.author.login},`)} ${status3.label} ${chalk160.dim(`${formatDate(status3.date)})`)}`;
|
|
17819
17963
|
}
|
|
17820
17964
|
function logPrDetails(pr) {
|
|
17821
17965
|
console.log(
|
|
17822
|
-
|
|
17966
|
+
chalk160.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
|
|
17823
17967
|
);
|
|
17824
17968
|
console.log();
|
|
17825
17969
|
}
|
|
@@ -18161,17 +18305,17 @@ function registerPrs(program2) {
|
|
|
18161
18305
|
prsCommand.command("reply <comment-id> <body>").description("Reply to a comment thread without resolving it").action((commentId, body) => {
|
|
18162
18306
|
reply(Number.parseInt(commentId, 10), body);
|
|
18163
18307
|
});
|
|
18164
|
-
prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((
|
|
18165
|
-
comment2(
|
|
18308
|
+
prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((path71, line, body) => {
|
|
18309
|
+
comment2(path71, Number.parseInt(line, 10), body);
|
|
18166
18310
|
});
|
|
18167
18311
|
configHelp(prsCommand, prsConfigHelp);
|
|
18168
18312
|
}
|
|
18169
18313
|
|
|
18170
18314
|
// src/commands/ravendb/ravendbAuth.ts
|
|
18171
|
-
import
|
|
18315
|
+
import chalk166 from "chalk";
|
|
18172
18316
|
|
|
18173
18317
|
// src/shared/createConnectionAuth.ts
|
|
18174
|
-
import
|
|
18318
|
+
import chalk161 from "chalk";
|
|
18175
18319
|
function listConnections(connections, format) {
|
|
18176
18320
|
if (connections.length === 0) {
|
|
18177
18321
|
console.log("No connections configured.");
|
|
@@ -18184,7 +18328,7 @@ function listConnections(connections, format) {
|
|
|
18184
18328
|
function removeConnection(connections, name, save) {
|
|
18185
18329
|
const filtered = connections.filter((c) => c.name !== name);
|
|
18186
18330
|
if (filtered.length === connections.length) {
|
|
18187
|
-
console.error(
|
|
18331
|
+
console.error(chalk161.red(`Connection "${name}" not found.`));
|
|
18188
18332
|
process.exit(1);
|
|
18189
18333
|
}
|
|
18190
18334
|
save(filtered);
|
|
@@ -18230,15 +18374,15 @@ function saveConnections(connections) {
|
|
|
18230
18374
|
}
|
|
18231
18375
|
|
|
18232
18376
|
// src/commands/ravendb/promptConnection.ts
|
|
18233
|
-
import
|
|
18377
|
+
import chalk164 from "chalk";
|
|
18234
18378
|
|
|
18235
18379
|
// src/commands/ravendb/selectOpSecret.ts
|
|
18236
|
-
import
|
|
18380
|
+
import chalk163 from "chalk";
|
|
18237
18381
|
import Enquirer2 from "enquirer";
|
|
18238
18382
|
|
|
18239
18383
|
// src/commands/ravendb/searchItems.ts
|
|
18240
18384
|
import { execSync as execSync49 } from "child_process";
|
|
18241
|
-
import
|
|
18385
|
+
import chalk162 from "chalk";
|
|
18242
18386
|
function opExec(args) {
|
|
18243
18387
|
return execSync49(`op ${args}`, {
|
|
18244
18388
|
encoding: "utf8",
|
|
@@ -18251,7 +18395,7 @@ function searchItems(search2) {
|
|
|
18251
18395
|
items2 = JSON.parse(opExec("item list --format=json"));
|
|
18252
18396
|
} catch {
|
|
18253
18397
|
console.error(
|
|
18254
|
-
|
|
18398
|
+
chalk162.red(
|
|
18255
18399
|
"Failed to search 1Password. Ensure the CLI is installed and you are signed in."
|
|
18256
18400
|
)
|
|
18257
18401
|
);
|
|
@@ -18265,7 +18409,7 @@ function getItemFields(itemId2) {
|
|
|
18265
18409
|
const item = JSON.parse(opExec(`item get "${itemId2}" --format=json`));
|
|
18266
18410
|
return item.fields.filter((f) => f.reference && f.label);
|
|
18267
18411
|
} catch {
|
|
18268
|
-
console.error(
|
|
18412
|
+
console.error(chalk162.red("Failed to get item details from 1Password."));
|
|
18269
18413
|
process.exit(1);
|
|
18270
18414
|
}
|
|
18271
18415
|
}
|
|
@@ -18284,7 +18428,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
18284
18428
|
}).run();
|
|
18285
18429
|
const items2 = searchItems(search2);
|
|
18286
18430
|
if (items2.length === 0) {
|
|
18287
|
-
console.error(
|
|
18431
|
+
console.error(chalk163.red(`No items found matching "${search2}".`));
|
|
18288
18432
|
process.exit(1);
|
|
18289
18433
|
}
|
|
18290
18434
|
const itemId2 = await selectOne(
|
|
@@ -18293,7 +18437,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
18293
18437
|
);
|
|
18294
18438
|
const fields = getItemFields(itemId2);
|
|
18295
18439
|
if (fields.length === 0) {
|
|
18296
|
-
console.error(
|
|
18440
|
+
console.error(chalk163.red("No fields with references found on this item."));
|
|
18297
18441
|
process.exit(1);
|
|
18298
18442
|
}
|
|
18299
18443
|
const ref = await selectOne(
|
|
@@ -18307,7 +18451,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
18307
18451
|
async function promptConnection(existingNames) {
|
|
18308
18452
|
const name = await promptInput("name", "Connection name:");
|
|
18309
18453
|
if (existingNames.includes(name)) {
|
|
18310
|
-
console.error(
|
|
18454
|
+
console.error(chalk164.red(`Connection "${name}" already exists.`));
|
|
18311
18455
|
process.exit(1);
|
|
18312
18456
|
}
|
|
18313
18457
|
const url = await promptInput(
|
|
@@ -18316,22 +18460,22 @@ async function promptConnection(existingNames) {
|
|
|
18316
18460
|
);
|
|
18317
18461
|
const database = await promptInput("database", "Database name:");
|
|
18318
18462
|
if (!name || !url || !database) {
|
|
18319
|
-
console.error(
|
|
18463
|
+
console.error(chalk164.red("All fields are required."));
|
|
18320
18464
|
process.exit(1);
|
|
18321
18465
|
}
|
|
18322
18466
|
const apiKeyRef = await selectOpSecret();
|
|
18323
|
-
console.log(
|
|
18467
|
+
console.log(chalk164.dim(`Using: ${apiKeyRef}`));
|
|
18324
18468
|
return { name, url, database, apiKeyRef };
|
|
18325
18469
|
}
|
|
18326
18470
|
|
|
18327
18471
|
// src/commands/ravendb/ravendbSetConnection.ts
|
|
18328
|
-
import
|
|
18472
|
+
import chalk165 from "chalk";
|
|
18329
18473
|
function ravendbSetConnection(name) {
|
|
18330
18474
|
const raw = loadGlobalConfigRaw();
|
|
18331
18475
|
const ravendb = raw.ravendb ?? {};
|
|
18332
18476
|
const connections = ravendb.connections ?? [];
|
|
18333
18477
|
if (!connections.some((c) => c.name === name)) {
|
|
18334
|
-
console.error(
|
|
18478
|
+
console.error(chalk165.red(`Connection "${name}" not found.`));
|
|
18335
18479
|
console.error(
|
|
18336
18480
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
18337
18481
|
);
|
|
@@ -18347,16 +18491,16 @@ function ravendbSetConnection(name) {
|
|
|
18347
18491
|
var ravendbAuth = createConnectionAuth({
|
|
18348
18492
|
load: loadConnections,
|
|
18349
18493
|
save: saveConnections,
|
|
18350
|
-
format: (c) => `${
|
|
18494
|
+
format: (c) => `${chalk166.bold(c.name)} ${c.url} db=${c.database} key=${c.apiKeyRef}`,
|
|
18351
18495
|
promptNew: promptConnection,
|
|
18352
18496
|
onFirst: (c) => ravendbSetConnection(c.name)
|
|
18353
18497
|
});
|
|
18354
18498
|
|
|
18355
18499
|
// src/commands/ravendb/ravendbCollections.ts
|
|
18356
|
-
import
|
|
18500
|
+
import chalk170 from "chalk";
|
|
18357
18501
|
|
|
18358
18502
|
// src/commands/ravendb/ravenFetch.ts
|
|
18359
|
-
import
|
|
18503
|
+
import chalk168 from "chalk";
|
|
18360
18504
|
|
|
18361
18505
|
// src/commands/ravendb/getAccessToken.ts
|
|
18362
18506
|
var OAUTH_URL = "https://amazon-useast-1-oauth.ravenhq.com/ApiKeys/OAuth/AccessToken";
|
|
@@ -18393,10 +18537,10 @@ ${errorText}`
|
|
|
18393
18537
|
|
|
18394
18538
|
// src/commands/ravendb/resolveOpSecret.ts
|
|
18395
18539
|
import { execSync as execSync50 } from "child_process";
|
|
18396
|
-
import
|
|
18540
|
+
import chalk167 from "chalk";
|
|
18397
18541
|
function resolveOpSecret(reference) {
|
|
18398
18542
|
if (!reference.startsWith("op://")) {
|
|
18399
|
-
console.error(
|
|
18543
|
+
console.error(chalk167.red(`Invalid secret reference: must start with op://`));
|
|
18400
18544
|
process.exit(1);
|
|
18401
18545
|
}
|
|
18402
18546
|
try {
|
|
@@ -18406,7 +18550,7 @@ function resolveOpSecret(reference) {
|
|
|
18406
18550
|
}).trim();
|
|
18407
18551
|
} catch {
|
|
18408
18552
|
console.error(
|
|
18409
|
-
|
|
18553
|
+
chalk167.red(
|
|
18410
18554
|
"Failed to resolve secret reference. Ensure 1Password CLI is installed and you are signed in."
|
|
18411
18555
|
)
|
|
18412
18556
|
);
|
|
@@ -18415,10 +18559,10 @@ function resolveOpSecret(reference) {
|
|
|
18415
18559
|
}
|
|
18416
18560
|
|
|
18417
18561
|
// src/commands/ravendb/ravenFetch.ts
|
|
18418
|
-
async function ravenFetch(connection,
|
|
18562
|
+
async function ravenFetch(connection, path71) {
|
|
18419
18563
|
const apiKey = resolveOpSecret(connection.apiKeyRef);
|
|
18420
18564
|
let accessToken = await getAccessToken(apiKey);
|
|
18421
|
-
const url = `${connection.url}${
|
|
18565
|
+
const url = `${connection.url}${path71}`;
|
|
18422
18566
|
const headers = {
|
|
18423
18567
|
Authorization: `Bearer ${accessToken}`,
|
|
18424
18568
|
"Content-Type": "application/json"
|
|
@@ -18433,7 +18577,7 @@ async function ravenFetch(connection, path70) {
|
|
|
18433
18577
|
if (!response.ok) {
|
|
18434
18578
|
const body = await response.text();
|
|
18435
18579
|
console.error(
|
|
18436
|
-
|
|
18580
|
+
chalk168.red(`RavenDB error: ${response.status} ${response.statusText}`)
|
|
18437
18581
|
);
|
|
18438
18582
|
console.error(body.substring(0, 500));
|
|
18439
18583
|
process.exit(1);
|
|
@@ -18442,7 +18586,7 @@ async function ravenFetch(connection, path70) {
|
|
|
18442
18586
|
}
|
|
18443
18587
|
|
|
18444
18588
|
// src/commands/ravendb/resolveConnection.ts
|
|
18445
|
-
import
|
|
18589
|
+
import chalk169 from "chalk";
|
|
18446
18590
|
function loadRavendb() {
|
|
18447
18591
|
const raw = loadGlobalConfigRaw();
|
|
18448
18592
|
const ravendb = raw.ravendb;
|
|
@@ -18456,7 +18600,7 @@ function resolveConnection(name) {
|
|
|
18456
18600
|
const connectionName = name ?? defaultConnection;
|
|
18457
18601
|
if (!connectionName) {
|
|
18458
18602
|
console.error(
|
|
18459
|
-
|
|
18603
|
+
chalk169.red(
|
|
18460
18604
|
"No connection specified and no default set. Use assist ravendb set-connection <name> or pass a connection name."
|
|
18461
18605
|
)
|
|
18462
18606
|
);
|
|
@@ -18464,7 +18608,7 @@ function resolveConnection(name) {
|
|
|
18464
18608
|
}
|
|
18465
18609
|
const connection = connections.find((c) => c.name === connectionName);
|
|
18466
18610
|
if (!connection) {
|
|
18467
|
-
console.error(
|
|
18611
|
+
console.error(chalk169.red(`Connection "${connectionName}" not found.`));
|
|
18468
18612
|
console.error(
|
|
18469
18613
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
18470
18614
|
);
|
|
@@ -18495,7 +18639,7 @@ async function ravendbCollections(connectionName) {
|
|
|
18495
18639
|
return;
|
|
18496
18640
|
}
|
|
18497
18641
|
for (const c of collections) {
|
|
18498
|
-
console.log(`${
|
|
18642
|
+
console.log(`${chalk170.bold(c.Name)} ${c.CountOfDocuments} docs`);
|
|
18499
18643
|
}
|
|
18500
18644
|
}
|
|
18501
18645
|
|
|
@@ -18514,24 +18658,24 @@ var ravendbConfigHelp = [
|
|
|
18514
18658
|
];
|
|
18515
18659
|
|
|
18516
18660
|
// src/commands/ravendb/ravendbQuery.ts
|
|
18517
|
-
import
|
|
18661
|
+
import chalk172 from "chalk";
|
|
18518
18662
|
|
|
18519
18663
|
// src/commands/ravendb/fetchAllPages.ts
|
|
18520
|
-
import
|
|
18664
|
+
import chalk171 from "chalk";
|
|
18521
18665
|
|
|
18522
18666
|
// src/commands/ravendb/buildQueryPath.ts
|
|
18523
18667
|
function buildQueryPath(opts) {
|
|
18524
18668
|
const db = encodeURIComponent(opts.db);
|
|
18525
|
-
let
|
|
18669
|
+
let path71;
|
|
18526
18670
|
if (opts.collection) {
|
|
18527
|
-
|
|
18671
|
+
path71 = `/databases/${db}/indexes/dynamic/${encodeURIComponent(opts.collection)}?start=${opts.start}&pageSize=${opts.pageSize}&sort=${encodeURIComponent(opts.sort)}`;
|
|
18528
18672
|
} else {
|
|
18529
|
-
|
|
18673
|
+
path71 = `/databases/${db}/queries?start=${opts.start}&pageSize=${opts.pageSize}`;
|
|
18530
18674
|
}
|
|
18531
18675
|
if (opts.query) {
|
|
18532
|
-
|
|
18676
|
+
path71 += `&query=${encodeURIComponent(opts.query)}`;
|
|
18533
18677
|
}
|
|
18534
|
-
return
|
|
18678
|
+
return path71;
|
|
18535
18679
|
}
|
|
18536
18680
|
|
|
18537
18681
|
// src/commands/ravendb/fetchAllPages.ts
|
|
@@ -18540,7 +18684,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
18540
18684
|
let start3 = 0;
|
|
18541
18685
|
while (true) {
|
|
18542
18686
|
const effectivePageSize = opts.limit !== void 0 ? Math.min(opts.pageSize, opts.limit - allResults.length) : opts.pageSize;
|
|
18543
|
-
const
|
|
18687
|
+
const path71 = buildQueryPath({
|
|
18544
18688
|
db: connection.database,
|
|
18545
18689
|
collection: opts.collection,
|
|
18546
18690
|
start: start3,
|
|
@@ -18548,14 +18692,14 @@ async function fetchAllPages(connection, opts) {
|
|
|
18548
18692
|
sort: opts.sort,
|
|
18549
18693
|
query: opts.query
|
|
18550
18694
|
});
|
|
18551
|
-
const data = await ravenFetch(connection,
|
|
18695
|
+
const data = await ravenFetch(connection, path71);
|
|
18552
18696
|
const results = data.Results ?? [];
|
|
18553
18697
|
const totalResults = data.TotalResults ?? 0;
|
|
18554
18698
|
if (results.length === 0) break;
|
|
18555
18699
|
allResults.push(...results);
|
|
18556
18700
|
start3 += results.length;
|
|
18557
18701
|
process.stderr.write(
|
|
18558
|
-
`\r${
|
|
18702
|
+
`\r${chalk171.dim(`Fetched ${allResults.length}/${totalResults}`)}`
|
|
18559
18703
|
);
|
|
18560
18704
|
if (start3 >= totalResults) break;
|
|
18561
18705
|
if (opts.limit !== void 0 && allResults.length >= opts.limit) break;
|
|
@@ -18570,7 +18714,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
18570
18714
|
async function ravendbQuery(connectionName, collection, options2) {
|
|
18571
18715
|
const resolved = resolveArgs(connectionName, collection);
|
|
18572
18716
|
if (!resolved.collection && !options2.query) {
|
|
18573
|
-
console.error(
|
|
18717
|
+
console.error(chalk172.red("Provide a collection name or --query filter."));
|
|
18574
18718
|
process.exit(1);
|
|
18575
18719
|
}
|
|
18576
18720
|
const { collection: col } = resolved;
|
|
@@ -18609,7 +18753,7 @@ import { spawn as spawn5 } from "child_process";
|
|
|
18609
18753
|
import * as path36 from "path";
|
|
18610
18754
|
|
|
18611
18755
|
// src/commands/refactor/logViolations.ts
|
|
18612
|
-
import
|
|
18756
|
+
import chalk173 from "chalk";
|
|
18613
18757
|
var DEFAULT_MAX_LINES = 100;
|
|
18614
18758
|
function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
18615
18759
|
if (violations.length === 0) {
|
|
@@ -18618,43 +18762,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
|
18618
18762
|
}
|
|
18619
18763
|
return;
|
|
18620
18764
|
}
|
|
18621
|
-
console.error(
|
|
18765
|
+
console.error(chalk173.red(`
|
|
18622
18766
|
Refactor check failed:
|
|
18623
18767
|
`));
|
|
18624
|
-
console.error(
|
|
18768
|
+
console.error(chalk173.red(` The following files exceed ${maxLines} lines:
|
|
18625
18769
|
`));
|
|
18626
18770
|
for (const violation of violations) {
|
|
18627
|
-
console.error(
|
|
18771
|
+
console.error(chalk173.red(` ${violation.file} (${violation.lines} lines)`));
|
|
18628
18772
|
}
|
|
18629
18773
|
console.error(
|
|
18630
|
-
|
|
18774
|
+
chalk173.yellow(
|
|
18631
18775
|
`
|
|
18632
18776
|
Each file needs to be sensibly refactored, or if there is no sensible
|
|
18633
18777
|
way to refactor it, ignore it with:
|
|
18634
18778
|
`
|
|
18635
18779
|
)
|
|
18636
18780
|
);
|
|
18637
|
-
console.error(
|
|
18781
|
+
console.error(chalk173.gray(` assist refactor ignore <file>
|
|
18638
18782
|
`));
|
|
18639
18783
|
if (process.env.CLAUDECODE) {
|
|
18640
|
-
console.error(
|
|
18784
|
+
console.error(chalk173.cyan(`
|
|
18641
18785
|
## Extracting Code to New Files
|
|
18642
18786
|
`));
|
|
18643
18787
|
console.error(
|
|
18644
|
-
|
|
18788
|
+
chalk173.cyan(
|
|
18645
18789
|
` When extracting logic from one file to another, consider where the extracted code belongs:
|
|
18646
18790
|
`
|
|
18647
18791
|
)
|
|
18648
18792
|
);
|
|
18649
18793
|
console.error(
|
|
18650
|
-
|
|
18794
|
+
chalk173.cyan(
|
|
18651
18795
|
` 1. Keep related logic together: If the extracted code is tightly coupled to the
|
|
18652
18796
|
original file's domain, create a new folder containing both the original and extracted files.
|
|
18653
18797
|
`
|
|
18654
18798
|
)
|
|
18655
18799
|
);
|
|
18656
18800
|
console.error(
|
|
18657
|
-
|
|
18801
|
+
chalk173.cyan(
|
|
18658
18802
|
` 2. Share common utilities: If the extracted code can be reused across multiple
|
|
18659
18803
|
domains, move it to a common/shared folder.
|
|
18660
18804
|
`
|
|
@@ -18810,7 +18954,7 @@ async function check(pattern2, options2) {
|
|
|
18810
18954
|
|
|
18811
18955
|
// src/commands/refactor/extract/index.ts
|
|
18812
18956
|
import path44 from "path";
|
|
18813
|
-
import
|
|
18957
|
+
import chalk176 from "chalk";
|
|
18814
18958
|
|
|
18815
18959
|
// src/commands/refactor/extract/applyExtraction.ts
|
|
18816
18960
|
import { SyntaxKind as SyntaxKind4 } from "ts-morph";
|
|
@@ -19409,23 +19553,23 @@ function buildPlan2(functionName, sourceFile, sourcePath, destPath, project) {
|
|
|
19409
19553
|
|
|
19410
19554
|
// src/commands/refactor/extract/displayPlan.ts
|
|
19411
19555
|
import path40 from "path";
|
|
19412
|
-
import
|
|
19556
|
+
import chalk174 from "chalk";
|
|
19413
19557
|
function section2(title) {
|
|
19414
19558
|
return `
|
|
19415
|
-
${
|
|
19559
|
+
${chalk174.cyan(title)}`;
|
|
19416
19560
|
}
|
|
19417
19561
|
function displayImporters(plan2, cwd) {
|
|
19418
19562
|
if (plan2.importersToUpdate.length === 0) return;
|
|
19419
19563
|
console.log(section2("Update importers:"));
|
|
19420
19564
|
for (const imp of plan2.importersToUpdate) {
|
|
19421
19565
|
const rel = path40.relative(cwd, imp.file.getFilePath());
|
|
19422
|
-
console.log(` ${
|
|
19566
|
+
console.log(` ${chalk174.dim(rel)}: \u2192 import from "${imp.relPath}"`);
|
|
19423
19567
|
}
|
|
19424
19568
|
}
|
|
19425
19569
|
function displayPlan(functionName, relDest, plan2, cwd) {
|
|
19426
|
-
console.log(
|
|
19570
|
+
console.log(chalk174.bold(`Extract: ${functionName} \u2192 ${relDest}
|
|
19427
19571
|
`));
|
|
19428
|
-
console.log(` ${
|
|
19572
|
+
console.log(` ${chalk174.cyan("Functions to move:")}`);
|
|
19429
19573
|
for (const name of plan2.extractedNames) {
|
|
19430
19574
|
console.log(` ${name}`);
|
|
19431
19575
|
}
|
|
@@ -19459,7 +19603,7 @@ function displayPlan(functionName, relDest, plan2, cwd) {
|
|
|
19459
19603
|
|
|
19460
19604
|
// src/commands/refactor/extract/loadProjectFile.ts
|
|
19461
19605
|
import path43 from "path";
|
|
19462
|
-
import
|
|
19606
|
+
import chalk175 from "chalk";
|
|
19463
19607
|
import { Project as Project4 } from "ts-morph";
|
|
19464
19608
|
|
|
19465
19609
|
// src/commands/refactor/extract/findTsConfig.ts
|
|
@@ -19551,7 +19695,7 @@ function loadProjectFile(file) {
|
|
|
19551
19695
|
});
|
|
19552
19696
|
const sourceFile = project.getSourceFile(sourcePath);
|
|
19553
19697
|
if (!sourceFile) {
|
|
19554
|
-
console.log(
|
|
19698
|
+
console.log(chalk175.red(`File not found in project: ${file}`));
|
|
19555
19699
|
process.exit(1);
|
|
19556
19700
|
}
|
|
19557
19701
|
return { project, sourceFile };
|
|
@@ -19574,19 +19718,19 @@ async function extract(file, functionName, destination, options2 = {}) {
|
|
|
19574
19718
|
displayPlan(functionName, relDest, plan2, cwd);
|
|
19575
19719
|
if (options2.apply) {
|
|
19576
19720
|
await applyExtraction(functionName, sourceFile, destPath, plan2, project);
|
|
19577
|
-
console.log(
|
|
19721
|
+
console.log(chalk176.green("\nExtraction complete"));
|
|
19578
19722
|
} else {
|
|
19579
|
-
console.log(
|
|
19723
|
+
console.log(chalk176.dim("\nDry run. Use --apply to execute."));
|
|
19580
19724
|
}
|
|
19581
19725
|
}
|
|
19582
19726
|
|
|
19583
19727
|
// src/commands/refactor/ignore.ts
|
|
19584
19728
|
import fs28 from "fs";
|
|
19585
|
-
import
|
|
19729
|
+
import chalk177 from "chalk";
|
|
19586
19730
|
var REFACTOR_YML_PATH2 = "refactor.yml";
|
|
19587
19731
|
function ignore2(file) {
|
|
19588
19732
|
if (!fs28.existsSync(file)) {
|
|
19589
|
-
console.error(
|
|
19733
|
+
console.error(chalk177.red(`Error: File does not exist: ${file}`));
|
|
19590
19734
|
process.exit(1);
|
|
19591
19735
|
}
|
|
19592
19736
|
const content = fs28.readFileSync(file, "utf8");
|
|
@@ -19602,7 +19746,7 @@ function ignore2(file) {
|
|
|
19602
19746
|
fs28.writeFileSync(REFACTOR_YML_PATH2, entry);
|
|
19603
19747
|
}
|
|
19604
19748
|
console.log(
|
|
19605
|
-
|
|
19749
|
+
chalk177.green(
|
|
19606
19750
|
`Added ${file} to refactor ignore list (max ${maxLines} lines)`
|
|
19607
19751
|
)
|
|
19608
19752
|
);
|
|
@@ -19611,12 +19755,12 @@ function ignore2(file) {
|
|
|
19611
19755
|
// src/commands/refactor/rename/index.ts
|
|
19612
19756
|
import fs31 from "fs";
|
|
19613
19757
|
import path49 from "path";
|
|
19614
|
-
import
|
|
19758
|
+
import chalk180 from "chalk";
|
|
19615
19759
|
|
|
19616
19760
|
// src/commands/refactor/rename/applyRename.ts
|
|
19617
19761
|
import fs30 from "fs";
|
|
19618
19762
|
import path46 from "path";
|
|
19619
|
-
import
|
|
19763
|
+
import chalk178 from "chalk";
|
|
19620
19764
|
|
|
19621
19765
|
// src/commands/refactor/restructure/computeRewrites/index.ts
|
|
19622
19766
|
import path45 from "path";
|
|
@@ -19721,13 +19865,13 @@ function applyRename(rewrites, sourcePath, destPath, cwd) {
|
|
|
19721
19865
|
const updatedContents = applyRewrites(rewrites);
|
|
19722
19866
|
for (const [file, content] of updatedContents) {
|
|
19723
19867
|
fs30.writeFileSync(file, content, "utf8");
|
|
19724
|
-
console.log(
|
|
19868
|
+
console.log(chalk178.cyan(` Updated imports in ${path46.relative(cwd, file)}`));
|
|
19725
19869
|
}
|
|
19726
19870
|
const destDir = path46.dirname(destPath);
|
|
19727
19871
|
if (!fs30.existsSync(destDir)) fs30.mkdirSync(destDir, { recursive: true });
|
|
19728
19872
|
fs30.renameSync(sourcePath, destPath);
|
|
19729
19873
|
console.log(
|
|
19730
|
-
|
|
19874
|
+
chalk178.white(
|
|
19731
19875
|
` Moved ${path46.relative(cwd, sourcePath)} \u2192 ${path46.relative(cwd, destPath)}`
|
|
19732
19876
|
)
|
|
19733
19877
|
);
|
|
@@ -19814,16 +19958,16 @@ function computeRenameRewrites(sourcePath, destPath) {
|
|
|
19814
19958
|
|
|
19815
19959
|
// src/commands/refactor/rename/printRenamePreview.ts
|
|
19816
19960
|
import path48 from "path";
|
|
19817
|
-
import
|
|
19961
|
+
import chalk179 from "chalk";
|
|
19818
19962
|
function printRenamePreview(rewrites, cwd) {
|
|
19819
19963
|
for (const rewrite of rewrites) {
|
|
19820
19964
|
console.log(
|
|
19821
|
-
|
|
19965
|
+
chalk179.dim(
|
|
19822
19966
|
` ${path48.relative(cwd, rewrite.file)}: ${rewrite.oldSpecifier} \u2192 ${rewrite.newSpecifier}`
|
|
19823
19967
|
)
|
|
19824
19968
|
);
|
|
19825
19969
|
}
|
|
19826
|
-
console.log(
|
|
19970
|
+
console.log(chalk179.dim("Dry run. Use --apply to execute."));
|
|
19827
19971
|
}
|
|
19828
19972
|
|
|
19829
19973
|
// src/commands/refactor/rename/index.ts
|
|
@@ -19834,20 +19978,20 @@ async function rename(source, destination, options2 = {}) {
|
|
|
19834
19978
|
const relSource = path49.relative(cwd, sourcePath);
|
|
19835
19979
|
const relDest = path49.relative(cwd, destPath);
|
|
19836
19980
|
if (!fs31.existsSync(sourcePath)) {
|
|
19837
|
-
console.log(
|
|
19981
|
+
console.log(chalk180.red(`File not found: ${source}`));
|
|
19838
19982
|
process.exit(1);
|
|
19839
19983
|
}
|
|
19840
19984
|
if (destPath !== sourcePath && fs31.existsSync(destPath)) {
|
|
19841
|
-
console.log(
|
|
19985
|
+
console.log(chalk180.red(`Destination already exists: ${destination}`));
|
|
19842
19986
|
process.exit(1);
|
|
19843
19987
|
}
|
|
19844
|
-
console.log(
|
|
19845
|
-
console.log(
|
|
19846
|
-
console.log(
|
|
19988
|
+
console.log(chalk180.bold(`Rename: ${relSource} \u2192 ${relDest}`));
|
|
19989
|
+
console.log(chalk180.dim("Loading project..."));
|
|
19990
|
+
console.log(chalk180.dim("Scanning imports across the project..."));
|
|
19847
19991
|
const rewrites = computeRenameRewrites(sourcePath, destPath);
|
|
19848
19992
|
const affectedFiles = new Set(rewrites.map((r) => r.file)).size;
|
|
19849
19993
|
console.log(
|
|
19850
|
-
|
|
19994
|
+
chalk180.dim(
|
|
19851
19995
|
`${rewrites.length} import path(s) to update across ${affectedFiles} file(s)`
|
|
19852
19996
|
)
|
|
19853
19997
|
);
|
|
@@ -19856,11 +20000,11 @@ async function rename(source, destination, options2 = {}) {
|
|
|
19856
20000
|
return;
|
|
19857
20001
|
}
|
|
19858
20002
|
applyRename(rewrites, sourcePath, destPath, cwd);
|
|
19859
|
-
console.log(
|
|
20003
|
+
console.log(chalk180.green("Done"));
|
|
19860
20004
|
}
|
|
19861
20005
|
|
|
19862
20006
|
// src/commands/refactor/renameSymbol/index.ts
|
|
19863
|
-
import
|
|
20007
|
+
import chalk181 from "chalk";
|
|
19864
20008
|
|
|
19865
20009
|
// src/commands/refactor/renameSymbol/findSymbol.ts
|
|
19866
20010
|
import { SyntaxKind as SyntaxKind15 } from "ts-morph";
|
|
@@ -19906,33 +20050,33 @@ async function renameSymbol(file, oldName, newName, options2 = {}) {
|
|
|
19906
20050
|
const { project, sourceFile } = loadProjectFile(file);
|
|
19907
20051
|
const symbol = findSymbol(sourceFile, oldName);
|
|
19908
20052
|
if (!symbol) {
|
|
19909
|
-
console.log(
|
|
20053
|
+
console.log(chalk181.red(`Symbol "${oldName}" not found in ${file}`));
|
|
19910
20054
|
process.exit(1);
|
|
19911
20055
|
}
|
|
19912
20056
|
const grouped = groupReferences(symbol, cwd);
|
|
19913
20057
|
const totalRefs = [...grouped.values()].reduce((s, l) => s + l.length, 0);
|
|
19914
20058
|
console.log(
|
|
19915
|
-
|
|
20059
|
+
chalk181.bold(`Rename: ${oldName} \u2192 ${newName} (${totalRefs} references)
|
|
19916
20060
|
`)
|
|
19917
20061
|
);
|
|
19918
20062
|
for (const [refFile, lines] of grouped) {
|
|
19919
20063
|
console.log(
|
|
19920
|
-
` ${
|
|
20064
|
+
` ${chalk181.dim(refFile)}: lines ${chalk181.cyan(lines.join(", "))}`
|
|
19921
20065
|
);
|
|
19922
20066
|
}
|
|
19923
20067
|
if (options2.apply) {
|
|
19924
20068
|
symbol.rename(newName);
|
|
19925
20069
|
await project.save();
|
|
19926
|
-
console.log(
|
|
20070
|
+
console.log(chalk181.green(`
|
|
19927
20071
|
Renamed ${oldName} \u2192 ${newName}`));
|
|
19928
20072
|
} else {
|
|
19929
|
-
console.log(
|
|
20073
|
+
console.log(chalk181.dim("\nDry run. Use --apply to execute."));
|
|
19930
20074
|
}
|
|
19931
20075
|
}
|
|
19932
20076
|
|
|
19933
20077
|
// src/commands/refactor/restructure/index.ts
|
|
19934
20078
|
import path57 from "path";
|
|
19935
|
-
import
|
|
20079
|
+
import chalk184 from "chalk";
|
|
19936
20080
|
|
|
19937
20081
|
// src/commands/refactor/restructure/clusterDirectories.ts
|
|
19938
20082
|
import path51 from "path";
|
|
@@ -20011,50 +20155,50 @@ function clusterFiles(graph) {
|
|
|
20011
20155
|
|
|
20012
20156
|
// src/commands/refactor/restructure/displayPlan.ts
|
|
20013
20157
|
import path53 from "path";
|
|
20014
|
-
import
|
|
20158
|
+
import chalk182 from "chalk";
|
|
20015
20159
|
function relPath(filePath) {
|
|
20016
20160
|
return path53.relative(process.cwd(), filePath);
|
|
20017
20161
|
}
|
|
20018
20162
|
function displayMoves(plan2) {
|
|
20019
20163
|
if (plan2.moves.length === 0) return;
|
|
20020
|
-
console.log(
|
|
20164
|
+
console.log(chalk182.bold("\nFile moves:"));
|
|
20021
20165
|
for (const move2 of plan2.moves) {
|
|
20022
20166
|
console.log(
|
|
20023
|
-
` ${
|
|
20167
|
+
` ${chalk182.red(relPath(move2.from))} \u2192 ${chalk182.green(relPath(move2.to))}`
|
|
20024
20168
|
);
|
|
20025
|
-
console.log(
|
|
20169
|
+
console.log(chalk182.dim(` ${move2.reason}`));
|
|
20026
20170
|
}
|
|
20027
20171
|
}
|
|
20028
20172
|
function displayRewrites(rewrites) {
|
|
20029
20173
|
if (rewrites.length === 0) return;
|
|
20030
20174
|
const affectedFiles = new Set(rewrites.map((r) => r.file));
|
|
20031
|
-
console.log(
|
|
20175
|
+
console.log(chalk182.bold(`
|
|
20032
20176
|
Import rewrites (${affectedFiles.size} files):`));
|
|
20033
20177
|
for (const file of affectedFiles) {
|
|
20034
|
-
console.log(` ${
|
|
20178
|
+
console.log(` ${chalk182.cyan(relPath(file))}:`);
|
|
20035
20179
|
for (const { oldSpecifier, newSpecifier } of rewrites.filter(
|
|
20036
20180
|
(r) => r.file === file
|
|
20037
20181
|
)) {
|
|
20038
20182
|
console.log(
|
|
20039
|
-
` ${
|
|
20183
|
+
` ${chalk182.red(`"${oldSpecifier}"`)} \u2192 ${chalk182.green(`"${newSpecifier}"`)}`
|
|
20040
20184
|
);
|
|
20041
20185
|
}
|
|
20042
20186
|
}
|
|
20043
20187
|
}
|
|
20044
20188
|
function displayPlan2(plan2) {
|
|
20045
20189
|
if (plan2.warnings.length > 0) {
|
|
20046
|
-
console.log(
|
|
20047
|
-
for (const w of plan2.warnings) console.log(
|
|
20190
|
+
console.log(chalk182.yellow("\nWarnings:"));
|
|
20191
|
+
for (const w of plan2.warnings) console.log(chalk182.yellow(` ${w}`));
|
|
20048
20192
|
}
|
|
20049
20193
|
if (plan2.newDirectories.length > 0) {
|
|
20050
|
-
console.log(
|
|
20194
|
+
console.log(chalk182.bold("\nNew directories:"));
|
|
20051
20195
|
for (const dir of plan2.newDirectories)
|
|
20052
|
-
console.log(
|
|
20196
|
+
console.log(chalk182.green(` ${dir}/`));
|
|
20053
20197
|
}
|
|
20054
20198
|
displayMoves(plan2);
|
|
20055
20199
|
displayRewrites(plan2.rewrites);
|
|
20056
20200
|
console.log(
|
|
20057
|
-
|
|
20201
|
+
chalk182.dim(
|
|
20058
20202
|
`
|
|
20059
20203
|
Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports rewritten`
|
|
20060
20204
|
)
|
|
@@ -20064,18 +20208,18 @@ Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports r
|
|
|
20064
20208
|
// src/commands/refactor/restructure/executePlan.ts
|
|
20065
20209
|
import fs32 from "fs";
|
|
20066
20210
|
import path54 from "path";
|
|
20067
|
-
import
|
|
20211
|
+
import chalk183 from "chalk";
|
|
20068
20212
|
function executePlan(plan2) {
|
|
20069
20213
|
const updatedContents = applyRewrites(plan2.rewrites);
|
|
20070
20214
|
for (const [file, content] of updatedContents) {
|
|
20071
20215
|
fs32.writeFileSync(file, content, "utf8");
|
|
20072
20216
|
console.log(
|
|
20073
|
-
|
|
20217
|
+
chalk183.cyan(` Rewrote imports in ${path54.relative(process.cwd(), file)}`)
|
|
20074
20218
|
);
|
|
20075
20219
|
}
|
|
20076
20220
|
for (const dir of plan2.newDirectories) {
|
|
20077
20221
|
fs32.mkdirSync(dir, { recursive: true });
|
|
20078
|
-
console.log(
|
|
20222
|
+
console.log(chalk183.green(` Created ${path54.relative(process.cwd(), dir)}/`));
|
|
20079
20223
|
}
|
|
20080
20224
|
for (const move2 of plan2.moves) {
|
|
20081
20225
|
const targetDir = path54.dirname(move2.to);
|
|
@@ -20084,7 +20228,7 @@ function executePlan(plan2) {
|
|
|
20084
20228
|
}
|
|
20085
20229
|
fs32.renameSync(move2.from, move2.to);
|
|
20086
20230
|
console.log(
|
|
20087
|
-
|
|
20231
|
+
chalk183.white(
|
|
20088
20232
|
` Moved ${path54.relative(process.cwd(), move2.from)} \u2192 ${path54.relative(process.cwd(), move2.to)}`
|
|
20089
20233
|
)
|
|
20090
20234
|
);
|
|
@@ -20099,7 +20243,7 @@ function removeEmptyDirectories(dirs) {
|
|
|
20099
20243
|
if (entries.length === 0) {
|
|
20100
20244
|
fs32.rmdirSync(dir);
|
|
20101
20245
|
console.log(
|
|
20102
|
-
|
|
20246
|
+
chalk183.dim(
|
|
20103
20247
|
` Removed empty directory ${path54.relative(process.cwd(), dir)}`
|
|
20104
20248
|
)
|
|
20105
20249
|
);
|
|
@@ -20232,22 +20376,22 @@ async function restructure(pattern2, options2 = {}) {
|
|
|
20232
20376
|
const targetPattern = pattern2 ?? "src";
|
|
20233
20377
|
const files = findSourceFiles2(targetPattern);
|
|
20234
20378
|
if (files.length === 0) {
|
|
20235
|
-
console.log(
|
|
20379
|
+
console.log(chalk184.yellow("No files found matching pattern"));
|
|
20236
20380
|
return;
|
|
20237
20381
|
}
|
|
20238
20382
|
const tsConfigPath = findTsConfig(path57.resolve(files[0]));
|
|
20239
20383
|
const plan2 = buildPlan3(files, tsConfigPath);
|
|
20240
20384
|
if (plan2.moves.length === 0) {
|
|
20241
|
-
console.log(
|
|
20385
|
+
console.log(chalk184.green("No restructuring needed"));
|
|
20242
20386
|
return;
|
|
20243
20387
|
}
|
|
20244
20388
|
displayPlan2(plan2);
|
|
20245
20389
|
if (options2.apply) {
|
|
20246
|
-
console.log(
|
|
20390
|
+
console.log(chalk184.bold("\nApplying changes..."));
|
|
20247
20391
|
executePlan(plan2);
|
|
20248
|
-
console.log(
|
|
20392
|
+
console.log(chalk184.green("\nRestructuring complete"));
|
|
20249
20393
|
} else {
|
|
20250
|
-
console.log(
|
|
20394
|
+
console.log(chalk184.dim("\nDry run. Use --apply to execute."));
|
|
20251
20395
|
}
|
|
20252
20396
|
}
|
|
20253
20397
|
|
|
@@ -20830,18 +20974,18 @@ function partitionFindingsByDiff(findings, index3) {
|
|
|
20830
20974
|
}
|
|
20831
20975
|
|
|
20832
20976
|
// src/commands/review/warnOutOfDiff.ts
|
|
20833
|
-
import
|
|
20977
|
+
import chalk185 from "chalk";
|
|
20834
20978
|
function warnOutOfDiff(outOfDiff) {
|
|
20835
20979
|
if (outOfDiff.length === 0) return;
|
|
20836
20980
|
console.warn(
|
|
20837
|
-
|
|
20981
|
+
chalk185.yellow(
|
|
20838
20982
|
`Skipped ${outOfDiff.length} finding(s) whose lines fall outside the PR diff (GitHub would silently drop these):`
|
|
20839
20983
|
)
|
|
20840
20984
|
);
|
|
20841
20985
|
for (const finding of outOfDiff) {
|
|
20842
20986
|
const range = finding.startLine !== void 0 ? `${finding.startLine}-${finding.line}` : `${finding.line}`;
|
|
20843
20987
|
console.warn(
|
|
20844
|
-
` ${
|
|
20988
|
+
` ${chalk185.yellow("\xB7")} ${finding.title} ${chalk185.dim(
|
|
20845
20989
|
`(${finding.file}:${range})`
|
|
20846
20990
|
)}`
|
|
20847
20991
|
);
|
|
@@ -20860,18 +21004,18 @@ function selectInDiffFindings(lineBound, prDiff) {
|
|
|
20860
21004
|
}
|
|
20861
21005
|
|
|
20862
21006
|
// src/commands/review/warnUnlocated.ts
|
|
20863
|
-
import
|
|
21007
|
+
import chalk186 from "chalk";
|
|
20864
21008
|
function warnUnlocated(unlocated) {
|
|
20865
21009
|
if (unlocated.length === 0) return;
|
|
20866
21010
|
console.warn(
|
|
20867
|
-
|
|
21011
|
+
chalk186.yellow(
|
|
20868
21012
|
`Skipped ${unlocated.length} finding(s) without a parseable file:line:`
|
|
20869
21013
|
)
|
|
20870
21014
|
);
|
|
20871
21015
|
for (const finding of unlocated) {
|
|
20872
|
-
const where = finding.location ||
|
|
21016
|
+
const where = finding.location || chalk186.dim("missing");
|
|
20873
21017
|
console.warn(
|
|
20874
|
-
` ${
|
|
21018
|
+
` ${chalk186.yellow("\xB7")} ${finding.title} ${chalk186.dim(`(${where})`)}`
|
|
20875
21019
|
);
|
|
20876
21020
|
}
|
|
20877
21021
|
}
|
|
@@ -20968,8 +21112,8 @@ async function handlePostSynthesis(synthesisPath, options2) {
|
|
|
20968
21112
|
// src/commands/review/prepareReviewDir.ts
|
|
20969
21113
|
import { existsSync as existsSync45, mkdirSync as mkdirSync18, unlinkSync as unlinkSync16, writeFileSync as writeFileSync36 } from "fs";
|
|
20970
21114
|
function clearReviewFiles(paths) {
|
|
20971
|
-
for (const
|
|
20972
|
-
if (existsSync45(
|
|
21115
|
+
for (const path71 of [paths.claudePath, paths.codexPath, paths.synthesisPath]) {
|
|
21116
|
+
if (existsSync45(path71)) unlinkSync16(path71);
|
|
20973
21117
|
}
|
|
20974
21118
|
}
|
|
20975
21119
|
function prepareReviewDir(paths, requestBody, force) {
|
|
@@ -22043,7 +22187,7 @@ function registerReview(program2) {
|
|
|
22043
22187
|
}
|
|
22044
22188
|
|
|
22045
22189
|
// src/commands/seq/seqAuth.ts
|
|
22046
|
-
import
|
|
22190
|
+
import chalk188 from "chalk";
|
|
22047
22191
|
|
|
22048
22192
|
// src/commands/seq/loadConnections.ts
|
|
22049
22193
|
function loadConnections2() {
|
|
@@ -22072,10 +22216,10 @@ function setDefaultConnection(name) {
|
|
|
22072
22216
|
}
|
|
22073
22217
|
|
|
22074
22218
|
// src/shared/assertUniqueName.ts
|
|
22075
|
-
import
|
|
22219
|
+
import chalk187 from "chalk";
|
|
22076
22220
|
function assertUniqueName(existingNames, name) {
|
|
22077
22221
|
if (existingNames.includes(name)) {
|
|
22078
|
-
console.error(
|
|
22222
|
+
console.error(chalk187.red(`Connection "${name}" already exists.`));
|
|
22079
22223
|
process.exit(1);
|
|
22080
22224
|
}
|
|
22081
22225
|
}
|
|
@@ -22093,7 +22237,7 @@ async function promptConnection2(existingNames) {
|
|
|
22093
22237
|
var seqAuth = createConnectionAuth({
|
|
22094
22238
|
load: loadConnections2,
|
|
22095
22239
|
save: saveConnections2,
|
|
22096
|
-
format: (c) => `${
|
|
22240
|
+
format: (c) => `${chalk188.bold(c.name)} ${c.url}`,
|
|
22097
22241
|
promptNew: promptConnection2,
|
|
22098
22242
|
onFirst: (c) => setDefaultConnection(c.name)
|
|
22099
22243
|
});
|
|
@@ -22113,12 +22257,12 @@ var seqConfigHelp = [
|
|
|
22113
22257
|
];
|
|
22114
22258
|
|
|
22115
22259
|
// src/commands/seq/seqQuery.ts
|
|
22116
|
-
import
|
|
22260
|
+
import chalk192 from "chalk";
|
|
22117
22261
|
|
|
22118
22262
|
// src/commands/seq/fetchSeq.ts
|
|
22119
|
-
import
|
|
22120
|
-
async function fetchSeq(conn,
|
|
22121
|
-
const url = `${conn.url}${
|
|
22263
|
+
import chalk189 from "chalk";
|
|
22264
|
+
async function fetchSeq(conn, path71, params) {
|
|
22265
|
+
const url = `${conn.url}${path71}?${params}`;
|
|
22122
22266
|
const response = await fetch(url, {
|
|
22123
22267
|
headers: {
|
|
22124
22268
|
Accept: "application/json",
|
|
@@ -22127,7 +22271,7 @@ async function fetchSeq(conn, path70, params) {
|
|
|
22127
22271
|
});
|
|
22128
22272
|
if (!response.ok) {
|
|
22129
22273
|
const body = await response.text();
|
|
22130
|
-
console.error(
|
|
22274
|
+
console.error(chalk189.red(`Seq returned ${response.status}: ${body}`));
|
|
22131
22275
|
process.exit(1);
|
|
22132
22276
|
}
|
|
22133
22277
|
return response;
|
|
@@ -22186,23 +22330,23 @@ async function fetchSeqEvents(conn, params) {
|
|
|
22186
22330
|
}
|
|
22187
22331
|
|
|
22188
22332
|
// src/commands/seq/formatEvent.ts
|
|
22189
|
-
import
|
|
22333
|
+
import chalk190 from "chalk";
|
|
22190
22334
|
function levelColor(level) {
|
|
22191
22335
|
switch (level) {
|
|
22192
22336
|
case "Fatal":
|
|
22193
|
-
return
|
|
22337
|
+
return chalk190.bgRed.white;
|
|
22194
22338
|
case "Error":
|
|
22195
|
-
return
|
|
22339
|
+
return chalk190.red;
|
|
22196
22340
|
case "Warning":
|
|
22197
|
-
return
|
|
22341
|
+
return chalk190.yellow;
|
|
22198
22342
|
case "Information":
|
|
22199
|
-
return
|
|
22343
|
+
return chalk190.cyan;
|
|
22200
22344
|
case "Debug":
|
|
22201
|
-
return
|
|
22345
|
+
return chalk190.gray;
|
|
22202
22346
|
case "Verbose":
|
|
22203
|
-
return
|
|
22347
|
+
return chalk190.dim;
|
|
22204
22348
|
default:
|
|
22205
|
-
return
|
|
22349
|
+
return chalk190.white;
|
|
22206
22350
|
}
|
|
22207
22351
|
}
|
|
22208
22352
|
function levelAbbrev(level) {
|
|
@@ -22243,12 +22387,12 @@ function formatTimestamp(iso) {
|
|
|
22243
22387
|
function formatEvent(event) {
|
|
22244
22388
|
const color = levelColor(event.Level);
|
|
22245
22389
|
const abbrev = levelAbbrev(event.Level);
|
|
22246
|
-
const ts8 =
|
|
22390
|
+
const ts8 = chalk190.dim(formatTimestamp(event.Timestamp));
|
|
22247
22391
|
const msg = renderMessage(event);
|
|
22248
22392
|
const lines = [`${ts8} ${color(`[${abbrev}]`)} ${msg}`];
|
|
22249
22393
|
if (event.Exception) {
|
|
22250
22394
|
for (const line of event.Exception.split("\n")) {
|
|
22251
|
-
lines.push(
|
|
22395
|
+
lines.push(chalk190.red(` ${line}`));
|
|
22252
22396
|
}
|
|
22253
22397
|
}
|
|
22254
22398
|
return lines.join("\n");
|
|
@@ -22281,11 +22425,11 @@ function rejectTimestampFilter(filter) {
|
|
|
22281
22425
|
}
|
|
22282
22426
|
|
|
22283
22427
|
// src/shared/resolveNamedConnection.ts
|
|
22284
|
-
import
|
|
22428
|
+
import chalk191 from "chalk";
|
|
22285
22429
|
function resolveNamedConnection(connections, requested, defaultName, kind, authCommand) {
|
|
22286
22430
|
if (connections.length === 0) {
|
|
22287
22431
|
console.error(
|
|
22288
|
-
|
|
22432
|
+
chalk191.red(
|
|
22289
22433
|
`No ${kind} connections configured. Run '${authCommand}' first.`
|
|
22290
22434
|
)
|
|
22291
22435
|
);
|
|
@@ -22294,7 +22438,7 @@ function resolveNamedConnection(connections, requested, defaultName, kind, authC
|
|
|
22294
22438
|
const target = requested ?? defaultName ?? connections[0].name;
|
|
22295
22439
|
const connection = connections.find((c) => c.name === target);
|
|
22296
22440
|
if (!connection) {
|
|
22297
|
-
console.error(
|
|
22441
|
+
console.error(chalk191.red(`${kind} connection "${target}" not found.`));
|
|
22298
22442
|
process.exit(1);
|
|
22299
22443
|
}
|
|
22300
22444
|
return connection;
|
|
@@ -22323,7 +22467,7 @@ async function seqQuery(filter, options2) {
|
|
|
22323
22467
|
new URLSearchParams({ filter, count: String(count7) })
|
|
22324
22468
|
);
|
|
22325
22469
|
if (events.length === 0) {
|
|
22326
|
-
console.log(
|
|
22470
|
+
console.log(chalk192.yellow("No events found."));
|
|
22327
22471
|
return;
|
|
22328
22472
|
}
|
|
22329
22473
|
if (options2.json) {
|
|
@@ -22334,11 +22478,11 @@ async function seqQuery(filter, options2) {
|
|
|
22334
22478
|
for (const event of chronological) {
|
|
22335
22479
|
console.log(formatEvent(event));
|
|
22336
22480
|
}
|
|
22337
|
-
console.log(
|
|
22481
|
+
console.log(chalk192.dim(`
|
|
22338
22482
|
${events.length} events`));
|
|
22339
22483
|
if (events.length >= count7) {
|
|
22340
22484
|
console.log(
|
|
22341
|
-
|
|
22485
|
+
chalk192.yellow(
|
|
22342
22486
|
`Results limited to ${count7}. Use --count to retrieve more.`
|
|
22343
22487
|
)
|
|
22344
22488
|
);
|
|
@@ -22346,10 +22490,10 @@ ${events.length} events`));
|
|
|
22346
22490
|
}
|
|
22347
22491
|
|
|
22348
22492
|
// src/shared/setNamedDefaultConnection.ts
|
|
22349
|
-
import
|
|
22493
|
+
import chalk193 from "chalk";
|
|
22350
22494
|
function setNamedDefaultConnection(connections, name, setDefault, kind) {
|
|
22351
22495
|
if (!connections.find((c) => c.name === name)) {
|
|
22352
|
-
console.error(
|
|
22496
|
+
console.error(chalk193.red(`Connection "${name}" not found.`));
|
|
22353
22497
|
process.exit(1);
|
|
22354
22498
|
}
|
|
22355
22499
|
setDefault(name);
|
|
@@ -22398,7 +22542,7 @@ function registerSignal(program2) {
|
|
|
22398
22542
|
}
|
|
22399
22543
|
|
|
22400
22544
|
// src/commands/sql/sqlAuth.ts
|
|
22401
|
-
import
|
|
22545
|
+
import chalk195 from "chalk";
|
|
22402
22546
|
|
|
22403
22547
|
// src/commands/sql/loadConnections.ts
|
|
22404
22548
|
function loadConnections3() {
|
|
@@ -22427,7 +22571,7 @@ function setDefaultConnection2(name) {
|
|
|
22427
22571
|
}
|
|
22428
22572
|
|
|
22429
22573
|
// src/commands/sql/promptConnection.ts
|
|
22430
|
-
import
|
|
22574
|
+
import chalk194 from "chalk";
|
|
22431
22575
|
async function promptConnection3(existingNames) {
|
|
22432
22576
|
const name = await promptInput("name", "Connection name:", "default");
|
|
22433
22577
|
assertUniqueName(existingNames, name);
|
|
@@ -22435,7 +22579,7 @@ async function promptConnection3(existingNames) {
|
|
|
22435
22579
|
const portStr = await promptInput("port", "Port:", "1433");
|
|
22436
22580
|
const port = Number.parseInt(portStr, 10);
|
|
22437
22581
|
if (!Number.isFinite(port)) {
|
|
22438
|
-
console.error(
|
|
22582
|
+
console.error(chalk194.red(`Invalid port "${portStr}".`));
|
|
22439
22583
|
process.exit(1);
|
|
22440
22584
|
}
|
|
22441
22585
|
const user = await promptInput("user", "User:");
|
|
@@ -22448,13 +22592,13 @@ async function promptConnection3(existingNames) {
|
|
|
22448
22592
|
var sqlAuth = createConnectionAuth({
|
|
22449
22593
|
load: loadConnections3,
|
|
22450
22594
|
save: saveConnections3,
|
|
22451
|
-
format: (c) => `${
|
|
22595
|
+
format: (c) => `${chalk195.bold(c.name)} ${c.server}:${c.port}/${c.database} (${c.user})`,
|
|
22452
22596
|
promptNew: promptConnection3,
|
|
22453
22597
|
onFirst: (c) => setDefaultConnection2(c.name)
|
|
22454
22598
|
});
|
|
22455
22599
|
|
|
22456
22600
|
// src/commands/sql/printTable.ts
|
|
22457
|
-
import
|
|
22601
|
+
import chalk196 from "chalk";
|
|
22458
22602
|
function formatCell(value) {
|
|
22459
22603
|
if (value === null || value === void 0) return "";
|
|
22460
22604
|
if (value instanceof Date) return value.toISOString();
|
|
@@ -22463,7 +22607,7 @@ function formatCell(value) {
|
|
|
22463
22607
|
}
|
|
22464
22608
|
function printTable(rows) {
|
|
22465
22609
|
if (rows.length === 0) {
|
|
22466
|
-
console.log(
|
|
22610
|
+
console.log(chalk196.yellow("(no rows)"));
|
|
22467
22611
|
return;
|
|
22468
22612
|
}
|
|
22469
22613
|
const columns = Object.keys(rows[0]);
|
|
@@ -22471,13 +22615,13 @@ function printTable(rows) {
|
|
|
22471
22615
|
(col) => Math.max(col.length, ...rows.map((r) => formatCell(r[col]).length))
|
|
22472
22616
|
);
|
|
22473
22617
|
const header = columns.map((c, i) => c.padEnd(widths[i])).join(" ");
|
|
22474
|
-
console.log(
|
|
22475
|
-
console.log(
|
|
22618
|
+
console.log(chalk196.dim(header));
|
|
22619
|
+
console.log(chalk196.dim("-".repeat(header.length)));
|
|
22476
22620
|
for (const row of rows) {
|
|
22477
22621
|
const line = columns.map((c, i) => formatCell(row[c]).padEnd(widths[i])).join(" ");
|
|
22478
22622
|
console.log(line);
|
|
22479
22623
|
}
|
|
22480
|
-
console.log(
|
|
22624
|
+
console.log(chalk196.dim(`
|
|
22481
22625
|
${rows.length} row${rows.length === 1 ? "" : "s"}`));
|
|
22482
22626
|
}
|
|
22483
22627
|
|
|
@@ -22551,7 +22695,7 @@ var sqlConfigHelp = [
|
|
|
22551
22695
|
];
|
|
22552
22696
|
|
|
22553
22697
|
// src/commands/sql/sqlMutate.ts
|
|
22554
|
-
import
|
|
22698
|
+
import chalk197 from "chalk";
|
|
22555
22699
|
|
|
22556
22700
|
// src/commands/sql/isMutation.ts
|
|
22557
22701
|
var MUTATION_KEYWORDS = [
|
|
@@ -22585,7 +22729,7 @@ function isMutation(sql25) {
|
|
|
22585
22729
|
async function sqlMutate(query, connectionName) {
|
|
22586
22730
|
if (!isMutation(query)) {
|
|
22587
22731
|
console.error(
|
|
22588
|
-
|
|
22732
|
+
chalk197.red(
|
|
22589
22733
|
"assist sql mutate refuses non-mutating statements. Use `assist sql query` instead."
|
|
22590
22734
|
)
|
|
22591
22735
|
);
|
|
@@ -22595,18 +22739,18 @@ async function sqlMutate(query, connectionName) {
|
|
|
22595
22739
|
const pool = await sqlConnect(conn);
|
|
22596
22740
|
try {
|
|
22597
22741
|
const result = await pool.request().query(query);
|
|
22598
|
-
console.log(
|
|
22742
|
+
console.log(chalk197.dim(`${result.rowsAffected.join(", ")} row(s) affected`));
|
|
22599
22743
|
} finally {
|
|
22600
22744
|
await pool.close();
|
|
22601
22745
|
}
|
|
22602
22746
|
}
|
|
22603
22747
|
|
|
22604
22748
|
// src/commands/sql/sqlQuery.ts
|
|
22605
|
-
import
|
|
22749
|
+
import chalk198 from "chalk";
|
|
22606
22750
|
async function sqlQuery(query, connectionName) {
|
|
22607
22751
|
if (isMutation(query)) {
|
|
22608
22752
|
console.error(
|
|
22609
|
-
|
|
22753
|
+
chalk198.red(
|
|
22610
22754
|
"assist sql query refuses mutating statements. Use `assist sql mutate` instead."
|
|
22611
22755
|
)
|
|
22612
22756
|
);
|
|
@@ -22621,7 +22765,7 @@ async function sqlQuery(query, connectionName) {
|
|
|
22621
22765
|
printTable(rows);
|
|
22622
22766
|
} else {
|
|
22623
22767
|
console.log(
|
|
22624
|
-
|
|
22768
|
+
chalk198.dim(`${result.rowsAffected.join(", ")} row(s) affected`)
|
|
22625
22769
|
);
|
|
22626
22770
|
}
|
|
22627
22771
|
} finally {
|
|
@@ -23436,7 +23580,7 @@ function registerVoice(program2) {
|
|
|
23436
23580
|
|
|
23437
23581
|
// src/commands/roam/auth.ts
|
|
23438
23582
|
import { randomBytes } from "crypto";
|
|
23439
|
-
import
|
|
23583
|
+
import chalk199 from "chalk";
|
|
23440
23584
|
|
|
23441
23585
|
// src/commands/roam/waitForCallback.ts
|
|
23442
23586
|
import { createServer as createServer3 } from "http";
|
|
@@ -23567,13 +23711,13 @@ async function auth() {
|
|
|
23567
23711
|
saveGlobalConfig(config);
|
|
23568
23712
|
const state = randomBytes(16).toString("hex");
|
|
23569
23713
|
console.log(
|
|
23570
|
-
|
|
23714
|
+
chalk199.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
|
|
23571
23715
|
);
|
|
23572
|
-
console.log(
|
|
23573
|
-
console.log(
|
|
23574
|
-
console.log(
|
|
23716
|
+
console.log(chalk199.white("http://localhost:14523/callback\n"));
|
|
23717
|
+
console.log(chalk199.blue("Opening browser for authorization..."));
|
|
23718
|
+
console.log(chalk199.dim("Waiting for authorization callback..."));
|
|
23575
23719
|
const { code, redirectUri } = await authorizeInBrowser(clientId, state);
|
|
23576
|
-
console.log(
|
|
23720
|
+
console.log(chalk199.dim("Exchanging code for tokens..."));
|
|
23577
23721
|
const tokens = await exchangeToken({
|
|
23578
23722
|
code,
|
|
23579
23723
|
clientId,
|
|
@@ -23589,7 +23733,7 @@ async function auth() {
|
|
|
23589
23733
|
};
|
|
23590
23734
|
saveGlobalConfig(config);
|
|
23591
23735
|
console.log(
|
|
23592
|
-
|
|
23736
|
+
chalk199.green("Roam credentials and tokens saved to ~/.assist.yml")
|
|
23593
23737
|
);
|
|
23594
23738
|
}
|
|
23595
23739
|
|
|
@@ -23605,9 +23749,9 @@ function findPortFile(roamDir) {
|
|
|
23605
23749
|
return void 0;
|
|
23606
23750
|
}
|
|
23607
23751
|
const candidates = entries.filter((name) => /^roam-local-api(-[^.]+)?\.port$/.test(name)).map((name) => {
|
|
23608
|
-
const
|
|
23752
|
+
const path71 = join62(roamDir, name);
|
|
23609
23753
|
try {
|
|
23610
|
-
return { path:
|
|
23754
|
+
return { path: path71, mtimeMs: statSync8(path71).mtimeMs };
|
|
23611
23755
|
} catch {
|
|
23612
23756
|
return void 0;
|
|
23613
23757
|
}
|
|
@@ -24026,11 +24170,11 @@ function findLinkIndex() {
|
|
|
24026
24170
|
function parseLinkArgs() {
|
|
24027
24171
|
const idx = findLinkIndex();
|
|
24028
24172
|
if (idx === -1) return null;
|
|
24029
|
-
const
|
|
24173
|
+
const path71 = process.argv[idx + 1];
|
|
24030
24174
|
const rest = process.argv.slice(idx + 2);
|
|
24031
24175
|
const { value: prefix2 } = extractOption(rest, "--prefix");
|
|
24032
24176
|
if (!prefix2) return null;
|
|
24033
|
-
return { path:
|
|
24177
|
+
return { path: path71, prefix: prefix2 };
|
|
24034
24178
|
}
|
|
24035
24179
|
function hasDuplicateLink(runList, linkPath) {
|
|
24036
24180
|
return runList.some(
|
|
@@ -24132,7 +24276,7 @@ import { execSync as execSync58 } from "child_process";
|
|
|
24132
24276
|
import { existsSync as existsSync56, mkdirSync as mkdirSync24, unlinkSync as unlinkSync21, writeFileSync as writeFileSync42 } from "fs";
|
|
24133
24277
|
import { tmpdir as tmpdir7 } from "os";
|
|
24134
24278
|
import { join as join66, resolve as resolve16 } from "path";
|
|
24135
|
-
import
|
|
24279
|
+
import chalk200 from "chalk";
|
|
24136
24280
|
|
|
24137
24281
|
// src/commands/screenshot/captureWindowPs1.ts
|
|
24138
24282
|
var captureWindowPs1 = `
|
|
@@ -24283,13 +24427,13 @@ function screenshot(processName) {
|
|
|
24283
24427
|
const config = loadConfig();
|
|
24284
24428
|
const outputDir = resolve16(config.screenshot.outputDir);
|
|
24285
24429
|
const outputPath = buildOutputPath(outputDir, processName);
|
|
24286
|
-
console.log(
|
|
24430
|
+
console.log(chalk200.gray(`Capturing window for process "${processName}" ...`));
|
|
24287
24431
|
try {
|
|
24288
24432
|
runPowerShellScript(processName, outputPath);
|
|
24289
|
-
console.log(
|
|
24433
|
+
console.log(chalk200.green(`Screenshot saved: ${outputPath}`));
|
|
24290
24434
|
} catch (error) {
|
|
24291
24435
|
const msg = error instanceof Error ? error.message : String(error);
|
|
24292
|
-
console.error(
|
|
24436
|
+
console.error(chalk200.red(`Failed to capture screenshot: ${msg}`));
|
|
24293
24437
|
process.exit(1);
|
|
24294
24438
|
}
|
|
24295
24439
|
}
|
|
@@ -24911,6 +25055,7 @@ function dismissSession(sessions, id) {
|
|
|
24911
25055
|
if (!s) return false;
|
|
24912
25056
|
if (s.status !== "done") s.pty?.kill();
|
|
24913
25057
|
s.activityWatcher?.close();
|
|
25058
|
+
s.transcriptWatcher?.close();
|
|
24914
25059
|
removeActivity(s.id);
|
|
24915
25060
|
if (s.activity?.itemId != null) releaseLock(s.activity.itemId);
|
|
24916
25061
|
sessions.delete(id);
|
|
@@ -25017,113 +25162,18 @@ function logSpawnedSession(session) {
|
|
|
25017
25162
|
);
|
|
25018
25163
|
}
|
|
25019
25164
|
|
|
25020
|
-
// src/commands/sessions/daemon/
|
|
25021
|
-
function
|
|
25022
|
-
const
|
|
25023
|
-
if (session
|
|
25024
|
-
session.runningMs += now - session.runningSince;
|
|
25025
|
-
}
|
|
25026
|
-
session.runningSince = newStatus === "running" ? now : null;
|
|
25027
|
-
session.status = newStatus;
|
|
25028
|
-
}
|
|
25029
|
-
|
|
25030
|
-
// src/commands/sessions/daemon/shouldAutoDismiss.ts
|
|
25031
|
-
function shouldAutoDismiss(session, exitCode) {
|
|
25032
|
-
if (session.status !== "done" || exitCode !== 0) {
|
|
25033
|
-
return false;
|
|
25034
|
-
}
|
|
25035
|
-
if (session.reviewStarted) {
|
|
25036
|
-
return session.autoAdvance === true;
|
|
25037
|
-
}
|
|
25038
|
-
const args = session.assistArgs;
|
|
25039
|
-
if (args === void 0) return false;
|
|
25040
|
-
if (args[0] === "update") return true;
|
|
25041
|
-
return args.includes("--once") && args[0] !== "next";
|
|
25042
|
-
}
|
|
25043
|
-
|
|
25044
|
-
// src/commands/sessions/daemon/shouldAutoRun.ts
|
|
25045
|
-
function shouldAutoRun(session) {
|
|
25046
|
-
if (!session.autoRun) return { run: false, reason: null };
|
|
25047
|
-
if (session.status !== "done")
|
|
25048
|
-
return {
|
|
25049
|
-
run: false,
|
|
25050
|
-
reason: `session status is "${session.status}", not "done"`
|
|
25051
|
-
};
|
|
25052
|
-
if (session.commandType !== "assist")
|
|
25053
|
-
return {
|
|
25054
|
-
run: false,
|
|
25055
|
-
reason: `command type is "${session.commandType}", not "assist"`
|
|
25056
|
-
};
|
|
25057
|
-
const cmd = session.assistArgs?.[0];
|
|
25058
|
-
if (cmd !== "draft" && cmd !== "bug" && cmd !== "refine")
|
|
25059
|
-
return {
|
|
25060
|
-
run: false,
|
|
25061
|
-
reason: `command "${cmd ?? "(none)"}" is not draft/bug/refine`
|
|
25062
|
-
};
|
|
25063
|
-
const itemId2 = session.activity?.itemId;
|
|
25064
|
-
if (itemId2 == null)
|
|
25065
|
-
return {
|
|
25066
|
-
run: false,
|
|
25067
|
-
reason: "no itemId in activity (draft did not create an item)"
|
|
25068
|
-
};
|
|
25069
|
-
return { run: true, itemId: itemId2 };
|
|
25070
|
-
}
|
|
25071
|
-
|
|
25072
|
-
// src/commands/sessions/daemon/watchEscInterrupt.ts
|
|
25073
|
-
var ESC3 = "\x1B";
|
|
25074
|
-
var SETTLE_MS = 1e3;
|
|
25075
|
-
function isInterruptKey(data) {
|
|
25076
|
-
return data === ESC3;
|
|
25077
|
-
}
|
|
25078
|
-
function scheduleSettle(session, onStatusChange) {
|
|
25079
|
-
if (session.escInterruptTimer) clearTimeout(session.escInterruptTimer);
|
|
25080
|
-
session.escInterruptTimer = setTimeout(() => {
|
|
25081
|
-
session.escInterruptTimer = void 0;
|
|
25082
|
-
if (session.status !== "running") return;
|
|
25083
|
-
daemonLog(`session ${session.id} esc-interrupt settled -> waiting`);
|
|
25084
|
-
onStatusChange(session, "waiting");
|
|
25085
|
-
}, SETTLE_MS);
|
|
25086
|
-
}
|
|
25087
|
-
function watchEscInterrupt(session, data, onStatusChange) {
|
|
25088
|
-
if (session.status !== "running") return;
|
|
25089
|
-
if (!isInterruptKey(data)) return;
|
|
25090
|
-
scheduleSettle(session, onStatusChange);
|
|
25091
|
-
}
|
|
25092
|
-
function noteOutputForEscInterrupt(session, onStatusChange) {
|
|
25093
|
-
if (!session.escInterruptTimer) return;
|
|
25094
|
-
scheduleSettle(session, onStatusChange);
|
|
25095
|
-
}
|
|
25096
|
-
function disarmEscInterrupt(session) {
|
|
25097
|
-
if (!session.escInterruptTimer) return;
|
|
25098
|
-
clearTimeout(session.escInterruptTimer);
|
|
25099
|
-
session.escInterruptTimer = void 0;
|
|
25100
|
-
}
|
|
25101
|
-
|
|
25102
|
-
// src/commands/sessions/daemon/applyStatusChange.ts
|
|
25103
|
-
function applyStatusChange(session, status3, exitCode, dismiss, notify2, reuseForRun) {
|
|
25104
|
-
disarmEscInterrupt(session);
|
|
25105
|
-
if (session.status === status3) return;
|
|
25106
|
-
daemonLog(`session ${session.id} status: ${session.status} -> ${status3}`);
|
|
25107
|
-
void flushPhaseActiveMs(session);
|
|
25108
|
-
setStatus2(session, status3);
|
|
25109
|
-
const autoRun = shouldAutoRun(session);
|
|
25110
|
-
if (autoRun.run) {
|
|
25111
|
-
reuseForRun(session, autoRun.itemId);
|
|
25112
|
-
notify2();
|
|
25113
|
-
return;
|
|
25114
|
-
}
|
|
25115
|
-
if (status3 === "done" && autoRun.reason != null) {
|
|
25165
|
+
// src/commands/sessions/daemon/applySetStatus.ts
|
|
25166
|
+
function applySetStatus(sessions, id, status3, source, onStatusChange) {
|
|
25167
|
+
const session = sessions.get(id);
|
|
25168
|
+
if (!session) {
|
|
25116
25169
|
daemonLog(
|
|
25117
|
-
`session
|
|
25170
|
+
`set-status for unknown session id=${id} status=${status3} (no live session; ignoring)`
|
|
25118
25171
|
);
|
|
25172
|
+
return;
|
|
25119
25173
|
}
|
|
25120
|
-
if (
|
|
25121
|
-
|
|
25122
|
-
|
|
25123
|
-
|
|
25124
|
-
// src/commands/sessions/daemon/makeStatusChangeHandler.ts
|
|
25125
|
-
function makeStatusChangeHandler(dismiss, notify2, reuseForRun) {
|
|
25126
|
-
return (s, status3, exitCode) => applyStatusChange(s, status3, exitCode, dismiss, notify2, reuseForRun);
|
|
25174
|
+
if (source === "permission") session.permissionActive = true;
|
|
25175
|
+
if (status3 === "running") session.permissionActive = false;
|
|
25176
|
+
onStatusChange(session, status3);
|
|
25127
25177
|
}
|
|
25128
25178
|
|
|
25129
25179
|
// src/shared/db/recordPhaseCycleContext.ts
|
|
@@ -25282,12 +25332,102 @@ function recordSessionUsage(sessions, claudeSessionId, transcriptPath, usedPct,
|
|
|
25282
25332
|
return false;
|
|
25283
25333
|
}
|
|
25284
25334
|
|
|
25335
|
+
// src/commands/sessions/daemon/applyUsageRecord.ts
|
|
25336
|
+
function applyUsageRecord(sessions, windows, notify2, claudeSessionId, transcriptPath, usedPct) {
|
|
25337
|
+
if (recordSessionUsage(
|
|
25338
|
+
sessions,
|
|
25339
|
+
claudeSessionId,
|
|
25340
|
+
transcriptPath,
|
|
25341
|
+
usedPct,
|
|
25342
|
+
windows
|
|
25343
|
+
))
|
|
25344
|
+
notify2();
|
|
25345
|
+
}
|
|
25346
|
+
|
|
25347
|
+
// src/commands/sessions/daemon/setStatus.ts
|
|
25348
|
+
function setStatus2(session, newStatus) {
|
|
25349
|
+
const now = Date.now();
|
|
25350
|
+
if (session.status === "running" && session.runningSince != null) {
|
|
25351
|
+
session.runningMs += now - session.runningSince;
|
|
25352
|
+
}
|
|
25353
|
+
session.runningSince = newStatus === "running" ? now : null;
|
|
25354
|
+
session.status = newStatus;
|
|
25355
|
+
}
|
|
25356
|
+
|
|
25357
|
+
// src/commands/sessions/daemon/shouldAutoDismiss.ts
|
|
25358
|
+
function shouldAutoDismiss(session, exitCode) {
|
|
25359
|
+
if (session.status !== "done" || exitCode !== 0) {
|
|
25360
|
+
return false;
|
|
25361
|
+
}
|
|
25362
|
+
if (session.reviewStarted) {
|
|
25363
|
+
return session.autoAdvance === true;
|
|
25364
|
+
}
|
|
25365
|
+
const args = session.assistArgs;
|
|
25366
|
+
if (args === void 0) return false;
|
|
25367
|
+
if (args[0] === "update") return true;
|
|
25368
|
+
return args.includes("--once") && args[0] !== "next";
|
|
25369
|
+
}
|
|
25370
|
+
|
|
25371
|
+
// src/commands/sessions/daemon/shouldAutoRun.ts
|
|
25372
|
+
function shouldAutoRun(session) {
|
|
25373
|
+
if (!session.autoRun) return { run: false, reason: null };
|
|
25374
|
+
if (session.status !== "done")
|
|
25375
|
+
return {
|
|
25376
|
+
run: false,
|
|
25377
|
+
reason: `session status is "${session.status}", not "done"`
|
|
25378
|
+
};
|
|
25379
|
+
if (session.commandType !== "assist")
|
|
25380
|
+
return {
|
|
25381
|
+
run: false,
|
|
25382
|
+
reason: `command type is "${session.commandType}", not "assist"`
|
|
25383
|
+
};
|
|
25384
|
+
const cmd = session.assistArgs?.[0];
|
|
25385
|
+
if (cmd !== "draft" && cmd !== "bug" && cmd !== "refine")
|
|
25386
|
+
return {
|
|
25387
|
+
run: false,
|
|
25388
|
+
reason: `command "${cmd ?? "(none)"}" is not draft/bug/refine`
|
|
25389
|
+
};
|
|
25390
|
+
const itemId2 = session.activity?.itemId;
|
|
25391
|
+
if (itemId2 == null)
|
|
25392
|
+
return {
|
|
25393
|
+
run: false,
|
|
25394
|
+
reason: "no itemId in activity (draft did not create an item)"
|
|
25395
|
+
};
|
|
25396
|
+
return { run: true, itemId: itemId2 };
|
|
25397
|
+
}
|
|
25398
|
+
|
|
25399
|
+
// src/commands/sessions/daemon/applyStatusChange.ts
|
|
25400
|
+
function applyStatusChange(session, status3, exitCode, dismiss, notify2, reuseForRun) {
|
|
25401
|
+
if (session.status === status3) return;
|
|
25402
|
+
daemonLog(`session ${session.id} status: ${session.status} -> ${status3}`);
|
|
25403
|
+
void flushPhaseActiveMs(session);
|
|
25404
|
+
setStatus2(session, status3);
|
|
25405
|
+
const autoRun = shouldAutoRun(session);
|
|
25406
|
+
if (autoRun.run) {
|
|
25407
|
+
reuseForRun(session, autoRun.itemId);
|
|
25408
|
+
notify2();
|
|
25409
|
+
return;
|
|
25410
|
+
}
|
|
25411
|
+
if (status3 === "done" && autoRun.reason != null) {
|
|
25412
|
+
daemonLog(
|
|
25413
|
+
`session ${session.id} auto-run enabled but skipped (exit ${exitCode ?? "none"}): ${autoRun.reason}`
|
|
25414
|
+
);
|
|
25415
|
+
}
|
|
25416
|
+
if (shouldAutoDismiss(session, exitCode)) dismiss(session.id);
|
|
25417
|
+
else notify2();
|
|
25418
|
+
}
|
|
25419
|
+
|
|
25420
|
+
// src/commands/sessions/daemon/makeStatusChangeHandler.ts
|
|
25421
|
+
function makeStatusChangeHandler(dismiss, notify2, reuseForRun) {
|
|
25422
|
+
return (s, status3, exitCode) => applyStatusChange(s, status3, exitCode, dismiss, notify2, reuseForRun);
|
|
25423
|
+
}
|
|
25424
|
+
|
|
25285
25425
|
// src/commands/sessions/daemon/errorTail.ts
|
|
25286
|
-
var
|
|
25426
|
+
var ESC3 = String.fromCharCode(27);
|
|
25287
25427
|
var CSI = String.fromCharCode(155);
|
|
25288
25428
|
var BEL = String.fromCharCode(7);
|
|
25289
25429
|
var ANSI = new RegExp(
|
|
25290
|
-
String.raw`[${
|
|
25430
|
+
String.raw`[${ESC3}${CSI}][[\]()#;?]*(?:(?:[a-zA-Z\d]*(?:;[a-zA-Z\d]*)*)?${BEL}|(?:\d{1,4}(?:;\d{0,4})*)?[\dA-PR-TZcf-ntqry=><~])`,
|
|
25291
25431
|
"g"
|
|
25292
25432
|
);
|
|
25293
25433
|
var MAX_TAIL_LINES = 40;
|
|
@@ -25355,10 +25495,10 @@ async function seedRunningMsFromUsage(session, notify2) {
|
|
|
25355
25495
|
|
|
25356
25496
|
// src/commands/sessions/daemon/watchActivity.ts
|
|
25357
25497
|
var DEBOUNCE_MS = 50;
|
|
25358
|
-
function watchActivity(session, notify2) {
|
|
25498
|
+
function watchActivity(session, notify2, onClaudeSessionId) {
|
|
25359
25499
|
if (session.commandType !== "assist" || !session.cwd) return;
|
|
25360
|
-
const
|
|
25361
|
-
const dir = dirname29(
|
|
25500
|
+
const path71 = activityPath(session.id);
|
|
25501
|
+
const dir = dirname29(path71);
|
|
25362
25502
|
try {
|
|
25363
25503
|
mkdirSync25(dir, { recursive: true });
|
|
25364
25504
|
} catch {
|
|
@@ -25368,21 +25508,23 @@ function watchActivity(session, notify2) {
|
|
|
25368
25508
|
let timer = null;
|
|
25369
25509
|
const read = () => {
|
|
25370
25510
|
timer = null;
|
|
25371
|
-
const activity2 = readActivity(
|
|
25511
|
+
const activity2 = readActivity(path71);
|
|
25372
25512
|
if (!activity2) return;
|
|
25373
25513
|
session.activity = activity2;
|
|
25374
|
-
if (activity2.claudeSessionId)
|
|
25514
|
+
if (activity2.claudeSessionId) {
|
|
25375
25515
|
session.claudeSessionId = activity2.claudeSessionId;
|
|
25516
|
+
onClaudeSessionId?.(session);
|
|
25517
|
+
}
|
|
25376
25518
|
applyReviewPause(session, activity2);
|
|
25377
25519
|
void seedRunningMsFromUsage(session, notify2);
|
|
25378
25520
|
notify2();
|
|
25379
25521
|
};
|
|
25380
25522
|
session.activityWatcher = watch(dir, (_event, filename) => {
|
|
25381
|
-
if (filename && !
|
|
25523
|
+
if (filename && !path71.endsWith(filename)) return;
|
|
25382
25524
|
if (timer) clearTimeout(timer);
|
|
25383
25525
|
timer = setTimeout(read, DEBOUNCE_MS);
|
|
25384
25526
|
});
|
|
25385
|
-
if (existsSync58(
|
|
25527
|
+
if (existsSync58(path71)) read();
|
|
25386
25528
|
}
|
|
25387
25529
|
function refreshActivity(session) {
|
|
25388
25530
|
if (session.commandType !== "assist" || !session.cwd) return;
|
|
@@ -25445,7 +25587,6 @@ function wirePtyEvents(session, clients, onStatusChange) {
|
|
|
25445
25587
|
if (!session.pty) return;
|
|
25446
25588
|
session.pty.onData((data) => {
|
|
25447
25589
|
appendScrollback(session, data);
|
|
25448
|
-
noteOutputForEscInterrupt(session, onStatusChange);
|
|
25449
25590
|
broadcast(clients, { type: "output", sessionId: session.id, data });
|
|
25450
25591
|
});
|
|
25451
25592
|
session.pty.onExit(
|
|
@@ -25613,6 +25754,222 @@ function errorSession(id, persisted, error) {
|
|
|
25613
25754
|
};
|
|
25614
25755
|
}
|
|
25615
25756
|
|
|
25757
|
+
// src/commands/sessions/shared/normalizeUser.ts
|
|
25758
|
+
var INTERRUPT_PREFIX = "[Request interrupted";
|
|
25759
|
+
function normalizeUser(entry) {
|
|
25760
|
+
const content = asRecord(entry.message)?.content;
|
|
25761
|
+
if (typeof content === "string")
|
|
25762
|
+
return isInterruptText(content) ? { kind: "interrupt" } : { kind: "user" };
|
|
25763
|
+
if (!Array.isArray(content)) return { kind: "user" };
|
|
25764
|
+
const toolResultIds = [];
|
|
25765
|
+
let hasInterrupt = false;
|
|
25766
|
+
let hasNonToolResult = false;
|
|
25767
|
+
for (const block of content) {
|
|
25768
|
+
const b = asRecord(block);
|
|
25769
|
+
if (!b) continue;
|
|
25770
|
+
if (b.type === "tool_result") {
|
|
25771
|
+
if (typeof b.tool_use_id === "string") toolResultIds.push(b.tool_use_id);
|
|
25772
|
+
} else if (b.type === "text" && isInterruptText(b.text)) {
|
|
25773
|
+
hasInterrupt = true;
|
|
25774
|
+
} else {
|
|
25775
|
+
hasNonToolResult = true;
|
|
25776
|
+
}
|
|
25777
|
+
}
|
|
25778
|
+
if (hasInterrupt) return { kind: "interrupt" };
|
|
25779
|
+
if (hasNonToolResult) return { kind: "user" };
|
|
25780
|
+
return { kind: "toolResult", ids: toolResultIds };
|
|
25781
|
+
}
|
|
25782
|
+
function asRecord(value) {
|
|
25783
|
+
return value && typeof value === "object" ? value : null;
|
|
25784
|
+
}
|
|
25785
|
+
function isInterruptText(value) {
|
|
25786
|
+
return typeof value === "string" && value.startsWith(INTERRUPT_PREFIX);
|
|
25787
|
+
}
|
|
25788
|
+
|
|
25789
|
+
// src/commands/sessions/shared/normalizeTranscriptEvents.ts
|
|
25790
|
+
function normalizeTranscriptEvents(entries) {
|
|
25791
|
+
return entries.map(normalizeEntry).filter((event) => event !== null);
|
|
25792
|
+
}
|
|
25793
|
+
function normalizeEntry(entry) {
|
|
25794
|
+
if (entry.isSidechain || entry.isMeta) return null;
|
|
25795
|
+
if (entry.type === "assistant") return normalizeAssistant(entry);
|
|
25796
|
+
if (entry.type === "user") return normalizeUser(entry);
|
|
25797
|
+
return null;
|
|
25798
|
+
}
|
|
25799
|
+
function normalizeAssistant(entry) {
|
|
25800
|
+
const message = asRecord2(entry.message);
|
|
25801
|
+
const stopReason = typeof message?.stop_reason === "string" ? message.stop_reason : null;
|
|
25802
|
+
const content = message?.content;
|
|
25803
|
+
const toolUses = [];
|
|
25804
|
+
if (Array.isArray(content))
|
|
25805
|
+
for (const block of content) {
|
|
25806
|
+
const b = asRecord2(block);
|
|
25807
|
+
if (b?.type === "tool_use")
|
|
25808
|
+
toolUses.push({
|
|
25809
|
+
id: typeof b.id === "string" ? b.id : "",
|
|
25810
|
+
name: typeof b.name === "string" ? b.name : ""
|
|
25811
|
+
});
|
|
25812
|
+
}
|
|
25813
|
+
return { kind: "assistant", stopReason, toolUses };
|
|
25814
|
+
}
|
|
25815
|
+
function asRecord2(value) {
|
|
25816
|
+
return value && typeof value === "object" ? value : null;
|
|
25817
|
+
}
|
|
25818
|
+
|
|
25819
|
+
// src/commands/sessions/shared/deriveTranscriptStatus.ts
|
|
25820
|
+
var ASK_USER_QUESTION2 = "AskUserQuestion";
|
|
25821
|
+
var TURN_END_STOP_REASONS = /* @__PURE__ */ new Set(["end_turn", "stop_sequence"]);
|
|
25822
|
+
function deriveTranscriptStatus(entries, opts = {}) {
|
|
25823
|
+
const events = normalizeTranscriptEvents(entries);
|
|
25824
|
+
const lastIdx = lastDecisiveIndex(events);
|
|
25825
|
+
if (lastIdx === -1) return null;
|
|
25826
|
+
const ev = events[lastIdx];
|
|
25827
|
+
if (ev.kind === "interrupt") return "waiting";
|
|
25828
|
+
if (ev.kind === "user") return "running";
|
|
25829
|
+
if (ev.kind === "toolResult") return null;
|
|
25830
|
+
if (ev.stopReason != null && TURN_END_STOP_REASONS.has(ev.stopReason))
|
|
25831
|
+
return "waiting";
|
|
25832
|
+
const resolved = resolvedToolUseIds(events, lastIdx);
|
|
25833
|
+
const pending = ev.toolUses.filter((tool) => !resolved.has(tool.id));
|
|
25834
|
+
if (pending.length === 0) return "running";
|
|
25835
|
+
if (pending.some((tool) => tool.name === ASK_USER_QUESTION2))
|
|
25836
|
+
return "waiting";
|
|
25837
|
+
if (opts.permissionActive) return "waiting";
|
|
25838
|
+
return "running";
|
|
25839
|
+
}
|
|
25840
|
+
function lastDecisiveIndex(events) {
|
|
25841
|
+
for (let i = events.length - 1; i >= 0; i--)
|
|
25842
|
+
if (events[i].kind !== "toolResult") return i;
|
|
25843
|
+
return -1;
|
|
25844
|
+
}
|
|
25845
|
+
function resolvedToolUseIds(events, afterIdx) {
|
|
25846
|
+
const ids = /* @__PURE__ */ new Set();
|
|
25847
|
+
for (let i = afterIdx + 1; i < events.length; i++) {
|
|
25848
|
+
const event = events[i];
|
|
25849
|
+
if (event.kind === "toolResult") for (const id of event.ids) ids.add(id);
|
|
25850
|
+
}
|
|
25851
|
+
return ids;
|
|
25852
|
+
}
|
|
25853
|
+
|
|
25854
|
+
// src/commands/sessions/shared/readTranscriptTail.ts
|
|
25855
|
+
import * as fs37 from "fs";
|
|
25856
|
+
var DEFAULT_MAX_BYTES = 256 * 1024;
|
|
25857
|
+
function parseTailEntries(raw) {
|
|
25858
|
+
const entries = [];
|
|
25859
|
+
for (const line of raw.split("\n")) {
|
|
25860
|
+
const trimmed = line.trim();
|
|
25861
|
+
if (!trimmed) continue;
|
|
25862
|
+
try {
|
|
25863
|
+
const parsed = JSON.parse(trimmed);
|
|
25864
|
+
if (parsed && typeof parsed === "object")
|
|
25865
|
+
entries.push(parsed);
|
|
25866
|
+
} catch {
|
|
25867
|
+
}
|
|
25868
|
+
}
|
|
25869
|
+
return entries;
|
|
25870
|
+
}
|
|
25871
|
+
function dropPartialFirstLine(raw, sliced) {
|
|
25872
|
+
if (!sliced) return raw;
|
|
25873
|
+
const newline = raw.indexOf("\n");
|
|
25874
|
+
return newline === -1 ? "" : raw.slice(newline + 1);
|
|
25875
|
+
}
|
|
25876
|
+
async function readTranscriptTail(filePath, maxBytes = DEFAULT_MAX_BYTES) {
|
|
25877
|
+
let handle;
|
|
25878
|
+
try {
|
|
25879
|
+
handle = await fs37.promises.open(filePath, "r");
|
|
25880
|
+
const { size } = await handle.stat();
|
|
25881
|
+
const start3 = Math.max(0, size - maxBytes);
|
|
25882
|
+
const length = size - start3;
|
|
25883
|
+
if (length === 0) return [];
|
|
25884
|
+
const buf = Buffer.alloc(length);
|
|
25885
|
+
await handle.read(buf, 0, length, start3);
|
|
25886
|
+
return parseTailEntries(
|
|
25887
|
+
dropPartialFirstLine(buf.toString("utf8"), start3 > 0)
|
|
25888
|
+
);
|
|
25889
|
+
} catch {
|
|
25890
|
+
return [];
|
|
25891
|
+
} finally {
|
|
25892
|
+
await handle?.close();
|
|
25893
|
+
}
|
|
25894
|
+
}
|
|
25895
|
+
function readTranscriptTailSync(filePath, maxBytes = DEFAULT_MAX_BYTES) {
|
|
25896
|
+
let fd;
|
|
25897
|
+
try {
|
|
25898
|
+
fd = fs37.openSync(filePath, "r");
|
|
25899
|
+
const { size } = fs37.fstatSync(fd);
|
|
25900
|
+
const start3 = Math.max(0, size - maxBytes);
|
|
25901
|
+
const length = size - start3;
|
|
25902
|
+
if (length === 0) return [];
|
|
25903
|
+
const buf = Buffer.alloc(length);
|
|
25904
|
+
fs37.readSync(fd, buf, 0, length, start3);
|
|
25905
|
+
return parseTailEntries(
|
|
25906
|
+
dropPartialFirstLine(buf.toString("utf8"), start3 > 0)
|
|
25907
|
+
);
|
|
25908
|
+
} catch {
|
|
25909
|
+
return [];
|
|
25910
|
+
} finally {
|
|
25911
|
+
if (fd !== void 0) fs37.closeSync(fd);
|
|
25912
|
+
}
|
|
25913
|
+
}
|
|
25914
|
+
|
|
25915
|
+
// src/commands/sessions/shared/findTranscriptPathSync.ts
|
|
25916
|
+
import * as fs38 from "fs";
|
|
25917
|
+
import * as os4 from "os";
|
|
25918
|
+
import * as path60 from "path";
|
|
25919
|
+
function projectDirForCwd(cwd) {
|
|
25920
|
+
return path60.join(
|
|
25921
|
+
os4.homedir(),
|
|
25922
|
+
".claude",
|
|
25923
|
+
"projects",
|
|
25924
|
+
cwd.replace(/[^a-zA-Z0-9]/g, "-")
|
|
25925
|
+
);
|
|
25926
|
+
}
|
|
25927
|
+
function transcriptPathFor(cwd, claudeSessionId) {
|
|
25928
|
+
return path60.join(projectDirForCwd(cwd), `${claudeSessionId}.jsonl`);
|
|
25929
|
+
}
|
|
25930
|
+
function findTranscriptPathSync(cwd, claudeSessionId) {
|
|
25931
|
+
const direct = transcriptPathFor(cwd, claudeSessionId);
|
|
25932
|
+
if (fs38.existsSync(direct)) return direct;
|
|
25933
|
+
const dir = projectDirForCwd(cwd);
|
|
25934
|
+
let files;
|
|
25935
|
+
try {
|
|
25936
|
+
files = fs38.readdirSync(dir);
|
|
25937
|
+
} catch {
|
|
25938
|
+
return null;
|
|
25939
|
+
}
|
|
25940
|
+
for (const file of files) {
|
|
25941
|
+
if (!file.endsWith(".jsonl")) continue;
|
|
25942
|
+
if (headContainsSessionId(path60.join(dir, file), claudeSessionId))
|
|
25943
|
+
return path60.join(dir, file);
|
|
25944
|
+
}
|
|
25945
|
+
return null;
|
|
25946
|
+
}
|
|
25947
|
+
function headContainsSessionId(filePath, claudeSessionId) {
|
|
25948
|
+
let fd;
|
|
25949
|
+
try {
|
|
25950
|
+
fd = fs38.openSync(filePath, "r");
|
|
25951
|
+
const buf = Buffer.alloc(16384);
|
|
25952
|
+
const bytesRead = fs38.readSync(fd, buf, 0, buf.length, 0);
|
|
25953
|
+
return buf.toString("utf8", 0, bytesRead).includes(claudeSessionId);
|
|
25954
|
+
} catch {
|
|
25955
|
+
return false;
|
|
25956
|
+
} finally {
|
|
25957
|
+
if (fd !== void 0) fs38.closeSync(fd);
|
|
25958
|
+
}
|
|
25959
|
+
}
|
|
25960
|
+
|
|
25961
|
+
// src/commands/sessions/daemon/deriveRestoreStatus.ts
|
|
25962
|
+
function deriveRestoreStatus(persisted) {
|
|
25963
|
+
if (!persisted.claudeSessionId) return "waiting";
|
|
25964
|
+
const filePath = findTranscriptPathSync(
|
|
25965
|
+
persisted.cwd,
|
|
25966
|
+
persisted.claudeSessionId
|
|
25967
|
+
);
|
|
25968
|
+
if (!filePath) return "waiting";
|
|
25969
|
+
const entries = readTranscriptTailSync(filePath);
|
|
25970
|
+
return deriveTranscriptStatus(entries) === "running" ? "running" : "waiting";
|
|
25971
|
+
}
|
|
25972
|
+
|
|
25616
25973
|
// src/commands/sessions/daemon/runningSession.ts
|
|
25617
25974
|
function runningSession(base, persisted, pty2) {
|
|
25618
25975
|
return restoredSession(base, persisted, pty2, "running");
|
|
@@ -25636,17 +25993,16 @@ function restoredSession(base, persisted, pty2, status3) {
|
|
|
25636
25993
|
}
|
|
25637
25994
|
|
|
25638
25995
|
// src/commands/sessions/daemon/restoreInteractiveSession.ts
|
|
25639
|
-
function restoreInteractiveSession(id, persisted, base) {
|
|
25996
|
+
function restoreInteractiveSession(id, persisted, base, idle) {
|
|
25640
25997
|
if (persisted.commandType !== "run" && persisted.claudeSessionId) {
|
|
25641
|
-
return resumeViaClaude(id, persisted, base);
|
|
25998
|
+
return resumeViaClaude(id, persisted, base, idle);
|
|
25642
25999
|
}
|
|
25643
26000
|
if (persisted.commandType === "claude") {
|
|
25644
26001
|
return unrecoverableClaude(id, persisted);
|
|
25645
26002
|
}
|
|
25646
26003
|
return notRestoredStub(base, persisted);
|
|
25647
26004
|
}
|
|
25648
|
-
function resumeViaClaude(id, persisted, base) {
|
|
25649
|
-
const idle = persisted.status !== "running";
|
|
26005
|
+
function resumeViaClaude(id, persisted, base, idle) {
|
|
25650
26006
|
const pty2 = spawnClaude2({
|
|
25651
26007
|
resumeSessionId: persisted.claudeSessionId,
|
|
25652
26008
|
prompt: idle ? void 0 : buildResumePrompt(),
|
|
@@ -25695,8 +26051,8 @@ function isUpdate(persisted) {
|
|
|
25695
26051
|
function restoreSession(id, persisted) {
|
|
25696
26052
|
const base = restoreBase(id, persisted);
|
|
25697
26053
|
if (isUpdate(persisted)) return updatedSession(id, persisted);
|
|
26054
|
+
const idle = deriveRestoreStatus(persisted) !== "running";
|
|
25698
26055
|
if (needsWrapperRelaunch(persisted)) {
|
|
25699
|
-
const idle = persisted.status !== "running";
|
|
25700
26056
|
const pty2 = spawnPty(
|
|
25701
26057
|
assistResumeArgs(persisted),
|
|
25702
26058
|
persisted.cwd,
|
|
@@ -25705,7 +26061,7 @@ function restoreSession(id, persisted) {
|
|
|
25705
26061
|
);
|
|
25706
26062
|
return idle ? waitingSession(base, persisted, pty2) : runningSession(base, persisted, pty2);
|
|
25707
26063
|
}
|
|
25708
|
-
return restoreInteractiveSession(id, persisted, base);
|
|
26064
|
+
return restoreInteractiveSession(id, persisted, base, idle);
|
|
25709
26065
|
}
|
|
25710
26066
|
function needsWrapperRelaunch(persisted) {
|
|
25711
26067
|
return isBacklogRun(persisted) || isOnceLaunch(persisted) && !!persisted.claudeSessionId;
|
|
@@ -25846,6 +26202,77 @@ function shutdownSessions(sessions) {
|
|
|
25846
26202
|
}
|
|
25847
26203
|
}
|
|
25848
26204
|
|
|
26205
|
+
// src/commands/sessions/daemon/watchTranscript.ts
|
|
26206
|
+
import { existsSync as existsSync60, watch as watch2 } from "fs";
|
|
26207
|
+
|
|
26208
|
+
// src/commands/sessions/daemon/reconcileTranscriptStatus.ts
|
|
26209
|
+
async function resolveTranscriptPath(session) {
|
|
26210
|
+
if (session.transcriptPath) return session.transcriptPath;
|
|
26211
|
+
if (!session.claudeSessionId) return null;
|
|
26212
|
+
const direct = session.cwd ? findTranscriptPathSync(session.cwd, session.claudeSessionId) : null;
|
|
26213
|
+
const filePath = direct ?? await findSessionJsonlPath(session.claudeSessionId);
|
|
26214
|
+
if (filePath) session.transcriptPath = filePath;
|
|
26215
|
+
return filePath;
|
|
26216
|
+
}
|
|
26217
|
+
async function reconcileTranscriptStatus(session, onStatusChange) {
|
|
26218
|
+
if (session.status === "done" || session.status === "error") return;
|
|
26219
|
+
const filePath = await resolveTranscriptPath(session);
|
|
26220
|
+
if (!filePath) return;
|
|
26221
|
+
const entries = await readTranscriptTail(filePath);
|
|
26222
|
+
const derived = deriveTranscriptStatus(entries, {
|
|
26223
|
+
permissionActive: session.permissionActive
|
|
26224
|
+
});
|
|
26225
|
+
if (!derived) return;
|
|
26226
|
+
if (derived === "running") session.permissionActive = false;
|
|
26227
|
+
if (derived === session.status) return;
|
|
26228
|
+
daemonLog(
|
|
26229
|
+
`session ${session.id} transcript reconcile: ${session.status} -> ${derived}`
|
|
26230
|
+
);
|
|
26231
|
+
onStatusChange(session, derived);
|
|
26232
|
+
}
|
|
26233
|
+
|
|
26234
|
+
// src/commands/sessions/daemon/watchTranscript.ts
|
|
26235
|
+
var DEBOUNCE_MS2 = 100;
|
|
26236
|
+
function watchTranscript(session, onStatusChange) {
|
|
26237
|
+
if (!session.cwd || !session.claudeSessionId) return;
|
|
26238
|
+
if (session.watchedTranscriptId === session.claudeSessionId) return;
|
|
26239
|
+
const dir = projectDirForCwd(session.cwd);
|
|
26240
|
+
if (!existsSync60(dir)) return;
|
|
26241
|
+
if (session.transcriptWatcher) {
|
|
26242
|
+
session.transcriptWatcher.close();
|
|
26243
|
+
session.transcriptWatcher = void 0;
|
|
26244
|
+
}
|
|
26245
|
+
session.transcriptPath = void 0;
|
|
26246
|
+
const fileName = `${session.claudeSessionId}.jsonl`;
|
|
26247
|
+
let timer = null;
|
|
26248
|
+
const run4 = () => {
|
|
26249
|
+
timer = null;
|
|
26250
|
+
void reconcileTranscriptStatus(session, onStatusChange);
|
|
26251
|
+
};
|
|
26252
|
+
try {
|
|
26253
|
+
session.transcriptWatcher = watch2(dir, (_event, changed) => {
|
|
26254
|
+
if (changed && changed !== fileName) return;
|
|
26255
|
+
if (timer) clearTimeout(timer);
|
|
26256
|
+
timer = setTimeout(run4, DEBOUNCE_MS2);
|
|
26257
|
+
});
|
|
26258
|
+
} catch (error) {
|
|
26259
|
+
daemonLog(
|
|
26260
|
+
`session ${session.id} transcript watch failed: ${error instanceof Error ? error.message : String(error)}`
|
|
26261
|
+
);
|
|
26262
|
+
return;
|
|
26263
|
+
}
|
|
26264
|
+
session.watchedTranscriptId = session.claudeSessionId;
|
|
26265
|
+
daemonLog(`session ${session.id} watching transcript ${fileName}`);
|
|
26266
|
+
run4();
|
|
26267
|
+
}
|
|
26268
|
+
|
|
26269
|
+
// src/commands/sessions/daemon/wireSessionWatchers.ts
|
|
26270
|
+
function wireSessionWatchers(session, notify2, onStatusChange) {
|
|
26271
|
+
const wireTranscript = (s) => watchTranscript(s, onStatusChange);
|
|
26272
|
+
watchActivity(session, notify2, wireTranscript);
|
|
26273
|
+
wireTranscript(session);
|
|
26274
|
+
}
|
|
26275
|
+
|
|
25849
26276
|
// src/commands/sessions/daemon/connectToWindowsDaemon.ts
|
|
25850
26277
|
import * as net2 from "net";
|
|
25851
26278
|
|
|
@@ -25961,13 +26388,13 @@ async function defaultConnect() {
|
|
|
25961
26388
|
}
|
|
25962
26389
|
|
|
25963
26390
|
// src/commands/sessions/daemon/hasPersistedWindowsSessions.ts
|
|
25964
|
-
import { existsSync as
|
|
26391
|
+
import { existsSync as existsSync61, readFileSync as readFileSync49 } from "fs";
|
|
25965
26392
|
import { posix } from "path";
|
|
25966
26393
|
function hasPersistedWindowsSessions() {
|
|
25967
26394
|
const sessionsFile = windowsSessionsFileFromWsl();
|
|
25968
26395
|
if (!sessionsFile) return false;
|
|
25969
26396
|
try {
|
|
25970
|
-
if (!
|
|
26397
|
+
if (!existsSync61(sessionsFile)) return false;
|
|
25971
26398
|
const data = JSON.parse(readFileSync49(sessionsFile, "utf8"));
|
|
25972
26399
|
return Array.isArray(data) && data.length > 0;
|
|
25973
26400
|
} catch (error) {
|
|
@@ -26528,7 +26955,6 @@ function writeToSession(sessions, id, data, onStatusChange) {
|
|
|
26528
26955
|
const s = sessions.get(id);
|
|
26529
26956
|
if (!s || s.status === "done") return;
|
|
26530
26957
|
s.pty?.write(data);
|
|
26531
|
-
watchEscInterrupt(s, data, onStatusChange);
|
|
26532
26958
|
watchPromptSubmit(s, data, onStatusChange);
|
|
26533
26959
|
}
|
|
26534
26960
|
function resizeSession(sessions, id, cols, rows) {
|
|
@@ -26608,7 +27034,7 @@ var SessionManager = class {
|
|
|
26608
27034
|
drain = () => drainSessions(this.sessions, this.notify);
|
|
26609
27035
|
add(session) {
|
|
26610
27036
|
this.wire(session);
|
|
26611
|
-
|
|
27037
|
+
wireSessionWatchers(session, this.notify, this.onStatusChange);
|
|
26612
27038
|
logSpawnedSession(session);
|
|
26613
27039
|
return session.id;
|
|
26614
27040
|
}
|
|
@@ -26671,27 +27097,20 @@ var SessionManager = class {
|
|
|
26671
27097
|
setStarred(id, starred) {
|
|
26672
27098
|
if (setStarred2(this.sessions, id, starred)) this.notify();
|
|
26673
27099
|
}
|
|
26674
|
-
setStatus(id, status3) {
|
|
26675
|
-
|
|
26676
|
-
if (!session) {
|
|
26677
|
-
daemonLog(
|
|
26678
|
-
`set-status for unknown session id=${id} status=${status3} (no live session; ignoring)`
|
|
26679
|
-
);
|
|
26680
|
-
return;
|
|
26681
|
-
}
|
|
26682
|
-
this.onStatusChange(session, status3);
|
|
27100
|
+
setStatus(id, status3, source) {
|
|
27101
|
+
applySetStatus(this.sessions, id, status3, source, this.onStatusChange);
|
|
26683
27102
|
}
|
|
26684
27103
|
/* why: the status line relays token totals keyed by Claude's session id; join
|
|
26685
27104
|
* it to the running backlog phase so the spend accumulates against that row. */
|
|
26686
27105
|
recordUsage(claudeSessionId, transcriptPath, usedPct) {
|
|
26687
|
-
|
|
27106
|
+
applyUsageRecord(
|
|
26688
27107
|
this.sessions.values(),
|
|
27108
|
+
this.clients.currentWindows(),
|
|
27109
|
+
this.notify,
|
|
26689
27110
|
claudeSessionId,
|
|
26690
27111
|
transcriptPath,
|
|
26691
|
-
usedPct
|
|
26692
|
-
|
|
26693
|
-
))
|
|
26694
|
-
this.notify();
|
|
27112
|
+
usedPct
|
|
27113
|
+
);
|
|
26695
27114
|
}
|
|
26696
27115
|
listSessions = () => {
|
|
26697
27116
|
const local = [...this.sessions.values()].map(toSessionInfo);
|
|
@@ -26712,8 +27131,30 @@ import * as net3 from "net";
|
|
|
26712
27131
|
// src/commands/sessions/daemon/handleConnection.ts
|
|
26713
27132
|
import { createInterface as createInterface9 } from "readline";
|
|
26714
27133
|
|
|
27134
|
+
// src/commands/sessions/daemon/creator.ts
|
|
27135
|
+
function creator(isNew, spawn12) {
|
|
27136
|
+
return (client, m, d) => {
|
|
27137
|
+
if (m.windowsProxy.route(client, d)) return;
|
|
27138
|
+
sendTo(client, { type: "created", sessionId: spawn12(m, d), isNew });
|
|
27139
|
+
};
|
|
27140
|
+
}
|
|
27141
|
+
|
|
27142
|
+
// src/commands/sessions/daemon/handleSetStatus.ts
|
|
27143
|
+
function handleSetStatus(client, m, d) {
|
|
27144
|
+
daemonLog(
|
|
27145
|
+
`set-status received: id=${d.sessionId} status=${d.status}${d.source ? ` source=${d.source}` : ""}`
|
|
27146
|
+
);
|
|
27147
|
+
if (m.windowsProxy.route(client, d)) return;
|
|
27148
|
+
m.setStatus(
|
|
27149
|
+
d.sessionId,
|
|
27150
|
+
d.status,
|
|
27151
|
+
d.source
|
|
27152
|
+
);
|
|
27153
|
+
if (d.ack) sendTo(client, { type: "ack", sessionId: d.sessionId });
|
|
27154
|
+
}
|
|
27155
|
+
|
|
26715
27156
|
// src/commands/sessions/shared/parseTranscript.ts
|
|
26716
|
-
import * as
|
|
27157
|
+
import * as fs39 from "fs";
|
|
26717
27158
|
|
|
26718
27159
|
// src/commands/sessions/shared/toolTarget.ts
|
|
26719
27160
|
function toolTarget(input) {
|
|
@@ -26765,7 +27206,7 @@ async function parseTranscript(sessionId) {
|
|
|
26765
27206
|
const filePath = await findSessionJsonlPath(sessionId);
|
|
26766
27207
|
if (!filePath) return [];
|
|
26767
27208
|
try {
|
|
26768
|
-
const raw = await
|
|
27209
|
+
const raw = await fs39.promises.readFile(filePath, "utf8");
|
|
26769
27210
|
return parseTranscriptLines(raw.split("\n"));
|
|
26770
27211
|
} catch {
|
|
26771
27212
|
return [];
|
|
@@ -26829,12 +27270,6 @@ function spawnCreate(m, d) {
|
|
|
26829
27270
|
}
|
|
26830
27271
|
|
|
26831
27272
|
// src/commands/sessions/daemon/messageHandlers.ts
|
|
26832
|
-
function creator(isNew, spawn12) {
|
|
26833
|
-
return (client, m, d) => {
|
|
26834
|
-
if (m.windowsProxy.route(client, d)) return;
|
|
26835
|
-
sendTo(client, { type: "created", sessionId: spawn12(m, d), isNew });
|
|
26836
|
-
};
|
|
26837
|
-
}
|
|
26838
27273
|
function routed(local) {
|
|
26839
27274
|
return (client, m, d) => {
|
|
26840
27275
|
if (!m.windowsProxy.route(client, d)) local(client, m, d);
|
|
@@ -26903,11 +27338,7 @@ var messageHandlers = {
|
|
|
26903
27338
|
(_client, m, d) => m.setStarred(d.sessionId, d.starred)
|
|
26904
27339
|
),
|
|
26905
27340
|
"set-active": (_client, m, d) => m.active.set(d.cwd, d.sessionId),
|
|
26906
|
-
"set-status":
|
|
26907
|
-
daemonLog(`set-status received: id=${d.sessionId} status=${d.status}`);
|
|
26908
|
-
if (!m.windowsProxy.route(client, d))
|
|
26909
|
-
m.setStatus(d.sessionId, d.status);
|
|
26910
|
-
},
|
|
27341
|
+
"set-status": handleSetStatus,
|
|
26911
27342
|
"ui-status": (_client, _m, d) => daemonLog(`ui rendered: id=${d.sessionId} status=${d.status}`)
|
|
26912
27343
|
};
|
|
26913
27344
|
|
|
@@ -27093,18 +27524,33 @@ function registerDaemon(program2) {
|
|
|
27093
27524
|
).action(drainDaemon);
|
|
27094
27525
|
}
|
|
27095
27526
|
|
|
27527
|
+
// src/commands/sessions/registerSetStatusCommand.ts
|
|
27528
|
+
function registerSetStatusCommand(cmd) {
|
|
27529
|
+
cmd.command("set-status <status>").description(
|
|
27530
|
+
"Report the current session's status to the sessions daemon (used by Claude Code hooks)"
|
|
27531
|
+
).option(
|
|
27532
|
+
"--source <source>",
|
|
27533
|
+
"Originating hook (permission, stop, notification, prompt, pretool, posttool)"
|
|
27534
|
+
).option(
|
|
27535
|
+
"--ack",
|
|
27536
|
+
"Wait for the daemon to acknowledge delivery, retrying on failure"
|
|
27537
|
+
).action(
|
|
27538
|
+
(status3, options2) => setSessionStatus(status3, { source: options2.source, ack: options2.ack })
|
|
27539
|
+
);
|
|
27540
|
+
}
|
|
27541
|
+
|
|
27096
27542
|
// src/commands/sessions/summarise/index.ts
|
|
27097
|
-
import * as
|
|
27098
|
-
import
|
|
27543
|
+
import * as fs41 from "fs";
|
|
27544
|
+
import chalk201 from "chalk";
|
|
27099
27545
|
|
|
27100
27546
|
// src/commands/sessions/summarise/shared.ts
|
|
27101
|
-
import * as
|
|
27547
|
+
import * as fs40 from "fs";
|
|
27102
27548
|
function writeSummary(jsonlPath2, summary) {
|
|
27103
|
-
|
|
27549
|
+
fs40.writeFileSync(summaryPathFor(jsonlPath2), `${summary.trim()}
|
|
27104
27550
|
`, "utf8");
|
|
27105
27551
|
}
|
|
27106
27552
|
function hasSummary(jsonlPath2) {
|
|
27107
|
-
return
|
|
27553
|
+
return fs40.existsSync(summaryPathFor(jsonlPath2));
|
|
27108
27554
|
}
|
|
27109
27555
|
function summaryPathFor(jsonlPath2) {
|
|
27110
27556
|
return jsonlPath2.replace(/\.jsonl$/, ".summary");
|
|
@@ -27169,29 +27615,29 @@ ${firstMessage}`);
|
|
|
27169
27615
|
async function summarise2(options2) {
|
|
27170
27616
|
const files = await discoverSessionFiles();
|
|
27171
27617
|
if (files.length === 0) {
|
|
27172
|
-
console.log(
|
|
27618
|
+
console.log(chalk201.yellow("No sessions found."));
|
|
27173
27619
|
return;
|
|
27174
27620
|
}
|
|
27175
27621
|
const toProcess = selectCandidates(files, options2);
|
|
27176
27622
|
if (toProcess.length === 0) {
|
|
27177
|
-
console.log(
|
|
27623
|
+
console.log(chalk201.green("All sessions already summarised."));
|
|
27178
27624
|
return;
|
|
27179
27625
|
}
|
|
27180
27626
|
console.log(
|
|
27181
|
-
|
|
27627
|
+
chalk201.cyan(
|
|
27182
27628
|
`Summarising ${toProcess.length} session(s) (${files.length} total)\u2026`
|
|
27183
27629
|
)
|
|
27184
27630
|
);
|
|
27185
27631
|
const { succeeded, failed: failed2 } = processSessions(toProcess);
|
|
27186
27632
|
console.log(
|
|
27187
|
-
|
|
27633
|
+
chalk201.green(`Done: ${succeeded} summarised`) + (failed2 > 0 ? chalk201.yellow(`, ${failed2} skipped`) : "")
|
|
27188
27634
|
);
|
|
27189
27635
|
}
|
|
27190
27636
|
function selectCandidates(files, options2) {
|
|
27191
27637
|
const candidates = options2.force ? files : files.filter((f) => !hasSummary(f));
|
|
27192
27638
|
candidates.sort((a, b) => {
|
|
27193
27639
|
try {
|
|
27194
|
-
return
|
|
27640
|
+
return fs41.statSync(b).mtimeMs - fs41.statSync(a).mtimeMs;
|
|
27195
27641
|
} catch {
|
|
27196
27642
|
return 0;
|
|
27197
27643
|
}
|
|
@@ -27204,16 +27650,16 @@ function processSessions(files) {
|
|
|
27204
27650
|
let failed2 = 0;
|
|
27205
27651
|
for (let i = 0; i < files.length; i++) {
|
|
27206
27652
|
const file = files[i];
|
|
27207
|
-
process.stdout.write(
|
|
27653
|
+
process.stdout.write(chalk201.dim(` [${i + 1}/${files.length}] `));
|
|
27208
27654
|
const summary = summariseSession(file);
|
|
27209
27655
|
if (summary) {
|
|
27210
27656
|
writeSummary(file, summary);
|
|
27211
27657
|
succeeded++;
|
|
27212
|
-
process.stdout.write(`${
|
|
27658
|
+
process.stdout.write(`${chalk201.green("\u2713")} ${summary}
|
|
27213
27659
|
`);
|
|
27214
27660
|
} else {
|
|
27215
27661
|
failed2++;
|
|
27216
|
-
process.stdout.write(` ${
|
|
27662
|
+
process.stdout.write(` ${chalk201.yellow("skip")}
|
|
27217
27663
|
`);
|
|
27218
27664
|
}
|
|
27219
27665
|
}
|
|
@@ -27229,9 +27675,7 @@ function registerSessions(program2) {
|
|
|
27229
27675
|
(options2, command) => web({ ...options2, open: command.optsWithGlobals().open })
|
|
27230
27676
|
);
|
|
27231
27677
|
cmd.command("summarise").description("Generate one-line summaries for Claude sessions").option("-f, --force", "Re-generate all summaries, even existing ones").option("-n, --limit <count>", "Maximum number of sessions to summarise").action(summarise2);
|
|
27232
|
-
cmd
|
|
27233
|
-
"Report the current session's status to the sessions daemon (used by Claude Code hooks)"
|
|
27234
|
-
).action(setSessionStatus);
|
|
27678
|
+
registerSetStatusCommand(cmd);
|
|
27235
27679
|
configHelp(cmd, [
|
|
27236
27680
|
{
|
|
27237
27681
|
key: "sessions.windowsProjectsRoot",
|
|
@@ -27257,7 +27701,7 @@ function registerSessions(program2) {
|
|
|
27257
27701
|
}
|
|
27258
27702
|
|
|
27259
27703
|
// src/commands/statusLine.ts
|
|
27260
|
-
import
|
|
27704
|
+
import chalk203 from "chalk";
|
|
27261
27705
|
|
|
27262
27706
|
// src/shared/contextLevel.ts
|
|
27263
27707
|
function contextLevel(pct) {
|
|
@@ -27267,7 +27711,7 @@ function contextLevel(pct) {
|
|
|
27267
27711
|
}
|
|
27268
27712
|
|
|
27269
27713
|
// src/commands/buildLimitsSegment.ts
|
|
27270
|
-
import
|
|
27714
|
+
import chalk202 from "chalk";
|
|
27271
27715
|
|
|
27272
27716
|
// src/shared/rateLimitLevel.ts
|
|
27273
27717
|
var FIVE_HOUR_SECONDS = 5 * 3600;
|
|
@@ -27298,9 +27742,9 @@ function rateLimitLevel(pct, resetsAt, windowSeconds, now) {
|
|
|
27298
27742
|
|
|
27299
27743
|
// src/commands/buildLimitsSegment.ts
|
|
27300
27744
|
var LEVEL_COLOR = {
|
|
27301
|
-
ok:
|
|
27302
|
-
warn:
|
|
27303
|
-
over:
|
|
27745
|
+
ok: chalk202.green,
|
|
27746
|
+
warn: chalk202.yellow,
|
|
27747
|
+
over: chalk202.red
|
|
27304
27748
|
};
|
|
27305
27749
|
function formatLimit(pct, resetsAt, windowSeconds, fallbackLabel, now) {
|
|
27306
27750
|
const level = rateLimitLevel(pct, resetsAt, windowSeconds, now);
|
|
@@ -27332,9 +27776,9 @@ function buildLimitsSegment(rateLimits) {
|
|
|
27332
27776
|
|
|
27333
27777
|
// src/commands/readGitBranch.ts
|
|
27334
27778
|
import { readFileSync as readFileSync52, statSync as statSync11 } from "fs";
|
|
27335
|
-
import { isAbsolute as isAbsolute2, join as
|
|
27779
|
+
import { isAbsolute as isAbsolute2, join as join69, resolve as resolve17 } from "path";
|
|
27336
27780
|
function resolveGitDir(cwd) {
|
|
27337
|
-
const dotGit =
|
|
27781
|
+
const dotGit = join69(cwd, ".git");
|
|
27338
27782
|
let stat2;
|
|
27339
27783
|
try {
|
|
27340
27784
|
stat2 = statSync11(dotGit);
|
|
@@ -27364,7 +27808,7 @@ function readGitBranch(cwd) {
|
|
|
27364
27808
|
}
|
|
27365
27809
|
let head;
|
|
27366
27810
|
try {
|
|
27367
|
-
head = readFileSync52(
|
|
27811
|
+
head = readFileSync52(join69(gitDir, "HEAD"), "utf8");
|
|
27368
27812
|
} catch {
|
|
27369
27813
|
return null;
|
|
27370
27814
|
}
|
|
@@ -27396,7 +27840,7 @@ async function relayUsage(claudeSessionId, transcriptPath, usedPct) {
|
|
|
27396
27840
|
}
|
|
27397
27841
|
|
|
27398
27842
|
// src/commands/statusLine.ts
|
|
27399
|
-
|
|
27843
|
+
chalk203.level = 3;
|
|
27400
27844
|
function formatNumber(num) {
|
|
27401
27845
|
return num.toLocaleString("en-US");
|
|
27402
27846
|
}
|
|
@@ -27404,9 +27848,9 @@ function colorizePercent(pct) {
|
|
|
27404
27848
|
const label2 = `${Math.round(pct)}%`;
|
|
27405
27849
|
switch (contextLevel(pct)) {
|
|
27406
27850
|
case "red":
|
|
27407
|
-
return
|
|
27851
|
+
return chalk203.red(label2);
|
|
27408
27852
|
case "yellow":
|
|
27409
|
-
return
|
|
27853
|
+
return chalk203.yellow(label2);
|
|
27410
27854
|
default:
|
|
27411
27855
|
return label2;
|
|
27412
27856
|
}
|
|
@@ -27419,7 +27863,7 @@ async function statusLine() {
|
|
|
27419
27863
|
const usedPct = data.context_window.used_percentage ?? 0;
|
|
27420
27864
|
const dir = data.workspace?.current_dir ?? data.cwd;
|
|
27421
27865
|
const branch2 = dir ? readGitBranch(toGitCwd(dir)) : null;
|
|
27422
|
-
const branchSegment = branch2 ? `\u{1F33F}\uFE0F ${
|
|
27866
|
+
const branchSegment = branch2 ? `\u{1F33F}\uFE0F ${chalk203.cyan(branch2)} | ` : "";
|
|
27423
27867
|
console.log(
|
|
27424
27868
|
`${branchSegment}${model} | Tokens - ${formatNumber(totalIn)} \u2191 : ${formatNumber(totalOut)} \u2193 | Context - ${colorizePercent(usedPct)}${buildLimitsSegment(data.rate_limits)}`
|
|
27425
27869
|
);
|
|
@@ -27432,29 +27876,29 @@ async function statusLine() {
|
|
|
27432
27876
|
}
|
|
27433
27877
|
|
|
27434
27878
|
// src/commands/sync.ts
|
|
27435
|
-
import * as
|
|
27436
|
-
import * as
|
|
27437
|
-
import * as
|
|
27879
|
+
import * as fs48 from "fs";
|
|
27880
|
+
import * as os5 from "os";
|
|
27881
|
+
import * as path69 from "path";
|
|
27438
27882
|
import { fileURLToPath as fileURLToPath9 } from "url";
|
|
27439
27883
|
|
|
27440
27884
|
// src/commands/sync/syncClaudeMd.ts
|
|
27441
|
-
import * as
|
|
27442
|
-
import * as
|
|
27443
|
-
import
|
|
27885
|
+
import * as fs42 from "fs";
|
|
27886
|
+
import * as path61 from "path";
|
|
27887
|
+
import chalk204 from "chalk";
|
|
27444
27888
|
async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
27445
|
-
const source =
|
|
27446
|
-
const target =
|
|
27447
|
-
const sourceContent =
|
|
27448
|
-
if (
|
|
27449
|
-
const targetContent =
|
|
27889
|
+
const source = path61.join(claudeDir, "CLAUDE.md");
|
|
27890
|
+
const target = path61.join(targetBase, "CLAUDE.md");
|
|
27891
|
+
const sourceContent = fs42.readFileSync(source, "utf8");
|
|
27892
|
+
if (fs42.existsSync(target)) {
|
|
27893
|
+
const targetContent = fs42.readFileSync(target, "utf8");
|
|
27450
27894
|
if (sourceContent !== targetContent) {
|
|
27451
27895
|
console.log(
|
|
27452
|
-
|
|
27896
|
+
chalk204.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
27453
27897
|
);
|
|
27454
27898
|
console.log();
|
|
27455
27899
|
printDiff(targetContent, sourceContent);
|
|
27456
27900
|
const confirm = options2?.yes || await promptConfirm(
|
|
27457
|
-
|
|
27901
|
+
chalk204.red("Overwrite existing CLAUDE.md?"),
|
|
27458
27902
|
false
|
|
27459
27903
|
);
|
|
27460
27904
|
if (!confirm) {
|
|
@@ -27463,38 +27907,38 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
27463
27907
|
}
|
|
27464
27908
|
}
|
|
27465
27909
|
}
|
|
27466
|
-
|
|
27910
|
+
fs42.copyFileSync(source, target);
|
|
27467
27911
|
console.log("Copied CLAUDE.md to ~/.claude/CLAUDE.md");
|
|
27468
27912
|
}
|
|
27469
27913
|
|
|
27470
27914
|
// src/commands/sync/syncCodex.ts
|
|
27471
|
-
import * as
|
|
27915
|
+
import * as path64 from "path";
|
|
27472
27916
|
|
|
27473
27917
|
// src/commands/sync/installHarnessCommands.ts
|
|
27474
|
-
import * as
|
|
27475
|
-
import * as
|
|
27918
|
+
import * as fs43 from "fs";
|
|
27919
|
+
import * as path62 from "path";
|
|
27476
27920
|
function installHarnessCommands(claudeDir, harness, transform) {
|
|
27477
|
-
const commandsSource =
|
|
27478
|
-
const files =
|
|
27921
|
+
const commandsSource = path62.join(claudeDir, "commands");
|
|
27922
|
+
const files = fs43.readdirSync(commandsSource);
|
|
27479
27923
|
let synced = 0;
|
|
27480
27924
|
for (const file of files) {
|
|
27481
27925
|
if (!file.endsWith(".md")) continue;
|
|
27482
27926
|
const name = file.replace(/\.md$/, "");
|
|
27483
|
-
const content =
|
|
27484
|
-
const target =
|
|
27485
|
-
|
|
27486
|
-
|
|
27927
|
+
const content = fs43.readFileSync(path62.join(commandsSource, file), "utf8");
|
|
27928
|
+
const target = path62.join(harness.homeDir, harness.sync.commandDest(name));
|
|
27929
|
+
fs43.mkdirSync(path62.dirname(target), { recursive: true });
|
|
27930
|
+
fs43.writeFileSync(target, transform(name, content));
|
|
27487
27931
|
synced++;
|
|
27488
27932
|
}
|
|
27489
|
-
const agentsTarget =
|
|
27490
|
-
|
|
27491
|
-
|
|
27933
|
+
const agentsTarget = path62.join(harness.homeDir, harness.sync.agentsFile);
|
|
27934
|
+
fs43.mkdirSync(path62.dirname(agentsTarget), { recursive: true });
|
|
27935
|
+
fs43.copyFileSync(path62.join(claudeDir, "CLAUDE.md"), agentsTarget);
|
|
27492
27936
|
return { total: files.length, synced };
|
|
27493
27937
|
}
|
|
27494
27938
|
|
|
27495
27939
|
// src/commands/sync/syncCodexHooks.ts
|
|
27496
|
-
import * as
|
|
27497
|
-
import * as
|
|
27940
|
+
import * as fs44 from "fs";
|
|
27941
|
+
import * as path63 from "path";
|
|
27498
27942
|
var BEGIN = "# >>> assist codex hooks (managed) \u2014 do not edit >>>";
|
|
27499
27943
|
var END = "# <<< assist codex hooks (managed) <<<";
|
|
27500
27944
|
function upsertManagedBlock(existing, body) {
|
|
@@ -27524,11 +27968,11 @@ ${rest}
|
|
|
27524
27968
|
`;
|
|
27525
27969
|
}
|
|
27526
27970
|
function syncCodexHooks(sourcePath) {
|
|
27527
|
-
const body =
|
|
27528
|
-
const configPath =
|
|
27529
|
-
const existing =
|
|
27530
|
-
|
|
27531
|
-
|
|
27971
|
+
const body = fs44.readFileSync(sourcePath, "utf8");
|
|
27972
|
+
const configPath = path63.join(harnesses.codex.homeDir, "config.toml");
|
|
27973
|
+
const existing = fs44.existsSync(configPath) ? fs44.readFileSync(configPath, "utf8") : "";
|
|
27974
|
+
fs44.mkdirSync(path63.dirname(configPath), { recursive: true });
|
|
27975
|
+
fs44.writeFileSync(configPath, upsertManagedBlock(existing, body));
|
|
27532
27976
|
console.log(
|
|
27533
27977
|
"Registered assist codex-hook in ~/.codex/config.toml (PreToolUse, PermissionRequest)"
|
|
27534
27978
|
);
|
|
@@ -27559,50 +28003,50 @@ function syncCodex(claudeDir) {
|
|
|
27559
28003
|
harnesses.codex,
|
|
27560
28004
|
commandToSkill
|
|
27561
28005
|
);
|
|
27562
|
-
syncCodexHooks(
|
|
28006
|
+
syncCodexHooks(path64.join(claudeDir, "..", "codex", "config.toml"));
|
|
27563
28007
|
console.log(
|
|
27564
28008
|
`Synced ${total} skill(s) to ~/.codex/skills and CLAUDE.md to ~/.codex/AGENTS.md`
|
|
27565
28009
|
);
|
|
27566
28010
|
}
|
|
27567
28011
|
|
|
27568
28012
|
// src/commands/sync/syncDesign.ts
|
|
27569
|
-
import * as
|
|
27570
|
-
import * as
|
|
28013
|
+
import * as fs45 from "fs";
|
|
28014
|
+
import * as path65 from "path";
|
|
27571
28015
|
function syncDesign(claudeDir, targetBase) {
|
|
27572
|
-
const systemPromptSource =
|
|
27573
|
-
const systemPromptTarget =
|
|
27574
|
-
|
|
28016
|
+
const systemPromptSource = path65.join(claudeDir, "system-prompt.md");
|
|
28017
|
+
const systemPromptTarget = path65.join(targetBase, "system-prompt.md");
|
|
28018
|
+
fs45.copyFileSync(systemPromptSource, systemPromptTarget);
|
|
27575
28019
|
console.log("Copied system-prompt.md to ~/.claude/system-prompt.md");
|
|
27576
|
-
const skillsSource =
|
|
27577
|
-
const skillsTarget =
|
|
27578
|
-
|
|
27579
|
-
const files =
|
|
28020
|
+
const skillsSource = path65.join(claudeDir, "skills");
|
|
28021
|
+
const skillsTarget = path65.join(targetBase, "skills");
|
|
28022
|
+
fs45.mkdirSync(skillsTarget, { recursive: true });
|
|
28023
|
+
const files = fs45.readdirSync(skillsSource);
|
|
27580
28024
|
for (const file of files) {
|
|
27581
|
-
|
|
27582
|
-
|
|
27583
|
-
|
|
28025
|
+
fs45.copyFileSync(
|
|
28026
|
+
path65.join(skillsSource, file),
|
|
28027
|
+
path65.join(skillsTarget, file)
|
|
27584
28028
|
);
|
|
27585
28029
|
}
|
|
27586
28030
|
console.log(`Synced ${files.length} design skill(s) to ~/.claude/skills`);
|
|
27587
28031
|
}
|
|
27588
28032
|
|
|
27589
28033
|
// src/commands/sync/syncPi.ts
|
|
27590
|
-
import * as
|
|
28034
|
+
import * as path67 from "path";
|
|
27591
28035
|
|
|
27592
28036
|
// src/commands/sync/syncPiHooks.ts
|
|
27593
|
-
import * as
|
|
27594
|
-
import * as
|
|
28037
|
+
import * as fs46 from "fs";
|
|
28038
|
+
import * as path66 from "path";
|
|
27595
28039
|
function piExtensionsDir() {
|
|
27596
|
-
return
|
|
28040
|
+
return path66.join(harnesses.pi.homeDir, "extensions");
|
|
27597
28041
|
}
|
|
27598
28042
|
function syncPiHooks(sourceDir) {
|
|
27599
28043
|
const target = piExtensionsDir();
|
|
27600
|
-
|
|
27601
|
-
const files =
|
|
28044
|
+
fs46.mkdirSync(target, { recursive: true });
|
|
28045
|
+
const files = fs46.readdirSync(sourceDir).filter((f) => f.endsWith(".ts"));
|
|
27602
28046
|
for (const file of files) {
|
|
27603
|
-
|
|
27604
|
-
|
|
27605
|
-
|
|
28047
|
+
fs46.copyFileSync(
|
|
28048
|
+
path66.join(sourceDir, file),
|
|
28049
|
+
path66.join(target, `assist-${file}`)
|
|
27606
28050
|
);
|
|
27607
28051
|
}
|
|
27608
28052
|
console.log(
|
|
@@ -27639,23 +28083,23 @@ function syncPi(claudeDir) {
|
|
|
27639
28083
|
harnesses.pi,
|
|
27640
28084
|
commandToPrompt
|
|
27641
28085
|
);
|
|
27642
|
-
syncPiHooks(
|
|
28086
|
+
syncPiHooks(path67.join(claudeDir, "..", "pi"));
|
|
27643
28087
|
console.log(
|
|
27644
28088
|
`Synced ${synced} prompt(s) to ~/.pi/agent/prompts and CLAUDE.md to ~/.pi/agent/AGENTS.md`
|
|
27645
28089
|
);
|
|
27646
28090
|
}
|
|
27647
28091
|
|
|
27648
28092
|
// src/commands/sync/syncSettings.ts
|
|
27649
|
-
import * as
|
|
27650
|
-
import * as
|
|
27651
|
-
import
|
|
28093
|
+
import * as fs47 from "fs";
|
|
28094
|
+
import * as path68 from "path";
|
|
28095
|
+
import chalk205 from "chalk";
|
|
27652
28096
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
27653
|
-
const source =
|
|
27654
|
-
const target =
|
|
27655
|
-
const sourceContent =
|
|
28097
|
+
const source = path68.join(claudeDir, "settings.json");
|
|
28098
|
+
const target = path68.join(targetBase, "settings.json");
|
|
28099
|
+
const sourceContent = fs47.readFileSync(source, "utf8");
|
|
27656
28100
|
const sourceSettings = JSON.parse(sourceContent);
|
|
27657
|
-
const targetExists =
|
|
27658
|
-
const targetContent = targetExists ?
|
|
28101
|
+
const targetExists = fs47.existsSync(target);
|
|
28102
|
+
const targetContent = targetExists ? fs47.readFileSync(target, "utf8") : "";
|
|
27659
28103
|
const preservedUserSettings = targetExists ? JSON.parse(targetContent) : {};
|
|
27660
28104
|
const mergedContent = JSON.stringify(
|
|
27661
28105
|
{ ...preservedUserSettings, ...sourceSettings },
|
|
@@ -27667,14 +28111,14 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
27667
28111
|
if (mergedContent !== normalizedTarget) {
|
|
27668
28112
|
if (!options2?.yes) {
|
|
27669
28113
|
console.log(
|
|
27670
|
-
|
|
28114
|
+
chalk205.yellow(
|
|
27671
28115
|
"\n\u26A0\uFE0F Warning: settings.json differs from existing file"
|
|
27672
28116
|
)
|
|
27673
28117
|
);
|
|
27674
28118
|
console.log();
|
|
27675
28119
|
printDiff(targetContent, mergedContent);
|
|
27676
28120
|
const confirm = await promptConfirm(
|
|
27677
|
-
|
|
28121
|
+
chalk205.red("Overwrite existing settings.json?"),
|
|
27678
28122
|
false
|
|
27679
28123
|
);
|
|
27680
28124
|
if (!confirm) {
|
|
@@ -27684,18 +28128,18 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
27684
28128
|
}
|
|
27685
28129
|
}
|
|
27686
28130
|
}
|
|
27687
|
-
|
|
28131
|
+
fs47.writeFileSync(target, mergedContent);
|
|
27688
28132
|
console.log("Copied settings.json to ~/.claude/settings.json");
|
|
27689
28133
|
}
|
|
27690
28134
|
|
|
27691
28135
|
// src/commands/sync.ts
|
|
27692
28136
|
var __filename5 = fileURLToPath9(import.meta.url);
|
|
27693
|
-
var __dirname7 =
|
|
28137
|
+
var __dirname7 = path69.dirname(__filename5);
|
|
27694
28138
|
async function sync(options2) {
|
|
27695
28139
|
const config = loadConfig();
|
|
27696
28140
|
const yes = options2?.yes ?? config.sync.autoConfirm;
|
|
27697
|
-
const claudeDir =
|
|
27698
|
-
const targetBase =
|
|
28141
|
+
const claudeDir = path69.join(__dirname7, "..", "claude");
|
|
28142
|
+
const targetBase = path69.join(os5.homedir(), ".claude");
|
|
27699
28143
|
syncCommands(claudeDir, targetBase);
|
|
27700
28144
|
syncDesign(claudeDir, targetBase);
|
|
27701
28145
|
await syncSettings(claudeDir, targetBase, { yes });
|
|
@@ -27704,12 +28148,12 @@ async function sync(options2) {
|
|
|
27704
28148
|
syncPi(claudeDir);
|
|
27705
28149
|
}
|
|
27706
28150
|
function syncCommands(claudeDir, targetBase) {
|
|
27707
|
-
const sourceDir =
|
|
27708
|
-
const targetDir =
|
|
27709
|
-
|
|
27710
|
-
const files =
|
|
28151
|
+
const sourceDir = path69.join(claudeDir, "commands");
|
|
28152
|
+
const targetDir = path69.join(targetBase, "commands");
|
|
28153
|
+
fs48.mkdirSync(targetDir, { recursive: true });
|
|
28154
|
+
const files = fs48.readdirSync(sourceDir);
|
|
27711
28155
|
for (const file of files) {
|
|
27712
|
-
|
|
28156
|
+
fs48.copyFileSync(path69.join(sourceDir, file), path69.join(targetDir, file));
|
|
27713
28157
|
console.log(`Copied ${file} to ${targetDir}`);
|
|
27714
28158
|
}
|
|
27715
28159
|
console.log(`Synced ${files.length} command(s) to ~/.claude/commands`);
|
|
@@ -27717,7 +28161,7 @@ function syncCommands(claudeDir, targetBase) {
|
|
|
27717
28161
|
|
|
27718
28162
|
// src/commands/update.ts
|
|
27719
28163
|
import { execSync as execSync59 } from "child_process";
|
|
27720
|
-
import * as
|
|
28164
|
+
import * as path70 from "path";
|
|
27721
28165
|
|
|
27722
28166
|
// src/commands/restartDaemonAfterUpdate.ts
|
|
27723
28167
|
async function restartDaemonAfterUpdate() {
|
|
@@ -27736,12 +28180,12 @@ async function restartDaemonAfterUpdate() {
|
|
|
27736
28180
|
// src/commands/update.ts
|
|
27737
28181
|
function isGlobalNpmInstall(dir) {
|
|
27738
28182
|
try {
|
|
27739
|
-
const resolved =
|
|
27740
|
-
if (resolved.split(
|
|
28183
|
+
const resolved = path70.resolve(dir);
|
|
28184
|
+
if (resolved.split(path70.sep).includes("node_modules")) {
|
|
27741
28185
|
return true;
|
|
27742
28186
|
}
|
|
27743
28187
|
const globalPrefix = execSync59("npm prefix -g", { stdio: "pipe" }).toString().trim();
|
|
27744
|
-
return resolved.toLowerCase().startsWith(
|
|
28188
|
+
return resolved.toLowerCase().startsWith(path70.resolve(globalPrefix).toLowerCase());
|
|
27745
28189
|
} catch {
|
|
27746
28190
|
return false;
|
|
27747
28191
|
}
|
|
@@ -27773,10 +28217,10 @@ async function update2() {
|
|
|
27773
28217
|
}
|
|
27774
28218
|
|
|
27775
28219
|
// src/reportCliError.ts
|
|
27776
|
-
import
|
|
28220
|
+
import chalk206 from "chalk";
|
|
27777
28221
|
function reportCliError(error) {
|
|
27778
|
-
if (error instanceof InvalidItemIdError) {
|
|
27779
|
-
console.error(
|
|
28222
|
+
if (error instanceof InvalidItemIdError || error instanceof AmbiguousRepoConfigError) {
|
|
28223
|
+
console.error(chalk206.red(error.message));
|
|
27780
28224
|
} else {
|
|
27781
28225
|
console.error(error);
|
|
27782
28226
|
}
|