@staff0rd/assist 0.440.0 → 0.441.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/dist/commands/sessions/web/bundle.js +465 -465
- package/dist/index.js +907 -714
- package/package.json +2 -3
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.441.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -98,11 +98,11 @@ var package_default = {
|
|
|
98
98
|
"@types/pg-copy-streams": "^1.2.5",
|
|
99
99
|
"@types/react": "^19.2.14",
|
|
100
100
|
"@types/react-dom": "^19.2.3",
|
|
101
|
-
"@types/react-file-icon": "^1.0.5",
|
|
102
101
|
"@types/semver": "^7.7.1",
|
|
103
102
|
"@types/shell-quote": "^1.7.5",
|
|
104
103
|
"@types/ws": "^8.18.1",
|
|
105
104
|
"@vitest/coverage-v8": "^4.1.2",
|
|
105
|
+
"devicons-react": "^1.5.0",
|
|
106
106
|
esbuild: "^0.27.3",
|
|
107
107
|
jscpd: "^4.0.5",
|
|
108
108
|
jsdom: "^29.1.1",
|
|
@@ -111,7 +111,6 @@ var package_default = {
|
|
|
111
111
|
oxlint: "^1.69.0",
|
|
112
112
|
react: "^19.2.4",
|
|
113
113
|
"react-dom": "^19.2.4",
|
|
114
|
-
"react-file-icon": "^1.6.0",
|
|
115
114
|
"react-router": "^7.14.0",
|
|
116
115
|
"semantic-release": "^25.0.2",
|
|
117
116
|
skott: "^0.35.11",
|
|
@@ -585,9 +584,6 @@ function loadConfigFrom(cwd) {
|
|
|
585
584
|
}
|
|
586
585
|
|
|
587
586
|
// src/shared/loadConfig.ts
|
|
588
|
-
function getConfigPath() {
|
|
589
|
-
return getConfigPathFrom(process.cwd());
|
|
590
|
-
}
|
|
591
587
|
function getConfigDir() {
|
|
592
588
|
return getConfigDirFrom(process.cwd());
|
|
593
589
|
}
|
|
@@ -598,8 +594,8 @@ function getProjectRoot() {
|
|
|
598
594
|
function loadConfig() {
|
|
599
595
|
return loadConfigFrom(process.cwd());
|
|
600
596
|
}
|
|
601
|
-
function loadProjectConfig() {
|
|
602
|
-
return loadRawYaml(
|
|
597
|
+
function loadProjectConfig(cwd = process.cwd()) {
|
|
598
|
+
return loadRawYaml(getConfigPathFrom(cwd));
|
|
603
599
|
}
|
|
604
600
|
function loadGlobalConfigRaw() {
|
|
605
601
|
return loadRawYaml(getGlobalConfigPath());
|
|
@@ -607,8 +603,8 @@ function loadGlobalConfigRaw() {
|
|
|
607
603
|
function saveGlobalConfig(config) {
|
|
608
604
|
writeFileSync(getGlobalConfigPath(), stringifyYaml(config, { lineWidth: 0 }));
|
|
609
605
|
}
|
|
610
|
-
function saveConfig(config) {
|
|
611
|
-
const configPath =
|
|
606
|
+
function saveConfig(config, cwd = process.cwd()) {
|
|
607
|
+
const configPath = getConfigPathFrom(cwd);
|
|
612
608
|
writeFileSync(configPath, stringifyYaml(config, { lineWidth: 0 }));
|
|
613
609
|
}
|
|
614
610
|
function getTranscriptConfig() {
|
|
@@ -3532,7 +3528,7 @@ function configHelp(command, entries, preamble) {
|
|
|
3532
3528
|
);
|
|
3533
3529
|
}
|
|
3534
3530
|
|
|
3535
|
-
// src/shared/
|
|
3531
|
+
// src/shared/unwrapSchemaNode.ts
|
|
3536
3532
|
var WRAPPER_TYPES = /* @__PURE__ */ new Set([
|
|
3537
3533
|
"optional",
|
|
3538
3534
|
"default",
|
|
@@ -3541,28 +3537,64 @@ var WRAPPER_TYPES = /* @__PURE__ */ new Set([
|
|
|
3541
3537
|
"readonly",
|
|
3542
3538
|
"catch"
|
|
3543
3539
|
]);
|
|
3544
|
-
function
|
|
3540
|
+
function unwrapSchemaNode(node) {
|
|
3545
3541
|
let current = node;
|
|
3542
|
+
let defaultValue;
|
|
3546
3543
|
while (current.def && WRAPPER_TYPES.has(current.def.type ?? "") && current.def.innerType) {
|
|
3544
|
+
if (current.def.type === "default" && defaultValue === void 0) {
|
|
3545
|
+
defaultValue = current.def.defaultValue;
|
|
3546
|
+
}
|
|
3547
3547
|
current = current.def.innerType;
|
|
3548
3548
|
}
|
|
3549
|
-
return current;
|
|
3549
|
+
return { inner: current, defaultValue };
|
|
3550
|
+
}
|
|
3551
|
+
|
|
3552
|
+
// src/shared/describeConfigLeaves.ts
|
|
3553
|
+
var LEAF_TYPES = {
|
|
3554
|
+
string: "string",
|
|
3555
|
+
number: "number",
|
|
3556
|
+
boolean: "boolean",
|
|
3557
|
+
enum: "enum",
|
|
3558
|
+
array: "array",
|
|
3559
|
+
record: "record"
|
|
3560
|
+
};
|
|
3561
|
+
function leafType(node) {
|
|
3562
|
+
return LEAF_TYPES[node.def?.type ?? ""] ?? "other";
|
|
3563
|
+
}
|
|
3564
|
+
function enumValues(node) {
|
|
3565
|
+
const entries = node.def?.entries;
|
|
3566
|
+
if (!entries) return void 0;
|
|
3567
|
+
return Object.values(entries).filter(
|
|
3568
|
+
(value) => typeof value === "string"
|
|
3569
|
+
);
|
|
3570
|
+
}
|
|
3571
|
+
function toLeaf(key, node, defaultValue) {
|
|
3572
|
+
const type = leafType(node);
|
|
3573
|
+
const leaf = { key, type };
|
|
3574
|
+
if (type === "enum") leaf.enumValues = enumValues(node);
|
|
3575
|
+
if (defaultValue !== void 0) leaf.defaultValue = defaultValue;
|
|
3576
|
+
return leaf;
|
|
3550
3577
|
}
|
|
3551
3578
|
function collect(node, prefix2, out) {
|
|
3552
|
-
const
|
|
3553
|
-
const shape =
|
|
3554
|
-
if (
|
|
3579
|
+
const { inner, defaultValue } = unwrapSchemaNode(node);
|
|
3580
|
+
const shape = inner.def?.shape;
|
|
3581
|
+
if (inner.def?.type === "object" && shape) {
|
|
3555
3582
|
for (const [key, child] of Object.entries(shape)) {
|
|
3556
3583
|
collect(child, prefix2 ? `${prefix2}.${key}` : key, out);
|
|
3557
3584
|
}
|
|
3558
3585
|
return;
|
|
3559
3586
|
}
|
|
3560
|
-
out.push(prefix2);
|
|
3587
|
+
out.push(toLeaf(prefix2, inner, defaultValue));
|
|
3561
3588
|
}
|
|
3562
|
-
function
|
|
3589
|
+
function describeConfigLeaves(schema2) {
|
|
3563
3590
|
const out = [];
|
|
3564
3591
|
collect(schema2, "", out);
|
|
3565
|
-
return out.sort();
|
|
3592
|
+
return out.sort((a, b) => a.key < b.key ? -1 : a.key > b.key ? 1 : 0);
|
|
3593
|
+
}
|
|
3594
|
+
|
|
3595
|
+
// src/shared/enumerateConfigLeafKeys.ts
|
|
3596
|
+
function enumerateConfigLeafKeys(schema2) {
|
|
3597
|
+
return describeConfigLeaves(schema2).map((leaf) => leaf.key);
|
|
3566
3598
|
}
|
|
3567
3599
|
|
|
3568
3600
|
// src/commands/verify/pendingConfigDocumentation.ts
|
|
@@ -3648,9 +3680,9 @@ function forbiddenStrings() {
|
|
|
3648
3680
|
console.log("No forbidden-strings rules configured.");
|
|
3649
3681
|
process.exit(0);
|
|
3650
3682
|
}
|
|
3651
|
-
const
|
|
3683
|
+
const cache3 = /* @__PURE__ */ new Map();
|
|
3652
3684
|
const readJson = (file) => {
|
|
3653
|
-
if (
|
|
3685
|
+
if (cache3.has(file)) return cache3.get(file);
|
|
3654
3686
|
if (!existsSync12(file)) {
|
|
3655
3687
|
console.log(`Forbidden-strings file not found: ${file}`);
|
|
3656
3688
|
process.exit(1);
|
|
@@ -3662,7 +3694,7 @@ function forbiddenStrings() {
|
|
|
3662
3694
|
console.log(`Could not parse ${file}: ${error.message}`);
|
|
3663
3695
|
process.exit(1);
|
|
3664
3696
|
}
|
|
3665
|
-
|
|
3697
|
+
cache3.set(file, parsed);
|
|
3666
3698
|
return parsed;
|
|
3667
3699
|
};
|
|
3668
3700
|
const violations = findForbiddenStrings(rules, readJson);
|
|
@@ -8098,26 +8130,210 @@ function delay(ms) {
|
|
|
8098
8130
|
return new Promise((resolve20) => setTimeout(resolve20, ms));
|
|
8099
8131
|
}
|
|
8100
8132
|
|
|
8133
|
+
// src/commands/sessions/daemon/isWindowsCwd.ts
|
|
8134
|
+
function isWindowsCwd(cwd) {
|
|
8135
|
+
return /^[A-Za-z]:[\\/]/.test(cwd);
|
|
8136
|
+
}
|
|
8137
|
+
function shouldProxyToWindows(cwd) {
|
|
8138
|
+
return detectPlatform() === "wsl" && isWindowsCwd(cwd);
|
|
8139
|
+
}
|
|
8140
|
+
|
|
8141
|
+
// src/commands/sessions/daemon/originForCwd.ts
|
|
8142
|
+
var cache = /* @__PURE__ */ new Map();
|
|
8143
|
+
function originForCwd(cwd) {
|
|
8144
|
+
if (!cwd) return void 0;
|
|
8145
|
+
const cached = cache.get(cwd);
|
|
8146
|
+
if (cached !== void 0) return cached;
|
|
8147
|
+
const origin = getCurrentOrigin(cwd);
|
|
8148
|
+
cache.set(cwd, origin);
|
|
8149
|
+
return origin;
|
|
8150
|
+
}
|
|
8151
|
+
|
|
8152
|
+
// src/commands/sessions/daemon/worktree/git.ts
|
|
8153
|
+
import { execFile as execFile2, execFileSync as execFileSync2 } from "child_process";
|
|
8154
|
+
function isWindowsPath(cwd) {
|
|
8155
|
+
return /^[A-Za-z]:[\\/]/.test(cwd);
|
|
8156
|
+
}
|
|
8157
|
+
function gitInvocation(cwd, args) {
|
|
8158
|
+
const windows = isWindowsPath(cwd);
|
|
8159
|
+
return {
|
|
8160
|
+
file: windows ? "git.exe" : "git",
|
|
8161
|
+
argv: windows ? ["-C", cwd, ...args] : args,
|
|
8162
|
+
options: { encoding: "utf8", ...windows ? {} : { cwd } }
|
|
8163
|
+
};
|
|
8164
|
+
}
|
|
8165
|
+
function git2(cwd, args) {
|
|
8166
|
+
const { file, argv, options: options2 } = gitInvocation(cwd, args);
|
|
8167
|
+
return new Promise((resolve20, reject) => {
|
|
8168
|
+
execFile2(file, argv, options2, (error, stdout) => {
|
|
8169
|
+
if (error) reject(error);
|
|
8170
|
+
else resolve20(stdout.toString());
|
|
8171
|
+
});
|
|
8172
|
+
});
|
|
8173
|
+
}
|
|
8174
|
+
async function gitOrNull(cwd, args) {
|
|
8175
|
+
try {
|
|
8176
|
+
return (await git2(cwd, args)).trim() || null;
|
|
8177
|
+
} catch {
|
|
8178
|
+
return null;
|
|
8179
|
+
}
|
|
8180
|
+
}
|
|
8181
|
+
async function gitResult(cwd, args) {
|
|
8182
|
+
try {
|
|
8183
|
+
return { ok: true, out: (await git2(cwd, args)).trim() };
|
|
8184
|
+
} catch (error) {
|
|
8185
|
+
return {
|
|
8186
|
+
ok: false,
|
|
8187
|
+
error: error instanceof Error ? error.message : String(error)
|
|
8188
|
+
};
|
|
8189
|
+
}
|
|
8190
|
+
}
|
|
8191
|
+
function gitSyncResult(cwd, args) {
|
|
8192
|
+
try {
|
|
8193
|
+
return { ok: true, out: gitSync(cwd, args).trim() };
|
|
8194
|
+
} catch (error) {
|
|
8195
|
+
return {
|
|
8196
|
+
ok: false,
|
|
8197
|
+
error: error instanceof Error ? error.message : String(error)
|
|
8198
|
+
};
|
|
8199
|
+
}
|
|
8200
|
+
}
|
|
8201
|
+
function gitSync(cwd, args) {
|
|
8202
|
+
const { file, argv, options: options2 } = gitInvocation(cwd, args);
|
|
8203
|
+
return execFileSync2(file, argv, {
|
|
8204
|
+
...options2,
|
|
8205
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
8206
|
+
}).toString();
|
|
8207
|
+
}
|
|
8208
|
+
function gitSyncOrNull(cwd, args) {
|
|
8209
|
+
try {
|
|
8210
|
+
return gitSync(cwd, args).trim() || null;
|
|
8211
|
+
} catch {
|
|
8212
|
+
return null;
|
|
8213
|
+
}
|
|
8214
|
+
}
|
|
8215
|
+
|
|
8216
|
+
// src/commands/sessions/daemon/worktree/listWorktreePaths.ts
|
|
8217
|
+
function listWorktreePaths(cwd) {
|
|
8218
|
+
const out = gitSyncOrNull(cwd, ["worktree", "list", "--porcelain"]);
|
|
8219
|
+
if (!out) return [];
|
|
8220
|
+
return out.split("\n").filter((line) => line.startsWith("worktree ")).map((line) => line.slice("worktree ".length).trim());
|
|
8221
|
+
}
|
|
8222
|
+
function mainWorktree(cwd) {
|
|
8223
|
+
return listWorktreePaths(cwd)[0] ?? null;
|
|
8224
|
+
}
|
|
8225
|
+
function listLocalBranches(cwd) {
|
|
8226
|
+
const out = gitSyncOrNull(cwd, [
|
|
8227
|
+
"for-each-ref",
|
|
8228
|
+
"--format=%(refname:short)",
|
|
8229
|
+
"refs/heads"
|
|
8230
|
+
]);
|
|
8231
|
+
return out ? out.split("\n").map((line) => line.trim()) : [];
|
|
8232
|
+
}
|
|
8233
|
+
function gitCommonDir(cwd) {
|
|
8234
|
+
return gitSyncOrNull(cwd, [
|
|
8235
|
+
"rev-parse",
|
|
8236
|
+
"--path-format=absolute",
|
|
8237
|
+
"--git-common-dir"
|
|
8238
|
+
]);
|
|
8239
|
+
}
|
|
8240
|
+
|
|
8241
|
+
// src/shared/loadJson.ts
|
|
8242
|
+
import { existsSync as existsSync25, mkdirSync as mkdirSync11, readFileSync as readFileSync18, writeFileSync as writeFileSync20 } from "fs";
|
|
8243
|
+
import { homedir as homedir11 } from "os";
|
|
8244
|
+
import { join as join22 } from "path";
|
|
8245
|
+
function getStoreDir() {
|
|
8246
|
+
return join22(homedir11(), ".assist");
|
|
8247
|
+
}
|
|
8248
|
+
function getStorePath(filename) {
|
|
8249
|
+
return join22(getStoreDir(), filename);
|
|
8250
|
+
}
|
|
8251
|
+
function loadJson(filename) {
|
|
8252
|
+
const path71 = getStorePath(filename);
|
|
8253
|
+
if (existsSync25(path71)) {
|
|
8254
|
+
try {
|
|
8255
|
+
return JSON.parse(readFileSync18(path71, "utf8"));
|
|
8256
|
+
} catch {
|
|
8257
|
+
return {};
|
|
8258
|
+
}
|
|
8259
|
+
}
|
|
8260
|
+
return {};
|
|
8261
|
+
}
|
|
8262
|
+
function saveJson(filename, data) {
|
|
8263
|
+
const dir = getStoreDir();
|
|
8264
|
+
if (!existsSync25(dir)) {
|
|
8265
|
+
mkdirSync11(dir, { recursive: true });
|
|
8266
|
+
}
|
|
8267
|
+
writeFileSync20(getStorePath(filename), JSON.stringify(data, null, 2));
|
|
8268
|
+
}
|
|
8269
|
+
|
|
8270
|
+
// src/commands/sessions/daemon/worktree/readWorktreeRegistry.ts
|
|
8271
|
+
var REGISTRY_FILE = "worktrees.json";
|
|
8272
|
+
function readWorktreeRegistry() {
|
|
8273
|
+
const data = loadJson(REGISTRY_FILE);
|
|
8274
|
+
return Object.entries(data).filter(([, record]) => !record.reaped).map(([path71, record]) => ({ path: path71, ...record }));
|
|
8275
|
+
}
|
|
8276
|
+
function worktreeAttributionIncludingReaped(path71) {
|
|
8277
|
+
const record = loadJson(REGISTRY_FILE)[path71];
|
|
8278
|
+
return record ? { clone: record.clone, origin: record.origin } : void 0;
|
|
8279
|
+
}
|
|
8280
|
+
function recordWorktree(path71, clone, origin) {
|
|
8281
|
+
const data = loadJson(REGISTRY_FILE);
|
|
8282
|
+
data[path71] = { clone, origin };
|
|
8283
|
+
saveJson(REGISTRY_FILE, data);
|
|
8284
|
+
}
|
|
8285
|
+
function forgetWorktree(path71) {
|
|
8286
|
+
const data = loadJson(REGISTRY_FILE);
|
|
8287
|
+
const record = data[path71];
|
|
8288
|
+
if (!record || record.reaped) return;
|
|
8289
|
+
data[path71] = { ...record, reaped: true };
|
|
8290
|
+
saveJson(REGISTRY_FILE, data);
|
|
8291
|
+
}
|
|
8292
|
+
|
|
8293
|
+
// src/commands/sessions/daemon/repoGroupForCwd.ts
|
|
8294
|
+
var cache2 = /* @__PURE__ */ new Map();
|
|
8295
|
+
function repoGroupForCwd(cwd) {
|
|
8296
|
+
if (!cwd) return void 0;
|
|
8297
|
+
if (cache2.has(cwd)) return cache2.get(cwd);
|
|
8298
|
+
const group = resolveRepoGroup(cwd);
|
|
8299
|
+
cache2.set(cwd, group);
|
|
8300
|
+
return group;
|
|
8301
|
+
}
|
|
8302
|
+
function resolveRepoGroup(cwd) {
|
|
8303
|
+
const live = groupFromLiveTree(cwd);
|
|
8304
|
+
if (live) return live;
|
|
8305
|
+
const reaped = worktreeAttributionIncludingReaped(cwd);
|
|
8306
|
+
return reaped && hostedGroup(cwd, reaped.origin, reaped.clone);
|
|
8307
|
+
}
|
|
8308
|
+
function groupFromLiveTree(cwd) {
|
|
8309
|
+
const clone = mainWorktree(cwd);
|
|
8310
|
+
const origin = clone ? originForCwd(clone) : void 0;
|
|
8311
|
+
return clone && origin ? hostedGroup(cwd, origin, clone) : void 0;
|
|
8312
|
+
}
|
|
8313
|
+
function hostedGroup(cwd, origin, clone) {
|
|
8314
|
+
return { origin: isWindowsCwd(cwd) ? `windows:${origin}` : origin, clone };
|
|
8315
|
+
}
|
|
8316
|
+
|
|
8101
8317
|
// src/shared/createBundleHandler.ts
|
|
8102
8318
|
import { createHash } from "crypto";
|
|
8103
|
-
import { readFileSync as
|
|
8104
|
-
import { dirname as dirname19, join as
|
|
8319
|
+
import { readFileSync as readFileSync19, statSync as statSync2 } from "fs";
|
|
8320
|
+
import { dirname as dirname19, join as join23 } from "path";
|
|
8105
8321
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
8106
8322
|
function createBundleHandler(importMetaUrl, bundlePath, contentType = "application/javascript") {
|
|
8107
|
-
const file =
|
|
8108
|
-
let
|
|
8323
|
+
const file = join23(dirname19(fileURLToPath4(importMetaUrl)), bundlePath);
|
|
8324
|
+
let cache3;
|
|
8109
8325
|
return (req, res) => {
|
|
8110
8326
|
const mtimeMs = statSync2(file).mtimeMs;
|
|
8111
|
-
if (
|
|
8112
|
-
const body =
|
|
8327
|
+
if (cache3?.mtimeMs !== mtimeMs) {
|
|
8328
|
+
const body = readFileSync19(file, "utf8");
|
|
8113
8329
|
const etag = `"${createHash("sha256").update(body).digest("hex").slice(0, 16)}"`;
|
|
8114
|
-
|
|
8330
|
+
cache3 = { body, etag, mtimeMs };
|
|
8115
8331
|
}
|
|
8116
8332
|
const headers = {
|
|
8117
|
-
ETag:
|
|
8333
|
+
ETag: cache3.etag,
|
|
8118
8334
|
"Cache-Control": "no-cache"
|
|
8119
8335
|
};
|
|
8120
|
-
if (req.headers["if-none-match"] ===
|
|
8336
|
+
if (req.headers["if-none-match"] === cache3.etag) {
|
|
8121
8337
|
res.writeHead(304, headers);
|
|
8122
8338
|
res.end();
|
|
8123
8339
|
return;
|
|
@@ -8126,7 +8342,7 @@ function createBundleHandler(importMetaUrl, bundlePath, contentType = "applicati
|
|
|
8126
8342
|
"Content-Type": contentType,
|
|
8127
8343
|
...headers
|
|
8128
8344
|
});
|
|
8129
|
-
res.end(
|
|
8345
|
+
res.end(cache3.body);
|
|
8130
8346
|
};
|
|
8131
8347
|
}
|
|
8132
8348
|
|
|
@@ -8238,15 +8454,15 @@ async function loadItemSummaries(orm, origin) {
|
|
|
8238
8454
|
}
|
|
8239
8455
|
|
|
8240
8456
|
// src/commands/backlog/resolveRepoLocation.ts
|
|
8241
|
-
import { existsSync as
|
|
8457
|
+
import { existsSync as existsSync26 } from "fs";
|
|
8242
8458
|
|
|
8243
8459
|
// src/commands/backlog/cloneTargetDir.ts
|
|
8244
|
-
import { join as
|
|
8460
|
+
import { join as join24, resolve as resolve8 } from "path";
|
|
8245
8461
|
function cloneTargetDir(origin, baseDir) {
|
|
8246
8462
|
if (origin.startsWith("local:")) return null;
|
|
8247
8463
|
const repoName = origin.split("/").filter(Boolean).pop();
|
|
8248
8464
|
if (!repoName) return null;
|
|
8249
|
-
return resolve8(
|
|
8465
|
+
return resolve8(join24(baseDir, repoName));
|
|
8250
8466
|
}
|
|
8251
8467
|
|
|
8252
8468
|
// src/commands/backlog/resolveRepoLocation.ts
|
|
@@ -8254,7 +8470,7 @@ function resolveRepoLocation(origin, knownCwd, baseDir) {
|
|
|
8254
8470
|
if (knownCwd) return { cwd: knownCwd };
|
|
8255
8471
|
const target = cloneTargetDir(origin, baseDir);
|
|
8256
8472
|
if (!target) return {};
|
|
8257
|
-
if (
|
|
8473
|
+
if (existsSync26(target) && getCurrentOrigin(target) === origin)
|
|
8258
8474
|
return { cwd: target };
|
|
8259
8475
|
return { cloneTarget: target };
|
|
8260
8476
|
}
|
|
@@ -8582,9 +8798,9 @@ async function handleItemRoute(req, res, pathname) {
|
|
|
8582
8798
|
}
|
|
8583
8799
|
|
|
8584
8800
|
// src/commands/sessions/web/execGit.ts
|
|
8585
|
-
import { execFile as
|
|
8801
|
+
import { execFile as execFile3 } from "child_process";
|
|
8586
8802
|
import { promisify as promisify2 } from "util";
|
|
8587
|
-
var execFileAsync2 = promisify2(
|
|
8803
|
+
var execFileAsync2 = promisify2(execFile3);
|
|
8588
8804
|
async function execGit(cwd, args, opts = {}) {
|
|
8589
8805
|
const { maxBuffer, allowFailure } = opts;
|
|
8590
8806
|
const { file, argv } = /^[A-Za-z]:[\\/]/.test(cwd) ? { file: "git.exe", argv: ["-C", cwd, ...args] } : { file: "git", argv: args };
|
|
@@ -8719,6 +8935,39 @@ async function getBackups(_req, res) {
|
|
|
8719
8935
|
respondJson(res, 200, await listBackups(await getDb()));
|
|
8720
8936
|
}
|
|
8721
8937
|
|
|
8938
|
+
// src/commands/config/getNestedValue.ts
|
|
8939
|
+
function isTraversable(value) {
|
|
8940
|
+
return value !== null && value !== void 0 && typeof value === "object";
|
|
8941
|
+
}
|
|
8942
|
+
function stepInto(current, key) {
|
|
8943
|
+
return isTraversable(current) ? current[key] : void 0;
|
|
8944
|
+
}
|
|
8945
|
+
function getNestedValue(obj, path71) {
|
|
8946
|
+
let current = obj;
|
|
8947
|
+
for (const key of path71.split(".")) current = stepInto(current, key);
|
|
8948
|
+
return current;
|
|
8949
|
+
}
|
|
8950
|
+
|
|
8951
|
+
// src/commands/config/readConfigEntries.ts
|
|
8952
|
+
var KEYS_STRIPPED_FROM_MERGED_CONFIG = /* @__PURE__ */ new Set(["repos"]);
|
|
8953
|
+
function readConfigEntries(cwd) {
|
|
8954
|
+
const config = loadConfigFrom(cwd);
|
|
8955
|
+
return describeConfigLeaves(assistConfigSchema).filter((leaf) => !KEYS_STRIPPED_FROM_MERGED_CONFIG.has(leaf.key)).map((leaf) => ({ ...leaf, value: getNestedValue(config, leaf.key) }));
|
|
8956
|
+
}
|
|
8957
|
+
|
|
8958
|
+
// src/commands/sessions/web/getConfig.ts
|
|
8959
|
+
function getConfig(req, res) {
|
|
8960
|
+
const cwd = getCwdParam(req, res);
|
|
8961
|
+
if (!cwd) return;
|
|
8962
|
+
try {
|
|
8963
|
+
respondJson(res, 200, readConfigEntries(cwd));
|
|
8964
|
+
} catch (error) {
|
|
8965
|
+
respondJson(res, 500, {
|
|
8966
|
+
error: error instanceof Error ? error.message : "Failed to read config"
|
|
8967
|
+
});
|
|
8968
|
+
}
|
|
8969
|
+
}
|
|
8970
|
+
|
|
8722
8971
|
// src/commands/sessions/web/getHtml.ts
|
|
8723
8972
|
function getHtml() {
|
|
8724
8973
|
return `<!DOCTYPE html>
|
|
@@ -8768,26 +9017,26 @@ function handleServerRuns(req, res) {
|
|
|
8768
9017
|
}
|
|
8769
9018
|
|
|
8770
9019
|
// src/commands/sessions/web/getReviewSynthesis.ts
|
|
8771
|
-
import { execFile as
|
|
8772
|
-
import { readFileSync as
|
|
8773
|
-
import { homedir as
|
|
8774
|
-
import { basename as basename6, join as
|
|
9020
|
+
import { execFile as execFile4 } from "child_process";
|
|
9021
|
+
import { readFileSync as readFileSync20 } from "fs";
|
|
9022
|
+
import { homedir as homedir12 } from "os";
|
|
9023
|
+
import { basename as basename6, join as join26 } from "path";
|
|
8775
9024
|
import { promisify as promisify3 } from "util";
|
|
8776
9025
|
|
|
8777
9026
|
// src/commands/sessions/web/findSynthesisForBranch.ts
|
|
8778
|
-
import { existsSync as
|
|
8779
|
-
import { basename as basename5, dirname as dirname20, join as
|
|
9027
|
+
import { existsSync as existsSync27, readdirSync as readdirSync2, statSync as statSync3 } from "fs";
|
|
9028
|
+
import { basename as basename5, dirname as dirname20, join as join25 } from "path";
|
|
8780
9029
|
function findSynthesisForBranch(repoReviewsDir, branch2) {
|
|
8781
|
-
const branchKeyPath =
|
|
9030
|
+
const branchKeyPath = join25(repoReviewsDir, `${branch2}-`);
|
|
8782
9031
|
const parent = dirname20(branchKeyPath);
|
|
8783
9032
|
const branchPrefix = basename5(branchKeyPath);
|
|
8784
|
-
if (!
|
|
8785
|
-
const synthesisFiles = readdirSync2(parent).filter((name) => name.startsWith(branchPrefix)).map((name) =>
|
|
9033
|
+
if (!existsSync27(parent)) return null;
|
|
9034
|
+
const synthesisFiles = readdirSync2(parent).filter((name) => name.startsWith(branchPrefix)).map((name) => join25(parent, name, "synthesis.md")).filter((path71) => existsSync27(path71)).map((path71) => ({ path: path71, mtime: statSync3(path71).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
|
|
8786
9035
|
return synthesisFiles[0]?.path ?? null;
|
|
8787
9036
|
}
|
|
8788
9037
|
|
|
8789
9038
|
// src/commands/sessions/web/getReviewSynthesis.ts
|
|
8790
|
-
var execFileAsync3 = promisify3(
|
|
9039
|
+
var execFileAsync3 = promisify3(execFile4);
|
|
8791
9040
|
function runGit(cwd, args) {
|
|
8792
9041
|
return execFileAsync3("git", args, {
|
|
8793
9042
|
encoding: "utf8",
|
|
@@ -8799,8 +9048,8 @@ async function resolveSynthesisPath(cwd) {
|
|
|
8799
9048
|
runGit(cwd, ["rev-parse", "--show-toplevel"]),
|
|
8800
9049
|
runGit(cwd, ["rev-parse", "--abbrev-ref", "HEAD"])
|
|
8801
9050
|
]);
|
|
8802
|
-
const repoReviewsDir =
|
|
8803
|
-
|
|
9051
|
+
const repoReviewsDir = join26(
|
|
9052
|
+
homedir12(),
|
|
8804
9053
|
".assist",
|
|
8805
9054
|
"reviews",
|
|
8806
9055
|
basename6(repoRoot)
|
|
@@ -8816,7 +9065,7 @@ async function getReviewSynthesis(req, res) {
|
|
|
8816
9065
|
respondJson(res, 404, { error: "No synthesis found" });
|
|
8817
9066
|
return;
|
|
8818
9067
|
}
|
|
8819
|
-
respondJson(res, 200, { synthesis:
|
|
9068
|
+
respondJson(res, 200, { synthesis: readFileSync20(path71, "utf8") });
|
|
8820
9069
|
} catch {
|
|
8821
9070
|
respondJson(res, 404, { error: "No synthesis found" });
|
|
8822
9071
|
}
|
|
@@ -8944,35 +9193,6 @@ function harnessCapabilities(_req, res) {
|
|
|
8944
9193
|
respondJson(res, 200, { exposeCodexActions, exposePiActions });
|
|
8945
9194
|
}
|
|
8946
9195
|
|
|
8947
|
-
// src/shared/loadJson.ts
|
|
8948
|
-
import { existsSync as existsSync27, mkdirSync as mkdirSync11, readFileSync as readFileSync20, writeFileSync as writeFileSync20 } from "fs";
|
|
8949
|
-
import { homedir as homedir13 } from "os";
|
|
8950
|
-
import { join as join27 } from "path";
|
|
8951
|
-
function getStoreDir() {
|
|
8952
|
-
return join27(homedir13(), ".assist");
|
|
8953
|
-
}
|
|
8954
|
-
function getStorePath(filename) {
|
|
8955
|
-
return join27(getStoreDir(), filename);
|
|
8956
|
-
}
|
|
8957
|
-
function loadJson(filename) {
|
|
8958
|
-
const path71 = getStorePath(filename);
|
|
8959
|
-
if (existsSync27(path71)) {
|
|
8960
|
-
try {
|
|
8961
|
-
return JSON.parse(readFileSync20(path71, "utf8"));
|
|
8962
|
-
} catch {
|
|
8963
|
-
return {};
|
|
8964
|
-
}
|
|
8965
|
-
}
|
|
8966
|
-
return {};
|
|
8967
|
-
}
|
|
8968
|
-
function saveJson(filename, data) {
|
|
8969
|
-
const dir = getStoreDir();
|
|
8970
|
-
if (!existsSync27(dir)) {
|
|
8971
|
-
mkdirSync11(dir, { recursive: true });
|
|
8972
|
-
}
|
|
8973
|
-
writeFileSync20(getStorePath(filename), JSON.stringify(data, null, 2));
|
|
8974
|
-
}
|
|
8975
|
-
|
|
8976
9196
|
// src/commands/sessions/web/jiraSite.ts
|
|
8977
9197
|
function jiraSite(_req, res) {
|
|
8978
9198
|
const config = loadJson("jira.json");
|
|
@@ -9251,17 +9471,17 @@ async function openInCode(req, res) {
|
|
|
9251
9471
|
}
|
|
9252
9472
|
|
|
9253
9473
|
// src/commands/sessions/web/createCachedGhJson.ts
|
|
9254
|
-
import { execFile as
|
|
9474
|
+
import { execFile as execFile5 } from "child_process";
|
|
9255
9475
|
import { promisify as promisify5 } from "util";
|
|
9256
|
-
var execFileAsync4 = promisify5(
|
|
9476
|
+
var execFileAsync4 = promisify5(execFile5);
|
|
9257
9477
|
var CACHE_TTL_MS2 = 3e4;
|
|
9258
9478
|
function createCachedGhJson(args, parse3, fallback, options2 = {}) {
|
|
9259
9479
|
const { cacheFallback = true } = options2;
|
|
9260
|
-
const
|
|
9480
|
+
const cache3 = /* @__PURE__ */ new Map();
|
|
9261
9481
|
return async (cwd, extraArgs = []) => {
|
|
9262
9482
|
const key = extraArgs.length ? `${cwd}\0${extraArgs.join("\0")}` : cwd;
|
|
9263
9483
|
const now = Date.now();
|
|
9264
|
-
const cached =
|
|
9484
|
+
const cached = cache3.get(key);
|
|
9265
9485
|
if (cached && cached.expires > now) return cached.value;
|
|
9266
9486
|
let value = fallback;
|
|
9267
9487
|
try {
|
|
@@ -9274,7 +9494,7 @@ function createCachedGhJson(args, parse3, fallback, options2 = {}) {
|
|
|
9274
9494
|
value = fallback;
|
|
9275
9495
|
}
|
|
9276
9496
|
if (cacheFallback || value !== fallback)
|
|
9277
|
-
|
|
9497
|
+
cache3.set(key, { value, expires: now + CACHE_TTL_MS2 });
|
|
9278
9498
|
return value;
|
|
9279
9499
|
};
|
|
9280
9500
|
}
|
|
@@ -9309,9 +9529,9 @@ async function prList(req, res) {
|
|
|
9309
9529
|
}
|
|
9310
9530
|
|
|
9311
9531
|
// src/commands/sessions/web/prStatus.ts
|
|
9312
|
-
import { execFile as
|
|
9532
|
+
import { execFile as execFile6 } from "child_process";
|
|
9313
9533
|
import { promisify as promisify6 } from "util";
|
|
9314
|
-
var execFileAsync5 = promisify6(
|
|
9534
|
+
var execFileAsync5 = promisify6(execFile6);
|
|
9315
9535
|
function toPrSummary(parsed) {
|
|
9316
9536
|
if (typeof parsed.number !== "number") return null;
|
|
9317
9537
|
return {
|
|
@@ -9468,13 +9688,198 @@ async function restartWeb(req, res, deps2 = {}) {
|
|
|
9468
9688
|
}
|
|
9469
9689
|
}
|
|
9470
9690
|
|
|
9691
|
+
// src/commands/config/setNestedValue.ts
|
|
9692
|
+
function isPlainObject(val) {
|
|
9693
|
+
return val !== null && typeof val === "object" && !Array.isArray(val);
|
|
9694
|
+
}
|
|
9695
|
+
function isNumericKey(key) {
|
|
9696
|
+
return /^\d+$/.test(key);
|
|
9697
|
+
}
|
|
9698
|
+
function resolveKey(key) {
|
|
9699
|
+
return isNumericKey(key) ? Number.parseInt(key, 10) : key;
|
|
9700
|
+
}
|
|
9701
|
+
function getItem(container, key) {
|
|
9702
|
+
if (Array.isArray(container)) return container[key];
|
|
9703
|
+
return container[key];
|
|
9704
|
+
}
|
|
9705
|
+
function setItem(container, key, value) {
|
|
9706
|
+
if (Array.isArray(container)) container[key] = value;
|
|
9707
|
+
else container[key] = value;
|
|
9708
|
+
}
|
|
9709
|
+
function ensureArray(container, key) {
|
|
9710
|
+
const existing = getItem(container, key);
|
|
9711
|
+
const arr = Array.isArray(existing) ? [...existing] : [];
|
|
9712
|
+
setItem(container, key, arr);
|
|
9713
|
+
return arr;
|
|
9714
|
+
}
|
|
9715
|
+
function ensureObject(container, key) {
|
|
9716
|
+
const existing = getItem(container, key);
|
|
9717
|
+
const obj = isPlainObject(existing) ? { ...existing } : {};
|
|
9718
|
+
setItem(container, key, obj);
|
|
9719
|
+
return obj;
|
|
9720
|
+
}
|
|
9721
|
+
function stepIntoNested(container, key, nextKey) {
|
|
9722
|
+
const resolved = resolveKey(key);
|
|
9723
|
+
if (nextKey !== void 0 && isNumericKey(nextKey)) {
|
|
9724
|
+
return ensureArray(container, resolved);
|
|
9725
|
+
}
|
|
9726
|
+
return ensureObject(container, resolved);
|
|
9727
|
+
}
|
|
9728
|
+
function setNestedValue(obj, path71, value) {
|
|
9729
|
+
const keys = path71.split(".");
|
|
9730
|
+
const result = { ...obj };
|
|
9731
|
+
let current = result;
|
|
9732
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
9733
|
+
current = stepIntoNested(current, keys[i], keys[i + 1]);
|
|
9734
|
+
}
|
|
9735
|
+
setItem(current, resolveKey(keys[keys.length - 1]), value);
|
|
9736
|
+
return result;
|
|
9737
|
+
}
|
|
9738
|
+
|
|
9739
|
+
// src/commands/config/validateConfig.ts
|
|
9740
|
+
function validateConfig(updated, key) {
|
|
9741
|
+
const result = assistConfigSchema.safeParse(updated);
|
|
9742
|
+
if (result.success) return { ok: true };
|
|
9743
|
+
return {
|
|
9744
|
+
ok: false,
|
|
9745
|
+
errors: result.error.issues.map((issue) => formatIssue(issue, key))
|
|
9746
|
+
};
|
|
9747
|
+
}
|
|
9748
|
+
function formatIssue(issue, key) {
|
|
9749
|
+
const path71 = issue.path.length > 0 ? issue.path.join(".") : key;
|
|
9750
|
+
return `${path71}: ${issue.message}`;
|
|
9751
|
+
}
|
|
9752
|
+
|
|
9753
|
+
// src/commands/config/applyConfigSet.ts
|
|
9754
|
+
var GLOBAL_ONLY_KEYS = ["sync.autoConfirm"];
|
|
9755
|
+
function applyConfigSet(key, coerced, global, cwd = process.cwd()) {
|
|
9756
|
+
if (!global && isGlobalOnly(key)) {
|
|
9757
|
+
return {
|
|
9758
|
+
ok: false,
|
|
9759
|
+
errors: [
|
|
9760
|
+
`"${key}" is a global-only key. Use --global to set it in ~/.assist.yml`
|
|
9761
|
+
]
|
|
9762
|
+
};
|
|
9763
|
+
}
|
|
9764
|
+
const raw = global ? loadGlobalConfigRaw() : loadProjectConfig(cwd);
|
|
9765
|
+
const updated = setNestedValue(raw, key, coerced);
|
|
9766
|
+
const validation = validateConfig(updated, key);
|
|
9767
|
+
if (!validation.ok) return validation;
|
|
9768
|
+
if (global) {
|
|
9769
|
+
saveGlobalConfig(updated);
|
|
9770
|
+
return { ok: true, target: "global" };
|
|
9771
|
+
}
|
|
9772
|
+
saveConfig(updated, cwd);
|
|
9773
|
+
return { ok: true, target: "project" };
|
|
9774
|
+
}
|
|
9775
|
+
function isGlobalOnly(key) {
|
|
9776
|
+
return GLOBAL_ONLY_KEYS.some((k) => key.startsWith(k));
|
|
9777
|
+
}
|
|
9778
|
+
|
|
9779
|
+
// src/commands/config/coerceConfigValue.ts
|
|
9780
|
+
var EDITABLE_TYPES = /* @__PURE__ */ new Set(["string", "number", "boolean", "enum"]);
|
|
9781
|
+
function coerceConfigValue(key, raw) {
|
|
9782
|
+
const leaf = describeConfigLeaves(assistConfigSchema).find(
|
|
9783
|
+
(candidate) => candidate.key === key
|
|
9784
|
+
);
|
|
9785
|
+
if (!leaf) return { ok: false, error: `Unknown config key "${key}"` };
|
|
9786
|
+
if (!EDITABLE_TYPES.has(leaf.type)) {
|
|
9787
|
+
return {
|
|
9788
|
+
ok: false,
|
|
9789
|
+
error: `"${key}" is a ${leaf.type} value and is read-only here`
|
|
9790
|
+
};
|
|
9791
|
+
}
|
|
9792
|
+
if (leaf.type === "boolean") return coerceBoolean(key, raw);
|
|
9793
|
+
if (leaf.type === "number") return coerceNumber(key, raw);
|
|
9794
|
+
return coerceString(key, raw);
|
|
9795
|
+
}
|
|
9796
|
+
function coerceBoolean(key, raw) {
|
|
9797
|
+
if (typeof raw === "boolean") return { ok: true, value: raw };
|
|
9798
|
+
if (raw === "true") return { ok: true, value: true };
|
|
9799
|
+
if (raw === "false") return { ok: true, value: false };
|
|
9800
|
+
return { ok: false, error: `${key}: expected a boolean` };
|
|
9801
|
+
}
|
|
9802
|
+
function coerceNumber(key, raw) {
|
|
9803
|
+
if (typeof raw === "number" && Number.isFinite(raw)) {
|
|
9804
|
+
return { ok: true, value: raw };
|
|
9805
|
+
}
|
|
9806
|
+
if (typeof raw === "string" && raw.trim() !== "") {
|
|
9807
|
+
const parsed = Number(raw);
|
|
9808
|
+
if (Number.isFinite(parsed)) return { ok: true, value: parsed };
|
|
9809
|
+
}
|
|
9810
|
+
return { ok: false, error: `${key}: expected a number` };
|
|
9811
|
+
}
|
|
9812
|
+
function coerceString(key, raw) {
|
|
9813
|
+
if (typeof raw === "string") return { ok: true, value: raw };
|
|
9814
|
+
return { ok: false, error: `${key}: expected a string` };
|
|
9815
|
+
}
|
|
9816
|
+
|
|
9817
|
+
// src/commands/sessions/web/readJsonBody.ts
|
|
9818
|
+
async function readJsonBody(req) {
|
|
9819
|
+
const chunks = [];
|
|
9820
|
+
for await (const chunk of req) chunks.push(chunk);
|
|
9821
|
+
return JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
9822
|
+
}
|
|
9823
|
+
|
|
9824
|
+
// src/commands/sessions/web/parseSetConfigRequest.ts
|
|
9825
|
+
async function parseSetConfigRequest(req) {
|
|
9826
|
+
let body;
|
|
9827
|
+
try {
|
|
9828
|
+
body = await readJsonBody(req);
|
|
9829
|
+
} catch {
|
|
9830
|
+
return { ok: false, error: "Invalid JSON body" };
|
|
9831
|
+
}
|
|
9832
|
+
const { key, cwd, scope } = body;
|
|
9833
|
+
if (typeof key !== "string" || key === "")
|
|
9834
|
+
return { ok: false, error: "Missing key" };
|
|
9835
|
+
if (typeof cwd !== "string" || cwd === "")
|
|
9836
|
+
return { ok: false, error: "Missing cwd" };
|
|
9837
|
+
if (scope !== "project" && scope !== "global")
|
|
9838
|
+
return { ok: false, error: 'scope must be "project" or "global"' };
|
|
9839
|
+
return { ok: true, key, value: body.value, cwd, global: scope === "global" };
|
|
9840
|
+
}
|
|
9841
|
+
|
|
9842
|
+
// src/commands/sessions/web/setConfig.ts
|
|
9843
|
+
async function setConfig(req, res) {
|
|
9844
|
+
const parsed = await parseSetConfigRequest(req);
|
|
9845
|
+
if (!parsed.ok) {
|
|
9846
|
+
respondJson(res, 400, { error: parsed.error });
|
|
9847
|
+
return;
|
|
9848
|
+
}
|
|
9849
|
+
const coerced = coerceConfigValue(parsed.key, parsed.value);
|
|
9850
|
+
if (!coerced.ok) {
|
|
9851
|
+
respondJson(res, 400, { error: coerced.error, errors: [coerced.error] });
|
|
9852
|
+
return;
|
|
9853
|
+
}
|
|
9854
|
+
try {
|
|
9855
|
+
const result = applyConfigSet(
|
|
9856
|
+
parsed.key,
|
|
9857
|
+
coerced.value,
|
|
9858
|
+
parsed.global,
|
|
9859
|
+
parsed.cwd
|
|
9860
|
+
);
|
|
9861
|
+
if (!result.ok) {
|
|
9862
|
+
respondJson(res, 400, {
|
|
9863
|
+
error: result.errors.join("\n"),
|
|
9864
|
+
errors: result.errors
|
|
9865
|
+
});
|
|
9866
|
+
return;
|
|
9867
|
+
}
|
|
9868
|
+
respondJson(res, 200, { target: result.target });
|
|
9869
|
+
} catch (error) {
|
|
9870
|
+
respondJson(res, 500, {
|
|
9871
|
+
error: error instanceof Error ? error.message : "Failed to save config"
|
|
9872
|
+
});
|
|
9873
|
+
}
|
|
9874
|
+
}
|
|
9875
|
+
|
|
9471
9876
|
// src/commands/sessions/web/uploadPrImage.ts
|
|
9472
9877
|
import { rm } from "fs/promises";
|
|
9473
9878
|
|
|
9474
9879
|
// src/commands/sessions/web/runGhImage.ts
|
|
9475
|
-
import { execFile as
|
|
9880
|
+
import { execFile as execFile7 } from "child_process";
|
|
9476
9881
|
import { promisify as promisify7 } from "util";
|
|
9477
|
-
var execFileAsync6 = promisify7(
|
|
9882
|
+
var execFileAsync6 = promisify7(execFile7);
|
|
9478
9883
|
var GhImageUnavailableError = class extends Error {
|
|
9479
9884
|
name = "GhImageUnavailableError";
|
|
9480
9885
|
};
|
|
@@ -9600,22 +10005,22 @@ import { readFileSync as readFileSync21 } from "fs";
|
|
|
9600
10005
|
import { createRequire as createRequire2 } from "module";
|
|
9601
10006
|
var require3 = createRequire2(import.meta.url);
|
|
9602
10007
|
function createCssHandler(packageEntry) {
|
|
9603
|
-
let
|
|
10008
|
+
let cache3;
|
|
9604
10009
|
return (req, res) => {
|
|
9605
|
-
if (!
|
|
10010
|
+
if (!cache3) {
|
|
9606
10011
|
const resolved = require3.resolve(packageEntry);
|
|
9607
10012
|
const body = readFileSync21(resolved, "utf8");
|
|
9608
10013
|
const etag = `"${createHash2("sha256").update(body).digest("hex").slice(0, 16)}"`;
|
|
9609
|
-
|
|
10014
|
+
cache3 = { body, etag };
|
|
9610
10015
|
}
|
|
9611
|
-
const headers = { ETag:
|
|
9612
|
-
if (req.headers["if-none-match"] ===
|
|
10016
|
+
const headers = { ETag: cache3.etag, "Cache-Control": "no-cache" };
|
|
10017
|
+
if (req.headers["if-none-match"] === cache3.etag) {
|
|
9613
10018
|
res.writeHead(304, headers);
|
|
9614
10019
|
res.end();
|
|
9615
10020
|
return;
|
|
9616
10021
|
}
|
|
9617
10022
|
res.writeHead(200, { "Content-Type": "text/css", ...headers });
|
|
9618
|
-
res.end(
|
|
10023
|
+
res.end(cache3.body);
|
|
9619
10024
|
};
|
|
9620
10025
|
}
|
|
9621
10026
|
|
|
@@ -9651,6 +10056,8 @@ var routes2 = {
|
|
|
9651
10056
|
"GET /api/news/items": listNewsItems,
|
|
9652
10057
|
"GET /api/usage/history": listUsageHistory,
|
|
9653
10058
|
"GET /api/backups/list": getBackups,
|
|
10059
|
+
"GET /api/config": getConfig,
|
|
10060
|
+
"POST /api/config/set": setConfig,
|
|
9654
10061
|
"GET /api/review/synthesis": getReviewSynthesis
|
|
9655
10062
|
};
|
|
9656
10063
|
var handleRequest = createFallbackHandler(
|
|
@@ -9992,6 +10399,9 @@ function scheduleReconnect() {
|
|
|
9992
10399
|
}
|
|
9993
10400
|
|
|
9994
10401
|
// src/commands/sessions/web/index.ts
|
|
10402
|
+
function repoEntryCwd(serverCwd) {
|
|
10403
|
+
return repoGroupForCwd(serverCwd)?.clone ?? serverCwd;
|
|
10404
|
+
}
|
|
9995
10405
|
async function web(options2) {
|
|
9996
10406
|
const port = Number.parseInt(options2.port, 10);
|
|
9997
10407
|
const server = startWebServer(
|
|
@@ -10004,7 +10414,7 @@ async function web(options2) {
|
|
|
10004
10414
|
const serverCwd = process.cwd();
|
|
10005
10415
|
const ctx = {
|
|
10006
10416
|
serverCwd,
|
|
10007
|
-
repoCwd: isGitRepo(serverCwd) ? serverCwd : void 0
|
|
10417
|
+
repoCwd: isGitRepo(serverCwd) ? repoEntryCwd(serverCwd) : void 0
|
|
10008
10418
|
};
|
|
10009
10419
|
const wss = new WebSocketServer({ noServer: true });
|
|
10010
10420
|
server.on("upgrade", (req, socket, head) => {
|
|
@@ -14296,7 +14706,7 @@ function formatResultLine(entry, failing) {
|
|
|
14296
14706
|
// src/commands/complexity/maintainability/getMaintainabilityGitState.ts
|
|
14297
14707
|
import { execSync as execSync32 } from "child_process";
|
|
14298
14708
|
import path28 from "path";
|
|
14299
|
-
function
|
|
14709
|
+
function git3(command) {
|
|
14300
14710
|
return execSync32(command, { encoding: "utf8" });
|
|
14301
14711
|
}
|
|
14302
14712
|
function toAbsolute(root, repoRelative) {
|
|
@@ -14304,7 +14714,7 @@ function toAbsolute(root, repoRelative) {
|
|
|
14304
14714
|
}
|
|
14305
14715
|
function collectShrunkFiles(root) {
|
|
14306
14716
|
const shrunk = /* @__PURE__ */ new Set();
|
|
14307
|
-
const numstat =
|
|
14717
|
+
const numstat = git3("git diff --numstat HEAD").trim();
|
|
14308
14718
|
if (numstat === "") return shrunk;
|
|
14309
14719
|
for (const line of numstat.split("\n")) {
|
|
14310
14720
|
const [addedRaw, removedRaw, ...rest] = line.split(" ");
|
|
@@ -14317,7 +14727,7 @@ function collectShrunkFiles(root) {
|
|
|
14317
14727
|
return shrunk;
|
|
14318
14728
|
}
|
|
14319
14729
|
function hasNewSourceFile() {
|
|
14320
|
-
const status3 =
|
|
14730
|
+
const status3 = git3("git status --porcelain --untracked-files=all").trim();
|
|
14321
14731
|
if (status3 === "") return false;
|
|
14322
14732
|
for (const line of status3.split("\n")) {
|
|
14323
14733
|
const code = line.slice(0, 2);
|
|
@@ -14329,7 +14739,7 @@ function hasNewSourceFile() {
|
|
|
14329
14739
|
}
|
|
14330
14740
|
function getMaintainabilityGitState() {
|
|
14331
14741
|
try {
|
|
14332
|
-
const root =
|
|
14742
|
+
const root = git3("git rev-parse --show-toplevel").trim();
|
|
14333
14743
|
return {
|
|
14334
14744
|
shrunkFiles: collectShrunkFiles(root),
|
|
14335
14745
|
newFileCreated: hasNewSourceFile()
|
|
@@ -14525,21 +14935,6 @@ function configList() {
|
|
|
14525
14935
|
|
|
14526
14936
|
// src/commands/config/configGet.ts
|
|
14527
14937
|
import chalk127 from "chalk";
|
|
14528
|
-
|
|
14529
|
-
// src/commands/config/getNestedValue.ts
|
|
14530
|
-
function isTraversable(value) {
|
|
14531
|
-
return value !== null && value !== void 0 && typeof value === "object";
|
|
14532
|
-
}
|
|
14533
|
-
function stepInto(current, key) {
|
|
14534
|
-
return isTraversable(current) ? current[key] : void 0;
|
|
14535
|
-
}
|
|
14536
|
-
function getNestedValue(obj, path71) {
|
|
14537
|
-
let current = obj;
|
|
14538
|
-
for (const key of path71.split(".")) current = stepInto(current, key);
|
|
14539
|
-
return current;
|
|
14540
|
-
}
|
|
14541
|
-
|
|
14542
|
-
// src/commands/config/configGet.ts
|
|
14543
14938
|
function configGet(key) {
|
|
14544
14939
|
console.log(
|
|
14545
14940
|
formatOutput(
|
|
@@ -14561,106 +14956,8 @@ function exitKeyNotSet(key) {
|
|
|
14561
14956
|
}
|
|
14562
14957
|
|
|
14563
14958
|
// src/commands/config/configSet.ts
|
|
14564
|
-
import chalk130 from "chalk";
|
|
14565
|
-
|
|
14566
|
-
// src/commands/config/applyConfigSet.ts
|
|
14567
14959
|
import chalk129 from "chalk";
|
|
14568
14960
|
|
|
14569
|
-
// src/commands/config/setNestedValue.ts
|
|
14570
|
-
function isPlainObject(val) {
|
|
14571
|
-
return val !== null && typeof val === "object" && !Array.isArray(val);
|
|
14572
|
-
}
|
|
14573
|
-
function isNumericKey(key) {
|
|
14574
|
-
return /^\d+$/.test(key);
|
|
14575
|
-
}
|
|
14576
|
-
function resolveKey(key) {
|
|
14577
|
-
return isNumericKey(key) ? Number.parseInt(key, 10) : key;
|
|
14578
|
-
}
|
|
14579
|
-
function getItem(container, key) {
|
|
14580
|
-
if (Array.isArray(container)) return container[key];
|
|
14581
|
-
return container[key];
|
|
14582
|
-
}
|
|
14583
|
-
function setItem(container, key, value) {
|
|
14584
|
-
if (Array.isArray(container)) container[key] = value;
|
|
14585
|
-
else container[key] = value;
|
|
14586
|
-
}
|
|
14587
|
-
function ensureArray(container, key) {
|
|
14588
|
-
const existing = getItem(container, key);
|
|
14589
|
-
const arr = Array.isArray(existing) ? [...existing] : [];
|
|
14590
|
-
setItem(container, key, arr);
|
|
14591
|
-
return arr;
|
|
14592
|
-
}
|
|
14593
|
-
function ensureObject(container, key) {
|
|
14594
|
-
const existing = getItem(container, key);
|
|
14595
|
-
const obj = isPlainObject(existing) ? { ...existing } : {};
|
|
14596
|
-
setItem(container, key, obj);
|
|
14597
|
-
return obj;
|
|
14598
|
-
}
|
|
14599
|
-
function stepIntoNested(container, key, nextKey) {
|
|
14600
|
-
const resolved = resolveKey(key);
|
|
14601
|
-
if (nextKey !== void 0 && isNumericKey(nextKey)) {
|
|
14602
|
-
return ensureArray(container, resolved);
|
|
14603
|
-
}
|
|
14604
|
-
return ensureObject(container, resolved);
|
|
14605
|
-
}
|
|
14606
|
-
function setNestedValue(obj, path71, value) {
|
|
14607
|
-
const keys = path71.split(".");
|
|
14608
|
-
const result = { ...obj };
|
|
14609
|
-
let current = result;
|
|
14610
|
-
for (let i = 0; i < keys.length - 1; i++) {
|
|
14611
|
-
current = stepIntoNested(current, keys[i], keys[i + 1]);
|
|
14612
|
-
}
|
|
14613
|
-
setItem(current, resolveKey(keys[keys.length - 1]), value);
|
|
14614
|
-
return result;
|
|
14615
|
-
}
|
|
14616
|
-
|
|
14617
|
-
// src/commands/config/validateConfig.ts
|
|
14618
|
-
import chalk128 from "chalk";
|
|
14619
|
-
function validateConfig(updated, key) {
|
|
14620
|
-
const result = assistConfigSchema.safeParse(updated);
|
|
14621
|
-
if (!result.success) return exitValidationFailed(result.error.issues, key);
|
|
14622
|
-
return updated;
|
|
14623
|
-
}
|
|
14624
|
-
function exitValidationFailed(issues, key) {
|
|
14625
|
-
printValidationErrors(issues, key);
|
|
14626
|
-
process.exit(1);
|
|
14627
|
-
}
|
|
14628
|
-
function printValidationErrors(issues, key) {
|
|
14629
|
-
for (const issue of issues) {
|
|
14630
|
-
console.error(
|
|
14631
|
-
chalk128.red(`${formatIssuePath(issue, key)}: ${issue.message}`)
|
|
14632
|
-
);
|
|
14633
|
-
}
|
|
14634
|
-
}
|
|
14635
|
-
function formatIssuePath(issue, key) {
|
|
14636
|
-
return issue.path.length > 0 ? issue.path.join(".") : key;
|
|
14637
|
-
}
|
|
14638
|
-
|
|
14639
|
-
// src/commands/config/applyConfigSet.ts
|
|
14640
|
-
var GLOBAL_ONLY_KEYS = ["sync.autoConfirm"];
|
|
14641
|
-
function applyConfigSet(key, coerced, global) {
|
|
14642
|
-
assertNotGlobalOnly(key, global);
|
|
14643
|
-
const raw = global ? loadGlobalConfigRaw() : loadProjectConfig();
|
|
14644
|
-
const updated = setNestedValue(raw, key, coerced);
|
|
14645
|
-
validateConfig(updated, key);
|
|
14646
|
-
if (global) {
|
|
14647
|
-
saveGlobalConfig(updated);
|
|
14648
|
-
return "global";
|
|
14649
|
-
}
|
|
14650
|
-
saveConfig(updated);
|
|
14651
|
-
return "project";
|
|
14652
|
-
}
|
|
14653
|
-
function assertNotGlobalOnly(key, global) {
|
|
14654
|
-
if (!global && GLOBAL_ONLY_KEYS.some((k) => key.startsWith(k))) {
|
|
14655
|
-
console.error(
|
|
14656
|
-
chalk129.red(
|
|
14657
|
-
`"${key}" is a global-only key. Use --global to set it in ~/.assist.yml`
|
|
14658
|
-
)
|
|
14659
|
-
);
|
|
14660
|
-
process.exit(1);
|
|
14661
|
-
}
|
|
14662
|
-
}
|
|
14663
|
-
|
|
14664
14961
|
// src/shared/resolveNamedRepoWriteLabel.ts
|
|
14665
14962
|
var UnknownRepoConfigError = class extends Error {
|
|
14666
14963
|
name = "UnknownRepoConfigError";
|
|
@@ -14683,6 +14980,13 @@ function resolveNamedRepoWriteLabel(globalRaw, name) {
|
|
|
14683
14980
|
return matches[0];
|
|
14684
14981
|
}
|
|
14685
14982
|
|
|
14983
|
+
// src/commands/config/exitWithConfigErrors.ts
|
|
14984
|
+
import chalk128 from "chalk";
|
|
14985
|
+
function exitWithConfigErrors(errors) {
|
|
14986
|
+
for (const error of errors) console.error(chalk128.red(error));
|
|
14987
|
+
process.exit(1);
|
|
14988
|
+
}
|
|
14989
|
+
|
|
14686
14990
|
// src/commands/config/applyRepoConfigSet.ts
|
|
14687
14991
|
function applyRepoConfigSet(key, coerced, repoName) {
|
|
14688
14992
|
const globalRaw = loadGlobalConfigRaw();
|
|
@@ -14690,7 +14994,8 @@ function applyRepoConfigSet(key, coerced, repoName) {
|
|
|
14690
14994
|
const repos2 = isPlainObject2(globalRaw.repos) ? { ...globalRaw.repos } : {};
|
|
14691
14995
|
const existingBlock = isPlainObject2(repos2[label2]) ? repos2[label2] : {};
|
|
14692
14996
|
const updatedBlock = setNestedValue(existingBlock, key, coerced);
|
|
14693
|
-
validateConfig(updatedBlock, key);
|
|
14997
|
+
const validation = validateConfig(updatedBlock, key);
|
|
14998
|
+
if (!validation.ok) exitWithConfigErrors(validation.errors);
|
|
14694
14999
|
repos2[label2] = updatedBlock;
|
|
14695
15000
|
saveGlobalConfig({ ...globalRaw, repos: repos2 });
|
|
14696
15001
|
return label2;
|
|
@@ -14714,21 +15019,26 @@ function resolveRepoTarget(key, value, repo) {
|
|
|
14714
15019
|
function configSet(key, value, options2 = {}) {
|
|
14715
15020
|
if (options2.repo !== void 0 && !options2.global) {
|
|
14716
15021
|
console.error(
|
|
14717
|
-
|
|
15022
|
+
chalk129.red("--repo writes to the global config; add -g (e.g. -g --repo)")
|
|
14718
15023
|
);
|
|
14719
15024
|
process.exit(1);
|
|
14720
15025
|
}
|
|
14721
15026
|
const resolved = resolveRepoTarget(key, value, options2.repo);
|
|
14722
15027
|
if (resolved.value === void 0) {
|
|
14723
|
-
console.error(
|
|
15028
|
+
console.error(chalk129.red(`Missing required argument for '${resolved.key}'`));
|
|
14724
15029
|
process.exit(1);
|
|
14725
15030
|
}
|
|
14726
15031
|
const coerced = coerceValue(resolved.value);
|
|
14727
|
-
const target = resolved.useRepo ? `repo: ${applyRepoConfigSet(resolved.key, coerced, resolved.repoName)}` :
|
|
15032
|
+
const target = resolved.useRepo ? `repo: ${applyRepoConfigSet(resolved.key, coerced, resolved.repoName)}` : applyOrExit(resolved.key, coerced, options2.global ?? false);
|
|
14728
15033
|
console.log(
|
|
14729
|
-
|
|
15034
|
+
chalk129.green(`Set ${resolved.key} = ${JSON.stringify(coerced)} (${target})`)
|
|
14730
15035
|
);
|
|
14731
15036
|
}
|
|
15037
|
+
function applyOrExit(key, coerced, global) {
|
|
15038
|
+
const result = applyConfigSet(key, coerced, global);
|
|
15039
|
+
if (!result.ok) exitWithConfigErrors(result.errors);
|
|
15040
|
+
return result.target;
|
|
15041
|
+
}
|
|
14732
15042
|
function coerceValue(value) {
|
|
14733
15043
|
if (value === "true") return true;
|
|
14734
15044
|
if (value === "false") return false;
|
|
@@ -14747,40 +15057,40 @@ function registerConfig(program2) {
|
|
|
14747
15057
|
}
|
|
14748
15058
|
|
|
14749
15059
|
// src/commands/db/reportMigrationStatus.ts
|
|
14750
|
-
import
|
|
15060
|
+
import chalk130 from "chalk";
|
|
14751
15061
|
function reportApplied(applied) {
|
|
14752
15062
|
if (applied.length === 0) {
|
|
14753
|
-
console.error(
|
|
15063
|
+
console.error(chalk130.green("Database is up to date; nothing to apply."));
|
|
14754
15064
|
return;
|
|
14755
15065
|
}
|
|
14756
15066
|
for (const migration of applied) {
|
|
14757
15067
|
console.error(
|
|
14758
|
-
|
|
15068
|
+
chalk130.green(`Applied migration ${migration.id} (${migration.name}).`)
|
|
14759
15069
|
);
|
|
14760
15070
|
}
|
|
14761
15071
|
}
|
|
14762
15072
|
function reportMigrationStatus(status3) {
|
|
14763
15073
|
if (status3.state === "in-sync") {
|
|
14764
15074
|
console.error(
|
|
14765
|
-
|
|
15075
|
+
chalk130.green(`In sync at migration ${status3.version} (latest).`)
|
|
14766
15076
|
);
|
|
14767
15077
|
return;
|
|
14768
15078
|
}
|
|
14769
15079
|
if (status3.state === "behind") {
|
|
14770
15080
|
console.error(
|
|
14771
|
-
|
|
15081
|
+
chalk130.yellow(
|
|
14772
15082
|
`Behind: applied ${status3.applied}, build expects ${status3.expected}.`
|
|
14773
15083
|
)
|
|
14774
15084
|
);
|
|
14775
15085
|
console.error(
|
|
14776
|
-
|
|
15086
|
+
chalk130.yellow(
|
|
14777
15087
|
`Pending: ${status3.pending.join(", ")}. Run \`assist db migrate\`.`
|
|
14778
15088
|
)
|
|
14779
15089
|
);
|
|
14780
15090
|
return;
|
|
14781
15091
|
}
|
|
14782
15092
|
console.error(
|
|
14783
|
-
|
|
15093
|
+
chalk130.red(
|
|
14784
15094
|
`Ahead: applied ${status3.applied}, build knows ${status3.expected}. Update assist.`
|
|
14785
15095
|
)
|
|
14786
15096
|
);
|
|
@@ -14815,7 +15125,7 @@ function registerDb(program2) {
|
|
|
14815
15125
|
|
|
14816
15126
|
// src/commands/dbMigration/dbMigrationConfirm.ts
|
|
14817
15127
|
import { unlinkSync as unlinkSync9, writeFileSync as writeFileSync26 } from "fs";
|
|
14818
|
-
import
|
|
15128
|
+
import chalk131 from "chalk";
|
|
14819
15129
|
|
|
14820
15130
|
// src/commands/dbMigration/getMigrationPinPath.ts
|
|
14821
15131
|
import { join as join35 } from "path";
|
|
@@ -14846,7 +15156,7 @@ function dbMigrationConfirm(pin) {
|
|
|
14846
15156
|
sweepRestrictedDir();
|
|
14847
15157
|
const state = readMigrationPinState(pin);
|
|
14848
15158
|
if (!state) {
|
|
14849
|
-
console.error(
|
|
15159
|
+
console.error(chalk131.red(`No pending migration unlock for pin: ${pin}`));
|
|
14850
15160
|
process.exitCode = 1;
|
|
14851
15161
|
return;
|
|
14852
15162
|
}
|
|
@@ -14856,7 +15166,7 @@ function dbMigrationConfirm(pin) {
|
|
|
14856
15166
|
);
|
|
14857
15167
|
unlinkSync9(getMigrationPinPath(pin));
|
|
14858
15168
|
console.log(
|
|
14859
|
-
|
|
15169
|
+
chalk131.green(
|
|
14860
15170
|
`Approved creation of migration ${state.migrationId}. The next write of that migration module will be allowed once.`
|
|
14861
15171
|
)
|
|
14862
15172
|
);
|
|
@@ -14865,7 +15175,7 @@ function dbMigrationConfirm(pin) {
|
|
|
14865
15175
|
// src/commands/dbMigration/dbMigrationUnlock.ts
|
|
14866
15176
|
import { mkdirSync as mkdirSync15, writeFileSync as writeFileSync27 } from "fs";
|
|
14867
15177
|
import { randomInt as randomInt2 } from "crypto";
|
|
14868
|
-
import
|
|
15178
|
+
import chalk132 from "chalk";
|
|
14869
15179
|
|
|
14870
15180
|
// src/commands/dbMigration/nextMigrationId.ts
|
|
14871
15181
|
function nextMigrationId() {
|
|
@@ -14880,7 +15190,7 @@ function dbMigrationUnlock() {
|
|
|
14880
15190
|
sweepRestrictedDir();
|
|
14881
15191
|
writeFileSync27(getMigrationPinPath(pin), JSON.stringify({ pin, migrationId }));
|
|
14882
15192
|
console.error(
|
|
14883
|
-
|
|
15193
|
+
chalk132.yellow.bold(
|
|
14884
15194
|
"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."
|
|
14885
15195
|
)
|
|
14886
15196
|
);
|
|
@@ -14890,7 +15200,7 @@ function dbMigrationUnlock() {
|
|
|
14890
15200
|
});
|
|
14891
15201
|
if (!delivered) {
|
|
14892
15202
|
console.error(
|
|
14893
|
-
|
|
15203
|
+
chalk132.red(
|
|
14894
15204
|
"Could not deliver the confirmation pin via notification.\nThe migration cannot be approved until the notification channel works."
|
|
14895
15205
|
)
|
|
14896
15206
|
);
|
|
@@ -14900,7 +15210,7 @@ function dbMigrationUnlock() {
|
|
|
14900
15210
|
console.log(
|
|
14901
15211
|
`A confirmation pin was sent to your desktop notifications.
|
|
14902
15212
|
To approve creating migration ${migrationId}, run:
|
|
14903
|
-
${
|
|
15213
|
+
${chalk132.cyan(" assist db-migration confirm <PIN>")}
|
|
14904
15214
|
using the pin from that notification.`
|
|
14905
15215
|
);
|
|
14906
15216
|
}
|
|
@@ -14920,7 +15230,7 @@ function registerDbMigration(parent) {
|
|
|
14920
15230
|
|
|
14921
15231
|
// src/commands/deploy/redirect.ts
|
|
14922
15232
|
import { existsSync as existsSync35, readFileSync as readFileSync30, writeFileSync as writeFileSync28 } from "fs";
|
|
14923
|
-
import
|
|
15233
|
+
import chalk133 from "chalk";
|
|
14924
15234
|
var TRAILING_SLASH_SCRIPT = ` <script>
|
|
14925
15235
|
if (!window.location.pathname.endsWith('/')) {
|
|
14926
15236
|
window.location.href = \`\${window.location.pathname}/\${window.location.search}\${window.location.hash}\`;
|
|
@@ -14929,23 +15239,23 @@ var TRAILING_SLASH_SCRIPT = ` <script>
|
|
|
14929
15239
|
function redirect() {
|
|
14930
15240
|
const indexPath = "index.html";
|
|
14931
15241
|
if (!existsSync35(indexPath)) {
|
|
14932
|
-
console.log(
|
|
15242
|
+
console.log(chalk133.yellow("No index.html found"));
|
|
14933
15243
|
return;
|
|
14934
15244
|
}
|
|
14935
15245
|
const content = readFileSync30(indexPath, "utf8");
|
|
14936
15246
|
if (content.includes("window.location.pathname.endsWith('/')")) {
|
|
14937
|
-
console.log(
|
|
15247
|
+
console.log(chalk133.dim("Trailing slash script already present"));
|
|
14938
15248
|
return;
|
|
14939
15249
|
}
|
|
14940
15250
|
const headCloseIndex = content.indexOf("</head>");
|
|
14941
15251
|
if (headCloseIndex === -1) {
|
|
14942
|
-
console.log(
|
|
15252
|
+
console.log(chalk133.red("Could not find </head> tag in index.html"));
|
|
14943
15253
|
return;
|
|
14944
15254
|
}
|
|
14945
15255
|
const newContent = `${content.slice(0, headCloseIndex) + TRAILING_SLASH_SCRIPT}
|
|
14946
15256
|
${content.slice(headCloseIndex)}`;
|
|
14947
15257
|
writeFileSync28(indexPath, newContent);
|
|
14948
|
-
console.log(
|
|
15258
|
+
console.log(chalk133.green("Added trailing slash redirect to index.html"));
|
|
14949
15259
|
}
|
|
14950
15260
|
|
|
14951
15261
|
// src/commands/registerDeploy.ts
|
|
@@ -14956,7 +15266,7 @@ function registerDeploy(program2) {
|
|
|
14956
15266
|
}
|
|
14957
15267
|
|
|
14958
15268
|
// src/commands/devlog/list/index.ts
|
|
14959
|
-
import { execFileSync as
|
|
15269
|
+
import { execFileSync as execFileSync3 } from "child_process";
|
|
14960
15270
|
import { basename as basename9 } from "path";
|
|
14961
15271
|
|
|
14962
15272
|
// src/commands/devlog/loadBlogSkipDays.ts
|
|
@@ -14972,7 +15282,7 @@ function loadBlogSkipDays(repoName) {
|
|
|
14972
15282
|
|
|
14973
15283
|
// src/commands/devlog/shared.ts
|
|
14974
15284
|
import { execSync as execSync33 } from "child_process";
|
|
14975
|
-
import
|
|
15285
|
+
import chalk134 from "chalk";
|
|
14976
15286
|
|
|
14977
15287
|
// src/shared/getRepoName.ts
|
|
14978
15288
|
import { existsSync as existsSync36, readFileSync as readFileSync31 } from "fs";
|
|
@@ -15081,13 +15391,13 @@ function shouldIgnoreCommit(files, ignorePaths) {
|
|
|
15081
15391
|
}
|
|
15082
15392
|
function printCommitsWithFiles(commits2, ignore3, verbose) {
|
|
15083
15393
|
for (const commit2 of commits2) {
|
|
15084
|
-
console.log(` ${
|
|
15394
|
+
console.log(` ${chalk134.yellow(commit2.hash)} ${commit2.message}`);
|
|
15085
15395
|
if (verbose) {
|
|
15086
15396
|
const visibleFiles = commit2.files.filter(
|
|
15087
15397
|
(file) => !ignore3.some((p) => file.startsWith(p))
|
|
15088
15398
|
);
|
|
15089
15399
|
for (const file of visibleFiles) {
|
|
15090
|
-
console.log(` ${
|
|
15400
|
+
console.log(` ${chalk134.dim(file)}`);
|
|
15091
15401
|
}
|
|
15092
15402
|
}
|
|
15093
15403
|
}
|
|
@@ -15112,15 +15422,15 @@ function parseGitLogCommits(output, ignore3, afterDate) {
|
|
|
15112
15422
|
}
|
|
15113
15423
|
|
|
15114
15424
|
// src/commands/devlog/list/printDateHeader.ts
|
|
15115
|
-
import
|
|
15425
|
+
import chalk135 from "chalk";
|
|
15116
15426
|
function printDateHeader(date, isSkipped, entries) {
|
|
15117
15427
|
if (isSkipped) {
|
|
15118
|
-
console.log(`${
|
|
15428
|
+
console.log(`${chalk135.bold.blue(date)} ${chalk135.dim("skipped")}`);
|
|
15119
15429
|
} else if (entries && entries.length > 0) {
|
|
15120
|
-
const entryInfo = entries.map((e) => `${
|
|
15121
|
-
console.log(`${
|
|
15430
|
+
const entryInfo = entries.map((e) => `${chalk135.green(e.version)} ${e.title}`).join(" | ");
|
|
15431
|
+
console.log(`${chalk135.bold.blue(date)} ${entryInfo}`);
|
|
15122
15432
|
} else {
|
|
15123
|
-
console.log(`${
|
|
15433
|
+
console.log(`${chalk135.bold.blue(date)} ${chalk135.red("\u26A0 devlog missing")}`);
|
|
15124
15434
|
}
|
|
15125
15435
|
}
|
|
15126
15436
|
|
|
@@ -15136,7 +15446,7 @@ function list3(options2) {
|
|
|
15136
15446
|
if (options2.reverse) args.push("--reverse");
|
|
15137
15447
|
else args.push("-n", "500");
|
|
15138
15448
|
args.push("--pretty=format:%ad|%h|%s", "--date=short");
|
|
15139
|
-
const output =
|
|
15449
|
+
const output = execFileSync3("git", args, { encoding: "utf8" });
|
|
15140
15450
|
const commitsByDate = parseGitLogCommits(output, ignore3);
|
|
15141
15451
|
let dateCount = 0;
|
|
15142
15452
|
let isFirst = true;
|
|
@@ -15159,7 +15469,7 @@ function list3(options2) {
|
|
|
15159
15469
|
}
|
|
15160
15470
|
|
|
15161
15471
|
// src/commands/devlog/getLastVersionInfo.ts
|
|
15162
|
-
import { execFileSync as
|
|
15472
|
+
import { execFileSync as execFileSync4, execSync as execSync34 } from "child_process";
|
|
15163
15473
|
import semver from "semver";
|
|
15164
15474
|
function getVersionAtCommit(hash) {
|
|
15165
15475
|
try {
|
|
@@ -15178,7 +15488,7 @@ function stripToMinor(version2) {
|
|
|
15178
15488
|
}
|
|
15179
15489
|
function getLastVersionInfoFromGit() {
|
|
15180
15490
|
try {
|
|
15181
|
-
const output =
|
|
15491
|
+
const output = execFileSync4(
|
|
15182
15492
|
"git",
|
|
15183
15493
|
["log", "-1", "--pretty=format:%ad|%h", "--date=short"],
|
|
15184
15494
|
{
|
|
@@ -15223,25 +15533,25 @@ function bumpVersion(version2, type) {
|
|
|
15223
15533
|
}
|
|
15224
15534
|
|
|
15225
15535
|
// src/commands/devlog/next/displayNextEntry/index.ts
|
|
15226
|
-
import { execFileSync as
|
|
15227
|
-
import
|
|
15536
|
+
import { execFileSync as execFileSync5 } from "child_process";
|
|
15537
|
+
import chalk137 from "chalk";
|
|
15228
15538
|
|
|
15229
15539
|
// src/commands/devlog/next/displayNextEntry/displayVersion.ts
|
|
15230
|
-
import
|
|
15540
|
+
import chalk136 from "chalk";
|
|
15231
15541
|
function displayVersion(conventional, firstHash, patchVersion, minorVersion) {
|
|
15232
15542
|
if (conventional && firstHash) {
|
|
15233
15543
|
const version2 = getVersionAtCommit(firstHash);
|
|
15234
15544
|
if (version2) {
|
|
15235
|
-
console.log(`${
|
|
15545
|
+
console.log(`${chalk136.bold("version:")} ${stripToMinor(version2)}`);
|
|
15236
15546
|
} else {
|
|
15237
|
-
console.log(`${
|
|
15547
|
+
console.log(`${chalk136.bold("version:")} ${chalk136.red("unknown")}`);
|
|
15238
15548
|
}
|
|
15239
15549
|
} else if (patchVersion && minorVersion) {
|
|
15240
15550
|
console.log(
|
|
15241
|
-
`${
|
|
15551
|
+
`${chalk136.bold("version:")} ${patchVersion} (patch) or ${minorVersion} (minor)`
|
|
15242
15552
|
);
|
|
15243
15553
|
} else {
|
|
15244
|
-
console.log(`${
|
|
15554
|
+
console.log(`${chalk136.bold("version:")} v0.1 (initial)`);
|
|
15245
15555
|
}
|
|
15246
15556
|
}
|
|
15247
15557
|
|
|
@@ -15257,7 +15567,7 @@ function findTargetDate(commitsByDate, skipDays) {
|
|
|
15257
15567
|
return Array.from(commitsByDate.keys()).filter((d) => !skipDays.has(d)).sort()[0];
|
|
15258
15568
|
}
|
|
15259
15569
|
function fetchCommitsByDate(ignore3, lastDate) {
|
|
15260
|
-
const output =
|
|
15570
|
+
const output = execFileSync5(
|
|
15261
15571
|
"git",
|
|
15262
15572
|
["log", "--pretty=format:%ad|%h|%s", "--date=short", "-n", "500"],
|
|
15263
15573
|
{ encoding: "utf8" }
|
|
@@ -15289,16 +15599,16 @@ function noCommitsMessage(hasLastInfo) {
|
|
|
15289
15599
|
return hasLastInfo ? "No commits after last versioned entry" : "No commits found";
|
|
15290
15600
|
}
|
|
15291
15601
|
function logName(repoName) {
|
|
15292
|
-
console.log(`${
|
|
15602
|
+
console.log(`${chalk137.bold("name:")} ${repoName}`);
|
|
15293
15603
|
}
|
|
15294
15604
|
function displayNextEntry(ctx, targetDate, commits2) {
|
|
15295
15605
|
logName(ctx.repoName);
|
|
15296
15606
|
printVersionInfo(ctx.config, ctx.lastInfo, commits2[0]?.hash);
|
|
15297
|
-
console.log(
|
|
15607
|
+
console.log(chalk137.bold.blue(targetDate));
|
|
15298
15608
|
printCommitsWithFiles(commits2, ctx.ignore, ctx.verbose);
|
|
15299
15609
|
}
|
|
15300
15610
|
function logNoCommits(lastInfo) {
|
|
15301
|
-
console.log(
|
|
15611
|
+
console.log(chalk137.dim(noCommitsMessage(!!lastInfo)));
|
|
15302
15612
|
}
|
|
15303
15613
|
|
|
15304
15614
|
// src/commands/devlog/next/index.ts
|
|
@@ -15339,11 +15649,11 @@ function next2(options2) {
|
|
|
15339
15649
|
import { execSync as execSync35 } from "child_process";
|
|
15340
15650
|
|
|
15341
15651
|
// src/commands/devlog/repos/printReposTable.ts
|
|
15342
|
-
import
|
|
15652
|
+
import chalk138 from "chalk";
|
|
15343
15653
|
function colorStatus(status3) {
|
|
15344
|
-
if (status3 === "missing") return
|
|
15345
|
-
if (status3 === "outdated") return
|
|
15346
|
-
return
|
|
15654
|
+
if (status3 === "missing") return chalk138.red(status3);
|
|
15655
|
+
if (status3 === "outdated") return chalk138.yellow(status3);
|
|
15656
|
+
return chalk138.green(status3);
|
|
15347
15657
|
}
|
|
15348
15658
|
function formatRow(row, nameWidth) {
|
|
15349
15659
|
const devlog = (row.lastDevlog ?? "-").padEnd(11);
|
|
@@ -15357,8 +15667,8 @@ function printReposTable(rows) {
|
|
|
15357
15667
|
"Last Devlog".padEnd(11),
|
|
15358
15668
|
"Status"
|
|
15359
15669
|
].join(" ");
|
|
15360
|
-
console.log(
|
|
15361
|
-
console.log(
|
|
15670
|
+
console.log(chalk138.dim(header));
|
|
15671
|
+
console.log(chalk138.dim("-".repeat(header.length)));
|
|
15362
15672
|
for (const row of rows) {
|
|
15363
15673
|
console.log(formatRow(row, nameWidth));
|
|
15364
15674
|
}
|
|
@@ -15416,14 +15726,14 @@ function repos(options2) {
|
|
|
15416
15726
|
// src/commands/devlog/skip.ts
|
|
15417
15727
|
import { writeFileSync as writeFileSync29 } from "fs";
|
|
15418
15728
|
import { join as join39 } from "path";
|
|
15419
|
-
import
|
|
15729
|
+
import chalk139 from "chalk";
|
|
15420
15730
|
import { stringify as stringifyYaml3 } from "yaml";
|
|
15421
15731
|
function getBlogConfigPath() {
|
|
15422
15732
|
return join39(BLOG_REPO_ROOT, "assist.yml");
|
|
15423
15733
|
}
|
|
15424
15734
|
function skip(date) {
|
|
15425
15735
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
|
|
15426
|
-
console.log(
|
|
15736
|
+
console.log(chalk139.red("Invalid date format. Use YYYY-MM-DD"));
|
|
15427
15737
|
process.exit(1);
|
|
15428
15738
|
}
|
|
15429
15739
|
const repoName = getRepoName();
|
|
@@ -15434,7 +15744,7 @@ function skip(date) {
|
|
|
15434
15744
|
const skipDays = skip2[repoName] ?? [];
|
|
15435
15745
|
if (skipDays.includes(date)) {
|
|
15436
15746
|
console.log(
|
|
15437
|
-
|
|
15747
|
+
chalk139.yellow(`${date} is already in skip list for ${repoName}`)
|
|
15438
15748
|
);
|
|
15439
15749
|
return;
|
|
15440
15750
|
}
|
|
@@ -15444,20 +15754,20 @@ function skip(date) {
|
|
|
15444
15754
|
devlog.skip = skip2;
|
|
15445
15755
|
config.devlog = devlog;
|
|
15446
15756
|
writeFileSync29(configPath, stringifyYaml3(config, { lineWidth: 0 }));
|
|
15447
|
-
console.log(
|
|
15757
|
+
console.log(chalk139.green(`Added ${date} to skip list for ${repoName}`));
|
|
15448
15758
|
}
|
|
15449
15759
|
|
|
15450
15760
|
// src/commands/devlog/version.ts
|
|
15451
|
-
import
|
|
15761
|
+
import chalk140 from "chalk";
|
|
15452
15762
|
function version() {
|
|
15453
15763
|
const config = loadConfig();
|
|
15454
15764
|
const name = getRepoName();
|
|
15455
15765
|
const lastInfo = getLastVersionInfo(name, config);
|
|
15456
15766
|
const lastVersion = lastInfo?.version ?? null;
|
|
15457
15767
|
const nextVersion = lastVersion ? bumpVersion(lastVersion, "patch") : null;
|
|
15458
|
-
console.log(`${
|
|
15459
|
-
console.log(`${
|
|
15460
|
-
console.log(`${
|
|
15768
|
+
console.log(`${chalk140.bold("name:")} ${name}`);
|
|
15769
|
+
console.log(`${chalk140.bold("last:")} ${lastVersion ?? chalk140.dim("none")}`);
|
|
15770
|
+
console.log(`${chalk140.bold("next:")} ${nextVersion ?? chalk140.dim("none")}`);
|
|
15461
15771
|
}
|
|
15462
15772
|
|
|
15463
15773
|
// src/commands/devlog/devlogConfigHelp.ts
|
|
@@ -15501,7 +15811,7 @@ function registerDevlog(program2) {
|
|
|
15501
15811
|
// src/commands/dotnet/checkBuildLocks.ts
|
|
15502
15812
|
import { closeSync as closeSync3, openSync as openSync3, readdirSync as readdirSync5 } from "fs";
|
|
15503
15813
|
import { join as join40 } from "path";
|
|
15504
|
-
import
|
|
15814
|
+
import chalk141 from "chalk";
|
|
15505
15815
|
|
|
15506
15816
|
// src/shared/findRepoRoot.ts
|
|
15507
15817
|
import { existsSync as existsSync37 } from "fs";
|
|
@@ -15564,14 +15874,14 @@ function checkBuildLocks(startDir) {
|
|
|
15564
15874
|
const locked = findFirstLockedDll(startDir ?? getSearchRoot());
|
|
15565
15875
|
if (locked) {
|
|
15566
15876
|
console.error(
|
|
15567
|
-
|
|
15877
|
+
chalk141.red("Build output locked (is VS debugging?): ") + locked
|
|
15568
15878
|
);
|
|
15569
15879
|
process.exit(1);
|
|
15570
15880
|
}
|
|
15571
15881
|
}
|
|
15572
15882
|
async function checkBuildLocksCommand() {
|
|
15573
15883
|
checkBuildLocks();
|
|
15574
|
-
console.log(
|
|
15884
|
+
console.log(chalk141.green("No build locks detected"));
|
|
15575
15885
|
}
|
|
15576
15886
|
|
|
15577
15887
|
// src/commands/dotnet/buildTree.ts
|
|
@@ -15670,30 +15980,30 @@ function escapeRegex(s) {
|
|
|
15670
15980
|
}
|
|
15671
15981
|
|
|
15672
15982
|
// src/commands/dotnet/printTree.ts
|
|
15673
|
-
import
|
|
15983
|
+
import chalk142 from "chalk";
|
|
15674
15984
|
function printNodes(nodes, prefix2) {
|
|
15675
15985
|
for (let i = 0; i < nodes.length; i++) {
|
|
15676
15986
|
const isLast = i === nodes.length - 1;
|
|
15677
15987
|
const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
|
|
15678
15988
|
const childPrefix = isLast ? " " : "\u2502 ";
|
|
15679
15989
|
const isMissing = nodes[i].relativePath.startsWith("[MISSING]");
|
|
15680
|
-
const label2 = isMissing ?
|
|
15990
|
+
const label2 = isMissing ? chalk142.red(nodes[i].relativePath) : nodes[i].relativePath;
|
|
15681
15991
|
console.log(`${prefix2}${connector}${label2}`);
|
|
15682
15992
|
printNodes(nodes[i].children, prefix2 + childPrefix);
|
|
15683
15993
|
}
|
|
15684
15994
|
}
|
|
15685
15995
|
function printTree(tree, totalCount, solutions) {
|
|
15686
|
-
console.log(
|
|
15687
|
-
console.log(
|
|
15996
|
+
console.log(chalk142.bold("\nProject Dependency Tree"));
|
|
15997
|
+
console.log(chalk142.cyan(tree.relativePath));
|
|
15688
15998
|
printNodes(tree.children, "");
|
|
15689
|
-
console.log(
|
|
15999
|
+
console.log(chalk142.dim(`
|
|
15690
16000
|
${totalCount} projects total (including root)`));
|
|
15691
|
-
console.log(
|
|
16001
|
+
console.log(chalk142.bold("\nSolution Membership"));
|
|
15692
16002
|
if (solutions.length === 0) {
|
|
15693
|
-
console.log(
|
|
16003
|
+
console.log(chalk142.yellow(" Not found in any .sln"));
|
|
15694
16004
|
} else {
|
|
15695
16005
|
for (const sln of solutions) {
|
|
15696
|
-
console.log(` ${
|
|
16006
|
+
console.log(` ${chalk142.green(sln)}`);
|
|
15697
16007
|
}
|
|
15698
16008
|
}
|
|
15699
16009
|
console.log();
|
|
@@ -15722,16 +16032,16 @@ function printJson(tree, totalCount, solutions) {
|
|
|
15722
16032
|
// src/commands/dotnet/resolveCsproj.ts
|
|
15723
16033
|
import { existsSync as existsSync38 } from "fs";
|
|
15724
16034
|
import path33 from "path";
|
|
15725
|
-
import
|
|
16035
|
+
import chalk143 from "chalk";
|
|
15726
16036
|
function resolveCsproj(csprojPath) {
|
|
15727
16037
|
const resolved = path33.resolve(csprojPath);
|
|
15728
16038
|
if (!existsSync38(resolved)) {
|
|
15729
|
-
console.error(
|
|
16039
|
+
console.error(chalk143.red(`File not found: ${resolved}`));
|
|
15730
16040
|
process.exit(1);
|
|
15731
16041
|
}
|
|
15732
16042
|
const repoRoot = findRepoRoot(path33.dirname(resolved));
|
|
15733
16043
|
if (!repoRoot) {
|
|
15734
|
-
console.error(
|
|
16044
|
+
console.error(chalk143.red("Could not find git repository root"));
|
|
15735
16045
|
process.exit(1);
|
|
15736
16046
|
}
|
|
15737
16047
|
return { resolved, repoRoot };
|
|
@@ -15781,12 +16091,12 @@ function getChangedCsFiles(scope) {
|
|
|
15781
16091
|
}
|
|
15782
16092
|
|
|
15783
16093
|
// src/commands/dotnet/inSln.ts
|
|
15784
|
-
import
|
|
16094
|
+
import chalk144 from "chalk";
|
|
15785
16095
|
async function inSln(csprojPath) {
|
|
15786
16096
|
const { resolved, repoRoot } = resolveCsproj(csprojPath);
|
|
15787
16097
|
const solutions = findContainingSolutions(resolved, repoRoot);
|
|
15788
16098
|
if (solutions.length === 0) {
|
|
15789
|
-
console.log(
|
|
16099
|
+
console.log(chalk144.yellow("Not found in any .sln file"));
|
|
15790
16100
|
process.exit(1);
|
|
15791
16101
|
}
|
|
15792
16102
|
for (const sln of solutions) {
|
|
@@ -15795,7 +16105,7 @@ async function inSln(csprojPath) {
|
|
|
15795
16105
|
}
|
|
15796
16106
|
|
|
15797
16107
|
// src/commands/dotnet/inspect.ts
|
|
15798
|
-
import
|
|
16108
|
+
import chalk150 from "chalk";
|
|
15799
16109
|
|
|
15800
16110
|
// src/shared/formatElapsed.ts
|
|
15801
16111
|
function formatElapsed(ms) {
|
|
@@ -15807,12 +16117,12 @@ function formatElapsed(ms) {
|
|
|
15807
16117
|
}
|
|
15808
16118
|
|
|
15809
16119
|
// src/commands/dotnet/displayIssues.ts
|
|
15810
|
-
import
|
|
16120
|
+
import chalk145 from "chalk";
|
|
15811
16121
|
var SEVERITY_COLOR = {
|
|
15812
|
-
ERROR:
|
|
15813
|
-
WARNING:
|
|
15814
|
-
SUGGESTION:
|
|
15815
|
-
HINT:
|
|
16122
|
+
ERROR: chalk145.red,
|
|
16123
|
+
WARNING: chalk145.yellow,
|
|
16124
|
+
SUGGESTION: chalk145.cyan,
|
|
16125
|
+
HINT: chalk145.dim
|
|
15816
16126
|
};
|
|
15817
16127
|
function groupByFile(issues) {
|
|
15818
16128
|
const byFile = /* @__PURE__ */ new Map();
|
|
@@ -15828,15 +16138,15 @@ function groupByFile(issues) {
|
|
|
15828
16138
|
}
|
|
15829
16139
|
function displayIssues(issues) {
|
|
15830
16140
|
for (const [file, fileIssues] of groupByFile(issues)) {
|
|
15831
|
-
console.log(
|
|
16141
|
+
console.log(chalk145.bold(file));
|
|
15832
16142
|
for (const issue of fileIssues.sort((a, b) => a.line - b.line)) {
|
|
15833
|
-
const color = SEVERITY_COLOR[issue.severity] ??
|
|
16143
|
+
const color = SEVERITY_COLOR[issue.severity] ?? chalk145.white;
|
|
15834
16144
|
console.log(
|
|
15835
|
-
` ${
|
|
16145
|
+
` ${chalk145.dim(`${issue.line}:`)} ${color(issue.severity)} [${issue.typeId}] ${issue.message}`
|
|
15836
16146
|
);
|
|
15837
16147
|
}
|
|
15838
16148
|
}
|
|
15839
|
-
console.log(
|
|
16149
|
+
console.log(chalk145.dim(`
|
|
15840
16150
|
${issues.length} issue(s) found`));
|
|
15841
16151
|
}
|
|
15842
16152
|
|
|
@@ -15895,12 +16205,12 @@ function filterIssues(issues, all, cliOnly, cliSuppress) {
|
|
|
15895
16205
|
// src/commands/dotnet/resolveSolution.ts
|
|
15896
16206
|
import { existsSync as existsSync39 } from "fs";
|
|
15897
16207
|
import path34 from "path";
|
|
15898
|
-
import
|
|
16208
|
+
import chalk147 from "chalk";
|
|
15899
16209
|
|
|
15900
16210
|
// src/commands/dotnet/findSolution.ts
|
|
15901
16211
|
import { readdirSync as readdirSync7 } from "fs";
|
|
15902
16212
|
import { dirname as dirname22, join as join41 } from "path";
|
|
15903
|
-
import
|
|
16213
|
+
import chalk146 from "chalk";
|
|
15904
16214
|
function findSlnInDir(dir) {
|
|
15905
16215
|
try {
|
|
15906
16216
|
return readdirSync7(dir).filter((f) => f.endsWith(".sln")).map((f) => join41(dir, f));
|
|
@@ -15916,17 +16226,17 @@ function findSolution() {
|
|
|
15916
16226
|
const slnFiles = findSlnInDir(current);
|
|
15917
16227
|
if (slnFiles.length === 1) return slnFiles[0];
|
|
15918
16228
|
if (slnFiles.length > 1) {
|
|
15919
|
-
console.error(
|
|
16229
|
+
console.error(chalk146.red(`Multiple .sln files found in ${current}:`));
|
|
15920
16230
|
for (const f of slnFiles) console.error(` ${f}`);
|
|
15921
16231
|
console.error(
|
|
15922
|
-
|
|
16232
|
+
chalk146.yellow("Specify which one: assist dotnet inspect <sln>")
|
|
15923
16233
|
);
|
|
15924
16234
|
process.exit(1);
|
|
15925
16235
|
}
|
|
15926
16236
|
if (current === ceiling) break;
|
|
15927
16237
|
current = dirname22(current);
|
|
15928
16238
|
}
|
|
15929
|
-
console.error(
|
|
16239
|
+
console.error(chalk146.red("No .sln file found between cwd and repo root"));
|
|
15930
16240
|
process.exit(1);
|
|
15931
16241
|
}
|
|
15932
16242
|
|
|
@@ -15935,7 +16245,7 @@ function resolveSolution(sln) {
|
|
|
15935
16245
|
if (sln) {
|
|
15936
16246
|
const resolved = path34.resolve(sln);
|
|
15937
16247
|
if (!existsSync39(resolved)) {
|
|
15938
|
-
console.error(
|
|
16248
|
+
console.error(chalk147.red(`Solution file not found: ${resolved}`));
|
|
15939
16249
|
process.exit(1);
|
|
15940
16250
|
}
|
|
15941
16251
|
return resolved;
|
|
@@ -15977,14 +16287,14 @@ import { execSync as execSync37 } from "child_process";
|
|
|
15977
16287
|
import { existsSync as existsSync40, readFileSync as readFileSync35, unlinkSync as unlinkSync10 } from "fs";
|
|
15978
16288
|
import { tmpdir as tmpdir4 } from "os";
|
|
15979
16289
|
import path35 from "path";
|
|
15980
|
-
import
|
|
16290
|
+
import chalk148 from "chalk";
|
|
15981
16291
|
function assertJbInstalled() {
|
|
15982
16292
|
try {
|
|
15983
16293
|
execSync37("jb inspectcode --version", { stdio: "pipe" });
|
|
15984
16294
|
} catch {
|
|
15985
|
-
console.error(
|
|
16295
|
+
console.error(chalk148.red("jb is not installed. Install with:"));
|
|
15986
16296
|
console.error(
|
|
15987
|
-
|
|
16297
|
+
chalk148.yellow(" dotnet tool install -g JetBrains.ReSharper.GlobalTools")
|
|
15988
16298
|
);
|
|
15989
16299
|
process.exit(1);
|
|
15990
16300
|
}
|
|
@@ -16002,11 +16312,11 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
16002
16312
|
if (error && typeof error === "object" && "stderr" in error) {
|
|
16003
16313
|
process.stderr.write(error.stderr);
|
|
16004
16314
|
}
|
|
16005
|
-
console.error(
|
|
16315
|
+
console.error(chalk148.red("jb inspectcode failed"));
|
|
16006
16316
|
process.exit(1);
|
|
16007
16317
|
}
|
|
16008
16318
|
if (!existsSync40(reportPath)) {
|
|
16009
|
-
console.error(
|
|
16319
|
+
console.error(chalk148.red("Report file not generated"));
|
|
16010
16320
|
process.exit(1);
|
|
16011
16321
|
}
|
|
16012
16322
|
const xml = readFileSync35(reportPath, "utf8");
|
|
@@ -16016,7 +16326,7 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
16016
16326
|
|
|
16017
16327
|
// src/commands/dotnet/runRoslynInspect.ts
|
|
16018
16328
|
import { execSync as execSync38 } from "child_process";
|
|
16019
|
-
import
|
|
16329
|
+
import chalk149 from "chalk";
|
|
16020
16330
|
function resolveMsbuildPath() {
|
|
16021
16331
|
const { run: run4 } = loadConfig();
|
|
16022
16332
|
const configs = resolveRunConfigs(run4, getConfigDir());
|
|
@@ -16028,9 +16338,9 @@ function assertMsbuildInstalled() {
|
|
|
16028
16338
|
try {
|
|
16029
16339
|
execSync38(`"${msbuild}" -version`, { stdio: "pipe" });
|
|
16030
16340
|
} catch {
|
|
16031
|
-
console.error(
|
|
16341
|
+
console.error(chalk149.red(`msbuild not found at: ${msbuild}`));
|
|
16032
16342
|
console.error(
|
|
16033
|
-
|
|
16343
|
+
chalk149.yellow(
|
|
16034
16344
|
"Configure it via a 'build' run entry in .claude/assist.yml or add msbuild to PATH."
|
|
16035
16345
|
)
|
|
16036
16346
|
);
|
|
@@ -16077,17 +16387,17 @@ function runEngine(resolved, changedFiles2, options2) {
|
|
|
16077
16387
|
// src/commands/dotnet/inspect.ts
|
|
16078
16388
|
function logScope(changedFiles2) {
|
|
16079
16389
|
if (changedFiles2 === null) {
|
|
16080
|
-
console.log(
|
|
16390
|
+
console.log(chalk150.dim("Inspecting full solution..."));
|
|
16081
16391
|
} else {
|
|
16082
16392
|
console.log(
|
|
16083
|
-
|
|
16393
|
+
chalk150.dim(`Inspecting ${changedFiles2.length} changed file(s)...`)
|
|
16084
16394
|
);
|
|
16085
16395
|
}
|
|
16086
16396
|
}
|
|
16087
16397
|
function reportResults(issues, elapsed) {
|
|
16088
16398
|
if (issues.length > 0) displayIssues(issues);
|
|
16089
|
-
else console.log(
|
|
16090
|
-
console.log(
|
|
16399
|
+
else console.log(chalk150.green("No issues found"));
|
|
16400
|
+
console.log(chalk150.dim(`Completed in ${formatElapsed(elapsed)}`));
|
|
16091
16401
|
if (issues.length > 0) process.exit(1);
|
|
16092
16402
|
}
|
|
16093
16403
|
async function inspect(sln, options2) {
|
|
@@ -16098,7 +16408,7 @@ async function inspect(sln, options2) {
|
|
|
16098
16408
|
const scope = parseScope(options2.scope);
|
|
16099
16409
|
const changedFiles2 = getChangedCsFiles(scope);
|
|
16100
16410
|
if (changedFiles2 !== null && changedFiles2.length === 0) {
|
|
16101
|
-
console.log(
|
|
16411
|
+
console.log(chalk150.green("No changed .cs files found"));
|
|
16102
16412
|
return;
|
|
16103
16413
|
}
|
|
16104
16414
|
logScope(changedFiles2);
|
|
@@ -16481,25 +16791,25 @@ function fetchRepoCommitAuthors(org, repo, since) {
|
|
|
16481
16791
|
}
|
|
16482
16792
|
|
|
16483
16793
|
// src/commands/github/printCountTable.ts
|
|
16484
|
-
import
|
|
16794
|
+
import chalk151 from "chalk";
|
|
16485
16795
|
function printCountTable(labelHeader, rows) {
|
|
16486
16796
|
const labelWidth = Math.max(
|
|
16487
16797
|
labelHeader.length,
|
|
16488
16798
|
...rows.map((row) => row.label.length)
|
|
16489
16799
|
);
|
|
16490
16800
|
const header = `${labelHeader.padEnd(labelWidth)} Commits`;
|
|
16491
|
-
console.log(
|
|
16492
|
-
console.log(
|
|
16801
|
+
console.log(chalk151.dim(header));
|
|
16802
|
+
console.log(chalk151.dim("-".repeat(header.length)));
|
|
16493
16803
|
for (const row of rows) {
|
|
16494
16804
|
console.log(`${row.label.padEnd(labelWidth)} ${row.count}`);
|
|
16495
16805
|
}
|
|
16496
16806
|
}
|
|
16497
16807
|
|
|
16498
16808
|
// src/commands/github/printRepoAuthorBreakdown.ts
|
|
16499
|
-
import
|
|
16809
|
+
import chalk152 from "chalk";
|
|
16500
16810
|
function printRepoAuthorBreakdown(repos2) {
|
|
16501
16811
|
for (const repo of repos2) {
|
|
16502
|
-
console.log(
|
|
16812
|
+
console.log(chalk152.bold(repo.name));
|
|
16503
16813
|
const authorWidth = Math.max(
|
|
16504
16814
|
0,
|
|
16505
16815
|
...repo.authors.map((a) => a.author.length)
|
|
@@ -16817,7 +17127,7 @@ function registerHandover(program2) {
|
|
|
16817
17127
|
}
|
|
16818
17128
|
|
|
16819
17129
|
// src/commands/jira/acceptanceCriteria.ts
|
|
16820
|
-
import
|
|
17130
|
+
import chalk153 from "chalk";
|
|
16821
17131
|
|
|
16822
17132
|
// src/commands/jira/adfToText.ts
|
|
16823
17133
|
function renderInline(node) {
|
|
@@ -16884,7 +17194,7 @@ function acceptanceCriteria(issueKey) {
|
|
|
16884
17194
|
const parsed = fetchIssue(issueKey, field);
|
|
16885
17195
|
const acValue = parsed?.fields?.[field];
|
|
16886
17196
|
if (!acValue) {
|
|
16887
|
-
console.log(
|
|
17197
|
+
console.log(chalk153.yellow(`No acceptance criteria found on ${issueKey}.`));
|
|
16888
17198
|
return;
|
|
16889
17199
|
}
|
|
16890
17200
|
if (typeof acValue === "string") {
|
|
@@ -16950,14 +17260,14 @@ async function jiraAuth() {
|
|
|
16950
17260
|
}
|
|
16951
17261
|
|
|
16952
17262
|
// src/commands/jira/viewIssue.ts
|
|
16953
|
-
import
|
|
17263
|
+
import chalk154 from "chalk";
|
|
16954
17264
|
function viewIssue(issueKey) {
|
|
16955
17265
|
const parsed = fetchIssue(issueKey, "summary,description");
|
|
16956
17266
|
const fields = parsed?.fields;
|
|
16957
17267
|
const summary = fields?.summary;
|
|
16958
17268
|
const description = fields?.description;
|
|
16959
17269
|
if (summary) {
|
|
16960
|
-
console.log(
|
|
17270
|
+
console.log(chalk154.bold(summary));
|
|
16961
17271
|
}
|
|
16962
17272
|
if (description) {
|
|
16963
17273
|
if (summary) console.log();
|
|
@@ -16971,7 +17281,7 @@ function viewIssue(issueKey) {
|
|
|
16971
17281
|
}
|
|
16972
17282
|
if (!summary && !description) {
|
|
16973
17283
|
console.log(
|
|
16974
|
-
|
|
17284
|
+
chalk154.yellow(`No summary or description found on ${issueKey}.`)
|
|
16975
17285
|
);
|
|
16976
17286
|
}
|
|
16977
17287
|
}
|
|
@@ -17025,15 +17335,15 @@ function registerRefineLaunch(program2, resumeFlag) {
|
|
|
17025
17335
|
}
|
|
17026
17336
|
|
|
17027
17337
|
// src/commands/reviewPrComments.ts
|
|
17028
|
-
import { execFileSync as
|
|
17338
|
+
import { execFileSync as execFileSync6 } from "child_process";
|
|
17029
17339
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
17030
|
-
import
|
|
17340
|
+
import chalk155 from "chalk";
|
|
17031
17341
|
async function reviewPrComments(number) {
|
|
17032
17342
|
if (number) {
|
|
17033
17343
|
try {
|
|
17034
|
-
|
|
17344
|
+
execFileSync6("gh", ["pr", "checkout", number], { stdio: "inherit" });
|
|
17035
17345
|
} catch {
|
|
17036
|
-
console.error(
|
|
17346
|
+
console.error(chalk155.red(`gh pr checkout ${number} failed; aborting.`));
|
|
17037
17347
|
process.exit(1);
|
|
17038
17348
|
}
|
|
17039
17349
|
}
|
|
@@ -17106,15 +17416,15 @@ function registerList(program2) {
|
|
|
17106
17416
|
// src/commands/mermaid/index.ts
|
|
17107
17417
|
import { mkdirSync as mkdirSync16, readdirSync as readdirSync9 } from "fs";
|
|
17108
17418
|
import { resolve as resolve13 } from "path";
|
|
17109
|
-
import
|
|
17419
|
+
import chalk158 from "chalk";
|
|
17110
17420
|
|
|
17111
17421
|
// src/commands/mermaid/exportFile.ts
|
|
17112
17422
|
import { readFileSync as readFileSync37, writeFileSync as writeFileSync31 } from "fs";
|
|
17113
17423
|
import { basename as basename11, extname as extname2, resolve as resolve12 } from "path";
|
|
17114
|
-
import
|
|
17424
|
+
import chalk157 from "chalk";
|
|
17115
17425
|
|
|
17116
17426
|
// src/commands/mermaid/renderBlock.ts
|
|
17117
|
-
import
|
|
17427
|
+
import chalk156 from "chalk";
|
|
17118
17428
|
async function renderBlock(krokiUrl, source) {
|
|
17119
17429
|
const response = await fetch(`${krokiUrl}/mermaid/svg`, {
|
|
17120
17430
|
method: "POST",
|
|
@@ -17123,7 +17433,7 @@ async function renderBlock(krokiUrl, source) {
|
|
|
17123
17433
|
});
|
|
17124
17434
|
if (!response.ok) {
|
|
17125
17435
|
console.error(
|
|
17126
|
-
|
|
17436
|
+
chalk156.red(
|
|
17127
17437
|
`Kroki request failed: ${response.status} ${response.statusText}`
|
|
17128
17438
|
)
|
|
17129
17439
|
);
|
|
@@ -17141,19 +17451,19 @@ async function exportFile(file, outDir, krokiUrl, onlyIndex) {
|
|
|
17141
17451
|
if (onlyIndex !== void 0) {
|
|
17142
17452
|
if (onlyIndex < 1 || onlyIndex > blocks.length) {
|
|
17143
17453
|
console.error(
|
|
17144
|
-
|
|
17454
|
+
chalk157.red(
|
|
17145
17455
|
`${file}: --index ${onlyIndex} out of range (file has ${blocks.length} diagram(s))`
|
|
17146
17456
|
)
|
|
17147
17457
|
);
|
|
17148
17458
|
process.exit(1);
|
|
17149
17459
|
}
|
|
17150
17460
|
console.log(
|
|
17151
|
-
|
|
17461
|
+
chalk157.gray(
|
|
17152
17462
|
`${file} \u2014 rendering diagram ${onlyIndex} of ${blocks.length}`
|
|
17153
17463
|
)
|
|
17154
17464
|
);
|
|
17155
17465
|
} else {
|
|
17156
|
-
console.log(
|
|
17466
|
+
console.log(chalk157.gray(`${file} \u2014 ${blocks.length} diagram(s)`));
|
|
17157
17467
|
}
|
|
17158
17468
|
for (const [i, source] of blocks.entries()) {
|
|
17159
17469
|
const idx = i + 1;
|
|
@@ -17161,7 +17471,7 @@ async function exportFile(file, outDir, krokiUrl, onlyIndex) {
|
|
|
17161
17471
|
const outPath = resolve12(outDir, `${stem}-${idx}.svg`);
|
|
17162
17472
|
const svg = await renderBlock(krokiUrl, source);
|
|
17163
17473
|
writeFileSync31(outPath, svg, "utf8");
|
|
17164
|
-
console.log(
|
|
17474
|
+
console.log(chalk157.green(` \u2192 ${outPath}`));
|
|
17165
17475
|
}
|
|
17166
17476
|
}
|
|
17167
17477
|
function extractMermaidBlocks(markdown) {
|
|
@@ -17177,18 +17487,18 @@ async function mermaidExport(file, options2 = {}) {
|
|
|
17177
17487
|
if (options2.index !== void 0) {
|
|
17178
17488
|
if (!Number.isInteger(options2.index) || options2.index < 1) {
|
|
17179
17489
|
console.error(
|
|
17180
|
-
|
|
17490
|
+
chalk158.red(`--index must be a positive integer (got ${options2.index})`)
|
|
17181
17491
|
);
|
|
17182
17492
|
process.exit(1);
|
|
17183
17493
|
}
|
|
17184
17494
|
if (!file) {
|
|
17185
|
-
console.error(
|
|
17495
|
+
console.error(chalk158.red("--index requires a file argument"));
|
|
17186
17496
|
process.exit(1);
|
|
17187
17497
|
}
|
|
17188
17498
|
}
|
|
17189
17499
|
const files = file ? [file] : readdirSync9(process.cwd()).filter((name) => name.toLowerCase().endsWith(".md")).sort();
|
|
17190
17500
|
if (files.length === 0) {
|
|
17191
|
-
console.log(
|
|
17501
|
+
console.log(chalk158.gray("No markdown files found in current directory."));
|
|
17192
17502
|
return;
|
|
17193
17503
|
}
|
|
17194
17504
|
for (const f of files) {
|
|
@@ -17221,7 +17531,7 @@ function registerMermaid(program2) {
|
|
|
17221
17531
|
import { mkdir as mkdir4 } from "fs/promises";
|
|
17222
17532
|
import { createServer as createServer2 } from "http";
|
|
17223
17533
|
import { dirname as dirname24 } from "path";
|
|
17224
|
-
import
|
|
17534
|
+
import chalk160 from "chalk";
|
|
17225
17535
|
|
|
17226
17536
|
// src/commands/netcap/corsHeaders.ts
|
|
17227
17537
|
var corsHeaders = {
|
|
@@ -17300,7 +17610,7 @@ function createNetcapHandler(options2) {
|
|
|
17300
17610
|
import { cp, readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
|
|
17301
17611
|
import { networkInterfaces } from "os";
|
|
17302
17612
|
import { join as join47 } from "path";
|
|
17303
|
-
import
|
|
17613
|
+
import chalk159 from "chalk";
|
|
17304
17614
|
|
|
17305
17615
|
// src/commands/netcap/netcapExtensionDir.ts
|
|
17306
17616
|
import { dirname as dirname23, join as join46 } from "path";
|
|
@@ -17344,7 +17654,7 @@ async function prepareExtensionForLoad(port, filter = "") {
|
|
|
17344
17654
|
const host = lanIPv4();
|
|
17345
17655
|
if (!host) {
|
|
17346
17656
|
console.log(
|
|
17347
|
-
|
|
17657
|
+
chalk159.yellow("could not determine the WSL IP for the extension")
|
|
17348
17658
|
);
|
|
17349
17659
|
await configureBackground(source, "127.0.0.1", port, filter);
|
|
17350
17660
|
return source;
|
|
@@ -17355,7 +17665,7 @@ async function prepareExtensionForLoad(port, filter = "") {
|
|
|
17355
17665
|
return WSL_WINDOWS_PATH;
|
|
17356
17666
|
} catch {
|
|
17357
17667
|
console.log(
|
|
17358
|
-
|
|
17668
|
+
chalk159.yellow(`could not copy extension to ${WSL_WINDOWS_PATH}`)
|
|
17359
17669
|
);
|
|
17360
17670
|
return source;
|
|
17361
17671
|
}
|
|
@@ -17388,30 +17698,30 @@ async function netcap(options2) {
|
|
|
17388
17698
|
let count7 = 0;
|
|
17389
17699
|
const handler = createNetcapHandler({
|
|
17390
17700
|
outPath,
|
|
17391
|
-
onPing: () => console.log(
|
|
17701
|
+
onPing: () => console.log(chalk160.dim("ping from extension")),
|
|
17392
17702
|
onCapture: (entry) => {
|
|
17393
17703
|
count7 += 1;
|
|
17394
17704
|
console.log(
|
|
17395
|
-
|
|
17396
|
-
|
|
17705
|
+
chalk160.green(`captured #${count7}`),
|
|
17706
|
+
chalk160.dim(`${entry.method ?? "?"} ${entry.url ?? "?"}`)
|
|
17397
17707
|
);
|
|
17398
17708
|
}
|
|
17399
17709
|
});
|
|
17400
17710
|
const server = createServer2(handler);
|
|
17401
17711
|
server.listen(port, () => {
|
|
17402
17712
|
console.log(
|
|
17403
|
-
|
|
17713
|
+
chalk160.bold(`netcap receiver listening on http://127.0.0.1:${port}`)
|
|
17404
17714
|
);
|
|
17405
|
-
console.log(
|
|
17715
|
+
console.log(chalk160.dim(`appending captures to ${outPath}`));
|
|
17406
17716
|
if (filter)
|
|
17407
|
-
console.log(
|
|
17408
|
-
console.log(
|
|
17409
|
-
console.log(
|
|
17717
|
+
console.log(chalk160.dim(`forwarding only URLs matching "${filter}"`));
|
|
17718
|
+
console.log(chalk160.dim(`load the unpacked extension from ${extensionPath}`));
|
|
17719
|
+
console.log(chalk160.dim("press Ctrl-C to stop"));
|
|
17410
17720
|
});
|
|
17411
17721
|
process.on("SIGINT", () => {
|
|
17412
17722
|
server.close();
|
|
17413
17723
|
console.log(
|
|
17414
|
-
|
|
17724
|
+
chalk160.bold(
|
|
17415
17725
|
`
|
|
17416
17726
|
netcap stopped \u2014 captured ${count7} ${count7 === 1 ? "entry" : "entries"} to ${outPath}`
|
|
17417
17727
|
)
|
|
@@ -17423,7 +17733,7 @@ netcap stopped \u2014 captured ${count7} ${count7 === 1 ? "entry" : "entries"} t
|
|
|
17423
17733
|
// src/commands/netcap/netcapExtract.ts
|
|
17424
17734
|
import { writeFileSync as writeFileSync32 } from "fs";
|
|
17425
17735
|
import { join as join50 } from "path";
|
|
17426
|
-
import
|
|
17736
|
+
import chalk161 from "chalk";
|
|
17427
17737
|
|
|
17428
17738
|
// src/commands/netcap/extractPostsFromCapture.ts
|
|
17429
17739
|
import { readFileSync as readFileSync38 } from "fs";
|
|
@@ -17871,8 +18181,8 @@ function netcapExtract(file) {
|
|
|
17871
18181
|
writeFileSync32(outFile, `${JSON.stringify(posts, null, 2)}
|
|
17872
18182
|
`);
|
|
17873
18183
|
console.log(
|
|
17874
|
-
|
|
17875
|
-
|
|
18184
|
+
chalk161.green(`extracted ${posts.length} posts`),
|
|
18185
|
+
chalk161.dim(`-> ${outFile}`)
|
|
17876
18186
|
);
|
|
17877
18187
|
}
|
|
17878
18188
|
|
|
@@ -17893,7 +18203,7 @@ function registerNetcap(program2) {
|
|
|
17893
18203
|
}
|
|
17894
18204
|
|
|
17895
18205
|
// src/commands/news/add/index.ts
|
|
17896
|
-
import
|
|
18206
|
+
import chalk162 from "chalk";
|
|
17897
18207
|
import enquirer8 from "enquirer";
|
|
17898
18208
|
async function add2(url) {
|
|
17899
18209
|
if (!url) {
|
|
@@ -17915,10 +18225,10 @@ async function add2(url) {
|
|
|
17915
18225
|
const { orm } = await getReady();
|
|
17916
18226
|
const added = await addFeed(orm, url);
|
|
17917
18227
|
if (!added) {
|
|
17918
|
-
console.log(
|
|
18228
|
+
console.log(chalk162.yellow("Feed already exists"));
|
|
17919
18229
|
return;
|
|
17920
18230
|
}
|
|
17921
|
-
console.log(
|
|
18231
|
+
console.log(chalk162.green(`Added feed: ${url}`));
|
|
17922
18232
|
}
|
|
17923
18233
|
|
|
17924
18234
|
// src/commands/registerNews.ts
|
|
@@ -17965,7 +18275,7 @@ function registerPiHook(program2) {
|
|
|
17965
18275
|
}
|
|
17966
18276
|
|
|
17967
18277
|
// src/commands/prompts/printPromptsTable.ts
|
|
17968
|
-
import
|
|
18278
|
+
import chalk163 from "chalk";
|
|
17969
18279
|
function truncate(str, max) {
|
|
17970
18280
|
if (str.length <= max) return str;
|
|
17971
18281
|
return `${str.slice(0, max - 1)}\u2026`;
|
|
@@ -17983,14 +18293,14 @@ function printPromptsTable(rows) {
|
|
|
17983
18293
|
"Command".padEnd(commandWidth),
|
|
17984
18294
|
"Repos"
|
|
17985
18295
|
].join(" ");
|
|
17986
|
-
console.log(
|
|
17987
|
-
console.log(
|
|
18296
|
+
console.log(chalk163.dim(header));
|
|
18297
|
+
console.log(chalk163.dim("-".repeat(header.length)));
|
|
17988
18298
|
for (const row of rows) {
|
|
17989
18299
|
const count7 = String(row.count).padStart(countWidth);
|
|
17990
18300
|
const tool = row.tool.padEnd(toolWidth);
|
|
17991
18301
|
const command = truncate(row.command, 60).padEnd(commandWidth);
|
|
17992
18302
|
console.log(
|
|
17993
|
-
`${
|
|
18303
|
+
`${chalk163.yellow(count7)} ${tool} ${command} ${chalk163.dim(row.repos)}`
|
|
17994
18304
|
);
|
|
17995
18305
|
}
|
|
17996
18306
|
}
|
|
@@ -18154,7 +18464,7 @@ function comment2(path71, line, body, startLine) {
|
|
|
18154
18464
|
}
|
|
18155
18465
|
|
|
18156
18466
|
// src/commands/prs/edit.ts
|
|
18157
|
-
import { execFileSync as
|
|
18467
|
+
import { execFileSync as execFileSync7 } from "child_process";
|
|
18158
18468
|
|
|
18159
18469
|
// src/commands/prs/buildPrBody.ts
|
|
18160
18470
|
function jiraBrowseUrl(key) {
|
|
@@ -18345,7 +18655,7 @@ function edit(options2) {
|
|
|
18345
18655
|
if (options2.title) args.push("--title", options2.title);
|
|
18346
18656
|
args.push("--body", newBody);
|
|
18347
18657
|
try {
|
|
18348
|
-
|
|
18658
|
+
execFileSync7("gh", args, { stdio: "inherit" });
|
|
18349
18659
|
} catch {
|
|
18350
18660
|
process.exit(1);
|
|
18351
18661
|
}
|
|
@@ -18407,20 +18717,20 @@ function resolveThread(threadId) {
|
|
|
18407
18717
|
}
|
|
18408
18718
|
}
|
|
18409
18719
|
function requireCache(prNumber) {
|
|
18410
|
-
const
|
|
18411
|
-
if (!
|
|
18720
|
+
const cache3 = loadCommentsCache(prNumber);
|
|
18721
|
+
if (!cache3) {
|
|
18412
18722
|
console.error(
|
|
18413
18723
|
`Error: No cached comments found for PR #${prNumber}. Run "assist prs list-comments" first.`
|
|
18414
18724
|
);
|
|
18415
18725
|
process.exit(1);
|
|
18416
18726
|
}
|
|
18417
|
-
return
|
|
18727
|
+
return cache3;
|
|
18418
18728
|
}
|
|
18419
18729
|
function findLineComment(comments3, commentId) {
|
|
18420
18730
|
return comments3.find((c) => c.type === "line" && c.id === commentId);
|
|
18421
18731
|
}
|
|
18422
|
-
function requireLineComment(
|
|
18423
|
-
const comment3 = findLineComment(
|
|
18732
|
+
function requireLineComment(cache3, commentId) {
|
|
18733
|
+
const comment3 = findLineComment(cache3.comments, commentId);
|
|
18424
18734
|
if (!comment3 || comment3.type !== "line" || !comment3.threadId) {
|
|
18425
18735
|
console.error(
|
|
18426
18736
|
`Error: Comment #${commentId} not found or has no thread ID.`
|
|
@@ -18429,8 +18739,8 @@ function requireLineComment(cache2, commentId) {
|
|
|
18429
18739
|
}
|
|
18430
18740
|
return comment3;
|
|
18431
18741
|
}
|
|
18432
|
-
function cleanupCacheIfDone(
|
|
18433
|
-
const hasRemaining =
|
|
18742
|
+
function cleanupCacheIfDone(cache3, prNumber, commentId) {
|
|
18743
|
+
const hasRemaining = cache3.comments.some(
|
|
18434
18744
|
(c) => c.type === "line" && c.id !== commentId
|
|
18435
18745
|
);
|
|
18436
18746
|
if (!hasRemaining) deleteCommentsCache(prNumber);
|
|
@@ -18438,13 +18748,13 @@ function cleanupCacheIfDone(cache2, prNumber, commentId) {
|
|
|
18438
18748
|
function resolveCommentWithReply(commentId, message2) {
|
|
18439
18749
|
const prNumber = getCurrentPrNumber();
|
|
18440
18750
|
const { org, repo } = getRepoInfo();
|
|
18441
|
-
const
|
|
18442
|
-
const comment3 = requireLineComment(
|
|
18751
|
+
const cache3 = requireCache(prNumber);
|
|
18752
|
+
const comment3 = requireLineComment(cache3, commentId);
|
|
18443
18753
|
replyToComment(org, repo, prNumber, commentId, message2);
|
|
18444
18754
|
console.log("Reply posted successfully.");
|
|
18445
18755
|
resolveThread(comment3.threadId);
|
|
18446
18756
|
console.log("Thread resolved successfully.");
|
|
18447
|
-
cleanupCacheIfDone(
|
|
18757
|
+
cleanupCacheIfDone(cache3, prNumber, commentId);
|
|
18448
18758
|
}
|
|
18449
18759
|
|
|
18450
18760
|
// src/commands/prs/fixed.ts
|
|
@@ -18557,20 +18867,20 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
|
|
|
18557
18867
|
}
|
|
18558
18868
|
|
|
18559
18869
|
// src/commands/prs/listComments/printComments.ts
|
|
18560
|
-
import
|
|
18870
|
+
import chalk164 from "chalk";
|
|
18561
18871
|
function formatForHuman(comment3) {
|
|
18562
18872
|
if (comment3.type === "review") {
|
|
18563
|
-
const stateColor = comment3.state === "APPROVED" ?
|
|
18873
|
+
const stateColor = comment3.state === "APPROVED" ? chalk164.green : comment3.state === "CHANGES_REQUESTED" ? chalk164.red : chalk164.yellow;
|
|
18564
18874
|
return [
|
|
18565
|
-
`${
|
|
18875
|
+
`${chalk164.cyan("Review")} by ${chalk164.bold(comment3.user)} ${stateColor(`[${comment3.state}]`)}`,
|
|
18566
18876
|
comment3.body,
|
|
18567
18877
|
""
|
|
18568
18878
|
].join("\n");
|
|
18569
18879
|
}
|
|
18570
18880
|
const location = comment3.line ? `:${comment3.line}` : "";
|
|
18571
18881
|
return [
|
|
18572
|
-
`${
|
|
18573
|
-
|
|
18882
|
+
`${chalk164.cyan("Line comment")} by ${chalk164.bold(comment3.user)} on ${chalk164.dim(`${comment3.path}${location}`)}`,
|
|
18883
|
+
chalk164.dim(comment3.diff_hunk.split("\n").slice(-3).join("\n")),
|
|
18574
18884
|
comment3.body,
|
|
18575
18885
|
""
|
|
18576
18886
|
].join("\n");
|
|
@@ -18660,13 +18970,13 @@ import { execSync as execSync46 } from "child_process";
|
|
|
18660
18970
|
import enquirer9 from "enquirer";
|
|
18661
18971
|
|
|
18662
18972
|
// src/commands/prs/prs/displayPaginated/printPr.ts
|
|
18663
|
-
import
|
|
18973
|
+
import chalk165 from "chalk";
|
|
18664
18974
|
var STATUS_MAP = {
|
|
18665
|
-
MERGED: (pr) => pr.mergedAt ? { label:
|
|
18666
|
-
CLOSED: (pr) => pr.closedAt ? { label:
|
|
18975
|
+
MERGED: (pr) => pr.mergedAt ? { label: chalk165.magenta("merged"), date: pr.mergedAt } : null,
|
|
18976
|
+
CLOSED: (pr) => pr.closedAt ? { label: chalk165.red("closed"), date: pr.closedAt } : null
|
|
18667
18977
|
};
|
|
18668
18978
|
function defaultStatus(pr) {
|
|
18669
|
-
return { label:
|
|
18979
|
+
return { label: chalk165.green("opened"), date: pr.createdAt };
|
|
18670
18980
|
}
|
|
18671
18981
|
function getStatus2(pr) {
|
|
18672
18982
|
return STATUS_MAP[pr.state]?.(pr) ?? defaultStatus(pr);
|
|
@@ -18675,11 +18985,11 @@ function formatDate(dateStr) {
|
|
|
18675
18985
|
return new Date(dateStr).toISOString().split("T")[0];
|
|
18676
18986
|
}
|
|
18677
18987
|
function formatPrHeader(pr, status3) {
|
|
18678
|
-
return `${
|
|
18988
|
+
return `${chalk165.cyan(`#${pr.number}`)} ${pr.title} ${chalk165.dim(`(${pr.author.login},`)} ${status3.label} ${chalk165.dim(`${formatDate(status3.date)})`)}`;
|
|
18679
18989
|
}
|
|
18680
18990
|
function logPrDetails(pr) {
|
|
18681
18991
|
console.log(
|
|
18682
|
-
|
|
18992
|
+
chalk165.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
|
|
18683
18993
|
);
|
|
18684
18994
|
console.log();
|
|
18685
18995
|
}
|
|
@@ -18800,7 +19110,7 @@ function buildValidatedBody(options2, usage) {
|
|
|
18800
19110
|
}
|
|
18801
19111
|
|
|
18802
19112
|
// src/commands/prs/placePr.ts
|
|
18803
|
-
import { execFileSync as
|
|
19113
|
+
import { execFileSync as execFileSync8 } from "child_process";
|
|
18804
19114
|
|
|
18805
19115
|
// src/commands/prs/buildCreateArgs.ts
|
|
18806
19116
|
function buildEditArgs(number, title, body) {
|
|
@@ -18867,7 +19177,7 @@ async function recordPrActivity() {
|
|
|
18867
19177
|
// src/commands/prs/placePr.ts
|
|
18868
19178
|
function hasUpstream() {
|
|
18869
19179
|
try {
|
|
18870
|
-
|
|
19180
|
+
execFileSync8(
|
|
18871
19181
|
"git",
|
|
18872
19182
|
["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"],
|
|
18873
19183
|
{ stdio: "pipe" }
|
|
@@ -18879,13 +19189,13 @@ function hasUpstream() {
|
|
|
18879
19189
|
}
|
|
18880
19190
|
function ensureBranchPushed() {
|
|
18881
19191
|
const args = hasUpstream() ? ["push"] : ["push", "--set-upstream", "origin", "HEAD"];
|
|
18882
|
-
|
|
19192
|
+
execFileSync8("git", args, { stdio: "inherit" });
|
|
18883
19193
|
}
|
|
18884
19194
|
async function placePr(prNumber, title, body, options2) {
|
|
18885
19195
|
const args = prNumber !== null ? buildEditArgs(prNumber, title, body) : buildCreateArgs(title, body, options2);
|
|
18886
19196
|
try {
|
|
18887
19197
|
if (prNumber === null && !options2.head) ensureBranchPushed();
|
|
18888
|
-
|
|
19198
|
+
execFileSync8("gh", args, { stdio: "inherit" });
|
|
18889
19199
|
} catch {
|
|
18890
19200
|
process.exit(1);
|
|
18891
19201
|
}
|
|
@@ -19194,10 +19504,10 @@ function registerPrs(program2) {
|
|
|
19194
19504
|
}
|
|
19195
19505
|
|
|
19196
19506
|
// src/commands/ravendb/ravendbAuth.ts
|
|
19197
|
-
import
|
|
19507
|
+
import chalk171 from "chalk";
|
|
19198
19508
|
|
|
19199
19509
|
// src/shared/createConnectionAuth.ts
|
|
19200
|
-
import
|
|
19510
|
+
import chalk166 from "chalk";
|
|
19201
19511
|
function listConnections(connections, format) {
|
|
19202
19512
|
if (connections.length === 0) {
|
|
19203
19513
|
console.log("No connections configured.");
|
|
@@ -19210,7 +19520,7 @@ function listConnections(connections, format) {
|
|
|
19210
19520
|
function removeConnection(connections, name, save) {
|
|
19211
19521
|
const filtered = connections.filter((c) => c.name !== name);
|
|
19212
19522
|
if (filtered.length === connections.length) {
|
|
19213
|
-
console.error(
|
|
19523
|
+
console.error(chalk166.red(`Connection "${name}" not found.`));
|
|
19214
19524
|
process.exit(1);
|
|
19215
19525
|
}
|
|
19216
19526
|
save(filtered);
|
|
@@ -19256,15 +19566,15 @@ function saveConnections(connections) {
|
|
|
19256
19566
|
}
|
|
19257
19567
|
|
|
19258
19568
|
// src/commands/ravendb/promptConnection.ts
|
|
19259
|
-
import
|
|
19569
|
+
import chalk169 from "chalk";
|
|
19260
19570
|
|
|
19261
19571
|
// src/commands/ravendb/selectOpSecret.ts
|
|
19262
|
-
import
|
|
19572
|
+
import chalk168 from "chalk";
|
|
19263
19573
|
import Enquirer2 from "enquirer";
|
|
19264
19574
|
|
|
19265
19575
|
// src/commands/ravendb/searchItems.ts
|
|
19266
19576
|
import { execSync as execSync49 } from "child_process";
|
|
19267
|
-
import
|
|
19577
|
+
import chalk167 from "chalk";
|
|
19268
19578
|
function opExec(args) {
|
|
19269
19579
|
return execSync49(`op ${args}`, {
|
|
19270
19580
|
encoding: "utf8",
|
|
@@ -19277,7 +19587,7 @@ function searchItems(search2) {
|
|
|
19277
19587
|
items2 = JSON.parse(opExec("item list --format=json"));
|
|
19278
19588
|
} catch {
|
|
19279
19589
|
console.error(
|
|
19280
|
-
|
|
19590
|
+
chalk167.red(
|
|
19281
19591
|
"Failed to search 1Password. Ensure the CLI is installed and you are signed in."
|
|
19282
19592
|
)
|
|
19283
19593
|
);
|
|
@@ -19291,7 +19601,7 @@ function getItemFields(itemId2) {
|
|
|
19291
19601
|
const item = JSON.parse(opExec(`item get "${itemId2}" --format=json`));
|
|
19292
19602
|
return item.fields.filter((f) => f.reference && f.label);
|
|
19293
19603
|
} catch {
|
|
19294
|
-
console.error(
|
|
19604
|
+
console.error(chalk167.red("Failed to get item details from 1Password."));
|
|
19295
19605
|
process.exit(1);
|
|
19296
19606
|
}
|
|
19297
19607
|
}
|
|
@@ -19310,7 +19620,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
19310
19620
|
}).run();
|
|
19311
19621
|
const items2 = searchItems(search2);
|
|
19312
19622
|
if (items2.length === 0) {
|
|
19313
|
-
console.error(
|
|
19623
|
+
console.error(chalk168.red(`No items found matching "${search2}".`));
|
|
19314
19624
|
process.exit(1);
|
|
19315
19625
|
}
|
|
19316
19626
|
const itemId2 = await selectOne(
|
|
@@ -19319,7 +19629,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
19319
19629
|
);
|
|
19320
19630
|
const fields = getItemFields(itemId2);
|
|
19321
19631
|
if (fields.length === 0) {
|
|
19322
|
-
console.error(
|
|
19632
|
+
console.error(chalk168.red("No fields with references found on this item."));
|
|
19323
19633
|
process.exit(1);
|
|
19324
19634
|
}
|
|
19325
19635
|
const ref = await selectOne(
|
|
@@ -19333,7 +19643,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
19333
19643
|
async function promptConnection(existingNames) {
|
|
19334
19644
|
const name = await promptInput("name", "Connection name:");
|
|
19335
19645
|
if (existingNames.includes(name)) {
|
|
19336
|
-
console.error(
|
|
19646
|
+
console.error(chalk169.red(`Connection "${name}" already exists.`));
|
|
19337
19647
|
process.exit(1);
|
|
19338
19648
|
}
|
|
19339
19649
|
const url = await promptInput(
|
|
@@ -19342,22 +19652,22 @@ async function promptConnection(existingNames) {
|
|
|
19342
19652
|
);
|
|
19343
19653
|
const database = await promptInput("database", "Database name:");
|
|
19344
19654
|
if (!name || !url || !database) {
|
|
19345
|
-
console.error(
|
|
19655
|
+
console.error(chalk169.red("All fields are required."));
|
|
19346
19656
|
process.exit(1);
|
|
19347
19657
|
}
|
|
19348
19658
|
const apiKeyRef = await selectOpSecret();
|
|
19349
|
-
console.log(
|
|
19659
|
+
console.log(chalk169.dim(`Using: ${apiKeyRef}`));
|
|
19350
19660
|
return { name, url, database, apiKeyRef };
|
|
19351
19661
|
}
|
|
19352
19662
|
|
|
19353
19663
|
// src/commands/ravendb/ravendbSetConnection.ts
|
|
19354
|
-
import
|
|
19664
|
+
import chalk170 from "chalk";
|
|
19355
19665
|
function ravendbSetConnection(name) {
|
|
19356
19666
|
const raw = loadGlobalConfigRaw();
|
|
19357
19667
|
const ravendb = raw.ravendb ?? {};
|
|
19358
19668
|
const connections = ravendb.connections ?? [];
|
|
19359
19669
|
if (!connections.some((c) => c.name === name)) {
|
|
19360
|
-
console.error(
|
|
19670
|
+
console.error(chalk170.red(`Connection "${name}" not found.`));
|
|
19361
19671
|
console.error(
|
|
19362
19672
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
19363
19673
|
);
|
|
@@ -19373,16 +19683,16 @@ function ravendbSetConnection(name) {
|
|
|
19373
19683
|
var ravendbAuth = createConnectionAuth({
|
|
19374
19684
|
load: loadConnections,
|
|
19375
19685
|
save: saveConnections,
|
|
19376
|
-
format: (c) => `${
|
|
19686
|
+
format: (c) => `${chalk171.bold(c.name)} ${c.url} db=${c.database} key=${c.apiKeyRef}`,
|
|
19377
19687
|
promptNew: promptConnection,
|
|
19378
19688
|
onFirst: (c) => ravendbSetConnection(c.name)
|
|
19379
19689
|
});
|
|
19380
19690
|
|
|
19381
19691
|
// src/commands/ravendb/ravendbCollections.ts
|
|
19382
|
-
import
|
|
19692
|
+
import chalk175 from "chalk";
|
|
19383
19693
|
|
|
19384
19694
|
// src/commands/ravendb/ravenFetch.ts
|
|
19385
|
-
import
|
|
19695
|
+
import chalk173 from "chalk";
|
|
19386
19696
|
|
|
19387
19697
|
// src/commands/ravendb/getAccessToken.ts
|
|
19388
19698
|
var OAUTH_URL = "https://amazon-useast-1-oauth.ravenhq.com/ApiKeys/OAuth/AccessToken";
|
|
@@ -19419,10 +19729,10 @@ ${errorText}`
|
|
|
19419
19729
|
|
|
19420
19730
|
// src/commands/ravendb/resolveOpSecret.ts
|
|
19421
19731
|
import { execSync as execSync50 } from "child_process";
|
|
19422
|
-
import
|
|
19732
|
+
import chalk172 from "chalk";
|
|
19423
19733
|
function resolveOpSecret(reference) {
|
|
19424
19734
|
if (!reference.startsWith("op://")) {
|
|
19425
|
-
console.error(
|
|
19735
|
+
console.error(chalk172.red(`Invalid secret reference: must start with op://`));
|
|
19426
19736
|
process.exit(1);
|
|
19427
19737
|
}
|
|
19428
19738
|
try {
|
|
@@ -19432,7 +19742,7 @@ function resolveOpSecret(reference) {
|
|
|
19432
19742
|
}).trim();
|
|
19433
19743
|
} catch {
|
|
19434
19744
|
console.error(
|
|
19435
|
-
|
|
19745
|
+
chalk172.red(
|
|
19436
19746
|
"Failed to resolve secret reference. Ensure 1Password CLI is installed and you are signed in."
|
|
19437
19747
|
)
|
|
19438
19748
|
);
|
|
@@ -19459,7 +19769,7 @@ async function ravenFetch(connection, path71) {
|
|
|
19459
19769
|
if (!response.ok) {
|
|
19460
19770
|
const body = await response.text();
|
|
19461
19771
|
console.error(
|
|
19462
|
-
|
|
19772
|
+
chalk173.red(`RavenDB error: ${response.status} ${response.statusText}`)
|
|
19463
19773
|
);
|
|
19464
19774
|
console.error(body.substring(0, 500));
|
|
19465
19775
|
process.exit(1);
|
|
@@ -19468,7 +19778,7 @@ async function ravenFetch(connection, path71) {
|
|
|
19468
19778
|
}
|
|
19469
19779
|
|
|
19470
19780
|
// src/commands/ravendb/resolveConnection.ts
|
|
19471
|
-
import
|
|
19781
|
+
import chalk174 from "chalk";
|
|
19472
19782
|
function loadRavendb() {
|
|
19473
19783
|
const raw = loadGlobalConfigRaw();
|
|
19474
19784
|
const ravendb = raw.ravendb;
|
|
@@ -19482,7 +19792,7 @@ function resolveConnection(name) {
|
|
|
19482
19792
|
const connectionName = name ?? defaultConnection;
|
|
19483
19793
|
if (!connectionName) {
|
|
19484
19794
|
console.error(
|
|
19485
|
-
|
|
19795
|
+
chalk174.red(
|
|
19486
19796
|
"No connection specified and no default set. Use assist ravendb set-connection <name> or pass a connection name."
|
|
19487
19797
|
)
|
|
19488
19798
|
);
|
|
@@ -19490,7 +19800,7 @@ function resolveConnection(name) {
|
|
|
19490
19800
|
}
|
|
19491
19801
|
const connection = connections.find((c) => c.name === connectionName);
|
|
19492
19802
|
if (!connection) {
|
|
19493
|
-
console.error(
|
|
19803
|
+
console.error(chalk174.red(`Connection "${connectionName}" not found.`));
|
|
19494
19804
|
console.error(
|
|
19495
19805
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
19496
19806
|
);
|
|
@@ -19521,7 +19831,7 @@ async function ravendbCollections(connectionName) {
|
|
|
19521
19831
|
return;
|
|
19522
19832
|
}
|
|
19523
19833
|
for (const c of collections) {
|
|
19524
|
-
console.log(`${
|
|
19834
|
+
console.log(`${chalk175.bold(c.Name)} ${c.CountOfDocuments} docs`);
|
|
19525
19835
|
}
|
|
19526
19836
|
}
|
|
19527
19837
|
|
|
@@ -19540,10 +19850,10 @@ var ravendbConfigHelp = [
|
|
|
19540
19850
|
];
|
|
19541
19851
|
|
|
19542
19852
|
// src/commands/ravendb/ravendbQuery.ts
|
|
19543
|
-
import
|
|
19853
|
+
import chalk177 from "chalk";
|
|
19544
19854
|
|
|
19545
19855
|
// src/commands/ravendb/fetchAllPages.ts
|
|
19546
|
-
import
|
|
19856
|
+
import chalk176 from "chalk";
|
|
19547
19857
|
|
|
19548
19858
|
// src/commands/ravendb/buildQueryPath.ts
|
|
19549
19859
|
function buildQueryPath(opts) {
|
|
@@ -19581,7 +19891,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
19581
19891
|
allResults.push(...results);
|
|
19582
19892
|
start3 += results.length;
|
|
19583
19893
|
process.stderr.write(
|
|
19584
|
-
`\r${
|
|
19894
|
+
`\r${chalk176.dim(`Fetched ${allResults.length}/${totalResults}`)}`
|
|
19585
19895
|
);
|
|
19586
19896
|
if (start3 >= totalResults) break;
|
|
19587
19897
|
if (opts.limit !== void 0 && allResults.length >= opts.limit) break;
|
|
@@ -19596,7 +19906,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
19596
19906
|
async function ravendbQuery(connectionName, collection, options2) {
|
|
19597
19907
|
const resolved = resolveArgs(connectionName, collection);
|
|
19598
19908
|
if (!resolved.collection && !options2.query) {
|
|
19599
|
-
console.error(
|
|
19909
|
+
console.error(chalk177.red("Provide a collection name or --query filter."));
|
|
19600
19910
|
process.exit(1);
|
|
19601
19911
|
}
|
|
19602
19912
|
const { collection: col } = resolved;
|
|
@@ -19635,7 +19945,7 @@ import { spawn as spawn5 } from "child_process";
|
|
|
19635
19945
|
import * as path36 from "path";
|
|
19636
19946
|
|
|
19637
19947
|
// src/commands/refactor/logViolations.ts
|
|
19638
|
-
import
|
|
19948
|
+
import chalk178 from "chalk";
|
|
19639
19949
|
var DEFAULT_MAX_LINES = 100;
|
|
19640
19950
|
function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
19641
19951
|
if (violations.length === 0) {
|
|
@@ -19644,43 +19954,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
|
19644
19954
|
}
|
|
19645
19955
|
return;
|
|
19646
19956
|
}
|
|
19647
|
-
console.error(
|
|
19957
|
+
console.error(chalk178.red(`
|
|
19648
19958
|
Refactor check failed:
|
|
19649
19959
|
`));
|
|
19650
|
-
console.error(
|
|
19960
|
+
console.error(chalk178.red(` The following files exceed ${maxLines} lines:
|
|
19651
19961
|
`));
|
|
19652
19962
|
for (const violation of violations) {
|
|
19653
|
-
console.error(
|
|
19963
|
+
console.error(chalk178.red(` ${violation.file} (${violation.lines} lines)`));
|
|
19654
19964
|
}
|
|
19655
19965
|
console.error(
|
|
19656
|
-
|
|
19966
|
+
chalk178.yellow(
|
|
19657
19967
|
`
|
|
19658
19968
|
Each file needs to be sensibly refactored, or if there is no sensible
|
|
19659
19969
|
way to refactor it, ignore it with:
|
|
19660
19970
|
`
|
|
19661
19971
|
)
|
|
19662
19972
|
);
|
|
19663
|
-
console.error(
|
|
19973
|
+
console.error(chalk178.gray(` assist refactor ignore <file>
|
|
19664
19974
|
`));
|
|
19665
19975
|
if (process.env.CLAUDECODE) {
|
|
19666
|
-
console.error(
|
|
19976
|
+
console.error(chalk178.cyan(`
|
|
19667
19977
|
## Extracting Code to New Files
|
|
19668
19978
|
`));
|
|
19669
19979
|
console.error(
|
|
19670
|
-
|
|
19980
|
+
chalk178.cyan(
|
|
19671
19981
|
` When extracting logic from one file to another, consider where the extracted code belongs:
|
|
19672
19982
|
`
|
|
19673
19983
|
)
|
|
19674
19984
|
);
|
|
19675
19985
|
console.error(
|
|
19676
|
-
|
|
19986
|
+
chalk178.cyan(
|
|
19677
19987
|
` 1. Keep related logic together: If the extracted code is tightly coupled to the
|
|
19678
19988
|
original file's domain, create a new folder containing both the original and extracted files.
|
|
19679
19989
|
`
|
|
19680
19990
|
)
|
|
19681
19991
|
);
|
|
19682
19992
|
console.error(
|
|
19683
|
-
|
|
19993
|
+
chalk178.cyan(
|
|
19684
19994
|
` 2. Share common utilities: If the extracted code can be reused across multiple
|
|
19685
19995
|
domains, move it to a common/shared folder.
|
|
19686
19996
|
`
|
|
@@ -19836,7 +20146,7 @@ async function check(pattern2, options2) {
|
|
|
19836
20146
|
|
|
19837
20147
|
// src/commands/refactor/extract/index.ts
|
|
19838
20148
|
import path44 from "path";
|
|
19839
|
-
import
|
|
20149
|
+
import chalk181 from "chalk";
|
|
19840
20150
|
|
|
19841
20151
|
// src/commands/refactor/extract/applyExtraction.ts
|
|
19842
20152
|
import { SyntaxKind as SyntaxKind4 } from "ts-morph";
|
|
@@ -20435,23 +20745,23 @@ function buildPlan2(functionName, sourceFile, sourcePath, destPath, project) {
|
|
|
20435
20745
|
|
|
20436
20746
|
// src/commands/refactor/extract/displayPlan.ts
|
|
20437
20747
|
import path40 from "path";
|
|
20438
|
-
import
|
|
20748
|
+
import chalk179 from "chalk";
|
|
20439
20749
|
function section2(title) {
|
|
20440
20750
|
return `
|
|
20441
|
-
${
|
|
20751
|
+
${chalk179.cyan(title)}`;
|
|
20442
20752
|
}
|
|
20443
20753
|
function displayImporters(plan2, cwd) {
|
|
20444
20754
|
if (plan2.importersToUpdate.length === 0) return;
|
|
20445
20755
|
console.log(section2("Update importers:"));
|
|
20446
20756
|
for (const imp of plan2.importersToUpdate) {
|
|
20447
20757
|
const rel = path40.relative(cwd, imp.file.getFilePath());
|
|
20448
|
-
console.log(` ${
|
|
20758
|
+
console.log(` ${chalk179.dim(rel)}: \u2192 import from "${imp.relPath}"`);
|
|
20449
20759
|
}
|
|
20450
20760
|
}
|
|
20451
20761
|
function displayPlan(functionName, relDest, plan2, cwd) {
|
|
20452
|
-
console.log(
|
|
20762
|
+
console.log(chalk179.bold(`Extract: ${functionName} \u2192 ${relDest}
|
|
20453
20763
|
`));
|
|
20454
|
-
console.log(` ${
|
|
20764
|
+
console.log(` ${chalk179.cyan("Functions to move:")}`);
|
|
20455
20765
|
for (const name of plan2.extractedNames) {
|
|
20456
20766
|
console.log(` ${name}`);
|
|
20457
20767
|
}
|
|
@@ -20485,7 +20795,7 @@ function displayPlan(functionName, relDest, plan2, cwd) {
|
|
|
20485
20795
|
|
|
20486
20796
|
// src/commands/refactor/extract/loadProjectFile.ts
|
|
20487
20797
|
import path43 from "path";
|
|
20488
|
-
import
|
|
20798
|
+
import chalk180 from "chalk";
|
|
20489
20799
|
import { Project as Project4 } from "ts-morph";
|
|
20490
20800
|
|
|
20491
20801
|
// src/commands/refactor/extract/findTsConfig.ts
|
|
@@ -20577,7 +20887,7 @@ function loadProjectFile(file) {
|
|
|
20577
20887
|
});
|
|
20578
20888
|
const sourceFile = project.getSourceFile(sourcePath);
|
|
20579
20889
|
if (!sourceFile) {
|
|
20580
|
-
console.log(
|
|
20890
|
+
console.log(chalk180.red(`File not found in project: ${file}`));
|
|
20581
20891
|
process.exit(1);
|
|
20582
20892
|
}
|
|
20583
20893
|
return { project, sourceFile };
|
|
@@ -20600,19 +20910,19 @@ async function extract(file, functionName, destination, options2 = {}) {
|
|
|
20600
20910
|
displayPlan(functionName, relDest, plan2, cwd);
|
|
20601
20911
|
if (options2.apply) {
|
|
20602
20912
|
await applyExtraction(functionName, sourceFile, destPath, plan2, project);
|
|
20603
|
-
console.log(
|
|
20913
|
+
console.log(chalk181.green("\nExtraction complete"));
|
|
20604
20914
|
} else {
|
|
20605
|
-
console.log(
|
|
20915
|
+
console.log(chalk181.dim("\nDry run. Use --apply to execute."));
|
|
20606
20916
|
}
|
|
20607
20917
|
}
|
|
20608
20918
|
|
|
20609
20919
|
// src/commands/refactor/ignore.ts
|
|
20610
20920
|
import fs28 from "fs";
|
|
20611
|
-
import
|
|
20921
|
+
import chalk182 from "chalk";
|
|
20612
20922
|
var REFACTOR_YML_PATH2 = "refactor.yml";
|
|
20613
20923
|
function ignore2(file) {
|
|
20614
20924
|
if (!fs28.existsSync(file)) {
|
|
20615
|
-
console.error(
|
|
20925
|
+
console.error(chalk182.red(`Error: File does not exist: ${file}`));
|
|
20616
20926
|
process.exit(1);
|
|
20617
20927
|
}
|
|
20618
20928
|
const content = fs28.readFileSync(file, "utf8");
|
|
@@ -20628,7 +20938,7 @@ function ignore2(file) {
|
|
|
20628
20938
|
fs28.writeFileSync(REFACTOR_YML_PATH2, entry);
|
|
20629
20939
|
}
|
|
20630
20940
|
console.log(
|
|
20631
|
-
|
|
20941
|
+
chalk182.green(
|
|
20632
20942
|
`Added ${file} to refactor ignore list (max ${maxLines} lines)`
|
|
20633
20943
|
)
|
|
20634
20944
|
);
|
|
@@ -20637,12 +20947,12 @@ function ignore2(file) {
|
|
|
20637
20947
|
// src/commands/refactor/rename/index.ts
|
|
20638
20948
|
import fs31 from "fs";
|
|
20639
20949
|
import path49 from "path";
|
|
20640
|
-
import
|
|
20950
|
+
import chalk185 from "chalk";
|
|
20641
20951
|
|
|
20642
20952
|
// src/commands/refactor/rename/applyRename.ts
|
|
20643
20953
|
import fs30 from "fs";
|
|
20644
20954
|
import path46 from "path";
|
|
20645
|
-
import
|
|
20955
|
+
import chalk183 from "chalk";
|
|
20646
20956
|
|
|
20647
20957
|
// src/commands/refactor/restructure/computeRewrites/index.ts
|
|
20648
20958
|
import path45 from "path";
|
|
@@ -20747,13 +21057,13 @@ function applyRename(rewrites, sourcePath, destPath, cwd) {
|
|
|
20747
21057
|
const updatedContents = applyRewrites(rewrites);
|
|
20748
21058
|
for (const [file, content] of updatedContents) {
|
|
20749
21059
|
fs30.writeFileSync(file, content, "utf8");
|
|
20750
|
-
console.log(
|
|
21060
|
+
console.log(chalk183.cyan(` Updated imports in ${path46.relative(cwd, file)}`));
|
|
20751
21061
|
}
|
|
20752
21062
|
const destDir = path46.dirname(destPath);
|
|
20753
21063
|
if (!fs30.existsSync(destDir)) fs30.mkdirSync(destDir, { recursive: true });
|
|
20754
21064
|
fs30.renameSync(sourcePath, destPath);
|
|
20755
21065
|
console.log(
|
|
20756
|
-
|
|
21066
|
+
chalk183.white(
|
|
20757
21067
|
` Moved ${path46.relative(cwd, sourcePath)} \u2192 ${path46.relative(cwd, destPath)}`
|
|
20758
21068
|
)
|
|
20759
21069
|
);
|
|
@@ -20840,16 +21150,16 @@ function computeRenameRewrites(sourcePath, destPath) {
|
|
|
20840
21150
|
|
|
20841
21151
|
// src/commands/refactor/rename/printRenamePreview.ts
|
|
20842
21152
|
import path48 from "path";
|
|
20843
|
-
import
|
|
21153
|
+
import chalk184 from "chalk";
|
|
20844
21154
|
function printRenamePreview(rewrites, cwd) {
|
|
20845
21155
|
for (const rewrite of rewrites) {
|
|
20846
21156
|
console.log(
|
|
20847
|
-
|
|
21157
|
+
chalk184.dim(
|
|
20848
21158
|
` ${path48.relative(cwd, rewrite.file)}: ${rewrite.oldSpecifier} \u2192 ${rewrite.newSpecifier}`
|
|
20849
21159
|
)
|
|
20850
21160
|
);
|
|
20851
21161
|
}
|
|
20852
|
-
console.log(
|
|
21162
|
+
console.log(chalk184.dim("Dry run. Use --apply to execute."));
|
|
20853
21163
|
}
|
|
20854
21164
|
|
|
20855
21165
|
// src/commands/refactor/rename/index.ts
|
|
@@ -20860,20 +21170,20 @@ async function rename(source, destination, options2 = {}) {
|
|
|
20860
21170
|
const relSource = path49.relative(cwd, sourcePath);
|
|
20861
21171
|
const relDest = path49.relative(cwd, destPath);
|
|
20862
21172
|
if (!fs31.existsSync(sourcePath)) {
|
|
20863
|
-
console.log(
|
|
21173
|
+
console.log(chalk185.red(`File not found: ${source}`));
|
|
20864
21174
|
process.exit(1);
|
|
20865
21175
|
}
|
|
20866
21176
|
if (destPath !== sourcePath && fs31.existsSync(destPath)) {
|
|
20867
|
-
console.log(
|
|
21177
|
+
console.log(chalk185.red(`Destination already exists: ${destination}`));
|
|
20868
21178
|
process.exit(1);
|
|
20869
21179
|
}
|
|
20870
|
-
console.log(
|
|
20871
|
-
console.log(
|
|
20872
|
-
console.log(
|
|
21180
|
+
console.log(chalk185.bold(`Rename: ${relSource} \u2192 ${relDest}`));
|
|
21181
|
+
console.log(chalk185.dim("Loading project..."));
|
|
21182
|
+
console.log(chalk185.dim("Scanning imports across the project..."));
|
|
20873
21183
|
const rewrites = computeRenameRewrites(sourcePath, destPath);
|
|
20874
21184
|
const affectedFiles = new Set(rewrites.map((r) => r.file)).size;
|
|
20875
21185
|
console.log(
|
|
20876
|
-
|
|
21186
|
+
chalk185.dim(
|
|
20877
21187
|
`${rewrites.length} import path(s) to update across ${affectedFiles} file(s)`
|
|
20878
21188
|
)
|
|
20879
21189
|
);
|
|
@@ -20882,11 +21192,11 @@ async function rename(source, destination, options2 = {}) {
|
|
|
20882
21192
|
return;
|
|
20883
21193
|
}
|
|
20884
21194
|
applyRename(rewrites, sourcePath, destPath, cwd);
|
|
20885
|
-
console.log(
|
|
21195
|
+
console.log(chalk185.green("Done"));
|
|
20886
21196
|
}
|
|
20887
21197
|
|
|
20888
21198
|
// src/commands/refactor/renameSymbol/index.ts
|
|
20889
|
-
import
|
|
21199
|
+
import chalk186 from "chalk";
|
|
20890
21200
|
|
|
20891
21201
|
// src/commands/refactor/renameSymbol/findSymbol.ts
|
|
20892
21202
|
import { SyntaxKind as SyntaxKind15 } from "ts-morph";
|
|
@@ -20932,33 +21242,33 @@ async function renameSymbol(file, oldName, newName, options2 = {}) {
|
|
|
20932
21242
|
const { project, sourceFile } = loadProjectFile(file);
|
|
20933
21243
|
const symbol = findSymbol(sourceFile, oldName);
|
|
20934
21244
|
if (!symbol) {
|
|
20935
|
-
console.log(
|
|
21245
|
+
console.log(chalk186.red(`Symbol "${oldName}" not found in ${file}`));
|
|
20936
21246
|
process.exit(1);
|
|
20937
21247
|
}
|
|
20938
21248
|
const grouped = groupReferences(symbol, cwd);
|
|
20939
21249
|
const totalRefs = [...grouped.values()].reduce((s, l) => s + l.length, 0);
|
|
20940
21250
|
console.log(
|
|
20941
|
-
|
|
21251
|
+
chalk186.bold(`Rename: ${oldName} \u2192 ${newName} (${totalRefs} references)
|
|
20942
21252
|
`)
|
|
20943
21253
|
);
|
|
20944
21254
|
for (const [refFile, lines] of grouped) {
|
|
20945
21255
|
console.log(
|
|
20946
|
-
` ${
|
|
21256
|
+
` ${chalk186.dim(refFile)}: lines ${chalk186.cyan(lines.join(", "))}`
|
|
20947
21257
|
);
|
|
20948
21258
|
}
|
|
20949
21259
|
if (options2.apply) {
|
|
20950
21260
|
symbol.rename(newName);
|
|
20951
21261
|
await project.save();
|
|
20952
|
-
console.log(
|
|
21262
|
+
console.log(chalk186.green(`
|
|
20953
21263
|
Renamed ${oldName} \u2192 ${newName}`));
|
|
20954
21264
|
} else {
|
|
20955
|
-
console.log(
|
|
21265
|
+
console.log(chalk186.dim("\nDry run. Use --apply to execute."));
|
|
20956
21266
|
}
|
|
20957
21267
|
}
|
|
20958
21268
|
|
|
20959
21269
|
// src/commands/refactor/restructure/index.ts
|
|
20960
21270
|
import path57 from "path";
|
|
20961
|
-
import
|
|
21271
|
+
import chalk189 from "chalk";
|
|
20962
21272
|
|
|
20963
21273
|
// src/commands/refactor/restructure/clusterDirectories.ts
|
|
20964
21274
|
import path51 from "path";
|
|
@@ -21037,50 +21347,50 @@ function clusterFiles(graph) {
|
|
|
21037
21347
|
|
|
21038
21348
|
// src/commands/refactor/restructure/displayPlan.ts
|
|
21039
21349
|
import path53 from "path";
|
|
21040
|
-
import
|
|
21350
|
+
import chalk187 from "chalk";
|
|
21041
21351
|
function relPath(filePath) {
|
|
21042
21352
|
return path53.relative(process.cwd(), filePath);
|
|
21043
21353
|
}
|
|
21044
21354
|
function displayMoves(plan2) {
|
|
21045
21355
|
if (plan2.moves.length === 0) return;
|
|
21046
|
-
console.log(
|
|
21356
|
+
console.log(chalk187.bold("\nFile moves:"));
|
|
21047
21357
|
for (const move2 of plan2.moves) {
|
|
21048
21358
|
console.log(
|
|
21049
|
-
` ${
|
|
21359
|
+
` ${chalk187.red(relPath(move2.from))} \u2192 ${chalk187.green(relPath(move2.to))}`
|
|
21050
21360
|
);
|
|
21051
|
-
console.log(
|
|
21361
|
+
console.log(chalk187.dim(` ${move2.reason}`));
|
|
21052
21362
|
}
|
|
21053
21363
|
}
|
|
21054
21364
|
function displayRewrites(rewrites) {
|
|
21055
21365
|
if (rewrites.length === 0) return;
|
|
21056
21366
|
const affectedFiles = new Set(rewrites.map((r) => r.file));
|
|
21057
|
-
console.log(
|
|
21367
|
+
console.log(chalk187.bold(`
|
|
21058
21368
|
Import rewrites (${affectedFiles.size} files):`));
|
|
21059
21369
|
for (const file of affectedFiles) {
|
|
21060
|
-
console.log(` ${
|
|
21370
|
+
console.log(` ${chalk187.cyan(relPath(file))}:`);
|
|
21061
21371
|
for (const { oldSpecifier, newSpecifier } of rewrites.filter(
|
|
21062
21372
|
(r) => r.file === file
|
|
21063
21373
|
)) {
|
|
21064
21374
|
console.log(
|
|
21065
|
-
` ${
|
|
21375
|
+
` ${chalk187.red(`"${oldSpecifier}"`)} \u2192 ${chalk187.green(`"${newSpecifier}"`)}`
|
|
21066
21376
|
);
|
|
21067
21377
|
}
|
|
21068
21378
|
}
|
|
21069
21379
|
}
|
|
21070
21380
|
function displayPlan2(plan2) {
|
|
21071
21381
|
if (plan2.warnings.length > 0) {
|
|
21072
|
-
console.log(
|
|
21073
|
-
for (const w of plan2.warnings) console.log(
|
|
21382
|
+
console.log(chalk187.yellow("\nWarnings:"));
|
|
21383
|
+
for (const w of plan2.warnings) console.log(chalk187.yellow(` ${w}`));
|
|
21074
21384
|
}
|
|
21075
21385
|
if (plan2.newDirectories.length > 0) {
|
|
21076
|
-
console.log(
|
|
21386
|
+
console.log(chalk187.bold("\nNew directories:"));
|
|
21077
21387
|
for (const dir of plan2.newDirectories)
|
|
21078
|
-
console.log(
|
|
21388
|
+
console.log(chalk187.green(` ${dir}/`));
|
|
21079
21389
|
}
|
|
21080
21390
|
displayMoves(plan2);
|
|
21081
21391
|
displayRewrites(plan2.rewrites);
|
|
21082
21392
|
console.log(
|
|
21083
|
-
|
|
21393
|
+
chalk187.dim(
|
|
21084
21394
|
`
|
|
21085
21395
|
Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports rewritten`
|
|
21086
21396
|
)
|
|
@@ -21090,18 +21400,18 @@ Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports r
|
|
|
21090
21400
|
// src/commands/refactor/restructure/executePlan.ts
|
|
21091
21401
|
import fs32 from "fs";
|
|
21092
21402
|
import path54 from "path";
|
|
21093
|
-
import
|
|
21403
|
+
import chalk188 from "chalk";
|
|
21094
21404
|
function executePlan(plan2) {
|
|
21095
21405
|
const updatedContents = applyRewrites(plan2.rewrites);
|
|
21096
21406
|
for (const [file, content] of updatedContents) {
|
|
21097
21407
|
fs32.writeFileSync(file, content, "utf8");
|
|
21098
21408
|
console.log(
|
|
21099
|
-
|
|
21409
|
+
chalk188.cyan(` Rewrote imports in ${path54.relative(process.cwd(), file)}`)
|
|
21100
21410
|
);
|
|
21101
21411
|
}
|
|
21102
21412
|
for (const dir of plan2.newDirectories) {
|
|
21103
21413
|
fs32.mkdirSync(dir, { recursive: true });
|
|
21104
|
-
console.log(
|
|
21414
|
+
console.log(chalk188.green(` Created ${path54.relative(process.cwd(), dir)}/`));
|
|
21105
21415
|
}
|
|
21106
21416
|
for (const move2 of plan2.moves) {
|
|
21107
21417
|
const targetDir = path54.dirname(move2.to);
|
|
@@ -21110,7 +21420,7 @@ function executePlan(plan2) {
|
|
|
21110
21420
|
}
|
|
21111
21421
|
fs32.renameSync(move2.from, move2.to);
|
|
21112
21422
|
console.log(
|
|
21113
|
-
|
|
21423
|
+
chalk188.white(
|
|
21114
21424
|
` Moved ${path54.relative(process.cwd(), move2.from)} \u2192 ${path54.relative(process.cwd(), move2.to)}`
|
|
21115
21425
|
)
|
|
21116
21426
|
);
|
|
@@ -21125,7 +21435,7 @@ function removeEmptyDirectories(dirs) {
|
|
|
21125
21435
|
if (entries.length === 0) {
|
|
21126
21436
|
fs32.rmdirSync(dir);
|
|
21127
21437
|
console.log(
|
|
21128
|
-
|
|
21438
|
+
chalk188.dim(
|
|
21129
21439
|
` Removed empty directory ${path54.relative(process.cwd(), dir)}`
|
|
21130
21440
|
)
|
|
21131
21441
|
);
|
|
@@ -21258,22 +21568,22 @@ async function restructure(pattern2, options2 = {}) {
|
|
|
21258
21568
|
const targetPattern = pattern2 ?? "src";
|
|
21259
21569
|
const files = findSourceFiles2(targetPattern);
|
|
21260
21570
|
if (files.length === 0) {
|
|
21261
|
-
console.log(
|
|
21571
|
+
console.log(chalk189.yellow("No files found matching pattern"));
|
|
21262
21572
|
return;
|
|
21263
21573
|
}
|
|
21264
21574
|
const tsConfigPath = findTsConfig(path57.resolve(files[0]));
|
|
21265
21575
|
const plan2 = buildPlan3(files, tsConfigPath);
|
|
21266
21576
|
if (plan2.moves.length === 0) {
|
|
21267
|
-
console.log(
|
|
21577
|
+
console.log(chalk189.green("No restructuring needed"));
|
|
21268
21578
|
return;
|
|
21269
21579
|
}
|
|
21270
21580
|
displayPlan2(plan2);
|
|
21271
21581
|
if (options2.apply) {
|
|
21272
|
-
console.log(
|
|
21582
|
+
console.log(chalk189.bold("\nApplying changes..."));
|
|
21273
21583
|
executePlan(plan2);
|
|
21274
|
-
console.log(
|
|
21584
|
+
console.log(chalk189.green("\nRestructuring complete"));
|
|
21275
21585
|
} else {
|
|
21276
|
-
console.log(
|
|
21586
|
+
console.log(chalk189.dim("\nDry run. Use --apply to execute."));
|
|
21277
21587
|
}
|
|
21278
21588
|
}
|
|
21279
21589
|
|
|
@@ -21323,7 +21633,7 @@ function registerRefactor(program2) {
|
|
|
21323
21633
|
}
|
|
21324
21634
|
|
|
21325
21635
|
// src/commands/review/review.ts
|
|
21326
|
-
import { execFileSync as
|
|
21636
|
+
import { execFileSync as execFileSync9 } from "child_process";
|
|
21327
21637
|
|
|
21328
21638
|
// src/commands/review/annotateDiffWithLineNumbers.ts
|
|
21329
21639
|
var FILE_HEADER2 = /^\+\+\+ (?:b\/)?(.+)$/;
|
|
@@ -21856,18 +22166,18 @@ function partitionFindingsByDiff(findings, index3) {
|
|
|
21856
22166
|
}
|
|
21857
22167
|
|
|
21858
22168
|
// src/commands/review/warnOutOfDiff.ts
|
|
21859
|
-
import
|
|
22169
|
+
import chalk190 from "chalk";
|
|
21860
22170
|
function warnOutOfDiff(outOfDiff) {
|
|
21861
22171
|
if (outOfDiff.length === 0) return;
|
|
21862
22172
|
console.warn(
|
|
21863
|
-
|
|
22173
|
+
chalk190.yellow(
|
|
21864
22174
|
`Skipped ${outOfDiff.length} finding(s) whose lines fall outside the PR diff (GitHub would silently drop these):`
|
|
21865
22175
|
)
|
|
21866
22176
|
);
|
|
21867
22177
|
for (const finding of outOfDiff) {
|
|
21868
22178
|
const range = finding.startLine !== void 0 ? `${finding.startLine}-${finding.line}` : `${finding.line}`;
|
|
21869
22179
|
console.warn(
|
|
21870
|
-
` ${
|
|
22180
|
+
` ${chalk190.yellow("\xB7")} ${finding.title} ${chalk190.dim(
|
|
21871
22181
|
`(${finding.file}:${range})`
|
|
21872
22182
|
)}`
|
|
21873
22183
|
);
|
|
@@ -21886,18 +22196,18 @@ function selectInDiffFindings(lineBound, prDiff) {
|
|
|
21886
22196
|
}
|
|
21887
22197
|
|
|
21888
22198
|
// src/commands/review/warnUnlocated.ts
|
|
21889
|
-
import
|
|
22199
|
+
import chalk191 from "chalk";
|
|
21890
22200
|
function warnUnlocated(unlocated) {
|
|
21891
22201
|
if (unlocated.length === 0) return;
|
|
21892
22202
|
console.warn(
|
|
21893
|
-
|
|
22203
|
+
chalk191.yellow(
|
|
21894
22204
|
`Skipped ${unlocated.length} finding(s) without a parseable file:line:`
|
|
21895
22205
|
)
|
|
21896
22206
|
);
|
|
21897
22207
|
for (const finding of unlocated) {
|
|
21898
|
-
const where = finding.location ||
|
|
22208
|
+
const where = finding.location || chalk191.dim("missing");
|
|
21899
22209
|
console.warn(
|
|
21900
|
-
` ${
|
|
22210
|
+
` ${chalk191.yellow("\xB7")} ${finding.title} ${chalk191.dim(`(${where})`)}`
|
|
21901
22211
|
);
|
|
21902
22212
|
}
|
|
21903
22213
|
}
|
|
@@ -23021,7 +23331,7 @@ function validateOptions(options2) {
|
|
|
23021
23331
|
}
|
|
23022
23332
|
function checkoutPr(number) {
|
|
23023
23333
|
try {
|
|
23024
|
-
|
|
23334
|
+
execFileSync9("gh", ["pr", "checkout", number], { stdio: "inherit" });
|
|
23025
23335
|
} catch {
|
|
23026
23336
|
console.error(`gh pr checkout ${number} failed; aborting.`);
|
|
23027
23337
|
process.exit(1);
|
|
@@ -23069,7 +23379,7 @@ function registerReview(program2) {
|
|
|
23069
23379
|
}
|
|
23070
23380
|
|
|
23071
23381
|
// src/commands/seq/seqAuth.ts
|
|
23072
|
-
import
|
|
23382
|
+
import chalk193 from "chalk";
|
|
23073
23383
|
|
|
23074
23384
|
// src/commands/seq/loadConnections.ts
|
|
23075
23385
|
function loadConnections2() {
|
|
@@ -23098,10 +23408,10 @@ function setDefaultConnection(name) {
|
|
|
23098
23408
|
}
|
|
23099
23409
|
|
|
23100
23410
|
// src/shared/assertUniqueName.ts
|
|
23101
|
-
import
|
|
23411
|
+
import chalk192 from "chalk";
|
|
23102
23412
|
function assertUniqueName(existingNames, name) {
|
|
23103
23413
|
if (existingNames.includes(name)) {
|
|
23104
|
-
console.error(
|
|
23414
|
+
console.error(chalk192.red(`Connection "${name}" already exists.`));
|
|
23105
23415
|
process.exit(1);
|
|
23106
23416
|
}
|
|
23107
23417
|
}
|
|
@@ -23119,7 +23429,7 @@ async function promptConnection2(existingNames) {
|
|
|
23119
23429
|
var seqAuth = createConnectionAuth({
|
|
23120
23430
|
load: loadConnections2,
|
|
23121
23431
|
save: saveConnections2,
|
|
23122
|
-
format: (c) => `${
|
|
23432
|
+
format: (c) => `${chalk193.bold(c.name)} ${c.url}`,
|
|
23123
23433
|
promptNew: promptConnection2,
|
|
23124
23434
|
onFirst: (c) => setDefaultConnection(c.name)
|
|
23125
23435
|
});
|
|
@@ -23139,10 +23449,10 @@ var seqConfigHelp = [
|
|
|
23139
23449
|
];
|
|
23140
23450
|
|
|
23141
23451
|
// src/commands/seq/seqQuery.ts
|
|
23142
|
-
import
|
|
23452
|
+
import chalk197 from "chalk";
|
|
23143
23453
|
|
|
23144
23454
|
// src/commands/seq/fetchSeq.ts
|
|
23145
|
-
import
|
|
23455
|
+
import chalk194 from "chalk";
|
|
23146
23456
|
async function fetchSeq(conn, path71, params) {
|
|
23147
23457
|
const url = `${conn.url}${path71}?${params}`;
|
|
23148
23458
|
const response = await fetch(url, {
|
|
@@ -23153,7 +23463,7 @@ async function fetchSeq(conn, path71, params) {
|
|
|
23153
23463
|
});
|
|
23154
23464
|
if (!response.ok) {
|
|
23155
23465
|
const body = await response.text();
|
|
23156
|
-
console.error(
|
|
23466
|
+
console.error(chalk194.red(`Seq returned ${response.status}: ${body}`));
|
|
23157
23467
|
process.exit(1);
|
|
23158
23468
|
}
|
|
23159
23469
|
return response;
|
|
@@ -23212,23 +23522,23 @@ async function fetchSeqEvents(conn, params) {
|
|
|
23212
23522
|
}
|
|
23213
23523
|
|
|
23214
23524
|
// src/commands/seq/formatEvent.ts
|
|
23215
|
-
import
|
|
23525
|
+
import chalk195 from "chalk";
|
|
23216
23526
|
function levelColor(level) {
|
|
23217
23527
|
switch (level) {
|
|
23218
23528
|
case "Fatal":
|
|
23219
|
-
return
|
|
23529
|
+
return chalk195.bgRed.white;
|
|
23220
23530
|
case "Error":
|
|
23221
|
-
return
|
|
23531
|
+
return chalk195.red;
|
|
23222
23532
|
case "Warning":
|
|
23223
|
-
return
|
|
23533
|
+
return chalk195.yellow;
|
|
23224
23534
|
case "Information":
|
|
23225
|
-
return
|
|
23535
|
+
return chalk195.cyan;
|
|
23226
23536
|
case "Debug":
|
|
23227
|
-
return
|
|
23537
|
+
return chalk195.gray;
|
|
23228
23538
|
case "Verbose":
|
|
23229
|
-
return
|
|
23539
|
+
return chalk195.dim;
|
|
23230
23540
|
default:
|
|
23231
|
-
return
|
|
23541
|
+
return chalk195.white;
|
|
23232
23542
|
}
|
|
23233
23543
|
}
|
|
23234
23544
|
function levelAbbrev(level) {
|
|
@@ -23269,12 +23579,12 @@ function formatTimestamp(iso) {
|
|
|
23269
23579
|
function formatEvent(event) {
|
|
23270
23580
|
const color = levelColor(event.Level);
|
|
23271
23581
|
const abbrev = levelAbbrev(event.Level);
|
|
23272
|
-
const ts8 =
|
|
23582
|
+
const ts8 = chalk195.dim(formatTimestamp(event.Timestamp));
|
|
23273
23583
|
const msg = renderMessage(event);
|
|
23274
23584
|
const lines = [`${ts8} ${color(`[${abbrev}]`)} ${msg}`];
|
|
23275
23585
|
if (event.Exception) {
|
|
23276
23586
|
for (const line of event.Exception.split("\n")) {
|
|
23277
|
-
lines.push(
|
|
23587
|
+
lines.push(chalk195.red(` ${line}`));
|
|
23278
23588
|
}
|
|
23279
23589
|
}
|
|
23280
23590
|
return lines.join("\n");
|
|
@@ -23307,11 +23617,11 @@ function rejectTimestampFilter(filter) {
|
|
|
23307
23617
|
}
|
|
23308
23618
|
|
|
23309
23619
|
// src/shared/resolveNamedConnection.ts
|
|
23310
|
-
import
|
|
23620
|
+
import chalk196 from "chalk";
|
|
23311
23621
|
function resolveNamedConnection(connections, requested, defaultName, kind, authCommand) {
|
|
23312
23622
|
if (connections.length === 0) {
|
|
23313
23623
|
console.error(
|
|
23314
|
-
|
|
23624
|
+
chalk196.red(
|
|
23315
23625
|
`No ${kind} connections configured. Run '${authCommand}' first.`
|
|
23316
23626
|
)
|
|
23317
23627
|
);
|
|
@@ -23320,7 +23630,7 @@ function resolveNamedConnection(connections, requested, defaultName, kind, authC
|
|
|
23320
23630
|
const target = requested ?? defaultName ?? connections[0].name;
|
|
23321
23631
|
const connection = connections.find((c) => c.name === target);
|
|
23322
23632
|
if (!connection) {
|
|
23323
|
-
console.error(
|
|
23633
|
+
console.error(chalk196.red(`${kind} connection "${target}" not found.`));
|
|
23324
23634
|
process.exit(1);
|
|
23325
23635
|
}
|
|
23326
23636
|
return connection;
|
|
@@ -23349,7 +23659,7 @@ async function seqQuery(filter, options2) {
|
|
|
23349
23659
|
new URLSearchParams({ filter, count: String(count7) })
|
|
23350
23660
|
);
|
|
23351
23661
|
if (events.length === 0) {
|
|
23352
|
-
console.log(
|
|
23662
|
+
console.log(chalk197.yellow("No events found."));
|
|
23353
23663
|
return;
|
|
23354
23664
|
}
|
|
23355
23665
|
if (options2.json) {
|
|
@@ -23360,11 +23670,11 @@ async function seqQuery(filter, options2) {
|
|
|
23360
23670
|
for (const event of chronological) {
|
|
23361
23671
|
console.log(formatEvent(event));
|
|
23362
23672
|
}
|
|
23363
|
-
console.log(
|
|
23673
|
+
console.log(chalk197.dim(`
|
|
23364
23674
|
${events.length} events`));
|
|
23365
23675
|
if (events.length >= count7) {
|
|
23366
23676
|
console.log(
|
|
23367
|
-
|
|
23677
|
+
chalk197.yellow(
|
|
23368
23678
|
`Results limited to ${count7}. Use --count to retrieve more.`
|
|
23369
23679
|
)
|
|
23370
23680
|
);
|
|
@@ -23372,10 +23682,10 @@ ${events.length} events`));
|
|
|
23372
23682
|
}
|
|
23373
23683
|
|
|
23374
23684
|
// src/shared/setNamedDefaultConnection.ts
|
|
23375
|
-
import
|
|
23685
|
+
import chalk198 from "chalk";
|
|
23376
23686
|
function setNamedDefaultConnection(connections, name, setDefault, kind) {
|
|
23377
23687
|
if (!connections.find((c) => c.name === name)) {
|
|
23378
|
-
console.error(
|
|
23688
|
+
console.error(chalk198.red(`Connection "${name}" not found.`));
|
|
23379
23689
|
process.exit(1);
|
|
23380
23690
|
}
|
|
23381
23691
|
setDefault(name);
|
|
@@ -23424,7 +23734,7 @@ function registerSignal(program2) {
|
|
|
23424
23734
|
}
|
|
23425
23735
|
|
|
23426
23736
|
// src/commands/sql/sqlAuth.ts
|
|
23427
|
-
import
|
|
23737
|
+
import chalk200 from "chalk";
|
|
23428
23738
|
|
|
23429
23739
|
// src/commands/sql/loadConnections.ts
|
|
23430
23740
|
function loadConnections3() {
|
|
@@ -23453,7 +23763,7 @@ function setDefaultConnection2(name) {
|
|
|
23453
23763
|
}
|
|
23454
23764
|
|
|
23455
23765
|
// src/commands/sql/promptConnection.ts
|
|
23456
|
-
import
|
|
23766
|
+
import chalk199 from "chalk";
|
|
23457
23767
|
async function promptConnection3(existingNames) {
|
|
23458
23768
|
const name = await promptInput("name", "Connection name:", "default");
|
|
23459
23769
|
assertUniqueName(existingNames, name);
|
|
@@ -23461,7 +23771,7 @@ async function promptConnection3(existingNames) {
|
|
|
23461
23771
|
const portStr = await promptInput("port", "Port:", "1433");
|
|
23462
23772
|
const port = Number.parseInt(portStr, 10);
|
|
23463
23773
|
if (!Number.isFinite(port)) {
|
|
23464
|
-
console.error(
|
|
23774
|
+
console.error(chalk199.red(`Invalid port "${portStr}".`));
|
|
23465
23775
|
process.exit(1);
|
|
23466
23776
|
}
|
|
23467
23777
|
const user = await promptInput("user", "User:");
|
|
@@ -23474,13 +23784,13 @@ async function promptConnection3(existingNames) {
|
|
|
23474
23784
|
var sqlAuth = createConnectionAuth({
|
|
23475
23785
|
load: loadConnections3,
|
|
23476
23786
|
save: saveConnections3,
|
|
23477
|
-
format: (c) => `${
|
|
23787
|
+
format: (c) => `${chalk200.bold(c.name)} ${c.server}:${c.port}/${c.database} (${c.user})`,
|
|
23478
23788
|
promptNew: promptConnection3,
|
|
23479
23789
|
onFirst: (c) => setDefaultConnection2(c.name)
|
|
23480
23790
|
});
|
|
23481
23791
|
|
|
23482
23792
|
// src/commands/sql/printTable.ts
|
|
23483
|
-
import
|
|
23793
|
+
import chalk201 from "chalk";
|
|
23484
23794
|
function formatCell(value) {
|
|
23485
23795
|
if (value === null || value === void 0) return "";
|
|
23486
23796
|
if (value instanceof Date) return value.toISOString();
|
|
@@ -23489,7 +23799,7 @@ function formatCell(value) {
|
|
|
23489
23799
|
}
|
|
23490
23800
|
function printTable(rows) {
|
|
23491
23801
|
if (rows.length === 0) {
|
|
23492
|
-
console.log(
|
|
23802
|
+
console.log(chalk201.yellow("(no rows)"));
|
|
23493
23803
|
return;
|
|
23494
23804
|
}
|
|
23495
23805
|
const columns = Object.keys(rows[0]);
|
|
@@ -23497,13 +23807,13 @@ function printTable(rows) {
|
|
|
23497
23807
|
(col) => Math.max(col.length, ...rows.map((r) => formatCell(r[col]).length))
|
|
23498
23808
|
);
|
|
23499
23809
|
const header = columns.map((c, i) => c.padEnd(widths[i])).join(" ");
|
|
23500
|
-
console.log(
|
|
23501
|
-
console.log(
|
|
23810
|
+
console.log(chalk201.dim(header));
|
|
23811
|
+
console.log(chalk201.dim("-".repeat(header.length)));
|
|
23502
23812
|
for (const row of rows) {
|
|
23503
23813
|
const line = columns.map((c, i) => formatCell(row[c]).padEnd(widths[i])).join(" ");
|
|
23504
23814
|
console.log(line);
|
|
23505
23815
|
}
|
|
23506
|
-
console.log(
|
|
23816
|
+
console.log(chalk201.dim(`
|
|
23507
23817
|
${rows.length} row${rows.length === 1 ? "" : "s"}`));
|
|
23508
23818
|
}
|
|
23509
23819
|
|
|
@@ -23577,7 +23887,7 @@ var sqlConfigHelp = [
|
|
|
23577
23887
|
];
|
|
23578
23888
|
|
|
23579
23889
|
// src/commands/sql/sqlMutate.ts
|
|
23580
|
-
import
|
|
23890
|
+
import chalk202 from "chalk";
|
|
23581
23891
|
|
|
23582
23892
|
// src/commands/sql/isMutation.ts
|
|
23583
23893
|
var MUTATION_KEYWORDS = [
|
|
@@ -23611,7 +23921,7 @@ function isMutation(sql25) {
|
|
|
23611
23921
|
async function sqlMutate(query, connectionName) {
|
|
23612
23922
|
if (!isMutation(query)) {
|
|
23613
23923
|
console.error(
|
|
23614
|
-
|
|
23924
|
+
chalk202.red(
|
|
23615
23925
|
"assist sql mutate refuses non-mutating statements. Use `assist sql query` instead."
|
|
23616
23926
|
)
|
|
23617
23927
|
);
|
|
@@ -23621,18 +23931,18 @@ async function sqlMutate(query, connectionName) {
|
|
|
23621
23931
|
const pool = await sqlConnect(conn);
|
|
23622
23932
|
try {
|
|
23623
23933
|
const result = await pool.request().query(query);
|
|
23624
|
-
console.log(
|
|
23934
|
+
console.log(chalk202.dim(`${result.rowsAffected.join(", ")} row(s) affected`));
|
|
23625
23935
|
} finally {
|
|
23626
23936
|
await pool.close();
|
|
23627
23937
|
}
|
|
23628
23938
|
}
|
|
23629
23939
|
|
|
23630
23940
|
// src/commands/sql/sqlQuery.ts
|
|
23631
|
-
import
|
|
23941
|
+
import chalk203 from "chalk";
|
|
23632
23942
|
async function sqlQuery(query, connectionName) {
|
|
23633
23943
|
if (isMutation(query)) {
|
|
23634
23944
|
console.error(
|
|
23635
|
-
|
|
23945
|
+
chalk203.red(
|
|
23636
23946
|
"assist sql query refuses mutating statements. Use `assist sql mutate` instead."
|
|
23637
23947
|
)
|
|
23638
23948
|
);
|
|
@@ -23647,7 +23957,7 @@ async function sqlQuery(query, connectionName) {
|
|
|
23647
23957
|
printTable(rows);
|
|
23648
23958
|
} else {
|
|
23649
23959
|
console.log(
|
|
23650
|
-
|
|
23960
|
+
chalk203.dim(`${result.rowsAffected.join(", ")} row(s) affected`)
|
|
23651
23961
|
);
|
|
23652
23962
|
}
|
|
23653
23963
|
} finally {
|
|
@@ -24462,7 +24772,7 @@ function registerVoice(program2) {
|
|
|
24462
24772
|
|
|
24463
24773
|
// src/commands/roam/auth.ts
|
|
24464
24774
|
import { randomBytes } from "crypto";
|
|
24465
|
-
import
|
|
24775
|
+
import chalk204 from "chalk";
|
|
24466
24776
|
|
|
24467
24777
|
// src/commands/roam/waitForCallback.ts
|
|
24468
24778
|
import { createServer as createServer3 } from "http";
|
|
@@ -24593,13 +24903,13 @@ async function auth() {
|
|
|
24593
24903
|
saveGlobalConfig(config);
|
|
24594
24904
|
const state = randomBytes(16).toString("hex");
|
|
24595
24905
|
console.log(
|
|
24596
|
-
|
|
24906
|
+
chalk204.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
|
|
24597
24907
|
);
|
|
24598
|
-
console.log(
|
|
24599
|
-
console.log(
|
|
24600
|
-
console.log(
|
|
24908
|
+
console.log(chalk204.white("http://localhost:14523/callback\n"));
|
|
24909
|
+
console.log(chalk204.blue("Opening browser for authorization..."));
|
|
24910
|
+
console.log(chalk204.dim("Waiting for authorization callback..."));
|
|
24601
24911
|
const { code, redirectUri } = await authorizeInBrowser(clientId, state);
|
|
24602
|
-
console.log(
|
|
24912
|
+
console.log(chalk204.dim("Exchanging code for tokens..."));
|
|
24603
24913
|
const tokens = await exchangeToken({
|
|
24604
24914
|
code,
|
|
24605
24915
|
clientId,
|
|
@@ -24615,12 +24925,12 @@ async function auth() {
|
|
|
24615
24925
|
};
|
|
24616
24926
|
saveGlobalConfig(config);
|
|
24617
24927
|
console.log(
|
|
24618
|
-
|
|
24928
|
+
chalk204.green("Roam credentials and tokens saved to ~/.assist.yml")
|
|
24619
24929
|
);
|
|
24620
24930
|
}
|
|
24621
24931
|
|
|
24622
24932
|
// src/commands/roam/postRoamActivity.ts
|
|
24623
|
-
import { execFileSync as
|
|
24933
|
+
import { execFileSync as execFileSync10 } from "child_process";
|
|
24624
24934
|
import { readdirSync as readdirSync11, readFileSync as readFileSync47, statSync as statSync9 } from "fs";
|
|
24625
24935
|
import { join as join63 } from "path";
|
|
24626
24936
|
function findPortFile(roamDir) {
|
|
@@ -24653,7 +24963,7 @@ function postRoamActivity(app, event) {
|
|
|
24653
24963
|
}
|
|
24654
24964
|
const url = `http://127.0.0.1:${port}/api/v1/activity/${app}/${event}?pid=${app === "codex" ? 99998 : 99999}`;
|
|
24655
24965
|
try {
|
|
24656
|
-
|
|
24966
|
+
execFileSync10("curl", ["-sf", "--max-time", "0.2", "-X", "POST", url], {
|
|
24657
24967
|
stdio: "ignore"
|
|
24658
24968
|
});
|
|
24659
24969
|
} catch {
|
|
@@ -24862,13 +25172,13 @@ function runPreCommands(pre, cwd) {
|
|
|
24862
25172
|
}
|
|
24863
25173
|
|
|
24864
25174
|
// src/commands/run/spawnRunCommand.ts
|
|
24865
|
-
import { execFileSync as
|
|
25175
|
+
import { execFileSync as execFileSync11, spawn as spawn8 } from "child_process";
|
|
24866
25176
|
import { existsSync as existsSync54 } from "fs";
|
|
24867
25177
|
import { dirname as dirname27, join as join64, resolve as resolve15 } from "path";
|
|
24868
25178
|
function resolveCommand2(command) {
|
|
24869
25179
|
if (process.platform !== "win32" || command !== "bash") return command;
|
|
24870
25180
|
try {
|
|
24871
|
-
const gitPath =
|
|
25181
|
+
const gitPath = execFileSync11("where", ["git"], { encoding: "utf8" }).trim().split("\r\n")[0];
|
|
24872
25182
|
const gitRoot = resolve15(dirname27(gitPath), "..");
|
|
24873
25183
|
const gitBash = join64(gitRoot, "bin", "bash.exe");
|
|
24874
25184
|
if (existsSync54(gitBash)) return gitBash;
|
|
@@ -25158,7 +25468,7 @@ import { execSync as execSync58 } from "child_process";
|
|
|
25158
25468
|
import { existsSync as existsSync56, mkdirSync as mkdirSync24, unlinkSync as unlinkSync21, writeFileSync as writeFileSync42 } from "fs";
|
|
25159
25469
|
import { tmpdir as tmpdir8 } from "os";
|
|
25160
25470
|
import { join as join67, resolve as resolve17 } from "path";
|
|
25161
|
-
import
|
|
25471
|
+
import chalk205 from "chalk";
|
|
25162
25472
|
|
|
25163
25473
|
// src/commands/screenshot/captureWindowPs1.ts
|
|
25164
25474
|
var captureWindowPs1 = `
|
|
@@ -25309,23 +25619,23 @@ function screenshot(processName) {
|
|
|
25309
25619
|
const config = loadConfig();
|
|
25310
25620
|
const outputDir = resolve17(config.screenshot.outputDir);
|
|
25311
25621
|
const outputPath = buildOutputPath(outputDir, processName);
|
|
25312
|
-
console.log(
|
|
25622
|
+
console.log(chalk205.gray(`Capturing window for process "${processName}" ...`));
|
|
25313
25623
|
try {
|
|
25314
25624
|
runPowerShellScript(processName, outputPath);
|
|
25315
|
-
console.log(
|
|
25625
|
+
console.log(chalk205.green(`Screenshot saved: ${outputPath}`));
|
|
25316
25626
|
} catch (error) {
|
|
25317
25627
|
const msg = error instanceof Error ? error.message : String(error);
|
|
25318
|
-
console.error(
|
|
25628
|
+
console.error(chalk205.red(`Failed to capture screenshot: ${msg}`));
|
|
25319
25629
|
process.exit(1);
|
|
25320
25630
|
}
|
|
25321
25631
|
}
|
|
25322
25632
|
|
|
25323
25633
|
// src/commands/sessions/daemon/listDaemonPids.ts
|
|
25324
|
-
import { execFileSync as
|
|
25634
|
+
import { execFileSync as execFileSync12 } from "child_process";
|
|
25325
25635
|
function listDaemonPids() {
|
|
25326
25636
|
if (process.platform === "win32") return [];
|
|
25327
25637
|
try {
|
|
25328
|
-
const out =
|
|
25638
|
+
const out = execFileSync12("ps", ["-eo", "pid=,args="], {
|
|
25329
25639
|
encoding: "utf8"
|
|
25330
25640
|
});
|
|
25331
25641
|
return out.split("\n").filter((line) => line.includes("assist") && / daemon run\b/.test(line)).map((line) => Number.parseInt(line.trim(), 10)).filter((pid) => Number.isInteger(pid));
|
|
@@ -25684,17 +25994,6 @@ function broadcast(clients, msg) {
|
|
|
25684
25994
|
}
|
|
25685
25995
|
}
|
|
25686
25996
|
|
|
25687
|
-
// src/commands/sessions/daemon/originForCwd.ts
|
|
25688
|
-
var cache = /* @__PURE__ */ new Map();
|
|
25689
|
-
function originForCwd(cwd) {
|
|
25690
|
-
if (!cwd) return void 0;
|
|
25691
|
-
const cached = cache.get(cwd);
|
|
25692
|
-
if (cached !== void 0) return cached;
|
|
25693
|
-
const origin = getCurrentOrigin(cwd);
|
|
25694
|
-
cache.set(cwd, origin);
|
|
25695
|
-
return origin;
|
|
25696
|
-
}
|
|
25697
|
-
|
|
25698
25997
|
// src/commands/sessions/daemon/toSessionInfo.ts
|
|
25699
25998
|
function toSessionInfo({
|
|
25700
25999
|
id,
|
|
@@ -25744,6 +26043,7 @@ function toSessionInfo({
|
|
|
25744
26043
|
remoteOrigin: serverOrigin ?? originForCwd(cwd),
|
|
25745
26044
|
assistArgs,
|
|
25746
26045
|
cwd,
|
|
26046
|
+
repoGroup: repoGroupForCwd(cwd),
|
|
25747
26047
|
restored,
|
|
25748
26048
|
error,
|
|
25749
26049
|
activity: activity2,
|
|
@@ -26060,116 +26360,9 @@ function otherTreeHolders(sessions, session) {
|
|
|
26060
26360
|
// src/commands/sessions/daemon/worktree/reapWorktree.ts
|
|
26061
26361
|
import { existsSync as existsSync59 } from "fs";
|
|
26062
26362
|
|
|
26063
|
-
// src/commands/sessions/daemon/worktree/git.ts
|
|
26064
|
-
import { execFile as execFile7, execFileSync as execFileSync12 } from "child_process";
|
|
26065
|
-
function isWindowsPath(cwd) {
|
|
26066
|
-
return /^[A-Za-z]:[\\/]/.test(cwd);
|
|
26067
|
-
}
|
|
26068
|
-
function gitInvocation(cwd, args) {
|
|
26069
|
-
const windows = isWindowsPath(cwd);
|
|
26070
|
-
return {
|
|
26071
|
-
file: windows ? "git.exe" : "git",
|
|
26072
|
-
argv: windows ? ["-C", cwd, ...args] : args,
|
|
26073
|
-
options: { encoding: "utf8", ...windows ? {} : { cwd } }
|
|
26074
|
-
};
|
|
26075
|
-
}
|
|
26076
|
-
function git3(cwd, args) {
|
|
26077
|
-
const { file, argv, options: options2 } = gitInvocation(cwd, args);
|
|
26078
|
-
return new Promise((resolve20, reject) => {
|
|
26079
|
-
execFile7(file, argv, options2, (error, stdout) => {
|
|
26080
|
-
if (error) reject(error);
|
|
26081
|
-
else resolve20(stdout.toString());
|
|
26082
|
-
});
|
|
26083
|
-
});
|
|
26084
|
-
}
|
|
26085
|
-
async function gitOrNull(cwd, args) {
|
|
26086
|
-
try {
|
|
26087
|
-
return (await git3(cwd, args)).trim() || null;
|
|
26088
|
-
} catch {
|
|
26089
|
-
return null;
|
|
26090
|
-
}
|
|
26091
|
-
}
|
|
26092
|
-
async function gitResult(cwd, args) {
|
|
26093
|
-
try {
|
|
26094
|
-
return { ok: true, out: (await git3(cwd, args)).trim() };
|
|
26095
|
-
} catch (error) {
|
|
26096
|
-
return {
|
|
26097
|
-
ok: false,
|
|
26098
|
-
error: error instanceof Error ? error.message : String(error)
|
|
26099
|
-
};
|
|
26100
|
-
}
|
|
26101
|
-
}
|
|
26102
|
-
function gitSyncResult(cwd, args) {
|
|
26103
|
-
try {
|
|
26104
|
-
return { ok: true, out: gitSync(cwd, args).trim() };
|
|
26105
|
-
} catch (error) {
|
|
26106
|
-
return {
|
|
26107
|
-
ok: false,
|
|
26108
|
-
error: error instanceof Error ? error.message : String(error)
|
|
26109
|
-
};
|
|
26110
|
-
}
|
|
26111
|
-
}
|
|
26112
|
-
function gitSync(cwd, args) {
|
|
26113
|
-
const { file, argv, options: options2 } = gitInvocation(cwd, args);
|
|
26114
|
-
return execFileSync12(file, argv, {
|
|
26115
|
-
...options2,
|
|
26116
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
26117
|
-
}).toString();
|
|
26118
|
-
}
|
|
26119
|
-
function gitSyncOrNull(cwd, args) {
|
|
26120
|
-
try {
|
|
26121
|
-
return gitSync(cwd, args).trim() || null;
|
|
26122
|
-
} catch {
|
|
26123
|
-
return null;
|
|
26124
|
-
}
|
|
26125
|
-
}
|
|
26126
|
-
|
|
26127
|
-
// src/commands/sessions/daemon/worktree/listWorktreePaths.ts
|
|
26128
|
-
function listWorktreePaths(cwd) {
|
|
26129
|
-
const out = gitSyncOrNull(cwd, ["worktree", "list", "--porcelain"]);
|
|
26130
|
-
if (!out) return [];
|
|
26131
|
-
return out.split("\n").filter((line) => line.startsWith("worktree ")).map((line) => line.slice("worktree ".length).trim());
|
|
26132
|
-
}
|
|
26133
|
-
function mainWorktree(cwd) {
|
|
26134
|
-
return listWorktreePaths(cwd)[0] ?? null;
|
|
26135
|
-
}
|
|
26136
|
-
function listLocalBranches(cwd) {
|
|
26137
|
-
const out = gitSyncOrNull(cwd, [
|
|
26138
|
-
"for-each-ref",
|
|
26139
|
-
"--format=%(refname:short)",
|
|
26140
|
-
"refs/heads"
|
|
26141
|
-
]);
|
|
26142
|
-
return out ? out.split("\n").map((line) => line.trim()) : [];
|
|
26143
|
-
}
|
|
26144
|
-
function gitCommonDir(cwd) {
|
|
26145
|
-
return gitSyncOrNull(cwd, [
|
|
26146
|
-
"rev-parse",
|
|
26147
|
-
"--path-format=absolute",
|
|
26148
|
-
"--git-common-dir"
|
|
26149
|
-
]);
|
|
26150
|
-
}
|
|
26151
|
-
|
|
26152
|
-
// src/commands/sessions/daemon/worktree/readWorktreeRegistry.ts
|
|
26153
|
-
var REGISTRY_FILE = "worktrees.json";
|
|
26154
|
-
function readWorktreeRegistry() {
|
|
26155
|
-
const data = loadJson(REGISTRY_FILE);
|
|
26156
|
-
return Object.entries(data).map(([path71, record]) => ({ path: path71, ...record }));
|
|
26157
|
-
}
|
|
26158
|
-
function recordWorktree(path71, clone, origin) {
|
|
26159
|
-
const data = loadJson(REGISTRY_FILE);
|
|
26160
|
-
data[path71] = { clone, origin };
|
|
26161
|
-
saveJson(REGISTRY_FILE, data);
|
|
26162
|
-
}
|
|
26163
|
-
function forgetWorktree(path71) {
|
|
26164
|
-
const data = loadJson(REGISTRY_FILE);
|
|
26165
|
-
if (!(path71 in data)) return;
|
|
26166
|
-
delete data[path71];
|
|
26167
|
-
saveJson(REGISTRY_FILE, data);
|
|
26168
|
-
}
|
|
26169
|
-
|
|
26170
26363
|
// src/commands/sessions/daemon/worktree/removeTree.ts
|
|
26171
26364
|
async function removeTree(clone, worktreePath, force) {
|
|
26172
|
-
const remove2 = (forced) =>
|
|
26365
|
+
const remove2 = (forced) => git2(clone, [
|
|
26173
26366
|
"worktree",
|
|
26174
26367
|
"remove",
|
|
26175
26368
|
...forced ? ["--force"] : [],
|
|
@@ -26285,7 +26478,7 @@ async function deleteBranch(clone, branch2) {
|
|
|
26285
26478
|
const current = await gitOrNull(clone, ["symbolic-ref", "--short", "HEAD"]);
|
|
26286
26479
|
if (branch2 === current) return;
|
|
26287
26480
|
try {
|
|
26288
|
-
await
|
|
26481
|
+
await git2(clone, ["branch", "-D", branch2]);
|
|
26289
26482
|
} catch {
|
|
26290
26483
|
}
|
|
26291
26484
|
}
|
|
@@ -27870,7 +28063,7 @@ async function reclaimVanishedWorktrees(clone, paths) {
|
|
|
27870
28063
|
}
|
|
27871
28064
|
async function pruneBookkeeping(clone) {
|
|
27872
28065
|
try {
|
|
27873
|
-
await
|
|
28066
|
+
await git2(clone, ["worktree", "prune"]);
|
|
27874
28067
|
daemonLog(`worktree bookkeeping pruned for clone ${clone}`);
|
|
27875
28068
|
} catch (error) {
|
|
27876
28069
|
daemonLog(
|
|
@@ -27881,7 +28074,7 @@ async function pruneBookkeeping(clone) {
|
|
|
27881
28074
|
async function reclaimBranch(clone, branch2) {
|
|
27882
28075
|
if (!listLocalBranches(clone).includes(branch2)) return true;
|
|
27883
28076
|
try {
|
|
27884
|
-
await
|
|
28077
|
+
await git2(clone, ["branch", "-d", branch2]);
|
|
27885
28078
|
daemonLog(`stale worktree branch ${branch2} pruned from clone ${clone}`);
|
|
27886
28079
|
return true;
|
|
27887
28080
|
} catch {
|
|
@@ -28617,14 +28810,6 @@ function runOnWindowsHost(command, timeoutMs) {
|
|
|
28617
28810
|
});
|
|
28618
28811
|
}
|
|
28619
28812
|
|
|
28620
|
-
// src/commands/sessions/daemon/isWindowsCwd.ts
|
|
28621
|
-
function isWindowsCwd(cwd) {
|
|
28622
|
-
return /^[A-Za-z]:[\\/]/.test(cwd);
|
|
28623
|
-
}
|
|
28624
|
-
function shouldProxyToWindows(cwd) {
|
|
28625
|
-
return detectPlatform() === "wsl" && isWindowsCwd(cwd);
|
|
28626
|
-
}
|
|
28627
|
-
|
|
28628
28813
|
// src/commands/sessions/daemon/isWindowsCreate.ts
|
|
28629
28814
|
function isWindowsCreate(data) {
|
|
28630
28815
|
return typeof data.cwd === "string" && shouldProxyToWindows(data.cwd);
|
|
@@ -29389,10 +29574,18 @@ function safeParse2(line) {
|
|
|
29389
29574
|
}
|
|
29390
29575
|
}
|
|
29391
29576
|
|
|
29577
|
+
// src/commands/sessions/daemon/withRepoGroups.ts
|
|
29578
|
+
function withRepoGroups(sessions) {
|
|
29579
|
+
return sessions.map((session) => {
|
|
29580
|
+
const repoGroup = repoGroupForCwd(session.cwd);
|
|
29581
|
+
return repoGroup ? { ...session, repoGroup } : session;
|
|
29582
|
+
});
|
|
29583
|
+
}
|
|
29584
|
+
|
|
29392
29585
|
// src/commands/sessions/daemon/lifecycleHandlers.ts
|
|
29393
29586
|
function handleHistory(client) {
|
|
29394
29587
|
discoverSessions().then(
|
|
29395
|
-
(sessions) => sendTo(client, { type: "history", sessions })
|
|
29588
|
+
(sessions) => sendTo(client, { type: "history", sessions: withRepoGroups(sessions) })
|
|
29396
29589
|
);
|
|
29397
29590
|
}
|
|
29398
29591
|
function handleFetchTranscript(client, _manager, data) {
|
|
@@ -29750,7 +29943,7 @@ var sessionsConfigHelp = [
|
|
|
29750
29943
|
|
|
29751
29944
|
// src/commands/sessions/summarise/index.ts
|
|
29752
29945
|
import * as fs41 from "fs";
|
|
29753
|
-
import
|
|
29946
|
+
import chalk206 from "chalk";
|
|
29754
29947
|
|
|
29755
29948
|
// src/commands/sessions/summarise/shared.ts
|
|
29756
29949
|
import * as fs40 from "fs";
|
|
@@ -29824,22 +30017,22 @@ ${firstMessage}`);
|
|
|
29824
30017
|
async function summarise2(options2) {
|
|
29825
30018
|
const files = await discoverSessionFiles();
|
|
29826
30019
|
if (files.length === 0) {
|
|
29827
|
-
console.log(
|
|
30020
|
+
console.log(chalk206.yellow("No sessions found."));
|
|
29828
30021
|
return;
|
|
29829
30022
|
}
|
|
29830
30023
|
const toProcess = selectCandidates(files, options2);
|
|
29831
30024
|
if (toProcess.length === 0) {
|
|
29832
|
-
console.log(
|
|
30025
|
+
console.log(chalk206.green("All sessions already summarised."));
|
|
29833
30026
|
return;
|
|
29834
30027
|
}
|
|
29835
30028
|
console.log(
|
|
29836
|
-
|
|
30029
|
+
chalk206.cyan(
|
|
29837
30030
|
`Summarising ${toProcess.length} session(s) (${files.length} total)\u2026`
|
|
29838
30031
|
)
|
|
29839
30032
|
);
|
|
29840
30033
|
const { succeeded, failed: failed2 } = processSessions(toProcess);
|
|
29841
30034
|
console.log(
|
|
29842
|
-
|
|
30035
|
+
chalk206.green(`Done: ${succeeded} summarised`) + (failed2 > 0 ? chalk206.yellow(`, ${failed2} skipped`) : "")
|
|
29843
30036
|
);
|
|
29844
30037
|
}
|
|
29845
30038
|
function selectCandidates(files, options2) {
|
|
@@ -29859,16 +30052,16 @@ function processSessions(files) {
|
|
|
29859
30052
|
let failed2 = 0;
|
|
29860
30053
|
for (let i = 0; i < files.length; i++) {
|
|
29861
30054
|
const file = files[i];
|
|
29862
|
-
process.stdout.write(
|
|
30055
|
+
process.stdout.write(chalk206.dim(` [${i + 1}/${files.length}] `));
|
|
29863
30056
|
const summary = summariseSession(file);
|
|
29864
30057
|
if (summary) {
|
|
29865
30058
|
writeSummary(file, summary);
|
|
29866
30059
|
succeeded++;
|
|
29867
|
-
process.stdout.write(`${
|
|
30060
|
+
process.stdout.write(`${chalk206.green("\u2713")} ${summary}
|
|
29868
30061
|
`);
|
|
29869
30062
|
} else {
|
|
29870
30063
|
failed2++;
|
|
29871
|
-
process.stdout.write(` ${
|
|
30064
|
+
process.stdout.write(` ${chalk206.yellow("skip")}
|
|
29872
30065
|
`);
|
|
29873
30066
|
}
|
|
29874
30067
|
}
|
|
@@ -29889,7 +30082,7 @@ function registerSessions(program2) {
|
|
|
29889
30082
|
}
|
|
29890
30083
|
|
|
29891
30084
|
// src/commands/statusLine.ts
|
|
29892
|
-
import
|
|
30085
|
+
import chalk208 from "chalk";
|
|
29893
30086
|
|
|
29894
30087
|
// src/shared/contextLevel.ts
|
|
29895
30088
|
function contextLevel(pct) {
|
|
@@ -29899,7 +30092,7 @@ function contextLevel(pct) {
|
|
|
29899
30092
|
}
|
|
29900
30093
|
|
|
29901
30094
|
// src/commands/buildLimitsSegment.ts
|
|
29902
|
-
import
|
|
30095
|
+
import chalk207 from "chalk";
|
|
29903
30096
|
|
|
29904
30097
|
// src/shared/rateLimitLevel.ts
|
|
29905
30098
|
var FIVE_HOUR_SECONDS = 5 * 3600;
|
|
@@ -29930,9 +30123,9 @@ function rateLimitLevel(pct, resetsAt, windowSeconds, now) {
|
|
|
29930
30123
|
|
|
29931
30124
|
// src/commands/buildLimitsSegment.ts
|
|
29932
30125
|
var LEVEL_COLOR = {
|
|
29933
|
-
ok:
|
|
29934
|
-
warn:
|
|
29935
|
-
over:
|
|
30126
|
+
ok: chalk207.green,
|
|
30127
|
+
warn: chalk207.yellow,
|
|
30128
|
+
over: chalk207.red
|
|
29936
30129
|
};
|
|
29937
30130
|
function formatLimit(pct, resetsAt, windowSeconds, fallbackLabel, now) {
|
|
29938
30131
|
const level = rateLimitLevel(pct, resetsAt, windowSeconds, now);
|
|
@@ -30028,7 +30221,7 @@ async function relayUsage(claudeSessionId, transcriptPath, usedPct) {
|
|
|
30028
30221
|
}
|
|
30029
30222
|
|
|
30030
30223
|
// src/commands/statusLine.ts
|
|
30031
|
-
|
|
30224
|
+
chalk208.level = 3;
|
|
30032
30225
|
function formatNumber(num) {
|
|
30033
30226
|
return num.toLocaleString("en-US");
|
|
30034
30227
|
}
|
|
@@ -30036,9 +30229,9 @@ function colorizePercent(pct) {
|
|
|
30036
30229
|
const label2 = `${Math.round(pct)}%`;
|
|
30037
30230
|
switch (contextLevel(pct)) {
|
|
30038
30231
|
case "red":
|
|
30039
|
-
return
|
|
30232
|
+
return chalk208.red(label2);
|
|
30040
30233
|
case "yellow":
|
|
30041
|
-
return
|
|
30234
|
+
return chalk208.yellow(label2);
|
|
30042
30235
|
default:
|
|
30043
30236
|
return label2;
|
|
30044
30237
|
}
|
|
@@ -30051,7 +30244,7 @@ async function statusLine() {
|
|
|
30051
30244
|
const usedPct = data.context_window.used_percentage ?? 0;
|
|
30052
30245
|
const dir = data.workspace?.current_dir ?? data.cwd;
|
|
30053
30246
|
const branch2 = dir ? readGitBranch(toGitCwd(dir)) : null;
|
|
30054
|
-
const branchSegment = branch2 ? `\u{1F33F}\uFE0F ${
|
|
30247
|
+
const branchSegment = branch2 ? `\u{1F33F}\uFE0F ${chalk208.cyan(branch2)} | ` : "";
|
|
30055
30248
|
console.log(
|
|
30056
30249
|
`${branchSegment}${model} | Tokens - ${formatNumber(totalIn)} \u2191 : ${formatNumber(totalOut)} \u2193 | Context - ${colorizePercent(usedPct)}${buildLimitsSegment(data.rate_limits)}`
|
|
30057
30250
|
);
|
|
@@ -30072,14 +30265,14 @@ import { fileURLToPath as fileURLToPath9 } from "url";
|
|
|
30072
30265
|
// src/commands/sync/syncClaudeMd.ts
|
|
30073
30266
|
import * as fs42 from "fs";
|
|
30074
30267
|
import * as path61 from "path";
|
|
30075
|
-
import
|
|
30268
|
+
import chalk210 from "chalk";
|
|
30076
30269
|
|
|
30077
30270
|
// src/commands/sync/printAutoConfirmHint.ts
|
|
30078
|
-
import
|
|
30271
|
+
import chalk209 from "chalk";
|
|
30079
30272
|
var autoConfirmHintCommand = "assist config set sync.autoConfirm true --global";
|
|
30080
30273
|
function printAutoConfirmHint() {
|
|
30081
30274
|
console.log(
|
|
30082
|
-
|
|
30275
|
+
chalk209.dim(
|
|
30083
30276
|
`Tip: run \`${autoConfirmHintCommand}\` to overwrite automatically next time`
|
|
30084
30277
|
)
|
|
30085
30278
|
);
|
|
@@ -30095,14 +30288,14 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
30095
30288
|
const targetContent = fs42.readFileSync(target, "utf8");
|
|
30096
30289
|
if (sourceContent !== targetContent) {
|
|
30097
30290
|
console.log(
|
|
30098
|
-
|
|
30291
|
+
chalk210.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
30099
30292
|
);
|
|
30100
30293
|
console.log();
|
|
30101
30294
|
printDiff(targetContent, sourceContent);
|
|
30102
30295
|
if (!options2?.yes) {
|
|
30103
30296
|
printAutoConfirmHint();
|
|
30104
30297
|
const confirm = await promptConfirm(
|
|
30105
|
-
|
|
30298
|
+
chalk210.red("Overwrite existing CLAUDE.md?"),
|
|
30106
30299
|
false
|
|
30107
30300
|
);
|
|
30108
30301
|
if (!confirm) {
|
|
@@ -30297,7 +30490,7 @@ function syncPi(claudeDir) {
|
|
|
30297
30490
|
// src/commands/sync/syncSettings.ts
|
|
30298
30491
|
import * as fs47 from "fs";
|
|
30299
30492
|
import * as path68 from "path";
|
|
30300
|
-
import
|
|
30493
|
+
import chalk211 from "chalk";
|
|
30301
30494
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
30302
30495
|
const source = path68.join(claudeDir, "settings.json");
|
|
30303
30496
|
const target = path68.join(targetBase, "settings.json");
|
|
@@ -30316,7 +30509,7 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
30316
30509
|
if (mergedContent !== normalizedTarget) {
|
|
30317
30510
|
if (!options2?.yes) {
|
|
30318
30511
|
console.log(
|
|
30319
|
-
|
|
30512
|
+
chalk211.yellow(
|
|
30320
30513
|
"\n\u26A0\uFE0F Warning: settings.json differs from existing file"
|
|
30321
30514
|
)
|
|
30322
30515
|
);
|
|
@@ -30324,7 +30517,7 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
30324
30517
|
printDiff(targetContent, mergedContent);
|
|
30325
30518
|
printAutoConfirmHint();
|
|
30326
30519
|
const confirm = await promptConfirm(
|
|
30327
|
-
|
|
30520
|
+
chalk211.red("Overwrite existing settings.json?"),
|
|
30328
30521
|
false
|
|
30329
30522
|
);
|
|
30330
30523
|
if (!confirm) {
|
|
@@ -30423,10 +30616,10 @@ async function update2() {
|
|
|
30423
30616
|
}
|
|
30424
30617
|
|
|
30425
30618
|
// src/reportCliError.ts
|
|
30426
|
-
import
|
|
30619
|
+
import chalk212 from "chalk";
|
|
30427
30620
|
function reportCliError(error) {
|
|
30428
30621
|
if (error instanceof InvalidItemIdError || error instanceof AmbiguousRepoConfigError || error instanceof UnknownRepoConfigError) {
|
|
30429
|
-
console.error(
|
|
30622
|
+
console.error(chalk212.red(error.message));
|
|
30430
30623
|
} else {
|
|
30431
30624
|
console.error(error);
|
|
30432
30625
|
}
|