@staff0rd/assist 0.391.3 → 0.392.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/codex/config.toml +14 -0
- package/dist/commands/sessions/web/bundle.js +1 -1
- package/dist/index.js +362 -221
- package/package.json +2 -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.392.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -17,6 +17,7 @@ var package_default = {
|
|
|
17
17
|
files: [
|
|
18
18
|
"dist",
|
|
19
19
|
"claude",
|
|
20
|
+
"codex",
|
|
20
21
|
"allowed.cli-reads",
|
|
21
22
|
"allowed.cli-writes"
|
|
22
23
|
],
|
|
@@ -140,10 +141,10 @@ import { stringify as stringifyYaml } from "yaml";
|
|
|
140
141
|
// src/shared/loadRawYaml.ts
|
|
141
142
|
import { existsSync, readFileSync } from "fs";
|
|
142
143
|
import { parse as parseYaml } from "yaml";
|
|
143
|
-
function loadRawYaml(
|
|
144
|
-
if (!existsSync(
|
|
144
|
+
function loadRawYaml(path64) {
|
|
145
|
+
if (!existsSync(path64)) return {};
|
|
145
146
|
try {
|
|
146
|
-
const content = readFileSync(
|
|
147
|
+
const content = readFileSync(path64, "utf8");
|
|
147
148
|
return parseYaml(content) || {};
|
|
148
149
|
} catch {
|
|
149
150
|
return {};
|
|
@@ -1360,8 +1361,8 @@ function findUnmergedPaths() {
|
|
|
1360
1361
|
}
|
|
1361
1362
|
const found = /* @__PURE__ */ new Set();
|
|
1362
1363
|
for (const line of output.split("\n")) {
|
|
1363
|
-
const
|
|
1364
|
-
if (
|
|
1364
|
+
const path64 = line.split(" ")[1];
|
|
1365
|
+
if (path64) found.add(path64.trim());
|
|
1365
1366
|
}
|
|
1366
1367
|
return [...found];
|
|
1367
1368
|
}
|
|
@@ -1460,8 +1461,8 @@ function getPreferredRemoteRepo(cwd) {
|
|
|
1460
1461
|
function gitRefUrl(kind, ref, cwd) {
|
|
1461
1462
|
const repo = getPreferredRemoteRepo(cwd);
|
|
1462
1463
|
if (!repo) return void 0;
|
|
1463
|
-
const
|
|
1464
|
-
return `https://github.com/${repo.org}/${repo.repo}/${
|
|
1464
|
+
const path64 = kind === "branch" ? "tree" : "commit";
|
|
1465
|
+
return `https://github.com/${repo.org}/${repo.repo}/${path64}/${ref}`;
|
|
1465
1466
|
}
|
|
1466
1467
|
|
|
1467
1468
|
// src/commands/commit/collectCommitRefs.ts
|
|
@@ -3232,9 +3233,9 @@ import { existsSync as existsSync12, readFileSync as readFileSync9 } from "fs";
|
|
|
3232
3233
|
|
|
3233
3234
|
// src/commands/verify/forbiddenStrings/findForbiddenStrings.ts
|
|
3234
3235
|
import { minimatch as minimatch2 } from "minimatch";
|
|
3235
|
-
function resolveStringsAtPath(data,
|
|
3236
|
+
function resolveStringsAtPath(data, path64) {
|
|
3236
3237
|
let current = data;
|
|
3237
|
-
for (const segment of
|
|
3238
|
+
for (const segment of path64.split(".")) {
|
|
3238
3239
|
if (current === null || typeof current !== "object") return [];
|
|
3239
3240
|
current = current[segment];
|
|
3240
3241
|
}
|
|
@@ -3247,10 +3248,10 @@ function resolveStringsAtPath(data, path63) {
|
|
|
3247
3248
|
}
|
|
3248
3249
|
function findRuleViolations(data, rule) {
|
|
3249
3250
|
const violations = [];
|
|
3250
|
-
for (const
|
|
3251
|
-
for (const value of resolveStringsAtPath(data,
|
|
3251
|
+
for (const path64 of rule.paths) {
|
|
3252
|
+
for (const value of resolveStringsAtPath(data, path64)) {
|
|
3252
3253
|
if (minimatch2(value, rule.disallowed))
|
|
3253
|
-
violations.push({ file: rule.file, path:
|
|
3254
|
+
violations.push({ file: rule.file, path: path64, value });
|
|
3254
3255
|
}
|
|
3255
3256
|
}
|
|
3256
3257
|
return violations;
|
|
@@ -3289,8 +3290,8 @@ function forbiddenStrings() {
|
|
|
3289
3290
|
process.exit(0);
|
|
3290
3291
|
}
|
|
3291
3292
|
console.log("Forbidden strings found:\n");
|
|
3292
|
-
for (const { file, path:
|
|
3293
|
-
console.log(` ${file} ${
|
|
3293
|
+
for (const { file, path: path64, value } of violations) {
|
|
3294
|
+
console.log(` ${file} ${path64}: ${value}`);
|
|
3294
3295
|
}
|
|
3295
3296
|
console.log(`
|
|
3296
3297
|
Total: ${violations.length} forbidden string(s).`);
|
|
@@ -3582,15 +3583,15 @@ function readBaselineMigrations(repoRelativeDir, ref) {
|
|
|
3582
3583
|
} catch {
|
|
3583
3584
|
return baseline;
|
|
3584
3585
|
}
|
|
3585
|
-
const paths = listing.split("\n").map((line) => line.trim()).filter(Boolean).filter((
|
|
3586
|
-
for (const
|
|
3586
|
+
const paths = listing.split("\n").map((line) => line.trim()).filter(Boolean).filter((path64) => MIGRATION_FILE3.test(basename(path64)));
|
|
3587
|
+
for (const path64 of paths) {
|
|
3587
3588
|
try {
|
|
3588
|
-
const content = execSync12(`git show "${ref}:${
|
|
3589
|
+
const content = execSync12(`git show "${ref}:${path64}"`, {
|
|
3589
3590
|
encoding: "utf8",
|
|
3590
3591
|
maxBuffer: 16 * 1024 * 1024,
|
|
3591
3592
|
stdio: ["pipe", "pipe", "pipe"]
|
|
3592
3593
|
});
|
|
3593
|
-
baseline.set(basename(
|
|
3594
|
+
baseline.set(basename(path64), content);
|
|
3594
3595
|
} catch {
|
|
3595
3596
|
}
|
|
3596
3597
|
}
|
|
@@ -4955,10 +4956,10 @@ var hooksSettings = {
|
|
|
4955
4956
|
}
|
|
4956
4957
|
};
|
|
4957
4958
|
function ensureHooksSettings() {
|
|
4958
|
-
const
|
|
4959
|
-
mkdirSync5(dirname12(
|
|
4960
|
-
writeFileSync15(
|
|
4961
|
-
return
|
|
4959
|
+
const path64 = daemonPaths.hooksSettings;
|
|
4960
|
+
mkdirSync5(dirname12(path64), { recursive: true });
|
|
4961
|
+
writeFileSync15(path64, JSON.stringify(hooksSettings, null, 2));
|
|
4962
|
+
return path64;
|
|
4962
4963
|
}
|
|
4963
4964
|
|
|
4964
4965
|
// src/shared/spawnInherit.ts
|
|
@@ -5222,9 +5223,9 @@ var LOCAL_FILES = ["backlog.jsonl", "backlog.db"];
|
|
|
5222
5223
|
function backupLocalBacklogFiles(dir) {
|
|
5223
5224
|
const moved = [];
|
|
5224
5225
|
for (const name of LOCAL_FILES) {
|
|
5225
|
-
const
|
|
5226
|
-
if (existsSync18(
|
|
5227
|
-
renameSync(
|
|
5226
|
+
const path64 = join15(dir, ".assist", name);
|
|
5227
|
+
if (existsSync18(path64)) {
|
|
5228
|
+
renameSync(path64, `${path64}.bak`);
|
|
5228
5229
|
moved.push(`${name} \u2192 ${name}.bak`);
|
|
5229
5230
|
}
|
|
5230
5231
|
}
|
|
@@ -5663,8 +5664,8 @@ var backlogItemSchema = z3.strictObject({
|
|
|
5663
5664
|
var backlogFileSchema = z3.array(backlogItemSchema);
|
|
5664
5665
|
|
|
5665
5666
|
// src/commands/backlog/parseBacklogJsonl.ts
|
|
5666
|
-
function parseBacklogJsonl(
|
|
5667
|
-
const content = readFileSync14(
|
|
5667
|
+
function parseBacklogJsonl(path64) {
|
|
5668
|
+
const content = readFileSync14(path64, "utf8").trim();
|
|
5668
5669
|
if (content.length === 0) return [];
|
|
5669
5670
|
return content.split("\n").map((line) => line.trim()).filter(Boolean).map((line) => backlogItemSchema.parse(JSON.parse(line)));
|
|
5670
5671
|
}
|
|
@@ -5746,8 +5747,8 @@ function findBacklogUp(startDir) {
|
|
|
5746
5747
|
|
|
5747
5748
|
// src/commands/backlog/getCurrentOrigin.ts
|
|
5748
5749
|
import { execFileSync } from "child_process";
|
|
5749
|
-
function stripLeadingSlashes(
|
|
5750
|
-
return
|
|
5750
|
+
function stripLeadingSlashes(path64) {
|
|
5751
|
+
return path64.replace(/^\/+/, "");
|
|
5751
5752
|
}
|
|
5752
5753
|
function normalizeOrigin(raw) {
|
|
5753
5754
|
const trimmed = raw.trim().replace(/\.git$/i, "").replace(/\/+$/, "");
|
|
@@ -6287,24 +6288,24 @@ function getOwnerPath(itemId2) {
|
|
|
6287
6288
|
function recordSignalOwner(itemId2) {
|
|
6288
6289
|
const sessionId = process.env.ASSIST_SESSION_ID;
|
|
6289
6290
|
if (!sessionId) return;
|
|
6290
|
-
const
|
|
6291
|
-
mkdirSync7(dirname14(
|
|
6292
|
-
writeFileSync17(
|
|
6291
|
+
const path64 = getOwnerPath(itemId2);
|
|
6292
|
+
mkdirSync7(dirname14(path64), { recursive: true });
|
|
6293
|
+
writeFileSync17(path64, JSON.stringify({ sessionId }));
|
|
6293
6294
|
}
|
|
6294
6295
|
function readSignalOwner(itemId2) {
|
|
6295
|
-
const
|
|
6296
|
-
if (!existsSync21(
|
|
6296
|
+
const path64 = getOwnerPath(itemId2);
|
|
6297
|
+
if (!existsSync21(path64)) return void 0;
|
|
6297
6298
|
try {
|
|
6298
|
-
const parsed = JSON.parse(readFileSync15(
|
|
6299
|
+
const parsed = JSON.parse(readFileSync15(path64, "utf8"));
|
|
6299
6300
|
return parsed.sessionId;
|
|
6300
6301
|
} catch {
|
|
6301
6302
|
return void 0;
|
|
6302
6303
|
}
|
|
6303
6304
|
}
|
|
6304
6305
|
function clearSignalOwner(itemId2) {
|
|
6305
|
-
const
|
|
6306
|
+
const path64 = getOwnerPath(itemId2);
|
|
6306
6307
|
try {
|
|
6307
|
-
rmSync(
|
|
6308
|
+
rmSync(path64);
|
|
6308
6309
|
} catch {
|
|
6309
6310
|
}
|
|
6310
6311
|
}
|
|
@@ -6341,19 +6342,19 @@ function resolveSignalTarget(event, data) {
|
|
|
6341
6342
|
function writeSignal(event, data) {
|
|
6342
6343
|
const target = resolveSignalTarget(event, data);
|
|
6343
6344
|
if (!target) return;
|
|
6344
|
-
const
|
|
6345
|
-
if (!
|
|
6345
|
+
const path64 = getSignalPath(target);
|
|
6346
|
+
if (!path64) return;
|
|
6346
6347
|
const signal = { event, sessionId: target, ...data };
|
|
6347
|
-
mkdirSync8(dirname15(
|
|
6348
|
-
writeFileSync18(
|
|
6348
|
+
mkdirSync8(dirname15(path64), { recursive: true });
|
|
6349
|
+
writeFileSync18(path64, JSON.stringify(signal));
|
|
6349
6350
|
}
|
|
6350
6351
|
|
|
6351
6352
|
// src/commands/backlog/readSignal.ts
|
|
6352
6353
|
function readSignal() {
|
|
6353
|
-
const
|
|
6354
|
-
if (!
|
|
6354
|
+
const path64 = getSignalPath();
|
|
6355
|
+
if (!path64 || !existsSync22(path64)) return void 0;
|
|
6355
6356
|
try {
|
|
6356
|
-
return JSON.parse(readFileSync16(
|
|
6357
|
+
return JSON.parse(readFileSync16(path64, "utf8"));
|
|
6357
6358
|
} catch {
|
|
6358
6359
|
return void 0;
|
|
6359
6360
|
}
|
|
@@ -6448,13 +6449,13 @@ function activityPath(sessionId) {
|
|
|
6448
6449
|
function emitActivity(activity2) {
|
|
6449
6450
|
const sessionId = process.env.ASSIST_ACTIVITY_ID;
|
|
6450
6451
|
if (!sessionId) return;
|
|
6451
|
-
const
|
|
6452
|
-
mkdirSync9(dirname16(
|
|
6453
|
-
writeFileSync19(
|
|
6452
|
+
const path64 = activityPath(sessionId);
|
|
6453
|
+
mkdirSync9(dirname16(path64), { recursive: true });
|
|
6454
|
+
writeFileSync19(path64, JSON.stringify({ ...activity2, startedAt: Date.now() }));
|
|
6454
6455
|
}
|
|
6455
|
-
function readActivity(
|
|
6456
|
+
function readActivity(path64) {
|
|
6456
6457
|
try {
|
|
6457
|
-
return JSON.parse(readFileSync17(
|
|
6458
|
+
return JSON.parse(readFileSync17(path64, "utf8"));
|
|
6458
6459
|
} catch {
|
|
6459
6460
|
return void 0;
|
|
6460
6461
|
}
|
|
@@ -6464,9 +6465,9 @@ function reconcileActivity(sessionId, activity2) {
|
|
|
6464
6465
|
removeActivity(sessionId);
|
|
6465
6466
|
return;
|
|
6466
6467
|
}
|
|
6467
|
-
const
|
|
6468
|
-
mkdirSync9(dirname16(
|
|
6469
|
-
writeFileSync19(
|
|
6468
|
+
const path64 = activityPath(sessionId);
|
|
6469
|
+
mkdirSync9(dirname16(path64), { recursive: true });
|
|
6470
|
+
writeFileSync19(path64, JSON.stringify(activity2));
|
|
6470
6471
|
}
|
|
6471
6472
|
function removeActivity(sessionId) {
|
|
6472
6473
|
try {
|
|
@@ -7697,8 +7698,8 @@ async function getBacklogExists(req, res) {
|
|
|
7697
7698
|
// src/commands/backlog/originDisplayName.ts
|
|
7698
7699
|
function originDisplayName(origin) {
|
|
7699
7700
|
if (origin.startsWith("local:")) {
|
|
7700
|
-
const
|
|
7701
|
-
const segments =
|
|
7701
|
+
const path64 = origin.slice("local:".length).replace(/\/+$/, "");
|
|
7702
|
+
const segments = path64.split("/").filter(Boolean);
|
|
7702
7703
|
return segments[segments.length - 1] ?? origin;
|
|
7703
7704
|
}
|
|
7704
7705
|
const firstSlash = origin.indexOf("/");
|
|
@@ -8089,7 +8090,7 @@ function findSynthesisForBranch(repoReviewsDir, branch2) {
|
|
|
8089
8090
|
const parent = dirname20(branchKeyPath);
|
|
8090
8091
|
const branchPrefix = basename5(branchKeyPath);
|
|
8091
8092
|
if (!existsSync25(parent)) return null;
|
|
8092
|
-
const synthesisFiles = readdirSync2(parent).filter((name) => name.startsWith(branchPrefix)).map((name) => join23(parent, name, "synthesis.md")).filter((
|
|
8093
|
+
const synthesisFiles = readdirSync2(parent).filter((name) => name.startsWith(branchPrefix)).map((name) => join23(parent, name, "synthesis.md")).filter((path64) => existsSync25(path64)).map((path64) => ({ path: path64, mtime: statSync2(path64).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
|
|
8093
8094
|
return synthesisFiles[0]?.path ?? null;
|
|
8094
8095
|
}
|
|
8095
8096
|
|
|
@@ -8143,12 +8144,12 @@ async function getReviewSynthesis(req, res) {
|
|
|
8143
8144
|
const cwd = getCwdParam(req, res);
|
|
8144
8145
|
if (!cwd) return;
|
|
8145
8146
|
try {
|
|
8146
|
-
const
|
|
8147
|
-
if (!
|
|
8147
|
+
const path64 = await resolveSynthesisPath(cwd);
|
|
8148
|
+
if (!path64) {
|
|
8148
8149
|
respondJson(res, 404, { error: "No synthesis found" });
|
|
8149
8150
|
return;
|
|
8150
8151
|
}
|
|
8151
|
-
respondJson(res, 200, { synthesis: readFileSync19(
|
|
8152
|
+
respondJson(res, 200, { synthesis: readFileSync19(path64, "utf8") });
|
|
8152
8153
|
} catch {
|
|
8153
8154
|
respondJson(res, 404, { error: "No synthesis found" });
|
|
8154
8155
|
}
|
|
@@ -8283,10 +8284,10 @@ function getStorePath(filename) {
|
|
|
8283
8284
|
return join26(getStoreDir(), filename);
|
|
8284
8285
|
}
|
|
8285
8286
|
function loadJson(filename) {
|
|
8286
|
-
const
|
|
8287
|
-
if (existsSync26(
|
|
8287
|
+
const path64 = getStorePath(filename);
|
|
8288
|
+
if (existsSync26(path64)) {
|
|
8288
8289
|
try {
|
|
8289
|
-
return JSON.parse(readFileSync20(
|
|
8290
|
+
return JSON.parse(readFileSync20(path64, "utf8"));
|
|
8290
8291
|
} catch {
|
|
8291
8292
|
return {};
|
|
8292
8293
|
}
|
|
@@ -11440,52 +11441,6 @@ function findBuiltinDenyRaw(rawCommand) {
|
|
|
11440
11441
|
return toDecision(matchBuiltinDeny(rawCommand));
|
|
11441
11442
|
}
|
|
11442
11443
|
|
|
11443
|
-
// src/commands/cliHook/logDeniedToolCall.ts
|
|
11444
|
-
import { mkdirSync as mkdirSync12 } from "fs";
|
|
11445
|
-
import { homedir as homedir14 } from "os";
|
|
11446
|
-
import { join as join28 } from "path";
|
|
11447
|
-
import Database from "better-sqlite3";
|
|
11448
|
-
var _db;
|
|
11449
|
-
function getDbDir() {
|
|
11450
|
-
return join28(homedir14(), ".assist");
|
|
11451
|
-
}
|
|
11452
|
-
function initSchema(db) {
|
|
11453
|
-
db.exec(`
|
|
11454
|
-
CREATE TABLE IF NOT EXISTS denied_tool_calls (
|
|
11455
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
11456
|
-
tool TEXT NOT NULL,
|
|
11457
|
-
command TEXT NOT NULL,
|
|
11458
|
-
repo TEXT NOT NULL,
|
|
11459
|
-
session_id TEXT,
|
|
11460
|
-
deny_reason TEXT NOT NULL,
|
|
11461
|
-
timestamp TEXT NOT NULL DEFAULT (datetime('now'))
|
|
11462
|
-
);
|
|
11463
|
-
`);
|
|
11464
|
-
}
|
|
11465
|
-
function openPromptsDb(dir) {
|
|
11466
|
-
if (_db) return _db;
|
|
11467
|
-
const dbDir = dir ?? getDbDir();
|
|
11468
|
-
mkdirSync12(dbDir, { recursive: true });
|
|
11469
|
-
const db = new Database(join28(dbDir, "assist.db"));
|
|
11470
|
-
db.pragma("journal_mode = WAL");
|
|
11471
|
-
initSchema(db);
|
|
11472
|
-
_db = db;
|
|
11473
|
-
return db;
|
|
11474
|
-
}
|
|
11475
|
-
function logDeniedToolCall(entry) {
|
|
11476
|
-
const db = openPromptsDb();
|
|
11477
|
-
db.prepare(
|
|
11478
|
-
`INSERT INTO denied_tool_calls (tool, command, repo, session_id, deny_reason)
|
|
11479
|
-
VALUES (@tool, @command, @repo, @sessionId, @denyReason)`
|
|
11480
|
-
).run({
|
|
11481
|
-
tool: entry.tool,
|
|
11482
|
-
command: entry.command,
|
|
11483
|
-
repo: entry.repo,
|
|
11484
|
-
sessionId: entry.sessionId ?? null,
|
|
11485
|
-
denyReason: entry.denyReason
|
|
11486
|
-
});
|
|
11487
|
-
}
|
|
11488
|
-
|
|
11489
11444
|
// src/shared/isApprovedRead.ts
|
|
11490
11445
|
import { resolve as resolve9, sep } from "path";
|
|
11491
11446
|
|
|
@@ -11576,9 +11531,9 @@ var __dirname4 = dirname21(__filename3);
|
|
|
11576
11531
|
function packageRoot() {
|
|
11577
11532
|
return __dirname4;
|
|
11578
11533
|
}
|
|
11579
|
-
function readLines(
|
|
11580
|
-
if (!existsSync27(
|
|
11581
|
-
return readFileSync23(
|
|
11534
|
+
function readLines(path64) {
|
|
11535
|
+
if (!existsSync27(path64)) return [];
|
|
11536
|
+
return readFileSync23(path64, "utf8").split("\n").filter((line) => line.trim() !== "");
|
|
11582
11537
|
}
|
|
11583
11538
|
var cachedReads;
|
|
11584
11539
|
var cachedWrites;
|
|
@@ -11625,13 +11580,13 @@ function findCliWrite(command) {
|
|
|
11625
11580
|
|
|
11626
11581
|
// src/shared/readSettingsPerms.ts
|
|
11627
11582
|
import { existsSync as existsSync28, readFileSync as readFileSync24 } from "fs";
|
|
11628
|
-
import { homedir as
|
|
11629
|
-
import { join as
|
|
11583
|
+
import { homedir as homedir14 } from "os";
|
|
11584
|
+
import { join as join28 } from "path";
|
|
11630
11585
|
function readSettingsPerms(key) {
|
|
11631
11586
|
const paths = [
|
|
11632
|
-
|
|
11633
|
-
|
|
11634
|
-
|
|
11587
|
+
join28(homedir14(), ".claude", "settings.json"),
|
|
11588
|
+
join28(process.cwd(), ".claude", "settings.json"),
|
|
11589
|
+
join28(process.cwd(), ".claude", "settings.local.json")
|
|
11635
11590
|
];
|
|
11636
11591
|
const entries = [];
|
|
11637
11592
|
for (const p of paths) {
|
|
@@ -11823,6 +11778,59 @@ function resolvePermission(toolName, parts) {
|
|
|
11823
11778
|
};
|
|
11824
11779
|
}
|
|
11825
11780
|
|
|
11781
|
+
// src/commands/cliHook/decideCommand.ts
|
|
11782
|
+
function decideCommand(toolName, rawCommand) {
|
|
11783
|
+
const result = splitCompound(rawCommand);
|
|
11784
|
+
if (result.ok) return resolvePermission(toolName, result.parts);
|
|
11785
|
+
return findBuiltinDenyRaw(rawCommand) ?? findDeny(toolName, [rawCommand]);
|
|
11786
|
+
}
|
|
11787
|
+
|
|
11788
|
+
// src/commands/cliHook/logDeniedToolCall.ts
|
|
11789
|
+
import { mkdirSync as mkdirSync12 } from "fs";
|
|
11790
|
+
import { homedir as homedir15 } from "os";
|
|
11791
|
+
import { join as join29 } from "path";
|
|
11792
|
+
import Database from "better-sqlite3";
|
|
11793
|
+
var _db;
|
|
11794
|
+
function getDbDir() {
|
|
11795
|
+
return join29(homedir15(), ".assist");
|
|
11796
|
+
}
|
|
11797
|
+
function initSchema(db) {
|
|
11798
|
+
db.exec(`
|
|
11799
|
+
CREATE TABLE IF NOT EXISTS denied_tool_calls (
|
|
11800
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
11801
|
+
tool TEXT NOT NULL,
|
|
11802
|
+
command TEXT NOT NULL,
|
|
11803
|
+
repo TEXT NOT NULL,
|
|
11804
|
+
session_id TEXT,
|
|
11805
|
+
deny_reason TEXT NOT NULL,
|
|
11806
|
+
timestamp TEXT NOT NULL DEFAULT (datetime('now'))
|
|
11807
|
+
);
|
|
11808
|
+
`);
|
|
11809
|
+
}
|
|
11810
|
+
function openPromptsDb(dir) {
|
|
11811
|
+
if (_db) return _db;
|
|
11812
|
+
const dbDir = dir ?? getDbDir();
|
|
11813
|
+
mkdirSync12(dbDir, { recursive: true });
|
|
11814
|
+
const db = new Database(join29(dbDir, "assist.db"));
|
|
11815
|
+
db.pragma("journal_mode = WAL");
|
|
11816
|
+
initSchema(db);
|
|
11817
|
+
_db = db;
|
|
11818
|
+
return db;
|
|
11819
|
+
}
|
|
11820
|
+
function logDeniedToolCall(entry) {
|
|
11821
|
+
const db = openPromptsDb();
|
|
11822
|
+
db.prepare(
|
|
11823
|
+
`INSERT INTO denied_tool_calls (tool, command, repo, session_id, deny_reason)
|
|
11824
|
+
VALUES (@tool, @command, @repo, @sessionId, @denyReason)`
|
|
11825
|
+
).run({
|
|
11826
|
+
tool: entry.tool,
|
|
11827
|
+
command: entry.command,
|
|
11828
|
+
repo: entry.repo,
|
|
11829
|
+
sessionId: entry.sessionId ?? null,
|
|
11830
|
+
denyReason: entry.denyReason
|
|
11831
|
+
});
|
|
11832
|
+
}
|
|
11833
|
+
|
|
11826
11834
|
// src/commands/cliHook/index.ts
|
|
11827
11835
|
var SUPPORTED_TOOLS = /* @__PURE__ */ new Set(["Bash", "PowerShell"]);
|
|
11828
11836
|
function tryParseInput(raw) {
|
|
@@ -11838,15 +11846,10 @@ function tryParseInput(raw) {
|
|
|
11838
11846
|
return void 0;
|
|
11839
11847
|
}
|
|
11840
11848
|
}
|
|
11841
|
-
function decide(toolName, rawCommand) {
|
|
11842
|
-
const result = splitCompound(rawCommand);
|
|
11843
|
-
if (result.ok) return resolvePermission(toolName, result.parts);
|
|
11844
|
-
return findBuiltinDenyRaw(rawCommand) ?? findDeny(toolName, [rawCommand]);
|
|
11845
|
-
}
|
|
11846
11849
|
async function cliHook() {
|
|
11847
11850
|
const input = tryParseInput(await readStdin());
|
|
11848
11851
|
if (!input) return;
|
|
11849
|
-
const decision =
|
|
11852
|
+
const decision = decideCommand(input.toolName, input.command);
|
|
11850
11853
|
if (!decision) return;
|
|
11851
11854
|
console.log(
|
|
11852
11855
|
JSON.stringify({
|
|
@@ -12022,14 +12025,14 @@ function showProgress(p, label2) {
|
|
|
12022
12025
|
const pct = Math.round(p.done / p.total * 100);
|
|
12023
12026
|
process.stderr.write(`\r\x1B[K[${pct}%] Scanning ${label2}...`);
|
|
12024
12027
|
}
|
|
12025
|
-
async function resolveCommand(cli,
|
|
12026
|
-
showProgress(p,
|
|
12027
|
-
const subHelp = await runHelp([cli, ...
|
|
12028
|
+
async function resolveCommand(cli, path64, description, depth, p) {
|
|
12029
|
+
showProgress(p, path64.join(" "));
|
|
12030
|
+
const subHelp = await runHelp([cli, ...path64]);
|
|
12028
12031
|
if (!subHelp || !hasSubcommands(subHelp)) {
|
|
12029
|
-
return [{ path:
|
|
12032
|
+
return [{ path: path64, description }];
|
|
12030
12033
|
}
|
|
12031
|
-
const children = await discoverAt(cli,
|
|
12032
|
-
return children.length > 0 ? children : [{ path:
|
|
12034
|
+
const children = await discoverAt(cli, path64, depth + 1, p);
|
|
12035
|
+
return children.length > 0 ? children : [{ path: path64, description }];
|
|
12033
12036
|
}
|
|
12034
12037
|
async function discoverAt(cli, parentPath, depth, p) {
|
|
12035
12038
|
if (depth > SAFETY_DEPTH) return [];
|
|
@@ -12177,9 +12180,9 @@ function logPath(cli) {
|
|
|
12177
12180
|
return join30(homedir16(), ".assist", `cli-discover-${safeName}.log`);
|
|
12178
12181
|
}
|
|
12179
12182
|
function readCache(cli) {
|
|
12180
|
-
const
|
|
12181
|
-
if (!existsSync29(
|
|
12182
|
-
return readFileSync25(
|
|
12183
|
+
const path64 = logPath(cli);
|
|
12184
|
+
if (!existsSync29(path64)) return void 0;
|
|
12185
|
+
return readFileSync25(path64, "utf8");
|
|
12183
12186
|
}
|
|
12184
12187
|
function writeCache(cli, output) {
|
|
12185
12188
|
const dir = join30(homedir16(), ".assist");
|
|
@@ -12351,9 +12354,9 @@ function sweepRestrictedDir(dir = getRestrictedDir()) {
|
|
|
12351
12354
|
}
|
|
12352
12355
|
const cutoff = Date.now() - STALE_AFTER_MS;
|
|
12353
12356
|
for (const entry of entries) {
|
|
12354
|
-
const
|
|
12357
|
+
const path64 = join32(dir, entry);
|
|
12355
12358
|
try {
|
|
12356
|
-
if (statSync3(
|
|
12359
|
+
if (statSync3(path64).mtimeMs < cutoff) unlinkSync7(path64);
|
|
12357
12360
|
} catch {
|
|
12358
12361
|
continue;
|
|
12359
12362
|
}
|
|
@@ -12363,10 +12366,10 @@ function sweepRestrictedDir(dir = getRestrictedDir()) {
|
|
|
12363
12366
|
// src/commands/codeComment/readPinState.ts
|
|
12364
12367
|
import { existsSync as existsSync30, readFileSync as readFileSync26 } from "fs";
|
|
12365
12368
|
function readPinState(pin) {
|
|
12366
|
-
const
|
|
12367
|
-
if (!existsSync30(
|
|
12369
|
+
const path64 = getPinStatePath(pin);
|
|
12370
|
+
if (!existsSync30(path64)) return void 0;
|
|
12368
12371
|
try {
|
|
12369
|
-
const state = JSON.parse(readFileSync26(
|
|
12372
|
+
const state = JSON.parse(readFileSync26(path64, "utf8"));
|
|
12370
12373
|
if (state.pin !== pin) return void 0;
|
|
12371
12374
|
return state;
|
|
12372
12375
|
} catch {
|
|
@@ -12515,6 +12518,65 @@ function registerCodeComment(parent) {
|
|
|
12515
12518
|
codeComment.command("confirm").description("Confirm a pin to insert its comment and clear the pin state").argument("<pin>", "Pin issued by 'code-comment set'").action(codeCommentConfirm);
|
|
12516
12519
|
}
|
|
12517
12520
|
|
|
12521
|
+
// src/commands/codexHook/index.ts
|
|
12522
|
+
var SUPPORTED_TOOLS2 = /* @__PURE__ */ new Set(["Bash", "PowerShell"]);
|
|
12523
|
+
function parseInput(raw) {
|
|
12524
|
+
try {
|
|
12525
|
+
const data = JSON.parse(raw);
|
|
12526
|
+
const command = data.tool_input?.command;
|
|
12527
|
+
if (typeof command !== "string" || !command.trim()) return void 0;
|
|
12528
|
+
if (!data.tool_name || !SUPPORTED_TOOLS2.has(data.tool_name))
|
|
12529
|
+
return void 0;
|
|
12530
|
+
return {
|
|
12531
|
+
event: data.hook_event_name ?? "PreToolUse",
|
|
12532
|
+
toolName: data.tool_name,
|
|
12533
|
+
command: command.trim()
|
|
12534
|
+
};
|
|
12535
|
+
} catch {
|
|
12536
|
+
return void 0;
|
|
12537
|
+
}
|
|
12538
|
+
}
|
|
12539
|
+
function preToolUseOutput(decision) {
|
|
12540
|
+
if (decision.permissionDecision === "allow") {
|
|
12541
|
+
return {
|
|
12542
|
+
hookSpecificOutput: {
|
|
12543
|
+
hookEventName: "PreToolUse",
|
|
12544
|
+
permissionDecision: "allow",
|
|
12545
|
+
permissionDecisionReason: decision.permissionDecisionReason
|
|
12546
|
+
}
|
|
12547
|
+
};
|
|
12548
|
+
}
|
|
12549
|
+
return { decision: "block", reason: decision.permissionDecisionReason };
|
|
12550
|
+
}
|
|
12551
|
+
function permissionRequestOutput(decision) {
|
|
12552
|
+
return {
|
|
12553
|
+
hookSpecificOutput: {
|
|
12554
|
+
hookEventName: "PermissionRequest",
|
|
12555
|
+
decision: {
|
|
12556
|
+
behavior: decision.permissionDecision === "allow" ? "allow" : "deny",
|
|
12557
|
+
message: decision.permissionDecisionReason
|
|
12558
|
+
}
|
|
12559
|
+
}
|
|
12560
|
+
};
|
|
12561
|
+
}
|
|
12562
|
+
async function codexHook() {
|
|
12563
|
+
const input = parseInput(await readStdin());
|
|
12564
|
+
if (!input) return;
|
|
12565
|
+
const decision = decideCommand(input.toolName, input.command);
|
|
12566
|
+
if (!decision) return;
|
|
12567
|
+
const output = input.event === "PermissionRequest" ? permissionRequestOutput(decision) : preToolUseOutput(decision);
|
|
12568
|
+
console.log(JSON.stringify(output));
|
|
12569
|
+
}
|
|
12570
|
+
|
|
12571
|
+
// src/commands/registerCodexHook.ts
|
|
12572
|
+
function registerCodexHook(program2) {
|
|
12573
|
+
program2.command("codex-hook").description(
|
|
12574
|
+
"Codex PreToolUse/PermissionRequest hook for auto-approving read-only CLI commands"
|
|
12575
|
+
).action(() => {
|
|
12576
|
+
codexHook();
|
|
12577
|
+
});
|
|
12578
|
+
}
|
|
12579
|
+
|
|
12518
12580
|
// src/commands/complexity/analyze.ts
|
|
12519
12581
|
import chalk119 from "chalk";
|
|
12520
12582
|
|
|
@@ -13132,8 +13194,8 @@ function stepIntoNested(container, key, nextKey) {
|
|
|
13132
13194
|
}
|
|
13133
13195
|
return ensureObject(container, resolved);
|
|
13134
13196
|
}
|
|
13135
|
-
function setNestedValue(obj,
|
|
13136
|
-
const keys =
|
|
13197
|
+
function setNestedValue(obj, path64, value) {
|
|
13198
|
+
const keys = path64.split(".");
|
|
13137
13199
|
const result = { ...obj };
|
|
13138
13200
|
let current = result;
|
|
13139
13201
|
for (let i = 0; i < keys.length - 1; i++) {
|
|
@@ -13213,9 +13275,9 @@ function isTraversable(value) {
|
|
|
13213
13275
|
function stepInto(current, key) {
|
|
13214
13276
|
return isTraversable(current) ? current[key] : void 0;
|
|
13215
13277
|
}
|
|
13216
|
-
function getNestedValue(obj,
|
|
13278
|
+
function getNestedValue(obj, path64) {
|
|
13217
13279
|
let current = obj;
|
|
13218
|
-
for (const key of
|
|
13280
|
+
for (const key of path64.split(".")) current = stepInto(current, key);
|
|
13219
13281
|
return current;
|
|
13220
13282
|
}
|
|
13221
13283
|
|
|
@@ -15801,9 +15863,9 @@ function parseRscRows(flight) {
|
|
|
15801
15863
|
}
|
|
15802
15864
|
function makeRscResolver(rows) {
|
|
15803
15865
|
return (ref) => {
|
|
15804
|
-
const [id, ...
|
|
15866
|
+
const [id, ...path64] = ref.slice(1).replace(/^[L@]/, "").split(":");
|
|
15805
15867
|
let v = rows[id];
|
|
15806
|
-
for (const key of
|
|
15868
|
+
for (const key of path64) {
|
|
15807
15869
|
if (v == null || typeof v !== "object") return void 0;
|
|
15808
15870
|
v = v[key];
|
|
15809
15871
|
}
|
|
@@ -16450,15 +16512,15 @@ function postComment(vars) {
|
|
|
16450
16512
|
const stdout = startLine === void 0 ? runGhGraphql(MUTATION_SINGLE, base) : runGhGraphql(MUTATION_MULTI, { ...base, startLine });
|
|
16451
16513
|
assertThreadCreated(stdout);
|
|
16452
16514
|
}
|
|
16453
|
-
function comment2(
|
|
16515
|
+
function comment2(path64, line, body, startLine) {
|
|
16454
16516
|
validateBody(body);
|
|
16455
16517
|
validateLine(line);
|
|
16456
16518
|
if (startLine !== void 0) validateLine(startLine);
|
|
16457
16519
|
try {
|
|
16458
16520
|
const prId = getCurrentPrNodeId();
|
|
16459
|
-
postComment({ prId, body, path:
|
|
16521
|
+
postComment({ prId, body, path: path64, line, startLine });
|
|
16460
16522
|
const range = startLine !== void 0 ? `${startLine}-${line}` : `${line}`;
|
|
16461
|
-
console.log(`Added review comment on ${
|
|
16523
|
+
console.log(`Added review comment on ${path64}:${range}`);
|
|
16462
16524
|
} catch (error) {
|
|
16463
16525
|
if (isGhNotInstalled(error)) {
|
|
16464
16526
|
console.error("Error: GitHub CLI (gh) is not installed.");
|
|
@@ -17319,8 +17381,8 @@ function registerPrs(program2) {
|
|
|
17319
17381
|
prsCommand.command("reply <comment-id> <body>").description("Reply to a comment thread without resolving it").action((commentId, body) => {
|
|
17320
17382
|
reply(Number.parseInt(commentId, 10), body);
|
|
17321
17383
|
});
|
|
17322
|
-
prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((
|
|
17323
|
-
comment2(
|
|
17384
|
+
prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((path64, line, body) => {
|
|
17385
|
+
comment2(path64, Number.parseInt(line, 10), body);
|
|
17324
17386
|
});
|
|
17325
17387
|
configHelp(prsCommand, prsConfigHelp);
|
|
17326
17388
|
}
|
|
@@ -17573,10 +17635,10 @@ function resolveOpSecret(reference) {
|
|
|
17573
17635
|
}
|
|
17574
17636
|
|
|
17575
17637
|
// src/commands/ravendb/ravenFetch.ts
|
|
17576
|
-
async function ravenFetch(connection,
|
|
17638
|
+
async function ravenFetch(connection, path64) {
|
|
17577
17639
|
const apiKey = resolveOpSecret(connection.apiKeyRef);
|
|
17578
17640
|
let accessToken = await getAccessToken(apiKey);
|
|
17579
|
-
const url = `${connection.url}${
|
|
17641
|
+
const url = `${connection.url}${path64}`;
|
|
17580
17642
|
const headers = {
|
|
17581
17643
|
Authorization: `Bearer ${accessToken}`,
|
|
17582
17644
|
"Content-Type": "application/json"
|
|
@@ -17680,16 +17742,16 @@ import chalk166 from "chalk";
|
|
|
17680
17742
|
// src/commands/ravendb/buildQueryPath.ts
|
|
17681
17743
|
function buildQueryPath(opts) {
|
|
17682
17744
|
const db = encodeURIComponent(opts.db);
|
|
17683
|
-
let
|
|
17745
|
+
let path64;
|
|
17684
17746
|
if (opts.collection) {
|
|
17685
|
-
|
|
17747
|
+
path64 = `/databases/${db}/indexes/dynamic/${encodeURIComponent(opts.collection)}?start=${opts.start}&pageSize=${opts.pageSize}&sort=${encodeURIComponent(opts.sort)}`;
|
|
17686
17748
|
} else {
|
|
17687
|
-
|
|
17749
|
+
path64 = `/databases/${db}/queries?start=${opts.start}&pageSize=${opts.pageSize}`;
|
|
17688
17750
|
}
|
|
17689
17751
|
if (opts.query) {
|
|
17690
|
-
|
|
17752
|
+
path64 += `&query=${encodeURIComponent(opts.query)}`;
|
|
17691
17753
|
}
|
|
17692
|
-
return
|
|
17754
|
+
return path64;
|
|
17693
17755
|
}
|
|
17694
17756
|
|
|
17695
17757
|
// src/commands/ravendb/fetchAllPages.ts
|
|
@@ -17698,7 +17760,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
17698
17760
|
let start3 = 0;
|
|
17699
17761
|
while (true) {
|
|
17700
17762
|
const effectivePageSize = opts.limit !== void 0 ? Math.min(opts.pageSize, opts.limit - allResults.length) : opts.pageSize;
|
|
17701
|
-
const
|
|
17763
|
+
const path64 = buildQueryPath({
|
|
17702
17764
|
db: connection.database,
|
|
17703
17765
|
collection: opts.collection,
|
|
17704
17766
|
start: start3,
|
|
@@ -17706,7 +17768,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
17706
17768
|
sort: opts.sort,
|
|
17707
17769
|
query: opts.query
|
|
17708
17770
|
});
|
|
17709
|
-
const data = await ravenFetch(connection,
|
|
17771
|
+
const data = await ravenFetch(connection, path64);
|
|
17710
17772
|
const results = data.Results ?? [];
|
|
17711
17773
|
const totalResults = data.TotalResults ?? 0;
|
|
17712
17774
|
if (results.length === 0) break;
|
|
@@ -20094,8 +20156,8 @@ async function handlePostSynthesis(synthesisPath, options2) {
|
|
|
20094
20156
|
// src/commands/review/prepareReviewDir.ts
|
|
20095
20157
|
import { existsSync as existsSync41, mkdirSync as mkdirSync17, unlinkSync as unlinkSync14, writeFileSync as writeFileSync34 } from "fs";
|
|
20096
20158
|
function clearReviewFiles(paths) {
|
|
20097
|
-
for (const
|
|
20098
|
-
if (existsSync41(
|
|
20159
|
+
for (const path64 of [paths.claudePath, paths.codexPath, paths.synthesisPath]) {
|
|
20160
|
+
if (existsSync41(path64)) unlinkSync14(path64);
|
|
20099
20161
|
}
|
|
20100
20162
|
}
|
|
20101
20163
|
function prepareReviewDir(paths, requestBody, force) {
|
|
@@ -21243,8 +21305,8 @@ import chalk187 from "chalk";
|
|
|
21243
21305
|
|
|
21244
21306
|
// src/commands/seq/fetchSeq.ts
|
|
21245
21307
|
import chalk184 from "chalk";
|
|
21246
|
-
async function fetchSeq(conn,
|
|
21247
|
-
const url = `${conn.url}${
|
|
21308
|
+
async function fetchSeq(conn, path64, params) {
|
|
21309
|
+
const url = `${conn.url}${path64}?${params}`;
|
|
21248
21310
|
const response = await fetch(url, {
|
|
21249
21311
|
headers: {
|
|
21250
21312
|
Accept: "application/json",
|
|
@@ -22731,9 +22793,9 @@ function findPortFile(roamDir) {
|
|
|
22731
22793
|
return void 0;
|
|
22732
22794
|
}
|
|
22733
22795
|
const candidates = entries.filter((name) => /^roam-local-api(-[^.]+)?\.port$/.test(name)).map((name) => {
|
|
22734
|
-
const
|
|
22796
|
+
const path64 = join60(roamDir, name);
|
|
22735
22797
|
try {
|
|
22736
|
-
return { path:
|
|
22798
|
+
return { path: path64, mtimeMs: statSync8(path64).mtimeMs };
|
|
22737
22799
|
} catch {
|
|
22738
22800
|
return void 0;
|
|
22739
22801
|
}
|
|
@@ -23152,11 +23214,11 @@ function findLinkIndex() {
|
|
|
23152
23214
|
function parseLinkArgs() {
|
|
23153
23215
|
const idx = findLinkIndex();
|
|
23154
23216
|
if (idx === -1) return null;
|
|
23155
|
-
const
|
|
23217
|
+
const path64 = process.argv[idx + 1];
|
|
23156
23218
|
const rest = process.argv.slice(idx + 2);
|
|
23157
23219
|
const { value: prefix2 } = extractOption(rest, "--prefix");
|
|
23158
23220
|
if (!prefix2) return null;
|
|
23159
|
-
return { path:
|
|
23221
|
+
return { path: path64, prefix: prefix2 };
|
|
23160
23222
|
}
|
|
23161
23223
|
function hasDuplicateLink(runList, linkPath) {
|
|
23162
23224
|
return runList.some(
|
|
@@ -24436,8 +24498,8 @@ async function seedRunningMsFromUsage(session, notify2) {
|
|
|
24436
24498
|
var DEBOUNCE_MS = 50;
|
|
24437
24499
|
function watchActivity(session, notify2) {
|
|
24438
24500
|
if (session.commandType !== "assist" || !session.cwd) return;
|
|
24439
|
-
const
|
|
24440
|
-
const dir = dirname29(
|
|
24501
|
+
const path64 = activityPath(session.id);
|
|
24502
|
+
const dir = dirname29(path64);
|
|
24441
24503
|
try {
|
|
24442
24504
|
mkdirSync24(dir, { recursive: true });
|
|
24443
24505
|
} catch {
|
|
@@ -24447,7 +24509,7 @@ function watchActivity(session, notify2) {
|
|
|
24447
24509
|
let timer = null;
|
|
24448
24510
|
const read = () => {
|
|
24449
24511
|
timer = null;
|
|
24450
|
-
const activity2 = readActivity(
|
|
24512
|
+
const activity2 = readActivity(path64);
|
|
24451
24513
|
if (!activity2) return;
|
|
24452
24514
|
session.activity = activity2;
|
|
24453
24515
|
if (activity2.claudeSessionId)
|
|
@@ -24457,11 +24519,11 @@ function watchActivity(session, notify2) {
|
|
|
24457
24519
|
notify2();
|
|
24458
24520
|
};
|
|
24459
24521
|
session.activityWatcher = watch(dir, (_event, filename) => {
|
|
24460
|
-
if (filename && !
|
|
24522
|
+
if (filename && !path64.endsWith(filename)) return;
|
|
24461
24523
|
if (timer) clearTimeout(timer);
|
|
24462
24524
|
timer = setTimeout(read, DEBOUNCE_MS);
|
|
24463
24525
|
});
|
|
24464
|
-
if (existsSync54(
|
|
24526
|
+
if (existsSync54(path64)) read();
|
|
24465
24527
|
}
|
|
24466
24528
|
function refreshActivity(session) {
|
|
24467
24529
|
if (session.commandType !== "assist" || !session.cwd) return;
|
|
@@ -25027,10 +25089,43 @@ async function defaultConnect() {
|
|
|
25027
25089
|
return connectToWindowsDaemon();
|
|
25028
25090
|
}
|
|
25029
25091
|
|
|
25092
|
+
// src/commands/sessions/daemon/hasPersistedWindowsSessions.ts
|
|
25093
|
+
import { existsSync as existsSync55, readFileSync as readFileSync48 } from "fs";
|
|
25094
|
+
import { posix } from "path";
|
|
25095
|
+
function hasPersistedWindowsSessions() {
|
|
25096
|
+
const sessionsFile = windowsSessionsFileFromWsl();
|
|
25097
|
+
if (!sessionsFile) return false;
|
|
25098
|
+
try {
|
|
25099
|
+
if (!existsSync55(sessionsFile)) return false;
|
|
25100
|
+
const data = JSON.parse(readFileSync48(sessionsFile, "utf8"));
|
|
25101
|
+
return Array.isArray(data) && data.length > 0;
|
|
25102
|
+
} catch (error) {
|
|
25103
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
25104
|
+
daemonLog(
|
|
25105
|
+
`windows proxy: could not read windows sessions.json: ${message}`
|
|
25106
|
+
);
|
|
25107
|
+
return false;
|
|
25108
|
+
}
|
|
25109
|
+
}
|
|
25110
|
+
function windowsSessionsFileFromWsl() {
|
|
25111
|
+
const projectsRootUnderWinHome = loadConfig().sessions?.windowsProjectsRoot;
|
|
25112
|
+
if (!projectsRootUnderWinHome) return null;
|
|
25113
|
+
const winHome = posix.dirname(posix.dirname(projectsRootUnderWinHome));
|
|
25114
|
+
return posix.join(winHome, ".assist", "sessions.json");
|
|
25115
|
+
}
|
|
25116
|
+
|
|
25030
25117
|
// src/commands/sessions/daemon/discoverWindowsSessions.ts
|
|
25031
25118
|
async function discoverWindowsSessions(conn) {
|
|
25032
|
-
if (conn.connected
|
|
25033
|
-
|
|
25119
|
+
if (conn.connected) return;
|
|
25120
|
+
if (await isWindowsDaemonRunning()) {
|
|
25121
|
+
daemonLog("windows proxy: discovering sessions on running windows daemon");
|
|
25122
|
+
} else if (hasPersistedWindowsSessions()) {
|
|
25123
|
+
daemonLog(
|
|
25124
|
+
"windows proxy: launching windows daemon to restore persisted sessions"
|
|
25125
|
+
);
|
|
25126
|
+
} else {
|
|
25127
|
+
return;
|
|
25128
|
+
}
|
|
25034
25129
|
try {
|
|
25035
25130
|
await conn.ensure();
|
|
25036
25131
|
} catch (error) {
|
|
@@ -25971,7 +26066,7 @@ function handleConnection(socket, manager) {
|
|
|
25971
26066
|
import { unlinkSync as unlinkSync20, writeFileSync as writeFileSync41 } from "fs";
|
|
25972
26067
|
|
|
25973
26068
|
// src/commands/sessions/daemon/startPidFileWatchdog.ts
|
|
25974
|
-
import { readFileSync as
|
|
26069
|
+
import { readFileSync as readFileSync49 } from "fs";
|
|
25975
26070
|
var WATCHDOG_INTERVAL_MS = 5e3;
|
|
25976
26071
|
function startPidFileWatchdog(onLost, intervalMs = WATCHDOG_INTERVAL_MS) {
|
|
25977
26072
|
const timer = setInterval(() => {
|
|
@@ -25982,7 +26077,7 @@ function startPidFileWatchdog(onLost, intervalMs = WATCHDOG_INTERVAL_MS) {
|
|
|
25982
26077
|
}
|
|
25983
26078
|
function ownsPidFile() {
|
|
25984
26079
|
try {
|
|
25985
|
-
return
|
|
26080
|
+
return readFileSync49(daemonPaths.pid, "utf8").trim() === String(process.pid);
|
|
25986
26081
|
} catch {
|
|
25987
26082
|
return false;
|
|
25988
26083
|
}
|
|
@@ -26421,7 +26516,7 @@ function buildLimitsSegment(rateLimits) {
|
|
|
26421
26516
|
}
|
|
26422
26517
|
|
|
26423
26518
|
// src/commands/readGitBranch.ts
|
|
26424
|
-
import { readFileSync as
|
|
26519
|
+
import { readFileSync as readFileSync51, statSync as statSync11 } from "fs";
|
|
26425
26520
|
import { isAbsolute as isAbsolute2, join as join66, resolve as resolve16 } from "path";
|
|
26426
26521
|
function resolveGitDir(cwd) {
|
|
26427
26522
|
const dotGit = join66(cwd, ".git");
|
|
@@ -26436,7 +26531,7 @@ function resolveGitDir(cwd) {
|
|
|
26436
26531
|
}
|
|
26437
26532
|
let contents;
|
|
26438
26533
|
try {
|
|
26439
|
-
contents =
|
|
26534
|
+
contents = readFileSync51(dotGit, "utf8");
|
|
26440
26535
|
} catch {
|
|
26441
26536
|
return null;
|
|
26442
26537
|
}
|
|
@@ -26454,7 +26549,7 @@ function readGitBranch(cwd) {
|
|
|
26454
26549
|
}
|
|
26455
26550
|
let head;
|
|
26456
26551
|
try {
|
|
26457
|
-
head =
|
|
26552
|
+
head = readFileSync51(join66(gitDir, "HEAD"), "utf8");
|
|
26458
26553
|
} catch {
|
|
26459
26554
|
return null;
|
|
26460
26555
|
}
|
|
@@ -26517,9 +26612,9 @@ async function statusLine() {
|
|
|
26517
26612
|
}
|
|
26518
26613
|
|
|
26519
26614
|
// src/commands/sync.ts
|
|
26520
|
-
import * as
|
|
26615
|
+
import * as fs44 from "fs";
|
|
26521
26616
|
import * as os3 from "os";
|
|
26522
|
-
import * as
|
|
26617
|
+
import * as path62 from "path";
|
|
26523
26618
|
import { fileURLToPath as fileURLToPath9 } from "url";
|
|
26524
26619
|
|
|
26525
26620
|
// src/commands/sync/syncClaudeMd.ts
|
|
@@ -26553,8 +26648,52 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
26553
26648
|
}
|
|
26554
26649
|
|
|
26555
26650
|
// src/commands/sync/syncCodex.ts
|
|
26651
|
+
import * as fs41 from "fs";
|
|
26652
|
+
import * as path59 from "path";
|
|
26653
|
+
|
|
26654
|
+
// src/commands/sync/syncCodexHooks.ts
|
|
26556
26655
|
import * as fs40 from "fs";
|
|
26557
26656
|
import * as path58 from "path";
|
|
26657
|
+
var BEGIN = "# >>> assist codex hooks (managed) \u2014 do not edit >>>";
|
|
26658
|
+
var END = "# <<< assist codex hooks (managed) <<<";
|
|
26659
|
+
function upsertManagedBlock(existing, body) {
|
|
26660
|
+
const block = `${BEGIN}
|
|
26661
|
+
${body.trim()}
|
|
26662
|
+
${END}`;
|
|
26663
|
+
const begin = existing.indexOf(BEGIN);
|
|
26664
|
+
if (begin === -1) {
|
|
26665
|
+
const base = existing.replace(/\s*$/, "");
|
|
26666
|
+
return base ? `${base}
|
|
26667
|
+
|
|
26668
|
+
${block}
|
|
26669
|
+
` : `${block}
|
|
26670
|
+
`;
|
|
26671
|
+
}
|
|
26672
|
+
const endMarker = existing.indexOf(END, begin);
|
|
26673
|
+
const after = endMarker === -1 ? existing.length : endMarker + END.length;
|
|
26674
|
+
const before = existing.slice(0, begin).replace(/\s*$/, "");
|
|
26675
|
+
const rest = existing.slice(after).replace(/^\s*/, "");
|
|
26676
|
+
const head = before ? `${before}
|
|
26677
|
+
|
|
26678
|
+
${block}` : block;
|
|
26679
|
+
return rest ? `${head}
|
|
26680
|
+
|
|
26681
|
+
${rest}
|
|
26682
|
+
` : `${head}
|
|
26683
|
+
`;
|
|
26684
|
+
}
|
|
26685
|
+
function syncCodexHooks(sourcePath) {
|
|
26686
|
+
const body = fs40.readFileSync(sourcePath, "utf8");
|
|
26687
|
+
const configPath = path58.join(harnesses.codex.homeDir, "config.toml");
|
|
26688
|
+
const existing = fs40.existsSync(configPath) ? fs40.readFileSync(configPath, "utf8") : "";
|
|
26689
|
+
fs40.mkdirSync(path58.dirname(configPath), { recursive: true });
|
|
26690
|
+
fs40.writeFileSync(configPath, upsertManagedBlock(existing, body));
|
|
26691
|
+
console.log(
|
|
26692
|
+
"Registered assist codex-hook in ~/.codex/config.toml (PreToolUse, PermissionRequest)"
|
|
26693
|
+
);
|
|
26694
|
+
}
|
|
26695
|
+
|
|
26696
|
+
// src/commands/sync/syncCodex.ts
|
|
26558
26697
|
function quoteYaml(value) {
|
|
26559
26698
|
return `"${value.replace(/\\/g, String.raw`\\`).replace(/"/g, String.raw`\"`)}"`;
|
|
26560
26699
|
}
|
|
@@ -26575,56 +26714,57 @@ description: ${quoteYaml(description)}
|
|
|
26575
26714
|
function syncCodex(claudeDir) {
|
|
26576
26715
|
if (!isHarnessAvailable("codex")) return;
|
|
26577
26716
|
const codex = harnesses.codex;
|
|
26578
|
-
const commandsSource =
|
|
26579
|
-
const files =
|
|
26717
|
+
const commandsSource = path59.join(claudeDir, "commands");
|
|
26718
|
+
const files = fs41.readdirSync(commandsSource);
|
|
26580
26719
|
for (const file of files) {
|
|
26581
26720
|
if (!file.endsWith(".md")) continue;
|
|
26582
26721
|
const name = file.replace(/\.md$/, "");
|
|
26583
|
-
const content =
|
|
26584
|
-
const target =
|
|
26585
|
-
|
|
26586
|
-
|
|
26587
|
-
}
|
|
26588
|
-
const agentsTarget =
|
|
26589
|
-
|
|
26590
|
-
|
|
26722
|
+
const content = fs41.readFileSync(path59.join(commandsSource, file), "utf8");
|
|
26723
|
+
const target = path59.join(codex.homeDir, codex.sync.commandDest(name));
|
|
26724
|
+
fs41.mkdirSync(path59.dirname(target), { recursive: true });
|
|
26725
|
+
fs41.writeFileSync(target, commandToSkill(name, content));
|
|
26726
|
+
}
|
|
26727
|
+
const agentsTarget = path59.join(codex.homeDir, codex.sync.agentsFile);
|
|
26728
|
+
fs41.mkdirSync(path59.dirname(agentsTarget), { recursive: true });
|
|
26729
|
+
fs41.copyFileSync(path59.join(claudeDir, "CLAUDE.md"), agentsTarget);
|
|
26730
|
+
syncCodexHooks(path59.join(claudeDir, "..", "codex", "config.toml"));
|
|
26591
26731
|
console.log(
|
|
26592
26732
|
`Synced ${files.length} skill(s) to ~/.codex/skills and CLAUDE.md to ~/.codex/AGENTS.md`
|
|
26593
26733
|
);
|
|
26594
26734
|
}
|
|
26595
26735
|
|
|
26596
26736
|
// src/commands/sync/syncDesign.ts
|
|
26597
|
-
import * as
|
|
26598
|
-
import * as
|
|
26737
|
+
import * as fs42 from "fs";
|
|
26738
|
+
import * as path60 from "path";
|
|
26599
26739
|
function syncDesign(claudeDir, targetBase) {
|
|
26600
|
-
const systemPromptSource =
|
|
26601
|
-
const systemPromptTarget =
|
|
26602
|
-
|
|
26740
|
+
const systemPromptSource = path60.join(claudeDir, "system-prompt.md");
|
|
26741
|
+
const systemPromptTarget = path60.join(targetBase, "system-prompt.md");
|
|
26742
|
+
fs42.copyFileSync(systemPromptSource, systemPromptTarget);
|
|
26603
26743
|
console.log("Copied system-prompt.md to ~/.claude/system-prompt.md");
|
|
26604
|
-
const skillsSource =
|
|
26605
|
-
const skillsTarget =
|
|
26606
|
-
|
|
26607
|
-
const files =
|
|
26744
|
+
const skillsSource = path60.join(claudeDir, "skills");
|
|
26745
|
+
const skillsTarget = path60.join(targetBase, "skills");
|
|
26746
|
+
fs42.mkdirSync(skillsTarget, { recursive: true });
|
|
26747
|
+
const files = fs42.readdirSync(skillsSource);
|
|
26608
26748
|
for (const file of files) {
|
|
26609
|
-
|
|
26610
|
-
|
|
26611
|
-
|
|
26749
|
+
fs42.copyFileSync(
|
|
26750
|
+
path60.join(skillsSource, file),
|
|
26751
|
+
path60.join(skillsTarget, file)
|
|
26612
26752
|
);
|
|
26613
26753
|
}
|
|
26614
26754
|
console.log(`Synced ${files.length} design skill(s) to ~/.claude/skills`);
|
|
26615
26755
|
}
|
|
26616
26756
|
|
|
26617
26757
|
// src/commands/sync/syncSettings.ts
|
|
26618
|
-
import * as
|
|
26619
|
-
import * as
|
|
26758
|
+
import * as fs43 from "fs";
|
|
26759
|
+
import * as path61 from "path";
|
|
26620
26760
|
import chalk200 from "chalk";
|
|
26621
26761
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
26622
|
-
const source =
|
|
26623
|
-
const target =
|
|
26624
|
-
const sourceContent =
|
|
26762
|
+
const source = path61.join(claudeDir, "settings.json");
|
|
26763
|
+
const target = path61.join(targetBase, "settings.json");
|
|
26764
|
+
const sourceContent = fs43.readFileSync(source, "utf8");
|
|
26625
26765
|
const sourceSettings = JSON.parse(sourceContent);
|
|
26626
|
-
const targetExists =
|
|
26627
|
-
const targetContent = targetExists ?
|
|
26766
|
+
const targetExists = fs43.existsSync(target);
|
|
26767
|
+
const targetContent = targetExists ? fs43.readFileSync(target, "utf8") : "";
|
|
26628
26768
|
const preservedUserSettings = targetExists ? JSON.parse(targetContent) : {};
|
|
26629
26769
|
const mergedContent = JSON.stringify(
|
|
26630
26770
|
{ ...preservedUserSettings, ...sourceSettings },
|
|
@@ -26653,18 +26793,18 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
26653
26793
|
}
|
|
26654
26794
|
}
|
|
26655
26795
|
}
|
|
26656
|
-
|
|
26796
|
+
fs43.writeFileSync(target, mergedContent);
|
|
26657
26797
|
console.log("Copied settings.json to ~/.claude/settings.json");
|
|
26658
26798
|
}
|
|
26659
26799
|
|
|
26660
26800
|
// src/commands/sync.ts
|
|
26661
26801
|
var __filename5 = fileURLToPath9(import.meta.url);
|
|
26662
|
-
var __dirname7 =
|
|
26802
|
+
var __dirname7 = path62.dirname(__filename5);
|
|
26663
26803
|
async function sync(options2) {
|
|
26664
26804
|
const config = loadConfig();
|
|
26665
26805
|
const yes = options2?.yes ?? config.sync.autoConfirm;
|
|
26666
|
-
const claudeDir =
|
|
26667
|
-
const targetBase =
|
|
26806
|
+
const claudeDir = path62.join(__dirname7, "..", "claude");
|
|
26807
|
+
const targetBase = path62.join(os3.homedir(), ".claude");
|
|
26668
26808
|
syncCommands(claudeDir, targetBase);
|
|
26669
26809
|
syncDesign(claudeDir, targetBase);
|
|
26670
26810
|
await syncSettings(claudeDir, targetBase, { yes });
|
|
@@ -26672,12 +26812,12 @@ async function sync(options2) {
|
|
|
26672
26812
|
syncCodex(claudeDir);
|
|
26673
26813
|
}
|
|
26674
26814
|
function syncCommands(claudeDir, targetBase) {
|
|
26675
|
-
const sourceDir =
|
|
26676
|
-
const targetDir =
|
|
26677
|
-
|
|
26678
|
-
const files =
|
|
26815
|
+
const sourceDir = path62.join(claudeDir, "commands");
|
|
26816
|
+
const targetDir = path62.join(targetBase, "commands");
|
|
26817
|
+
fs44.mkdirSync(targetDir, { recursive: true });
|
|
26818
|
+
const files = fs44.readdirSync(sourceDir);
|
|
26679
26819
|
for (const file of files) {
|
|
26680
|
-
|
|
26820
|
+
fs44.copyFileSync(path62.join(sourceDir, file), path62.join(targetDir, file));
|
|
26681
26821
|
console.log(`Copied ${file} to ${targetDir}`);
|
|
26682
26822
|
}
|
|
26683
26823
|
console.log(`Synced ${files.length} command(s) to ~/.claude/commands`);
|
|
@@ -26685,7 +26825,7 @@ function syncCommands(claudeDir, targetBase) {
|
|
|
26685
26825
|
|
|
26686
26826
|
// src/commands/update.ts
|
|
26687
26827
|
import { execSync as execSync57 } from "child_process";
|
|
26688
|
-
import * as
|
|
26828
|
+
import * as path63 from "path";
|
|
26689
26829
|
|
|
26690
26830
|
// src/commands/restartDaemonAfterUpdate.ts
|
|
26691
26831
|
async function restartDaemonAfterUpdate() {
|
|
@@ -26704,12 +26844,12 @@ async function restartDaemonAfterUpdate() {
|
|
|
26704
26844
|
// src/commands/update.ts
|
|
26705
26845
|
function isGlobalNpmInstall(dir) {
|
|
26706
26846
|
try {
|
|
26707
|
-
const resolved =
|
|
26708
|
-
if (resolved.split(
|
|
26847
|
+
const resolved = path63.resolve(dir);
|
|
26848
|
+
if (resolved.split(path63.sep).includes("node_modules")) {
|
|
26709
26849
|
return true;
|
|
26710
26850
|
}
|
|
26711
26851
|
const globalPrefix = execSync57("npm prefix -g", { stdio: "pipe" }).toString().trim();
|
|
26712
|
-
return resolved.toLowerCase().startsWith(
|
|
26852
|
+
return resolved.toLowerCase().startsWith(path63.resolve(globalPrefix).toLowerCase());
|
|
26713
26853
|
} catch {
|
|
26714
26854
|
return false;
|
|
26715
26855
|
}
|
|
@@ -26755,7 +26895,7 @@ function reportCliError(error) {
|
|
|
26755
26895
|
var program = new Command();
|
|
26756
26896
|
program.name("assist").description("CLI application").version(package_default.version).option("--no-open", "Do not open a browser on startup").action((options2) => web({ port: "3100", open: options2.open }));
|
|
26757
26897
|
var syncCommand = program.command("sync").description(
|
|
26758
|
-
"Copy command files to ~/.claude/commands; when codex is detected, also install commands as ~/.codex/skills/<name>/SKILL.md
|
|
26898
|
+
"Copy command files to ~/.claude/commands; when codex is detected, also install commands as ~/.codex/skills/<name>/SKILL.md, CLAUDE.md as ~/.codex/AGENTS.md, and register the assist codex-hook auto-approval hook in ~/.codex/config.toml"
|
|
26759
26899
|
).option("-y, --yes", "Overwrite settings.json without prompting").action((options2) => sync(options2));
|
|
26760
26900
|
configHelp(syncCommand, rootConfigHelp.sync);
|
|
26761
26901
|
program.command("init").description("Initialize VS Code and verify configurations").action(init5);
|
|
@@ -26782,6 +26922,7 @@ registerBackup(program);
|
|
|
26782
26922
|
registerDb(program);
|
|
26783
26923
|
registerCliHook(program);
|
|
26784
26924
|
registerCodeComment(program);
|
|
26925
|
+
registerCodexHook(program);
|
|
26785
26926
|
registerEditHook(program);
|
|
26786
26927
|
registerGithub(program);
|
|
26787
26928
|
registerHandover(program);
|