@staff0rd/assist 0.273.2 → 0.275.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 +60 -60
- package/dist/index.js +831 -624
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Command } from "commander";
|
|
|
6
6
|
// package.json
|
|
7
7
|
var package_default = {
|
|
8
8
|
name: "@staff0rd/assist",
|
|
9
|
-
version: "0.
|
|
9
|
+
version: "0.275.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -119,10 +119,10 @@ import { stringify as stringifyYaml } from "yaml";
|
|
|
119
119
|
// src/shared/loadRawYaml.ts
|
|
120
120
|
import { existsSync, readFileSync } from "fs";
|
|
121
121
|
import { parse as parseYaml } from "yaml";
|
|
122
|
-
function loadRawYaml(
|
|
123
|
-
if (!existsSync(
|
|
122
|
+
function loadRawYaml(path54) {
|
|
123
|
+
if (!existsSync(path54)) return {};
|
|
124
124
|
try {
|
|
125
|
-
const content = readFileSync(
|
|
125
|
+
const content = readFileSync(path54, "utf-8");
|
|
126
126
|
return parseYaml(content) || {};
|
|
127
127
|
} catch {
|
|
128
128
|
return {};
|
|
@@ -1859,8 +1859,8 @@ var MACHINE_DIRECTIVES = [
|
|
|
1859
1859
|
"v8 ignore",
|
|
1860
1860
|
"c8 ignore"
|
|
1861
1861
|
];
|
|
1862
|
-
function isCommentExempt(
|
|
1863
|
-
const lower =
|
|
1862
|
+
function isCommentExempt(text3, markers) {
|
|
1863
|
+
const lower = text3.toLowerCase();
|
|
1864
1864
|
if (MACHINE_DIRECTIVES.some((d) => lower.includes(d))) return true;
|
|
1865
1865
|
return markers.some((m) => lower.includes(m.toLowerCase()));
|
|
1866
1866
|
}
|
|
@@ -1903,8 +1903,8 @@ function parseDiffAddedLines(diff2) {
|
|
|
1903
1903
|
|
|
1904
1904
|
// src/commands/verify/commentPolicy/findAddedComments.ts
|
|
1905
1905
|
var SOURCE_EXTENSIONS = [".ts", ".tsx", ".cts", ".mts", ".js", ".jsx"];
|
|
1906
|
-
function toSingleLine(
|
|
1907
|
-
return
|
|
1906
|
+
function toSingleLine(text3) {
|
|
1907
|
+
return text3.replace(/\s+/g, " ").trim();
|
|
1908
1908
|
}
|
|
1909
1909
|
function shouldScan(file, ignoreGlobs) {
|
|
1910
1910
|
if (!SOURCE_EXTENSIONS.some((ext) => file.endsWith(ext))) return false;
|
|
@@ -1925,11 +1925,11 @@ function findAddedComments(options2) {
|
|
|
1925
1925
|
for (const [file, lines] of addedLines) {
|
|
1926
1926
|
if (!shouldScan(file, options2.ignoreGlobs)) continue;
|
|
1927
1927
|
const sourceFile = project.addSourceFileAtPath(file);
|
|
1928
|
-
for (const { pos, text:
|
|
1928
|
+
for (const { pos, text: text3 } of collectComments(sourceFile)) {
|
|
1929
1929
|
const { line } = sourceFile.getLineAndColumnAtPos(pos);
|
|
1930
1930
|
if (!lines.has(line)) continue;
|
|
1931
|
-
if (isCommentExempt(
|
|
1932
|
-
findings.push({ file, line, text: toSingleLine(
|
|
1931
|
+
if (isCommentExempt(text3, options2.markers)) continue;
|
|
1932
|
+
findings.push({ file, line, text: toSingleLine(text3) });
|
|
1933
1933
|
}
|
|
1934
1934
|
}
|
|
1935
1935
|
findings.sort((a, b) => a.file.localeCompare(b.file) || a.line - b.line);
|
|
@@ -1948,8 +1948,8 @@ function commentPolicy() {
|
|
|
1948
1948
|
process.exit(0);
|
|
1949
1949
|
}
|
|
1950
1950
|
console.log("Comments added on changed lines:\n");
|
|
1951
|
-
for (const { file, line, text:
|
|
1952
|
-
console.log(`${file}:${line} \u2192 ${
|
|
1951
|
+
for (const { file, line, text: text3 } of findings) {
|
|
1952
|
+
console.log(`${file}:${line} \u2192 ${text3}`);
|
|
1953
1953
|
}
|
|
1954
1954
|
console.log(`
|
|
1955
1955
|
Total: ${findings.length} comment(s)`);
|
|
@@ -3034,22 +3034,6 @@ function buildArgs(prompt, options2) {
|
|
|
3034
3034
|
return [prompt];
|
|
3035
3035
|
}
|
|
3036
3036
|
|
|
3037
|
-
// src/commands/backlog/prepareRun.ts
|
|
3038
|
-
import chalk32 from "chalk";
|
|
3039
|
-
|
|
3040
|
-
// src/commands/backlog/resolvePlan.ts
|
|
3041
|
-
function resolvePlan(item) {
|
|
3042
|
-
if (item.plan && item.plan.length > 0) {
|
|
3043
|
-
return item.plan;
|
|
3044
|
-
}
|
|
3045
|
-
return [
|
|
3046
|
-
{
|
|
3047
|
-
name: "Implement",
|
|
3048
|
-
tasks: item.acceptanceCriteria.map((ac) => ({ task: ac }))
|
|
3049
|
-
}
|
|
3050
|
-
];
|
|
3051
|
-
}
|
|
3052
|
-
|
|
3053
3037
|
// src/commands/backlog/shared.ts
|
|
3054
3038
|
import chalk31 from "chalk";
|
|
3055
3039
|
|
|
@@ -3072,9 +3056,9 @@ var LOCAL_FILES = ["backlog.jsonl", "backlog.db"];
|
|
|
3072
3056
|
function backupLocalBacklogFiles(dir) {
|
|
3073
3057
|
const moved = [];
|
|
3074
3058
|
for (const name of LOCAL_FILES) {
|
|
3075
|
-
const
|
|
3076
|
-
if (existsSync15(
|
|
3077
|
-
renameSync(
|
|
3059
|
+
const path54 = join11(dir, ".assist", name);
|
|
3060
|
+
if (existsSync15(path54)) {
|
|
3061
|
+
renameSync(path54, `${path54}.bak`);
|
|
3078
3062
|
moved.push(`${name} \u2192 ${name}.bak`);
|
|
3079
3063
|
}
|
|
3080
3064
|
}
|
|
@@ -3364,8 +3348,8 @@ var backlogItemSchema = z3.strictObject({
|
|
|
3364
3348
|
var backlogFileSchema = z3.array(backlogItemSchema);
|
|
3365
3349
|
|
|
3366
3350
|
// src/commands/backlog/parseBacklogJsonl.ts
|
|
3367
|
-
function parseBacklogJsonl(
|
|
3368
|
-
const content = readFileSync10(
|
|
3351
|
+
function parseBacklogJsonl(path54) {
|
|
3352
|
+
const content = readFileSync10(path54, "utf-8").trim();
|
|
3369
3353
|
if (content.length === 0) return [];
|
|
3370
3354
|
return content.split("\n").map((line) => line.trim()).filter(Boolean).map((line) => backlogItemSchema.parse(JSON.parse(line)));
|
|
3371
3355
|
}
|
|
@@ -3440,8 +3424,8 @@ function findBacklogUp(startDir) {
|
|
|
3440
3424
|
|
|
3441
3425
|
// src/commands/backlog/getCurrentOrigin.ts
|
|
3442
3426
|
import { execSync as execSync18 } from "child_process";
|
|
3443
|
-
function stripLeadingSlashes(
|
|
3444
|
-
return
|
|
3427
|
+
function stripLeadingSlashes(path54) {
|
|
3428
|
+
return path54.replace(/^\/+/, "");
|
|
3445
3429
|
}
|
|
3446
3430
|
function normalizeOrigin(raw) {
|
|
3447
3431
|
const trimmed = raw.trim().replace(/\.git$/i, "").replace(/\/+$/, "");
|
|
@@ -3589,6 +3573,43 @@ async function removeItem(id) {
|
|
|
3589
3573
|
return name;
|
|
3590
3574
|
}
|
|
3591
3575
|
|
|
3576
|
+
// src/commands/backlog/handleReviewResult.ts
|
|
3577
|
+
async function handleReviewResult(id, review2) {
|
|
3578
|
+
if (review2.kind === "fail" || review2.kind === "abort")
|
|
3579
|
+
return { kind: "stop", success: false };
|
|
3580
|
+
if (review2.kind === "paused") return { kind: "stop", success: true };
|
|
3581
|
+
if (review2.kind === "rewind")
|
|
3582
|
+
return {
|
|
3583
|
+
kind: "resume",
|
|
3584
|
+
startPhase: review2.targetPhase,
|
|
3585
|
+
plan: review2.plan
|
|
3586
|
+
};
|
|
3587
|
+
await ensureDone(id);
|
|
3588
|
+
return { kind: "stop", success: true };
|
|
3589
|
+
}
|
|
3590
|
+
async function ensureDone(id) {
|
|
3591
|
+
try {
|
|
3592
|
+
await setStatus(id, "done");
|
|
3593
|
+
} catch {
|
|
3594
|
+
}
|
|
3595
|
+
}
|
|
3596
|
+
|
|
3597
|
+
// src/commands/backlog/prepareRun.ts
|
|
3598
|
+
import chalk32 from "chalk";
|
|
3599
|
+
|
|
3600
|
+
// src/commands/backlog/resolvePlan.ts
|
|
3601
|
+
function resolvePlan(item) {
|
|
3602
|
+
if (item.plan && item.plan.length > 0) {
|
|
3603
|
+
return item.plan;
|
|
3604
|
+
}
|
|
3605
|
+
return [
|
|
3606
|
+
{
|
|
3607
|
+
name: "Implement",
|
|
3608
|
+
tasks: item.acceptanceCriteria.map((ac) => ({ task: ac }))
|
|
3609
|
+
}
|
|
3610
|
+
];
|
|
3611
|
+
}
|
|
3612
|
+
|
|
3592
3613
|
// src/commands/backlog/prepareRun.ts
|
|
3593
3614
|
async function prepareRun(id) {
|
|
3594
3615
|
const found = await findOneItem(id);
|
|
@@ -3610,14 +3631,47 @@ async function prepareRun(id) {
|
|
|
3610
3631
|
return { item, plan: plan2, startPhase };
|
|
3611
3632
|
}
|
|
3612
3633
|
|
|
3634
|
+
// src/commands/backlog/consumePause.ts
|
|
3635
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync5, unlinkSync as unlinkSync3, writeFileSync as writeFileSync12 } from "fs";
|
|
3636
|
+
import { homedir as homedir4 } from "os";
|
|
3637
|
+
import { join as join14 } from "path";
|
|
3638
|
+
function getControlsDir() {
|
|
3639
|
+
return join14(homedir4(), ".assist", "controls");
|
|
3640
|
+
}
|
|
3641
|
+
function getPausePath(itemId) {
|
|
3642
|
+
return join14(getControlsDir(), `pause-${itemId}.json`);
|
|
3643
|
+
}
|
|
3644
|
+
function requestPause(itemId) {
|
|
3645
|
+
mkdirSync5(getControlsDir(), { recursive: true });
|
|
3646
|
+
writeFileSync12(
|
|
3647
|
+
getPausePath(itemId),
|
|
3648
|
+
JSON.stringify({ timestamp: (/* @__PURE__ */ new Date()).toISOString() })
|
|
3649
|
+
);
|
|
3650
|
+
}
|
|
3651
|
+
function clearPause(itemId) {
|
|
3652
|
+
try {
|
|
3653
|
+
unlinkSync3(getPausePath(itemId));
|
|
3654
|
+
} catch {
|
|
3655
|
+
}
|
|
3656
|
+
}
|
|
3657
|
+
function consumePause(itemId) {
|
|
3658
|
+
const pausePath = getPausePath(itemId);
|
|
3659
|
+
if (!existsSync18(pausePath)) return false;
|
|
3660
|
+
try {
|
|
3661
|
+
unlinkSync3(pausePath);
|
|
3662
|
+
} catch {
|
|
3663
|
+
}
|
|
3664
|
+
return true;
|
|
3665
|
+
}
|
|
3666
|
+
|
|
3613
3667
|
// src/commands/backlog/executePhase.ts
|
|
3614
3668
|
import { randomUUID } from "crypto";
|
|
3615
3669
|
import chalk34 from "chalk";
|
|
3616
3670
|
|
|
3617
3671
|
// src/shared/emitActivity.ts
|
|
3618
|
-
import { mkdirSync as
|
|
3619
|
-
import { homedir as
|
|
3620
|
-
import { dirname as dirname14, join as
|
|
3672
|
+
import { mkdirSync as mkdirSync6, readFileSync as readFileSync11, rmSync, writeFileSync as writeFileSync13 } from "fs";
|
|
3673
|
+
import { homedir as homedir5 } from "os";
|
|
3674
|
+
import { dirname as dirname14, join as join15 } from "path";
|
|
3621
3675
|
import { z as z4 } from "zod";
|
|
3622
3676
|
var activitySchema = z4.object({
|
|
3623
3677
|
kind: z4.enum(["command", "backlog"]),
|
|
@@ -3630,18 +3684,18 @@ var activitySchema = z4.object({
|
|
|
3630
3684
|
startedAt: z4.number()
|
|
3631
3685
|
});
|
|
3632
3686
|
function activityPath(sessionId) {
|
|
3633
|
-
return
|
|
3687
|
+
return join15(homedir5(), ".assist", "activity", `activity-${sessionId}.json`);
|
|
3634
3688
|
}
|
|
3635
3689
|
function emitActivity(activity2) {
|
|
3636
3690
|
const sessionId = process.env.ASSIST_ACTIVITY_ID;
|
|
3637
3691
|
if (!sessionId) return;
|
|
3638
|
-
const
|
|
3639
|
-
|
|
3640
|
-
|
|
3692
|
+
const path54 = activityPath(sessionId);
|
|
3693
|
+
mkdirSync6(dirname14(path54), { recursive: true });
|
|
3694
|
+
writeFileSync13(path54, JSON.stringify({ ...activity2, startedAt: Date.now() }));
|
|
3641
3695
|
}
|
|
3642
|
-
function readActivity(
|
|
3696
|
+
function readActivity(path54) {
|
|
3643
3697
|
try {
|
|
3644
|
-
return JSON.parse(readFileSync11(
|
|
3698
|
+
return JSON.parse(readFileSync11(path54, "utf-8"));
|
|
3645
3699
|
} catch {
|
|
3646
3700
|
return void 0;
|
|
3647
3701
|
}
|
|
@@ -3763,7 +3817,7 @@ function buildResumePrompt() {
|
|
|
3763
3817
|
}
|
|
3764
3818
|
|
|
3765
3819
|
// src/commands/backlog/resolvePhaseResult.ts
|
|
3766
|
-
import { existsSync as
|
|
3820
|
+
import { existsSync as existsSync20, unlinkSync as unlinkSync4 } from "fs";
|
|
3767
3821
|
import chalk33 from "chalk";
|
|
3768
3822
|
|
|
3769
3823
|
// src/commands/backlog/handleIncompletePhase.ts
|
|
@@ -3783,28 +3837,28 @@ async function handleIncompletePhase() {
|
|
|
3783
3837
|
}
|
|
3784
3838
|
|
|
3785
3839
|
// src/commands/backlog/readSignal.ts
|
|
3786
|
-
import { existsSync as
|
|
3840
|
+
import { existsSync as existsSync19, readFileSync as readFileSync12 } from "fs";
|
|
3787
3841
|
|
|
3788
3842
|
// src/commands/backlog/writeSignal.ts
|
|
3789
|
-
import { writeFileSync as
|
|
3790
|
-
import { join as
|
|
3843
|
+
import { writeFileSync as writeFileSync14 } from "fs";
|
|
3844
|
+
import { join as join16 } from "path";
|
|
3791
3845
|
function getSignalPath() {
|
|
3792
3846
|
const sessionId = process.env.ASSIST_SESSION_ID;
|
|
3793
3847
|
const filename = sessionId ? `.assist-signal-${sessionId}.json` : ".assist-signal.json";
|
|
3794
|
-
return
|
|
3848
|
+
return join16(getBacklogDir(), filename);
|
|
3795
3849
|
}
|
|
3796
3850
|
function writeSignal(event, data) {
|
|
3797
3851
|
const sessionId = process.env.ASSIST_SESSION_ID;
|
|
3798
3852
|
const signal = { event, ...sessionId && { sessionId }, ...data };
|
|
3799
|
-
|
|
3853
|
+
writeFileSync14(getSignalPath(), JSON.stringify(signal));
|
|
3800
3854
|
}
|
|
3801
3855
|
|
|
3802
3856
|
// src/commands/backlog/readSignal.ts
|
|
3803
3857
|
function readSignal() {
|
|
3804
|
-
const
|
|
3805
|
-
if (!
|
|
3858
|
+
const path54 = getSignalPath();
|
|
3859
|
+
if (!existsSync19(path54)) return void 0;
|
|
3806
3860
|
try {
|
|
3807
|
-
return JSON.parse(readFileSync12(
|
|
3861
|
+
return JSON.parse(readFileSync12(path54, "utf-8"));
|
|
3808
3862
|
} catch {
|
|
3809
3863
|
return void 0;
|
|
3810
3864
|
}
|
|
@@ -3813,8 +3867,8 @@ function readSignal() {
|
|
|
3813
3867
|
// src/commands/backlog/resolvePhaseResult.ts
|
|
3814
3868
|
function cleanupSignal() {
|
|
3815
3869
|
const statusPath = getSignalPath();
|
|
3816
|
-
if (
|
|
3817
|
-
|
|
3870
|
+
if (existsSync20(statusPath)) {
|
|
3871
|
+
unlinkSync4(statusPath);
|
|
3818
3872
|
}
|
|
3819
3873
|
}
|
|
3820
3874
|
async function isTerminalStatus(itemId) {
|
|
@@ -3823,7 +3877,7 @@ async function isTerminalStatus(itemId) {
|
|
|
3823
3877
|
return item?.status === "done" || item?.status === "wontdo";
|
|
3824
3878
|
}
|
|
3825
3879
|
async function resolvePhaseResult(phaseIndex, itemId) {
|
|
3826
|
-
if (!
|
|
3880
|
+
if (!existsSync20(getSignalPath())) {
|
|
3827
3881
|
if (await isTerminalStatus(itemId)) return -1;
|
|
3828
3882
|
const action = await handleIncompletePhase();
|
|
3829
3883
|
if (action === "abort") return -1;
|
|
@@ -3845,11 +3899,11 @@ Phase ${phaseNumber} completed.`));
|
|
|
3845
3899
|
}
|
|
3846
3900
|
|
|
3847
3901
|
// src/commands/backlog/watchForMarker.ts
|
|
3848
|
-
import { existsSync as
|
|
3902
|
+
import { existsSync as existsSync21, unwatchFile, watchFile } from "fs";
|
|
3849
3903
|
function watchForMarker(child, options2) {
|
|
3850
3904
|
const statusPath = getSignalPath();
|
|
3851
3905
|
watchFile(statusPath, { interval: 1e3 }, () => {
|
|
3852
|
-
if (!
|
|
3906
|
+
if (!existsSync21(statusPath)) return;
|
|
3853
3907
|
const signal = readSignal();
|
|
3854
3908
|
if (!signal) return;
|
|
3855
3909
|
if (signal.event === "done" && !options2?.actOnDone) return;
|
|
@@ -3915,10 +3969,11 @@ async function runPhases(item, startPhase, plan2, spawnOptions) {
|
|
|
3915
3969
|
currentPlan.length + 1
|
|
3916
3970
|
);
|
|
3917
3971
|
phaseOptions = withoutResumeSession(phaseOptions);
|
|
3918
|
-
if (phaseIndex < 0) return
|
|
3972
|
+
if (phaseIndex < 0) return { kind: "fail" };
|
|
3973
|
+
if (consumePause(item.id)) return { kind: "paused" };
|
|
3919
3974
|
currentPlan = await reloadPlan(item.id) ?? currentPlan;
|
|
3920
3975
|
}
|
|
3921
|
-
return
|
|
3976
|
+
return { kind: "completed" };
|
|
3922
3977
|
}
|
|
3923
3978
|
|
|
3924
3979
|
// src/commands/backlog/buildReviewPhase.ts
|
|
@@ -3954,8 +4009,9 @@ async function runReview(item, fallbackPlan, spawnOptions) {
|
|
|
3954
4009
|
// src/commands/backlog/runOnce.ts
|
|
3955
4010
|
async function runOnce(item, startPhase, plan2, spawnOptions) {
|
|
3956
4011
|
const reviewOptions = startPhase >= plan2.length ? spawnOptions : withoutResumeSession(spawnOptions);
|
|
3957
|
-
|
|
3958
|
-
|
|
4012
|
+
const phases = await runPhases(item, startPhase, plan2, spawnOptions);
|
|
4013
|
+
if (phases.kind === "fail") return { kind: "fail" };
|
|
4014
|
+
if (phases.kind === "paused") return { kind: "paused" };
|
|
3959
4015
|
return runReview(item, plan2, reviewOptions);
|
|
3960
4016
|
}
|
|
3961
4017
|
|
|
@@ -3976,15 +4032,10 @@ async function runPrepared(id, prepared, spawnOptions) {
|
|
|
3976
4032
|
while (true) {
|
|
3977
4033
|
const review2 = await runOnce(item, startPhase, plan2, spawnOptions);
|
|
3978
4034
|
spawnOptions = withoutResumeSession(spawnOptions);
|
|
3979
|
-
|
|
3980
|
-
if (
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
plan2 = review2.plan;
|
|
3984
|
-
continue;
|
|
3985
|
-
}
|
|
3986
|
-
await ensureDone(id);
|
|
3987
|
-
return true;
|
|
4035
|
+
const outcome = await handleReviewResult(id, review2);
|
|
4036
|
+
if (outcome.kind === "stop") return outcome.success;
|
|
4037
|
+
startPhase = outcome.startPhase;
|
|
4038
|
+
plan2 = outcome.plan;
|
|
3988
4039
|
}
|
|
3989
4040
|
} finally {
|
|
3990
4041
|
releaseLock(item.id);
|
|
@@ -4004,12 +4055,6 @@ function logProgress(id, { plan: plan2, startPhase, item }) {
|
|
|
4004
4055
|
`));
|
|
4005
4056
|
}
|
|
4006
4057
|
}
|
|
4007
|
-
async function ensureDone(id) {
|
|
4008
|
-
try {
|
|
4009
|
-
await setStatus(id, "done");
|
|
4010
|
-
} catch {
|
|
4011
|
-
}
|
|
4012
|
-
}
|
|
4013
4058
|
|
|
4014
4059
|
// src/commands/backlog/next.ts
|
|
4015
4060
|
function toChoice(item, items2) {
|
|
@@ -4069,11 +4114,11 @@ import chalk37 from "chalk";
|
|
|
4069
4114
|
|
|
4070
4115
|
// src/commands/backlog/appendComment.ts
|
|
4071
4116
|
import { sql as sql2 } from "drizzle-orm";
|
|
4072
|
-
async function appendComment(orm, itemId,
|
|
4117
|
+
async function appendComment(orm, itemId, text3, opts = {}) {
|
|
4073
4118
|
await orm.insert(comments).values({
|
|
4074
4119
|
itemId,
|
|
4075
4120
|
idx: sql2`(SELECT COALESCE(MAX(${comments.idx}) + 1, 0) FROM ${comments} WHERE ${comments.itemId} = ${itemId})`,
|
|
4076
|
-
text:
|
|
4121
|
+
text: text3,
|
|
4077
4122
|
phase: opts.phase ?? null,
|
|
4078
4123
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4079
4124
|
type: opts.type ?? "comment"
|
|
@@ -4351,10 +4396,10 @@ function startWebServer(label2, port, handler, initialPath) {
|
|
|
4351
4396
|
import { spawn as spawn4 } from "child_process";
|
|
4352
4397
|
import {
|
|
4353
4398
|
closeSync,
|
|
4354
|
-
mkdirSync as
|
|
4399
|
+
mkdirSync as mkdirSync7,
|
|
4355
4400
|
openSync,
|
|
4356
4401
|
statSync,
|
|
4357
|
-
unlinkSync as
|
|
4402
|
+
unlinkSync as unlinkSync5,
|
|
4358
4403
|
writeSync
|
|
4359
4404
|
} from "fs";
|
|
4360
4405
|
|
|
@@ -4362,15 +4407,15 @@ import {
|
|
|
4362
4407
|
import * as net from "net";
|
|
4363
4408
|
|
|
4364
4409
|
// src/commands/sessions/daemon/daemonPaths.ts
|
|
4365
|
-
import { homedir as
|
|
4366
|
-
import { join as
|
|
4367
|
-
var DAEMON_DIR =
|
|
4410
|
+
import { homedir as homedir6 } from "os";
|
|
4411
|
+
import { join as join17 } from "path";
|
|
4412
|
+
var DAEMON_DIR = join17(homedir6(), ".assist", "daemon");
|
|
4368
4413
|
var daemonPaths = {
|
|
4369
4414
|
dir: DAEMON_DIR,
|
|
4370
|
-
socket: process.platform === "win32" ? "\\\\.\\pipe\\assist-sessions-daemon" :
|
|
4371
|
-
log:
|
|
4372
|
-
pid:
|
|
4373
|
-
spawnLock:
|
|
4415
|
+
socket: process.platform === "win32" ? "\\\\.\\pipe\\assist-sessions-daemon" : join17(DAEMON_DIR, "daemon.sock"),
|
|
4416
|
+
log: join17(DAEMON_DIR, "daemon.log"),
|
|
4417
|
+
pid: join17(DAEMON_DIR, "daemon.pid"),
|
|
4418
|
+
spawnLock: join17(DAEMON_DIR, "spawn.lock")
|
|
4374
4419
|
};
|
|
4375
4420
|
|
|
4376
4421
|
// src/commands/sessions/daemon/connectToDaemon.ts
|
|
@@ -4396,7 +4441,7 @@ var RETRY_DELAY_MS = 200;
|
|
|
4396
4441
|
var STALE_LOCK_MS = SPAWN_TIMEOUT_MS + 5e3;
|
|
4397
4442
|
async function ensureDaemonRunning(reason = "unspecified") {
|
|
4398
4443
|
if (await isDaemonRunning()) return;
|
|
4399
|
-
|
|
4444
|
+
mkdirSync7(daemonPaths.dir, { recursive: true });
|
|
4400
4445
|
const holdsLock = acquireSpawnLock();
|
|
4401
4446
|
if (holdsLock) spawnDaemon(reason);
|
|
4402
4447
|
try {
|
|
@@ -4419,7 +4464,7 @@ function acquireSpawnLock() {
|
|
|
4419
4464
|
if (tryCreateLock()) return true;
|
|
4420
4465
|
if (!isLockStale()) return false;
|
|
4421
4466
|
try {
|
|
4422
|
-
|
|
4467
|
+
unlinkSync5(daemonPaths.spawnLock);
|
|
4423
4468
|
} catch {
|
|
4424
4469
|
}
|
|
4425
4470
|
return tryCreateLock();
|
|
@@ -4443,7 +4488,7 @@ function isLockStale() {
|
|
|
4443
4488
|
}
|
|
4444
4489
|
function releaseSpawnLock() {
|
|
4445
4490
|
try {
|
|
4446
|
-
|
|
4491
|
+
unlinkSync5(daemonPaths.spawnLock);
|
|
4447
4492
|
} catch {
|
|
4448
4493
|
}
|
|
4449
4494
|
}
|
|
@@ -4466,14 +4511,14 @@ import { createRequire as createRequire2 } from "module";
|
|
|
4466
4511
|
|
|
4467
4512
|
// src/shared/createBundleHandler.ts
|
|
4468
4513
|
import { readFileSync as readFileSync13 } from "fs";
|
|
4469
|
-
import { dirname as dirname16, join as
|
|
4514
|
+
import { dirname as dirname16, join as join18 } from "path";
|
|
4470
4515
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
4471
4516
|
function createBundleHandler(importMetaUrl, bundlePath) {
|
|
4472
4517
|
const dir = dirname16(fileURLToPath4(importMetaUrl));
|
|
4473
4518
|
let cache;
|
|
4474
4519
|
return (_req, res) => {
|
|
4475
4520
|
if (!cache) {
|
|
4476
|
-
cache = readFileSync13(
|
|
4521
|
+
cache = readFileSync13(join18(dir, bundlePath), "utf-8");
|
|
4477
4522
|
}
|
|
4478
4523
|
res.writeHead(200, { "Content-Type": "application/javascript" });
|
|
4479
4524
|
res.end(cache);
|
|
@@ -5076,10 +5121,10 @@ async function web2(options2) {
|
|
|
5076
5121
|
|
|
5077
5122
|
// src/commands/backlog/comment/index.ts
|
|
5078
5123
|
import chalk45 from "chalk";
|
|
5079
|
-
async function comment(id,
|
|
5124
|
+
async function comment(id, text3) {
|
|
5080
5125
|
const found = await findOneItem(id);
|
|
5081
5126
|
if (!found) process.exit(1);
|
|
5082
|
-
await appendComment(found.orm, found.item.id,
|
|
5127
|
+
await appendComment(found.orm, found.item.id, text3);
|
|
5083
5128
|
console.log(chalk45.green(`Comment added to item #${id}.`));
|
|
5084
5129
|
}
|
|
5085
5130
|
|
|
@@ -5249,9 +5294,9 @@ function readLine(dump, start3) {
|
|
|
5249
5294
|
return { text: dump.subarray(start3, eol).toString("utf8"), next: eol + 1 };
|
|
5250
5295
|
}
|
|
5251
5296
|
function parseHeader(dump) {
|
|
5252
|
-
const { text:
|
|
5297
|
+
const { text: text3, next: next3 } = readLine(dump, 0);
|
|
5253
5298
|
try {
|
|
5254
|
-
return { header: JSON.parse(
|
|
5299
|
+
return { header: JSON.parse(text3), bodyStart: next3 };
|
|
5255
5300
|
} catch {
|
|
5256
5301
|
return invalid("header is not valid JSON.");
|
|
5257
5302
|
}
|
|
@@ -5260,9 +5305,9 @@ function parseSections(dump, bodyStart) {
|
|
|
5260
5305
|
const sections = /* @__PURE__ */ new Map();
|
|
5261
5306
|
let cursor = bodyStart;
|
|
5262
5307
|
while (cursor < dump.length) {
|
|
5263
|
-
const { text:
|
|
5264
|
-
const match =
|
|
5265
|
-
if (!match) invalid(`malformed table marker "${
|
|
5308
|
+
const { text: text3, next: next3 } = readLine(dump, cursor);
|
|
5309
|
+
const match = text3.match(/^@table (\S+) (\d+)$/);
|
|
5310
|
+
if (!match) invalid(`malformed table marker "${text3}".`);
|
|
5266
5311
|
const [, name, bytes] = match;
|
|
5267
5312
|
const end = next3 + Number(bytes);
|
|
5268
5313
|
if (end > dump.length) invalid(`section "${name}" overruns the dump.`);
|
|
@@ -5416,9 +5461,9 @@ import chalk51 from "chalk";
|
|
|
5416
5461
|
|
|
5417
5462
|
// src/commands/backlog/add/shared.ts
|
|
5418
5463
|
import { spawnSync } from "child_process";
|
|
5419
|
-
import { mkdtempSync, readFileSync as readFileSync15, unlinkSync as
|
|
5464
|
+
import { mkdtempSync, readFileSync as readFileSync15, unlinkSync as unlinkSync6, writeFileSync as writeFileSync15 } from "fs";
|
|
5420
5465
|
import { tmpdir } from "os";
|
|
5421
|
-
import { join as
|
|
5466
|
+
import { join as join19 } from "path";
|
|
5422
5467
|
import enquirer6 from "enquirer";
|
|
5423
5468
|
async function promptType() {
|
|
5424
5469
|
const { type } = await enquirer6.prompt({
|
|
@@ -5458,16 +5503,16 @@ async function promptDescription() {
|
|
|
5458
5503
|
}
|
|
5459
5504
|
function openEditor() {
|
|
5460
5505
|
const editor = process.env.EDITOR || process.env.VISUAL || "vi";
|
|
5461
|
-
const dir = mkdtempSync(
|
|
5462
|
-
const filePath =
|
|
5463
|
-
|
|
5506
|
+
const dir = mkdtempSync(join19(tmpdir(), "assist-"));
|
|
5507
|
+
const filePath = join19(dir, "description.md");
|
|
5508
|
+
writeFileSync15(filePath, "");
|
|
5464
5509
|
const result = spawnSync(editor, [filePath], { stdio: "inherit" });
|
|
5465
5510
|
if (result.status !== 0) {
|
|
5466
|
-
|
|
5511
|
+
unlinkSync6(filePath);
|
|
5467
5512
|
return void 0;
|
|
5468
5513
|
}
|
|
5469
5514
|
const content = readFileSync15(filePath, "utf-8").trim();
|
|
5470
|
-
|
|
5515
|
+
unlinkSync6(filePath);
|
|
5471
5516
|
return content || void 0;
|
|
5472
5517
|
}
|
|
5473
5518
|
async function promptAcceptanceCriteria() {
|
|
@@ -5600,8 +5645,8 @@ import chalk54 from "chalk";
|
|
|
5600
5645
|
// src/commands/backlog/originDisplayName.ts
|
|
5601
5646
|
function originDisplayName(origin) {
|
|
5602
5647
|
if (origin.startsWith("local:")) {
|
|
5603
|
-
const
|
|
5604
|
-
const segments =
|
|
5648
|
+
const path54 = origin.slice("local:".length).replace(/\/+$/, "");
|
|
5649
|
+
const segments = path54.split("/").filter(Boolean);
|
|
5605
5650
|
return segments[segments.length - 1] ?? origin;
|
|
5606
5651
|
}
|
|
5607
5652
|
const firstSlash = origin.indexOf("/");
|
|
@@ -6724,13 +6769,13 @@ function stripEnvPrefix(parts) {
|
|
|
6724
6769
|
}
|
|
6725
6770
|
|
|
6726
6771
|
// src/commands/cliHook/logDeniedToolCall.ts
|
|
6727
|
-
import { mkdirSync as
|
|
6728
|
-
import { homedir as
|
|
6729
|
-
import { join as
|
|
6772
|
+
import { mkdirSync as mkdirSync8 } from "fs";
|
|
6773
|
+
import { homedir as homedir7 } from "os";
|
|
6774
|
+
import { join as join20 } from "path";
|
|
6730
6775
|
import Database from "better-sqlite3";
|
|
6731
6776
|
var _db;
|
|
6732
6777
|
function getDbDir() {
|
|
6733
|
-
return
|
|
6778
|
+
return join20(homedir7(), ".assist");
|
|
6734
6779
|
}
|
|
6735
6780
|
function initSchema(db) {
|
|
6736
6781
|
db.exec(`
|
|
@@ -6748,8 +6793,8 @@ function initSchema(db) {
|
|
|
6748
6793
|
function openPromptsDb(dir) {
|
|
6749
6794
|
if (_db) return _db;
|
|
6750
6795
|
const dbDir = dir ?? getDbDir();
|
|
6751
|
-
|
|
6752
|
-
const db = new Database(
|
|
6796
|
+
mkdirSync8(dbDir, { recursive: true });
|
|
6797
|
+
const db = new Database(join20(dbDir, "assist.db"));
|
|
6753
6798
|
db.pragma("journal_mode = WAL");
|
|
6754
6799
|
initSchema(db);
|
|
6755
6800
|
_db = db;
|
|
@@ -6851,7 +6896,7 @@ function extractGraphqlQuery(args) {
|
|
|
6851
6896
|
}
|
|
6852
6897
|
|
|
6853
6898
|
// src/shared/loadCliReads.ts
|
|
6854
|
-
import { existsSync as
|
|
6899
|
+
import { existsSync as existsSync22, readFileSync as readFileSync16, writeFileSync as writeFileSync16 } from "fs";
|
|
6855
6900
|
import { dirname as dirname17, resolve as resolve7 } from "path";
|
|
6856
6901
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
6857
6902
|
var __filename3 = fileURLToPath5(import.meta.url);
|
|
@@ -6859,9 +6904,9 @@ var __dirname5 = dirname17(__filename3);
|
|
|
6859
6904
|
function packageRoot() {
|
|
6860
6905
|
return __dirname5;
|
|
6861
6906
|
}
|
|
6862
|
-
function readLines(
|
|
6863
|
-
if (!
|
|
6864
|
-
return readFileSync16(
|
|
6907
|
+
function readLines(path54) {
|
|
6908
|
+
if (!existsSync22(path54)) return [];
|
|
6909
|
+
return readFileSync16(path54, "utf-8").split("\n").filter((line) => line.trim() !== "");
|
|
6865
6910
|
}
|
|
6866
6911
|
var cachedReads;
|
|
6867
6912
|
var cachedWrites;
|
|
@@ -6881,7 +6926,7 @@ function loadCliReads() {
|
|
|
6881
6926
|
return getCliReadsLines();
|
|
6882
6927
|
}
|
|
6883
6928
|
function saveCliReads(commands) {
|
|
6884
|
-
|
|
6929
|
+
writeFileSync16(
|
|
6885
6930
|
resolve7(packageRoot(), "allowed.cli-reads"),
|
|
6886
6931
|
`${commands.join("\n")}
|
|
6887
6932
|
`
|
|
@@ -6907,14 +6952,14 @@ function findCliWrite(command) {
|
|
|
6907
6952
|
}
|
|
6908
6953
|
|
|
6909
6954
|
// src/shared/readSettingsPerms.ts
|
|
6910
|
-
import { existsSync as
|
|
6911
|
-
import { homedir as
|
|
6912
|
-
import { join as
|
|
6955
|
+
import { existsSync as existsSync23, readFileSync as readFileSync17 } from "fs";
|
|
6956
|
+
import { homedir as homedir8 } from "os";
|
|
6957
|
+
import { join as join21 } from "path";
|
|
6913
6958
|
function readSettingsPerms(key) {
|
|
6914
6959
|
const paths = [
|
|
6915
|
-
|
|
6916
|
-
|
|
6917
|
-
|
|
6960
|
+
join21(homedir8(), ".claude", "settings.json"),
|
|
6961
|
+
join21(process.cwd(), ".claude", "settings.json"),
|
|
6962
|
+
join21(process.cwd(), ".claude", "settings.local.json")
|
|
6918
6963
|
];
|
|
6919
6964
|
const entries = [];
|
|
6920
6965
|
for (const p of paths) {
|
|
@@ -6923,7 +6968,7 @@ function readSettingsPerms(key) {
|
|
|
6923
6968
|
return entries;
|
|
6924
6969
|
}
|
|
6925
6970
|
function readPermissionArray(filePath, key) {
|
|
6926
|
-
if (!
|
|
6971
|
+
if (!existsSync23(filePath)) return [];
|
|
6927
6972
|
try {
|
|
6928
6973
|
const data = JSON.parse(readFileSync17(filePath, "utf-8"));
|
|
6929
6974
|
const arr = data?.permissions?.[key];
|
|
@@ -7205,9 +7250,9 @@ ${reasons.join("\n")}`);
|
|
|
7205
7250
|
}
|
|
7206
7251
|
|
|
7207
7252
|
// src/commands/permitCliReads/index.ts
|
|
7208
|
-
import { existsSync as
|
|
7209
|
-
import { homedir as
|
|
7210
|
-
import { join as
|
|
7253
|
+
import { existsSync as existsSync24, mkdirSync as mkdirSync9, readFileSync as readFileSync18, writeFileSync as writeFileSync17 } from "fs";
|
|
7254
|
+
import { homedir as homedir9 } from "os";
|
|
7255
|
+
import { join as join22 } from "path";
|
|
7211
7256
|
|
|
7212
7257
|
// src/shared/checkCliAvailable.ts
|
|
7213
7258
|
import { execSync as execSync22 } from "child_process";
|
|
@@ -7344,14 +7389,14 @@ function showProgress(p, label2) {
|
|
|
7344
7389
|
const pct = Math.round(p.done / p.total * 100);
|
|
7345
7390
|
process.stderr.write(`\r\x1B[K[${pct}%] Scanning ${label2}...`);
|
|
7346
7391
|
}
|
|
7347
|
-
async function resolveCommand(cli,
|
|
7348
|
-
showProgress(p,
|
|
7349
|
-
const subHelp = await runHelp([cli, ...
|
|
7392
|
+
async function resolveCommand(cli, path54, description, depth, p) {
|
|
7393
|
+
showProgress(p, path54.join(" "));
|
|
7394
|
+
const subHelp = await runHelp([cli, ...path54]);
|
|
7350
7395
|
if (!subHelp || !hasSubcommands(subHelp)) {
|
|
7351
|
-
return [{ path:
|
|
7396
|
+
return [{ path: path54, description }];
|
|
7352
7397
|
}
|
|
7353
|
-
const children = await discoverAt(cli,
|
|
7354
|
-
return children.length > 0 ? children : [{ path:
|
|
7398
|
+
const children = await discoverAt(cli, path54, depth + 1, p);
|
|
7399
|
+
return children.length > 0 ? children : [{ path: path54, description }];
|
|
7355
7400
|
}
|
|
7356
7401
|
async function discoverAt(cli, parentPath, depth, p) {
|
|
7357
7402
|
if (depth > SAFETY_DEPTH) return [];
|
|
@@ -7461,8 +7506,8 @@ function formatHuman(cli, commands) {
|
|
|
7461
7506
|
`];
|
|
7462
7507
|
for (const cmd of sorted) {
|
|
7463
7508
|
const full = `${cli} ${cmd.path.join(" ")}`;
|
|
7464
|
-
const
|
|
7465
|
-
lines.push(`${prefix(classifyVerb(cmd.path))}${
|
|
7509
|
+
const text3 = cmd.description ? `${full} \u2014 ${cmd.description}` : full;
|
|
7510
|
+
lines.push(`${prefix(classifyVerb(cmd.path))}${text3}`);
|
|
7466
7511
|
}
|
|
7467
7512
|
return lines.join("\n");
|
|
7468
7513
|
}
|
|
@@ -7496,17 +7541,17 @@ function updateSettings(cli, commands) {
|
|
|
7496
7541
|
// src/commands/permitCliReads/index.ts
|
|
7497
7542
|
function logPath(cli) {
|
|
7498
7543
|
const safeName = cli.replace(/\s+/g, "-");
|
|
7499
|
-
return
|
|
7544
|
+
return join22(homedir9(), ".assist", `cli-discover-${safeName}.log`);
|
|
7500
7545
|
}
|
|
7501
7546
|
function readCache(cli) {
|
|
7502
|
-
const
|
|
7503
|
-
if (!
|
|
7504
|
-
return readFileSync18(
|
|
7547
|
+
const path54 = logPath(cli);
|
|
7548
|
+
if (!existsSync24(path54)) return void 0;
|
|
7549
|
+
return readFileSync18(path54, "utf-8");
|
|
7505
7550
|
}
|
|
7506
7551
|
function writeCache(cli, output) {
|
|
7507
|
-
const dir =
|
|
7508
|
-
|
|
7509
|
-
|
|
7552
|
+
const dir = join22(homedir9(), ".assist");
|
|
7553
|
+
mkdirSync9(dir, { recursive: true });
|
|
7554
|
+
writeFileSync17(logPath(cli), output);
|
|
7510
7555
|
}
|
|
7511
7556
|
async function permitCliReads(cli, options2 = { noCache: false }) {
|
|
7512
7557
|
if (!cli) {
|
|
@@ -8190,8 +8235,8 @@ function stepIntoNested(container, key, nextKey) {
|
|
|
8190
8235
|
}
|
|
8191
8236
|
return ensureObject(container, resolved);
|
|
8192
8237
|
}
|
|
8193
|
-
function setNestedValue(obj,
|
|
8194
|
-
const keys =
|
|
8238
|
+
function setNestedValue(obj, path54, value) {
|
|
8239
|
+
const keys = path54.split(".");
|
|
8195
8240
|
const result = { ...obj };
|
|
8196
8241
|
let current = result;
|
|
8197
8242
|
for (let i = 0; i < keys.length - 1; i++) {
|
|
@@ -8271,9 +8316,9 @@ function isTraversable(value) {
|
|
|
8271
8316
|
function stepInto(current, key) {
|
|
8272
8317
|
return isTraversable(current) ? current[key] : void 0;
|
|
8273
8318
|
}
|
|
8274
|
-
function getNestedValue(obj,
|
|
8319
|
+
function getNestedValue(obj, path54) {
|
|
8275
8320
|
let current = obj;
|
|
8276
|
-
for (const key of
|
|
8321
|
+
for (const key of path54.split(".")) current = stepInto(current, key);
|
|
8277
8322
|
return current;
|
|
8278
8323
|
}
|
|
8279
8324
|
|
|
@@ -8307,7 +8352,7 @@ function registerConfig(program2) {
|
|
|
8307
8352
|
}
|
|
8308
8353
|
|
|
8309
8354
|
// src/commands/deploy/redirect.ts
|
|
8310
|
-
import { existsSync as
|
|
8355
|
+
import { existsSync as existsSync25, readFileSync as readFileSync19, writeFileSync as writeFileSync18 } from "fs";
|
|
8311
8356
|
import chalk88 from "chalk";
|
|
8312
8357
|
var TRAILING_SLASH_SCRIPT = ` <script>
|
|
8313
8358
|
if (!window.location.pathname.endsWith('/')) {
|
|
@@ -8316,7 +8361,7 @@ var TRAILING_SLASH_SCRIPT = ` <script>
|
|
|
8316
8361
|
</script>`;
|
|
8317
8362
|
function redirect() {
|
|
8318
8363
|
const indexPath = "index.html";
|
|
8319
|
-
if (!
|
|
8364
|
+
if (!existsSync25(indexPath)) {
|
|
8320
8365
|
console.log(chalk88.yellow("No index.html found"));
|
|
8321
8366
|
return;
|
|
8322
8367
|
}
|
|
@@ -8331,7 +8376,7 @@ function redirect() {
|
|
|
8331
8376
|
return;
|
|
8332
8377
|
}
|
|
8333
8378
|
const newContent = content.slice(0, headCloseIndex) + TRAILING_SLASH_SCRIPT + "\n " + content.slice(headCloseIndex);
|
|
8334
|
-
|
|
8379
|
+
writeFileSync18(indexPath, newContent);
|
|
8335
8380
|
console.log(chalk88.green("Added trailing slash redirect to index.html"));
|
|
8336
8381
|
}
|
|
8337
8382
|
|
|
@@ -8347,11 +8392,11 @@ import { execFileSync } from "child_process";
|
|
|
8347
8392
|
import { basename as basename4 } from "path";
|
|
8348
8393
|
|
|
8349
8394
|
// src/commands/devlog/loadBlogSkipDays.ts
|
|
8350
|
-
import { homedir as
|
|
8351
|
-
import { join as
|
|
8352
|
-
var BLOG_REPO_ROOT =
|
|
8395
|
+
import { homedir as homedir10 } from "os";
|
|
8396
|
+
import { join as join23 } from "path";
|
|
8397
|
+
var BLOG_REPO_ROOT = join23(homedir10(), "git/blog");
|
|
8353
8398
|
function loadBlogSkipDays(repoName) {
|
|
8354
|
-
const config = loadRawYaml(
|
|
8399
|
+
const config = loadRawYaml(join23(BLOG_REPO_ROOT, "assist.yml"));
|
|
8355
8400
|
const devlog = config.devlog;
|
|
8356
8401
|
const skip2 = devlog?.skip;
|
|
8357
8402
|
return new Set(skip2?.[repoName] ?? []);
|
|
@@ -8362,15 +8407,15 @@ import { execSync as execSync23 } from "child_process";
|
|
|
8362
8407
|
import chalk89 from "chalk";
|
|
8363
8408
|
|
|
8364
8409
|
// src/shared/getRepoName.ts
|
|
8365
|
-
import { existsSync as
|
|
8366
|
-
import { basename as basename3, join as
|
|
8410
|
+
import { existsSync as existsSync26, readFileSync as readFileSync20 } from "fs";
|
|
8411
|
+
import { basename as basename3, join as join24 } from "path";
|
|
8367
8412
|
function getRepoName() {
|
|
8368
8413
|
const config = loadConfig();
|
|
8369
8414
|
if (config.devlog?.name) {
|
|
8370
8415
|
return config.devlog.name;
|
|
8371
8416
|
}
|
|
8372
|
-
const packageJsonPath =
|
|
8373
|
-
if (
|
|
8417
|
+
const packageJsonPath = join24(process.cwd(), "package.json");
|
|
8418
|
+
if (existsSync26(packageJsonPath)) {
|
|
8374
8419
|
try {
|
|
8375
8420
|
const content = readFileSync20(packageJsonPath, "utf-8");
|
|
8376
8421
|
const pkg = JSON.parse(content);
|
|
@@ -8385,8 +8430,8 @@ function getRepoName() {
|
|
|
8385
8430
|
|
|
8386
8431
|
// src/commands/devlog/loadDevlogEntries.ts
|
|
8387
8432
|
import { readdirSync, readFileSync as readFileSync21 } from "fs";
|
|
8388
|
-
import { join as
|
|
8389
|
-
var DEVLOG_DIR =
|
|
8433
|
+
import { join as join25 } from "path";
|
|
8434
|
+
var DEVLOG_DIR = join25(BLOG_REPO_ROOT, "src/content/devlog");
|
|
8390
8435
|
function extractFrontmatter(content) {
|
|
8391
8436
|
const fm = content.match(/^---\n([\s\S]*?)\n---/);
|
|
8392
8437
|
return fm?.[1] ?? null;
|
|
@@ -8414,7 +8459,7 @@ function readDevlogFiles(callback) {
|
|
|
8414
8459
|
try {
|
|
8415
8460
|
const files = readdirSync(DEVLOG_DIR).filter((f) => f.endsWith(".md"));
|
|
8416
8461
|
for (const file of files) {
|
|
8417
|
-
const content = readFileSync21(
|
|
8462
|
+
const content = readFileSync21(join25(DEVLOG_DIR, file), "utf-8");
|
|
8418
8463
|
const parsed = parseFrontmatter(content, file);
|
|
8419
8464
|
if (parsed) callback(parsed);
|
|
8420
8465
|
}
|
|
@@ -8801,12 +8846,12 @@ function repos(options2) {
|
|
|
8801
8846
|
}
|
|
8802
8847
|
|
|
8803
8848
|
// src/commands/devlog/skip.ts
|
|
8804
|
-
import { writeFileSync as
|
|
8805
|
-
import { join as
|
|
8849
|
+
import { writeFileSync as writeFileSync19 } from "fs";
|
|
8850
|
+
import { join as join26 } from "path";
|
|
8806
8851
|
import chalk94 from "chalk";
|
|
8807
8852
|
import { stringify as stringifyYaml3 } from "yaml";
|
|
8808
8853
|
function getBlogConfigPath() {
|
|
8809
|
-
return
|
|
8854
|
+
return join26(BLOG_REPO_ROOT, "assist.yml");
|
|
8810
8855
|
}
|
|
8811
8856
|
function skip(date) {
|
|
8812
8857
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
|
|
@@ -8830,7 +8875,7 @@ function skip(date) {
|
|
|
8830
8875
|
skip2[repoName] = skipDays;
|
|
8831
8876
|
devlog.skip = skip2;
|
|
8832
8877
|
config.devlog = devlog;
|
|
8833
|
-
|
|
8878
|
+
writeFileSync19(configPath, stringifyYaml3(config, { lineWidth: 0 }));
|
|
8834
8879
|
console.log(chalk94.green(`Added ${date} to skip list for ${repoName}`));
|
|
8835
8880
|
}
|
|
8836
8881
|
|
|
@@ -8867,16 +8912,16 @@ function registerDevlog(program2) {
|
|
|
8867
8912
|
|
|
8868
8913
|
// src/commands/dotnet/checkBuildLocks.ts
|
|
8869
8914
|
import { closeSync as closeSync2, openSync as openSync2, readdirSync as readdirSync2 } from "fs";
|
|
8870
|
-
import { join as
|
|
8915
|
+
import { join as join27 } from "path";
|
|
8871
8916
|
import chalk96 from "chalk";
|
|
8872
8917
|
|
|
8873
8918
|
// src/shared/findRepoRoot.ts
|
|
8874
|
-
import { existsSync as
|
|
8919
|
+
import { existsSync as existsSync27 } from "fs";
|
|
8875
8920
|
import path20 from "path";
|
|
8876
8921
|
function findRepoRoot(dir) {
|
|
8877
8922
|
let current = dir;
|
|
8878
8923
|
while (current !== path20.dirname(current)) {
|
|
8879
|
-
if (
|
|
8924
|
+
if (existsSync27(path20.join(current, ".git"))) {
|
|
8880
8925
|
return current;
|
|
8881
8926
|
}
|
|
8882
8927
|
current = path20.dirname(current);
|
|
@@ -8895,7 +8940,7 @@ function isLockedDll(debugDir) {
|
|
|
8895
8940
|
}
|
|
8896
8941
|
for (const file of files) {
|
|
8897
8942
|
if (!file.toLowerCase().endsWith(".dll")) continue;
|
|
8898
|
-
const dllPath =
|
|
8943
|
+
const dllPath = join27(debugDir, file);
|
|
8899
8944
|
try {
|
|
8900
8945
|
const fd = openSync2(dllPath, "r+");
|
|
8901
8946
|
closeSync2(fd);
|
|
@@ -8913,13 +8958,13 @@ function findFirstLockedDll(dir) {
|
|
|
8913
8958
|
return null;
|
|
8914
8959
|
}
|
|
8915
8960
|
if (entries.includes("bin")) {
|
|
8916
|
-
const locked = isLockedDll(
|
|
8961
|
+
const locked = isLockedDll(join27(dir, "bin", "Debug"));
|
|
8917
8962
|
if (locked) return locked;
|
|
8918
8963
|
}
|
|
8919
8964
|
for (const entry of entries) {
|
|
8920
8965
|
if (SKIP_DIRS.has(entry) || entry === "bin" || entry.startsWith("."))
|
|
8921
8966
|
continue;
|
|
8922
|
-
const found = findFirstLockedDll(
|
|
8967
|
+
const found = findFirstLockedDll(join27(dir, entry));
|
|
8923
8968
|
if (found) return found;
|
|
8924
8969
|
}
|
|
8925
8970
|
return null;
|
|
@@ -9087,12 +9132,12 @@ function printJson(tree, totalCount, solutions) {
|
|
|
9087
9132
|
}
|
|
9088
9133
|
|
|
9089
9134
|
// src/commands/dotnet/resolveCsproj.ts
|
|
9090
|
-
import { existsSync as
|
|
9135
|
+
import { existsSync as existsSync28 } from "fs";
|
|
9091
9136
|
import path23 from "path";
|
|
9092
9137
|
import chalk98 from "chalk";
|
|
9093
9138
|
function resolveCsproj(csprojPath) {
|
|
9094
9139
|
const resolved = path23.resolve(csprojPath);
|
|
9095
|
-
if (!
|
|
9140
|
+
if (!existsSync28(resolved)) {
|
|
9096
9141
|
console.error(chalk98.red(`File not found: ${resolved}`));
|
|
9097
9142
|
process.exit(1);
|
|
9098
9143
|
}
|
|
@@ -9260,17 +9305,17 @@ function filterIssues(issues, all, cliOnly, cliSuppress) {
|
|
|
9260
9305
|
}
|
|
9261
9306
|
|
|
9262
9307
|
// src/commands/dotnet/resolveSolution.ts
|
|
9263
|
-
import { existsSync as
|
|
9308
|
+
import { existsSync as existsSync29 } from "fs";
|
|
9264
9309
|
import path24 from "path";
|
|
9265
9310
|
import chalk102 from "chalk";
|
|
9266
9311
|
|
|
9267
9312
|
// src/commands/dotnet/findSolution.ts
|
|
9268
9313
|
import { readdirSync as readdirSync4 } from "fs";
|
|
9269
|
-
import { dirname as dirname18, join as
|
|
9314
|
+
import { dirname as dirname18, join as join28 } from "path";
|
|
9270
9315
|
import chalk101 from "chalk";
|
|
9271
9316
|
function findSlnInDir(dir) {
|
|
9272
9317
|
try {
|
|
9273
|
-
return readdirSync4(dir).filter((f) => f.endsWith(".sln")).map((f) =>
|
|
9318
|
+
return readdirSync4(dir).filter((f) => f.endsWith(".sln")).map((f) => join28(dir, f));
|
|
9274
9319
|
} catch {
|
|
9275
9320
|
return [];
|
|
9276
9321
|
}
|
|
@@ -9301,7 +9346,7 @@ function findSolution() {
|
|
|
9301
9346
|
function resolveSolution(sln) {
|
|
9302
9347
|
if (sln) {
|
|
9303
9348
|
const resolved = path24.resolve(sln);
|
|
9304
|
-
if (!
|
|
9349
|
+
if (!existsSync29(resolved)) {
|
|
9305
9350
|
console.error(chalk102.red(`Solution file not found: ${resolved}`));
|
|
9306
9351
|
process.exit(1);
|
|
9307
9352
|
}
|
|
@@ -9341,7 +9386,7 @@ function parseInspectReport(json) {
|
|
|
9341
9386
|
|
|
9342
9387
|
// src/commands/dotnet/runInspectCode.ts
|
|
9343
9388
|
import { execSync as execSync27 } from "child_process";
|
|
9344
|
-
import { existsSync as
|
|
9389
|
+
import { existsSync as existsSync30, readFileSync as readFileSync24, unlinkSync as unlinkSync7 } from "fs";
|
|
9345
9390
|
import { tmpdir as tmpdir3 } from "os";
|
|
9346
9391
|
import path25 from "path";
|
|
9347
9392
|
import chalk103 from "chalk";
|
|
@@ -9372,12 +9417,12 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
9372
9417
|
console.error(chalk103.red("jb inspectcode failed"));
|
|
9373
9418
|
process.exit(1);
|
|
9374
9419
|
}
|
|
9375
|
-
if (!
|
|
9420
|
+
if (!existsSync30(reportPath)) {
|
|
9376
9421
|
console.error(chalk103.red("Report file not generated"));
|
|
9377
9422
|
process.exit(1);
|
|
9378
9423
|
}
|
|
9379
9424
|
const xml = readFileSync24(reportPath, "utf-8");
|
|
9380
|
-
|
|
9425
|
+
unlinkSync7(reportPath);
|
|
9381
9426
|
return xml;
|
|
9382
9427
|
}
|
|
9383
9428
|
|
|
@@ -9503,9 +9548,9 @@ function aggregateCommitters(authorLists) {
|
|
|
9503
9548
|
|
|
9504
9549
|
// src/shared/runGhGraphql.ts
|
|
9505
9550
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
9506
|
-
import { unlinkSync as
|
|
9551
|
+
import { unlinkSync as unlinkSync8, writeFileSync as writeFileSync20 } from "fs";
|
|
9507
9552
|
import { tmpdir as tmpdir4 } from "os";
|
|
9508
|
-
import { join as
|
|
9553
|
+
import { join as join29 } from "path";
|
|
9509
9554
|
function buildArgs2(queryFile, vars) {
|
|
9510
9555
|
const args = ["api", "graphql", "-F", `query=@${queryFile}`];
|
|
9511
9556
|
for (const [key, value] of Object.entries(vars)) {
|
|
@@ -9530,8 +9575,8 @@ function throwOnGraphqlErrors(stdout) {
|
|
|
9530
9575
|
throw new Error(messages || "GraphQL request returned errors");
|
|
9531
9576
|
}
|
|
9532
9577
|
function runGhGraphql(mutation, vars) {
|
|
9533
|
-
const queryFile =
|
|
9534
|
-
|
|
9578
|
+
const queryFile = join29(tmpdir4(), `gh-query-${Date.now()}.graphql`);
|
|
9579
|
+
writeFileSync20(queryFile, mutation);
|
|
9535
9580
|
try {
|
|
9536
9581
|
const result = spawnSync2("gh", buildArgs2(queryFile, vars), {
|
|
9537
9582
|
encoding: "utf-8"
|
|
@@ -9540,7 +9585,7 @@ function runGhGraphql(mutation, vars) {
|
|
|
9540
9585
|
throwOnGraphqlErrors(result.stdout);
|
|
9541
9586
|
return result.stdout;
|
|
9542
9587
|
} finally {
|
|
9543
|
-
|
|
9588
|
+
unlinkSync8(queryFile);
|
|
9544
9589
|
}
|
|
9545
9590
|
}
|
|
9546
9591
|
|
|
@@ -9709,8 +9754,8 @@ function registerGithub(program2) {
|
|
|
9709
9754
|
}
|
|
9710
9755
|
|
|
9711
9756
|
// src/commands/handover/archive.ts
|
|
9712
|
-
import { existsSync as
|
|
9713
|
-
import { join as
|
|
9757
|
+
import { existsSync as existsSync31, mkdirSync as mkdirSync10, renameSync as renameSync2 } from "fs";
|
|
9758
|
+
import { join as join31 } from "path";
|
|
9714
9759
|
|
|
9715
9760
|
// src/commands/handover/formatArchiveTimestamp.ts
|
|
9716
9761
|
function formatArchiveTimestamp(date = /* @__PURE__ */ new Date()) {
|
|
@@ -9725,9 +9770,9 @@ function formatArchiveTimestamp(date = /* @__PURE__ */ new Date()) {
|
|
|
9725
9770
|
}
|
|
9726
9771
|
|
|
9727
9772
|
// src/commands/handover/getHandoverArchiveDir.ts
|
|
9728
|
-
import { join as
|
|
9773
|
+
import { join as join30 } from "path";
|
|
9729
9774
|
function getHandoverArchiveDir(cwd = process.cwd()) {
|
|
9730
|
-
return
|
|
9775
|
+
return join30(cwd, ".assist", "handovers", "archive");
|
|
9731
9776
|
}
|
|
9732
9777
|
|
|
9733
9778
|
// src/commands/handover/archive.ts
|
|
@@ -9737,15 +9782,15 @@ function buildArchiveFilename(timestamp, suffix) {
|
|
|
9737
9782
|
return `${base}.md`;
|
|
9738
9783
|
}
|
|
9739
9784
|
function resolveCollisionPath(archiveDir, timestamp, suffix) {
|
|
9740
|
-
const initial =
|
|
9741
|
-
if (!
|
|
9785
|
+
const initial = join31(archiveDir, buildArchiveFilename(timestamp, suffix));
|
|
9786
|
+
if (!existsSync31(initial)) return initial;
|
|
9742
9787
|
for (let i = 1; i <= MAX_COLLISION_SUFFIX; i++) {
|
|
9743
9788
|
const collisionSuffix = suffix ? `${suffix}-${i}` : `${i}`;
|
|
9744
|
-
const candidate =
|
|
9789
|
+
const candidate = join31(
|
|
9745
9790
|
archiveDir,
|
|
9746
9791
|
buildArchiveFilename(timestamp, collisionSuffix)
|
|
9747
9792
|
);
|
|
9748
|
-
if (!
|
|
9793
|
+
if (!existsSync31(candidate)) return candidate;
|
|
9749
9794
|
}
|
|
9750
9795
|
throw new Error(
|
|
9751
9796
|
`Exhausted collision suffixes (1-${MAX_COLLISION_SUFFIX}) for ${timestamp}`
|
|
@@ -9754,9 +9799,9 @@ function resolveCollisionPath(archiveDir, timestamp, suffix) {
|
|
|
9754
9799
|
function archive(options2 = {}) {
|
|
9755
9800
|
const cwd = options2.cwd ?? process.cwd();
|
|
9756
9801
|
const handoverPath = getHandoverPath(cwd);
|
|
9757
|
-
if (!
|
|
9802
|
+
if (!existsSync31(handoverPath)) return void 0;
|
|
9758
9803
|
const archiveDir = getHandoverArchiveDir(cwd);
|
|
9759
|
-
|
|
9804
|
+
mkdirSync10(archiveDir, { recursive: true });
|
|
9760
9805
|
const timestamp = formatArchiveTimestamp(options2.now);
|
|
9761
9806
|
const destination = resolveCollisionPath(
|
|
9762
9807
|
archiveDir,
|
|
@@ -9768,7 +9813,7 @@ function archive(options2 = {}) {
|
|
|
9768
9813
|
}
|
|
9769
9814
|
|
|
9770
9815
|
// src/commands/handover/load.ts
|
|
9771
|
-
import { existsSync as
|
|
9816
|
+
import { existsSync as existsSync32, readFileSync as readFileSync26 } from "fs";
|
|
9772
9817
|
|
|
9773
9818
|
// src/commands/handover/parseLoadInput.ts
|
|
9774
9819
|
async function parseLoadInput(stdin) {
|
|
@@ -9807,16 +9852,16 @@ function parseUserLine(line) {
|
|
|
9807
9852
|
if (entry.type !== "user") return void 0;
|
|
9808
9853
|
const msg = entry.message;
|
|
9809
9854
|
const c = msg?.content;
|
|
9810
|
-
let
|
|
9855
|
+
let text3;
|
|
9811
9856
|
if (typeof c === "string") {
|
|
9812
|
-
|
|
9857
|
+
text3 = c;
|
|
9813
9858
|
} else if (Array.isArray(c)) {
|
|
9814
9859
|
const collected = c.filter((b) => b.type === "text").map((b) => b.text ?? "").join("\n");
|
|
9815
|
-
|
|
9860
|
+
text3 = collected || void 0;
|
|
9816
9861
|
}
|
|
9817
|
-
if (!
|
|
9862
|
+
if (!text3) return void 0;
|
|
9818
9863
|
return {
|
|
9819
|
-
text:
|
|
9864
|
+
text: text3,
|
|
9820
9865
|
entrypoint: typeof entry.entrypoint === "string" ? entry.entrypoint : void 0
|
|
9821
9866
|
};
|
|
9822
9867
|
}
|
|
@@ -9867,12 +9912,12 @@ ${payload}`;
|
|
|
9867
9912
|
return "";
|
|
9868
9913
|
}
|
|
9869
9914
|
}
|
|
9870
|
-
function stripPreludes(
|
|
9871
|
-
return
|
|
9915
|
+
function stripPreludes(text3) {
|
|
9916
|
+
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();
|
|
9872
9917
|
}
|
|
9873
|
-
function capPayload(
|
|
9874
|
-
const buf = Buffer.from(
|
|
9875
|
-
if (buf.length <= maxBytes) return
|
|
9918
|
+
function capPayload(text3, maxBytes) {
|
|
9919
|
+
const buf = Buffer.from(text3, "utf8");
|
|
9920
|
+
if (buf.length <= maxBytes) return text3;
|
|
9876
9921
|
return buf.subarray(buf.length - maxBytes).toString("utf8");
|
|
9877
9922
|
}
|
|
9878
9923
|
function normaliseOutput(raw) {
|
|
@@ -9883,7 +9928,7 @@ function normaliseOutput(raw) {
|
|
|
9883
9928
|
// src/commands/handover/load.ts
|
|
9884
9929
|
function loadFromHandover(cwd) {
|
|
9885
9930
|
const handoverPath = getHandoverPath(cwd);
|
|
9886
|
-
if (!
|
|
9931
|
+
if (!existsSync32(handoverPath)) return void 0;
|
|
9887
9932
|
const content = readFileSync26(handoverPath, "utf-8");
|
|
9888
9933
|
archive({ cwd });
|
|
9889
9934
|
return {
|
|
@@ -9941,9 +9986,9 @@ import chalk109 from "chalk";
|
|
|
9941
9986
|
|
|
9942
9987
|
// src/commands/jira/adfToText.ts
|
|
9943
9988
|
function renderInline(node) {
|
|
9944
|
-
const
|
|
9945
|
-
if (node.marks?.some((m) => m.type === "code")) return `\`${
|
|
9946
|
-
return
|
|
9989
|
+
const text3 = node.text ?? "";
|
|
9990
|
+
if (node.marks?.some((m) => m.type === "code")) return `\`${text3}\``;
|
|
9991
|
+
return text3;
|
|
9947
9992
|
}
|
|
9948
9993
|
function renderChildren(node, indent2) {
|
|
9949
9994
|
return renderNodes(node.content ?? [], indent2);
|
|
@@ -9985,8 +10030,8 @@ function isListNode(node) {
|
|
|
9985
10030
|
function renderListChild(child, indent2, pad, marker, isFirst) {
|
|
9986
10031
|
if (isListNode(child)) return renderNodes([child], indent2 + 1);
|
|
9987
10032
|
if (child.type !== "paragraph") return renderNode(child, indent2);
|
|
9988
|
-
const
|
|
9989
|
-
return isFirst ? `${pad}${marker} ${
|
|
10033
|
+
const text3 = renderChildren(child, indent2);
|
|
10034
|
+
return isFirst ? `${pad}${marker} ${text3}` : `${pad} ${text3}`;
|
|
9990
10035
|
}
|
|
9991
10036
|
function renderListItem(node, indent2, marker) {
|
|
9992
10037
|
const pad = " ".repeat(indent2);
|
|
@@ -10051,20 +10096,20 @@ function acceptanceCriteria(issueKey) {
|
|
|
10051
10096
|
import { execSync as execSync30 } from "child_process";
|
|
10052
10097
|
|
|
10053
10098
|
// src/shared/loadJson.ts
|
|
10054
|
-
import { existsSync as
|
|
10055
|
-
import { homedir as
|
|
10056
|
-
import { join as
|
|
10099
|
+
import { existsSync as existsSync33, mkdirSync as mkdirSync11, readFileSync as readFileSync27, writeFileSync as writeFileSync21 } from "fs";
|
|
10100
|
+
import { homedir as homedir11 } from "os";
|
|
10101
|
+
import { join as join32 } from "path";
|
|
10057
10102
|
function getStoreDir() {
|
|
10058
|
-
return
|
|
10103
|
+
return join32(homedir11(), ".assist");
|
|
10059
10104
|
}
|
|
10060
10105
|
function getStorePath(filename) {
|
|
10061
|
-
return
|
|
10106
|
+
return join32(getStoreDir(), filename);
|
|
10062
10107
|
}
|
|
10063
10108
|
function loadJson(filename) {
|
|
10064
|
-
const
|
|
10065
|
-
if (
|
|
10109
|
+
const path54 = getStorePath(filename);
|
|
10110
|
+
if (existsSync33(path54)) {
|
|
10066
10111
|
try {
|
|
10067
|
-
return JSON.parse(readFileSync27(
|
|
10112
|
+
return JSON.parse(readFileSync27(path54, "utf-8"));
|
|
10068
10113
|
} catch {
|
|
10069
10114
|
return {};
|
|
10070
10115
|
}
|
|
@@ -10073,10 +10118,10 @@ function loadJson(filename) {
|
|
|
10073
10118
|
}
|
|
10074
10119
|
function saveJson(filename, data) {
|
|
10075
10120
|
const dir = getStoreDir();
|
|
10076
|
-
if (!
|
|
10077
|
-
|
|
10121
|
+
if (!existsSync33(dir)) {
|
|
10122
|
+
mkdirSync11(dir, { recursive: true });
|
|
10078
10123
|
}
|
|
10079
|
-
|
|
10124
|
+
writeFileSync21(getStorePath(filename), JSON.stringify(data, null, 2));
|
|
10080
10125
|
}
|
|
10081
10126
|
|
|
10082
10127
|
// src/shared/promptInput.ts
|
|
@@ -10211,12 +10256,12 @@ function registerList(program2) {
|
|
|
10211
10256
|
}
|
|
10212
10257
|
|
|
10213
10258
|
// src/commands/mermaid/index.ts
|
|
10214
|
-
import { mkdirSync as
|
|
10259
|
+
import { mkdirSync as mkdirSync12, readdirSync as readdirSync5 } from "fs";
|
|
10215
10260
|
import { resolve as resolve10 } from "path";
|
|
10216
10261
|
import chalk114 from "chalk";
|
|
10217
10262
|
|
|
10218
10263
|
// src/commands/mermaid/exportFile.ts
|
|
10219
|
-
import { readFileSync as readFileSync28, writeFileSync as
|
|
10264
|
+
import { readFileSync as readFileSync28, writeFileSync as writeFileSync22 } from "fs";
|
|
10220
10265
|
import { basename as basename5, extname, resolve as resolve9 } from "path";
|
|
10221
10266
|
import chalk113 from "chalk";
|
|
10222
10267
|
|
|
@@ -10267,7 +10312,7 @@ async function exportFile(file, outDir, krokiUrl, onlyIndex) {
|
|
|
10267
10312
|
if (onlyIndex !== void 0 && idx !== onlyIndex) continue;
|
|
10268
10313
|
const outPath = resolve9(outDir, `${stem}-${idx}.svg`);
|
|
10269
10314
|
const svg = await renderBlock(krokiUrl, source);
|
|
10270
|
-
|
|
10315
|
+
writeFileSync22(outPath, svg, "utf8");
|
|
10271
10316
|
console.log(chalk113.green(` \u2192 ${outPath}`));
|
|
10272
10317
|
}
|
|
10273
10318
|
}
|
|
@@ -10280,7 +10325,7 @@ function extractMermaidBlocks(markdown) {
|
|
|
10280
10325
|
async function mermaidExport(file, options2 = {}) {
|
|
10281
10326
|
const { mermaid } = loadConfig();
|
|
10282
10327
|
const outDir = resolve10(process.cwd(), options2.out ?? ".");
|
|
10283
|
-
|
|
10328
|
+
mkdirSync12(outDir, { recursive: true });
|
|
10284
10329
|
if (options2.index !== void 0) {
|
|
10285
10330
|
if (!Number.isInteger(options2.index) || options2.index < 1) {
|
|
10286
10331
|
console.error(
|
|
@@ -10397,9 +10442,9 @@ function excerpt(xml, ...tags) {
|
|
|
10397
10442
|
for (const tag of tags) {
|
|
10398
10443
|
const raw = extractText(xml, tag);
|
|
10399
10444
|
if (!raw) continue;
|
|
10400
|
-
const
|
|
10401
|
-
if (
|
|
10402
|
-
return `${
|
|
10445
|
+
const text3 = stripHtml(raw);
|
|
10446
|
+
if (text3.length <= MAX_EXCERPT) return text3;
|
|
10447
|
+
return `${text3.slice(0, MAX_EXCERPT)}\u2026`;
|
|
10403
10448
|
}
|
|
10404
10449
|
return "";
|
|
10405
10450
|
}
|
|
@@ -10700,15 +10745,15 @@ function postComment(vars) {
|
|
|
10700
10745
|
const stdout = startLine === void 0 ? runGhGraphql(MUTATION_SINGLE, base) : runGhGraphql(MUTATION_MULTI, { ...base, startLine });
|
|
10701
10746
|
assertThreadCreated(stdout);
|
|
10702
10747
|
}
|
|
10703
|
-
function comment2(
|
|
10748
|
+
function comment2(path54, line, body, startLine) {
|
|
10704
10749
|
validateBody(body);
|
|
10705
10750
|
validateLine(line);
|
|
10706
10751
|
if (startLine !== void 0) validateLine(startLine);
|
|
10707
10752
|
try {
|
|
10708
10753
|
const prId = getCurrentPrNodeId();
|
|
10709
|
-
postComment({ prId, body, path:
|
|
10754
|
+
postComment({ prId, body, path: path54, line, startLine });
|
|
10710
10755
|
const range = startLine !== void 0 ? `${startLine}-${line}` : `${line}`;
|
|
10711
|
-
console.log(`Added review comment on ${
|
|
10756
|
+
console.log(`Added review comment on ${path54}:${range}`);
|
|
10712
10757
|
} catch (error) {
|
|
10713
10758
|
if (isGhNotInstalled(error)) {
|
|
10714
10759
|
console.error("Error: GitHub CLI (gh) is not installed.");
|
|
@@ -10786,20 +10831,20 @@ import { execSync as execSync34 } from "child_process";
|
|
|
10786
10831
|
|
|
10787
10832
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
10788
10833
|
import { execSync as execSync33 } from "child_process";
|
|
10789
|
-
import { unlinkSync as
|
|
10834
|
+
import { unlinkSync as unlinkSync10, writeFileSync as writeFileSync23 } from "fs";
|
|
10790
10835
|
import { tmpdir as tmpdir5 } from "os";
|
|
10791
|
-
import { join as
|
|
10836
|
+
import { join as join34 } from "path";
|
|
10792
10837
|
|
|
10793
10838
|
// src/commands/prs/loadCommentsCache.ts
|
|
10794
|
-
import { existsSync as
|
|
10795
|
-
import { join as
|
|
10839
|
+
import { existsSync as existsSync34, readFileSync as readFileSync29, unlinkSync as unlinkSync9 } from "fs";
|
|
10840
|
+
import { join as join33 } from "path";
|
|
10796
10841
|
import { parse as parse2 } from "yaml";
|
|
10797
10842
|
function getCachePath(prNumber) {
|
|
10798
|
-
return
|
|
10843
|
+
return join33(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`);
|
|
10799
10844
|
}
|
|
10800
10845
|
function loadCommentsCache(prNumber) {
|
|
10801
10846
|
const cachePath = getCachePath(prNumber);
|
|
10802
|
-
if (!
|
|
10847
|
+
if (!existsSync34(cachePath)) {
|
|
10803
10848
|
return null;
|
|
10804
10849
|
}
|
|
10805
10850
|
const content = readFileSync29(cachePath, "utf-8");
|
|
@@ -10807,8 +10852,8 @@ function loadCommentsCache(prNumber) {
|
|
|
10807
10852
|
}
|
|
10808
10853
|
function deleteCommentsCache(prNumber) {
|
|
10809
10854
|
const cachePath = getCachePath(prNumber);
|
|
10810
|
-
if (
|
|
10811
|
-
|
|
10855
|
+
if (existsSync34(cachePath)) {
|
|
10856
|
+
unlinkSync9(cachePath);
|
|
10812
10857
|
console.log("No more unresolved line comments. Cache dropped.");
|
|
10813
10858
|
}
|
|
10814
10859
|
}
|
|
@@ -10822,15 +10867,15 @@ function replyToComment(org, repo, prNumber, commentId, message) {
|
|
|
10822
10867
|
}
|
|
10823
10868
|
function resolveThread(threadId) {
|
|
10824
10869
|
const mutation = `mutation($threadId: ID!) { resolveReviewThread(input: {threadId: $threadId}) { thread { isResolved } } }`;
|
|
10825
|
-
const queryFile =
|
|
10826
|
-
|
|
10870
|
+
const queryFile = join34(tmpdir5(), `gh-mutation-${Date.now()}.graphql`);
|
|
10871
|
+
writeFileSync23(queryFile, mutation);
|
|
10827
10872
|
try {
|
|
10828
10873
|
execSync33(
|
|
10829
10874
|
`gh api graphql -F query=@${queryFile} -f threadId="${threadId}"`,
|
|
10830
10875
|
{ stdio: ["inherit", "pipe", "inherit"] }
|
|
10831
10876
|
);
|
|
10832
10877
|
} finally {
|
|
10833
|
-
|
|
10878
|
+
unlinkSync10(queryFile);
|
|
10834
10879
|
}
|
|
10835
10880
|
}
|
|
10836
10881
|
function requireCache(prNumber) {
|
|
@@ -10904,19 +10949,19 @@ function fixed(commentId, sha) {
|
|
|
10904
10949
|
}
|
|
10905
10950
|
|
|
10906
10951
|
// src/commands/prs/listComments/index.ts
|
|
10907
|
-
import { existsSync as
|
|
10908
|
-
import { join as
|
|
10952
|
+
import { existsSync as existsSync35, mkdirSync as mkdirSync13, writeFileSync as writeFileSync25 } from "fs";
|
|
10953
|
+
import { join as join36 } from "path";
|
|
10909
10954
|
import { stringify } from "yaml";
|
|
10910
10955
|
|
|
10911
10956
|
// src/commands/prs/fetchThreadIds.ts
|
|
10912
10957
|
import { execSync as execSync35 } from "child_process";
|
|
10913
|
-
import { unlinkSync as
|
|
10958
|
+
import { unlinkSync as unlinkSync11, writeFileSync as writeFileSync24 } from "fs";
|
|
10914
10959
|
import { tmpdir as tmpdir6 } from "os";
|
|
10915
|
-
import { join as
|
|
10960
|
+
import { join as join35 } from "path";
|
|
10916
10961
|
var THREAD_QUERY = `query($owner: String!, $repo: String!, $prNumber: Int!) { repository(owner: $owner, name: $repo) { pullRequest(number: $prNumber) { reviewThreads(first: 100) { nodes { id isResolved comments(first: 100) { nodes { databaseId } } } } } } }`;
|
|
10917
10962
|
function fetchThreadIds(org, repo, prNumber) {
|
|
10918
|
-
const queryFile =
|
|
10919
|
-
|
|
10963
|
+
const queryFile = join35(tmpdir6(), `gh-query-${Date.now()}.graphql`);
|
|
10964
|
+
writeFileSync24(queryFile, THREAD_QUERY);
|
|
10920
10965
|
try {
|
|
10921
10966
|
const result = execSync35(
|
|
10922
10967
|
`gh api graphql -F query=@${queryFile} -F owner="${org}" -F repo="${repo}" -F prNumber=${prNumber}`,
|
|
@@ -10935,7 +10980,7 @@ function fetchThreadIds(org, repo, prNumber) {
|
|
|
10935
10980
|
}
|
|
10936
10981
|
return { threadMap, resolvedThreadIds };
|
|
10937
10982
|
} finally {
|
|
10938
|
-
|
|
10983
|
+
unlinkSync11(queryFile);
|
|
10939
10984
|
}
|
|
10940
10985
|
}
|
|
10941
10986
|
|
|
@@ -11029,17 +11074,17 @@ function printComments2(result) {
|
|
|
11029
11074
|
|
|
11030
11075
|
// src/commands/prs/listComments/index.ts
|
|
11031
11076
|
function writeCommentsCache(prNumber, comments3) {
|
|
11032
|
-
const assistDir =
|
|
11033
|
-
if (!
|
|
11034
|
-
|
|
11077
|
+
const assistDir = join36(process.cwd(), ".assist");
|
|
11078
|
+
if (!existsSync35(assistDir)) {
|
|
11079
|
+
mkdirSync13(assistDir, { recursive: true });
|
|
11035
11080
|
}
|
|
11036
11081
|
const cacheData = {
|
|
11037
11082
|
prNumber,
|
|
11038
11083
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
11039
11084
|
comments: comments3
|
|
11040
11085
|
};
|
|
11041
|
-
const cachePath =
|
|
11042
|
-
|
|
11086
|
+
const cachePath = join36(assistDir, `pr-${prNumber}-comments.yaml`);
|
|
11087
|
+
writeFileSync25(cachePath, stringify(cacheData));
|
|
11043
11088
|
}
|
|
11044
11089
|
function handleKnownErrors(error) {
|
|
11045
11090
|
if (isGhNotInstalled(error)) {
|
|
@@ -11071,7 +11116,7 @@ async function listComments() {
|
|
|
11071
11116
|
];
|
|
11072
11117
|
updateCache(prNumber, allComments);
|
|
11073
11118
|
const hasLineComments = allComments.some((c) => c.type === "line");
|
|
11074
|
-
const cachePath = hasLineComments ?
|
|
11119
|
+
const cachePath = hasLineComments ? join36(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`) : null;
|
|
11075
11120
|
return { comments: allComments, cachePath };
|
|
11076
11121
|
} catch (error) {
|
|
11077
11122
|
const handled = handleKnownErrors(error);
|
|
@@ -11288,8 +11333,8 @@ function registerPrs(program2) {
|
|
|
11288
11333
|
prsCommand.command("wontfix <comment-id> <reason>").description("Reply with reason and resolve thread").action((commentId, reason) => {
|
|
11289
11334
|
wontfix(Number.parseInt(commentId, 10), reason);
|
|
11290
11335
|
});
|
|
11291
|
-
prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((
|
|
11292
|
-
comment2(
|
|
11336
|
+
prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((path54, line, body) => {
|
|
11337
|
+
comment2(path54, Number.parseInt(line, 10), body);
|
|
11293
11338
|
});
|
|
11294
11339
|
}
|
|
11295
11340
|
|
|
@@ -11541,10 +11586,10 @@ function resolveOpSecret(reference) {
|
|
|
11541
11586
|
}
|
|
11542
11587
|
|
|
11543
11588
|
// src/commands/ravendb/ravenFetch.ts
|
|
11544
|
-
async function ravenFetch(connection,
|
|
11589
|
+
async function ravenFetch(connection, path54) {
|
|
11545
11590
|
const apiKey = resolveOpSecret(connection.apiKeyRef);
|
|
11546
11591
|
let accessToken = await getAccessToken(apiKey);
|
|
11547
|
-
const url = `${connection.url}${
|
|
11592
|
+
const url = `${connection.url}${path54}`;
|
|
11548
11593
|
const headers = {
|
|
11549
11594
|
Authorization: `Bearer ${accessToken}`,
|
|
11550
11595
|
"Content-Type": "application/json"
|
|
@@ -11634,16 +11679,16 @@ import chalk130 from "chalk";
|
|
|
11634
11679
|
// src/commands/ravendb/buildQueryPath.ts
|
|
11635
11680
|
function buildQueryPath(opts) {
|
|
11636
11681
|
const db = encodeURIComponent(opts.db);
|
|
11637
|
-
let
|
|
11682
|
+
let path54;
|
|
11638
11683
|
if (opts.collection) {
|
|
11639
|
-
|
|
11684
|
+
path54 = `/databases/${db}/indexes/dynamic/${encodeURIComponent(opts.collection)}?start=${opts.start}&pageSize=${opts.pageSize}&sort=${encodeURIComponent(opts.sort)}`;
|
|
11640
11685
|
} else {
|
|
11641
|
-
|
|
11686
|
+
path54 = `/databases/${db}/queries?start=${opts.start}&pageSize=${opts.pageSize}`;
|
|
11642
11687
|
}
|
|
11643
11688
|
if (opts.query) {
|
|
11644
|
-
|
|
11689
|
+
path54 += `&query=${encodeURIComponent(opts.query)}`;
|
|
11645
11690
|
}
|
|
11646
|
-
return
|
|
11691
|
+
return path54;
|
|
11647
11692
|
}
|
|
11648
11693
|
|
|
11649
11694
|
// src/commands/ravendb/fetchAllPages.ts
|
|
@@ -11652,7 +11697,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
11652
11697
|
let start3 = 0;
|
|
11653
11698
|
while (true) {
|
|
11654
11699
|
const effectivePageSize = opts.limit !== void 0 ? Math.min(opts.pageSize, opts.limit - allResults.length) : opts.pageSize;
|
|
11655
|
-
const
|
|
11700
|
+
const path54 = buildQueryPath({
|
|
11656
11701
|
db: connection.database,
|
|
11657
11702
|
collection: opts.collection,
|
|
11658
11703
|
start: start3,
|
|
@@ -11660,7 +11705,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
11660
11705
|
sort: opts.sort,
|
|
11661
11706
|
query: opts.query
|
|
11662
11707
|
});
|
|
11663
|
-
const data = await ravenFetch(connection,
|
|
11708
|
+
const data = await ravenFetch(connection, path54);
|
|
11664
11709
|
const results = data.Results ?? [];
|
|
11665
11710
|
const totalResults = data.TotalResults ?? 0;
|
|
11666
11711
|
if (results.length === 0) break;
|
|
@@ -12307,9 +12352,9 @@ function resolveImports(target, dependencies, sourceFile, statements = []) {
|
|
|
12307
12352
|
function extractTexts(target, allFunctions, statements) {
|
|
12308
12353
|
const stmtTexts = statements.map((v) => v.getFullText().trim());
|
|
12309
12354
|
const fnTexts = allFunctions.map((fn) => {
|
|
12310
|
-
const
|
|
12311
|
-
if (fn === target && !
|
|
12312
|
-
return
|
|
12355
|
+
const text3 = fn.getFullText().trim();
|
|
12356
|
+
if (fn === target && !text3.startsWith("export ")) return `export ${text3}`;
|
|
12357
|
+
return text3;
|
|
12313
12358
|
});
|
|
12314
12359
|
return [...stmtTexts, ...fnTexts];
|
|
12315
12360
|
}
|
|
@@ -12878,8 +12923,8 @@ function findRootParent(file, importedBy, visited) {
|
|
|
12878
12923
|
function clusterFiles(graph) {
|
|
12879
12924
|
const clusters = /* @__PURE__ */ new Map();
|
|
12880
12925
|
for (const file of graph.files) {
|
|
12881
|
-
const
|
|
12882
|
-
if (
|
|
12926
|
+
const basename12 = path38.basename(file, path38.extname(file));
|
|
12927
|
+
if (basename12 === "index") continue;
|
|
12883
12928
|
const importers = graph.importedBy.get(file);
|
|
12884
12929
|
if (!importers || importers.size !== 1) continue;
|
|
12885
12930
|
const parent = [...importers][0];
|
|
@@ -13389,11 +13434,11 @@ ${annotateDiffWithLineNumbers(context.diff.trimEnd())}
|
|
|
13389
13434
|
}
|
|
13390
13435
|
|
|
13391
13436
|
// src/commands/review/buildReviewPaths.ts
|
|
13392
|
-
import { homedir as
|
|
13393
|
-
import { basename as basename6, join as
|
|
13437
|
+
import { homedir as homedir12 } from "os";
|
|
13438
|
+
import { basename as basename6, join as join37 } from "path";
|
|
13394
13439
|
function buildReviewPaths(repoRoot, key) {
|
|
13395
|
-
const reviewDir =
|
|
13396
|
-
|
|
13440
|
+
const reviewDir = join37(
|
|
13441
|
+
homedir12(),
|
|
13397
13442
|
".assist",
|
|
13398
13443
|
"reviews",
|
|
13399
13444
|
basename6(repoRoot),
|
|
@@ -13401,10 +13446,10 @@ function buildReviewPaths(repoRoot, key) {
|
|
|
13401
13446
|
);
|
|
13402
13447
|
return {
|
|
13403
13448
|
reviewDir,
|
|
13404
|
-
requestPath:
|
|
13405
|
-
claudePath:
|
|
13406
|
-
codexPath:
|
|
13407
|
-
synthesisPath:
|
|
13449
|
+
requestPath: join37(reviewDir, "request.md"),
|
|
13450
|
+
claudePath: join37(reviewDir, "claude.md"),
|
|
13451
|
+
codexPath: join37(reviewDir, "codex.md"),
|
|
13452
|
+
synthesisPath: join37(reviewDir, "synthesis.md")
|
|
13408
13453
|
};
|
|
13409
13454
|
}
|
|
13410
13455
|
|
|
@@ -13939,16 +13984,16 @@ async function handlePostSynthesis(synthesisPath, options2) {
|
|
|
13939
13984
|
}
|
|
13940
13985
|
|
|
13941
13986
|
// src/commands/review/prepareReviewDir.ts
|
|
13942
|
-
import { existsSync as
|
|
13987
|
+
import { existsSync as existsSync36, mkdirSync as mkdirSync14, unlinkSync as unlinkSync12, writeFileSync as writeFileSync26 } from "fs";
|
|
13943
13988
|
function clearReviewFiles(paths) {
|
|
13944
|
-
for (const
|
|
13945
|
-
if (
|
|
13989
|
+
for (const path54 of [paths.claudePath, paths.codexPath, paths.synthesisPath]) {
|
|
13990
|
+
if (existsSync36(path54)) unlinkSync12(path54);
|
|
13946
13991
|
}
|
|
13947
13992
|
}
|
|
13948
13993
|
function prepareReviewDir(paths, requestBody, force) {
|
|
13949
|
-
|
|
13994
|
+
mkdirSync14(paths.reviewDir, { recursive: true });
|
|
13950
13995
|
if (force) clearReviewFiles(paths);
|
|
13951
|
-
|
|
13996
|
+
writeFileSync26(paths.requestPath, requestBody);
|
|
13952
13997
|
}
|
|
13953
13998
|
|
|
13954
13999
|
// src/commands/review/runApplySession.ts
|
|
@@ -14077,9 +14122,9 @@ var MultiSpinner = class {
|
|
|
14077
14122
|
elapsedPrefix: prefix2
|
|
14078
14123
|
});
|
|
14079
14124
|
}
|
|
14080
|
-
failRemaining(
|
|
14125
|
+
failRemaining(text3) {
|
|
14081
14126
|
for (const entry of this.entries) {
|
|
14082
|
-
if (entry.state === "running") this.resolve(entry, "failed",
|
|
14127
|
+
if (entry.state === "running") this.resolve(entry, "failed", text3);
|
|
14083
14128
|
}
|
|
14084
14129
|
}
|
|
14085
14130
|
add(entry) {
|
|
@@ -14092,14 +14137,14 @@ var MultiSpinner = class {
|
|
|
14092
14137
|
set text(value) {
|
|
14093
14138
|
entry.text = value;
|
|
14094
14139
|
},
|
|
14095
|
-
succeed: (
|
|
14096
|
-
fail: (
|
|
14140
|
+
succeed: (text3) => this.resolve(entry, "succeeded", text3),
|
|
14141
|
+
fail: (text3) => this.resolve(entry, "failed", text3)
|
|
14097
14142
|
};
|
|
14098
14143
|
}
|
|
14099
|
-
resolve(entry, state,
|
|
14144
|
+
resolve(entry, state, text3) {
|
|
14100
14145
|
if (entry.state !== "running") return;
|
|
14101
14146
|
entry.state = state;
|
|
14102
|
-
if (
|
|
14147
|
+
if (text3 !== void 0) entry.text = text3;
|
|
14103
14148
|
entry.elapsedStart = void 0;
|
|
14104
14149
|
this.render();
|
|
14105
14150
|
this.maybeFinish();
|
|
@@ -14174,12 +14219,12 @@ function skippedCodexResult(outputPath) {
|
|
|
14174
14219
|
// src/commands/review/formatReviewerFailure.ts
|
|
14175
14220
|
var FAST_FAIL_MS = 1e3;
|
|
14176
14221
|
var STDOUT_TAIL_LINES = 20;
|
|
14177
|
-
function indent(
|
|
14178
|
-
return
|
|
14222
|
+
function indent(text3) {
|
|
14223
|
+
return text3.split(/\r?\n/).map((line) => ` ${line}`);
|
|
14179
14224
|
}
|
|
14180
|
-
function tailLines(
|
|
14181
|
-
const lines =
|
|
14182
|
-
return lines.length <= maxLines ?
|
|
14225
|
+
function tailLines(text3, maxLines) {
|
|
14226
|
+
const lines = text3.split(/\r?\n/);
|
|
14227
|
+
return lines.length <= maxLines ? text3 : lines.slice(-maxLines).join("\n");
|
|
14183
14228
|
}
|
|
14184
14229
|
function isFastFail(input) {
|
|
14185
14230
|
return input.exitCode !== 0 && input.elapsedMs !== void 0 && input.elapsedMs < FAST_FAIL_MS;
|
|
@@ -14227,7 +14272,7 @@ function printReviewerFailures(results) {
|
|
|
14227
14272
|
}
|
|
14228
14273
|
|
|
14229
14274
|
// src/commands/review/runAndSynthesise.ts
|
|
14230
|
-
import { existsSync as
|
|
14275
|
+
import { existsSync as existsSync38, unlinkSync as unlinkSync14 } from "fs";
|
|
14231
14276
|
|
|
14232
14277
|
// src/commands/review/buildReviewerStdin.ts
|
|
14233
14278
|
var REVIEW_PROMPT = `You are acting as a reviewer for a proposed code change made by another engineer. The full review request \u2014 branch, base, changed files, and unified diff \u2014 is in request.md in the current working directory.
|
|
@@ -14291,7 +14336,7 @@ The review request is at: ${requestPath}
|
|
|
14291
14336
|
}
|
|
14292
14337
|
|
|
14293
14338
|
// src/commands/review/runClaudeReviewer.ts
|
|
14294
|
-
import { writeFileSync as
|
|
14339
|
+
import { writeFileSync as writeFileSync27 } from "fs";
|
|
14295
14340
|
|
|
14296
14341
|
// src/commands/review/finaliseReviewerSpinner.ts
|
|
14297
14342
|
var SUMMARY_MAX_LEN = 80;
|
|
@@ -14627,7 +14672,7 @@ async function runClaudeReviewer(spec) {
|
|
|
14627
14672
|
}
|
|
14628
14673
|
});
|
|
14629
14674
|
if (result.exitCode === 0 && finalText)
|
|
14630
|
-
|
|
14675
|
+
writeFileSync27(spec.outputPath, finalText);
|
|
14631
14676
|
return finaliseReviewerRun({ ...spec, command }, spinner, result);
|
|
14632
14677
|
}
|
|
14633
14678
|
|
|
@@ -14645,7 +14690,7 @@ function resolveClaude(args) {
|
|
|
14645
14690
|
}
|
|
14646
14691
|
|
|
14647
14692
|
// src/commands/review/runCodexReviewer.ts
|
|
14648
|
-
import { existsSync as
|
|
14693
|
+
import { existsSync as existsSync37, unlinkSync as unlinkSync13 } from "fs";
|
|
14649
14694
|
|
|
14650
14695
|
// src/commands/review/parseCodexEvent.ts
|
|
14651
14696
|
function isItemStarted(value) {
|
|
@@ -14699,8 +14744,8 @@ async function runCodexReviewer(spec) {
|
|
|
14699
14744
|
reportReviewerToolUse(spec.name, event, spinner);
|
|
14700
14745
|
}
|
|
14701
14746
|
});
|
|
14702
|
-
if (result.exitCode !== 0 &&
|
|
14703
|
-
|
|
14747
|
+
if (result.exitCode !== 0 && existsSync37(spec.outputPath)) {
|
|
14748
|
+
unlinkSync13(spec.outputPath);
|
|
14704
14749
|
}
|
|
14705
14750
|
return finaliseReviewerRun({ ...spec, command }, spinner, result);
|
|
14706
14751
|
}
|
|
@@ -14847,8 +14892,8 @@ async function runAndSynthesise(args) {
|
|
|
14847
14892
|
console.error("Both reviewers failed; skipping synthesis.");
|
|
14848
14893
|
return { ok: false, failures };
|
|
14849
14894
|
}
|
|
14850
|
-
if (anyFresh &&
|
|
14851
|
-
|
|
14895
|
+
if (anyFresh && existsSync38(paths.synthesisPath)) {
|
|
14896
|
+
unlinkSync14(paths.synthesisPath);
|
|
14852
14897
|
}
|
|
14853
14898
|
const synthesisResult = await synthesise(paths, { multi });
|
|
14854
14899
|
if (synthesisResult.exitCode !== 0) failures.push(synthesisResult);
|
|
@@ -15077,8 +15122,8 @@ import chalk149 from "chalk";
|
|
|
15077
15122
|
|
|
15078
15123
|
// src/commands/seq/fetchSeq.ts
|
|
15079
15124
|
import chalk146 from "chalk";
|
|
15080
|
-
async function fetchSeq(conn,
|
|
15081
|
-
const url = `${conn.url}${
|
|
15125
|
+
async function fetchSeq(conn, path54, params) {
|
|
15126
|
+
const url = `${conn.url}${path54}?${params}`;
|
|
15082
15127
|
const response = await fetch(url, {
|
|
15083
15128
|
headers: {
|
|
15084
15129
|
Accept: "application/json",
|
|
@@ -15622,8 +15667,8 @@ function registerSql(program2) {
|
|
|
15622
15667
|
}
|
|
15623
15668
|
|
|
15624
15669
|
// src/commands/transcript/shared.ts
|
|
15625
|
-
import { existsSync as
|
|
15626
|
-
import { basename as basename7, join as
|
|
15670
|
+
import { existsSync as existsSync39, readdirSync as readdirSync6, statSync as statSync4 } from "fs";
|
|
15671
|
+
import { basename as basename7, join as join38, relative as relative2 } from "path";
|
|
15627
15672
|
import * as readline2 from "readline";
|
|
15628
15673
|
var DATE_PREFIX_REGEX = /^\d{4}-\d{2}-\d{2}/;
|
|
15629
15674
|
function getDatePrefix(daysOffset = 0) {
|
|
@@ -15638,10 +15683,10 @@ function isValidDatePrefix(filename) {
|
|
|
15638
15683
|
return DATE_PREFIX_REGEX.test(filename);
|
|
15639
15684
|
}
|
|
15640
15685
|
function collectFiles(dir, extension) {
|
|
15641
|
-
if (!
|
|
15686
|
+
if (!existsSync39(dir)) return [];
|
|
15642
15687
|
const results = [];
|
|
15643
15688
|
for (const entry of readdirSync6(dir)) {
|
|
15644
|
-
const fullPath =
|
|
15689
|
+
const fullPath = join38(dir, entry);
|
|
15645
15690
|
if (statSync4(fullPath).isDirectory()) {
|
|
15646
15691
|
results.push(...collectFiles(fullPath, extension));
|
|
15647
15692
|
} else if (entry.endsWith(extension)) {
|
|
@@ -15735,14 +15780,14 @@ async function configure() {
|
|
|
15735
15780
|
}
|
|
15736
15781
|
|
|
15737
15782
|
// src/commands/transcript/format/index.ts
|
|
15738
|
-
import { existsSync as
|
|
15783
|
+
import { existsSync as existsSync41 } from "fs";
|
|
15739
15784
|
|
|
15740
15785
|
// src/commands/transcript/format/fixInvalidDatePrefixes/index.ts
|
|
15741
|
-
import { dirname as dirname20, join as
|
|
15786
|
+
import { dirname as dirname20, join as join40 } from "path";
|
|
15742
15787
|
|
|
15743
15788
|
// src/commands/transcript/format/fixInvalidDatePrefixes/promptForDateFix.ts
|
|
15744
15789
|
import { renameSync as renameSync3 } from "fs";
|
|
15745
|
-
import { join as
|
|
15790
|
+
import { join as join39 } from "path";
|
|
15746
15791
|
async function resolveDate(rl, choice) {
|
|
15747
15792
|
if (choice === "1") return getDatePrefix(0);
|
|
15748
15793
|
if (choice === "2") return getDatePrefix(-1);
|
|
@@ -15757,7 +15802,7 @@ async function resolveDate(rl, choice) {
|
|
|
15757
15802
|
}
|
|
15758
15803
|
function renameWithPrefix(vttDir, vttFile, prefix2) {
|
|
15759
15804
|
const newFilename = `${prefix2}.${vttFile}`;
|
|
15760
|
-
renameSync3(
|
|
15805
|
+
renameSync3(join39(vttDir, vttFile), join39(vttDir, newFilename));
|
|
15761
15806
|
console.log(`Renamed to: ${newFilename}`);
|
|
15762
15807
|
return newFilename;
|
|
15763
15808
|
}
|
|
@@ -15791,12 +15836,12 @@ async function fixInvalidDatePrefixes(vttFiles) {
|
|
|
15791
15836
|
const vttFileDir = dirname20(vttFile.absolutePath);
|
|
15792
15837
|
const newFilename = await promptForDateFix(vttFile.filename, vttFileDir);
|
|
15793
15838
|
if (newFilename) {
|
|
15794
|
-
const newRelativePath =
|
|
15839
|
+
const newRelativePath = join40(
|
|
15795
15840
|
dirname20(vttFile.relativePath),
|
|
15796
15841
|
newFilename
|
|
15797
15842
|
);
|
|
15798
15843
|
vttFiles[i] = {
|
|
15799
|
-
absolutePath:
|
|
15844
|
+
absolutePath: join40(vttFileDir, newFilename),
|
|
15800
15845
|
relativePath: newRelativePath,
|
|
15801
15846
|
filename: newFilename
|
|
15802
15847
|
};
|
|
@@ -15809,12 +15854,12 @@ async function fixInvalidDatePrefixes(vttFiles) {
|
|
|
15809
15854
|
}
|
|
15810
15855
|
|
|
15811
15856
|
// src/commands/transcript/format/processVttFile/index.ts
|
|
15812
|
-
import { existsSync as
|
|
15813
|
-
import { basename as basename8, dirname as dirname21, join as
|
|
15857
|
+
import { existsSync as existsSync40, mkdirSync as mkdirSync15, readFileSync as readFileSync32, writeFileSync as writeFileSync28 } from "fs";
|
|
15858
|
+
import { basename as basename8, dirname as dirname21, join as join41 } from "path";
|
|
15814
15859
|
|
|
15815
15860
|
// src/commands/transcript/cleanText.ts
|
|
15816
|
-
function cleanText(
|
|
15817
|
-
const words =
|
|
15861
|
+
function cleanText(text3) {
|
|
15862
|
+
const words = text3.split(/\s+/);
|
|
15818
15863
|
const cleaned = [];
|
|
15819
15864
|
for (let i = 0; i < words.length; i++) {
|
|
15820
15865
|
let isRepeat = false;
|
|
@@ -15834,8 +15879,8 @@ function cleanText(text2) {
|
|
|
15834
15879
|
}
|
|
15835
15880
|
|
|
15836
15881
|
// src/commands/transcript/format/processVttFile/parseVtt/deduplicateCues/removeSubstringDuplicates.ts
|
|
15837
|
-
function normalizeText(
|
|
15838
|
-
return
|
|
15882
|
+
function normalizeText(text3) {
|
|
15883
|
+
return text3.toLowerCase().trim();
|
|
15839
15884
|
}
|
|
15840
15885
|
function checkSubstringRelation(textI, textJ) {
|
|
15841
15886
|
if (textI.includes(textJ) && textI.length > textJ.length)
|
|
@@ -15964,13 +16009,13 @@ function parseTimestampLine(line) {
|
|
|
15964
16009
|
return { startMs: parseTimestamp(startStr), endMs: parseTimestamp(endStr) };
|
|
15965
16010
|
}
|
|
15966
16011
|
function buildCue(startMs, endMs, fullText) {
|
|
15967
|
-
const { speaker, text:
|
|
15968
|
-
return
|
|
16012
|
+
const { speaker, text: text3 } = extractSpeaker(fullText);
|
|
16013
|
+
return text3 ? { startMs, endMs, speaker, text: text3 } : null;
|
|
15969
16014
|
}
|
|
15970
16015
|
function parseCueLine(lines, i) {
|
|
15971
16016
|
const { startMs, endMs } = parseTimestampLine(lines[i]);
|
|
15972
|
-
const { text:
|
|
15973
|
-
return { cue: buildCue(startMs, endMs,
|
|
16017
|
+
const { text: text3, nextIndex } = collectTextLines(lines, i + 1);
|
|
16018
|
+
return { cue: buildCue(startMs, endMs, text3), nextIndex };
|
|
15974
16019
|
}
|
|
15975
16020
|
function isCueSeparator(line) {
|
|
15976
16021
|
return line.trim().includes("-->");
|
|
@@ -16020,22 +16065,22 @@ function toMdFilename(vttFilename) {
|
|
|
16020
16065
|
return `${basename8(vttFilename, ".vtt").replace(/\s*Transcription\s*/g, " ").trim()}.md`;
|
|
16021
16066
|
}
|
|
16022
16067
|
function resolveOutputDir(relativeDir, transcriptsDir) {
|
|
16023
|
-
return relativeDir === "." ? transcriptsDir :
|
|
16068
|
+
return relativeDir === "." ? transcriptsDir : join41(transcriptsDir, relativeDir);
|
|
16024
16069
|
}
|
|
16025
16070
|
function buildOutputPaths(vttFile, transcriptsDir) {
|
|
16026
16071
|
const mdFile = toMdFilename(vttFile.filename);
|
|
16027
16072
|
const relativeDir = dirname21(vttFile.relativePath);
|
|
16028
16073
|
const outputDir = resolveOutputDir(relativeDir, transcriptsDir);
|
|
16029
|
-
const outputPath =
|
|
16074
|
+
const outputPath = join41(outputDir, mdFile);
|
|
16030
16075
|
return { outputDir, outputPath, mdFile, relativeDir };
|
|
16031
16076
|
}
|
|
16032
16077
|
function logSkipped(relativeDir, mdFile) {
|
|
16033
|
-
console.log(`Skipping (already exists): ${
|
|
16078
|
+
console.log(`Skipping (already exists): ${join41(relativeDir, mdFile)}`);
|
|
16034
16079
|
return "skipped";
|
|
16035
16080
|
}
|
|
16036
16081
|
function ensureDirectory(dir, label2) {
|
|
16037
|
-
if (!
|
|
16038
|
-
|
|
16082
|
+
if (!existsSync40(dir)) {
|
|
16083
|
+
mkdirSync15(dir, { recursive: true });
|
|
16039
16084
|
console.log(`Created ${label2}: ${dir}`);
|
|
16040
16085
|
}
|
|
16041
16086
|
}
|
|
@@ -16060,7 +16105,7 @@ function readAndParseCues(inputPath) {
|
|
|
16060
16105
|
return processCues(readFileSync32(inputPath, "utf-8"));
|
|
16061
16106
|
}
|
|
16062
16107
|
function writeFormatted(outputPath, content) {
|
|
16063
|
-
|
|
16108
|
+
writeFileSync28(outputPath, content, "utf-8");
|
|
16064
16109
|
console.log(`Written: ${outputPath}`);
|
|
16065
16110
|
}
|
|
16066
16111
|
function convertVttToMarkdown(inputPath, outputPath) {
|
|
@@ -16070,7 +16115,7 @@ function convertVttToMarkdown(inputPath, outputPath) {
|
|
|
16070
16115
|
logReduction(cues.length, chatMessages.length);
|
|
16071
16116
|
}
|
|
16072
16117
|
function tryProcessVtt(vttFile, paths) {
|
|
16073
|
-
if (
|
|
16118
|
+
if (existsSync40(paths.outputPath))
|
|
16074
16119
|
return logSkipped(paths.relativeDir, paths.mdFile);
|
|
16075
16120
|
convertVttToMarkdown(vttFile.absolutePath, paths.outputPath);
|
|
16076
16121
|
return "processed";
|
|
@@ -16096,7 +16141,7 @@ function processAllFiles(vttFiles, transcriptsDir) {
|
|
|
16096
16141
|
logSummary(counts);
|
|
16097
16142
|
}
|
|
16098
16143
|
function requireVttDir(vttDir) {
|
|
16099
|
-
if (!
|
|
16144
|
+
if (!existsSync41(vttDir)) {
|
|
16100
16145
|
console.error(`VTT directory not found: ${vttDir}`);
|
|
16101
16146
|
process.exit(1);
|
|
16102
16147
|
}
|
|
@@ -16128,18 +16173,18 @@ async function format() {
|
|
|
16128
16173
|
}
|
|
16129
16174
|
|
|
16130
16175
|
// src/commands/transcript/summarise/index.ts
|
|
16131
|
-
import { existsSync as
|
|
16132
|
-
import { basename as basename9, dirname as dirname23, join as
|
|
16176
|
+
import { existsSync as existsSync43 } from "fs";
|
|
16177
|
+
import { basename as basename9, dirname as dirname23, join as join43, relative as relative3 } from "path";
|
|
16133
16178
|
|
|
16134
16179
|
// src/commands/transcript/summarise/processStagedFile/index.ts
|
|
16135
16180
|
import {
|
|
16136
|
-
existsSync as
|
|
16137
|
-
mkdirSync as
|
|
16181
|
+
existsSync as existsSync42,
|
|
16182
|
+
mkdirSync as mkdirSync16,
|
|
16138
16183
|
readFileSync as readFileSync33,
|
|
16139
16184
|
renameSync as renameSync4,
|
|
16140
16185
|
rmSync as rmSync2
|
|
16141
16186
|
} from "fs";
|
|
16142
|
-
import { dirname as dirname22, join as
|
|
16187
|
+
import { dirname as dirname22, join as join42 } from "path";
|
|
16143
16188
|
|
|
16144
16189
|
// src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
|
|
16145
16190
|
import chalk156 from "chalk";
|
|
@@ -16168,9 +16213,9 @@ function validateStagedContent(filename, content) {
|
|
|
16168
16213
|
}
|
|
16169
16214
|
|
|
16170
16215
|
// src/commands/transcript/summarise/processStagedFile/index.ts
|
|
16171
|
-
var STAGING_DIR =
|
|
16216
|
+
var STAGING_DIR = join42(process.cwd(), ".assist", "transcript");
|
|
16172
16217
|
function processStagedFile() {
|
|
16173
|
-
if (!
|
|
16218
|
+
if (!existsSync42(STAGING_DIR)) {
|
|
16174
16219
|
return false;
|
|
16175
16220
|
}
|
|
16176
16221
|
const stagedFiles = findMdFilesRecursive(STAGING_DIR);
|
|
@@ -16192,10 +16237,10 @@ function processStagedFile() {
|
|
|
16192
16237
|
);
|
|
16193
16238
|
process.exit(1);
|
|
16194
16239
|
}
|
|
16195
|
-
const destPath =
|
|
16240
|
+
const destPath = join42(summaryDir, matchingTranscript.relativePath);
|
|
16196
16241
|
const destDir = dirname22(destPath);
|
|
16197
|
-
if (!
|
|
16198
|
-
|
|
16242
|
+
if (!existsSync42(destDir)) {
|
|
16243
|
+
mkdirSync16(destDir, { recursive: true });
|
|
16199
16244
|
}
|
|
16200
16245
|
renameSync4(stagedFile.absolutePath, destPath);
|
|
16201
16246
|
const remaining = findMdFilesRecursive(STAGING_DIR);
|
|
@@ -16208,7 +16253,7 @@ function processStagedFile() {
|
|
|
16208
16253
|
// src/commands/transcript/summarise/index.ts
|
|
16209
16254
|
function buildRelativeKey(relativePath, baseName) {
|
|
16210
16255
|
const relDir = dirname23(relativePath);
|
|
16211
|
-
return relDir === "." ? baseName :
|
|
16256
|
+
return relDir === "." ? baseName : join43(relDir, baseName);
|
|
16212
16257
|
}
|
|
16213
16258
|
function buildSummaryIndex(summaryDir) {
|
|
16214
16259
|
const summaryFiles = findMdFilesRecursive(summaryDir);
|
|
@@ -16221,7 +16266,7 @@ function buildSummaryIndex(summaryDir) {
|
|
|
16221
16266
|
function summarise3() {
|
|
16222
16267
|
processStagedFile();
|
|
16223
16268
|
const { transcriptsDir, summaryDir } = getTranscriptConfig();
|
|
16224
|
-
if (!
|
|
16269
|
+
if (!existsSync43(transcriptsDir)) {
|
|
16225
16270
|
console.log("No transcripts directory found.");
|
|
16226
16271
|
return;
|
|
16227
16272
|
}
|
|
@@ -16242,8 +16287,8 @@ function summarise3() {
|
|
|
16242
16287
|
}
|
|
16243
16288
|
const next3 = missing[0];
|
|
16244
16289
|
const outputFilename = `${getTranscriptBaseName(next3.filename)}.md`;
|
|
16245
|
-
const outputPath =
|
|
16246
|
-
const summaryFileDir =
|
|
16290
|
+
const outputPath = join43(STAGING_DIR, outputFilename);
|
|
16291
|
+
const summaryFileDir = join43(summaryDir, dirname23(next3.relativePath));
|
|
16247
16292
|
const relativeTranscriptPath = encodeURI(
|
|
16248
16293
|
relative3(summaryFileDir, next3.absolutePath).replace(/\\/g, "/")
|
|
16249
16294
|
);
|
|
@@ -16293,45 +16338,45 @@ function registerVerify(program2) {
|
|
|
16293
16338
|
|
|
16294
16339
|
// src/commands/voice/devices.ts
|
|
16295
16340
|
import { spawnSync as spawnSync4 } from "child_process";
|
|
16296
|
-
import { join as
|
|
16341
|
+
import { join as join45 } from "path";
|
|
16297
16342
|
|
|
16298
16343
|
// src/commands/voice/shared.ts
|
|
16299
|
-
import { homedir as
|
|
16300
|
-
import { dirname as dirname24, join as
|
|
16344
|
+
import { homedir as homedir13 } from "os";
|
|
16345
|
+
import { dirname as dirname24, join as join44 } from "path";
|
|
16301
16346
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
16302
16347
|
var __dirname6 = dirname24(fileURLToPath6(import.meta.url));
|
|
16303
|
-
var VOICE_DIR =
|
|
16348
|
+
var VOICE_DIR = join44(homedir13(), ".assist", "voice");
|
|
16304
16349
|
var voicePaths = {
|
|
16305
16350
|
dir: VOICE_DIR,
|
|
16306
|
-
pid:
|
|
16307
|
-
log:
|
|
16308
|
-
venv:
|
|
16309
|
-
lock:
|
|
16351
|
+
pid: join44(VOICE_DIR, "voice.pid"),
|
|
16352
|
+
log: join44(VOICE_DIR, "voice.log"),
|
|
16353
|
+
venv: join44(VOICE_DIR, ".venv"),
|
|
16354
|
+
lock: join44(VOICE_DIR, "voice.lock")
|
|
16310
16355
|
};
|
|
16311
16356
|
function getPythonDir() {
|
|
16312
|
-
return
|
|
16357
|
+
return join44(__dirname6, "commands", "voice", "python");
|
|
16313
16358
|
}
|
|
16314
16359
|
function getVenvPython() {
|
|
16315
|
-
return process.platform === "win32" ?
|
|
16360
|
+
return process.platform === "win32" ? join44(voicePaths.venv, "Scripts", "python.exe") : join44(voicePaths.venv, "bin", "python");
|
|
16316
16361
|
}
|
|
16317
16362
|
function getLockDir() {
|
|
16318
16363
|
const config = loadConfig();
|
|
16319
16364
|
return config.voice?.lockDir ?? VOICE_DIR;
|
|
16320
16365
|
}
|
|
16321
16366
|
function getLockFile() {
|
|
16322
|
-
return
|
|
16367
|
+
return join44(getLockDir(), "voice.lock");
|
|
16323
16368
|
}
|
|
16324
16369
|
|
|
16325
16370
|
// src/commands/voice/devices.ts
|
|
16326
16371
|
function devices() {
|
|
16327
|
-
const script =
|
|
16372
|
+
const script = join45(getPythonDir(), "list_devices.py");
|
|
16328
16373
|
spawnSync4(getVenvPython(), [script], { stdio: "inherit" });
|
|
16329
16374
|
}
|
|
16330
16375
|
|
|
16331
16376
|
// src/commands/voice/logs.ts
|
|
16332
|
-
import { existsSync as
|
|
16377
|
+
import { existsSync as existsSync44, readFileSync as readFileSync34 } from "fs";
|
|
16333
16378
|
function logs(options2) {
|
|
16334
|
-
if (!
|
|
16379
|
+
if (!existsSync44(voicePaths.log)) {
|
|
16335
16380
|
console.log("No voice log file found");
|
|
16336
16381
|
return;
|
|
16337
16382
|
}
|
|
@@ -16358,13 +16403,13 @@ function logs(options2) {
|
|
|
16358
16403
|
|
|
16359
16404
|
// src/commands/voice/setup.ts
|
|
16360
16405
|
import { spawnSync as spawnSync5 } from "child_process";
|
|
16361
|
-
import { mkdirSync as
|
|
16362
|
-
import { join as
|
|
16406
|
+
import { mkdirSync as mkdirSync18 } from "fs";
|
|
16407
|
+
import { join as join47 } from "path";
|
|
16363
16408
|
|
|
16364
16409
|
// src/commands/voice/checkLockFile.ts
|
|
16365
16410
|
import { execSync as execSync46 } from "child_process";
|
|
16366
|
-
import { existsSync as
|
|
16367
|
-
import { join as
|
|
16411
|
+
import { existsSync as existsSync45, mkdirSync as mkdirSync17, readFileSync as readFileSync35, writeFileSync as writeFileSync29 } from "fs";
|
|
16412
|
+
import { join as join46 } from "path";
|
|
16368
16413
|
function isProcessAlive2(pid) {
|
|
16369
16414
|
try {
|
|
16370
16415
|
process.kill(pid, 0);
|
|
@@ -16375,7 +16420,7 @@ function isProcessAlive2(pid) {
|
|
|
16375
16420
|
}
|
|
16376
16421
|
function checkLockFile() {
|
|
16377
16422
|
const lockFile = getLockFile();
|
|
16378
|
-
if (!
|
|
16423
|
+
if (!existsSync45(lockFile)) return;
|
|
16379
16424
|
try {
|
|
16380
16425
|
const lock = JSON.parse(readFileSync35(lockFile, "utf-8"));
|
|
16381
16426
|
if (lock.pid && isProcessAlive2(lock.pid)) {
|
|
@@ -16388,7 +16433,7 @@ function checkLockFile() {
|
|
|
16388
16433
|
}
|
|
16389
16434
|
}
|
|
16390
16435
|
function bootstrapVenv() {
|
|
16391
|
-
if (
|
|
16436
|
+
if (existsSync45(getVenvPython())) return;
|
|
16392
16437
|
console.log("Setting up Python environment...");
|
|
16393
16438
|
const pythonDir = getPythonDir();
|
|
16394
16439
|
execSync46(
|
|
@@ -16401,8 +16446,8 @@ function bootstrapVenv() {
|
|
|
16401
16446
|
}
|
|
16402
16447
|
function writeLockFile(pid) {
|
|
16403
16448
|
const lockFile = getLockFile();
|
|
16404
|
-
|
|
16405
|
-
|
|
16449
|
+
mkdirSync17(join46(lockFile, ".."), { recursive: true });
|
|
16450
|
+
writeFileSync29(
|
|
16406
16451
|
lockFile,
|
|
16407
16452
|
JSON.stringify({
|
|
16408
16453
|
pid,
|
|
@@ -16414,10 +16459,10 @@ function writeLockFile(pid) {
|
|
|
16414
16459
|
|
|
16415
16460
|
// src/commands/voice/setup.ts
|
|
16416
16461
|
function setup() {
|
|
16417
|
-
|
|
16462
|
+
mkdirSync18(voicePaths.dir, { recursive: true });
|
|
16418
16463
|
bootstrapVenv();
|
|
16419
16464
|
console.log("\nDownloading models...\n");
|
|
16420
|
-
const script =
|
|
16465
|
+
const script = join47(getPythonDir(), "setup_models.py");
|
|
16421
16466
|
const result = spawnSync5(getVenvPython(), [script], {
|
|
16422
16467
|
stdio: "inherit",
|
|
16423
16468
|
env: { ...process.env, VOICE_LOG_FILE: voicePaths.log }
|
|
@@ -16430,8 +16475,8 @@ function setup() {
|
|
|
16430
16475
|
|
|
16431
16476
|
// src/commands/voice/start.ts
|
|
16432
16477
|
import { spawn as spawn7 } from "child_process";
|
|
16433
|
-
import { mkdirSync as
|
|
16434
|
-
import { join as
|
|
16478
|
+
import { mkdirSync as mkdirSync19, writeFileSync as writeFileSync30 } from "fs";
|
|
16479
|
+
import { join as join48 } from "path";
|
|
16435
16480
|
|
|
16436
16481
|
// src/commands/voice/buildDaemonEnv.ts
|
|
16437
16482
|
function buildDaemonEnv(options2) {
|
|
@@ -16459,17 +16504,17 @@ function spawnBackground(python, script, env) {
|
|
|
16459
16504
|
console.error("Failed to start voice daemon");
|
|
16460
16505
|
process.exit(1);
|
|
16461
16506
|
}
|
|
16462
|
-
|
|
16507
|
+
writeFileSync30(voicePaths.pid, String(pid));
|
|
16463
16508
|
writeLockFile(pid);
|
|
16464
16509
|
console.log(`Voice daemon started (PID ${pid})`);
|
|
16465
16510
|
}
|
|
16466
16511
|
function start2(options2) {
|
|
16467
|
-
|
|
16512
|
+
mkdirSync19(voicePaths.dir, { recursive: true });
|
|
16468
16513
|
checkLockFile();
|
|
16469
16514
|
bootstrapVenv();
|
|
16470
16515
|
const debug = options2.debug || options2.foreground || process.platform === "win32";
|
|
16471
16516
|
const env = buildDaemonEnv({ debug });
|
|
16472
|
-
const script =
|
|
16517
|
+
const script = join48(getPythonDir(), "voice_daemon.py");
|
|
16473
16518
|
const python = getVenvPython();
|
|
16474
16519
|
if (options2.foreground) {
|
|
16475
16520
|
spawnForeground(python, script, env);
|
|
@@ -16479,7 +16524,7 @@ function start2(options2) {
|
|
|
16479
16524
|
}
|
|
16480
16525
|
|
|
16481
16526
|
// src/commands/voice/status.ts
|
|
16482
|
-
import { existsSync as
|
|
16527
|
+
import { existsSync as existsSync46, readFileSync as readFileSync36 } from "fs";
|
|
16483
16528
|
function isProcessAlive3(pid) {
|
|
16484
16529
|
try {
|
|
16485
16530
|
process.kill(pid, 0);
|
|
@@ -16489,12 +16534,12 @@ function isProcessAlive3(pid) {
|
|
|
16489
16534
|
}
|
|
16490
16535
|
}
|
|
16491
16536
|
function readRecentLogs(count6) {
|
|
16492
|
-
if (!
|
|
16537
|
+
if (!existsSync46(voicePaths.log)) return [];
|
|
16493
16538
|
const lines = readFileSync36(voicePaths.log, "utf-8").trim().split("\n");
|
|
16494
16539
|
return lines.slice(-count6);
|
|
16495
16540
|
}
|
|
16496
16541
|
function status() {
|
|
16497
|
-
if (!
|
|
16542
|
+
if (!existsSync46(voicePaths.pid)) {
|
|
16498
16543
|
console.log("Voice daemon: not running (no PID file)");
|
|
16499
16544
|
return;
|
|
16500
16545
|
}
|
|
@@ -16517,9 +16562,9 @@ function status() {
|
|
|
16517
16562
|
}
|
|
16518
16563
|
|
|
16519
16564
|
// src/commands/voice/stop.ts
|
|
16520
|
-
import { existsSync as
|
|
16565
|
+
import { existsSync as existsSync47, readFileSync as readFileSync37, unlinkSync as unlinkSync15 } from "fs";
|
|
16521
16566
|
function stop2() {
|
|
16522
|
-
if (!
|
|
16567
|
+
if (!existsSync47(voicePaths.pid)) {
|
|
16523
16568
|
console.log("Voice daemon is not running (no PID file)");
|
|
16524
16569
|
return;
|
|
16525
16570
|
}
|
|
@@ -16531,12 +16576,12 @@ function stop2() {
|
|
|
16531
16576
|
console.log(`Voice daemon (PID ${pid}) is not running`);
|
|
16532
16577
|
}
|
|
16533
16578
|
try {
|
|
16534
|
-
|
|
16579
|
+
unlinkSync15(voicePaths.pid);
|
|
16535
16580
|
} catch {
|
|
16536
16581
|
}
|
|
16537
16582
|
try {
|
|
16538
16583
|
const lockFile = getLockFile();
|
|
16539
|
-
if (
|
|
16584
|
+
if (existsSync47(lockFile)) unlinkSync15(lockFile);
|
|
16540
16585
|
} catch {
|
|
16541
16586
|
}
|
|
16542
16587
|
console.log("Voice daemon stopped");
|
|
@@ -16683,8 +16728,8 @@ async function exchangeToken(params) {
|
|
|
16683
16728
|
body: body.toString()
|
|
16684
16729
|
});
|
|
16685
16730
|
if (!response.ok) {
|
|
16686
|
-
const
|
|
16687
|
-
throw new Error(`Token exchange failed (${response.status}): ${
|
|
16731
|
+
const text3 = await response.text();
|
|
16732
|
+
throw new Error(`Token exchange failed (${response.status}): ${text3}`);
|
|
16688
16733
|
}
|
|
16689
16734
|
return response.json();
|
|
16690
16735
|
}
|
|
@@ -16759,7 +16804,7 @@ async function auth() {
|
|
|
16759
16804
|
// src/commands/roam/postRoamActivity.ts
|
|
16760
16805
|
import { execFileSync as execFileSync7 } from "child_process";
|
|
16761
16806
|
import { readdirSync as readdirSync7, readFileSync as readFileSync38, statSync as statSync5 } from "fs";
|
|
16762
|
-
import { join as
|
|
16807
|
+
import { join as join49 } from "path";
|
|
16763
16808
|
function findPortFile(roamDir) {
|
|
16764
16809
|
let entries;
|
|
16765
16810
|
try {
|
|
@@ -16768,9 +16813,9 @@ function findPortFile(roamDir) {
|
|
|
16768
16813
|
return void 0;
|
|
16769
16814
|
}
|
|
16770
16815
|
const candidates = entries.filter((name) => /^roam-local-api(-[^.]+)?\.port$/.test(name)).map((name) => {
|
|
16771
|
-
const
|
|
16816
|
+
const path54 = join49(roamDir, name);
|
|
16772
16817
|
try {
|
|
16773
|
-
return { path:
|
|
16818
|
+
return { path: path54, mtimeMs: statSync5(path54).mtimeMs };
|
|
16774
16819
|
} catch {
|
|
16775
16820
|
return void 0;
|
|
16776
16821
|
}
|
|
@@ -16780,7 +16825,7 @@ function findPortFile(roamDir) {
|
|
|
16780
16825
|
function postRoamActivity(app, event) {
|
|
16781
16826
|
const appData = process.env.APPDATA;
|
|
16782
16827
|
if (!appData) return;
|
|
16783
|
-
const portFile = findPortFile(
|
|
16828
|
+
const portFile = findPortFile(join49(appData, "Roam"));
|
|
16784
16829
|
if (!portFile) return;
|
|
16785
16830
|
let port;
|
|
16786
16831
|
try {
|
|
@@ -16926,15 +16971,15 @@ function runPreCommands(pre, cwd) {
|
|
|
16926
16971
|
|
|
16927
16972
|
// src/commands/run/spawnRunCommand.ts
|
|
16928
16973
|
import { execFileSync as execFileSync8, spawn as spawn8 } from "child_process";
|
|
16929
|
-
import { existsSync as
|
|
16930
|
-
import { dirname as dirname25, join as
|
|
16974
|
+
import { existsSync as existsSync48 } from "fs";
|
|
16975
|
+
import { dirname as dirname25, join as join50, resolve as resolve11 } from "path";
|
|
16931
16976
|
function resolveCommand2(command) {
|
|
16932
16977
|
if (process.platform !== "win32" || command !== "bash") return command;
|
|
16933
16978
|
try {
|
|
16934
16979
|
const gitPath = execFileSync8("where", ["git"], { encoding: "utf8" }).trim().split("\r\n")[0];
|
|
16935
16980
|
const gitRoot = resolve11(dirname25(gitPath), "..");
|
|
16936
|
-
const gitBash =
|
|
16937
|
-
if (
|
|
16981
|
+
const gitBash = join50(gitRoot, "bin", "bash.exe");
|
|
16982
|
+
if (existsSync48(gitBash)) return gitBash;
|
|
16938
16983
|
} catch {
|
|
16939
16984
|
}
|
|
16940
16985
|
return command;
|
|
@@ -17019,8 +17064,8 @@ async function run3(name, args) {
|
|
|
17019
17064
|
}
|
|
17020
17065
|
|
|
17021
17066
|
// src/commands/run/add.ts
|
|
17022
|
-
import { mkdirSync as
|
|
17023
|
-
import { join as
|
|
17067
|
+
import { mkdirSync as mkdirSync20, writeFileSync as writeFileSync31 } from "fs";
|
|
17068
|
+
import { join as join51 } from "path";
|
|
17024
17069
|
|
|
17025
17070
|
// src/commands/run/extractOption.ts
|
|
17026
17071
|
function extractOption(args, flag) {
|
|
@@ -17081,16 +17126,16 @@ function saveNewRunConfig(name, command, args, cwd) {
|
|
|
17081
17126
|
saveConfig(config);
|
|
17082
17127
|
}
|
|
17083
17128
|
function createCommandFile(name) {
|
|
17084
|
-
const dir =
|
|
17085
|
-
|
|
17129
|
+
const dir = join51(".claude", "commands");
|
|
17130
|
+
mkdirSync20(dir, { recursive: true });
|
|
17086
17131
|
const content = `---
|
|
17087
17132
|
description: Run ${name}
|
|
17088
17133
|
---
|
|
17089
17134
|
|
|
17090
17135
|
Run \`assist run ${name} $ARGUMENTS 2>&1\`.
|
|
17091
17136
|
`;
|
|
17092
|
-
const filePath =
|
|
17093
|
-
|
|
17137
|
+
const filePath = join51(dir, `${name}.md`);
|
|
17138
|
+
writeFileSync31(filePath, content);
|
|
17094
17139
|
console.log(`Created command file: ${filePath}`);
|
|
17095
17140
|
}
|
|
17096
17141
|
function add3() {
|
|
@@ -17113,11 +17158,11 @@ function findLinkIndex() {
|
|
|
17113
17158
|
function parseLinkArgs() {
|
|
17114
17159
|
const idx = findLinkIndex();
|
|
17115
17160
|
if (idx === -1) return null;
|
|
17116
|
-
const
|
|
17161
|
+
const path54 = process.argv[idx + 1];
|
|
17117
17162
|
const rest = process.argv.slice(idx + 2);
|
|
17118
17163
|
const { value: prefix2 } = extractOption(rest, "--prefix");
|
|
17119
17164
|
if (!prefix2) return null;
|
|
17120
|
-
return { path:
|
|
17165
|
+
return { path: path54, prefix: prefix2 };
|
|
17121
17166
|
}
|
|
17122
17167
|
function hasDuplicateLink(runList, linkPath) {
|
|
17123
17168
|
return runList.some(
|
|
@@ -17145,8 +17190,8 @@ function link2() {
|
|
|
17145
17190
|
}
|
|
17146
17191
|
|
|
17147
17192
|
// src/commands/run/remove.ts
|
|
17148
|
-
import { existsSync as
|
|
17149
|
-
import { join as
|
|
17193
|
+
import { existsSync as existsSync49, unlinkSync as unlinkSync16 } from "fs";
|
|
17194
|
+
import { join as join52 } from "path";
|
|
17150
17195
|
function findRemoveIndex() {
|
|
17151
17196
|
const idx = process.argv.indexOf("remove");
|
|
17152
17197
|
if (idx === -1 || idx + 1 >= process.argv.length) return -1;
|
|
@@ -17161,9 +17206,9 @@ function parseRemoveName() {
|
|
|
17161
17206
|
return process.argv[idx + 1];
|
|
17162
17207
|
}
|
|
17163
17208
|
function deleteCommandFile(name) {
|
|
17164
|
-
const filePath =
|
|
17165
|
-
if (
|
|
17166
|
-
|
|
17209
|
+
const filePath = join52(".claude", "commands", `${name}.md`);
|
|
17210
|
+
if (existsSync49(filePath)) {
|
|
17211
|
+
unlinkSync16(filePath);
|
|
17167
17212
|
console.log(`Deleted command file: ${filePath}`);
|
|
17168
17213
|
}
|
|
17169
17214
|
}
|
|
@@ -17201,9 +17246,9 @@ function registerRun(program2) {
|
|
|
17201
17246
|
|
|
17202
17247
|
// src/commands/screenshot/index.ts
|
|
17203
17248
|
import { execSync as execSync49 } from "child_process";
|
|
17204
|
-
import { existsSync as
|
|
17249
|
+
import { existsSync as existsSync50, mkdirSync as mkdirSync21, unlinkSync as unlinkSync17, writeFileSync as writeFileSync32 } from "fs";
|
|
17205
17250
|
import { tmpdir as tmpdir7 } from "os";
|
|
17206
|
-
import { join as
|
|
17251
|
+
import { join as join53, resolve as resolve13 } from "path";
|
|
17207
17252
|
import chalk158 from "chalk";
|
|
17208
17253
|
|
|
17209
17254
|
// src/commands/screenshot/captureWindowPs1.ts
|
|
@@ -17333,22 +17378,22 @@ Write-Output $OutputPath
|
|
|
17333
17378
|
|
|
17334
17379
|
// src/commands/screenshot/index.ts
|
|
17335
17380
|
function buildOutputPath(outputDir, processName) {
|
|
17336
|
-
if (!
|
|
17337
|
-
|
|
17381
|
+
if (!existsSync50(outputDir)) {
|
|
17382
|
+
mkdirSync21(outputDir, { recursive: true });
|
|
17338
17383
|
}
|
|
17339
17384
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
17340
17385
|
return resolve13(outputDir, `${processName}-${timestamp}.png`);
|
|
17341
17386
|
}
|
|
17342
17387
|
function runPowerShellScript(processName, outputPath) {
|
|
17343
|
-
const scriptPath =
|
|
17344
|
-
|
|
17388
|
+
const scriptPath = join53(tmpdir7(), `assist-screenshot-${Date.now()}.ps1`);
|
|
17389
|
+
writeFileSync32(scriptPath, captureWindowPs1, "utf-8");
|
|
17345
17390
|
try {
|
|
17346
17391
|
execSync49(
|
|
17347
17392
|
`powershell -NoProfile -ExecutionPolicy Bypass -File "${scriptPath}" -ProcessName "${processName}" -OutputPath "${outputPath}"`,
|
|
17348
17393
|
{ stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }
|
|
17349
17394
|
);
|
|
17350
17395
|
} finally {
|
|
17351
|
-
|
|
17396
|
+
unlinkSync17(scriptPath);
|
|
17352
17397
|
}
|
|
17353
17398
|
}
|
|
17354
17399
|
function screenshot(processName) {
|
|
@@ -17516,7 +17561,7 @@ async function restartDaemon() {
|
|
|
17516
17561
|
}
|
|
17517
17562
|
|
|
17518
17563
|
// src/commands/sessions/daemon/runDaemon.ts
|
|
17519
|
-
import { mkdirSync as
|
|
17564
|
+
import { mkdirSync as mkdirSync23 } from "fs";
|
|
17520
17565
|
|
|
17521
17566
|
// src/commands/sessions/daemon/createAutoExit.ts
|
|
17522
17567
|
var DEFAULT_GRACE_MS = 6e4;
|
|
@@ -17537,121 +17582,6 @@ function daemonLog(message) {
|
|
|
17537
17582
|
console.log(`${(/* @__PURE__ */ new Date()).toISOString()} [${process.pid}] ${message}`);
|
|
17538
17583
|
}
|
|
17539
17584
|
|
|
17540
|
-
// src/commands/sessions/shared/discoverSessions.ts
|
|
17541
|
-
import * as fs26 from "fs";
|
|
17542
|
-
import * as os from "os";
|
|
17543
|
-
import * as path46 from "path";
|
|
17544
|
-
|
|
17545
|
-
// src/commands/sessions/shared/parseSessionFile.ts
|
|
17546
|
-
import * as fs25 from "fs";
|
|
17547
|
-
import * as path45 from "path";
|
|
17548
|
-
|
|
17549
|
-
// src/commands/sessions/shared/extractSessionMeta.ts
|
|
17550
|
-
function extractSessionMeta(lines) {
|
|
17551
|
-
let sessionId = "";
|
|
17552
|
-
let cwd = "";
|
|
17553
|
-
let timestamp = "";
|
|
17554
|
-
let name = "";
|
|
17555
|
-
for (const line of lines) {
|
|
17556
|
-
const entry = safeParse(line);
|
|
17557
|
-
if (!entry) continue;
|
|
17558
|
-
sessionId ||= typeof entry.sessionId === "string" ? entry.sessionId : "";
|
|
17559
|
-
timestamp ||= typeof entry.timestamp === "string" ? entry.timestamp : "";
|
|
17560
|
-
cwd ||= typeof entry.cwd === "string" ? entry.cwd : "";
|
|
17561
|
-
if (entry.type === "user" && !entry.isMeta) {
|
|
17562
|
-
name = extractName(entry);
|
|
17563
|
-
break;
|
|
17564
|
-
}
|
|
17565
|
-
}
|
|
17566
|
-
return { sessionId, cwd, timestamp, name };
|
|
17567
|
-
}
|
|
17568
|
-
function safeParse(line) {
|
|
17569
|
-
try {
|
|
17570
|
-
return JSON.parse(line);
|
|
17571
|
-
} catch {
|
|
17572
|
-
return null;
|
|
17573
|
-
}
|
|
17574
|
-
}
|
|
17575
|
-
function extractName(entry) {
|
|
17576
|
-
const msg = entry.message;
|
|
17577
|
-
const content = msg?.content;
|
|
17578
|
-
const text2 = typeof content === "string" ? content : Array.isArray(content) ? content.find((c) => c.type === "text")?.text ?? "" : "";
|
|
17579
|
-
return text2.replace(/<command-[^>]*>[^<]*<\/command-[^>]*>/g, "").trim().slice(0, 80);
|
|
17580
|
-
}
|
|
17581
|
-
|
|
17582
|
-
// src/commands/sessions/shared/parseSessionFile.ts
|
|
17583
|
-
async function parseSessionFile(filePath) {
|
|
17584
|
-
let handle;
|
|
17585
|
-
try {
|
|
17586
|
-
handle = await fs25.promises.open(filePath, "r");
|
|
17587
|
-
const buf = Buffer.alloc(16384);
|
|
17588
|
-
const { bytesRead } = await handle.read(buf, 0, buf.length, 0);
|
|
17589
|
-
const lines = buf.toString("utf8", 0, bytesRead).split("\n").filter(Boolean);
|
|
17590
|
-
const meta = extractSessionMeta(lines);
|
|
17591
|
-
if (!meta.sessionId) return null;
|
|
17592
|
-
const timestamp = meta.timestamp || (await fs25.promises.stat(filePath)).mtime.toISOString();
|
|
17593
|
-
const project = meta.cwd ? path45.basename(meta.cwd) : dirNameToProject(filePath);
|
|
17594
|
-
return {
|
|
17595
|
-
sessionId: meta.sessionId,
|
|
17596
|
-
name: meta.name || `Session ${meta.sessionId.slice(0, 8)}`,
|
|
17597
|
-
project,
|
|
17598
|
-
cwd: meta.cwd,
|
|
17599
|
-
timestamp
|
|
17600
|
-
};
|
|
17601
|
-
} catch {
|
|
17602
|
-
return null;
|
|
17603
|
-
} finally {
|
|
17604
|
-
await handle?.close();
|
|
17605
|
-
}
|
|
17606
|
-
}
|
|
17607
|
-
function dirNameToProject(filePath) {
|
|
17608
|
-
const dirName = path45.basename(path45.dirname(filePath));
|
|
17609
|
-
const parts = dirName.split("--");
|
|
17610
|
-
return parts[parts.length - 1].replace(/-/g, "/");
|
|
17611
|
-
}
|
|
17612
|
-
|
|
17613
|
-
// src/commands/sessions/shared/discoverSessions.ts
|
|
17614
|
-
async function discoverSessionJsonlPaths() {
|
|
17615
|
-
const projectsDir = path46.join(os.homedir(), ".claude", "projects");
|
|
17616
|
-
let projectDirs;
|
|
17617
|
-
try {
|
|
17618
|
-
projectDirs = await fs26.promises.readdir(projectsDir);
|
|
17619
|
-
} catch {
|
|
17620
|
-
return [];
|
|
17621
|
-
}
|
|
17622
|
-
const paths = [];
|
|
17623
|
-
await Promise.all(
|
|
17624
|
-
projectDirs.map(async (dirName) => {
|
|
17625
|
-
const dirPath = path46.join(projectsDir, dirName);
|
|
17626
|
-
let entries;
|
|
17627
|
-
try {
|
|
17628
|
-
entries = await fs26.promises.readdir(dirPath);
|
|
17629
|
-
} catch {
|
|
17630
|
-
return;
|
|
17631
|
-
}
|
|
17632
|
-
const jsonlFiles = entries.filter((e) => e.endsWith(".jsonl"));
|
|
17633
|
-
for (const file of jsonlFiles) {
|
|
17634
|
-
paths.push(path46.join(dirPath, file));
|
|
17635
|
-
}
|
|
17636
|
-
})
|
|
17637
|
-
);
|
|
17638
|
-
return paths;
|
|
17639
|
-
}
|
|
17640
|
-
async function discoverSessions() {
|
|
17641
|
-
const paths = await discoverSessionJsonlPaths();
|
|
17642
|
-
const sessions = [];
|
|
17643
|
-
await Promise.all(
|
|
17644
|
-
paths.map(async (filePath) => {
|
|
17645
|
-
const session = await parseSessionFile(filePath);
|
|
17646
|
-
if (session) sessions.push(session);
|
|
17647
|
-
})
|
|
17648
|
-
);
|
|
17649
|
-
sessions.sort(
|
|
17650
|
-
(a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()
|
|
17651
|
-
);
|
|
17652
|
-
return sessions;
|
|
17653
|
-
}
|
|
17654
|
-
|
|
17655
17585
|
// src/commands/sessions/daemon/broadcast.ts
|
|
17656
17586
|
function sendTo(client, msg) {
|
|
17657
17587
|
client.send(JSON.stringify(msg));
|
|
@@ -17720,7 +17650,8 @@ function toSessionInfo({
|
|
|
17720
17650
|
cwd,
|
|
17721
17651
|
restored,
|
|
17722
17652
|
activity: activity2,
|
|
17723
|
-
autoRun
|
|
17653
|
+
autoRun,
|
|
17654
|
+
autoAdvance
|
|
17724
17655
|
}) {
|
|
17725
17656
|
return {
|
|
17726
17657
|
id,
|
|
@@ -17734,7 +17665,8 @@ function toSessionInfo({
|
|
|
17734
17665
|
cwd,
|
|
17735
17666
|
restored,
|
|
17736
17667
|
activity: activity2,
|
|
17737
|
-
autoRun
|
|
17668
|
+
autoRun,
|
|
17669
|
+
autoAdvance
|
|
17738
17670
|
};
|
|
17739
17671
|
}
|
|
17740
17672
|
|
|
@@ -17751,22 +17683,22 @@ function broadcastSessions(sessions, clients) {
|
|
|
17751
17683
|
import * as pty from "node-pty";
|
|
17752
17684
|
|
|
17753
17685
|
// src/commands/sessions/daemon/ensureSpawnHelperExecutable.ts
|
|
17754
|
-
import { chmodSync, existsSync as
|
|
17686
|
+
import { chmodSync, existsSync as existsSync51, statSync as statSync6 } from "fs";
|
|
17755
17687
|
import { createRequire as createRequire3 } from "module";
|
|
17756
|
-
import
|
|
17688
|
+
import path45 from "path";
|
|
17757
17689
|
var require4 = createRequire3(import.meta.url);
|
|
17758
17690
|
var ensured = false;
|
|
17759
17691
|
function ensureSpawnHelperExecutable() {
|
|
17760
17692
|
if (ensured || process.platform !== "darwin") return;
|
|
17761
17693
|
ensured = true;
|
|
17762
|
-
const ptyRoot =
|
|
17763
|
-
const helper =
|
|
17694
|
+
const ptyRoot = path45.join(path45.dirname(require4.resolve("node-pty")), "..");
|
|
17695
|
+
const helper = path45.join(
|
|
17764
17696
|
ptyRoot,
|
|
17765
17697
|
"prebuilds",
|
|
17766
17698
|
`${process.platform}-${process.arch}`,
|
|
17767
17699
|
"spawn-helper"
|
|
17768
17700
|
);
|
|
17769
|
-
if (!
|
|
17701
|
+
if (!existsSync51(helper)) return;
|
|
17770
17702
|
const mode = statSync6(helper).mode;
|
|
17771
17703
|
if ((mode & 73) === 0) chmodSync(helper, mode | 493);
|
|
17772
17704
|
}
|
|
@@ -17996,22 +17928,22 @@ function clearIdle(session) {
|
|
|
17996
17928
|
}
|
|
17997
17929
|
|
|
17998
17930
|
// src/commands/sessions/daemon/watchActivity.ts
|
|
17999
|
-
import { existsSync as
|
|
18000
|
-
import { dirname as
|
|
17931
|
+
import { existsSync as existsSync52, mkdirSync as mkdirSync22, watch } from "fs";
|
|
17932
|
+
import { dirname as dirname26 } from "path";
|
|
18001
17933
|
var DEBOUNCE_MS = 50;
|
|
18002
17934
|
function watchActivity(session, notify2) {
|
|
18003
17935
|
if (session.commandType !== "assist" || !session.cwd) return;
|
|
18004
|
-
const
|
|
18005
|
-
const dir =
|
|
17936
|
+
const path54 = activityPath(session.id);
|
|
17937
|
+
const dir = dirname26(path54);
|
|
18006
17938
|
try {
|
|
18007
|
-
|
|
17939
|
+
mkdirSync22(dir, { recursive: true });
|
|
18008
17940
|
} catch {
|
|
18009
17941
|
return;
|
|
18010
17942
|
}
|
|
18011
17943
|
let timer = null;
|
|
18012
17944
|
const read = () => {
|
|
18013
17945
|
timer = null;
|
|
18014
|
-
const activity2 = readActivity(
|
|
17946
|
+
const activity2 = readActivity(path54);
|
|
18015
17947
|
if (!activity2) return;
|
|
18016
17948
|
session.activity = activity2;
|
|
18017
17949
|
if (activity2.claudeSessionId)
|
|
@@ -18019,11 +17951,11 @@ function watchActivity(session, notify2) {
|
|
|
18019
17951
|
notify2();
|
|
18020
17952
|
};
|
|
18021
17953
|
session.activityWatcher = watch(dir, (_event, filename) => {
|
|
18022
|
-
if (filename && !
|
|
17954
|
+
if (filename && !path54.endsWith(filename)) return;
|
|
18023
17955
|
if (timer) clearTimeout(timer);
|
|
18024
17956
|
timer = setTimeout(read, DEBOUNCE_MS);
|
|
18025
17957
|
});
|
|
18026
|
-
if (
|
|
17958
|
+
if (existsSync52(path54)) read();
|
|
18027
17959
|
}
|
|
18028
17960
|
function refreshActivity(session) {
|
|
18029
17961
|
if (session.commandType !== "assist" || !session.cwd) return;
|
|
@@ -18112,6 +18044,174 @@ function shutdownSessions(sessions) {
|
|
|
18112
18044
|
// src/commands/sessions/daemon/watchClaudeSessionId.ts
|
|
18113
18045
|
import * as fs27 from "fs";
|
|
18114
18046
|
import * as path48 from "path";
|
|
18047
|
+
|
|
18048
|
+
// src/commands/sessions/shared/discoverSessions.ts
|
|
18049
|
+
import * as fs26 from "fs";
|
|
18050
|
+
import * as os from "os";
|
|
18051
|
+
import * as path47 from "path";
|
|
18052
|
+
|
|
18053
|
+
// src/commands/sessions/shared/parseSessionFile.ts
|
|
18054
|
+
import * as fs25 from "fs";
|
|
18055
|
+
import * as path46 from "path";
|
|
18056
|
+
|
|
18057
|
+
// src/commands/sessions/shared/deriveHistoryFields.ts
|
|
18058
|
+
var KNOWN = ["draft", "next", "bug", "refine", "run"];
|
|
18059
|
+
function deriveHistoryFields(commandName, commandArgs, name) {
|
|
18060
|
+
const fields = {};
|
|
18061
|
+
const sessionType = deriveSessionType(commandName, name);
|
|
18062
|
+
if (sessionType) fields.sessionType = sessionType;
|
|
18063
|
+
const itemMatch = commandArgs.match(/^(\d+)\b\s*/);
|
|
18064
|
+
if (itemMatch) fields.itemId = Number(itemMatch[1]);
|
|
18065
|
+
const prompt = commandArgs.slice(itemMatch?.[0].length ?? 0).trim();
|
|
18066
|
+
if (prompt) fields.prompt = prompt;
|
|
18067
|
+
return fields;
|
|
18068
|
+
}
|
|
18069
|
+
function deriveSessionType(commandName, name) {
|
|
18070
|
+
if (KNOWN.includes(commandName))
|
|
18071
|
+
return commandName;
|
|
18072
|
+
if (commandName || name) return "prompt";
|
|
18073
|
+
return void 0;
|
|
18074
|
+
}
|
|
18075
|
+
|
|
18076
|
+
// src/commands/sessions/shared/backlogRunMarkers.ts
|
|
18077
|
+
function backlogRunMarkers(text3) {
|
|
18078
|
+
const match = text3.match(/backlog item #(\d+):[ \t]*([^\n]*)/);
|
|
18079
|
+
if (!match) return { commandName: "", commandArgs: "" };
|
|
18080
|
+
const title = match[2].trim();
|
|
18081
|
+
return {
|
|
18082
|
+
commandName: "next",
|
|
18083
|
+
commandArgs: title ? `${match[1]} ${title}` : match[1]
|
|
18084
|
+
};
|
|
18085
|
+
}
|
|
18086
|
+
|
|
18087
|
+
// src/commands/sessions/shared/extractSessionMeta.ts
|
|
18088
|
+
function extractSessionMeta(lines) {
|
|
18089
|
+
let sessionId = "";
|
|
18090
|
+
let cwd = "";
|
|
18091
|
+
let timestamp = "";
|
|
18092
|
+
let name = "";
|
|
18093
|
+
let commandName = "";
|
|
18094
|
+
let commandArgs = "";
|
|
18095
|
+
for (const line of lines) {
|
|
18096
|
+
const entry = safeParse(line);
|
|
18097
|
+
if (!entry) continue;
|
|
18098
|
+
sessionId ||= strField(entry, "sessionId");
|
|
18099
|
+
timestamp ||= strField(entry, "timestamp");
|
|
18100
|
+
cwd ||= strField(entry, "cwd");
|
|
18101
|
+
if (entry.type === "user" && !entry.isMeta) {
|
|
18102
|
+
({ name, commandName, commandArgs } = parseFirstUserEntry(entry));
|
|
18103
|
+
break;
|
|
18104
|
+
}
|
|
18105
|
+
}
|
|
18106
|
+
return { sessionId, cwd, timestamp, name, commandName, commandArgs };
|
|
18107
|
+
}
|
|
18108
|
+
function parseFirstUserEntry(entry) {
|
|
18109
|
+
const raw = messageText(entry);
|
|
18110
|
+
const commandName = matchMarker(raw, "command-name").replace(/^\//, "");
|
|
18111
|
+
const commandArgs = matchMarker(raw, "command-args");
|
|
18112
|
+
const name = stripMarkers(raw);
|
|
18113
|
+
if (commandName) return { name, commandName, commandArgs };
|
|
18114
|
+
return { name, ...backlogRunMarkers(raw) };
|
|
18115
|
+
}
|
|
18116
|
+
function strField(entry, key) {
|
|
18117
|
+
const value = entry[key];
|
|
18118
|
+
return typeof value === "string" ? value : "";
|
|
18119
|
+
}
|
|
18120
|
+
function safeParse(line) {
|
|
18121
|
+
try {
|
|
18122
|
+
return JSON.parse(line);
|
|
18123
|
+
} catch {
|
|
18124
|
+
return null;
|
|
18125
|
+
}
|
|
18126
|
+
}
|
|
18127
|
+
function messageText(entry) {
|
|
18128
|
+
const msg = entry.message;
|
|
18129
|
+
const content = msg?.content;
|
|
18130
|
+
return typeof content === "string" ? content : Array.isArray(content) ? content.find((c) => c.type === "text")?.text ?? "" : "";
|
|
18131
|
+
}
|
|
18132
|
+
function stripMarkers(text3) {
|
|
18133
|
+
return text3.replace(/<command-[^>]*>[^<]*<\/command-[^>]*>/g, "").trim().slice(0, 80);
|
|
18134
|
+
}
|
|
18135
|
+
function matchMarker(text3, tag) {
|
|
18136
|
+
const match = text3.match(new RegExp(`<${tag}>([\\s\\S]*?)</${tag}>`));
|
|
18137
|
+
return match ? match[1].trim() : "";
|
|
18138
|
+
}
|
|
18139
|
+
|
|
18140
|
+
// src/commands/sessions/shared/parseSessionFile.ts
|
|
18141
|
+
async function parseSessionFile(filePath) {
|
|
18142
|
+
let handle;
|
|
18143
|
+
try {
|
|
18144
|
+
handle = await fs25.promises.open(filePath, "r");
|
|
18145
|
+
const buf = Buffer.alloc(16384);
|
|
18146
|
+
const { bytesRead } = await handle.read(buf, 0, buf.length, 0);
|
|
18147
|
+
const lines = buf.toString("utf8", 0, bytesRead).split("\n").filter(Boolean);
|
|
18148
|
+
const meta = extractSessionMeta(lines);
|
|
18149
|
+
if (!meta.sessionId) return null;
|
|
18150
|
+
const timestamp = meta.timestamp || (await fs25.promises.stat(filePath)).mtime.toISOString();
|
|
18151
|
+
const project = meta.cwd ? path46.basename(meta.cwd) : dirNameToProject(filePath);
|
|
18152
|
+
return {
|
|
18153
|
+
sessionId: meta.sessionId,
|
|
18154
|
+
name: meta.name || `Session ${meta.sessionId.slice(0, 8)}`,
|
|
18155
|
+
project,
|
|
18156
|
+
cwd: meta.cwd,
|
|
18157
|
+
timestamp,
|
|
18158
|
+
...deriveHistoryFields(meta.commandName, meta.commandArgs, meta.name)
|
|
18159
|
+
};
|
|
18160
|
+
} catch {
|
|
18161
|
+
return null;
|
|
18162
|
+
} finally {
|
|
18163
|
+
await handle?.close();
|
|
18164
|
+
}
|
|
18165
|
+
}
|
|
18166
|
+
function dirNameToProject(filePath) {
|
|
18167
|
+
const dirName = path46.basename(path46.dirname(filePath));
|
|
18168
|
+
const parts = dirName.split("--");
|
|
18169
|
+
return parts[parts.length - 1].replace(/-/g, "/");
|
|
18170
|
+
}
|
|
18171
|
+
|
|
18172
|
+
// src/commands/sessions/shared/discoverSessions.ts
|
|
18173
|
+
async function discoverSessionJsonlPaths() {
|
|
18174
|
+
const projectsDir = path47.join(os.homedir(), ".claude", "projects");
|
|
18175
|
+
let projectDirs;
|
|
18176
|
+
try {
|
|
18177
|
+
projectDirs = await fs26.promises.readdir(projectsDir);
|
|
18178
|
+
} catch {
|
|
18179
|
+
return [];
|
|
18180
|
+
}
|
|
18181
|
+
const paths = [];
|
|
18182
|
+
await Promise.all(
|
|
18183
|
+
projectDirs.map(async (dirName) => {
|
|
18184
|
+
const dirPath = path47.join(projectsDir, dirName);
|
|
18185
|
+
let entries;
|
|
18186
|
+
try {
|
|
18187
|
+
entries = await fs26.promises.readdir(dirPath);
|
|
18188
|
+
} catch {
|
|
18189
|
+
return;
|
|
18190
|
+
}
|
|
18191
|
+
const jsonlFiles = entries.filter((e) => e.endsWith(".jsonl"));
|
|
18192
|
+
for (const file of jsonlFiles) {
|
|
18193
|
+
paths.push(path47.join(dirPath, file));
|
|
18194
|
+
}
|
|
18195
|
+
})
|
|
18196
|
+
);
|
|
18197
|
+
return paths;
|
|
18198
|
+
}
|
|
18199
|
+
async function discoverSessions() {
|
|
18200
|
+
const paths = await discoverSessionJsonlPaths();
|
|
18201
|
+
const sessions = [];
|
|
18202
|
+
await Promise.all(
|
|
18203
|
+
paths.map(async (filePath) => {
|
|
18204
|
+
const session = await parseSessionFile(filePath);
|
|
18205
|
+
if (session) sessions.push(session);
|
|
18206
|
+
})
|
|
18207
|
+
);
|
|
18208
|
+
sessions.sort(
|
|
18209
|
+
(a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()
|
|
18210
|
+
);
|
|
18211
|
+
return sessions;
|
|
18212
|
+
}
|
|
18213
|
+
|
|
18214
|
+
// src/commands/sessions/daemon/watchClaudeSessionId.ts
|
|
18115
18215
|
var POLL_MS = 3e3;
|
|
18116
18216
|
async function watchClaudeSessionId(options2) {
|
|
18117
18217
|
let adoptedMs = 0;
|
|
@@ -18192,6 +18292,17 @@ function setAutoRun(sessions, id, enabled) {
|
|
|
18192
18292
|
s.autoRun = enabled;
|
|
18193
18293
|
return true;
|
|
18194
18294
|
}
|
|
18295
|
+
function setAutoAdvance(sessions, id, enabled) {
|
|
18296
|
+
const s = sessions.get(id);
|
|
18297
|
+
if (!s) return false;
|
|
18298
|
+
s.autoAdvance = enabled;
|
|
18299
|
+
const itemId = s.activity?.itemId;
|
|
18300
|
+
if (itemId != null) {
|
|
18301
|
+
if (enabled) clearPause(itemId);
|
|
18302
|
+
else requestPause(itemId);
|
|
18303
|
+
}
|
|
18304
|
+
return true;
|
|
18305
|
+
}
|
|
18195
18306
|
function dismissSession(sessions, id) {
|
|
18196
18307
|
const s = sessions.get(id);
|
|
18197
18308
|
if (!s) return false;
|
|
@@ -18231,7 +18342,7 @@ var SessionManager = class {
|
|
|
18231
18342
|
}
|
|
18232
18343
|
restore() {
|
|
18233
18344
|
return loadPersistedSessions().map((persisted) => {
|
|
18234
|
-
this.
|
|
18345
|
+
this.spawnWith((id) => restoreSession(id, persisted));
|
|
18235
18346
|
return persisted.name;
|
|
18236
18347
|
});
|
|
18237
18348
|
}
|
|
@@ -18241,21 +18352,20 @@ var SessionManager = class {
|
|
|
18241
18352
|
watchActivity(session, this.notify);
|
|
18242
18353
|
return session.id;
|
|
18243
18354
|
}
|
|
18355
|
+
spawnWith(create2) {
|
|
18356
|
+
return this.add(create2(String(this.nextId++)));
|
|
18357
|
+
}
|
|
18244
18358
|
spawn(prompt, cwd) {
|
|
18245
|
-
return this.
|
|
18359
|
+
return this.spawnWith((id) => createSession(id, prompt, cwd));
|
|
18246
18360
|
}
|
|
18247
18361
|
spawnRun(runName, runArgs, cwd) {
|
|
18248
|
-
return this.
|
|
18249
|
-
createRunSession(String(this.nextId++), runName, runArgs, cwd)
|
|
18250
|
-
);
|
|
18362
|
+
return this.spawnWith((id) => createRunSession(id, runName, runArgs, cwd));
|
|
18251
18363
|
}
|
|
18252
18364
|
spawnAssist(assistArgs, cwd) {
|
|
18253
|
-
return this.
|
|
18254
|
-
createAssistSession(String(this.nextId++), assistArgs, cwd)
|
|
18255
|
-
);
|
|
18365
|
+
return this.spawnWith((id) => createAssistSession(id, assistArgs, cwd));
|
|
18256
18366
|
}
|
|
18257
18367
|
resume(sessionId, cwd, name) {
|
|
18258
|
-
return this.
|
|
18368
|
+
return this.spawnWith((id) => resumeSession(id, sessionId, cwd, name));
|
|
18259
18369
|
}
|
|
18260
18370
|
onStatusChange = makeStatusChangeHandler(
|
|
18261
18371
|
(id) => this.dismissSession(id),
|
|
@@ -18283,12 +18393,12 @@ var SessionManager = class {
|
|
|
18283
18393
|
setAutoRun(id, enabled) {
|
|
18284
18394
|
if (setAutoRun(this.sessions, id, enabled)) this.notify();
|
|
18285
18395
|
}
|
|
18396
|
+
setAutoAdvance(id, enabled) {
|
|
18397
|
+
if (setAutoAdvance(this.sessions, id, enabled)) this.notify();
|
|
18398
|
+
}
|
|
18286
18399
|
listSessions() {
|
|
18287
18400
|
return [...this.sessions.values()].map(toSessionInfo);
|
|
18288
18401
|
}
|
|
18289
|
-
async getHistory() {
|
|
18290
|
-
return discoverSessions();
|
|
18291
|
-
}
|
|
18292
18402
|
notify = () => {
|
|
18293
18403
|
if (this.shuttingDown) return;
|
|
18294
18404
|
broadcastSessions(this.sessions, this.clients);
|
|
@@ -18297,12 +18407,101 @@ var SessionManager = class {
|
|
|
18297
18407
|
};
|
|
18298
18408
|
|
|
18299
18409
|
// src/commands/sessions/daemon/startDaemonServer.ts
|
|
18300
|
-
import { unlinkSync as
|
|
18410
|
+
import { unlinkSync as unlinkSync19 } from "fs";
|
|
18301
18411
|
import * as net2 from "net";
|
|
18302
18412
|
|
|
18303
18413
|
// src/commands/sessions/daemon/handleConnection.ts
|
|
18304
18414
|
import { createInterface as createInterface5 } from "readline";
|
|
18305
18415
|
|
|
18416
|
+
// src/commands/sessions/shared/parseTranscript.ts
|
|
18417
|
+
import * as fs28 from "fs";
|
|
18418
|
+
|
|
18419
|
+
// src/commands/sessions/shared/toolTarget.ts
|
|
18420
|
+
function toolTarget(input) {
|
|
18421
|
+
if (!input || typeof input !== "object") return "";
|
|
18422
|
+
const i = input;
|
|
18423
|
+
const str = (v) => typeof v === "string" ? v : "";
|
|
18424
|
+
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);
|
|
18425
|
+
return target.replace(/\s+/g, " ").trim().slice(0, 120);
|
|
18426
|
+
}
|
|
18427
|
+
|
|
18428
|
+
// src/commands/sessions/shared/entryMessages.ts
|
|
18429
|
+
function entryMessages(entry) {
|
|
18430
|
+
const content = entry.message?.content;
|
|
18431
|
+
if (entry.type === "user") return userMessages(content);
|
|
18432
|
+
if (entry.type === "assistant") return assistantMessages(content);
|
|
18433
|
+
return [];
|
|
18434
|
+
}
|
|
18435
|
+
function userMessages(content) {
|
|
18436
|
+
if (typeof content === "string") return text2("user", cleanUserText(content));
|
|
18437
|
+
if (!Array.isArray(content)) return [];
|
|
18438
|
+
return content.filter((c) => c.type === "text").flatMap((c) => text2("user", cleanUserText(c.text ?? "")));
|
|
18439
|
+
}
|
|
18440
|
+
function assistantMessages(content) {
|
|
18441
|
+
if (typeof content === "string") return text2("assistant", content.trim());
|
|
18442
|
+
if (!Array.isArray(content)) return [];
|
|
18443
|
+
return content.flatMap((c) => assistantItem(c));
|
|
18444
|
+
}
|
|
18445
|
+
function assistantItem(c) {
|
|
18446
|
+
if (c.type === "text") return text2("assistant", (c.text ?? "").trim());
|
|
18447
|
+
if (c.type === "tool_use")
|
|
18448
|
+
return [
|
|
18449
|
+
{
|
|
18450
|
+
role: "tool",
|
|
18451
|
+
tool: typeof c.name === "string" ? c.name : "tool",
|
|
18452
|
+
target: toolTarget(c.input)
|
|
18453
|
+
}
|
|
18454
|
+
];
|
|
18455
|
+
return [];
|
|
18456
|
+
}
|
|
18457
|
+
function text2(role, value) {
|
|
18458
|
+
return value ? [{ role, text: value }] : [];
|
|
18459
|
+
}
|
|
18460
|
+
function cleanUserText(value) {
|
|
18461
|
+
return value.replace(/<command-[^>]*>[\s\S]*?<\/command-[^>]*>/g, "").replace(/<local-command-[^>]*>[\s\S]*?<\/local-command-[^>]*>/g, "").trim();
|
|
18462
|
+
}
|
|
18463
|
+
|
|
18464
|
+
// src/commands/sessions/shared/findSessionJsonlPath.ts
|
|
18465
|
+
import * as path49 from "path";
|
|
18466
|
+
async function findSessionJsonlPath(sessionId) {
|
|
18467
|
+
const paths = await discoverSessionJsonlPaths();
|
|
18468
|
+
const direct = paths.find((p) => path49.basename(p, ".jsonl") === sessionId);
|
|
18469
|
+
if (direct) return direct;
|
|
18470
|
+
for (const p of paths) {
|
|
18471
|
+
const meta = await parseSessionFile(p);
|
|
18472
|
+
if (meta?.sessionId === sessionId) return p;
|
|
18473
|
+
}
|
|
18474
|
+
return null;
|
|
18475
|
+
}
|
|
18476
|
+
|
|
18477
|
+
// src/commands/sessions/shared/parseTranscript.ts
|
|
18478
|
+
async function parseTranscript(sessionId) {
|
|
18479
|
+
const filePath = await findSessionJsonlPath(sessionId);
|
|
18480
|
+
if (!filePath) return [];
|
|
18481
|
+
try {
|
|
18482
|
+
const raw = await fs28.promises.readFile(filePath, "utf8");
|
|
18483
|
+
return parseTranscriptLines(raw.split("\n"));
|
|
18484
|
+
} catch {
|
|
18485
|
+
return [];
|
|
18486
|
+
}
|
|
18487
|
+
}
|
|
18488
|
+
function parseTranscriptLines(lines) {
|
|
18489
|
+
const messages = [];
|
|
18490
|
+
for (const line of lines) {
|
|
18491
|
+
const entry = line.trim() ? safeParse2(line) : null;
|
|
18492
|
+
if (!entry || entry.isSidechain || entry.isMeta) continue;
|
|
18493
|
+
messages.push(...entryMessages(entry));
|
|
18494
|
+
}
|
|
18495
|
+
return messages;
|
|
18496
|
+
}
|
|
18497
|
+
function safeParse2(line) {
|
|
18498
|
+
try {
|
|
18499
|
+
return JSON.parse(line);
|
|
18500
|
+
} catch {
|
|
18501
|
+
return null;
|
|
18502
|
+
}
|
|
18503
|
+
}
|
|
18504
|
+
|
|
18306
18505
|
// src/commands/sessions/daemon/dispatchMessage.ts
|
|
18307
18506
|
function sendCreated(client, id) {
|
|
18308
18507
|
sendTo(client, { type: "created", sessionId: id });
|
|
@@ -18345,10 +18544,16 @@ function handleResume(client, manager, data) {
|
|
|
18345
18544
|
)
|
|
18346
18545
|
);
|
|
18347
18546
|
}
|
|
18348
|
-
function handleHistory(client
|
|
18349
|
-
|
|
18350
|
-
sendTo(client, { type: "history", sessions
|
|
18351
|
-
|
|
18547
|
+
function handleHistory(client) {
|
|
18548
|
+
discoverSessions().then(
|
|
18549
|
+
(sessions) => sendTo(client, { type: "history", sessions })
|
|
18550
|
+
);
|
|
18551
|
+
}
|
|
18552
|
+
function handleFetchTranscript(client, _manager, data) {
|
|
18553
|
+
const sessionId = data.sessionId;
|
|
18554
|
+
parseTranscript(sessionId).then(
|
|
18555
|
+
(messages) => sendTo(client, { type: "transcript", sessionId, messages })
|
|
18556
|
+
);
|
|
18352
18557
|
}
|
|
18353
18558
|
function handleShutdown(client, manager) {
|
|
18354
18559
|
manager.shutdown();
|
|
@@ -18362,12 +18567,14 @@ var handlers = {
|
|
|
18362
18567
|
"create-assist": handleCreateAssist,
|
|
18363
18568
|
resume: handleResume,
|
|
18364
18569
|
history: handleHistory,
|
|
18570
|
+
"fetch-transcript": handleFetchTranscript,
|
|
18365
18571
|
shutdown: handleShutdown,
|
|
18366
18572
|
input: (_client, m, d) => m.writeToSession(d.sessionId, d.data),
|
|
18367
18573
|
resize: (_client, m, d) => m.resizeSession(d.sessionId, d.cols, d.rows),
|
|
18368
18574
|
retry: (_client, m, d) => m.retrySession(d.sessionId),
|
|
18369
18575
|
dismiss: (_client, m, d) => m.dismissSession(d.sessionId),
|
|
18370
|
-
"set-autorun": (_client, m, d) => m.setAutoRun(d.sessionId, d.enabled)
|
|
18576
|
+
"set-autorun": (_client, m, d) => m.setAutoRun(d.sessionId, d.enabled),
|
|
18577
|
+
"set-autoadvance": (_client, m, d) => m.setAutoAdvance(d.sessionId, d.enabled)
|
|
18371
18578
|
};
|
|
18372
18579
|
function dispatchMessage(client, manager, data) {
|
|
18373
18580
|
handlers[data.type]?.(client, manager, data);
|
|
@@ -18407,7 +18614,7 @@ function handleConnection(socket, manager) {
|
|
|
18407
18614
|
}
|
|
18408
18615
|
|
|
18409
18616
|
// src/commands/sessions/daemon/onListening.ts
|
|
18410
|
-
import { unlinkSync as
|
|
18617
|
+
import { unlinkSync as unlinkSync18, writeFileSync as writeFileSync33 } from "fs";
|
|
18411
18618
|
|
|
18412
18619
|
// src/commands/sessions/daemon/startPidFileWatchdog.ts
|
|
18413
18620
|
import { readFileSync as readFileSync40 } from "fs";
|
|
@@ -18429,7 +18636,7 @@ function ownsPidFile() {
|
|
|
18429
18636
|
|
|
18430
18637
|
// src/commands/sessions/daemon/onListening.ts
|
|
18431
18638
|
function onListening(manager, checkAutoExit) {
|
|
18432
|
-
|
|
18639
|
+
writeFileSync33(daemonPaths.pid, String(process.pid));
|
|
18433
18640
|
startPidFileWatchdog(() => {
|
|
18434
18641
|
daemonLog("lost daemon.pid ownership; shutting down sessions and exiting");
|
|
18435
18642
|
manager.shutdown();
|
|
@@ -18446,12 +18653,12 @@ function onListening(manager, checkAutoExit) {
|
|
|
18446
18653
|
function cleanupOwnedFiles() {
|
|
18447
18654
|
if (!ownsPidFile()) return;
|
|
18448
18655
|
try {
|
|
18449
|
-
|
|
18656
|
+
unlinkSync18(daemonPaths.pid);
|
|
18450
18657
|
} catch {
|
|
18451
18658
|
}
|
|
18452
18659
|
if (process.platform !== "win32") {
|
|
18453
18660
|
try {
|
|
18454
|
-
|
|
18661
|
+
unlinkSync18(daemonPaths.socket);
|
|
18455
18662
|
} catch {
|
|
18456
18663
|
}
|
|
18457
18664
|
}
|
|
@@ -18481,7 +18688,7 @@ async function recoverFromAddrInUse(server, manager, checkAutoExit) {
|
|
|
18481
18688
|
daemonLog("removing stale socket left by a crashed daemon");
|
|
18482
18689
|
if (process.platform !== "win32") {
|
|
18483
18690
|
try {
|
|
18484
|
-
|
|
18691
|
+
unlinkSync19(daemonPaths.socket);
|
|
18485
18692
|
} catch {
|
|
18486
18693
|
}
|
|
18487
18694
|
}
|
|
@@ -18490,7 +18697,7 @@ async function recoverFromAddrInUse(server, manager, checkAutoExit) {
|
|
|
18490
18697
|
|
|
18491
18698
|
// src/commands/sessions/daemon/runDaemon.ts
|
|
18492
18699
|
async function runDaemon() {
|
|
18493
|
-
|
|
18700
|
+
mkdirSync23(daemonPaths.dir, { recursive: true });
|
|
18494
18701
|
daemonLog(
|
|
18495
18702
|
`starting (reason: ${process.env.ASSIST_DAEMON_SPAWN_REASON ?? "manual"})`
|
|
18496
18703
|
);
|
|
@@ -18524,17 +18731,17 @@ function registerDaemon(program2) {
|
|
|
18524
18731
|
}
|
|
18525
18732
|
|
|
18526
18733
|
// src/commands/sessions/summarise/index.ts
|
|
18527
|
-
import * as
|
|
18734
|
+
import * as fs31 from "fs";
|
|
18528
18735
|
import chalk159 from "chalk";
|
|
18529
18736
|
|
|
18530
18737
|
// src/commands/sessions/summarise/shared.ts
|
|
18531
|
-
import * as
|
|
18738
|
+
import * as fs29 from "fs";
|
|
18532
18739
|
function writeSummary(jsonlPath2, summary) {
|
|
18533
|
-
|
|
18740
|
+
fs29.writeFileSync(summaryPathFor(jsonlPath2), `${summary.trim()}
|
|
18534
18741
|
`, "utf8");
|
|
18535
18742
|
}
|
|
18536
18743
|
function hasSummary(jsonlPath2) {
|
|
18537
|
-
return
|
|
18744
|
+
return fs29.existsSync(summaryPathFor(jsonlPath2));
|
|
18538
18745
|
}
|
|
18539
18746
|
function summaryPathFor(jsonlPath2) {
|
|
18540
18747
|
return jsonlPath2.replace(/\.jsonl$/, ".summary");
|
|
@@ -18544,17 +18751,17 @@ function summaryPathFor(jsonlPath2) {
|
|
|
18544
18751
|
import { execFileSync as execFileSync10 } from "child_process";
|
|
18545
18752
|
|
|
18546
18753
|
// src/commands/sessions/summarise/iterateUserMessages.ts
|
|
18547
|
-
import * as
|
|
18754
|
+
import * as fs30 from "fs";
|
|
18548
18755
|
function* iterateUserMessages(filePath, maxBytes = 65536) {
|
|
18549
18756
|
let content;
|
|
18550
18757
|
try {
|
|
18551
|
-
const fd =
|
|
18758
|
+
const fd = fs30.openSync(filePath, "r");
|
|
18552
18759
|
try {
|
|
18553
18760
|
const buf = Buffer.alloc(maxBytes);
|
|
18554
|
-
const bytesRead =
|
|
18761
|
+
const bytesRead = fs30.readSync(fd, buf, 0, buf.length, 0);
|
|
18555
18762
|
content = buf.toString("utf8", 0, bytesRead);
|
|
18556
18763
|
} finally {
|
|
18557
|
-
|
|
18764
|
+
fs30.closeSync(fd);
|
|
18558
18765
|
}
|
|
18559
18766
|
} catch {
|
|
18560
18767
|
return;
|
|
@@ -18568,13 +18775,13 @@ function* iterateUserMessages(filePath, maxBytes = 65536) {
|
|
|
18568
18775
|
|
|
18569
18776
|
// src/commands/sessions/summarise/extractFirstUserMessage.ts
|
|
18570
18777
|
function extractFirstUserMessage(filePath) {
|
|
18571
|
-
for (const
|
|
18572
|
-
return truncate3(
|
|
18778
|
+
for (const text3 of iterateUserMessages(filePath)) {
|
|
18779
|
+
return truncate3(text3);
|
|
18573
18780
|
}
|
|
18574
18781
|
return void 0;
|
|
18575
18782
|
}
|
|
18576
|
-
function truncate3(
|
|
18577
|
-
const trimmed =
|
|
18783
|
+
function truncate3(text3, maxChars = 500) {
|
|
18784
|
+
const trimmed = text3.trim();
|
|
18578
18785
|
if (trimmed.length <= maxChars) return trimmed;
|
|
18579
18786
|
return `${trimmed.slice(0, maxChars)}\u2026`;
|
|
18580
18787
|
}
|
|
@@ -18582,28 +18789,28 @@ function truncate3(text2, maxChars = 500) {
|
|
|
18582
18789
|
// src/commands/sessions/summarise/scanSessionBacklogRefs.ts
|
|
18583
18790
|
function scanSessionBacklogRefs(filePath) {
|
|
18584
18791
|
const ids = /* @__PURE__ */ new Set();
|
|
18585
|
-
for (const
|
|
18586
|
-
for (const id of extractBacklogIds(
|
|
18792
|
+
for (const text3 of iterateUserMessages(filePath, Number.MAX_SAFE_INTEGER)) {
|
|
18793
|
+
for (const id of extractBacklogIds(text3)) {
|
|
18587
18794
|
ids.add(id);
|
|
18588
18795
|
}
|
|
18589
18796
|
}
|
|
18590
18797
|
return [...ids].sort((a, b) => a - b);
|
|
18591
18798
|
}
|
|
18592
|
-
function extractBacklogIds(
|
|
18799
|
+
function extractBacklogIds(text3) {
|
|
18593
18800
|
const ids = [];
|
|
18594
|
-
for (const m of
|
|
18801
|
+
for (const m of text3.matchAll(/backlog\s+run\s+(\d+)/gi)) {
|
|
18595
18802
|
ids.push(Number.parseInt(m[1], 10));
|
|
18596
18803
|
}
|
|
18597
|
-
for (const m of
|
|
18804
|
+
for (const m of text3.matchAll(/backlog\s+(?:item\s+)?#(\d+)/gi)) {
|
|
18598
18805
|
ids.push(Number.parseInt(m[1], 10));
|
|
18599
18806
|
}
|
|
18600
|
-
for (const m of
|
|
18807
|
+
for (const m of text3.matchAll(/backlog\s+phase-done\s+(\d+)/gi)) {
|
|
18601
18808
|
ids.push(Number.parseInt(m[1], 10));
|
|
18602
18809
|
}
|
|
18603
|
-
for (const m of
|
|
18810
|
+
for (const m of text3.matchAll(/backlog\s+comment\s+(\d+)/gi)) {
|
|
18604
18811
|
ids.push(Number.parseInt(m[1], 10));
|
|
18605
18812
|
}
|
|
18606
|
-
for (const m of
|
|
18813
|
+
for (const m of text3.matchAll(/(?:^|[\s(])#(\d{1,4})(?=[\s).,;:!?]|$)/gm)) {
|
|
18607
18814
|
ids.push(Number.parseInt(m[1], 10));
|
|
18608
18815
|
}
|
|
18609
18816
|
return ids;
|
|
@@ -18674,7 +18881,7 @@ function selectCandidates(files, options2) {
|
|
|
18674
18881
|
const candidates = options2.force ? files : files.filter((f) => !hasSummary(f));
|
|
18675
18882
|
candidates.sort((a, b) => {
|
|
18676
18883
|
try {
|
|
18677
|
-
return
|
|
18884
|
+
return fs31.statSync(b).mtimeMs - fs31.statSync(a).mtimeMs;
|
|
18678
18885
|
} catch {
|
|
18679
18886
|
return 0;
|
|
18680
18887
|
}
|
|
@@ -18788,21 +18995,21 @@ async function statusLine() {
|
|
|
18788
18995
|
}
|
|
18789
18996
|
|
|
18790
18997
|
// src/commands/sync.ts
|
|
18791
|
-
import * as
|
|
18998
|
+
import * as fs34 from "fs";
|
|
18792
18999
|
import * as os2 from "os";
|
|
18793
|
-
import * as
|
|
19000
|
+
import * as path52 from "path";
|
|
18794
19001
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
18795
19002
|
|
|
18796
19003
|
// src/commands/sync/syncClaudeMd.ts
|
|
18797
|
-
import * as
|
|
18798
|
-
import * as
|
|
19004
|
+
import * as fs32 from "fs";
|
|
19005
|
+
import * as path50 from "path";
|
|
18799
19006
|
import chalk162 from "chalk";
|
|
18800
19007
|
async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
18801
|
-
const source =
|
|
18802
|
-
const target =
|
|
18803
|
-
const sourceContent =
|
|
18804
|
-
if (
|
|
18805
|
-
const targetContent =
|
|
19008
|
+
const source = path50.join(claudeDir, "CLAUDE.md");
|
|
19009
|
+
const target = path50.join(targetBase, "CLAUDE.md");
|
|
19010
|
+
const sourceContent = fs32.readFileSync(source, "utf-8");
|
|
19011
|
+
if (fs32.existsSync(target)) {
|
|
19012
|
+
const targetContent = fs32.readFileSync(target, "utf-8");
|
|
18806
19013
|
if (sourceContent !== targetContent) {
|
|
18807
19014
|
console.log(
|
|
18808
19015
|
chalk162.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
@@ -18819,21 +19026,21 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
18819
19026
|
}
|
|
18820
19027
|
}
|
|
18821
19028
|
}
|
|
18822
|
-
|
|
19029
|
+
fs32.copyFileSync(source, target);
|
|
18823
19030
|
console.log("Copied CLAUDE.md to ~/.claude/CLAUDE.md");
|
|
18824
19031
|
}
|
|
18825
19032
|
|
|
18826
19033
|
// src/commands/sync/syncSettings.ts
|
|
18827
|
-
import * as
|
|
18828
|
-
import * as
|
|
19034
|
+
import * as fs33 from "fs";
|
|
19035
|
+
import * as path51 from "path";
|
|
18829
19036
|
import chalk163 from "chalk";
|
|
18830
19037
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
18831
|
-
const source =
|
|
18832
|
-
const target =
|
|
18833
|
-
const sourceContent =
|
|
19038
|
+
const source = path51.join(claudeDir, "settings.json");
|
|
19039
|
+
const target = path51.join(targetBase, "settings.json");
|
|
19040
|
+
const sourceContent = fs33.readFileSync(source, "utf-8");
|
|
18834
19041
|
const mergedContent = JSON.stringify(JSON.parse(sourceContent), null, " ");
|
|
18835
|
-
if (
|
|
18836
|
-
const targetContent =
|
|
19042
|
+
if (fs33.existsSync(target)) {
|
|
19043
|
+
const targetContent = fs33.readFileSync(target, "utf-8");
|
|
18837
19044
|
const normalizedTarget = JSON.stringify(
|
|
18838
19045
|
JSON.parse(targetContent),
|
|
18839
19046
|
null,
|
|
@@ -18859,29 +19066,29 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
18859
19066
|
}
|
|
18860
19067
|
}
|
|
18861
19068
|
}
|
|
18862
|
-
|
|
19069
|
+
fs33.writeFileSync(target, mergedContent);
|
|
18863
19070
|
console.log("Copied settings.json to ~/.claude/settings.json");
|
|
18864
19071
|
}
|
|
18865
19072
|
|
|
18866
19073
|
// src/commands/sync.ts
|
|
18867
19074
|
var __filename4 = fileURLToPath7(import.meta.url);
|
|
18868
|
-
var __dirname7 =
|
|
19075
|
+
var __dirname7 = path52.dirname(__filename4);
|
|
18869
19076
|
async function sync(options2) {
|
|
18870
19077
|
const config = loadConfig();
|
|
18871
19078
|
const yes = options2?.yes ?? config.sync.autoConfirm;
|
|
18872
|
-
const claudeDir =
|
|
18873
|
-
const targetBase =
|
|
19079
|
+
const claudeDir = path52.join(__dirname7, "..", "claude");
|
|
19080
|
+
const targetBase = path52.join(os2.homedir(), ".claude");
|
|
18874
19081
|
syncCommands(claudeDir, targetBase);
|
|
18875
19082
|
await syncSettings(claudeDir, targetBase, { yes });
|
|
18876
19083
|
await syncClaudeMd(claudeDir, targetBase, { yes });
|
|
18877
19084
|
}
|
|
18878
19085
|
function syncCommands(claudeDir, targetBase) {
|
|
18879
|
-
const sourceDir =
|
|
18880
|
-
const targetDir =
|
|
18881
|
-
|
|
18882
|
-
const files =
|
|
19086
|
+
const sourceDir = path52.join(claudeDir, "commands");
|
|
19087
|
+
const targetDir = path52.join(targetBase, "commands");
|
|
19088
|
+
fs34.mkdirSync(targetDir, { recursive: true });
|
|
19089
|
+
const files = fs34.readdirSync(sourceDir);
|
|
18883
19090
|
for (const file of files) {
|
|
18884
|
-
|
|
19091
|
+
fs34.copyFileSync(path52.join(sourceDir, file), path52.join(targetDir, file));
|
|
18885
19092
|
console.log(`Copied ${file} to ${targetDir}`);
|
|
18886
19093
|
}
|
|
18887
19094
|
console.log(`Synced ${files.length} command(s) to ~/.claude/commands`);
|
|
@@ -18889,15 +19096,15 @@ function syncCommands(claudeDir, targetBase) {
|
|
|
18889
19096
|
|
|
18890
19097
|
// src/commands/update.ts
|
|
18891
19098
|
import { execSync as execSync50 } from "child_process";
|
|
18892
|
-
import * as
|
|
19099
|
+
import * as path53 from "path";
|
|
18893
19100
|
function isGlobalNpmInstall(dir) {
|
|
18894
19101
|
try {
|
|
18895
|
-
const resolved =
|
|
18896
|
-
if (resolved.split(
|
|
19102
|
+
const resolved = path53.resolve(dir);
|
|
19103
|
+
if (resolved.split(path53.sep).includes("node_modules")) {
|
|
18897
19104
|
return true;
|
|
18898
19105
|
}
|
|
18899
19106
|
const globalPrefix = execSync50("npm prefix -g", { stdio: "pipe" }).toString().trim();
|
|
18900
|
-
return resolved.toLowerCase().startsWith(
|
|
19107
|
+
return resolved.toLowerCase().startsWith(path53.resolve(globalPrefix).toLowerCase());
|
|
18901
19108
|
} catch {
|
|
18902
19109
|
return false;
|
|
18903
19110
|
}
|