@staff0rd/assist 0.274.0 → 0.275.1
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 +60 -60
- package/dist/index.js +459 -308
- package/package.json +6 -1
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Command } from "commander";
|
|
|
6
6
|
// package.json
|
|
7
7
|
var package_default = {
|
|
8
8
|
name: "@staff0rd/assist",
|
|
9
|
-
version: "0.
|
|
9
|
+
version: "0.275.1",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -29,6 +29,11 @@ var package_default = {
|
|
|
29
29
|
"check:types": "tsc --noEmit",
|
|
30
30
|
test: "vitest run"
|
|
31
31
|
},
|
|
32
|
+
overrides: {
|
|
33
|
+
lodash: "^4.18.0",
|
|
34
|
+
xml2js: "^0.5.0",
|
|
35
|
+
uuid: "^11.1.1"
|
|
36
|
+
},
|
|
32
37
|
keywords: [],
|
|
33
38
|
author: "",
|
|
34
39
|
license: "ISC",
|
|
@@ -119,10 +124,10 @@ import { stringify as stringifyYaml } from "yaml";
|
|
|
119
124
|
// src/shared/loadRawYaml.ts
|
|
120
125
|
import { existsSync, readFileSync } from "fs";
|
|
121
126
|
import { parse as parseYaml } from "yaml";
|
|
122
|
-
function loadRawYaml(
|
|
123
|
-
if (!existsSync(
|
|
127
|
+
function loadRawYaml(path54) {
|
|
128
|
+
if (!existsSync(path54)) return {};
|
|
124
129
|
try {
|
|
125
|
-
const content = readFileSync(
|
|
130
|
+
const content = readFileSync(path54, "utf-8");
|
|
126
131
|
return parseYaml(content) || {};
|
|
127
132
|
} catch {
|
|
128
133
|
return {};
|
|
@@ -1859,8 +1864,8 @@ var MACHINE_DIRECTIVES = [
|
|
|
1859
1864
|
"v8 ignore",
|
|
1860
1865
|
"c8 ignore"
|
|
1861
1866
|
];
|
|
1862
|
-
function isCommentExempt(
|
|
1863
|
-
const lower =
|
|
1867
|
+
function isCommentExempt(text3, markers) {
|
|
1868
|
+
const lower = text3.toLowerCase();
|
|
1864
1869
|
if (MACHINE_DIRECTIVES.some((d) => lower.includes(d))) return true;
|
|
1865
1870
|
return markers.some((m) => lower.includes(m.toLowerCase()));
|
|
1866
1871
|
}
|
|
@@ -1903,8 +1908,8 @@ function parseDiffAddedLines(diff2) {
|
|
|
1903
1908
|
|
|
1904
1909
|
// src/commands/verify/commentPolicy/findAddedComments.ts
|
|
1905
1910
|
var SOURCE_EXTENSIONS = [".ts", ".tsx", ".cts", ".mts", ".js", ".jsx"];
|
|
1906
|
-
function toSingleLine(
|
|
1907
|
-
return
|
|
1911
|
+
function toSingleLine(text3) {
|
|
1912
|
+
return text3.replace(/\s+/g, " ").trim();
|
|
1908
1913
|
}
|
|
1909
1914
|
function shouldScan(file, ignoreGlobs) {
|
|
1910
1915
|
if (!SOURCE_EXTENSIONS.some((ext) => file.endsWith(ext))) return false;
|
|
@@ -1925,11 +1930,11 @@ function findAddedComments(options2) {
|
|
|
1925
1930
|
for (const [file, lines] of addedLines) {
|
|
1926
1931
|
if (!shouldScan(file, options2.ignoreGlobs)) continue;
|
|
1927
1932
|
const sourceFile = project.addSourceFileAtPath(file);
|
|
1928
|
-
for (const { pos, text:
|
|
1933
|
+
for (const { pos, text: text3 } of collectComments(sourceFile)) {
|
|
1929
1934
|
const { line } = sourceFile.getLineAndColumnAtPos(pos);
|
|
1930
1935
|
if (!lines.has(line)) continue;
|
|
1931
|
-
if (isCommentExempt(
|
|
1932
|
-
findings.push({ file, line, text: toSingleLine(
|
|
1936
|
+
if (isCommentExempt(text3, options2.markers)) continue;
|
|
1937
|
+
findings.push({ file, line, text: toSingleLine(text3) });
|
|
1933
1938
|
}
|
|
1934
1939
|
}
|
|
1935
1940
|
findings.sort((a, b) => a.file.localeCompare(b.file) || a.line - b.line);
|
|
@@ -1948,8 +1953,8 @@ function commentPolicy() {
|
|
|
1948
1953
|
process.exit(0);
|
|
1949
1954
|
}
|
|
1950
1955
|
console.log("Comments added on changed lines:\n");
|
|
1951
|
-
for (const { file, line, text:
|
|
1952
|
-
console.log(`${file}:${line} \u2192 ${
|
|
1956
|
+
for (const { file, line, text: text3 } of findings) {
|
|
1957
|
+
console.log(`${file}:${line} \u2192 ${text3}`);
|
|
1953
1958
|
}
|
|
1954
1959
|
console.log(`
|
|
1955
1960
|
Total: ${findings.length} comment(s)`);
|
|
@@ -3056,9 +3061,9 @@ var LOCAL_FILES = ["backlog.jsonl", "backlog.db"];
|
|
|
3056
3061
|
function backupLocalBacklogFiles(dir) {
|
|
3057
3062
|
const moved = [];
|
|
3058
3063
|
for (const name of LOCAL_FILES) {
|
|
3059
|
-
const
|
|
3060
|
-
if (existsSync15(
|
|
3061
|
-
renameSync(
|
|
3064
|
+
const path54 = join11(dir, ".assist", name);
|
|
3065
|
+
if (existsSync15(path54)) {
|
|
3066
|
+
renameSync(path54, `${path54}.bak`);
|
|
3062
3067
|
moved.push(`${name} \u2192 ${name}.bak`);
|
|
3063
3068
|
}
|
|
3064
3069
|
}
|
|
@@ -3348,8 +3353,8 @@ var backlogItemSchema = z3.strictObject({
|
|
|
3348
3353
|
var backlogFileSchema = z3.array(backlogItemSchema);
|
|
3349
3354
|
|
|
3350
3355
|
// src/commands/backlog/parseBacklogJsonl.ts
|
|
3351
|
-
function parseBacklogJsonl(
|
|
3352
|
-
const content = readFileSync10(
|
|
3356
|
+
function parseBacklogJsonl(path54) {
|
|
3357
|
+
const content = readFileSync10(path54, "utf-8").trim();
|
|
3353
3358
|
if (content.length === 0) return [];
|
|
3354
3359
|
return content.split("\n").map((line) => line.trim()).filter(Boolean).map((line) => backlogItemSchema.parse(JSON.parse(line)));
|
|
3355
3360
|
}
|
|
@@ -3424,8 +3429,8 @@ function findBacklogUp(startDir) {
|
|
|
3424
3429
|
|
|
3425
3430
|
// src/commands/backlog/getCurrentOrigin.ts
|
|
3426
3431
|
import { execSync as execSync18 } from "child_process";
|
|
3427
|
-
function stripLeadingSlashes(
|
|
3428
|
-
return
|
|
3432
|
+
function stripLeadingSlashes(path54) {
|
|
3433
|
+
return path54.replace(/^\/+/, "");
|
|
3429
3434
|
}
|
|
3430
3435
|
function normalizeOrigin(raw) {
|
|
3431
3436
|
const trimmed = raw.trim().replace(/\.git$/i, "").replace(/\/+$/, "");
|
|
@@ -3689,13 +3694,13 @@ function activityPath(sessionId) {
|
|
|
3689
3694
|
function emitActivity(activity2) {
|
|
3690
3695
|
const sessionId = process.env.ASSIST_ACTIVITY_ID;
|
|
3691
3696
|
if (!sessionId) return;
|
|
3692
|
-
const
|
|
3693
|
-
mkdirSync6(dirname14(
|
|
3694
|
-
writeFileSync13(
|
|
3697
|
+
const path54 = activityPath(sessionId);
|
|
3698
|
+
mkdirSync6(dirname14(path54), { recursive: true });
|
|
3699
|
+
writeFileSync13(path54, JSON.stringify({ ...activity2, startedAt: Date.now() }));
|
|
3695
3700
|
}
|
|
3696
|
-
function readActivity(
|
|
3701
|
+
function readActivity(path54) {
|
|
3697
3702
|
try {
|
|
3698
|
-
return JSON.parse(readFileSync11(
|
|
3703
|
+
return JSON.parse(readFileSync11(path54, "utf-8"));
|
|
3699
3704
|
} catch {
|
|
3700
3705
|
return void 0;
|
|
3701
3706
|
}
|
|
@@ -3855,10 +3860,10 @@ function writeSignal(event, data) {
|
|
|
3855
3860
|
|
|
3856
3861
|
// src/commands/backlog/readSignal.ts
|
|
3857
3862
|
function readSignal() {
|
|
3858
|
-
const
|
|
3859
|
-
if (!existsSync19(
|
|
3863
|
+
const path54 = getSignalPath();
|
|
3864
|
+
if (!existsSync19(path54)) return void 0;
|
|
3860
3865
|
try {
|
|
3861
|
-
return JSON.parse(readFileSync12(
|
|
3866
|
+
return JSON.parse(readFileSync12(path54, "utf-8"));
|
|
3862
3867
|
} catch {
|
|
3863
3868
|
return void 0;
|
|
3864
3869
|
}
|
|
@@ -4114,11 +4119,11 @@ import chalk37 from "chalk";
|
|
|
4114
4119
|
|
|
4115
4120
|
// src/commands/backlog/appendComment.ts
|
|
4116
4121
|
import { sql as sql2 } from "drizzle-orm";
|
|
4117
|
-
async function appendComment(orm, itemId,
|
|
4122
|
+
async function appendComment(orm, itemId, text3, opts = {}) {
|
|
4118
4123
|
await orm.insert(comments).values({
|
|
4119
4124
|
itemId,
|
|
4120
4125
|
idx: sql2`(SELECT COALESCE(MAX(${comments.idx}) + 1, 0) FROM ${comments} WHERE ${comments.itemId} = ${itemId})`,
|
|
4121
|
-
text:
|
|
4126
|
+
text: text3,
|
|
4122
4127
|
phase: opts.phase ?? null,
|
|
4123
4128
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4124
4129
|
type: opts.type ?? "comment"
|
|
@@ -5121,10 +5126,10 @@ async function web2(options2) {
|
|
|
5121
5126
|
|
|
5122
5127
|
// src/commands/backlog/comment/index.ts
|
|
5123
5128
|
import chalk45 from "chalk";
|
|
5124
|
-
async function comment(id,
|
|
5129
|
+
async function comment(id, text3) {
|
|
5125
5130
|
const found = await findOneItem(id);
|
|
5126
5131
|
if (!found) process.exit(1);
|
|
5127
|
-
await appendComment(found.orm, found.item.id,
|
|
5132
|
+
await appendComment(found.orm, found.item.id, text3);
|
|
5128
5133
|
console.log(chalk45.green(`Comment added to item #${id}.`));
|
|
5129
5134
|
}
|
|
5130
5135
|
|
|
@@ -5294,9 +5299,9 @@ function readLine(dump, start3) {
|
|
|
5294
5299
|
return { text: dump.subarray(start3, eol).toString("utf8"), next: eol + 1 };
|
|
5295
5300
|
}
|
|
5296
5301
|
function parseHeader(dump) {
|
|
5297
|
-
const { text:
|
|
5302
|
+
const { text: text3, next: next3 } = readLine(dump, 0);
|
|
5298
5303
|
try {
|
|
5299
|
-
return { header: JSON.parse(
|
|
5304
|
+
return { header: JSON.parse(text3), bodyStart: next3 };
|
|
5300
5305
|
} catch {
|
|
5301
5306
|
return invalid("header is not valid JSON.");
|
|
5302
5307
|
}
|
|
@@ -5305,9 +5310,9 @@ function parseSections(dump, bodyStart) {
|
|
|
5305
5310
|
const sections = /* @__PURE__ */ new Map();
|
|
5306
5311
|
let cursor = bodyStart;
|
|
5307
5312
|
while (cursor < dump.length) {
|
|
5308
|
-
const { text:
|
|
5309
|
-
const match =
|
|
5310
|
-
if (!match) invalid(`malformed table marker "${
|
|
5313
|
+
const { text: text3, next: next3 } = readLine(dump, cursor);
|
|
5314
|
+
const match = text3.match(/^@table (\S+) (\d+)$/);
|
|
5315
|
+
if (!match) invalid(`malformed table marker "${text3}".`);
|
|
5311
5316
|
const [, name, bytes] = match;
|
|
5312
5317
|
const end = next3 + Number(bytes);
|
|
5313
5318
|
if (end > dump.length) invalid(`section "${name}" overruns the dump.`);
|
|
@@ -5645,8 +5650,8 @@ import chalk54 from "chalk";
|
|
|
5645
5650
|
// src/commands/backlog/originDisplayName.ts
|
|
5646
5651
|
function originDisplayName(origin) {
|
|
5647
5652
|
if (origin.startsWith("local:")) {
|
|
5648
|
-
const
|
|
5649
|
-
const segments =
|
|
5653
|
+
const path54 = origin.slice("local:".length).replace(/\/+$/, "");
|
|
5654
|
+
const segments = path54.split("/").filter(Boolean);
|
|
5650
5655
|
return segments[segments.length - 1] ?? origin;
|
|
5651
5656
|
}
|
|
5652
5657
|
const firstSlash = origin.indexOf("/");
|
|
@@ -6904,9 +6909,9 @@ var __dirname5 = dirname17(__filename3);
|
|
|
6904
6909
|
function packageRoot() {
|
|
6905
6910
|
return __dirname5;
|
|
6906
6911
|
}
|
|
6907
|
-
function readLines(
|
|
6908
|
-
if (!existsSync22(
|
|
6909
|
-
return readFileSync16(
|
|
6912
|
+
function readLines(path54) {
|
|
6913
|
+
if (!existsSync22(path54)) return [];
|
|
6914
|
+
return readFileSync16(path54, "utf-8").split("\n").filter((line) => line.trim() !== "");
|
|
6910
6915
|
}
|
|
6911
6916
|
var cachedReads;
|
|
6912
6917
|
var cachedWrites;
|
|
@@ -7389,14 +7394,14 @@ function showProgress(p, label2) {
|
|
|
7389
7394
|
const pct = Math.round(p.done / p.total * 100);
|
|
7390
7395
|
process.stderr.write(`\r\x1B[K[${pct}%] Scanning ${label2}...`);
|
|
7391
7396
|
}
|
|
7392
|
-
async function resolveCommand(cli,
|
|
7393
|
-
showProgress(p,
|
|
7394
|
-
const subHelp = await runHelp([cli, ...
|
|
7397
|
+
async function resolveCommand(cli, path54, description, depth, p) {
|
|
7398
|
+
showProgress(p, path54.join(" "));
|
|
7399
|
+
const subHelp = await runHelp([cli, ...path54]);
|
|
7395
7400
|
if (!subHelp || !hasSubcommands(subHelp)) {
|
|
7396
|
-
return [{ path:
|
|
7401
|
+
return [{ path: path54, description }];
|
|
7397
7402
|
}
|
|
7398
|
-
const children = await discoverAt(cli,
|
|
7399
|
-
return children.length > 0 ? children : [{ path:
|
|
7403
|
+
const children = await discoverAt(cli, path54, depth + 1, p);
|
|
7404
|
+
return children.length > 0 ? children : [{ path: path54, description }];
|
|
7400
7405
|
}
|
|
7401
7406
|
async function discoverAt(cli, parentPath, depth, p) {
|
|
7402
7407
|
if (depth > SAFETY_DEPTH) return [];
|
|
@@ -7506,8 +7511,8 @@ function formatHuman(cli, commands) {
|
|
|
7506
7511
|
`];
|
|
7507
7512
|
for (const cmd of sorted) {
|
|
7508
7513
|
const full = `${cli} ${cmd.path.join(" ")}`;
|
|
7509
|
-
const
|
|
7510
|
-
lines.push(`${prefix(classifyVerb(cmd.path))}${
|
|
7514
|
+
const text3 = cmd.description ? `${full} \u2014 ${cmd.description}` : full;
|
|
7515
|
+
lines.push(`${prefix(classifyVerb(cmd.path))}${text3}`);
|
|
7511
7516
|
}
|
|
7512
7517
|
return lines.join("\n");
|
|
7513
7518
|
}
|
|
@@ -7544,9 +7549,9 @@ function logPath(cli) {
|
|
|
7544
7549
|
return join22(homedir9(), ".assist", `cli-discover-${safeName}.log`);
|
|
7545
7550
|
}
|
|
7546
7551
|
function readCache(cli) {
|
|
7547
|
-
const
|
|
7548
|
-
if (!existsSync24(
|
|
7549
|
-
return readFileSync18(
|
|
7552
|
+
const path54 = logPath(cli);
|
|
7553
|
+
if (!existsSync24(path54)) return void 0;
|
|
7554
|
+
return readFileSync18(path54, "utf-8");
|
|
7550
7555
|
}
|
|
7551
7556
|
function writeCache(cli, output) {
|
|
7552
7557
|
const dir = join22(homedir9(), ".assist");
|
|
@@ -8235,8 +8240,8 @@ function stepIntoNested(container, key, nextKey) {
|
|
|
8235
8240
|
}
|
|
8236
8241
|
return ensureObject(container, resolved);
|
|
8237
8242
|
}
|
|
8238
|
-
function setNestedValue(obj,
|
|
8239
|
-
const keys =
|
|
8243
|
+
function setNestedValue(obj, path54, value) {
|
|
8244
|
+
const keys = path54.split(".");
|
|
8240
8245
|
const result = { ...obj };
|
|
8241
8246
|
let current = result;
|
|
8242
8247
|
for (let i = 0; i < keys.length - 1; i++) {
|
|
@@ -8316,9 +8321,9 @@ function isTraversable(value) {
|
|
|
8316
8321
|
function stepInto(current, key) {
|
|
8317
8322
|
return isTraversable(current) ? current[key] : void 0;
|
|
8318
8323
|
}
|
|
8319
|
-
function getNestedValue(obj,
|
|
8324
|
+
function getNestedValue(obj, path54) {
|
|
8320
8325
|
let current = obj;
|
|
8321
|
-
for (const key of
|
|
8326
|
+
for (const key of path54.split(".")) current = stepInto(current, key);
|
|
8322
8327
|
return current;
|
|
8323
8328
|
}
|
|
8324
8329
|
|
|
@@ -9852,16 +9857,16 @@ function parseUserLine(line) {
|
|
|
9852
9857
|
if (entry.type !== "user") return void 0;
|
|
9853
9858
|
const msg = entry.message;
|
|
9854
9859
|
const c = msg?.content;
|
|
9855
|
-
let
|
|
9860
|
+
let text3;
|
|
9856
9861
|
if (typeof c === "string") {
|
|
9857
|
-
|
|
9862
|
+
text3 = c;
|
|
9858
9863
|
} else if (Array.isArray(c)) {
|
|
9859
9864
|
const collected = c.filter((b) => b.type === "text").map((b) => b.text ?? "").join("\n");
|
|
9860
|
-
|
|
9865
|
+
text3 = collected || void 0;
|
|
9861
9866
|
}
|
|
9862
|
-
if (!
|
|
9867
|
+
if (!text3) return void 0;
|
|
9863
9868
|
return {
|
|
9864
|
-
text:
|
|
9869
|
+
text: text3,
|
|
9865
9870
|
entrypoint: typeof entry.entrypoint === "string" ? entry.entrypoint : void 0
|
|
9866
9871
|
};
|
|
9867
9872
|
}
|
|
@@ -9912,12 +9917,12 @@ ${payload}`;
|
|
|
9912
9917
|
return "";
|
|
9913
9918
|
}
|
|
9914
9919
|
}
|
|
9915
|
-
function stripPreludes(
|
|
9916
|
-
return
|
|
9920
|
+
function stripPreludes(text3) {
|
|
9921
|
+
return text3.replace(/<command-name>[\s\S]*?<\/command-name>/g, "").replace(/<command-message>[\s\S]*?<\/command-message>/g, "").replace(/<command-args>[\s\S]*?<\/command-args>/g, "").replace(/<local-command-stdout>[\s\S]*?<\/local-command-stdout>/g, "").replace(/<system-reminder>[\s\S]*?<\/system-reminder>/g, "").trim();
|
|
9917
9922
|
}
|
|
9918
|
-
function capPayload(
|
|
9919
|
-
const buf = Buffer.from(
|
|
9920
|
-
if (buf.length <= maxBytes) return
|
|
9923
|
+
function capPayload(text3, maxBytes) {
|
|
9924
|
+
const buf = Buffer.from(text3, "utf8");
|
|
9925
|
+
if (buf.length <= maxBytes) return text3;
|
|
9921
9926
|
return buf.subarray(buf.length - maxBytes).toString("utf8");
|
|
9922
9927
|
}
|
|
9923
9928
|
function normaliseOutput(raw) {
|
|
@@ -9986,9 +9991,9 @@ import chalk109 from "chalk";
|
|
|
9986
9991
|
|
|
9987
9992
|
// src/commands/jira/adfToText.ts
|
|
9988
9993
|
function renderInline(node) {
|
|
9989
|
-
const
|
|
9990
|
-
if (node.marks?.some((m) => m.type === "code")) return `\`${
|
|
9991
|
-
return
|
|
9994
|
+
const text3 = node.text ?? "";
|
|
9995
|
+
if (node.marks?.some((m) => m.type === "code")) return `\`${text3}\``;
|
|
9996
|
+
return text3;
|
|
9992
9997
|
}
|
|
9993
9998
|
function renderChildren(node, indent2) {
|
|
9994
9999
|
return renderNodes(node.content ?? [], indent2);
|
|
@@ -10030,8 +10035,8 @@ function isListNode(node) {
|
|
|
10030
10035
|
function renderListChild(child, indent2, pad, marker, isFirst) {
|
|
10031
10036
|
if (isListNode(child)) return renderNodes([child], indent2 + 1);
|
|
10032
10037
|
if (child.type !== "paragraph") return renderNode(child, indent2);
|
|
10033
|
-
const
|
|
10034
|
-
return isFirst ? `${pad}${marker} ${
|
|
10038
|
+
const text3 = renderChildren(child, indent2);
|
|
10039
|
+
return isFirst ? `${pad}${marker} ${text3}` : `${pad} ${text3}`;
|
|
10035
10040
|
}
|
|
10036
10041
|
function renderListItem(node, indent2, marker) {
|
|
10037
10042
|
const pad = " ".repeat(indent2);
|
|
@@ -10106,10 +10111,10 @@ function getStorePath(filename) {
|
|
|
10106
10111
|
return join32(getStoreDir(), filename);
|
|
10107
10112
|
}
|
|
10108
10113
|
function loadJson(filename) {
|
|
10109
|
-
const
|
|
10110
|
-
if (existsSync33(
|
|
10114
|
+
const path54 = getStorePath(filename);
|
|
10115
|
+
if (existsSync33(path54)) {
|
|
10111
10116
|
try {
|
|
10112
|
-
return JSON.parse(readFileSync27(
|
|
10117
|
+
return JSON.parse(readFileSync27(path54, "utf-8"));
|
|
10113
10118
|
} catch {
|
|
10114
10119
|
return {};
|
|
10115
10120
|
}
|
|
@@ -10442,9 +10447,9 @@ function excerpt(xml, ...tags) {
|
|
|
10442
10447
|
for (const tag of tags) {
|
|
10443
10448
|
const raw = extractText(xml, tag);
|
|
10444
10449
|
if (!raw) continue;
|
|
10445
|
-
const
|
|
10446
|
-
if (
|
|
10447
|
-
return `${
|
|
10450
|
+
const text3 = stripHtml(raw);
|
|
10451
|
+
if (text3.length <= MAX_EXCERPT) return text3;
|
|
10452
|
+
return `${text3.slice(0, MAX_EXCERPT)}\u2026`;
|
|
10448
10453
|
}
|
|
10449
10454
|
return "";
|
|
10450
10455
|
}
|
|
@@ -10745,15 +10750,15 @@ function postComment(vars) {
|
|
|
10745
10750
|
const stdout = startLine === void 0 ? runGhGraphql(MUTATION_SINGLE, base) : runGhGraphql(MUTATION_MULTI, { ...base, startLine });
|
|
10746
10751
|
assertThreadCreated(stdout);
|
|
10747
10752
|
}
|
|
10748
|
-
function comment2(
|
|
10753
|
+
function comment2(path54, line, body, startLine) {
|
|
10749
10754
|
validateBody(body);
|
|
10750
10755
|
validateLine(line);
|
|
10751
10756
|
if (startLine !== void 0) validateLine(startLine);
|
|
10752
10757
|
try {
|
|
10753
10758
|
const prId = getCurrentPrNodeId();
|
|
10754
|
-
postComment({ prId, body, path:
|
|
10759
|
+
postComment({ prId, body, path: path54, line, startLine });
|
|
10755
10760
|
const range = startLine !== void 0 ? `${startLine}-${line}` : `${line}`;
|
|
10756
|
-
console.log(`Added review comment on ${
|
|
10761
|
+
console.log(`Added review comment on ${path54}:${range}`);
|
|
10757
10762
|
} catch (error) {
|
|
10758
10763
|
if (isGhNotInstalled(error)) {
|
|
10759
10764
|
console.error("Error: GitHub CLI (gh) is not installed.");
|
|
@@ -11333,8 +11338,8 @@ function registerPrs(program2) {
|
|
|
11333
11338
|
prsCommand.command("wontfix <comment-id> <reason>").description("Reply with reason and resolve thread").action((commentId, reason) => {
|
|
11334
11339
|
wontfix(Number.parseInt(commentId, 10), reason);
|
|
11335
11340
|
});
|
|
11336
|
-
prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((
|
|
11337
|
-
comment2(
|
|
11341
|
+
prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((path54, line, body) => {
|
|
11342
|
+
comment2(path54, Number.parseInt(line, 10), body);
|
|
11338
11343
|
});
|
|
11339
11344
|
}
|
|
11340
11345
|
|
|
@@ -11586,10 +11591,10 @@ function resolveOpSecret(reference) {
|
|
|
11586
11591
|
}
|
|
11587
11592
|
|
|
11588
11593
|
// src/commands/ravendb/ravenFetch.ts
|
|
11589
|
-
async function ravenFetch(connection,
|
|
11594
|
+
async function ravenFetch(connection, path54) {
|
|
11590
11595
|
const apiKey = resolveOpSecret(connection.apiKeyRef);
|
|
11591
11596
|
let accessToken = await getAccessToken(apiKey);
|
|
11592
|
-
const url = `${connection.url}${
|
|
11597
|
+
const url = `${connection.url}${path54}`;
|
|
11593
11598
|
const headers = {
|
|
11594
11599
|
Authorization: `Bearer ${accessToken}`,
|
|
11595
11600
|
"Content-Type": "application/json"
|
|
@@ -11679,16 +11684,16 @@ import chalk130 from "chalk";
|
|
|
11679
11684
|
// src/commands/ravendb/buildQueryPath.ts
|
|
11680
11685
|
function buildQueryPath(opts) {
|
|
11681
11686
|
const db = encodeURIComponent(opts.db);
|
|
11682
|
-
let
|
|
11687
|
+
let path54;
|
|
11683
11688
|
if (opts.collection) {
|
|
11684
|
-
|
|
11689
|
+
path54 = `/databases/${db}/indexes/dynamic/${encodeURIComponent(opts.collection)}?start=${opts.start}&pageSize=${opts.pageSize}&sort=${encodeURIComponent(opts.sort)}`;
|
|
11685
11690
|
} else {
|
|
11686
|
-
|
|
11691
|
+
path54 = `/databases/${db}/queries?start=${opts.start}&pageSize=${opts.pageSize}`;
|
|
11687
11692
|
}
|
|
11688
11693
|
if (opts.query) {
|
|
11689
|
-
|
|
11694
|
+
path54 += `&query=${encodeURIComponent(opts.query)}`;
|
|
11690
11695
|
}
|
|
11691
|
-
return
|
|
11696
|
+
return path54;
|
|
11692
11697
|
}
|
|
11693
11698
|
|
|
11694
11699
|
// src/commands/ravendb/fetchAllPages.ts
|
|
@@ -11697,7 +11702,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
11697
11702
|
let start3 = 0;
|
|
11698
11703
|
while (true) {
|
|
11699
11704
|
const effectivePageSize = opts.limit !== void 0 ? Math.min(opts.pageSize, opts.limit - allResults.length) : opts.pageSize;
|
|
11700
|
-
const
|
|
11705
|
+
const path54 = buildQueryPath({
|
|
11701
11706
|
db: connection.database,
|
|
11702
11707
|
collection: opts.collection,
|
|
11703
11708
|
start: start3,
|
|
@@ -11705,7 +11710,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
11705
11710
|
sort: opts.sort,
|
|
11706
11711
|
query: opts.query
|
|
11707
11712
|
});
|
|
11708
|
-
const data = await ravenFetch(connection,
|
|
11713
|
+
const data = await ravenFetch(connection, path54);
|
|
11709
11714
|
const results = data.Results ?? [];
|
|
11710
11715
|
const totalResults = data.TotalResults ?? 0;
|
|
11711
11716
|
if (results.length === 0) break;
|
|
@@ -12352,9 +12357,9 @@ function resolveImports(target, dependencies, sourceFile, statements = []) {
|
|
|
12352
12357
|
function extractTexts(target, allFunctions, statements) {
|
|
12353
12358
|
const stmtTexts = statements.map((v) => v.getFullText().trim());
|
|
12354
12359
|
const fnTexts = allFunctions.map((fn) => {
|
|
12355
|
-
const
|
|
12356
|
-
if (fn === target && !
|
|
12357
|
-
return
|
|
12360
|
+
const text3 = fn.getFullText().trim();
|
|
12361
|
+
if (fn === target && !text3.startsWith("export ")) return `export ${text3}`;
|
|
12362
|
+
return text3;
|
|
12358
12363
|
});
|
|
12359
12364
|
return [...stmtTexts, ...fnTexts];
|
|
12360
12365
|
}
|
|
@@ -12923,8 +12928,8 @@ function findRootParent(file, importedBy, visited) {
|
|
|
12923
12928
|
function clusterFiles(graph) {
|
|
12924
12929
|
const clusters = /* @__PURE__ */ new Map();
|
|
12925
12930
|
for (const file of graph.files) {
|
|
12926
|
-
const
|
|
12927
|
-
if (
|
|
12931
|
+
const basename12 = path38.basename(file, path38.extname(file));
|
|
12932
|
+
if (basename12 === "index") continue;
|
|
12928
12933
|
const importers = graph.importedBy.get(file);
|
|
12929
12934
|
if (!importers || importers.size !== 1) continue;
|
|
12930
12935
|
const parent = [...importers][0];
|
|
@@ -13986,8 +13991,8 @@ async function handlePostSynthesis(synthesisPath, options2) {
|
|
|
13986
13991
|
// src/commands/review/prepareReviewDir.ts
|
|
13987
13992
|
import { existsSync as existsSync36, mkdirSync as mkdirSync14, unlinkSync as unlinkSync12, writeFileSync as writeFileSync26 } from "fs";
|
|
13988
13993
|
function clearReviewFiles(paths) {
|
|
13989
|
-
for (const
|
|
13990
|
-
if (existsSync36(
|
|
13994
|
+
for (const path54 of [paths.claudePath, paths.codexPath, paths.synthesisPath]) {
|
|
13995
|
+
if (existsSync36(path54)) unlinkSync12(path54);
|
|
13991
13996
|
}
|
|
13992
13997
|
}
|
|
13993
13998
|
function prepareReviewDir(paths, requestBody, force) {
|
|
@@ -14122,9 +14127,9 @@ var MultiSpinner = class {
|
|
|
14122
14127
|
elapsedPrefix: prefix2
|
|
14123
14128
|
});
|
|
14124
14129
|
}
|
|
14125
|
-
failRemaining(
|
|
14130
|
+
failRemaining(text3) {
|
|
14126
14131
|
for (const entry of this.entries) {
|
|
14127
|
-
if (entry.state === "running") this.resolve(entry, "failed",
|
|
14132
|
+
if (entry.state === "running") this.resolve(entry, "failed", text3);
|
|
14128
14133
|
}
|
|
14129
14134
|
}
|
|
14130
14135
|
add(entry) {
|
|
@@ -14137,14 +14142,14 @@ var MultiSpinner = class {
|
|
|
14137
14142
|
set text(value) {
|
|
14138
14143
|
entry.text = value;
|
|
14139
14144
|
},
|
|
14140
|
-
succeed: (
|
|
14141
|
-
fail: (
|
|
14145
|
+
succeed: (text3) => this.resolve(entry, "succeeded", text3),
|
|
14146
|
+
fail: (text3) => this.resolve(entry, "failed", text3)
|
|
14142
14147
|
};
|
|
14143
14148
|
}
|
|
14144
|
-
resolve(entry, state,
|
|
14149
|
+
resolve(entry, state, text3) {
|
|
14145
14150
|
if (entry.state !== "running") return;
|
|
14146
14151
|
entry.state = state;
|
|
14147
|
-
if (
|
|
14152
|
+
if (text3 !== void 0) entry.text = text3;
|
|
14148
14153
|
entry.elapsedStart = void 0;
|
|
14149
14154
|
this.render();
|
|
14150
14155
|
this.maybeFinish();
|
|
@@ -14219,12 +14224,12 @@ function skippedCodexResult(outputPath) {
|
|
|
14219
14224
|
// src/commands/review/formatReviewerFailure.ts
|
|
14220
14225
|
var FAST_FAIL_MS = 1e3;
|
|
14221
14226
|
var STDOUT_TAIL_LINES = 20;
|
|
14222
|
-
function indent(
|
|
14223
|
-
return
|
|
14227
|
+
function indent(text3) {
|
|
14228
|
+
return text3.split(/\r?\n/).map((line) => ` ${line}`);
|
|
14224
14229
|
}
|
|
14225
|
-
function tailLines(
|
|
14226
|
-
const lines =
|
|
14227
|
-
return lines.length <= maxLines ?
|
|
14230
|
+
function tailLines(text3, maxLines) {
|
|
14231
|
+
const lines = text3.split(/\r?\n/);
|
|
14232
|
+
return lines.length <= maxLines ? text3 : lines.slice(-maxLines).join("\n");
|
|
14228
14233
|
}
|
|
14229
14234
|
function isFastFail(input) {
|
|
14230
14235
|
return input.exitCode !== 0 && input.elapsedMs !== void 0 && input.elapsedMs < FAST_FAIL_MS;
|
|
@@ -15122,8 +15127,8 @@ import chalk149 from "chalk";
|
|
|
15122
15127
|
|
|
15123
15128
|
// src/commands/seq/fetchSeq.ts
|
|
15124
15129
|
import chalk146 from "chalk";
|
|
15125
|
-
async function fetchSeq(conn,
|
|
15126
|
-
const url = `${conn.url}${
|
|
15130
|
+
async function fetchSeq(conn, path54, params) {
|
|
15131
|
+
const url = `${conn.url}${path54}?${params}`;
|
|
15127
15132
|
const response = await fetch(url, {
|
|
15128
15133
|
headers: {
|
|
15129
15134
|
Accept: "application/json",
|
|
@@ -15858,8 +15863,8 @@ import { existsSync as existsSync40, mkdirSync as mkdirSync15, readFileSync as r
|
|
|
15858
15863
|
import { basename as basename8, dirname as dirname21, join as join41 } from "path";
|
|
15859
15864
|
|
|
15860
15865
|
// src/commands/transcript/cleanText.ts
|
|
15861
|
-
function cleanText(
|
|
15862
|
-
const words =
|
|
15866
|
+
function cleanText(text3) {
|
|
15867
|
+
const words = text3.split(/\s+/);
|
|
15863
15868
|
const cleaned = [];
|
|
15864
15869
|
for (let i = 0; i < words.length; i++) {
|
|
15865
15870
|
let isRepeat = false;
|
|
@@ -15879,8 +15884,8 @@ function cleanText(text2) {
|
|
|
15879
15884
|
}
|
|
15880
15885
|
|
|
15881
15886
|
// src/commands/transcript/format/processVttFile/parseVtt/deduplicateCues/removeSubstringDuplicates.ts
|
|
15882
|
-
function normalizeText(
|
|
15883
|
-
return
|
|
15887
|
+
function normalizeText(text3) {
|
|
15888
|
+
return text3.toLowerCase().trim();
|
|
15884
15889
|
}
|
|
15885
15890
|
function checkSubstringRelation(textI, textJ) {
|
|
15886
15891
|
if (textI.includes(textJ) && textI.length > textJ.length)
|
|
@@ -16009,13 +16014,13 @@ function parseTimestampLine(line) {
|
|
|
16009
16014
|
return { startMs: parseTimestamp(startStr), endMs: parseTimestamp(endStr) };
|
|
16010
16015
|
}
|
|
16011
16016
|
function buildCue(startMs, endMs, fullText) {
|
|
16012
|
-
const { speaker, text:
|
|
16013
|
-
return
|
|
16017
|
+
const { speaker, text: text3 } = extractSpeaker(fullText);
|
|
16018
|
+
return text3 ? { startMs, endMs, speaker, text: text3 } : null;
|
|
16014
16019
|
}
|
|
16015
16020
|
function parseCueLine(lines, i) {
|
|
16016
16021
|
const { startMs, endMs } = parseTimestampLine(lines[i]);
|
|
16017
|
-
const { text:
|
|
16018
|
-
return { cue: buildCue(startMs, endMs,
|
|
16022
|
+
const { text: text3, nextIndex } = collectTextLines(lines, i + 1);
|
|
16023
|
+
return { cue: buildCue(startMs, endMs, text3), nextIndex };
|
|
16019
16024
|
}
|
|
16020
16025
|
function isCueSeparator(line) {
|
|
16021
16026
|
return line.trim().includes("-->");
|
|
@@ -16728,8 +16733,8 @@ async function exchangeToken(params) {
|
|
|
16728
16733
|
body: body.toString()
|
|
16729
16734
|
});
|
|
16730
16735
|
if (!response.ok) {
|
|
16731
|
-
const
|
|
16732
|
-
throw new Error(`Token exchange failed (${response.status}): ${
|
|
16736
|
+
const text3 = await response.text();
|
|
16737
|
+
throw new Error(`Token exchange failed (${response.status}): ${text3}`);
|
|
16733
16738
|
}
|
|
16734
16739
|
return response.json();
|
|
16735
16740
|
}
|
|
@@ -16813,9 +16818,9 @@ function findPortFile(roamDir) {
|
|
|
16813
16818
|
return void 0;
|
|
16814
16819
|
}
|
|
16815
16820
|
const candidates = entries.filter((name) => /^roam-local-api(-[^.]+)?\.port$/.test(name)).map((name) => {
|
|
16816
|
-
const
|
|
16821
|
+
const path54 = join49(roamDir, name);
|
|
16817
16822
|
try {
|
|
16818
|
-
return { path:
|
|
16823
|
+
return { path: path54, mtimeMs: statSync5(path54).mtimeMs };
|
|
16819
16824
|
} catch {
|
|
16820
16825
|
return void 0;
|
|
16821
16826
|
}
|
|
@@ -17158,11 +17163,11 @@ function findLinkIndex() {
|
|
|
17158
17163
|
function parseLinkArgs() {
|
|
17159
17164
|
const idx = findLinkIndex();
|
|
17160
17165
|
if (idx === -1) return null;
|
|
17161
|
-
const
|
|
17166
|
+
const path54 = process.argv[idx + 1];
|
|
17162
17167
|
const rest = process.argv.slice(idx + 2);
|
|
17163
17168
|
const { value: prefix2 } = extractOption(rest, "--prefix");
|
|
17164
17169
|
if (!prefix2) return null;
|
|
17165
|
-
return { path:
|
|
17170
|
+
return { path: path54, prefix: prefix2 };
|
|
17166
17171
|
}
|
|
17167
17172
|
function hasDuplicateLink(runList, linkPath) {
|
|
17168
17173
|
return runList.some(
|
|
@@ -17582,121 +17587,6 @@ function daemonLog(message) {
|
|
|
17582
17587
|
console.log(`${(/* @__PURE__ */ new Date()).toISOString()} [${process.pid}] ${message}`);
|
|
17583
17588
|
}
|
|
17584
17589
|
|
|
17585
|
-
// src/commands/sessions/shared/discoverSessions.ts
|
|
17586
|
-
import * as fs26 from "fs";
|
|
17587
|
-
import * as os from "os";
|
|
17588
|
-
import * as path46 from "path";
|
|
17589
|
-
|
|
17590
|
-
// src/commands/sessions/shared/parseSessionFile.ts
|
|
17591
|
-
import * as fs25 from "fs";
|
|
17592
|
-
import * as path45 from "path";
|
|
17593
|
-
|
|
17594
|
-
// src/commands/sessions/shared/extractSessionMeta.ts
|
|
17595
|
-
function extractSessionMeta(lines) {
|
|
17596
|
-
let sessionId = "";
|
|
17597
|
-
let cwd = "";
|
|
17598
|
-
let timestamp = "";
|
|
17599
|
-
let name = "";
|
|
17600
|
-
for (const line of lines) {
|
|
17601
|
-
const entry = safeParse(line);
|
|
17602
|
-
if (!entry) continue;
|
|
17603
|
-
sessionId ||= typeof entry.sessionId === "string" ? entry.sessionId : "";
|
|
17604
|
-
timestamp ||= typeof entry.timestamp === "string" ? entry.timestamp : "";
|
|
17605
|
-
cwd ||= typeof entry.cwd === "string" ? entry.cwd : "";
|
|
17606
|
-
if (entry.type === "user" && !entry.isMeta) {
|
|
17607
|
-
name = extractName(entry);
|
|
17608
|
-
break;
|
|
17609
|
-
}
|
|
17610
|
-
}
|
|
17611
|
-
return { sessionId, cwd, timestamp, name };
|
|
17612
|
-
}
|
|
17613
|
-
function safeParse(line) {
|
|
17614
|
-
try {
|
|
17615
|
-
return JSON.parse(line);
|
|
17616
|
-
} catch {
|
|
17617
|
-
return null;
|
|
17618
|
-
}
|
|
17619
|
-
}
|
|
17620
|
-
function extractName(entry) {
|
|
17621
|
-
const msg = entry.message;
|
|
17622
|
-
const content = msg?.content;
|
|
17623
|
-
const text2 = typeof content === "string" ? content : Array.isArray(content) ? content.find((c) => c.type === "text")?.text ?? "" : "";
|
|
17624
|
-
return text2.replace(/<command-[^>]*>[^<]*<\/command-[^>]*>/g, "").trim().slice(0, 80);
|
|
17625
|
-
}
|
|
17626
|
-
|
|
17627
|
-
// src/commands/sessions/shared/parseSessionFile.ts
|
|
17628
|
-
async function parseSessionFile(filePath) {
|
|
17629
|
-
let handle;
|
|
17630
|
-
try {
|
|
17631
|
-
handle = await fs25.promises.open(filePath, "r");
|
|
17632
|
-
const buf = Buffer.alloc(16384);
|
|
17633
|
-
const { bytesRead } = await handle.read(buf, 0, buf.length, 0);
|
|
17634
|
-
const lines = buf.toString("utf8", 0, bytesRead).split("\n").filter(Boolean);
|
|
17635
|
-
const meta = extractSessionMeta(lines);
|
|
17636
|
-
if (!meta.sessionId) return null;
|
|
17637
|
-
const timestamp = meta.timestamp || (await fs25.promises.stat(filePath)).mtime.toISOString();
|
|
17638
|
-
const project = meta.cwd ? path45.basename(meta.cwd) : dirNameToProject(filePath);
|
|
17639
|
-
return {
|
|
17640
|
-
sessionId: meta.sessionId,
|
|
17641
|
-
name: meta.name || `Session ${meta.sessionId.slice(0, 8)}`,
|
|
17642
|
-
project,
|
|
17643
|
-
cwd: meta.cwd,
|
|
17644
|
-
timestamp
|
|
17645
|
-
};
|
|
17646
|
-
} catch {
|
|
17647
|
-
return null;
|
|
17648
|
-
} finally {
|
|
17649
|
-
await handle?.close();
|
|
17650
|
-
}
|
|
17651
|
-
}
|
|
17652
|
-
function dirNameToProject(filePath) {
|
|
17653
|
-
const dirName = path45.basename(path45.dirname(filePath));
|
|
17654
|
-
const parts = dirName.split("--");
|
|
17655
|
-
return parts[parts.length - 1].replace(/-/g, "/");
|
|
17656
|
-
}
|
|
17657
|
-
|
|
17658
|
-
// src/commands/sessions/shared/discoverSessions.ts
|
|
17659
|
-
async function discoverSessionJsonlPaths() {
|
|
17660
|
-
const projectsDir = path46.join(os.homedir(), ".claude", "projects");
|
|
17661
|
-
let projectDirs;
|
|
17662
|
-
try {
|
|
17663
|
-
projectDirs = await fs26.promises.readdir(projectsDir);
|
|
17664
|
-
} catch {
|
|
17665
|
-
return [];
|
|
17666
|
-
}
|
|
17667
|
-
const paths = [];
|
|
17668
|
-
await Promise.all(
|
|
17669
|
-
projectDirs.map(async (dirName) => {
|
|
17670
|
-
const dirPath = path46.join(projectsDir, dirName);
|
|
17671
|
-
let entries;
|
|
17672
|
-
try {
|
|
17673
|
-
entries = await fs26.promises.readdir(dirPath);
|
|
17674
|
-
} catch {
|
|
17675
|
-
return;
|
|
17676
|
-
}
|
|
17677
|
-
const jsonlFiles = entries.filter((e) => e.endsWith(".jsonl"));
|
|
17678
|
-
for (const file of jsonlFiles) {
|
|
17679
|
-
paths.push(path46.join(dirPath, file));
|
|
17680
|
-
}
|
|
17681
|
-
})
|
|
17682
|
-
);
|
|
17683
|
-
return paths;
|
|
17684
|
-
}
|
|
17685
|
-
async function discoverSessions() {
|
|
17686
|
-
const paths = await discoverSessionJsonlPaths();
|
|
17687
|
-
const sessions = [];
|
|
17688
|
-
await Promise.all(
|
|
17689
|
-
paths.map(async (filePath) => {
|
|
17690
|
-
const session = await parseSessionFile(filePath);
|
|
17691
|
-
if (session) sessions.push(session);
|
|
17692
|
-
})
|
|
17693
|
-
);
|
|
17694
|
-
sessions.sort(
|
|
17695
|
-
(a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()
|
|
17696
|
-
);
|
|
17697
|
-
return sessions;
|
|
17698
|
-
}
|
|
17699
|
-
|
|
17700
17590
|
// src/commands/sessions/daemon/broadcast.ts
|
|
17701
17591
|
function sendTo(client, msg) {
|
|
17702
17592
|
client.send(JSON.stringify(msg));
|
|
@@ -17800,14 +17690,14 @@ import * as pty from "node-pty";
|
|
|
17800
17690
|
// src/commands/sessions/daemon/ensureSpawnHelperExecutable.ts
|
|
17801
17691
|
import { chmodSync, existsSync as existsSync51, statSync as statSync6 } from "fs";
|
|
17802
17692
|
import { createRequire as createRequire3 } from "module";
|
|
17803
|
-
import
|
|
17693
|
+
import path45 from "path";
|
|
17804
17694
|
var require4 = createRequire3(import.meta.url);
|
|
17805
17695
|
var ensured = false;
|
|
17806
17696
|
function ensureSpawnHelperExecutable() {
|
|
17807
17697
|
if (ensured || process.platform !== "darwin") return;
|
|
17808
17698
|
ensured = true;
|
|
17809
|
-
const ptyRoot =
|
|
17810
|
-
const helper =
|
|
17699
|
+
const ptyRoot = path45.join(path45.dirname(require4.resolve("node-pty")), "..");
|
|
17700
|
+
const helper = path45.join(
|
|
17811
17701
|
ptyRoot,
|
|
17812
17702
|
"prebuilds",
|
|
17813
17703
|
`${process.platform}-${process.arch}`,
|
|
@@ -18044,12 +17934,12 @@ function clearIdle(session) {
|
|
|
18044
17934
|
|
|
18045
17935
|
// src/commands/sessions/daemon/watchActivity.ts
|
|
18046
17936
|
import { existsSync as existsSync52, mkdirSync as mkdirSync22, watch } from "fs";
|
|
18047
|
-
import { dirname as
|
|
17937
|
+
import { dirname as dirname26 } from "path";
|
|
18048
17938
|
var DEBOUNCE_MS = 50;
|
|
18049
17939
|
function watchActivity(session, notify2) {
|
|
18050
17940
|
if (session.commandType !== "assist" || !session.cwd) return;
|
|
18051
|
-
const
|
|
18052
|
-
const dir =
|
|
17941
|
+
const path54 = activityPath(session.id);
|
|
17942
|
+
const dir = dirname26(path54);
|
|
18053
17943
|
try {
|
|
18054
17944
|
mkdirSync22(dir, { recursive: true });
|
|
18055
17945
|
} catch {
|
|
@@ -18058,7 +17948,7 @@ function watchActivity(session, notify2) {
|
|
|
18058
17948
|
let timer = null;
|
|
18059
17949
|
const read = () => {
|
|
18060
17950
|
timer = null;
|
|
18061
|
-
const activity2 = readActivity(
|
|
17951
|
+
const activity2 = readActivity(path54);
|
|
18062
17952
|
if (!activity2) return;
|
|
18063
17953
|
session.activity = activity2;
|
|
18064
17954
|
if (activity2.claudeSessionId)
|
|
@@ -18066,11 +17956,11 @@ function watchActivity(session, notify2) {
|
|
|
18066
17956
|
notify2();
|
|
18067
17957
|
};
|
|
18068
17958
|
session.activityWatcher = watch(dir, (_event, filename) => {
|
|
18069
|
-
if (filename && !
|
|
17959
|
+
if (filename && !path54.endsWith(filename)) return;
|
|
18070
17960
|
if (timer) clearTimeout(timer);
|
|
18071
17961
|
timer = setTimeout(read, DEBOUNCE_MS);
|
|
18072
17962
|
});
|
|
18073
|
-
if (existsSync52(
|
|
17963
|
+
if (existsSync52(path54)) read();
|
|
18074
17964
|
}
|
|
18075
17965
|
function refreshActivity(session) {
|
|
18076
17966
|
if (session.commandType !== "assist" || !session.cwd) return;
|
|
@@ -18159,6 +18049,174 @@ function shutdownSessions(sessions) {
|
|
|
18159
18049
|
// src/commands/sessions/daemon/watchClaudeSessionId.ts
|
|
18160
18050
|
import * as fs27 from "fs";
|
|
18161
18051
|
import * as path48 from "path";
|
|
18052
|
+
|
|
18053
|
+
// src/commands/sessions/shared/discoverSessions.ts
|
|
18054
|
+
import * as fs26 from "fs";
|
|
18055
|
+
import * as os from "os";
|
|
18056
|
+
import * as path47 from "path";
|
|
18057
|
+
|
|
18058
|
+
// src/commands/sessions/shared/parseSessionFile.ts
|
|
18059
|
+
import * as fs25 from "fs";
|
|
18060
|
+
import * as path46 from "path";
|
|
18061
|
+
|
|
18062
|
+
// src/commands/sessions/shared/deriveHistoryFields.ts
|
|
18063
|
+
var KNOWN = ["draft", "next", "bug", "refine", "run"];
|
|
18064
|
+
function deriveHistoryFields(commandName, commandArgs, name) {
|
|
18065
|
+
const fields = {};
|
|
18066
|
+
const sessionType = deriveSessionType(commandName, name);
|
|
18067
|
+
if (sessionType) fields.sessionType = sessionType;
|
|
18068
|
+
const itemMatch = commandArgs.match(/^(\d+)\b\s*/);
|
|
18069
|
+
if (itemMatch) fields.itemId = Number(itemMatch[1]);
|
|
18070
|
+
const prompt = commandArgs.slice(itemMatch?.[0].length ?? 0).trim();
|
|
18071
|
+
if (prompt) fields.prompt = prompt;
|
|
18072
|
+
return fields;
|
|
18073
|
+
}
|
|
18074
|
+
function deriveSessionType(commandName, name) {
|
|
18075
|
+
if (KNOWN.includes(commandName))
|
|
18076
|
+
return commandName;
|
|
18077
|
+
if (commandName || name) return "prompt";
|
|
18078
|
+
return void 0;
|
|
18079
|
+
}
|
|
18080
|
+
|
|
18081
|
+
// src/commands/sessions/shared/backlogRunMarkers.ts
|
|
18082
|
+
function backlogRunMarkers(text3) {
|
|
18083
|
+
const match = text3.match(/backlog item #(\d+):[ \t]*([^\n]*)/);
|
|
18084
|
+
if (!match) return { commandName: "", commandArgs: "" };
|
|
18085
|
+
const title = match[2].trim();
|
|
18086
|
+
return {
|
|
18087
|
+
commandName: "next",
|
|
18088
|
+
commandArgs: title ? `${match[1]} ${title}` : match[1]
|
|
18089
|
+
};
|
|
18090
|
+
}
|
|
18091
|
+
|
|
18092
|
+
// src/commands/sessions/shared/extractSessionMeta.ts
|
|
18093
|
+
function extractSessionMeta(lines) {
|
|
18094
|
+
let sessionId = "";
|
|
18095
|
+
let cwd = "";
|
|
18096
|
+
let timestamp = "";
|
|
18097
|
+
let name = "";
|
|
18098
|
+
let commandName = "";
|
|
18099
|
+
let commandArgs = "";
|
|
18100
|
+
for (const line of lines) {
|
|
18101
|
+
const entry = safeParse(line);
|
|
18102
|
+
if (!entry) continue;
|
|
18103
|
+
sessionId ||= strField(entry, "sessionId");
|
|
18104
|
+
timestamp ||= strField(entry, "timestamp");
|
|
18105
|
+
cwd ||= strField(entry, "cwd");
|
|
18106
|
+
if (entry.type === "user" && !entry.isMeta) {
|
|
18107
|
+
({ name, commandName, commandArgs } = parseFirstUserEntry(entry));
|
|
18108
|
+
break;
|
|
18109
|
+
}
|
|
18110
|
+
}
|
|
18111
|
+
return { sessionId, cwd, timestamp, name, commandName, commandArgs };
|
|
18112
|
+
}
|
|
18113
|
+
function parseFirstUserEntry(entry) {
|
|
18114
|
+
const raw = messageText(entry);
|
|
18115
|
+
const commandName = matchMarker(raw, "command-name").replace(/^\//, "");
|
|
18116
|
+
const commandArgs = matchMarker(raw, "command-args");
|
|
18117
|
+
const name = stripMarkers(raw);
|
|
18118
|
+
if (commandName) return { name, commandName, commandArgs };
|
|
18119
|
+
return { name, ...backlogRunMarkers(raw) };
|
|
18120
|
+
}
|
|
18121
|
+
function strField(entry, key) {
|
|
18122
|
+
const value = entry[key];
|
|
18123
|
+
return typeof value === "string" ? value : "";
|
|
18124
|
+
}
|
|
18125
|
+
function safeParse(line) {
|
|
18126
|
+
try {
|
|
18127
|
+
return JSON.parse(line);
|
|
18128
|
+
} catch {
|
|
18129
|
+
return null;
|
|
18130
|
+
}
|
|
18131
|
+
}
|
|
18132
|
+
function messageText(entry) {
|
|
18133
|
+
const msg = entry.message;
|
|
18134
|
+
const content = msg?.content;
|
|
18135
|
+
return typeof content === "string" ? content : Array.isArray(content) ? content.find((c) => c.type === "text")?.text ?? "" : "";
|
|
18136
|
+
}
|
|
18137
|
+
function stripMarkers(text3) {
|
|
18138
|
+
return text3.replace(/<command-[^>]*>[^<]*<\/command-[^>]*>/g, "").trim().slice(0, 80);
|
|
18139
|
+
}
|
|
18140
|
+
function matchMarker(text3, tag) {
|
|
18141
|
+
const match = text3.match(new RegExp(`<${tag}>([\\s\\S]*?)</${tag}>`));
|
|
18142
|
+
return match ? match[1].trim() : "";
|
|
18143
|
+
}
|
|
18144
|
+
|
|
18145
|
+
// src/commands/sessions/shared/parseSessionFile.ts
|
|
18146
|
+
async function parseSessionFile(filePath) {
|
|
18147
|
+
let handle;
|
|
18148
|
+
try {
|
|
18149
|
+
handle = await fs25.promises.open(filePath, "r");
|
|
18150
|
+
const buf = Buffer.alloc(16384);
|
|
18151
|
+
const { bytesRead } = await handle.read(buf, 0, buf.length, 0);
|
|
18152
|
+
const lines = buf.toString("utf8", 0, bytesRead).split("\n").filter(Boolean);
|
|
18153
|
+
const meta = extractSessionMeta(lines);
|
|
18154
|
+
if (!meta.sessionId) return null;
|
|
18155
|
+
const timestamp = meta.timestamp || (await fs25.promises.stat(filePath)).mtime.toISOString();
|
|
18156
|
+
const project = meta.cwd ? path46.basename(meta.cwd) : dirNameToProject(filePath);
|
|
18157
|
+
return {
|
|
18158
|
+
sessionId: meta.sessionId,
|
|
18159
|
+
name: meta.name || `Session ${meta.sessionId.slice(0, 8)}`,
|
|
18160
|
+
project,
|
|
18161
|
+
cwd: meta.cwd,
|
|
18162
|
+
timestamp,
|
|
18163
|
+
...deriveHistoryFields(meta.commandName, meta.commandArgs, meta.name)
|
|
18164
|
+
};
|
|
18165
|
+
} catch {
|
|
18166
|
+
return null;
|
|
18167
|
+
} finally {
|
|
18168
|
+
await handle?.close();
|
|
18169
|
+
}
|
|
18170
|
+
}
|
|
18171
|
+
function dirNameToProject(filePath) {
|
|
18172
|
+
const dirName = path46.basename(path46.dirname(filePath));
|
|
18173
|
+
const parts = dirName.split("--");
|
|
18174
|
+
return parts[parts.length - 1].replace(/-/g, "/");
|
|
18175
|
+
}
|
|
18176
|
+
|
|
18177
|
+
// src/commands/sessions/shared/discoverSessions.ts
|
|
18178
|
+
async function discoverSessionJsonlPaths() {
|
|
18179
|
+
const projectsDir = path47.join(os.homedir(), ".claude", "projects");
|
|
18180
|
+
let projectDirs;
|
|
18181
|
+
try {
|
|
18182
|
+
projectDirs = await fs26.promises.readdir(projectsDir);
|
|
18183
|
+
} catch {
|
|
18184
|
+
return [];
|
|
18185
|
+
}
|
|
18186
|
+
const paths = [];
|
|
18187
|
+
await Promise.all(
|
|
18188
|
+
projectDirs.map(async (dirName) => {
|
|
18189
|
+
const dirPath = path47.join(projectsDir, dirName);
|
|
18190
|
+
let entries;
|
|
18191
|
+
try {
|
|
18192
|
+
entries = await fs26.promises.readdir(dirPath);
|
|
18193
|
+
} catch {
|
|
18194
|
+
return;
|
|
18195
|
+
}
|
|
18196
|
+
const jsonlFiles = entries.filter((e) => e.endsWith(".jsonl"));
|
|
18197
|
+
for (const file of jsonlFiles) {
|
|
18198
|
+
paths.push(path47.join(dirPath, file));
|
|
18199
|
+
}
|
|
18200
|
+
})
|
|
18201
|
+
);
|
|
18202
|
+
return paths;
|
|
18203
|
+
}
|
|
18204
|
+
async function discoverSessions() {
|
|
18205
|
+
const paths = await discoverSessionJsonlPaths();
|
|
18206
|
+
const sessions = [];
|
|
18207
|
+
await Promise.all(
|
|
18208
|
+
paths.map(async (filePath) => {
|
|
18209
|
+
const session = await parseSessionFile(filePath);
|
|
18210
|
+
if (session) sessions.push(session);
|
|
18211
|
+
})
|
|
18212
|
+
);
|
|
18213
|
+
sessions.sort(
|
|
18214
|
+
(a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()
|
|
18215
|
+
);
|
|
18216
|
+
return sessions;
|
|
18217
|
+
}
|
|
18218
|
+
|
|
18219
|
+
// src/commands/sessions/daemon/watchClaudeSessionId.ts
|
|
18162
18220
|
var POLL_MS = 3e3;
|
|
18163
18221
|
async function watchClaudeSessionId(options2) {
|
|
18164
18222
|
let adoptedMs = 0;
|
|
@@ -18346,9 +18404,6 @@ var SessionManager = class {
|
|
|
18346
18404
|
listSessions() {
|
|
18347
18405
|
return [...this.sessions.values()].map(toSessionInfo);
|
|
18348
18406
|
}
|
|
18349
|
-
async getHistory() {
|
|
18350
|
-
return discoverSessions();
|
|
18351
|
-
}
|
|
18352
18407
|
notify = () => {
|
|
18353
18408
|
if (this.shuttingDown) return;
|
|
18354
18409
|
broadcastSessions(this.sessions, this.clients);
|
|
@@ -18363,6 +18418,95 @@ import * as net2 from "net";
|
|
|
18363
18418
|
// src/commands/sessions/daemon/handleConnection.ts
|
|
18364
18419
|
import { createInterface as createInterface5 } from "readline";
|
|
18365
18420
|
|
|
18421
|
+
// src/commands/sessions/shared/parseTranscript.ts
|
|
18422
|
+
import * as fs28 from "fs";
|
|
18423
|
+
|
|
18424
|
+
// src/commands/sessions/shared/toolTarget.ts
|
|
18425
|
+
function toolTarget(input) {
|
|
18426
|
+
if (!input || typeof input !== "object") return "";
|
|
18427
|
+
const i = input;
|
|
18428
|
+
const str = (v) => typeof v === "string" ? v : "";
|
|
18429
|
+
const target = str(i.file_path) || str(i.path) || str(i.notebook_path) || str(i.command) || str(i.pattern) || str(i.url) || str(i.query) || str(i.description) || str(i.prompt);
|
|
18430
|
+
return target.replace(/\s+/g, " ").trim().slice(0, 120);
|
|
18431
|
+
}
|
|
18432
|
+
|
|
18433
|
+
// src/commands/sessions/shared/entryMessages.ts
|
|
18434
|
+
function entryMessages(entry) {
|
|
18435
|
+
const content = entry.message?.content;
|
|
18436
|
+
if (entry.type === "user") return userMessages(content);
|
|
18437
|
+
if (entry.type === "assistant") return assistantMessages(content);
|
|
18438
|
+
return [];
|
|
18439
|
+
}
|
|
18440
|
+
function userMessages(content) {
|
|
18441
|
+
if (typeof content === "string") return text2("user", cleanUserText(content));
|
|
18442
|
+
if (!Array.isArray(content)) return [];
|
|
18443
|
+
return content.filter((c) => c.type === "text").flatMap((c) => text2("user", cleanUserText(c.text ?? "")));
|
|
18444
|
+
}
|
|
18445
|
+
function assistantMessages(content) {
|
|
18446
|
+
if (typeof content === "string") return text2("assistant", content.trim());
|
|
18447
|
+
if (!Array.isArray(content)) return [];
|
|
18448
|
+
return content.flatMap((c) => assistantItem(c));
|
|
18449
|
+
}
|
|
18450
|
+
function assistantItem(c) {
|
|
18451
|
+
if (c.type === "text") return text2("assistant", (c.text ?? "").trim());
|
|
18452
|
+
if (c.type === "tool_use")
|
|
18453
|
+
return [
|
|
18454
|
+
{
|
|
18455
|
+
role: "tool",
|
|
18456
|
+
tool: typeof c.name === "string" ? c.name : "tool",
|
|
18457
|
+
target: toolTarget(c.input)
|
|
18458
|
+
}
|
|
18459
|
+
];
|
|
18460
|
+
return [];
|
|
18461
|
+
}
|
|
18462
|
+
function text2(role, value) {
|
|
18463
|
+
return value ? [{ role, text: value }] : [];
|
|
18464
|
+
}
|
|
18465
|
+
function cleanUserText(value) {
|
|
18466
|
+
return value.replace(/<command-[^>]*>[\s\S]*?<\/command-[^>]*>/g, "").replace(/<local-command-[^>]*>[\s\S]*?<\/local-command-[^>]*>/g, "").trim();
|
|
18467
|
+
}
|
|
18468
|
+
|
|
18469
|
+
// src/commands/sessions/shared/findSessionJsonlPath.ts
|
|
18470
|
+
import * as path49 from "path";
|
|
18471
|
+
async function findSessionJsonlPath(sessionId) {
|
|
18472
|
+
const paths = await discoverSessionJsonlPaths();
|
|
18473
|
+
const direct = paths.find((p) => path49.basename(p, ".jsonl") === sessionId);
|
|
18474
|
+
if (direct) return direct;
|
|
18475
|
+
for (const p of paths) {
|
|
18476
|
+
const meta = await parseSessionFile(p);
|
|
18477
|
+
if (meta?.sessionId === sessionId) return p;
|
|
18478
|
+
}
|
|
18479
|
+
return null;
|
|
18480
|
+
}
|
|
18481
|
+
|
|
18482
|
+
// src/commands/sessions/shared/parseTranscript.ts
|
|
18483
|
+
async function parseTranscript(sessionId) {
|
|
18484
|
+
const filePath = await findSessionJsonlPath(sessionId);
|
|
18485
|
+
if (!filePath) return [];
|
|
18486
|
+
try {
|
|
18487
|
+
const raw = await fs28.promises.readFile(filePath, "utf8");
|
|
18488
|
+
return parseTranscriptLines(raw.split("\n"));
|
|
18489
|
+
} catch {
|
|
18490
|
+
return [];
|
|
18491
|
+
}
|
|
18492
|
+
}
|
|
18493
|
+
function parseTranscriptLines(lines) {
|
|
18494
|
+
const messages = [];
|
|
18495
|
+
for (const line of lines) {
|
|
18496
|
+
const entry = line.trim() ? safeParse2(line) : null;
|
|
18497
|
+
if (!entry || entry.isSidechain || entry.isMeta) continue;
|
|
18498
|
+
messages.push(...entryMessages(entry));
|
|
18499
|
+
}
|
|
18500
|
+
return messages;
|
|
18501
|
+
}
|
|
18502
|
+
function safeParse2(line) {
|
|
18503
|
+
try {
|
|
18504
|
+
return JSON.parse(line);
|
|
18505
|
+
} catch {
|
|
18506
|
+
return null;
|
|
18507
|
+
}
|
|
18508
|
+
}
|
|
18509
|
+
|
|
18366
18510
|
// src/commands/sessions/daemon/dispatchMessage.ts
|
|
18367
18511
|
function sendCreated(client, id) {
|
|
18368
18512
|
sendTo(client, { type: "created", sessionId: id });
|
|
@@ -18405,10 +18549,16 @@ function handleResume(client, manager, data) {
|
|
|
18405
18549
|
)
|
|
18406
18550
|
);
|
|
18407
18551
|
}
|
|
18408
|
-
function handleHistory(client
|
|
18409
|
-
|
|
18410
|
-
sendTo(client, { type: "history", sessions
|
|
18411
|
-
|
|
18552
|
+
function handleHistory(client) {
|
|
18553
|
+
discoverSessions().then(
|
|
18554
|
+
(sessions) => sendTo(client, { type: "history", sessions })
|
|
18555
|
+
);
|
|
18556
|
+
}
|
|
18557
|
+
function handleFetchTranscript(client, _manager, data) {
|
|
18558
|
+
const sessionId = data.sessionId;
|
|
18559
|
+
parseTranscript(sessionId).then(
|
|
18560
|
+
(messages) => sendTo(client, { type: "transcript", sessionId, messages })
|
|
18561
|
+
);
|
|
18412
18562
|
}
|
|
18413
18563
|
function handleShutdown(client, manager) {
|
|
18414
18564
|
manager.shutdown();
|
|
@@ -18422,6 +18572,7 @@ var handlers = {
|
|
|
18422
18572
|
"create-assist": handleCreateAssist,
|
|
18423
18573
|
resume: handleResume,
|
|
18424
18574
|
history: handleHistory,
|
|
18575
|
+
"fetch-transcript": handleFetchTranscript,
|
|
18425
18576
|
shutdown: handleShutdown,
|
|
18426
18577
|
input: (_client, m, d) => m.writeToSession(d.sessionId, d.data),
|
|
18427
18578
|
resize: (_client, m, d) => m.resizeSession(d.sessionId, d.cols, d.rows),
|
|
@@ -18585,17 +18736,17 @@ function registerDaemon(program2) {
|
|
|
18585
18736
|
}
|
|
18586
18737
|
|
|
18587
18738
|
// src/commands/sessions/summarise/index.ts
|
|
18588
|
-
import * as
|
|
18739
|
+
import * as fs31 from "fs";
|
|
18589
18740
|
import chalk159 from "chalk";
|
|
18590
18741
|
|
|
18591
18742
|
// src/commands/sessions/summarise/shared.ts
|
|
18592
|
-
import * as
|
|
18743
|
+
import * as fs29 from "fs";
|
|
18593
18744
|
function writeSummary(jsonlPath2, summary) {
|
|
18594
|
-
|
|
18745
|
+
fs29.writeFileSync(summaryPathFor(jsonlPath2), `${summary.trim()}
|
|
18595
18746
|
`, "utf8");
|
|
18596
18747
|
}
|
|
18597
18748
|
function hasSummary(jsonlPath2) {
|
|
18598
|
-
return
|
|
18749
|
+
return fs29.existsSync(summaryPathFor(jsonlPath2));
|
|
18599
18750
|
}
|
|
18600
18751
|
function summaryPathFor(jsonlPath2) {
|
|
18601
18752
|
return jsonlPath2.replace(/\.jsonl$/, ".summary");
|
|
@@ -18605,17 +18756,17 @@ function summaryPathFor(jsonlPath2) {
|
|
|
18605
18756
|
import { execFileSync as execFileSync10 } from "child_process";
|
|
18606
18757
|
|
|
18607
18758
|
// src/commands/sessions/summarise/iterateUserMessages.ts
|
|
18608
|
-
import * as
|
|
18759
|
+
import * as fs30 from "fs";
|
|
18609
18760
|
function* iterateUserMessages(filePath, maxBytes = 65536) {
|
|
18610
18761
|
let content;
|
|
18611
18762
|
try {
|
|
18612
|
-
const fd =
|
|
18763
|
+
const fd = fs30.openSync(filePath, "r");
|
|
18613
18764
|
try {
|
|
18614
18765
|
const buf = Buffer.alloc(maxBytes);
|
|
18615
|
-
const bytesRead =
|
|
18766
|
+
const bytesRead = fs30.readSync(fd, buf, 0, buf.length, 0);
|
|
18616
18767
|
content = buf.toString("utf8", 0, bytesRead);
|
|
18617
18768
|
} finally {
|
|
18618
|
-
|
|
18769
|
+
fs30.closeSync(fd);
|
|
18619
18770
|
}
|
|
18620
18771
|
} catch {
|
|
18621
18772
|
return;
|
|
@@ -18629,13 +18780,13 @@ function* iterateUserMessages(filePath, maxBytes = 65536) {
|
|
|
18629
18780
|
|
|
18630
18781
|
// src/commands/sessions/summarise/extractFirstUserMessage.ts
|
|
18631
18782
|
function extractFirstUserMessage(filePath) {
|
|
18632
|
-
for (const
|
|
18633
|
-
return truncate3(
|
|
18783
|
+
for (const text3 of iterateUserMessages(filePath)) {
|
|
18784
|
+
return truncate3(text3);
|
|
18634
18785
|
}
|
|
18635
18786
|
return void 0;
|
|
18636
18787
|
}
|
|
18637
|
-
function truncate3(
|
|
18638
|
-
const trimmed =
|
|
18788
|
+
function truncate3(text3, maxChars = 500) {
|
|
18789
|
+
const trimmed = text3.trim();
|
|
18639
18790
|
if (trimmed.length <= maxChars) return trimmed;
|
|
18640
18791
|
return `${trimmed.slice(0, maxChars)}\u2026`;
|
|
18641
18792
|
}
|
|
@@ -18643,28 +18794,28 @@ function truncate3(text2, maxChars = 500) {
|
|
|
18643
18794
|
// src/commands/sessions/summarise/scanSessionBacklogRefs.ts
|
|
18644
18795
|
function scanSessionBacklogRefs(filePath) {
|
|
18645
18796
|
const ids = /* @__PURE__ */ new Set();
|
|
18646
|
-
for (const
|
|
18647
|
-
for (const id of extractBacklogIds(
|
|
18797
|
+
for (const text3 of iterateUserMessages(filePath, Number.MAX_SAFE_INTEGER)) {
|
|
18798
|
+
for (const id of extractBacklogIds(text3)) {
|
|
18648
18799
|
ids.add(id);
|
|
18649
18800
|
}
|
|
18650
18801
|
}
|
|
18651
18802
|
return [...ids].sort((a, b) => a - b);
|
|
18652
18803
|
}
|
|
18653
|
-
function extractBacklogIds(
|
|
18804
|
+
function extractBacklogIds(text3) {
|
|
18654
18805
|
const ids = [];
|
|
18655
|
-
for (const m of
|
|
18806
|
+
for (const m of text3.matchAll(/backlog\s+run\s+(\d+)/gi)) {
|
|
18656
18807
|
ids.push(Number.parseInt(m[1], 10));
|
|
18657
18808
|
}
|
|
18658
|
-
for (const m of
|
|
18809
|
+
for (const m of text3.matchAll(/backlog\s+(?:item\s+)?#(\d+)/gi)) {
|
|
18659
18810
|
ids.push(Number.parseInt(m[1], 10));
|
|
18660
18811
|
}
|
|
18661
|
-
for (const m of
|
|
18812
|
+
for (const m of text3.matchAll(/backlog\s+phase-done\s+(\d+)/gi)) {
|
|
18662
18813
|
ids.push(Number.parseInt(m[1], 10));
|
|
18663
18814
|
}
|
|
18664
|
-
for (const m of
|
|
18815
|
+
for (const m of text3.matchAll(/backlog\s+comment\s+(\d+)/gi)) {
|
|
18665
18816
|
ids.push(Number.parseInt(m[1], 10));
|
|
18666
18817
|
}
|
|
18667
|
-
for (const m of
|
|
18818
|
+
for (const m of text3.matchAll(/(?:^|[\s(])#(\d{1,4})(?=[\s).,;:!?]|$)/gm)) {
|
|
18668
18819
|
ids.push(Number.parseInt(m[1], 10));
|
|
18669
18820
|
}
|
|
18670
18821
|
return ids;
|
|
@@ -18735,7 +18886,7 @@ function selectCandidates(files, options2) {
|
|
|
18735
18886
|
const candidates = options2.force ? files : files.filter((f) => !hasSummary(f));
|
|
18736
18887
|
candidates.sort((a, b) => {
|
|
18737
18888
|
try {
|
|
18738
|
-
return
|
|
18889
|
+
return fs31.statSync(b).mtimeMs - fs31.statSync(a).mtimeMs;
|
|
18739
18890
|
} catch {
|
|
18740
18891
|
return 0;
|
|
18741
18892
|
}
|
|
@@ -18849,21 +19000,21 @@ async function statusLine() {
|
|
|
18849
19000
|
}
|
|
18850
19001
|
|
|
18851
19002
|
// src/commands/sync.ts
|
|
18852
|
-
import * as
|
|
19003
|
+
import * as fs34 from "fs";
|
|
18853
19004
|
import * as os2 from "os";
|
|
18854
|
-
import * as
|
|
19005
|
+
import * as path52 from "path";
|
|
18855
19006
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
18856
19007
|
|
|
18857
19008
|
// src/commands/sync/syncClaudeMd.ts
|
|
18858
|
-
import * as
|
|
18859
|
-
import * as
|
|
19009
|
+
import * as fs32 from "fs";
|
|
19010
|
+
import * as path50 from "path";
|
|
18860
19011
|
import chalk162 from "chalk";
|
|
18861
19012
|
async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
18862
|
-
const source =
|
|
18863
|
-
const target =
|
|
18864
|
-
const sourceContent =
|
|
18865
|
-
if (
|
|
18866
|
-
const targetContent =
|
|
19013
|
+
const source = path50.join(claudeDir, "CLAUDE.md");
|
|
19014
|
+
const target = path50.join(targetBase, "CLAUDE.md");
|
|
19015
|
+
const sourceContent = fs32.readFileSync(source, "utf-8");
|
|
19016
|
+
if (fs32.existsSync(target)) {
|
|
19017
|
+
const targetContent = fs32.readFileSync(target, "utf-8");
|
|
18867
19018
|
if (sourceContent !== targetContent) {
|
|
18868
19019
|
console.log(
|
|
18869
19020
|
chalk162.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
@@ -18880,21 +19031,21 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
18880
19031
|
}
|
|
18881
19032
|
}
|
|
18882
19033
|
}
|
|
18883
|
-
|
|
19034
|
+
fs32.copyFileSync(source, target);
|
|
18884
19035
|
console.log("Copied CLAUDE.md to ~/.claude/CLAUDE.md");
|
|
18885
19036
|
}
|
|
18886
19037
|
|
|
18887
19038
|
// src/commands/sync/syncSettings.ts
|
|
18888
|
-
import * as
|
|
18889
|
-
import * as
|
|
19039
|
+
import * as fs33 from "fs";
|
|
19040
|
+
import * as path51 from "path";
|
|
18890
19041
|
import chalk163 from "chalk";
|
|
18891
19042
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
18892
|
-
const source =
|
|
18893
|
-
const target =
|
|
18894
|
-
const sourceContent =
|
|
19043
|
+
const source = path51.join(claudeDir, "settings.json");
|
|
19044
|
+
const target = path51.join(targetBase, "settings.json");
|
|
19045
|
+
const sourceContent = fs33.readFileSync(source, "utf-8");
|
|
18895
19046
|
const mergedContent = JSON.stringify(JSON.parse(sourceContent), null, " ");
|
|
18896
|
-
if (
|
|
18897
|
-
const targetContent =
|
|
19047
|
+
if (fs33.existsSync(target)) {
|
|
19048
|
+
const targetContent = fs33.readFileSync(target, "utf-8");
|
|
18898
19049
|
const normalizedTarget = JSON.stringify(
|
|
18899
19050
|
JSON.parse(targetContent),
|
|
18900
19051
|
null,
|
|
@@ -18920,29 +19071,29 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
18920
19071
|
}
|
|
18921
19072
|
}
|
|
18922
19073
|
}
|
|
18923
|
-
|
|
19074
|
+
fs33.writeFileSync(target, mergedContent);
|
|
18924
19075
|
console.log("Copied settings.json to ~/.claude/settings.json");
|
|
18925
19076
|
}
|
|
18926
19077
|
|
|
18927
19078
|
// src/commands/sync.ts
|
|
18928
19079
|
var __filename4 = fileURLToPath7(import.meta.url);
|
|
18929
|
-
var __dirname7 =
|
|
19080
|
+
var __dirname7 = path52.dirname(__filename4);
|
|
18930
19081
|
async function sync(options2) {
|
|
18931
19082
|
const config = loadConfig();
|
|
18932
19083
|
const yes = options2?.yes ?? config.sync.autoConfirm;
|
|
18933
|
-
const claudeDir =
|
|
18934
|
-
const targetBase =
|
|
19084
|
+
const claudeDir = path52.join(__dirname7, "..", "claude");
|
|
19085
|
+
const targetBase = path52.join(os2.homedir(), ".claude");
|
|
18935
19086
|
syncCommands(claudeDir, targetBase);
|
|
18936
19087
|
await syncSettings(claudeDir, targetBase, { yes });
|
|
18937
19088
|
await syncClaudeMd(claudeDir, targetBase, { yes });
|
|
18938
19089
|
}
|
|
18939
19090
|
function syncCommands(claudeDir, targetBase) {
|
|
18940
|
-
const sourceDir =
|
|
18941
|
-
const targetDir =
|
|
18942
|
-
|
|
18943
|
-
const files =
|
|
19091
|
+
const sourceDir = path52.join(claudeDir, "commands");
|
|
19092
|
+
const targetDir = path52.join(targetBase, "commands");
|
|
19093
|
+
fs34.mkdirSync(targetDir, { recursive: true });
|
|
19094
|
+
const files = fs34.readdirSync(sourceDir);
|
|
18944
19095
|
for (const file of files) {
|
|
18945
|
-
|
|
19096
|
+
fs34.copyFileSync(path52.join(sourceDir, file), path52.join(targetDir, file));
|
|
18946
19097
|
console.log(`Copied ${file} to ${targetDir}`);
|
|
18947
19098
|
}
|
|
18948
19099
|
console.log(`Synced ${files.length} command(s) to ~/.claude/commands`);
|
|
@@ -18950,15 +19101,15 @@ function syncCommands(claudeDir, targetBase) {
|
|
|
18950
19101
|
|
|
18951
19102
|
// src/commands/update.ts
|
|
18952
19103
|
import { execSync as execSync50 } from "child_process";
|
|
18953
|
-
import * as
|
|
19104
|
+
import * as path53 from "path";
|
|
18954
19105
|
function isGlobalNpmInstall(dir) {
|
|
18955
19106
|
try {
|
|
18956
|
-
const resolved =
|
|
18957
|
-
if (resolved.split(
|
|
19107
|
+
const resolved = path53.resolve(dir);
|
|
19108
|
+
if (resolved.split(path53.sep).includes("node_modules")) {
|
|
18958
19109
|
return true;
|
|
18959
19110
|
}
|
|
18960
19111
|
const globalPrefix = execSync50("npm prefix -g", { stdio: "pipe" }).toString().trim();
|
|
18961
|
-
return resolved.toLowerCase().startsWith(
|
|
19112
|
+
return resolved.toLowerCase().startsWith(path53.resolve(globalPrefix).toLowerCase());
|
|
18962
19113
|
} catch {
|
|
18963
19114
|
return false;
|
|
18964
19115
|
}
|