@staff0rd/assist 0.191.3 → 0.193.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 -0
- package/dist/commands/sessions/web/bundle.js +116 -0
- package/dist/index.js +529 -99
- package/package.json +6 -1
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Command } from "commander";
|
|
|
6
6
|
// package.json
|
|
7
7
|
var package_default = {
|
|
8
8
|
name: "@staff0rd/assist",
|
|
9
|
-
version: "0.
|
|
9
|
+
version: "0.193.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -49,10 +49,12 @@ var package_default = {
|
|
|
49
49
|
"is-wsl": "^3.1.0",
|
|
50
50
|
minimatch: "^10.1.1",
|
|
51
51
|
"node-notifier": "^10.0.1",
|
|
52
|
+
"node-pty": "^1.1.0",
|
|
52
53
|
semver: "^7.7.3",
|
|
53
54
|
"shell-quote": "^1.8.3",
|
|
54
55
|
"ts-morph": "^27.0.2",
|
|
55
56
|
typescript: "^5.9.3",
|
|
57
|
+
ws: "^8.20.0",
|
|
56
58
|
yaml: "^2.8.2",
|
|
57
59
|
zod: "^4.3.6"
|
|
58
60
|
},
|
|
@@ -70,7 +72,10 @@ var package_default = {
|
|
|
70
72
|
"@types/react-dom": "^19.2.3",
|
|
71
73
|
"@types/semver": "^7.7.1",
|
|
72
74
|
"@types/shell-quote": "^1.7.5",
|
|
75
|
+
"@types/ws": "^8.18.1",
|
|
73
76
|
"@vitest/coverage-v8": "^4.1.2",
|
|
77
|
+
"@xterm/addon-fit": "^0.11.0",
|
|
78
|
+
"@xterm/xterm": "^6.0.0",
|
|
74
79
|
esbuild: "^0.27.3",
|
|
75
80
|
jotai: "^2.18.0",
|
|
76
81
|
jscpd: "^4.0.5",
|
|
@@ -920,10 +925,10 @@ function writeSignal(event, data) {
|
|
|
920
925
|
|
|
921
926
|
// src/commands/backlog/readSignal.ts
|
|
922
927
|
function readSignal() {
|
|
923
|
-
const
|
|
924
|
-
if (!existsSync5(
|
|
928
|
+
const path52 = getSignalPath();
|
|
929
|
+
if (!existsSync5(path52)) return void 0;
|
|
925
930
|
try {
|
|
926
|
-
return JSON.parse(readFileSync5(
|
|
931
|
+
return JSON.parse(readFileSync5(path52, "utf-8"));
|
|
927
932
|
} catch {
|
|
928
933
|
return void 0;
|
|
929
934
|
}
|
|
@@ -976,10 +981,10 @@ import { stringify as stringifyYaml } from "yaml";
|
|
|
976
981
|
// src/shared/loadRawYaml.ts
|
|
977
982
|
import { existsSync as existsSync7, readFileSync as readFileSync6 } from "fs";
|
|
978
983
|
import { parse as parseYaml2 } from "yaml";
|
|
979
|
-
function loadRawYaml(
|
|
980
|
-
if (!existsSync7(
|
|
984
|
+
function loadRawYaml(path52) {
|
|
985
|
+
if (!existsSync7(path52)) return {};
|
|
981
986
|
try {
|
|
982
|
-
const content = readFileSync6(
|
|
987
|
+
const content = readFileSync6(path52, "utf-8");
|
|
983
988
|
return parseYaml2(content) || {};
|
|
984
989
|
} catch {
|
|
985
990
|
return {};
|
|
@@ -1573,20 +1578,20 @@ function createBundleHandler(importMetaUrl, bundlePath) {
|
|
|
1573
1578
|
res.end(cache);
|
|
1574
1579
|
};
|
|
1575
1580
|
}
|
|
1576
|
-
function createHtmlHandler(
|
|
1581
|
+
function createHtmlHandler(getHtml4) {
|
|
1577
1582
|
return (_req, res) => {
|
|
1578
1583
|
res.writeHead(200, { "Content-Type": "text/html" });
|
|
1579
|
-
res.end(
|
|
1584
|
+
res.end(getHtml4());
|
|
1580
1585
|
};
|
|
1581
1586
|
}
|
|
1582
1587
|
function parseRoute(req, port) {
|
|
1583
1588
|
const url = new URL(req.url ?? "/", `http://localhost:${port}`);
|
|
1584
1589
|
return { method: req.method ?? "GET", pathname: url.pathname };
|
|
1585
1590
|
}
|
|
1586
|
-
function createRouteHandler(
|
|
1591
|
+
function createRouteHandler(routes4) {
|
|
1587
1592
|
return async (req, res, port) => {
|
|
1588
1593
|
const { method, pathname } = parseRoute(req, port);
|
|
1589
|
-
const handler =
|
|
1594
|
+
const handler = routes4[`${method} ${pathname}`];
|
|
1590
1595
|
if (handler) {
|
|
1591
1596
|
await handler(req, res);
|
|
1592
1597
|
return;
|
|
@@ -1605,6 +1610,25 @@ function startWebServer(label2, port, handler) {
|
|
|
1605
1610
|
console.log(chalk16.dim("Press Ctrl+C to stop"));
|
|
1606
1611
|
exec(`open ${url}`);
|
|
1607
1612
|
});
|
|
1613
|
+
return server;
|
|
1614
|
+
}
|
|
1615
|
+
|
|
1616
|
+
// src/shared/createFallbackHandler.ts
|
|
1617
|
+
function createFallbackHandler(routes4, htmlHandler3, extra) {
|
|
1618
|
+
const baseHandler = createRouteHandler(routes4);
|
|
1619
|
+
return async (req, res, port) => {
|
|
1620
|
+
const { method, pathname } = parseRoute(req, port);
|
|
1621
|
+
if (extra && await extra(req, res, pathname)) return;
|
|
1622
|
+
if (routes4[`${method} ${pathname}`]) {
|
|
1623
|
+
await baseHandler(req, res, port);
|
|
1624
|
+
return;
|
|
1625
|
+
}
|
|
1626
|
+
if (method === "GET" && !pathname.startsWith("/api/")) {
|
|
1627
|
+
await htmlHandler3(req, res);
|
|
1628
|
+
return;
|
|
1629
|
+
}
|
|
1630
|
+
await baseHandler(req, res, port);
|
|
1631
|
+
};
|
|
1608
1632
|
}
|
|
1609
1633
|
|
|
1610
1634
|
// src/commands/backlog/web/getHtml.ts
|
|
@@ -1711,8 +1735,9 @@ async function patchItemStatus(req, res, id) {
|
|
|
1711
1735
|
}
|
|
1712
1736
|
|
|
1713
1737
|
// src/commands/backlog/web/handleRequest.ts
|
|
1738
|
+
var htmlHandler = createHtmlHandler(getHtml);
|
|
1714
1739
|
var routes = {
|
|
1715
|
-
"GET /":
|
|
1740
|
+
"GET /": htmlHandler,
|
|
1716
1741
|
"GET /bundle.js": createBundleHandler(
|
|
1717
1742
|
import.meta.url,
|
|
1718
1743
|
"commands/backlog/web/bundle.js"
|
|
@@ -1726,8 +1751,6 @@ var itemRoutes = {
|
|
|
1726
1751
|
PATCH: (req, res, id) => patchItemStatus(req, res, id),
|
|
1727
1752
|
DELETE: (_req, res, id) => deleteItem2(res, id)
|
|
1728
1753
|
};
|
|
1729
|
-
var serveHtml = createHtmlHandler(getHtml);
|
|
1730
|
-
var baseHandler = createRouteHandler(routes);
|
|
1731
1754
|
async function handleItemRoute(req, res, pathname) {
|
|
1732
1755
|
const match = pathname.match(/^\/api\/items\/(\d+)$/);
|
|
1733
1756
|
if (!match) return false;
|
|
@@ -1736,21 +1759,11 @@ async function handleItemRoute(req, res, pathname) {
|
|
|
1736
1759
|
await handler(req, res, Number.parseInt(match[1], 10));
|
|
1737
1760
|
return true;
|
|
1738
1761
|
}
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
if (routes[`${method} ${pathname}`]) {
|
|
1745
|
-
await baseHandler(req, res, port);
|
|
1746
|
-
return;
|
|
1747
|
-
}
|
|
1748
|
-
if (method === "GET" && !pathname.startsWith("/api/")) {
|
|
1749
|
-
await serveHtml(req, res);
|
|
1750
|
-
return;
|
|
1751
|
-
}
|
|
1752
|
-
await baseHandler(req, res, port);
|
|
1753
|
-
}
|
|
1762
|
+
var handleRequest = createFallbackHandler(
|
|
1763
|
+
routes,
|
|
1764
|
+
htmlHandler,
|
|
1765
|
+
handleItemRoute
|
|
1766
|
+
);
|
|
1754
1767
|
|
|
1755
1768
|
// src/commands/backlog/web/index.ts
|
|
1756
1769
|
async function web(options2) {
|
|
@@ -4942,9 +4955,9 @@ var __dirname4 = dirname15(__filename2);
|
|
|
4942
4955
|
function packageRoot() {
|
|
4943
4956
|
return __dirname4;
|
|
4944
4957
|
}
|
|
4945
|
-
function readLines(
|
|
4946
|
-
if (!existsSync20(
|
|
4947
|
-
return readFileSync16(
|
|
4958
|
+
function readLines(path52) {
|
|
4959
|
+
if (!existsSync20(path52)) return [];
|
|
4960
|
+
return readFileSync16(path52, "utf-8").split("\n").filter((line) => line.trim() !== "");
|
|
4948
4961
|
}
|
|
4949
4962
|
var cachedReads;
|
|
4950
4963
|
var cachedWrites;
|
|
@@ -5377,14 +5390,14 @@ function showProgress(p, label2) {
|
|
|
5377
5390
|
const pct = Math.round(p.done / p.total * 100);
|
|
5378
5391
|
process.stderr.write(`\r\x1B[K[${pct}%] Scanning ${label2}...`);
|
|
5379
5392
|
}
|
|
5380
|
-
async function resolveCommand(cli,
|
|
5381
|
-
showProgress(p,
|
|
5382
|
-
const subHelp = await runHelp([cli, ...
|
|
5393
|
+
async function resolveCommand(cli, path52, description, depth, p) {
|
|
5394
|
+
showProgress(p, path52.join(" "));
|
|
5395
|
+
const subHelp = await runHelp([cli, ...path52]);
|
|
5383
5396
|
if (!subHelp || !hasSubcommands(subHelp)) {
|
|
5384
|
-
return [{ path:
|
|
5397
|
+
return [{ path: path52, description }];
|
|
5385
5398
|
}
|
|
5386
|
-
const children = await discoverAt(cli,
|
|
5387
|
-
return children.length > 0 ? children : [{ path:
|
|
5399
|
+
const children = await discoverAt(cli, path52, depth + 1, p);
|
|
5400
|
+
return children.length > 0 ? children : [{ path: path52, description }];
|
|
5388
5401
|
}
|
|
5389
5402
|
async function discoverAt(cli, parentPath, depth, p) {
|
|
5390
5403
|
if (depth > SAFETY_DEPTH) return [];
|
|
@@ -5532,9 +5545,9 @@ function logPath(cli) {
|
|
|
5532
5545
|
return join19(homedir4(), ".assist", `cli-discover-${safeName}.log`);
|
|
5533
5546
|
}
|
|
5534
5547
|
function readCache(cli) {
|
|
5535
|
-
const
|
|
5536
|
-
if (!existsSync22(
|
|
5537
|
-
return readFileSync18(
|
|
5548
|
+
const path52 = logPath(cli);
|
|
5549
|
+
if (!existsSync22(path52)) return void 0;
|
|
5550
|
+
return readFileSync18(path52, "utf-8");
|
|
5538
5551
|
}
|
|
5539
5552
|
function writeCache(cli, output) {
|
|
5540
5553
|
const dir = join19(homedir4(), ".assist");
|
|
@@ -6176,8 +6189,8 @@ function stepIntoNested(container, key, nextKey) {
|
|
|
6176
6189
|
}
|
|
6177
6190
|
return ensureObject(container, resolved);
|
|
6178
6191
|
}
|
|
6179
|
-
function setNestedValue(obj,
|
|
6180
|
-
const keys =
|
|
6192
|
+
function setNestedValue(obj, path52, value) {
|
|
6193
|
+
const keys = path52.split(".");
|
|
6181
6194
|
const result = { ...obj };
|
|
6182
6195
|
let current = result;
|
|
6183
6196
|
for (let i = 0; i < keys.length - 1; i++) {
|
|
@@ -6257,9 +6270,9 @@ function isTraversable(value) {
|
|
|
6257
6270
|
function stepInto(current, key) {
|
|
6258
6271
|
return isTraversable(current) ? current[key] : void 0;
|
|
6259
6272
|
}
|
|
6260
|
-
function getNestedValue(obj,
|
|
6273
|
+
function getNestedValue(obj, path52) {
|
|
6261
6274
|
let current = obj;
|
|
6262
|
-
for (const key of
|
|
6275
|
+
for (const key of path52.split(".")) current = stepInto(current, key);
|
|
6263
6276
|
return current;
|
|
6264
6277
|
}
|
|
6265
6278
|
|
|
@@ -7600,10 +7613,10 @@ function getStorePath(filename) {
|
|
|
7600
7613
|
return join26(getStoreDir(), filename);
|
|
7601
7614
|
}
|
|
7602
7615
|
function loadJson(filename) {
|
|
7603
|
-
const
|
|
7604
|
-
if (existsSync29(
|
|
7616
|
+
const path52 = getStorePath(filename);
|
|
7617
|
+
if (existsSync29(path52)) {
|
|
7605
7618
|
try {
|
|
7606
|
-
return JSON.parse(readFileSync25(
|
|
7619
|
+
return JSON.parse(readFileSync25(path52, "utf-8"));
|
|
7607
7620
|
} catch {
|
|
7608
7621
|
return {};
|
|
7609
7622
|
}
|
|
@@ -7996,7 +8009,7 @@ function validateLine(line) {
|
|
|
7996
8009
|
process.exit(1);
|
|
7997
8010
|
}
|
|
7998
8011
|
}
|
|
7999
|
-
function comment2(
|
|
8012
|
+
function comment2(path52, line, body) {
|
|
8000
8013
|
validateBody(body);
|
|
8001
8014
|
validateLine(line);
|
|
8002
8015
|
try {
|
|
@@ -8016,7 +8029,7 @@ function comment2(path50, line, body) {
|
|
|
8016
8029
|
"-f",
|
|
8017
8030
|
`body=${body}`,
|
|
8018
8031
|
"-f",
|
|
8019
|
-
`path=${
|
|
8032
|
+
`path=${path52}`,
|
|
8020
8033
|
"-F",
|
|
8021
8034
|
`line=${line}`
|
|
8022
8035
|
],
|
|
@@ -8025,7 +8038,7 @@ function comment2(path50, line, body) {
|
|
|
8025
8038
|
if (result.status !== 0) {
|
|
8026
8039
|
throw new Error(result.stderr || result.stdout);
|
|
8027
8040
|
}
|
|
8028
|
-
console.log(`Added review comment on ${
|
|
8041
|
+
console.log(`Added review comment on ${path52}:${line}`);
|
|
8029
8042
|
} finally {
|
|
8030
8043
|
unlinkSync6(queryFile);
|
|
8031
8044
|
}
|
|
@@ -8524,8 +8537,8 @@ function registerPrs(program2) {
|
|
|
8524
8537
|
prsCommand.command("wontfix <comment-id> <reason>").description("Reply with reason and resolve thread").action((commentId, reason) => {
|
|
8525
8538
|
wontfix(Number.parseInt(commentId, 10), reason);
|
|
8526
8539
|
});
|
|
8527
|
-
prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((
|
|
8528
|
-
comment2(
|
|
8540
|
+
prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((path52, line, body) => {
|
|
8541
|
+
comment2(path52, Number.parseInt(line, 10), body);
|
|
8529
8542
|
});
|
|
8530
8543
|
}
|
|
8531
8544
|
|
|
@@ -8777,10 +8790,10 @@ function resolveOpSecret(reference) {
|
|
|
8777
8790
|
}
|
|
8778
8791
|
|
|
8779
8792
|
// src/commands/ravendb/ravenFetch.ts
|
|
8780
|
-
async function ravenFetch(connection,
|
|
8793
|
+
async function ravenFetch(connection, path52) {
|
|
8781
8794
|
const apiKey = resolveOpSecret(connection.apiKeyRef);
|
|
8782
8795
|
let accessToken = await getAccessToken(apiKey);
|
|
8783
|
-
const url = `${connection.url}${
|
|
8796
|
+
const url = `${connection.url}${path52}`;
|
|
8784
8797
|
const headers = {
|
|
8785
8798
|
Authorization: `Bearer ${accessToken}`,
|
|
8786
8799
|
"Content-Type": "application/json"
|
|
@@ -8870,16 +8883,16 @@ import chalk111 from "chalk";
|
|
|
8870
8883
|
// src/commands/ravendb/buildQueryPath.ts
|
|
8871
8884
|
function buildQueryPath(opts) {
|
|
8872
8885
|
const db = encodeURIComponent(opts.db);
|
|
8873
|
-
let
|
|
8886
|
+
let path52;
|
|
8874
8887
|
if (opts.collection) {
|
|
8875
|
-
|
|
8888
|
+
path52 = `/databases/${db}/indexes/dynamic/${encodeURIComponent(opts.collection)}?start=${opts.start}&pageSize=${opts.pageSize}&sort=${encodeURIComponent(opts.sort)}`;
|
|
8876
8889
|
} else {
|
|
8877
|
-
|
|
8890
|
+
path52 = `/databases/${db}/queries?start=${opts.start}&pageSize=${opts.pageSize}`;
|
|
8878
8891
|
}
|
|
8879
8892
|
if (opts.query) {
|
|
8880
|
-
|
|
8893
|
+
path52 += `&query=${encodeURIComponent(opts.query)}`;
|
|
8881
8894
|
}
|
|
8882
|
-
return
|
|
8895
|
+
return path52;
|
|
8883
8896
|
}
|
|
8884
8897
|
|
|
8885
8898
|
// src/commands/ravendb/fetchAllPages.ts
|
|
@@ -8888,7 +8901,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
8888
8901
|
let start3 = 0;
|
|
8889
8902
|
while (true) {
|
|
8890
8903
|
const effectivePageSize = opts.limit !== void 0 ? Math.min(opts.pageSize, opts.limit - allResults.length) : opts.pageSize;
|
|
8891
|
-
const
|
|
8904
|
+
const path52 = buildQueryPath({
|
|
8892
8905
|
db: connection.database,
|
|
8893
8906
|
collection: opts.collection,
|
|
8894
8907
|
start: start3,
|
|
@@ -8896,7 +8909,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
8896
8909
|
sort: opts.sort,
|
|
8897
8910
|
query: opts.query
|
|
8898
8911
|
});
|
|
8899
|
-
const data = await ravenFetch(connection,
|
|
8912
|
+
const data = await ravenFetch(connection, path52);
|
|
8900
8913
|
const results = data.Results ?? [];
|
|
8901
8914
|
const totalResults = data.TotalResults ?? 0;
|
|
8902
8915
|
if (results.length === 0) break;
|
|
@@ -10067,8 +10080,8 @@ function findRootParent(file, importedBy, visited) {
|
|
|
10067
10080
|
function clusterFiles(graph) {
|
|
10068
10081
|
const clusters = /* @__PURE__ */ new Map();
|
|
10069
10082
|
for (const file of graph.files) {
|
|
10070
|
-
const
|
|
10071
|
-
if (
|
|
10083
|
+
const basename8 = path39.basename(file, path39.extname(file));
|
|
10084
|
+
if (basename8 === "index") continue;
|
|
10072
10085
|
const importers = graph.importedBy.get(file);
|
|
10073
10086
|
if (!importers || importers.size !== 1) continue;
|
|
10074
10087
|
const parent = [...importers][0];
|
|
@@ -10518,8 +10531,8 @@ import chalk128 from "chalk";
|
|
|
10518
10531
|
|
|
10519
10532
|
// src/commands/seq/fetchSeq.ts
|
|
10520
10533
|
import chalk125 from "chalk";
|
|
10521
|
-
async function fetchSeq(conn,
|
|
10522
|
-
const url = `${conn.url}${
|
|
10534
|
+
async function fetchSeq(conn, path52, params) {
|
|
10535
|
+
const url = `${conn.url}${path52}?${params}`;
|
|
10523
10536
|
const response = await fetch(url, {
|
|
10524
10537
|
headers: {
|
|
10525
10538
|
Accept: "application/json",
|
|
@@ -12123,11 +12136,11 @@ function findLinkIndex() {
|
|
|
12123
12136
|
function parseLinkArgs() {
|
|
12124
12137
|
const idx = findLinkIndex();
|
|
12125
12138
|
if (idx === -1) return null;
|
|
12126
|
-
const
|
|
12139
|
+
const path52 = process.argv[idx + 1];
|
|
12127
12140
|
const rest = process.argv.slice(idx + 2);
|
|
12128
12141
|
const { value: prefix2 } = extractOption(rest, "--prefix");
|
|
12129
12142
|
if (!prefix2) return null;
|
|
12130
|
-
return { path:
|
|
12143
|
+
return { path: path52, prefix: prefix2 };
|
|
12131
12144
|
}
|
|
12132
12145
|
function hasDuplicateLink(runList, linkPath) {
|
|
12133
12146
|
return runList.some(
|
|
@@ -12373,6 +12386,422 @@ function screenshot(processName) {
|
|
|
12373
12386
|
}
|
|
12374
12387
|
}
|
|
12375
12388
|
|
|
12389
|
+
// src/commands/sessions/web/index.ts
|
|
12390
|
+
import { WebSocketServer } from "ws";
|
|
12391
|
+
|
|
12392
|
+
// src/commands/sessions/web/handleRequest.ts
|
|
12393
|
+
import { readFileSync as readFileSync34 } from "fs";
|
|
12394
|
+
import { createRequire as createRequire2 } from "module";
|
|
12395
|
+
|
|
12396
|
+
// src/commands/sessions/web/getHtml.ts
|
|
12397
|
+
function getHtml3() {
|
|
12398
|
+
return `<!DOCTYPE html>
|
|
12399
|
+
<html lang="en">
|
|
12400
|
+
<head>
|
|
12401
|
+
<meta charset="UTF-8">
|
|
12402
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
12403
|
+
<title>Sessions</title>
|
|
12404
|
+
<link rel="stylesheet" href="/xterm.css">
|
|
12405
|
+
<style>
|
|
12406
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
12407
|
+
html, body, #app { width: 100%; height: 100%; overflow: hidden; background: #1e1e1e; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; }
|
|
12408
|
+
::-webkit-scrollbar { width: 6px; }
|
|
12409
|
+
::-webkit-scrollbar-track { background: transparent; }
|
|
12410
|
+
::-webkit-scrollbar-thumb { background: #555; border-radius: 3px; }
|
|
12411
|
+
::-webkit-scrollbar-thumb:hover { background: #777; }
|
|
12412
|
+
</style>
|
|
12413
|
+
</head>
|
|
12414
|
+
<body>
|
|
12415
|
+
<div id="app"></div>
|
|
12416
|
+
<script src="/bundle.js"></script>
|
|
12417
|
+
</body>
|
|
12418
|
+
</html>`;
|
|
12419
|
+
}
|
|
12420
|
+
|
|
12421
|
+
// src/commands/sessions/web/handleRequest.ts
|
|
12422
|
+
var require3 = createRequire2(import.meta.url);
|
|
12423
|
+
function createCssHandler(packageEntry) {
|
|
12424
|
+
let cache;
|
|
12425
|
+
return (_req, res) => {
|
|
12426
|
+
if (!cache) {
|
|
12427
|
+
const resolved = require3.resolve(packageEntry);
|
|
12428
|
+
cache = readFileSync34(resolved, "utf-8");
|
|
12429
|
+
}
|
|
12430
|
+
res.writeHead(200, { "Content-Type": "text/css" });
|
|
12431
|
+
res.end(cache);
|
|
12432
|
+
};
|
|
12433
|
+
}
|
|
12434
|
+
var htmlHandler2 = createHtmlHandler(getHtml3);
|
|
12435
|
+
var routes3 = {
|
|
12436
|
+
"GET /": htmlHandler2,
|
|
12437
|
+
"GET /bundle.js": createBundleHandler(
|
|
12438
|
+
import.meta.url,
|
|
12439
|
+
"commands/sessions/web/bundle.js"
|
|
12440
|
+
),
|
|
12441
|
+
"GET /xterm.css": createCssHandler("@xterm/xterm/css/xterm.css")
|
|
12442
|
+
};
|
|
12443
|
+
var handleRequest3 = createFallbackHandler(routes3, htmlHandler2);
|
|
12444
|
+
|
|
12445
|
+
// src/commands/sessions/web/handleSocket.ts
|
|
12446
|
+
function handleSocket(ws, manager) {
|
|
12447
|
+
manager.addClient(ws);
|
|
12448
|
+
ws.on("message", (msg) => {
|
|
12449
|
+
let data;
|
|
12450
|
+
try {
|
|
12451
|
+
data = JSON.parse(msg.toString());
|
|
12452
|
+
} catch {
|
|
12453
|
+
return;
|
|
12454
|
+
}
|
|
12455
|
+
switch (data.type) {
|
|
12456
|
+
case "create": {
|
|
12457
|
+
const id = manager.spawn(data.prompt);
|
|
12458
|
+
ws.send(JSON.stringify({ type: "created", sessionId: id }));
|
|
12459
|
+
break;
|
|
12460
|
+
}
|
|
12461
|
+
case "input":
|
|
12462
|
+
manager.writeToSession(data.sessionId, data.data);
|
|
12463
|
+
break;
|
|
12464
|
+
case "resize":
|
|
12465
|
+
manager.resizeSession(
|
|
12466
|
+
data.sessionId,
|
|
12467
|
+
data.cols,
|
|
12468
|
+
data.rows
|
|
12469
|
+
);
|
|
12470
|
+
break;
|
|
12471
|
+
case "resume": {
|
|
12472
|
+
const id = manager.resume(
|
|
12473
|
+
data.sessionId,
|
|
12474
|
+
data.cwd,
|
|
12475
|
+
data.name
|
|
12476
|
+
);
|
|
12477
|
+
ws.send(JSON.stringify({ type: "created", sessionId: id }));
|
|
12478
|
+
break;
|
|
12479
|
+
}
|
|
12480
|
+
case "dismiss":
|
|
12481
|
+
manager.dismissSession(data.sessionId);
|
|
12482
|
+
break;
|
|
12483
|
+
case "history":
|
|
12484
|
+
manager.getHistory().then((history) => {
|
|
12485
|
+
ws.send(JSON.stringify({ type: "history", sessions: history }));
|
|
12486
|
+
});
|
|
12487
|
+
break;
|
|
12488
|
+
}
|
|
12489
|
+
});
|
|
12490
|
+
ws.on("close", () => {
|
|
12491
|
+
manager.removeClient(ws);
|
|
12492
|
+
});
|
|
12493
|
+
}
|
|
12494
|
+
|
|
12495
|
+
// src/commands/sessions/web/spawnClaude.ts
|
|
12496
|
+
import * as pty from "node-pty";
|
|
12497
|
+
function spawnClaude2(opts = {}) {
|
|
12498
|
+
const shell = process.platform === "win32" ? "cmd.exe" : process.env.SHELL ?? "bash";
|
|
12499
|
+
const args = buildArgs(opts);
|
|
12500
|
+
return pty.spawn(shell, args, {
|
|
12501
|
+
name: "xterm-256color",
|
|
12502
|
+
cols: 120,
|
|
12503
|
+
rows: 30,
|
|
12504
|
+
cwd: opts.cwd ?? process.cwd(),
|
|
12505
|
+
env: { ...process.env }
|
|
12506
|
+
});
|
|
12507
|
+
}
|
|
12508
|
+
function buildArgs(opts) {
|
|
12509
|
+
const claudeArgs = opts.resumeSessionId ? ["claude", "--resume", opts.resumeSessionId] : opts.prompt ? ["claude", opts.prompt] : ["claude"];
|
|
12510
|
+
if (process.platform === "win32") {
|
|
12511
|
+
return ["/c", ...claudeArgs];
|
|
12512
|
+
}
|
|
12513
|
+
return ["-c", `exec ${claudeArgs.map(shellEscape).join(" ")}`];
|
|
12514
|
+
}
|
|
12515
|
+
function shellEscape(s) {
|
|
12516
|
+
return `'${s.replace(/'/g, "'\\''")}'`;
|
|
12517
|
+
}
|
|
12518
|
+
|
|
12519
|
+
// src/commands/sessions/web/createSession.ts
|
|
12520
|
+
function createSession(id, prompt) {
|
|
12521
|
+
return {
|
|
12522
|
+
id,
|
|
12523
|
+
name: prompt?.slice(0, 40) || `Session ${id}`,
|
|
12524
|
+
status: "running",
|
|
12525
|
+
startedAt: Date.now(),
|
|
12526
|
+
pty: spawnClaude2({ prompt }),
|
|
12527
|
+
scrollback: "",
|
|
12528
|
+
idleTimer: null,
|
|
12529
|
+
lastResizeAt: 0
|
|
12530
|
+
};
|
|
12531
|
+
}
|
|
12532
|
+
function resumeSession(id, sessionId, cwd, name) {
|
|
12533
|
+
return {
|
|
12534
|
+
id,
|
|
12535
|
+
name: name ? `${name.slice(0, 36)} (R)` : `Resume ${sessionId.slice(0, 8)}`,
|
|
12536
|
+
status: "running",
|
|
12537
|
+
startedAt: Date.now(),
|
|
12538
|
+
pty: spawnClaude2({ resumeSessionId: sessionId, cwd }),
|
|
12539
|
+
scrollback: "",
|
|
12540
|
+
idleTimer: null,
|
|
12541
|
+
lastResizeAt: 0
|
|
12542
|
+
};
|
|
12543
|
+
}
|
|
12544
|
+
|
|
12545
|
+
// src/commands/sessions/web/discoverSessions.ts
|
|
12546
|
+
import * as fs24 from "fs";
|
|
12547
|
+
import * as os from "os";
|
|
12548
|
+
import * as path47 from "path";
|
|
12549
|
+
|
|
12550
|
+
// src/commands/sessions/web/parseSessionFile.ts
|
|
12551
|
+
import * as fs23 from "fs";
|
|
12552
|
+
import * as path46 from "path";
|
|
12553
|
+
|
|
12554
|
+
// src/commands/sessions/web/extractSessionMeta.ts
|
|
12555
|
+
function extractSessionMeta(lines) {
|
|
12556
|
+
let sessionId = "";
|
|
12557
|
+
let cwd = "";
|
|
12558
|
+
let timestamp = "";
|
|
12559
|
+
let name = "";
|
|
12560
|
+
for (const line of lines) {
|
|
12561
|
+
const entry = safeParse(line);
|
|
12562
|
+
if (!entry) continue;
|
|
12563
|
+
sessionId ||= typeof entry.sessionId === "string" ? entry.sessionId : "";
|
|
12564
|
+
timestamp ||= typeof entry.timestamp === "string" ? entry.timestamp : "";
|
|
12565
|
+
cwd ||= typeof entry.cwd === "string" ? entry.cwd : "";
|
|
12566
|
+
if (entry.type === "user" && !entry.isMeta) {
|
|
12567
|
+
name = extractName(entry);
|
|
12568
|
+
break;
|
|
12569
|
+
}
|
|
12570
|
+
}
|
|
12571
|
+
return { sessionId, cwd, timestamp, name };
|
|
12572
|
+
}
|
|
12573
|
+
function safeParse(line) {
|
|
12574
|
+
try {
|
|
12575
|
+
return JSON.parse(line);
|
|
12576
|
+
} catch {
|
|
12577
|
+
return null;
|
|
12578
|
+
}
|
|
12579
|
+
}
|
|
12580
|
+
function extractName(entry) {
|
|
12581
|
+
const msg = entry.message;
|
|
12582
|
+
const content = msg?.content;
|
|
12583
|
+
const text = typeof content === "string" ? content : Array.isArray(content) ? content.find((c) => c.type === "text")?.text ?? "" : "";
|
|
12584
|
+
return text.replace(/<command-[^>]*>[^<]*<\/command-[^>]*>/g, "").trim().slice(0, 80);
|
|
12585
|
+
}
|
|
12586
|
+
|
|
12587
|
+
// src/commands/sessions/web/parseSessionFile.ts
|
|
12588
|
+
async function parseSessionFile(filePath) {
|
|
12589
|
+
let handle;
|
|
12590
|
+
try {
|
|
12591
|
+
handle = await fs23.promises.open(filePath, "r");
|
|
12592
|
+
const buf = Buffer.alloc(16384);
|
|
12593
|
+
const { bytesRead } = await handle.read(buf, 0, buf.length, 0);
|
|
12594
|
+
const lines = buf.toString("utf8", 0, bytesRead).split("\n").filter(Boolean);
|
|
12595
|
+
const meta = extractSessionMeta(lines);
|
|
12596
|
+
if (!meta.sessionId) return null;
|
|
12597
|
+
const timestamp = meta.timestamp || (await fs23.promises.stat(filePath)).mtime.toISOString();
|
|
12598
|
+
const project = meta.cwd ? path46.basename(meta.cwd) : dirNameToProject(filePath);
|
|
12599
|
+
return {
|
|
12600
|
+
sessionId: meta.sessionId,
|
|
12601
|
+
name: meta.name || `Session ${meta.sessionId.slice(0, 8)}`,
|
|
12602
|
+
project,
|
|
12603
|
+
cwd: meta.cwd,
|
|
12604
|
+
timestamp
|
|
12605
|
+
};
|
|
12606
|
+
} catch {
|
|
12607
|
+
return null;
|
|
12608
|
+
} finally {
|
|
12609
|
+
await handle?.close();
|
|
12610
|
+
}
|
|
12611
|
+
}
|
|
12612
|
+
function dirNameToProject(filePath) {
|
|
12613
|
+
const dirName = path46.basename(path46.dirname(filePath));
|
|
12614
|
+
const parts = dirName.split("--");
|
|
12615
|
+
return parts[parts.length - 1].replace(/-/g, "/");
|
|
12616
|
+
}
|
|
12617
|
+
|
|
12618
|
+
// src/commands/sessions/web/discoverSessions.ts
|
|
12619
|
+
async function discoverSessions() {
|
|
12620
|
+
const projectsDir = path47.join(os.homedir(), ".claude", "projects");
|
|
12621
|
+
let projectDirs;
|
|
12622
|
+
try {
|
|
12623
|
+
projectDirs = await fs24.promises.readdir(projectsDir);
|
|
12624
|
+
} catch {
|
|
12625
|
+
return [];
|
|
12626
|
+
}
|
|
12627
|
+
const sessions = [];
|
|
12628
|
+
await Promise.all(
|
|
12629
|
+
projectDirs.map(async (dirName) => {
|
|
12630
|
+
const dirPath = path47.join(projectsDir, dirName);
|
|
12631
|
+
let entries;
|
|
12632
|
+
try {
|
|
12633
|
+
entries = await fs24.promises.readdir(dirPath);
|
|
12634
|
+
} catch {
|
|
12635
|
+
return;
|
|
12636
|
+
}
|
|
12637
|
+
const jsonlFiles = entries.filter((e) => e.endsWith(".jsonl"));
|
|
12638
|
+
await Promise.all(
|
|
12639
|
+
jsonlFiles.map(async (file) => {
|
|
12640
|
+
const filePath = path47.join(dirPath, file);
|
|
12641
|
+
const session = await parseSessionFile(filePath);
|
|
12642
|
+
if (session) sessions.push(session);
|
|
12643
|
+
})
|
|
12644
|
+
);
|
|
12645
|
+
})
|
|
12646
|
+
);
|
|
12647
|
+
sessions.sort(
|
|
12648
|
+
(a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()
|
|
12649
|
+
);
|
|
12650
|
+
return sessions;
|
|
12651
|
+
}
|
|
12652
|
+
|
|
12653
|
+
// src/commands/sessions/web/scheduleIdle.ts
|
|
12654
|
+
var IDLE_MS = 3e3;
|
|
12655
|
+
function scheduleIdle(session, onIdle) {
|
|
12656
|
+
if (session.idleTimer) clearTimeout(session.idleTimer);
|
|
12657
|
+
if (session.status === "done") return;
|
|
12658
|
+
session.idleTimer = setTimeout(() => {
|
|
12659
|
+
if (session.status === "running") onIdle();
|
|
12660
|
+
}, IDLE_MS);
|
|
12661
|
+
}
|
|
12662
|
+
function clearIdle(session) {
|
|
12663
|
+
if (session.idleTimer) clearTimeout(session.idleTimer);
|
|
12664
|
+
}
|
|
12665
|
+
|
|
12666
|
+
// src/commands/sessions/web/wsBroadcast.ts
|
|
12667
|
+
function wsSend(ws, msg) {
|
|
12668
|
+
if (ws.readyState === ws.OPEN) ws.send(JSON.stringify(msg));
|
|
12669
|
+
}
|
|
12670
|
+
function wsBroadcast(clients, msg) {
|
|
12671
|
+
const json = JSON.stringify(msg);
|
|
12672
|
+
for (const ws of clients) {
|
|
12673
|
+
if (ws.readyState === ws.OPEN) ws.send(json);
|
|
12674
|
+
}
|
|
12675
|
+
}
|
|
12676
|
+
|
|
12677
|
+
// src/commands/sessions/web/wirePtyEvents.ts
|
|
12678
|
+
var MAX_SCROLLBACK = 256 * 1024;
|
|
12679
|
+
var RESIZE_GRACE_MS = 500;
|
|
12680
|
+
function appendScrollback(session, data) {
|
|
12681
|
+
session.scrollback += data;
|
|
12682
|
+
if (session.scrollback.length > MAX_SCROLLBACK) {
|
|
12683
|
+
session.scrollback = session.scrollback.slice(-MAX_SCROLLBACK);
|
|
12684
|
+
}
|
|
12685
|
+
}
|
|
12686
|
+
function wirePtyEvents(session, clients, onStatusChange) {
|
|
12687
|
+
session.pty.onData((data) => {
|
|
12688
|
+
appendScrollback(session, data);
|
|
12689
|
+
const isRedraw = Date.now() - session.lastResizeAt < RESIZE_GRACE_MS;
|
|
12690
|
+
if (!isRedraw && session.status !== "running")
|
|
12691
|
+
onStatusChange(session, "running");
|
|
12692
|
+
if (!isRedraw)
|
|
12693
|
+
scheduleIdle(session, () => onStatusChange(session, "waiting"));
|
|
12694
|
+
wsBroadcast(clients, { type: "output", sessionId: session.id, data });
|
|
12695
|
+
});
|
|
12696
|
+
session.pty.onExit(() => {
|
|
12697
|
+
clearIdle(session);
|
|
12698
|
+
onStatusChange(session, "done");
|
|
12699
|
+
});
|
|
12700
|
+
}
|
|
12701
|
+
|
|
12702
|
+
// src/commands/sessions/web/SessionManager.ts
|
|
12703
|
+
var SessionManager = class {
|
|
12704
|
+
sessions = /* @__PURE__ */ new Map();
|
|
12705
|
+
clients = /* @__PURE__ */ new Set();
|
|
12706
|
+
nextId = 1;
|
|
12707
|
+
addClient(ws) {
|
|
12708
|
+
this.clients.add(ws);
|
|
12709
|
+
wsSend(ws, { type: "sessions", sessions: this.listSessions() });
|
|
12710
|
+
for (const s of this.sessions.values()) {
|
|
12711
|
+
if (s.scrollback)
|
|
12712
|
+
wsSend(ws, { type: "output", sessionId: s.id, data: s.scrollback });
|
|
12713
|
+
}
|
|
12714
|
+
}
|
|
12715
|
+
removeClient(ws) {
|
|
12716
|
+
this.clients.delete(ws);
|
|
12717
|
+
}
|
|
12718
|
+
spawn(prompt) {
|
|
12719
|
+
const id = String(this.nextId++);
|
|
12720
|
+
const session = createSession(id, prompt);
|
|
12721
|
+
this.wire(session);
|
|
12722
|
+
return id;
|
|
12723
|
+
}
|
|
12724
|
+
resume(sessionId, cwd, name) {
|
|
12725
|
+
const id = String(this.nextId++);
|
|
12726
|
+
const session = resumeSession(id, sessionId, cwd, name);
|
|
12727
|
+
this.wire(session);
|
|
12728
|
+
return id;
|
|
12729
|
+
}
|
|
12730
|
+
wire(session) {
|
|
12731
|
+
this.sessions.set(session.id, session);
|
|
12732
|
+
wirePtyEvents(session, this.clients, (s, status2) => {
|
|
12733
|
+
s.status = status2;
|
|
12734
|
+
this.notify();
|
|
12735
|
+
});
|
|
12736
|
+
scheduleIdle(session, () => {
|
|
12737
|
+
session.status = "waiting";
|
|
12738
|
+
this.notify();
|
|
12739
|
+
});
|
|
12740
|
+
this.notify();
|
|
12741
|
+
}
|
|
12742
|
+
writeToSession(id, data) {
|
|
12743
|
+
const s = this.sessions.get(id);
|
|
12744
|
+
if (s && s.status !== "done") s.pty.write(data);
|
|
12745
|
+
}
|
|
12746
|
+
resizeSession(id, cols, rows) {
|
|
12747
|
+
const s = this.sessions.get(id);
|
|
12748
|
+
if (s && s.status !== "done") {
|
|
12749
|
+
s.lastResizeAt = Date.now();
|
|
12750
|
+
s.pty.resize(cols, rows);
|
|
12751
|
+
}
|
|
12752
|
+
}
|
|
12753
|
+
dismissSession(id) {
|
|
12754
|
+
const s = this.sessions.get(id);
|
|
12755
|
+
if (!s) return;
|
|
12756
|
+
if (s.status !== "done") s.pty.kill();
|
|
12757
|
+
clearIdle(s);
|
|
12758
|
+
this.sessions.delete(id);
|
|
12759
|
+
this.notify();
|
|
12760
|
+
}
|
|
12761
|
+
listSessions() {
|
|
12762
|
+
return [...this.sessions.values()].map(
|
|
12763
|
+
({ id, name, status: status2, startedAt }) => ({
|
|
12764
|
+
id,
|
|
12765
|
+
name,
|
|
12766
|
+
status: status2,
|
|
12767
|
+
startedAt
|
|
12768
|
+
})
|
|
12769
|
+
);
|
|
12770
|
+
}
|
|
12771
|
+
async getHistory() {
|
|
12772
|
+
return discoverSessions();
|
|
12773
|
+
}
|
|
12774
|
+
notify() {
|
|
12775
|
+
wsBroadcast(this.clients, {
|
|
12776
|
+
type: "sessions",
|
|
12777
|
+
sessions: this.listSessions()
|
|
12778
|
+
});
|
|
12779
|
+
}
|
|
12780
|
+
};
|
|
12781
|
+
|
|
12782
|
+
// src/commands/sessions/web/index.ts
|
|
12783
|
+
async function web3(options2) {
|
|
12784
|
+
const port = Number.parseInt(options2.port, 10);
|
|
12785
|
+
const server = startWebServer("Sessions", port, handleRequest3);
|
|
12786
|
+
const manager = new SessionManager();
|
|
12787
|
+
const wss = new WebSocketServer({ noServer: true });
|
|
12788
|
+
server.on("upgrade", (req, socket, head) => {
|
|
12789
|
+
if (req.url === "/ws") {
|
|
12790
|
+
wss.handleUpgrade(req, socket, head, (ws) => {
|
|
12791
|
+
handleSocket(ws, manager);
|
|
12792
|
+
});
|
|
12793
|
+
} else {
|
|
12794
|
+
socket.destroy();
|
|
12795
|
+
}
|
|
12796
|
+
});
|
|
12797
|
+
}
|
|
12798
|
+
|
|
12799
|
+
// src/commands/sessions/registerSessions.ts
|
|
12800
|
+
function registerSessions(program2) {
|
|
12801
|
+
const cmd = program2.command("sessions").description("Web dashboard for Claude Code sessions").action(() => web3({ port: "3100" }));
|
|
12802
|
+
cmd.command("web").description("Start the sessions web dashboard").option("-p, --port <number>", "Port to listen on", "3100").action(web3);
|
|
12803
|
+
}
|
|
12804
|
+
|
|
12376
12805
|
// src/commands/statusLine.ts
|
|
12377
12806
|
import chalk134 from "chalk";
|
|
12378
12807
|
|
|
@@ -12451,21 +12880,21 @@ async function statusLine() {
|
|
|
12451
12880
|
}
|
|
12452
12881
|
|
|
12453
12882
|
// src/commands/sync.ts
|
|
12454
|
-
import * as
|
|
12455
|
-
import * as
|
|
12456
|
-
import * as
|
|
12883
|
+
import * as fs27 from "fs";
|
|
12884
|
+
import * as os2 from "os";
|
|
12885
|
+
import * as path50 from "path";
|
|
12457
12886
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
12458
12887
|
|
|
12459
12888
|
// src/commands/sync/syncClaudeMd.ts
|
|
12460
|
-
import * as
|
|
12461
|
-
import * as
|
|
12889
|
+
import * as fs25 from "fs";
|
|
12890
|
+
import * as path48 from "path";
|
|
12462
12891
|
import chalk135 from "chalk";
|
|
12463
12892
|
async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
12464
|
-
const source =
|
|
12465
|
-
const target =
|
|
12466
|
-
const sourceContent =
|
|
12467
|
-
if (
|
|
12468
|
-
const targetContent =
|
|
12893
|
+
const source = path48.join(claudeDir, "CLAUDE.md");
|
|
12894
|
+
const target = path48.join(targetBase, "CLAUDE.md");
|
|
12895
|
+
const sourceContent = fs25.readFileSync(source, "utf-8");
|
|
12896
|
+
if (fs25.existsSync(target)) {
|
|
12897
|
+
const targetContent = fs25.readFileSync(target, "utf-8");
|
|
12469
12898
|
if (sourceContent !== targetContent) {
|
|
12470
12899
|
console.log(
|
|
12471
12900
|
chalk135.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
@@ -12482,21 +12911,21 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
12482
12911
|
}
|
|
12483
12912
|
}
|
|
12484
12913
|
}
|
|
12485
|
-
|
|
12914
|
+
fs25.copyFileSync(source, target);
|
|
12486
12915
|
console.log("Copied CLAUDE.md to ~/.claude/CLAUDE.md");
|
|
12487
12916
|
}
|
|
12488
12917
|
|
|
12489
12918
|
// src/commands/sync/syncSettings.ts
|
|
12490
|
-
import * as
|
|
12491
|
-
import * as
|
|
12919
|
+
import * as fs26 from "fs";
|
|
12920
|
+
import * as path49 from "path";
|
|
12492
12921
|
import chalk136 from "chalk";
|
|
12493
12922
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
12494
|
-
const source =
|
|
12495
|
-
const target =
|
|
12496
|
-
const sourceContent =
|
|
12923
|
+
const source = path49.join(claudeDir, "settings.json");
|
|
12924
|
+
const target = path49.join(targetBase, "settings.json");
|
|
12925
|
+
const sourceContent = fs26.readFileSync(source, "utf-8");
|
|
12497
12926
|
const mergedContent = JSON.stringify(JSON.parse(sourceContent), null, " ");
|
|
12498
|
-
if (
|
|
12499
|
-
const targetContent =
|
|
12927
|
+
if (fs26.existsSync(target)) {
|
|
12928
|
+
const targetContent = fs26.readFileSync(target, "utf-8");
|
|
12500
12929
|
const normalizedTarget = JSON.stringify(
|
|
12501
12930
|
JSON.parse(targetContent),
|
|
12502
12931
|
null,
|
|
@@ -12522,29 +12951,29 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
12522
12951
|
}
|
|
12523
12952
|
}
|
|
12524
12953
|
}
|
|
12525
|
-
|
|
12954
|
+
fs26.writeFileSync(target, mergedContent);
|
|
12526
12955
|
console.log("Copied settings.json to ~/.claude/settings.json");
|
|
12527
12956
|
}
|
|
12528
12957
|
|
|
12529
12958
|
// src/commands/sync.ts
|
|
12530
12959
|
var __filename4 = fileURLToPath7(import.meta.url);
|
|
12531
|
-
var __dirname7 =
|
|
12960
|
+
var __dirname7 = path50.dirname(__filename4);
|
|
12532
12961
|
async function sync(options2) {
|
|
12533
12962
|
const config = loadConfig();
|
|
12534
12963
|
const yes = options2?.yes ?? config.sync.autoConfirm;
|
|
12535
|
-
const claudeDir =
|
|
12536
|
-
const targetBase =
|
|
12964
|
+
const claudeDir = path50.join(__dirname7, "..", "claude");
|
|
12965
|
+
const targetBase = path50.join(os2.homedir(), ".claude");
|
|
12537
12966
|
syncCommands(claudeDir, targetBase);
|
|
12538
12967
|
await syncSettings(claudeDir, targetBase, { yes });
|
|
12539
12968
|
await syncClaudeMd(claudeDir, targetBase, { yes });
|
|
12540
12969
|
}
|
|
12541
12970
|
function syncCommands(claudeDir, targetBase) {
|
|
12542
|
-
const sourceDir =
|
|
12543
|
-
const targetDir =
|
|
12544
|
-
|
|
12545
|
-
const files =
|
|
12971
|
+
const sourceDir = path50.join(claudeDir, "commands");
|
|
12972
|
+
const targetDir = path50.join(targetBase, "commands");
|
|
12973
|
+
fs27.mkdirSync(targetDir, { recursive: true });
|
|
12974
|
+
const files = fs27.readdirSync(sourceDir);
|
|
12546
12975
|
for (const file of files) {
|
|
12547
|
-
|
|
12976
|
+
fs27.copyFileSync(path50.join(sourceDir, file), path50.join(targetDir, file));
|
|
12548
12977
|
console.log(`Copied ${file} to ${targetDir}`);
|
|
12549
12978
|
}
|
|
12550
12979
|
console.log(`Synced ${files.length} command(s) to ~/.claude/commands`);
|
|
@@ -12552,15 +12981,15 @@ function syncCommands(claudeDir, targetBase) {
|
|
|
12552
12981
|
|
|
12553
12982
|
// src/commands/update.ts
|
|
12554
12983
|
import { execSync as execSync42 } from "child_process";
|
|
12555
|
-
import * as
|
|
12984
|
+
import * as path51 from "path";
|
|
12556
12985
|
function isGlobalNpmInstall(dir) {
|
|
12557
12986
|
try {
|
|
12558
|
-
const resolved =
|
|
12559
|
-
if (resolved.split(
|
|
12987
|
+
const resolved = path51.resolve(dir);
|
|
12988
|
+
if (resolved.split(path51.sep).includes("node_modules")) {
|
|
12560
12989
|
return true;
|
|
12561
12990
|
}
|
|
12562
12991
|
const globalPrefix = execSync42("npm prefix -g", { stdio: "pipe" }).toString().trim();
|
|
12563
|
-
return resolved.toLowerCase().startsWith(
|
|
12992
|
+
return resolved.toLowerCase().startsWith(path51.resolve(globalPrefix).toLowerCase());
|
|
12564
12993
|
} catch {
|
|
12565
12994
|
return false;
|
|
12566
12995
|
}
|
|
@@ -12627,6 +13056,7 @@ registerRavendb(program);
|
|
|
12627
13056
|
registerSeq(program);
|
|
12628
13057
|
registerTranscript(program);
|
|
12629
13058
|
registerVoice(program);
|
|
13059
|
+
registerSessions(program);
|
|
12630
13060
|
registerDeny(program);
|
|
12631
13061
|
program.command("next").description("Alias for backlog next -w").action(() => next({ allowEdits: true }));
|
|
12632
13062
|
program.command("draft").alias("feat").description("Launch Claude in /draft mode, chain into next on /next signal").action(() => launchMode("draft"));
|