codebase-snapshot 0.9.5 → 0.9.7
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/CHANGELOG.md +80 -0
- package/README.md +4 -1
- package/dist/bin.js +471 -205
- package/dist/{chunk-4AHHSNGG.js → chunk-DPK6ZTOG.js} +33 -7
- package/dist/{chunk-B336MMNC.js → chunk-QABL7NRC.js} +445 -224
- package/dist/cli.cjs +574 -312
- package/dist/cli.d.cts +7 -1
- package/dist/cli.d.ts +7 -1
- package/dist/cli.js +16 -2
- package/dist/index.cjs +453 -217
- package/dist/index.d.cts +68 -2
- package/dist/index.d.ts +68 -2
- package/dist/index.js +1 -1
- package/dist/mcp.cjs +31 -4
- package/dist/mcp.d.cts +14 -1
- package/dist/mcp.d.ts +14 -1
- package/dist/mcp.js +2 -2
- package/docs/cli.md +19 -2
- package/docs/mcp.md +3 -3
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var childProcess = require('child_process');
|
|
4
|
-
var
|
|
5
|
-
var
|
|
4
|
+
var fs12 = require('fs');
|
|
5
|
+
var path13 = require('path');
|
|
6
6
|
var util = require('util');
|
|
7
7
|
var crypto2 = require('crypto');
|
|
8
8
|
var module$1 = require('module');
|
|
@@ -11,6 +11,7 @@ var readline = require('readline');
|
|
|
11
11
|
var async_hooks = require('async_hooks');
|
|
12
12
|
var os = require('os');
|
|
13
13
|
var ts = require('typescript');
|
|
14
|
+
var https = require('https');
|
|
14
15
|
|
|
15
16
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
16
17
|
|
|
@@ -33,12 +34,13 @@ function _interopNamespace(e) {
|
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
var childProcess__namespace = /*#__PURE__*/_interopNamespace(childProcess);
|
|
36
|
-
var
|
|
37
|
-
var
|
|
37
|
+
var fs12__namespace = /*#__PURE__*/_interopNamespace(fs12);
|
|
38
|
+
var path13__namespace = /*#__PURE__*/_interopNamespace(path13);
|
|
38
39
|
var crypto2__namespace = /*#__PURE__*/_interopNamespace(crypto2);
|
|
39
40
|
var readline__namespace = /*#__PURE__*/_interopNamespace(readline);
|
|
40
41
|
var os__namespace = /*#__PURE__*/_interopNamespace(os);
|
|
41
42
|
var ts__default = /*#__PURE__*/_interopDefault(ts);
|
|
43
|
+
var https__namespace = /*#__PURE__*/_interopNamespace(https);
|
|
42
44
|
|
|
43
45
|
// src/cli.ts
|
|
44
46
|
var MANIFEST_FILES = [
|
|
@@ -87,15 +89,15 @@ var SKIPPED_WALK_DIRS = /* @__PURE__ */ new Set([
|
|
|
87
89
|
]);
|
|
88
90
|
function readSmallFile(fullPath) {
|
|
89
91
|
try {
|
|
90
|
-
const stats =
|
|
92
|
+
const stats = fs12__namespace.statSync(fullPath);
|
|
91
93
|
if (!stats.isFile() || stats.size > MANIFEST_MAX_BYTES) return null;
|
|
92
|
-
return
|
|
94
|
+
return fs12__namespace.readFileSync(fullPath, "utf8");
|
|
93
95
|
} catch {
|
|
94
96
|
return null;
|
|
95
97
|
}
|
|
96
98
|
}
|
|
97
99
|
function readManifest(cwd, name) {
|
|
98
|
-
return readSmallFile(
|
|
100
|
+
return readSmallFile(path13__namespace.join(cwd, name));
|
|
99
101
|
}
|
|
100
102
|
function dependenciesFromPackageJson(raw) {
|
|
101
103
|
const names = /* @__PURE__ */ new Set();
|
|
@@ -155,7 +157,7 @@ function pnpmWorkspacePatterns(raw) {
|
|
|
155
157
|
function childDirectories(cwd, parent) {
|
|
156
158
|
let entries;
|
|
157
159
|
try {
|
|
158
|
-
entries =
|
|
160
|
+
entries = fs12__namespace.readdirSync(path13__namespace.join(cwd, parent), { withFileTypes: true });
|
|
159
161
|
} catch {
|
|
160
162
|
return [];
|
|
161
163
|
}
|
|
@@ -191,12 +193,12 @@ function scanWorkspacePackages(cwd, patterns) {
|
|
|
191
193
|
const files = /* @__PURE__ */ new Set();
|
|
192
194
|
const dependencies = /* @__PURE__ */ new Set();
|
|
193
195
|
for (const relative11 of workspacePackageDirs(cwd, patterns)) {
|
|
194
|
-
const full =
|
|
196
|
+
const full = path13__namespace.join(cwd, relative11);
|
|
195
197
|
try {
|
|
196
|
-
for (const entry of
|
|
198
|
+
for (const entry of fs12__namespace.readdirSync(full, { withFileTypes: true })) files.add(entry.name);
|
|
197
199
|
} catch {
|
|
198
200
|
}
|
|
199
|
-
const raw = readSmallFile(
|
|
201
|
+
const raw = readSmallFile(path13__namespace.join(full, "package.json"));
|
|
200
202
|
if (raw !== null) {
|
|
201
203
|
for (const name of dependenciesFromPackageJson(raw)) dependencies.add(name);
|
|
202
204
|
}
|
|
@@ -213,7 +215,7 @@ function countMarkdownFiles(cwd) {
|
|
|
213
215
|
directoriesSeen += 1;
|
|
214
216
|
let entries;
|
|
215
217
|
try {
|
|
216
|
-
entries =
|
|
218
|
+
entries = fs12__namespace.readdirSync(current.dir, { withFileTypes: true });
|
|
217
219
|
} catch {
|
|
218
220
|
continue;
|
|
219
221
|
}
|
|
@@ -224,7 +226,7 @@ function countMarkdownFiles(cwd) {
|
|
|
224
226
|
}
|
|
225
227
|
if (!entry.isDirectory() || current.depth >= 2) continue;
|
|
226
228
|
if (entry.name.startsWith(".") || SKIPPED_WALK_DIRS.has(entry.name)) continue;
|
|
227
|
-
queue.push({ dir:
|
|
229
|
+
queue.push({ dir: path13__namespace.join(current.dir, entry.name), depth: current.depth + 1 });
|
|
228
230
|
}
|
|
229
231
|
}
|
|
230
232
|
return count;
|
|
@@ -233,7 +235,7 @@ function buildPresetContext(cwd) {
|
|
|
233
235
|
const files = /* @__PURE__ */ new Set();
|
|
234
236
|
const dirs = /* @__PURE__ */ new Set();
|
|
235
237
|
try {
|
|
236
|
-
for (const entry of
|
|
238
|
+
for (const entry of fs12__namespace.readdirSync(cwd, { withFileTypes: true })) {
|
|
237
239
|
if (entry.isDirectory()) dirs.add(entry.name);
|
|
238
240
|
else if (entry.isFile()) files.add(entry.name);
|
|
239
241
|
}
|
|
@@ -250,7 +252,7 @@ function buildPresetContext(cwd) {
|
|
|
250
252
|
const isWorkspace = files.has("pnpm-workspace.yaml") || files.has("nx.json") || files.has("turbo.json") || files.has("lerna.json") || packageJson !== void 0 && packageJson.includes('"workspaces"') || declaredWorkspaces.length > 0;
|
|
251
253
|
let workspace = { files: /* @__PURE__ */ new Set(), dependencies: /* @__PURE__ */ new Set() };
|
|
252
254
|
if (isWorkspace) {
|
|
253
|
-
const pnpmRaw = files.has("pnpm-workspace.yaml") ? readSmallFile(
|
|
255
|
+
const pnpmRaw = files.has("pnpm-workspace.yaml") ? readSmallFile(path13__namespace.join(cwd, "pnpm-workspace.yaml")) : null;
|
|
254
256
|
const declared = pnpmRaw === null ? [] : pnpmWorkspacePatterns(pnpmRaw);
|
|
255
257
|
const patterns = declared.length > 0 ? declared : declaredWorkspaces.length > 0 ? declaredWorkspaces : DEFAULT_WORKSPACE_PATTERNS;
|
|
256
258
|
workspace = scanWorkspacePackages(cwd, patterns);
|
|
@@ -1525,14 +1527,14 @@ var PRESET_IGNORES = new Set(
|
|
|
1525
1527
|
);
|
|
1526
1528
|
function readLinkTarget(linkPath, fallback) {
|
|
1527
1529
|
try {
|
|
1528
|
-
return
|
|
1530
|
+
return fs12__namespace.readlinkSync(linkPath);
|
|
1529
1531
|
} catch {
|
|
1530
1532
|
return fallback;
|
|
1531
1533
|
}
|
|
1532
1534
|
}
|
|
1533
1535
|
function isInside(root, candidate) {
|
|
1534
|
-
const relative11 =
|
|
1535
|
-
return relative11 === "" || !relative11.startsWith(`..${
|
|
1536
|
+
const relative11 = path13__namespace.relative(root, candidate);
|
|
1537
|
+
return relative11 === "" || !relative11.startsWith(`..${path13__namespace.sep}`) && relative11 !== ".." && !path13__namespace.isAbsolute(relative11);
|
|
1536
1538
|
}
|
|
1537
1539
|
function getGitInfo(cwd, fallbackBranch = "main") {
|
|
1538
1540
|
try {
|
|
@@ -1737,10 +1739,10 @@ function trimUnescapedTrailingSpaces(line) {
|
|
|
1737
1739
|
return line.slice(0, end);
|
|
1738
1740
|
}
|
|
1739
1741
|
function readGitignoreRules(dir) {
|
|
1740
|
-
const gitignorePath2 =
|
|
1742
|
+
const gitignorePath2 = path13__namespace.join(dir, ".gitignore");
|
|
1741
1743
|
let raw;
|
|
1742
1744
|
try {
|
|
1743
|
-
raw =
|
|
1745
|
+
raw = fs12__namespace.readFileSync(gitignorePath2, "utf8");
|
|
1744
1746
|
} catch {
|
|
1745
1747
|
return [];
|
|
1746
1748
|
}
|
|
@@ -1867,7 +1869,7 @@ function isToolOwnedDirName(name) {
|
|
|
1867
1869
|
}
|
|
1868
1870
|
function hasSnapshotMarker(target) {
|
|
1869
1871
|
try {
|
|
1870
|
-
return
|
|
1872
|
+
return fs12__namespace.statSync(target).isDirectory() && fs12__namespace.existsSync(path13__namespace.join(target, ".codebase-snapshot"));
|
|
1871
1873
|
} catch {
|
|
1872
1874
|
return false;
|
|
1873
1875
|
}
|
|
@@ -1881,7 +1883,7 @@ function makeToolOwnedDecider(cwd, toolOwnedPaths) {
|
|
|
1881
1883
|
const prefix = parts.slice(0, depth).join("/");
|
|
1882
1884
|
let hasMarker = markers.get(prefix);
|
|
1883
1885
|
if (hasMarker === void 0) {
|
|
1884
|
-
hasMarker =
|
|
1886
|
+
hasMarker = fs12__namespace.existsSync(path13__namespace.join(cwd, prefix, ".codebase-snapshot"));
|
|
1885
1887
|
markers.set(prefix, hasMarker);
|
|
1886
1888
|
}
|
|
1887
1889
|
if (hasMarker) return true;
|
|
@@ -1896,7 +1898,7 @@ function makeLinkProbe() {
|
|
|
1896
1898
|
let known = cache.get(absolutePath);
|
|
1897
1899
|
if (known === void 0) {
|
|
1898
1900
|
try {
|
|
1899
|
-
known =
|
|
1901
|
+
known = fs12__namespace.lstatSync(absolutePath).isSymbolicLink();
|
|
1900
1902
|
} catch {
|
|
1901
1903
|
known = false;
|
|
1902
1904
|
}
|
|
@@ -1909,7 +1911,7 @@ function dropLinkedDirectories(cwd, candidates, skipped) {
|
|
|
1909
1911
|
const isLink = makeLinkProbe();
|
|
1910
1912
|
let rootReal = cwd;
|
|
1911
1913
|
try {
|
|
1912
|
-
rootReal =
|
|
1914
|
+
rootReal = fs12__namespace.realpathSync(cwd);
|
|
1913
1915
|
} catch {
|
|
1914
1916
|
}
|
|
1915
1917
|
const reported = /* @__PURE__ */ new Set();
|
|
@@ -1919,7 +1921,7 @@ function dropLinkedDirectories(cwd, candidates, skipped) {
|
|
|
1919
1921
|
let linkedDir = null;
|
|
1920
1922
|
for (let depth = 1; depth <= parts.length; depth += 1) {
|
|
1921
1923
|
const prefix = parts.slice(0, depth).join("/");
|
|
1922
|
-
if (isLink(
|
|
1924
|
+
if (isLink(path13__namespace.join(cwd, prefix))) {
|
|
1923
1925
|
linkedDir = prefix;
|
|
1924
1926
|
break;
|
|
1925
1927
|
}
|
|
@@ -1930,10 +1932,10 @@ function dropLinkedDirectories(cwd, candidates, skipped) {
|
|
|
1930
1932
|
}
|
|
1931
1933
|
if (reported.has(linkedDir)) continue;
|
|
1932
1934
|
reported.add(linkedDir);
|
|
1933
|
-
const absolute =
|
|
1935
|
+
const absolute = path13__namespace.join(cwd, linkedDir);
|
|
1934
1936
|
let targetReal = absolute;
|
|
1935
1937
|
try {
|
|
1936
|
-
targetReal =
|
|
1938
|
+
targetReal = fs12__namespace.realpathSync(absolute);
|
|
1937
1939
|
} catch {
|
|
1938
1940
|
}
|
|
1939
1941
|
const target = readLinkTarget(absolute, targetReal);
|
|
@@ -2010,7 +2012,7 @@ function collectFiles(cwd, options = {}) {
|
|
|
2010
2012
|
"Discovery mode is `git`, but git could not list this directory's files. Run inside a working repository, or pass --discovery walk (or auto) to scan the tree directly."
|
|
2011
2013
|
);
|
|
2012
2014
|
}
|
|
2013
|
-
if (
|
|
2015
|
+
if (fs12__namespace.existsSync(path13__namespace.join(cwd, ".git"))) {
|
|
2014
2016
|
throw new Error(
|
|
2015
2017
|
"This directory is a git repository, but git could not list its files. A plain walk honours .gitignore files, but git also applies .git/info/exclude and your global excludes file, includes files that are tracked although a .gitignore now matches them, and treats a submodule as a single entry. Fix the repository (git status should work), run outside git, or pass --discovery walk to accept those differences."
|
|
2016
2018
|
);
|
|
@@ -2069,7 +2071,7 @@ function collectFiles(cwd, options = {}) {
|
|
|
2069
2071
|
}
|
|
2070
2072
|
function rootRealFor(root) {
|
|
2071
2073
|
try {
|
|
2072
|
-
return
|
|
2074
|
+
return fs12__namespace.realpathSync(root);
|
|
2073
2075
|
} catch {
|
|
2074
2076
|
return root;
|
|
2075
2077
|
}
|
|
@@ -2077,18 +2079,18 @@ function rootRealFor(root) {
|
|
|
2077
2079
|
function walkDirectory(dir, baseDir, rootReal, visited, reservedPaths = /* @__PURE__ */ new Set(), parentGitignoreLayers = []) {
|
|
2078
2080
|
const results = { files: [], skipped: [] };
|
|
2079
2081
|
const stack = [];
|
|
2080
|
-
const relativeToBase = (target) =>
|
|
2082
|
+
const relativeToBase = (target) => path13__namespace.relative(baseDir, target).replace(/\\/g, "/") || ".";
|
|
2081
2083
|
const enter = (current, layers) => {
|
|
2082
2084
|
if (visited.has(current)) return false;
|
|
2083
2085
|
visited.add(current);
|
|
2084
2086
|
const localRules = readGitignoreRules(current);
|
|
2085
2087
|
const gitignoreLayers = localRules.length === 0 ? layers : [
|
|
2086
2088
|
...layers,
|
|
2087
|
-
{ prefix:
|
|
2089
|
+
{ prefix: path13__namespace.relative(baseDir, current).replace(/\\/g, "/"), rules: localRules }
|
|
2088
2090
|
];
|
|
2089
2091
|
let entries;
|
|
2090
2092
|
try {
|
|
2091
|
-
entries =
|
|
2093
|
+
entries = fs12__namespace.readdirSync(current, { withFileTypes: true });
|
|
2092
2094
|
} catch {
|
|
2093
2095
|
results.skipped.push({
|
|
2094
2096
|
path: relativeToBase(current),
|
|
@@ -2110,8 +2112,8 @@ function walkDirectory(dir, baseDir, rootReal, visited, reservedPaths = /* @__PU
|
|
|
2110
2112
|
}
|
|
2111
2113
|
const entry = frame.entries[frame.index];
|
|
2112
2114
|
frame.index += 1;
|
|
2113
|
-
const fullPath =
|
|
2114
|
-
const relPath =
|
|
2115
|
+
const fullPath = path13__namespace.join(frame.dir, entry.name);
|
|
2116
|
+
const relPath = path13__namespace.relative(baseDir, fullPath).replace(/\\/g, "/");
|
|
2115
2117
|
if (isToolOwnedDirName(entry.name) && reservedPaths.has(relPath)) continue;
|
|
2116
2118
|
if (DEFAULT_IGNORED_DIRS.includes(entry.name)) {
|
|
2117
2119
|
results.skipped.push({
|
|
@@ -2144,14 +2146,14 @@ function walkDirectory(dir, baseDir, rootReal, visited, reservedPaths = /* @__PU
|
|
|
2144
2146
|
if (entry.isSymbolicLink()) {
|
|
2145
2147
|
let targetReal;
|
|
2146
2148
|
try {
|
|
2147
|
-
targetReal =
|
|
2149
|
+
targetReal = fs12__namespace.realpathSync(fullPath);
|
|
2148
2150
|
} catch {
|
|
2149
2151
|
results.skipped.push({ path: relPath, reason: "read-error", detail: "broken symlink" });
|
|
2150
2152
|
continue;
|
|
2151
2153
|
}
|
|
2152
2154
|
let stats;
|
|
2153
2155
|
try {
|
|
2154
|
-
stats =
|
|
2156
|
+
stats = fs12__namespace.statSync(fullPath);
|
|
2155
2157
|
} catch {
|
|
2156
2158
|
results.skipped.push({ path: relPath, reason: "read-error", detail: "unreadable symlink" });
|
|
2157
2159
|
continue;
|
|
@@ -2204,13 +2206,13 @@ var CONFIG_FILENAMES = [
|
|
|
2204
2206
|
];
|
|
2205
2207
|
function findConfigFile(cwd) {
|
|
2206
2208
|
for (const filename of CONFIG_FILENAMES) {
|
|
2207
|
-
const fullPath =
|
|
2208
|
-
if (
|
|
2209
|
+
const fullPath = path13__namespace.join(cwd, filename);
|
|
2210
|
+
if (fs12__namespace.existsSync(fullPath)) return fullPath;
|
|
2209
2211
|
}
|
|
2210
|
-
const pkgJsonPath =
|
|
2211
|
-
if (!
|
|
2212
|
+
const pkgJsonPath = path13__namespace.join(cwd, "package.json");
|
|
2213
|
+
if (!fs12__namespace.existsSync(pkgJsonPath)) return null;
|
|
2212
2214
|
try {
|
|
2213
|
-
const parsed = JSON.parse(
|
|
2215
|
+
const parsed = JSON.parse(fs12__namespace.readFileSync(pkgJsonPath, "utf8"));
|
|
2214
2216
|
return parsed.snapshot === void 0 ? null : pkgJsonPath;
|
|
2215
2217
|
} catch {
|
|
2216
2218
|
return null;
|
|
@@ -2461,11 +2463,11 @@ async function loadConfigFileDetailed(cwd) {
|
|
|
2461
2463
|
const warnings = [];
|
|
2462
2464
|
const errors = [];
|
|
2463
2465
|
for (const filename of CONFIG_FILENAMES) {
|
|
2464
|
-
const fullPath =
|
|
2465
|
-
if (!
|
|
2466
|
+
const fullPath = path13__namespace.join(cwd, filename);
|
|
2467
|
+
if (!fs12__namespace.existsSync(fullPath)) continue;
|
|
2466
2468
|
if (filename.endsWith(".json") || filename === ".snapshotrc") {
|
|
2467
2469
|
try {
|
|
2468
|
-
const config = parseJsonish(
|
|
2470
|
+
const config = parseJsonish(fs12__namespace.readFileSync(fullPath, "utf8"), fullPath);
|
|
2469
2471
|
if (config === null || typeof config !== "object" || Array.isArray(config)) {
|
|
2470
2472
|
throw new Error(
|
|
2471
2473
|
`${fullPath} does not hold a configuration object (received ${describeValue2(config)}).`
|
|
@@ -2499,10 +2501,10 @@ async function loadConfigFileDetailed(cwd) {
|
|
|
2499
2501
|
continue;
|
|
2500
2502
|
}
|
|
2501
2503
|
}
|
|
2502
|
-
const pkgJsonPath =
|
|
2503
|
-
if (
|
|
2504
|
+
const pkgJsonPath = path13__namespace.join(cwd, "package.json");
|
|
2505
|
+
if (fs12__namespace.existsSync(pkgJsonPath)) {
|
|
2504
2506
|
try {
|
|
2505
|
-
const parsed = parseJsonish(
|
|
2507
|
+
const parsed = parseJsonish(fs12__namespace.readFileSync(pkgJsonPath, "utf8"), pkgJsonPath);
|
|
2506
2508
|
const snapshotKey = parsed.snapshot;
|
|
2507
2509
|
if (snapshotKey && typeof snapshotKey === "object" && !Array.isArray(snapshotKey)) {
|
|
2508
2510
|
return { config: snapshotKey, file: pkgJsonPath, warnings, errors };
|
|
@@ -2670,9 +2672,9 @@ function resolveKindRules(value) {
|
|
|
2670
2672
|
function outputExcludePatterns(cwd, outDir, tmpDir) {
|
|
2671
2673
|
const patterns = [];
|
|
2672
2674
|
for (const dir of [outDir, tmpDir]) {
|
|
2673
|
-
const absolute =
|
|
2674
|
-
const relative11 =
|
|
2675
|
-
if (!relative11 || relative11 === ".." || relative11.startsWith(`..${
|
|
2675
|
+
const absolute = path13__namespace.resolve(cwd, dir);
|
|
2676
|
+
const relative11 = path13__namespace.relative(cwd, absolute);
|
|
2677
|
+
if (!relative11 || relative11 === ".." || relative11.startsWith(`..${path13__namespace.sep}`) || path13__namespace.isAbsolute(relative11)) {
|
|
2676
2678
|
continue;
|
|
2677
2679
|
}
|
|
2678
2680
|
patterns.push(`${relative11.replace(/\\/g, "/")}/**`);
|
|
@@ -2791,11 +2793,11 @@ function resolveCandidateCwd(userConfig, cliOptions, baseDir) {
|
|
|
2791
2793
|
);
|
|
2792
2794
|
}
|
|
2793
2795
|
const candidate = cliOptions?.cwd || userConfig?.cwd || baseDir || process.cwd();
|
|
2794
|
-
const resolved =
|
|
2795
|
-
if (!
|
|
2796
|
+
const resolved = path13__namespace.resolve(candidate);
|
|
2797
|
+
if (!fs12__namespace.existsSync(resolved)) {
|
|
2796
2798
|
throw new Error(`Working directory does not exist: ${resolved}`);
|
|
2797
2799
|
}
|
|
2798
|
-
if (!
|
|
2800
|
+
if (!fs12__namespace.statSync(resolved).isDirectory()) {
|
|
2799
2801
|
throw new Error(`Working directory is not a directory: ${resolved}`);
|
|
2800
2802
|
}
|
|
2801
2803
|
return resolved;
|
|
@@ -3021,7 +3023,7 @@ var BINARY_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
3021
3023
|
".so"
|
|
3022
3024
|
]);
|
|
3023
3025
|
function isBinaryExtension(filePath) {
|
|
3024
|
-
const ext =
|
|
3026
|
+
const ext = path13__namespace.extname(filePath).toLowerCase();
|
|
3025
3027
|
return BINARY_EXTENSIONS.has(ext);
|
|
3026
3028
|
}
|
|
3027
3029
|
function countControlBytes(buffer) {
|
|
@@ -3188,13 +3190,13 @@ function isBinaryFile(absolutePath) {
|
|
|
3188
3190
|
if (isBinaryExtension(absolutePath)) return true;
|
|
3189
3191
|
let fd;
|
|
3190
3192
|
try {
|
|
3191
|
-
fd =
|
|
3193
|
+
fd = fs12__namespace.openSync(absolutePath, "r");
|
|
3192
3194
|
const buffer = Buffer.alloc(CHUNK);
|
|
3193
3195
|
let sample;
|
|
3194
3196
|
let position = 0;
|
|
3195
3197
|
while (position < BINARY_SCAN_BYTES) {
|
|
3196
3198
|
const wanted = Math.min(CHUNK, BINARY_SCAN_BYTES - position);
|
|
3197
|
-
const bytesRead =
|
|
3199
|
+
const bytesRead = fs12__namespace.readSync(fd, buffer, 0, wanted, position);
|
|
3198
3200
|
if (bytesRead === 0) return false;
|
|
3199
3201
|
const chunk = buffer.subarray(0, bytesRead);
|
|
3200
3202
|
if (sample === void 0) {
|
|
@@ -3212,7 +3214,7 @@ function isBinaryFile(absolutePath) {
|
|
|
3212
3214
|
} finally {
|
|
3213
3215
|
if (fd !== void 0) {
|
|
3214
3216
|
try {
|
|
3215
|
-
|
|
3217
|
+
fs12__namespace.closeSync(fd);
|
|
3216
3218
|
} catch {
|
|
3217
3219
|
}
|
|
3218
3220
|
}
|
|
@@ -3225,33 +3227,33 @@ function maskedPath(value, secretRules) {
|
|
|
3225
3227
|
}
|
|
3226
3228
|
function confineToDirectory(directory, filename) {
|
|
3227
3229
|
if (filename.includes("\0")) return null;
|
|
3228
|
-
if (
|
|
3229
|
-
const base =
|
|
3230
|
-
const resolved =
|
|
3230
|
+
if (path13__namespace.isAbsolute(filename)) return null;
|
|
3231
|
+
const base = path13__namespace.resolve(directory);
|
|
3232
|
+
const resolved = path13__namespace.resolve(base, filename);
|
|
3231
3233
|
const caseInsensitive = process.platform === "win32" || process.platform === "darwin";
|
|
3232
|
-
const prefix = caseInsensitive ? `${base}${
|
|
3234
|
+
const prefix = caseInsensitive ? `${base}${path13__namespace.sep}`.toLowerCase() : `${base}${path13__namespace.sep}`;
|
|
3233
3235
|
const candidate = caseInsensitive ? resolved.toLowerCase() : resolved;
|
|
3234
3236
|
return candidate.startsWith(prefix) ? resolved : null;
|
|
3235
3237
|
}
|
|
3236
3238
|
function findStagingDirectory(config) {
|
|
3237
|
-
const tmpDir =
|
|
3239
|
+
const tmpDir = path13__namespace.resolve(config.cwd, config.tmpDir);
|
|
3238
3240
|
let entries;
|
|
3239
3241
|
try {
|
|
3240
|
-
entries =
|
|
3242
|
+
entries = fs12__namespace.readdirSync(tmpDir);
|
|
3241
3243
|
} catch {
|
|
3242
3244
|
return null;
|
|
3243
3245
|
}
|
|
3244
3246
|
const runs = entries.filter((name) => name.startsWith("run-")).sort();
|
|
3245
3247
|
const newest = runs[runs.length - 1];
|
|
3246
|
-
return newest ?
|
|
3248
|
+
return newest ? path13__namespace.join(tmpDir, newest) : null;
|
|
3247
3249
|
}
|
|
3248
3250
|
function describeMissingManifest(config, manifestPath) {
|
|
3249
|
-
const outDir =
|
|
3250
|
-
const markerPath =
|
|
3251
|
+
const outDir = path13__namespace.resolve(config.cwd, config.outDir);
|
|
3252
|
+
const markerPath = path13__namespace.join(outDir, ".codebase-snapshot");
|
|
3251
3253
|
let marker2 = null;
|
|
3252
3254
|
try {
|
|
3253
|
-
if (
|
|
3254
|
-
const parsed = JSON.parse(
|
|
3255
|
+
if (fs12__namespace.existsSync(markerPath)) {
|
|
3256
|
+
const parsed = JSON.parse(fs12__namespace.readFileSync(markerPath, "utf8"));
|
|
3255
3257
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
3256
3258
|
marker2 = parsed;
|
|
3257
3259
|
}
|
|
@@ -3287,14 +3289,14 @@ function sha256Hex(buffer) {
|
|
|
3287
3289
|
}
|
|
3288
3290
|
var VERIFY_SNIFF_MAX_BYTES = 8 * 1024 * 1024;
|
|
3289
3291
|
function wouldNowBeIncluded(cwd, relativePath, reason) {
|
|
3290
|
-
const absolutePath =
|
|
3292
|
+
const absolutePath = path13__namespace.join(cwd, relativePath);
|
|
3291
3293
|
try {
|
|
3292
|
-
const stats =
|
|
3294
|
+
const stats = fs12__namespace.statSync(absolutePath);
|
|
3293
3295
|
if (!stats.isFile()) return false;
|
|
3294
3296
|
if (isBinaryFile(absolutePath)) return false;
|
|
3295
3297
|
if (reason !== "binary") return true;
|
|
3296
3298
|
if (stats.size > VERIFY_SNIFF_MAX_BYTES) return false;
|
|
3297
|
-
return !decodeText(
|
|
3299
|
+
return !decodeText(fs12__namespace.readFileSync(absolutePath)).binary;
|
|
3298
3300
|
} catch {
|
|
3299
3301
|
return false;
|
|
3300
3302
|
}
|
|
@@ -3352,8 +3354,8 @@ function describeManifestShapeProblem(value) {
|
|
|
3352
3354
|
function validateSnapshot(configInput) {
|
|
3353
3355
|
assertUsableConfigInput(configInput);
|
|
3354
3356
|
const config = isResolvedConfig(configInput) ? normalizeResolvedConfig(configInput) : resolveConfig(configInput);
|
|
3355
|
-
const manifestPath =
|
|
3356
|
-
if (!
|
|
3357
|
+
const manifestPath = path13__namespace.resolve(config.cwd, config.outDir, "manifest.json");
|
|
3358
|
+
if (!fs12__namespace.existsSync(manifestPath)) {
|
|
3357
3359
|
return {
|
|
3358
3360
|
valid: false,
|
|
3359
3361
|
manifestPresent: false,
|
|
@@ -3364,7 +3366,7 @@ function validateSnapshot(configInput) {
|
|
|
3364
3366
|
}
|
|
3365
3367
|
let manifest;
|
|
3366
3368
|
try {
|
|
3367
|
-
manifest = JSON.parse(
|
|
3369
|
+
manifest = JSON.parse(fs12__namespace.readFileSync(manifestPath, "utf8"));
|
|
3368
3370
|
} catch (err) {
|
|
3369
3371
|
return {
|
|
3370
3372
|
valid: false,
|
|
@@ -3386,7 +3388,7 @@ function validateSnapshot(configInput) {
|
|
|
3386
3388
|
}
|
|
3387
3389
|
const drift = emptyDrift();
|
|
3388
3390
|
const warnings = [];
|
|
3389
|
-
const snapshotDir =
|
|
3391
|
+
const snapshotDir = path13__namespace.resolve(config.cwd, config.outDir);
|
|
3390
3392
|
const manifestFileMap = /* @__PURE__ */ new Map();
|
|
3391
3393
|
for (const file of manifest.files) {
|
|
3392
3394
|
if (file && typeof file.relativePath === "string") {
|
|
@@ -3420,7 +3422,7 @@ function validateSnapshot(configInput) {
|
|
|
3420
3422
|
}
|
|
3421
3423
|
let diskHash;
|
|
3422
3424
|
try {
|
|
3423
|
-
diskHash = sha256Hex(
|
|
3425
|
+
diskHash = sha256Hex(fs12__namespace.readFileSync(path13__namespace.join(config.cwd, diskFile)));
|
|
3424
3426
|
} catch (err) {
|
|
3425
3427
|
if (err.code === "ENOENT") {
|
|
3426
3428
|
drift.missingOnDisk.push(diskFile);
|
|
@@ -3444,7 +3446,7 @@ function validateSnapshot(configInput) {
|
|
|
3444
3446
|
}
|
|
3445
3447
|
let statFailure = null;
|
|
3446
3448
|
try {
|
|
3447
|
-
|
|
3449
|
+
fs12__namespace.statSync(confined);
|
|
3448
3450
|
} catch (err) {
|
|
3449
3451
|
statFailure = err;
|
|
3450
3452
|
}
|
|
@@ -3464,7 +3466,7 @@ function validateSnapshot(configInput) {
|
|
|
3464
3466
|
...Object.values(config.budgets.byLayer)
|
|
3465
3467
|
);
|
|
3466
3468
|
const partNames = /* @__PURE__ */ new Set();
|
|
3467
|
-
const partsDir =
|
|
3469
|
+
const partsDir = path13__namespace.join(snapshotDir, "parts");
|
|
3468
3470
|
for (const part of manifest.parts) {
|
|
3469
3471
|
if (!part || typeof part.filename !== "string") continue;
|
|
3470
3472
|
partNames.add(part.filename);
|
|
@@ -3479,7 +3481,7 @@ function validateSnapshot(configInput) {
|
|
|
3479
3481
|
}
|
|
3480
3482
|
let buffer;
|
|
3481
3483
|
try {
|
|
3482
|
-
buffer =
|
|
3484
|
+
buffer = fs12__namespace.readFileSync(partPath);
|
|
3483
3485
|
} catch {
|
|
3484
3486
|
drift.partIssues.push({ part: part.filename, issue: "missing from snapshot/parts" });
|
|
3485
3487
|
continue;
|
|
@@ -3693,9 +3695,9 @@ function validateSnapshot(configInput) {
|
|
|
3693
3695
|
["full-codebase.md", manifest.artifacts?.fullMarkdown]
|
|
3694
3696
|
]) {
|
|
3695
3697
|
if (!artifact) continue;
|
|
3696
|
-
const artifactPath =
|
|
3698
|
+
const artifactPath = path13__namespace.join(snapshotDir, key);
|
|
3697
3699
|
try {
|
|
3698
|
-
const buffer =
|
|
3700
|
+
const buffer = fs12__namespace.readFileSync(artifactPath);
|
|
3699
3701
|
if (sha256Hex(buffer) !== artifact.sha256 || buffer.length !== artifact.byteSize) {
|
|
3700
3702
|
drift.partIssues.push({ part: key, issue: "artifact does not match its recorded digest" });
|
|
3701
3703
|
}
|
|
@@ -3956,14 +3958,14 @@ function compareManifests(before, after) {
|
|
|
3956
3958
|
function loadManifest(target) {
|
|
3957
3959
|
let isDirectory;
|
|
3958
3960
|
try {
|
|
3959
|
-
isDirectory =
|
|
3961
|
+
isDirectory = fs12__namespace.statSync(target).isDirectory();
|
|
3960
3962
|
} catch {
|
|
3961
3963
|
throw new Error(`No snapshot found at ${target}: the path does not exist.`);
|
|
3962
3964
|
}
|
|
3963
|
-
const manifestPath = isDirectory ?
|
|
3965
|
+
const manifestPath = isDirectory ? path13__namespace.join(target, "manifest.json") : target;
|
|
3964
3966
|
let raw;
|
|
3965
3967
|
try {
|
|
3966
|
-
raw =
|
|
3968
|
+
raw = fs12__namespace.readFileSync(manifestPath, "utf8");
|
|
3967
3969
|
} catch {
|
|
3968
3970
|
throw new Error(`Could not read a manifest at ${manifestPath}.`);
|
|
3969
3971
|
}
|
|
@@ -4114,10 +4116,10 @@ var LANGUAGE_BY_BASENAME = {
|
|
|
4114
4116
|
};
|
|
4115
4117
|
function detectLanguage(filePath) {
|
|
4116
4118
|
const normalized = filePath.replace(/\\/g, "/");
|
|
4117
|
-
const base =
|
|
4119
|
+
const base = path13__namespace.posix.basename(normalized);
|
|
4118
4120
|
if (LANGUAGE_BY_BASENAME[base]) return LANGUAGE_BY_BASENAME[base];
|
|
4119
4121
|
if (base === ".env" || base.startsWith(".env.")) return "dotenv";
|
|
4120
|
-
const ext =
|
|
4122
|
+
const ext = path13__namespace.posix.extname(base).toLowerCase();
|
|
4121
4123
|
return LANGUAGE_BY_EXTENSION[ext] ?? "text";
|
|
4122
4124
|
}
|
|
4123
4125
|
|
|
@@ -4159,10 +4161,10 @@ function describeMatcher(matcher) {
|
|
|
4159
4161
|
return String(matcher);
|
|
4160
4162
|
}
|
|
4161
4163
|
function normalizeTarget(cwd, target) {
|
|
4162
|
-
const absolute =
|
|
4163
|
-
const relative11 =
|
|
4164
|
-
if (relative11.startsWith("..") ||
|
|
4165
|
-
return relative11.split(
|
|
4164
|
+
const absolute = path13__namespace.resolve(cwd, target);
|
|
4165
|
+
const relative11 = path13__namespace.relative(cwd, absolute);
|
|
4166
|
+
if (relative11.startsWith("..") || path13__namespace.isAbsolute(relative11)) return target;
|
|
4167
|
+
return relative11.split(path13__namespace.sep).join("/");
|
|
4166
4168
|
}
|
|
4167
4169
|
function findRuleMatch(rules, relativePath) {
|
|
4168
4170
|
return rules.find(
|
|
@@ -4181,20 +4183,20 @@ function findRecordedAncestor(skipped, relative11, maskedPath2) {
|
|
|
4181
4183
|
return nearest;
|
|
4182
4184
|
}
|
|
4183
4185
|
function readManifest2(config) {
|
|
4184
|
-
const manifestPath =
|
|
4186
|
+
const manifestPath = path13__namespace.resolve(config.cwd, config.outDir, "manifest.json");
|
|
4185
4187
|
try {
|
|
4186
|
-
return JSON.parse(
|
|
4188
|
+
return JSON.parse(fs12__namespace.readFileSync(manifestPath, "utf8"));
|
|
4187
4189
|
} catch {
|
|
4188
4190
|
return null;
|
|
4189
4191
|
}
|
|
4190
4192
|
}
|
|
4191
4193
|
function explainPath(config, target) {
|
|
4192
4194
|
const relative11 = normalizeTarget(config.cwd, target);
|
|
4193
|
-
const absolute =
|
|
4195
|
+
const absolute = path13__namespace.join(config.cwd, relative11);
|
|
4194
4196
|
const maskedPath2 = findSecretInPath(relative11, config.secretRules)?.masked ?? relative11;
|
|
4195
4197
|
const result = {
|
|
4196
4198
|
path: maskedPath2,
|
|
4197
|
-
exists:
|
|
4199
|
+
exists: fs12__namespace.existsSync(absolute),
|
|
4198
4200
|
included: false
|
|
4199
4201
|
};
|
|
4200
4202
|
const collection = collectFiles(config.cwd, {
|
|
@@ -4205,7 +4207,7 @@ function explainPath(config, target) {
|
|
|
4205
4207
|
// Same exclusion `generate` applies, so `explain` never says "not-discovered" about a file
|
|
4206
4208
|
// that is only missing because the walker dropped the tool's own output directory.
|
|
4207
4209
|
toolOwnedPaths: [config.outDir, config.tmpDir].map(
|
|
4208
|
-
(directory) =>
|
|
4210
|
+
(directory) => path13__namespace.relative(config.cwd, path13__namespace.resolve(config.cwd, directory)).replace(/\\/g, "/")
|
|
4209
4211
|
).filter((relative12) => relative12.length > 0 && !relative12.startsWith(".."))
|
|
4210
4212
|
});
|
|
4211
4213
|
if (!collection.files.includes(relative11)) {
|
|
@@ -4244,8 +4246,8 @@ function explainPath(config, target) {
|
|
|
4244
4246
|
if (layerRule) result.layerMatch = describeMatcher(layerRule.match);
|
|
4245
4247
|
const kindRule = findRuleMatch(config.kinds, relative11);
|
|
4246
4248
|
if (kindRule) result.kindMatch = describeMatcher(kindRule.match);
|
|
4247
|
-
if (
|
|
4248
|
-
const buffer =
|
|
4249
|
+
if (fs12__namespace.existsSync(absolute) && fs12__namespace.statSync(absolute).isFile()) {
|
|
4250
|
+
const buffer = fs12__namespace.readFileSync(absolute);
|
|
4249
4251
|
const decoded = decodeText(buffer);
|
|
4250
4252
|
if (decoded.binary) {
|
|
4251
4253
|
result.included = false;
|
|
@@ -4304,15 +4306,15 @@ function renderExplainText(result) {
|
|
|
4304
4306
|
function appendGitignoreEntries(cwd, entries) {
|
|
4305
4307
|
const wanted = [...new Set(entries)].filter((entry) => entry.trim().length > 0);
|
|
4306
4308
|
if (wanted.length === 0) return { added: [], note: null };
|
|
4307
|
-
const ignorePath =
|
|
4309
|
+
const ignorePath = path13__namespace.join(cwd, ".gitignore");
|
|
4308
4310
|
const manual = `Add ${wanted.map((entry) => `"${entry}"`).join(" and ")} to your .gitignore yourself.`;
|
|
4309
4311
|
let existing = "";
|
|
4310
4312
|
try {
|
|
4311
|
-
if (
|
|
4312
|
-
if (
|
|
4313
|
+
if (fs12__namespace.existsSync(ignorePath)) {
|
|
4314
|
+
if (fs12__namespace.statSync(ignorePath).isDirectory()) {
|
|
4313
4315
|
return { added: [], note: `${ignorePath} is a directory, so it was not updated. ${manual}` };
|
|
4314
4316
|
}
|
|
4315
|
-
existing =
|
|
4317
|
+
existing = fs12__namespace.readFileSync(ignorePath, "utf8");
|
|
4316
4318
|
}
|
|
4317
4319
|
} catch (err) {
|
|
4318
4320
|
return {
|
|
@@ -4325,7 +4327,7 @@ function appendGitignoreEntries(cwd, entries) {
|
|
|
4325
4327
|
if (added.length === 0) return { added: [], note: null };
|
|
4326
4328
|
const prefix = existing.length === 0 || existing.endsWith("\n") ? "" : "\n";
|
|
4327
4329
|
try {
|
|
4328
|
-
|
|
4330
|
+
fs12__namespace.writeFileSync(ignorePath, `${existing}${prefix}${added.join("\n")}
|
|
4329
4331
|
`, "utf8");
|
|
4330
4332
|
} catch (err) {
|
|
4331
4333
|
return { added: [], note: `${err.message}. ${manual}` };
|
|
@@ -4333,12 +4335,12 @@ function appendGitignoreEntries(cwd, entries) {
|
|
|
4333
4335
|
return { added, note: null };
|
|
4334
4336
|
}
|
|
4335
4337
|
function gitignorePath(cwd, filePath) {
|
|
4336
|
-
return
|
|
4338
|
+
return path13__namespace.relative(cwd, filePath).split(path13__namespace.sep).join("/");
|
|
4337
4339
|
}
|
|
4338
4340
|
|
|
4339
4341
|
// src/version.ts
|
|
4340
4342
|
var GENERATOR_NAME = "codebase-snapshot";
|
|
4341
|
-
var GENERATOR_VERSION = "0.9.
|
|
4343
|
+
var GENERATOR_VERSION = "0.9.7";
|
|
4342
4344
|
var LEGACY_GENERATOR_NAMES = ["@ankurhalder/codebase-snapshot"];
|
|
4343
4345
|
function isOurGeneratorName(name) {
|
|
4344
4346
|
if (typeof name !== "string") return false;
|
|
@@ -4494,6 +4496,57 @@ function toggleIndex(selected, index) {
|
|
|
4494
4496
|
else next.add(index);
|
|
4495
4497
|
return next;
|
|
4496
4498
|
}
|
|
4499
|
+
function isWideCodePoint(code) {
|
|
4500
|
+
return code >= 4352 && code <= 4447 || // Hangul Jamo
|
|
4501
|
+
code >= 11904 && code <= 12350 || // CJK radicals, Kangxi, CJK symbols
|
|
4502
|
+
code >= 12353 && code <= 13311 || // kana through CJK compatibility
|
|
4503
|
+
code >= 13312 && code <= 19903 || // CJK extension A
|
|
4504
|
+
code >= 19968 && code <= 40959 || // CJK unified ideographs
|
|
4505
|
+
code >= 40960 && code <= 42191 || // Yi
|
|
4506
|
+
code >= 44032 && code <= 55203 || // Hangul syllables
|
|
4507
|
+
code >= 63744 && code <= 64255 || // CJK compatibility ideographs
|
|
4508
|
+
code >= 65072 && code <= 65135 || // CJK compatibility forms
|
|
4509
|
+
code >= 65280 && code <= 65376 || // fullwidth forms
|
|
4510
|
+
code >= 65504 && code <= 65510 || code >= 127744 && code <= 129535 || // emoji and pictographs
|
|
4511
|
+
code >= 131072 && code <= 262141;
|
|
4512
|
+
}
|
|
4513
|
+
var ANSI_PATTERN = /\u001b\[[0-9;?]*[A-Za-z]/g;
|
|
4514
|
+
function displayWidth(line) {
|
|
4515
|
+
let width = 0;
|
|
4516
|
+
for (const character of line.replace(ANSI_PATTERN, "")) {
|
|
4517
|
+
width += isWideCodePoint(character.codePointAt(0) ?? 0) ? 2 : 1;
|
|
4518
|
+
}
|
|
4519
|
+
return width;
|
|
4520
|
+
}
|
|
4521
|
+
function wrapOneLine(line, limit) {
|
|
4522
|
+
if (displayWidth(line) <= limit) return [line];
|
|
4523
|
+
const indent = /^[ \t]*/.exec(line)?.[0] ?? "";
|
|
4524
|
+
const continuation = `${indent} `;
|
|
4525
|
+
const rows = [];
|
|
4526
|
+
let prefix = indent;
|
|
4527
|
+
let rest = line.slice(indent.length).trimEnd();
|
|
4528
|
+
while (rest.length > 0) {
|
|
4529
|
+
const room = limit - displayWidth(prefix);
|
|
4530
|
+
if (room <= 0 || displayWidth(rest) <= room) {
|
|
4531
|
+
rows.push(prefix + rest);
|
|
4532
|
+
break;
|
|
4533
|
+
}
|
|
4534
|
+
let cut = room;
|
|
4535
|
+
const space = rest.slice(0, room).lastIndexOf(" ");
|
|
4536
|
+
if (space > 0) cut = space;
|
|
4537
|
+
const taken = rest.slice(0, cut).trimEnd();
|
|
4538
|
+
rows.push(`${prefix}${taken.length > 0 ? taken : rest.slice(0, cut)}`);
|
|
4539
|
+
rest = rest.slice(cut).trimStart();
|
|
4540
|
+
prefix = continuation;
|
|
4541
|
+
}
|
|
4542
|
+
return rows;
|
|
4543
|
+
}
|
|
4544
|
+
function wrapLines(text2, limit) {
|
|
4545
|
+
const width = Math.max(8, Math.floor(limit));
|
|
4546
|
+
const rows = [];
|
|
4547
|
+
for (const line of text2.split("\n")) rows.push(...wrapOneLine(line, width));
|
|
4548
|
+
return rows;
|
|
4549
|
+
}
|
|
4497
4550
|
function marker(active) {
|
|
4498
4551
|
return active ? "\u276F" : " ";
|
|
4499
4552
|
}
|
|
@@ -4571,14 +4624,27 @@ var Frame = class {
|
|
|
4571
4624
|
drawn = 0;
|
|
4572
4625
|
draw(text2) {
|
|
4573
4626
|
this.erase();
|
|
4574
|
-
this.
|
|
4627
|
+
const rows = wrapLines(text2, this.width());
|
|
4628
|
+
this.output.write(`${rows.join("\n")}
|
|
4575
4629
|
`);
|
|
4576
|
-
this.drawn =
|
|
4630
|
+
this.drawn = rows.length;
|
|
4577
4631
|
}
|
|
4578
4632
|
erase() {
|
|
4579
4633
|
if (this.drawn > 0) this.output.write(`\x1B[${this.drawn}A\x1B[0J`);
|
|
4580
4634
|
this.drawn = 0;
|
|
4581
4635
|
}
|
|
4636
|
+
/**
|
|
4637
|
+
* The usable width, in cells.
|
|
4638
|
+
*
|
|
4639
|
+
* Two cells of slack: an ambiguous-width glyph (`◆`, `❯`, `←`) renders two cells in some fonts
|
|
4640
|
+
* and one in others, and a row that lands exactly on the last column is the one case a terminal
|
|
4641
|
+
* may or may not wrap. Below that, a line cannot reach the edge to begin with.
|
|
4642
|
+
*/
|
|
4643
|
+
width() {
|
|
4644
|
+
const columns = this.output.columns;
|
|
4645
|
+
if (typeof columns !== "number" || !Number.isFinite(columns) || columns <= 0) return 80;
|
|
4646
|
+
return Math.max(8, Math.floor(columns) - 2);
|
|
4647
|
+
}
|
|
4582
4648
|
};
|
|
4583
4649
|
function isCancel(key) {
|
|
4584
4650
|
return key.ctrl === true && key.name === "c" || key.ctrl === true && key.name === "d";
|
|
@@ -4760,10 +4826,10 @@ var CONFIG_CANDIDATES = [
|
|
|
4760
4826
|
];
|
|
4761
4827
|
function chooseConfigFileName(cwd) {
|
|
4762
4828
|
if (!supportsTypeScriptImports()) return "snapshot.config.mjs";
|
|
4763
|
-
const pkgPath =
|
|
4764
|
-
if (!
|
|
4829
|
+
const pkgPath = path13__namespace.join(cwd, "package.json");
|
|
4830
|
+
if (!fs12__namespace.existsSync(pkgPath)) return "snapshot.config.mjs";
|
|
4765
4831
|
try {
|
|
4766
|
-
const parsed = JSON.parse(
|
|
4832
|
+
const parsed = JSON.parse(fs12__namespace.readFileSync(pkgPath, "utf8"));
|
|
4767
4833
|
return parsed.type === "module" ? "snapshot.config.ts" : "snapshot.config.mjs";
|
|
4768
4834
|
} catch {
|
|
4769
4835
|
return "snapshot.config.mjs";
|
|
@@ -4777,7 +4843,7 @@ var SIZE_CHOICES = [
|
|
|
4777
4843
|
];
|
|
4778
4844
|
function packageJsonHasConfig(cwd) {
|
|
4779
4845
|
try {
|
|
4780
|
-
const parsed = JSON.parse(
|
|
4846
|
+
const parsed = JSON.parse(fs12__namespace.readFileSync(path13__namespace.join(cwd, "package.json"), "utf8"));
|
|
4781
4847
|
return typeof parsed.snapshot === "object" && parsed.snapshot !== null && !Array.isArray(parsed.snapshot);
|
|
4782
4848
|
} catch {
|
|
4783
4849
|
return false;
|
|
@@ -4798,7 +4864,7 @@ function artifactAnswers(options) {
|
|
|
4798
4864
|
}
|
|
4799
4865
|
function topLevelDirs(cwd) {
|
|
4800
4866
|
try {
|
|
4801
|
-
return
|
|
4867
|
+
return fs12__namespace.readdirSync(cwd, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules").map((entry) => entry.name).sort();
|
|
4802
4868
|
} catch {
|
|
4803
4869
|
return [];
|
|
4804
4870
|
}
|
|
@@ -4811,7 +4877,7 @@ function describeJsonValue(value) {
|
|
|
4811
4877
|
}
|
|
4812
4878
|
function writeFileOrExplain(target, content) {
|
|
4813
4879
|
try {
|
|
4814
|
-
|
|
4880
|
+
fs12__namespace.writeFileSync(target, content, "utf8");
|
|
4815
4881
|
} catch (err) {
|
|
4816
4882
|
const code = err.code;
|
|
4817
4883
|
const reason = code === "EACCES" || code === "EPERM" || code === "EROFS" ? `permission denied (${code})` : code === "EISDIR" ? "it is a directory" : `${err.message}`;
|
|
@@ -4822,7 +4888,7 @@ function canWriteModuleConfig(name, cwd) {
|
|
|
4822
4888
|
if (name.endsWith(".mjs") || name.endsWith(".ts")) return true;
|
|
4823
4889
|
if (!name.endsWith(".js")) return false;
|
|
4824
4890
|
try {
|
|
4825
|
-
const parsed = JSON.parse(
|
|
4891
|
+
const parsed = JSON.parse(fs12__namespace.readFileSync(path13__namespace.join(cwd, "package.json"), "utf8"));
|
|
4826
4892
|
return parsed.type === "module";
|
|
4827
4893
|
} catch {
|
|
4828
4894
|
return false;
|
|
@@ -4857,19 +4923,19 @@ function serializePackageJson(raw, value) {
|
|
|
4857
4923
|
return `${text2}${raw.endsWith("\n") ? crlf ? "\r\n" : "\n" : ""}`;
|
|
4858
4924
|
}
|
|
4859
4925
|
function updatePackageJson(cwd, notes) {
|
|
4860
|
-
const packagePath =
|
|
4926
|
+
const packagePath = path13__namespace.join(cwd, "package.json");
|
|
4861
4927
|
const unchanged = {
|
|
4862
4928
|
scripts: [],
|
|
4863
4929
|
dependency: { name: GENERATOR_NAME, range: null, added: false }
|
|
4864
4930
|
};
|
|
4865
|
-
if (!
|
|
4931
|
+
if (!fs12__namespace.existsSync(packagePath)) {
|
|
4866
4932
|
notes.push("No package.json found, so npm scripts and the devDependency were not added.");
|
|
4867
4933
|
return unchanged;
|
|
4868
4934
|
}
|
|
4869
4935
|
let raw;
|
|
4870
4936
|
let parsed;
|
|
4871
4937
|
try {
|
|
4872
|
-
raw =
|
|
4938
|
+
raw = fs12__namespace.readFileSync(packagePath, "utf8");
|
|
4873
4939
|
parsed = JSON.parse(raw);
|
|
4874
4940
|
} catch {
|
|
4875
4941
|
notes.push("Could not parse package.json; npm scripts and the devDependency were not added.");
|
|
@@ -5161,7 +5227,7 @@ async function runInit(options) {
|
|
|
5161
5227
|
const configText = renderConfig(answers);
|
|
5162
5228
|
const preferredName = chooseConfigFileName(options.cwd);
|
|
5163
5229
|
const presentConfigs = CONFIG_CANDIDATES.filter(
|
|
5164
|
-
(name) =>
|
|
5230
|
+
(name) => fs12__namespace.existsSync(path13__namespace.join(options.cwd, name))
|
|
5165
5231
|
);
|
|
5166
5232
|
const present = presentConfigs[0] ?? null;
|
|
5167
5233
|
if (presentConfigs.length > 1) {
|
|
@@ -5170,7 +5236,7 @@ async function runInit(options) {
|
|
|
5170
5236
|
);
|
|
5171
5237
|
}
|
|
5172
5238
|
const configName = present !== null && options.force ? present : preferredName;
|
|
5173
|
-
const configPath =
|
|
5239
|
+
const configPath = path13__namespace.join(options.cwd, configName);
|
|
5174
5240
|
const reused = present !== null && options.force !== true && options.reuseConfig === true;
|
|
5175
5241
|
if (reused) notes.push(`Kept the existing ${present} instead of writing a new one.`);
|
|
5176
5242
|
if (options.dryRun) {
|
|
@@ -5203,7 +5269,7 @@ async function runInit(options) {
|
|
|
5203
5269
|
'package.json already defines a "snapshot" config. Remove that key, or re-run with --force to write a config file that takes precedence over it.'
|
|
5204
5270
|
);
|
|
5205
5271
|
}
|
|
5206
|
-
if (
|
|
5272
|
+
if (fs12__namespace.existsSync(configPath) && !options.force && !reused) {
|
|
5207
5273
|
throw new Error(`${configName} already exists. Re-run with --force to replace it.`);
|
|
5208
5274
|
}
|
|
5209
5275
|
if (!reused) writeFileOrExplain(configPath, configText);
|
|
@@ -5225,9 +5291,9 @@ async function runInit(options) {
|
|
|
5225
5291
|
};
|
|
5226
5292
|
}
|
|
5227
5293
|
function describeTarget(cwd) {
|
|
5228
|
-
const relative11 =
|
|
5294
|
+
const relative11 = path13__namespace.relative(process.cwd(), cwd);
|
|
5229
5295
|
if (relative11 === "") return "this directory";
|
|
5230
|
-
if (relative11.startsWith("..") ||
|
|
5296
|
+
if (relative11.startsWith("..") || path13__namespace.isAbsolute(relative11)) return cwd;
|
|
5231
5297
|
return relative11;
|
|
5232
5298
|
}
|
|
5233
5299
|
function firstRunMessage(reason, cwd) {
|
|
@@ -5251,7 +5317,7 @@ function planFirstRun(facts) {
|
|
|
5251
5317
|
var NOT_CONTENT = /* @__PURE__ */ new Set([".git", ".hg", ".svn", ".bzr", ".DS_Store", "Thumbs.db"]);
|
|
5252
5318
|
function isEffectivelyEmpty(cwd) {
|
|
5253
5319
|
try {
|
|
5254
|
-
return
|
|
5320
|
+
return fs12__namespace.readdirSync(cwd).every((entry) => NOT_CONTENT.has(entry));
|
|
5255
5321
|
} catch {
|
|
5256
5322
|
return false;
|
|
5257
5323
|
}
|
|
@@ -5259,7 +5325,7 @@ function isEffectivelyEmpty(cwd) {
|
|
|
5259
5325
|
function hasPriorSnapshot(cwd, outDir) {
|
|
5260
5326
|
let parsed;
|
|
5261
5327
|
try {
|
|
5262
|
-
parsed = JSON.parse(
|
|
5328
|
+
parsed = JSON.parse(fs12__namespace.readFileSync(path13__namespace.join(cwd, outDir, ".codebase-snapshot"), "utf8"));
|
|
5263
5329
|
} catch {
|
|
5264
5330
|
return false;
|
|
5265
5331
|
}
|
|
@@ -5489,9 +5555,9 @@ var JAVA_METHOD = /^\s+(?:public|private|protected)\s+(?:static\s+)?(?:final\s+)
|
|
|
5489
5555
|
var jvmProfile = {
|
|
5490
5556
|
id: "jvm",
|
|
5491
5557
|
extensions: [".java", ".kt", ".kts", ".scala"],
|
|
5492
|
-
summarize(
|
|
5558
|
+
summarize(path19, content) {
|
|
5493
5559
|
const summary = emptySummary();
|
|
5494
|
-
const lower =
|
|
5560
|
+
const lower = path19.toLowerCase();
|
|
5495
5561
|
const isJava = lower.endsWith(".java");
|
|
5496
5562
|
const isKotlin = lower.endsWith(".kt") || lower.endsWith(".kts");
|
|
5497
5563
|
eachLine(content, (line) => {
|
|
@@ -5944,16 +6010,16 @@ function summarizeTypeScriptSource(relativePath, content) {
|
|
|
5944
6010
|
// src/ast/profiles/sfc.ts
|
|
5945
6011
|
var SCRIPT_BLOCK = /<script[^>]*>([\s\S]*?)<\/script>/gi;
|
|
5946
6012
|
var ASTRO_FRONTMATTER = /^\uFEFF?---[ \t]*\r?\n([\s\S]*?)\r?\n---[ \t]*(?=\r?\n|$)/;
|
|
5947
|
-
function componentName(
|
|
5948
|
-
const base =
|
|
6013
|
+
function componentName(path19) {
|
|
6014
|
+
const base = path19.split("/").pop() ?? path19;
|
|
5949
6015
|
return base.replace(/\.[^.]+$/, "");
|
|
5950
6016
|
}
|
|
5951
6017
|
var sfcProfile = {
|
|
5952
6018
|
id: "sfc",
|
|
5953
6019
|
extensions: [".vue", ".svelte", ".astro"],
|
|
5954
|
-
summarize(
|
|
6020
|
+
summarize(path19, content) {
|
|
5955
6021
|
let script = "";
|
|
5956
|
-
if (
|
|
6022
|
+
if (path19.toLowerCase().endsWith(".astro")) {
|
|
5957
6023
|
const frontmatter = ASTRO_FRONTMATTER.exec(content);
|
|
5958
6024
|
if (frontmatter) script += `${frontmatter[1]}
|
|
5959
6025
|
`;
|
|
@@ -5962,7 +6028,7 @@ var sfcProfile = {
|
|
|
5962
6028
|
script += `${match[1]}
|
|
5963
6029
|
`;
|
|
5964
6030
|
}
|
|
5965
|
-
const name = componentName(
|
|
6031
|
+
const name = componentName(path19);
|
|
5966
6032
|
if (!script.trim()) {
|
|
5967
6033
|
const summary2 = emptySummary();
|
|
5968
6034
|
if (name) {
|
|
@@ -5996,15 +6062,15 @@ for (const profile of LANGUAGE_PROFILES) {
|
|
|
5996
6062
|
BY_EXTENSION.set(extension.toLowerCase(), profile);
|
|
5997
6063
|
}
|
|
5998
6064
|
}
|
|
5999
|
-
function profileForPath(
|
|
6000
|
-
const lower =
|
|
6065
|
+
function profileForPath(path19) {
|
|
6066
|
+
const lower = path19.toLowerCase();
|
|
6001
6067
|
const dot = lower.lastIndexOf(".");
|
|
6002
6068
|
if (dot === -1) return null;
|
|
6003
6069
|
return BY_EXTENSION.get(lower.slice(dot)) ?? null;
|
|
6004
6070
|
}
|
|
6005
|
-
function summarizeWithProfile(
|
|
6006
|
-
const profile = profileForPath(
|
|
6007
|
-
return profile ? profile.summarize(
|
|
6071
|
+
function summarizeWithProfile(path19, content) {
|
|
6072
|
+
const profile = profileForPath(path19);
|
|
6073
|
+
return profile ? profile.summarize(path19, content) : null;
|
|
6008
6074
|
}
|
|
6009
6075
|
|
|
6010
6076
|
// src/ast/structured.ts
|
|
@@ -6849,6 +6915,162 @@ function generateProjectTree(filePaths) {
|
|
|
6849
6915
|
const fence = fenceForText(lines.join("\n"), 3);
|
|
6850
6916
|
return ["# Project Tree", "", `${fence}text`, ...lines, fence, ""].join("\n");
|
|
6851
6917
|
}
|
|
6918
|
+
var PACKAGE_LATEST_URL = "https://registry.npmjs.org/codebase-snapshot/latest";
|
|
6919
|
+
var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
6920
|
+
var FAILURE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
6921
|
+
var REQUEST_TIMEOUT_MS = 1200;
|
|
6922
|
+
function versionParts(value) {
|
|
6923
|
+
const core = value.trim().replace(/^v/i, "").split("-")[0];
|
|
6924
|
+
return core.split(".").map((part) => {
|
|
6925
|
+
const parsed = Number(part);
|
|
6926
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
6927
|
+
});
|
|
6928
|
+
}
|
|
6929
|
+
function isNewer(candidate, current) {
|
|
6930
|
+
const left = versionParts(candidate);
|
|
6931
|
+
const right = versionParts(current);
|
|
6932
|
+
const length = Math.max(left.length, right.length);
|
|
6933
|
+
for (let index = 0; index < length; index += 1) {
|
|
6934
|
+
const a = left[index] ?? 0;
|
|
6935
|
+
const b = right[index] ?? 0;
|
|
6936
|
+
if (a !== b) return a > b;
|
|
6937
|
+
}
|
|
6938
|
+
return false;
|
|
6939
|
+
}
|
|
6940
|
+
function cacheDirectory(env = process.env, platform = process.platform) {
|
|
6941
|
+
if (platform === "win32") {
|
|
6942
|
+
const base2 = env.LOCALAPPDATA ?? path13__namespace.join(os__namespace.homedir(), "AppData", "Local");
|
|
6943
|
+
return path13__namespace.join(base2, "codebase-snapshot");
|
|
6944
|
+
}
|
|
6945
|
+
if (platform === "darwin") {
|
|
6946
|
+
return path13__namespace.join(os__namespace.homedir(), "Library", "Caches", "codebase-snapshot");
|
|
6947
|
+
}
|
|
6948
|
+
const base = env.XDG_CACHE_HOME ?? path13__namespace.join(os__namespace.homedir(), ".cache");
|
|
6949
|
+
return path13__namespace.join(base, "codebase-snapshot");
|
|
6950
|
+
}
|
|
6951
|
+
function cacheFilePath(env = process.env) {
|
|
6952
|
+
return path13__namespace.join(cacheDirectory(env), "update-check.json");
|
|
6953
|
+
}
|
|
6954
|
+
function shouldCheck(argv, env) {
|
|
6955
|
+
const disabled = ["1", "true", "yes"].includes(
|
|
6956
|
+
String(env.CODEBASE_SNAPSHOT_NO_UPDATE_CHECK ?? "").toLowerCase()
|
|
6957
|
+
);
|
|
6958
|
+
if (disabled) return false;
|
|
6959
|
+
if (env.CI !== void 0 && env.CI !== "" && env.CI !== "false" && env.CI !== "0") return false;
|
|
6960
|
+
const args = argv.map((argument) => argument.toLowerCase());
|
|
6961
|
+
if (args.includes("--no-update-check")) return false;
|
|
6962
|
+
for (const skip of ["mcp", "describe", "skill", "--version", "-v", "--help", "-h"]) {
|
|
6963
|
+
if (args.includes(skip)) return false;
|
|
6964
|
+
}
|
|
6965
|
+
if (args.some((argument) => argument.includes("json"))) return false;
|
|
6966
|
+
return true;
|
|
6967
|
+
}
|
|
6968
|
+
function readCache(file) {
|
|
6969
|
+
let raw;
|
|
6970
|
+
try {
|
|
6971
|
+
raw = fs12__namespace.readFileSync(file, "utf8");
|
|
6972
|
+
} catch {
|
|
6973
|
+
return null;
|
|
6974
|
+
}
|
|
6975
|
+
try {
|
|
6976
|
+
const parsed = JSON.parse(raw);
|
|
6977
|
+
if (typeof parsed !== "object" || parsed === null) return null;
|
|
6978
|
+
const candidate = parsed;
|
|
6979
|
+
if (typeof candidate.checkedAt !== "number") return null;
|
|
6980
|
+
const latest = typeof candidate.latest === "string" ? candidate.latest : null;
|
|
6981
|
+
return { checkedAt: candidate.checkedAt, latest };
|
|
6982
|
+
} catch {
|
|
6983
|
+
return null;
|
|
6984
|
+
}
|
|
6985
|
+
}
|
|
6986
|
+
function writeCache(file, entry) {
|
|
6987
|
+
try {
|
|
6988
|
+
fs12__namespace.mkdirSync(path13__namespace.dirname(file), { recursive: true });
|
|
6989
|
+
fs12__namespace.writeFileSync(file, `${JSON.stringify(entry)}
|
|
6990
|
+
`, "utf8");
|
|
6991
|
+
} catch {
|
|
6992
|
+
}
|
|
6993
|
+
}
|
|
6994
|
+
function fetchLatestVersion(url = PACKAGE_LATEST_URL, timeoutMs = REQUEST_TIMEOUT_MS) {
|
|
6995
|
+
return new Promise((resolve9) => {
|
|
6996
|
+
let settled = false;
|
|
6997
|
+
const finish = (value) => {
|
|
6998
|
+
if (settled) return;
|
|
6999
|
+
settled = true;
|
|
7000
|
+
resolve9(value);
|
|
7001
|
+
};
|
|
7002
|
+
const request = https__namespace.get(
|
|
7003
|
+
url,
|
|
7004
|
+
{
|
|
7005
|
+
headers: {
|
|
7006
|
+
accept: "application/json",
|
|
7007
|
+
"user-agent": "codebase-snapshot (update check)"
|
|
7008
|
+
}
|
|
7009
|
+
},
|
|
7010
|
+
(response) => {
|
|
7011
|
+
if (response.statusCode !== 200) {
|
|
7012
|
+
response.resume();
|
|
7013
|
+
finish(null);
|
|
7014
|
+
return;
|
|
7015
|
+
}
|
|
7016
|
+
let body = "";
|
|
7017
|
+
response.setEncoding("utf8");
|
|
7018
|
+
response.on("data", (chunk) => {
|
|
7019
|
+
body += chunk;
|
|
7020
|
+
if (body.length > 64 * 1024) {
|
|
7021
|
+
request.destroy();
|
|
7022
|
+
finish(null);
|
|
7023
|
+
}
|
|
7024
|
+
});
|
|
7025
|
+
response.on("end", () => {
|
|
7026
|
+
try {
|
|
7027
|
+
const parsed = JSON.parse(body);
|
|
7028
|
+
finish(typeof parsed.version === "string" ? parsed.version : null);
|
|
7029
|
+
} catch {
|
|
7030
|
+
finish(null);
|
|
7031
|
+
}
|
|
7032
|
+
});
|
|
7033
|
+
}
|
|
7034
|
+
);
|
|
7035
|
+
request.on("error", () => finish(null));
|
|
7036
|
+
request.setTimeout(timeoutMs, () => {
|
|
7037
|
+
request.destroy();
|
|
7038
|
+
finish(null);
|
|
7039
|
+
});
|
|
7040
|
+
});
|
|
7041
|
+
}
|
|
7042
|
+
async function checkForUpdate(options) {
|
|
7043
|
+
if (options.enabled === false) return null;
|
|
7044
|
+
const now = options.now ?? (() => Date.now());
|
|
7045
|
+
const fetchLatest = options.fetchLatest ?? fetchLatestVersion;
|
|
7046
|
+
let latest = null;
|
|
7047
|
+
try {
|
|
7048
|
+
const cached = readCache(options.cacheFile);
|
|
7049
|
+
let needsFetch = cached === null;
|
|
7050
|
+
if (cached) {
|
|
7051
|
+
const age = now() - cached.checkedAt;
|
|
7052
|
+
if (cached.latest === null) {
|
|
7053
|
+
needsFetch = age >= FAILURE_INTERVAL_MS;
|
|
7054
|
+
} else {
|
|
7055
|
+
latest = cached.latest;
|
|
7056
|
+
needsFetch = age >= CHECK_INTERVAL_MS;
|
|
7057
|
+
}
|
|
7058
|
+
}
|
|
7059
|
+
if (needsFetch) {
|
|
7060
|
+
const fetched = await fetchLatest(PACKAGE_LATEST_URL, REQUEST_TIMEOUT_MS);
|
|
7061
|
+
writeCache(options.cacheFile, { checkedAt: now(), latest: fetched });
|
|
7062
|
+
latest = fetched;
|
|
7063
|
+
}
|
|
7064
|
+
} catch {
|
|
7065
|
+
return null;
|
|
7066
|
+
}
|
|
7067
|
+
if (!latest) return null;
|
|
7068
|
+
return isNewer(latest, options.current) ? { current: options.current, latest } : null;
|
|
7069
|
+
}
|
|
7070
|
+
function formatUpdateNotice(notice) {
|
|
7071
|
+
return `\u2191 codebase-snapshot ${notice.latest} is available \u2014 you have ${notice.current}.
|
|
7072
|
+
npm install -g codebase-snapshot`;
|
|
7073
|
+
}
|
|
6852
7074
|
|
|
6853
7075
|
// src/index.ts
|
|
6854
7076
|
var SCHEMA_VERSION = "3.0.0";
|
|
@@ -6930,13 +7152,13 @@ function buildImportResolver(files) {
|
|
|
6930
7152
|
const relativePath = file.relativePath;
|
|
6931
7153
|
remember(byPath, relativePath, relativePath);
|
|
6932
7154
|
remember(byPathFolded, relativePath.toLowerCase(), relativePath);
|
|
6933
|
-
const extension =
|
|
7155
|
+
const extension = path13__namespace.posix.extname(relativePath);
|
|
6934
7156
|
if (!SOURCE_EXTENSIONS.has(extension)) continue;
|
|
6935
7157
|
const stem = relativePath.slice(0, -extension.length);
|
|
6936
7158
|
remember(byStem, stem, relativePath);
|
|
6937
7159
|
remember(byStemFolded, stem.toLowerCase(), relativePath);
|
|
6938
|
-
if (
|
|
6939
|
-
const directory =
|
|
7160
|
+
if (path13__namespace.posix.basename(stem) === "index") {
|
|
7161
|
+
const directory = path13__namespace.posix.dirname(stem);
|
|
6940
7162
|
remember(byStem, directory, relativePath);
|
|
6941
7163
|
remember(byStemFolded, directory.toLowerCase(), relativePath);
|
|
6942
7164
|
}
|
|
@@ -6945,8 +7167,8 @@ function buildImportResolver(files) {
|
|
|
6945
7167
|
}
|
|
6946
7168
|
function resolveSpecifier(fromFile, specifier, resolver) {
|
|
6947
7169
|
if (!RELATIVE_SPECIFIER.test(specifier)) return null;
|
|
6948
|
-
const joined =
|
|
6949
|
-
|
|
7170
|
+
const joined = path13__namespace.posix.normalize(
|
|
7171
|
+
path13__namespace.posix.join(path13__namespace.posix.dirname(fromFile), specifier)
|
|
6950
7172
|
);
|
|
6951
7173
|
const exact = (key) => resolver.byPath.get(key) ?? resolver.byPathFolded.get(key.toLowerCase()) ?? null;
|
|
6952
7174
|
const direct = exact(joined);
|
|
@@ -7039,11 +7261,11 @@ function verifyInMemory(files, parts, maxPartBytes) {
|
|
|
7039
7261
|
return errors;
|
|
7040
7262
|
}
|
|
7041
7263
|
function resolveSafeOutputDirs(config) {
|
|
7042
|
-
const cwd =
|
|
7043
|
-
const outDir =
|
|
7044
|
-
const tmpDir =
|
|
7045
|
-
const root =
|
|
7046
|
-
const contains = (parent, child) => child === parent || child.startsWith(`${parent}${
|
|
7264
|
+
const cwd = path13__namespace.resolve(config.cwd);
|
|
7265
|
+
const outDir = path13__namespace.resolve(cwd, config.outDir);
|
|
7266
|
+
const tmpDir = path13__namespace.resolve(cwd, config.tmpDir);
|
|
7267
|
+
const root = path13__namespace.parse(cwd).root;
|
|
7268
|
+
const contains = (parent, child) => child === parent || child.startsWith(`${parent}${path13__namespace.sep}`);
|
|
7047
7269
|
const reject = (reason) => {
|
|
7048
7270
|
throw new Error(
|
|
7049
7271
|
`Refusing to generate: ${reason}. outDir=${outDir} tmpDir=${tmpDir} cwd=${cwd}`
|
|
@@ -7099,14 +7321,14 @@ function listEntries(dir) {
|
|
|
7099
7321
|
const walk = (absolute, prefix) => {
|
|
7100
7322
|
let children;
|
|
7101
7323
|
try {
|
|
7102
|
-
children =
|
|
7324
|
+
children = fs12__namespace.readdirSync(absolute, { withFileTypes: true });
|
|
7103
7325
|
} catch {
|
|
7104
7326
|
return;
|
|
7105
7327
|
}
|
|
7106
7328
|
for (const child of children) {
|
|
7107
7329
|
const relative11 = prefix === "" ? child.name : `${prefix}/${child.name}`;
|
|
7108
7330
|
entries.push(relative11);
|
|
7109
|
-
if (child.isDirectory()) walk(
|
|
7331
|
+
if (child.isDirectory()) walk(path13__namespace.join(absolute, child.name), relative11);
|
|
7110
7332
|
}
|
|
7111
7333
|
};
|
|
7112
7334
|
walk(dir, "");
|
|
@@ -7123,28 +7345,28 @@ function markerPayload(dir, state, id, createdAt) {
|
|
|
7123
7345
|
pid: process.pid,
|
|
7124
7346
|
entries: listEntries(dir)
|
|
7125
7347
|
};
|
|
7126
|
-
const manifestPath =
|
|
7127
|
-
if (
|
|
7128
|
-
marker2.manifestSha256 = sha256Hex2(
|
|
7348
|
+
const manifestPath = path13__namespace.join(dir, "manifest.json");
|
|
7349
|
+
if (fs12__namespace.existsSync(manifestPath)) {
|
|
7350
|
+
marker2.manifestSha256 = sha256Hex2(fs12__namespace.readFileSync(manifestPath));
|
|
7129
7351
|
}
|
|
7130
7352
|
return marker2;
|
|
7131
7353
|
}
|
|
7132
7354
|
function writeOwnershipMarker(dir, marker2) {
|
|
7133
|
-
|
|
7134
|
-
|
|
7355
|
+
fs12__namespace.writeFileSync(
|
|
7356
|
+
path13__namespace.join(dir, OWNERSHIP_MARKER),
|
|
7135
7357
|
`${JSON.stringify(marker2, null, 2)}
|
|
7136
7358
|
`,
|
|
7137
7359
|
"utf8"
|
|
7138
7360
|
);
|
|
7139
7361
|
}
|
|
7140
7362
|
function readOwnershipMarker(dir) {
|
|
7141
|
-
const markerPath =
|
|
7142
|
-
if (!
|
|
7363
|
+
const markerPath = path13__namespace.join(dir, OWNERSHIP_MARKER);
|
|
7364
|
+
if (!fs12__namespace.existsSync(markerPath)) {
|
|
7143
7365
|
return { marker: null, problem: "it holds no .codebase-snapshot marker" };
|
|
7144
7366
|
}
|
|
7145
7367
|
let raw;
|
|
7146
7368
|
try {
|
|
7147
|
-
raw =
|
|
7369
|
+
raw = fs12__namespace.readFileSync(markerPath, "utf8");
|
|
7148
7370
|
} catch {
|
|
7149
7371
|
return { marker: null, problem: "its .codebase-snapshot marker could not be read" };
|
|
7150
7372
|
}
|
|
@@ -7212,11 +7434,11 @@ function assessSnapshotDirectory(dir) {
|
|
|
7212
7434
|
marker: marker2
|
|
7213
7435
|
};
|
|
7214
7436
|
}
|
|
7215
|
-
const manifestPath =
|
|
7216
|
-
if (
|
|
7437
|
+
const manifestPath = path13__namespace.join(dir, "manifest.json");
|
|
7438
|
+
if (fs12__namespace.existsSync(manifestPath)) {
|
|
7217
7439
|
let raw;
|
|
7218
7440
|
try {
|
|
7219
|
-
raw =
|
|
7441
|
+
raw = fs12__namespace.readFileSync(manifestPath, "utf8");
|
|
7220
7442
|
} catch {
|
|
7221
7443
|
return {
|
|
7222
7444
|
owned: false,
|
|
@@ -7298,13 +7520,13 @@ function containsNoFiles(dir) {
|
|
|
7298
7520
|
const current = pending.pop();
|
|
7299
7521
|
let entries;
|
|
7300
7522
|
try {
|
|
7301
|
-
entries =
|
|
7523
|
+
entries = fs12__namespace.readdirSync(current, { withFileTypes: true });
|
|
7302
7524
|
} catch {
|
|
7303
7525
|
return false;
|
|
7304
7526
|
}
|
|
7305
7527
|
for (const entry of entries) {
|
|
7306
7528
|
if (entry.isDirectory()) {
|
|
7307
|
-
pending.push(
|
|
7529
|
+
pending.push(path13__namespace.join(current, entry.name));
|
|
7308
7530
|
} else if (!IGNORABLE_ENTRIES.has(entry.name)) {
|
|
7309
7531
|
return false;
|
|
7310
7532
|
}
|
|
@@ -7313,13 +7535,13 @@ function containsNoFiles(dir) {
|
|
|
7313
7535
|
return true;
|
|
7314
7536
|
}
|
|
7315
7537
|
function assertReplaceable(target, label, secretRules) {
|
|
7316
|
-
if (!
|
|
7317
|
-
if (!
|
|
7538
|
+
if (!fs12__namespace.existsSync(target)) return;
|
|
7539
|
+
if (!fs12__namespace.statSync(target).isDirectory()) {
|
|
7318
7540
|
throw new Error(
|
|
7319
7541
|
`Refusing to write into ${label} ${target}: it exists but is not a directory.`
|
|
7320
7542
|
);
|
|
7321
7543
|
}
|
|
7322
|
-
const entries =
|
|
7544
|
+
const entries = fs12__namespace.readdirSync(target);
|
|
7323
7545
|
if (entries.length === 0) return;
|
|
7324
7546
|
if (entries.every((name) => IGNORABLE_ENTRIES.has(name))) return;
|
|
7325
7547
|
if (containsNoFiles(target)) return;
|
|
@@ -7339,18 +7561,18 @@ function assertReplaceable(target, label, secretRules) {
|
|
|
7339
7561
|
);
|
|
7340
7562
|
}
|
|
7341
7563
|
function assertStagingRootUsable(tmpDir, secretRules) {
|
|
7342
|
-
if (!
|
|
7343
|
-
if (!
|
|
7564
|
+
if (!fs12__namespace.existsSync(tmpDir)) return;
|
|
7565
|
+
if (!fs12__namespace.statSync(tmpDir).isDirectory()) {
|
|
7344
7566
|
throw new Error(`Refusing to write into tmpDir ${tmpDir}: it exists but is not a directory.`);
|
|
7345
7567
|
}
|
|
7346
|
-
const entries =
|
|
7568
|
+
const entries = fs12__namespace.readdirSync(tmpDir);
|
|
7347
7569
|
if (entries.length === 0) return;
|
|
7348
7570
|
const foreign = entries.filter((name) => {
|
|
7349
|
-
const full =
|
|
7571
|
+
const full = path13__namespace.join(tmpDir, name);
|
|
7350
7572
|
if (!name.startsWith(RUN_DIR_PREFIX)) return true;
|
|
7351
7573
|
let stats;
|
|
7352
7574
|
try {
|
|
7353
|
-
stats =
|
|
7575
|
+
stats = fs12__namespace.statSync(full);
|
|
7354
7576
|
} catch {
|
|
7355
7577
|
return true;
|
|
7356
7578
|
}
|
|
@@ -7358,7 +7580,7 @@ function assertStagingRootUsable(tmpDir, secretRules) {
|
|
|
7358
7580
|
const { marker: marker2 } = readOwnershipMarker(full);
|
|
7359
7581
|
if (marker2) return false;
|
|
7360
7582
|
try {
|
|
7361
|
-
return
|
|
7583
|
+
return fs12__namespace.readdirSync(full).length > 0;
|
|
7362
7584
|
} catch {
|
|
7363
7585
|
return true;
|
|
7364
7586
|
}
|
|
@@ -7373,13 +7595,13 @@ function assertStagingRootUsable(tmpDir, secretRules) {
|
|
|
7373
7595
|
function cleanStaleRunDirs(tmpDir) {
|
|
7374
7596
|
let entries;
|
|
7375
7597
|
try {
|
|
7376
|
-
entries =
|
|
7598
|
+
entries = fs12__namespace.readdirSync(tmpDir);
|
|
7377
7599
|
} catch {
|
|
7378
7600
|
return;
|
|
7379
7601
|
}
|
|
7380
7602
|
for (const name of entries) {
|
|
7381
7603
|
if (!name.startsWith(RUN_DIR_PREFIX)) continue;
|
|
7382
|
-
const full =
|
|
7604
|
+
const full = path13__namespace.join(tmpDir, name);
|
|
7383
7605
|
const { marker: marker2 } = readOwnershipMarker(full);
|
|
7384
7606
|
if (marker2) {
|
|
7385
7607
|
const created = Date.parse(marker2.createdAt);
|
|
@@ -7387,33 +7609,33 @@ function cleanStaleRunDirs(tmpDir) {
|
|
|
7387
7609
|
const abandoned = typeof marker2.pid === "number" && !isProcessAlive(marker2.pid);
|
|
7388
7610
|
if (aged || abandoned) {
|
|
7389
7611
|
try {
|
|
7390
|
-
|
|
7612
|
+
fs12__namespace.rmSync(full, { recursive: true, force: true });
|
|
7391
7613
|
} catch {
|
|
7392
7614
|
}
|
|
7393
7615
|
}
|
|
7394
7616
|
continue;
|
|
7395
7617
|
}
|
|
7396
7618
|
try {
|
|
7397
|
-
if (
|
|
7619
|
+
if (fs12__namespace.readdirSync(full).length === 0) fs12__namespace.rmSync(full, { recursive: true, force: true });
|
|
7398
7620
|
} catch {
|
|
7399
7621
|
}
|
|
7400
7622
|
}
|
|
7401
7623
|
}
|
|
7402
7624
|
function removeIfEmpty(dir) {
|
|
7403
7625
|
try {
|
|
7404
|
-
if (
|
|
7626
|
+
if (fs12__namespace.readdirSync(dir).length === 0) fs12__namespace.rmSync(dir, { recursive: true, force: true });
|
|
7405
7627
|
} catch {
|
|
7406
7628
|
}
|
|
7407
7629
|
}
|
|
7408
7630
|
function ensureParentDirectory(target, label) {
|
|
7409
|
-
const parent =
|
|
7410
|
-
if (
|
|
7631
|
+
const parent = path13__namespace.dirname(target);
|
|
7632
|
+
if (fs12__namespace.existsSync(parent) && !fs12__namespace.statSync(parent).isDirectory()) {
|
|
7411
7633
|
throw new Error(
|
|
7412
7634
|
`Refusing to create ${label} ${target}: ${parent} exists but is not a directory.`
|
|
7413
7635
|
);
|
|
7414
7636
|
}
|
|
7415
7637
|
try {
|
|
7416
|
-
|
|
7638
|
+
fs12__namespace.mkdirSync(parent, { recursive: true });
|
|
7417
7639
|
} catch (err) {
|
|
7418
7640
|
throw new Error(
|
|
7419
7641
|
`Refusing to create ${label} ${target}: its parent ${parent} could not be created (${err.message}).`
|
|
@@ -7422,7 +7644,7 @@ function ensureParentDirectory(target, label) {
|
|
|
7422
7644
|
}
|
|
7423
7645
|
function acquireRunLock(stagingRoot) {
|
|
7424
7646
|
const key = lockKeyFor(stagingRoot);
|
|
7425
|
-
const lockPath =
|
|
7647
|
+
const lockPath = path13__namespace.join(os__namespace.tmpdir(), `codebase-snapshot-${key}.lock`);
|
|
7426
7648
|
const payload = `${JSON.stringify({
|
|
7427
7649
|
pid: process.pid,
|
|
7428
7650
|
stagingRoot,
|
|
@@ -7431,22 +7653,22 @@ function acquireRunLock(stagingRoot) {
|
|
|
7431
7653
|
`;
|
|
7432
7654
|
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
7433
7655
|
try {
|
|
7434
|
-
const handle =
|
|
7656
|
+
const handle = fs12__namespace.openSync(lockPath, "wx");
|
|
7435
7657
|
try {
|
|
7436
|
-
|
|
7658
|
+
fs12__namespace.writeSync(handle, payload);
|
|
7437
7659
|
} finally {
|
|
7438
|
-
|
|
7660
|
+
fs12__namespace.closeSync(handle);
|
|
7439
7661
|
}
|
|
7440
7662
|
return () => {
|
|
7441
7663
|
try {
|
|
7442
|
-
|
|
7664
|
+
fs12__namespace.rmSync(lockPath, { force: true });
|
|
7443
7665
|
} catch {
|
|
7444
7666
|
}
|
|
7445
7667
|
};
|
|
7446
7668
|
} catch (err) {
|
|
7447
7669
|
if (err.code !== "EEXIST") throw err;
|
|
7448
7670
|
if (attempt === 0 && lockOwnerIsGone(lockPath)) {
|
|
7449
|
-
|
|
7671
|
+
fs12__namespace.rmSync(lockPath, { force: true });
|
|
7450
7672
|
continue;
|
|
7451
7673
|
}
|
|
7452
7674
|
throw new Error(
|
|
@@ -7459,7 +7681,7 @@ function acquireRunLock(stagingRoot) {
|
|
|
7459
7681
|
function lockKeyFor(stagingRoot) {
|
|
7460
7682
|
let key = stagingRoot;
|
|
7461
7683
|
try {
|
|
7462
|
-
key =
|
|
7684
|
+
key = fs12__namespace.realpathSync(stagingRoot);
|
|
7463
7685
|
} catch {
|
|
7464
7686
|
}
|
|
7465
7687
|
if (process.platform === "win32" || process.platform === "darwin") key = key.toLowerCase();
|
|
@@ -7468,7 +7690,7 @@ function lockKeyFor(stagingRoot) {
|
|
|
7468
7690
|
function lockOwnerIsGone(lockPath) {
|
|
7469
7691
|
let raw;
|
|
7470
7692
|
try {
|
|
7471
|
-
raw =
|
|
7693
|
+
raw = fs12__namespace.readFileSync(lockPath, "utf8");
|
|
7472
7694
|
} catch {
|
|
7473
7695
|
return false;
|
|
7474
7696
|
}
|
|
@@ -7488,12 +7710,12 @@ function lockOwnerIsGone(lockPath) {
|
|
|
7488
7710
|
}
|
|
7489
7711
|
function writeManifestAtomically(manifestPath, manifest) {
|
|
7490
7712
|
const tempPath = `${manifestPath}.${process.pid}.tmp`;
|
|
7491
|
-
|
|
7713
|
+
fs12__namespace.writeFileSync(tempPath, JSON.stringify(manifest, null, 2), "utf8");
|
|
7492
7714
|
try {
|
|
7493
|
-
|
|
7715
|
+
fs12__namespace.renameSync(tempPath, manifestPath);
|
|
7494
7716
|
} catch (err) {
|
|
7495
7717
|
try {
|
|
7496
|
-
|
|
7718
|
+
fs12__namespace.rmSync(tempPath, { force: true });
|
|
7497
7719
|
} catch {
|
|
7498
7720
|
}
|
|
7499
7721
|
throw err;
|
|
@@ -7516,31 +7738,31 @@ function swapIntoPlace(stagingDir, outDir) {
|
|
|
7516
7738
|
}
|
|
7517
7739
|
function swapOnce(stagingDir, outDir) {
|
|
7518
7740
|
const backupDir = `${outDir}.backup-${process.pid}-${Date.now()}`;
|
|
7519
|
-
const hadPrevious =
|
|
7520
|
-
if (hadPrevious)
|
|
7741
|
+
const hadPrevious = fs12__namespace.existsSync(outDir);
|
|
7742
|
+
if (hadPrevious) fs12__namespace.renameSync(outDir, backupDir);
|
|
7521
7743
|
try {
|
|
7522
7744
|
try {
|
|
7523
|
-
|
|
7745
|
+
fs12__namespace.renameSync(stagingDir, outDir);
|
|
7524
7746
|
} catch (err) {
|
|
7525
7747
|
if (err.code !== "EXDEV") throw err;
|
|
7526
7748
|
const partialDir = `${outDir}.partial-${process.pid}-${Date.now()}`;
|
|
7527
7749
|
try {
|
|
7528
|
-
|
|
7529
|
-
|
|
7530
|
-
|
|
7750
|
+
fs12__namespace.cpSync(stagingDir, partialDir, { recursive: true });
|
|
7751
|
+
fs12__namespace.renameSync(partialDir, outDir);
|
|
7752
|
+
fs12__namespace.rmSync(stagingDir, { recursive: true, force: true });
|
|
7531
7753
|
} catch (copyErr) {
|
|
7532
7754
|
try {
|
|
7533
|
-
|
|
7755
|
+
fs12__namespace.rmSync(partialDir, { recursive: true, force: true });
|
|
7534
7756
|
} catch {
|
|
7535
7757
|
}
|
|
7536
7758
|
throw copyErr;
|
|
7537
7759
|
}
|
|
7538
7760
|
}
|
|
7539
|
-
if (hadPrevious)
|
|
7761
|
+
if (hadPrevious) fs12__namespace.rmSync(backupDir, { recursive: true, force: true });
|
|
7540
7762
|
} catch (err) {
|
|
7541
|
-
if (hadPrevious &&
|
|
7542
|
-
if (
|
|
7543
|
-
|
|
7763
|
+
if (hadPrevious && fs12__namespace.existsSync(backupDir)) {
|
|
7764
|
+
if (fs12__namespace.existsSync(outDir)) fs12__namespace.rmSync(outDir, { recursive: true, force: true });
|
|
7765
|
+
fs12__namespace.renameSync(backupDir, outDir);
|
|
7544
7766
|
}
|
|
7545
7767
|
throw err;
|
|
7546
7768
|
}
|
|
@@ -7635,7 +7857,7 @@ function generateSnapshot(configInput, options) {
|
|
|
7635
7857
|
// first run cannot have marked them yet, so the name alone keeps a run from recording its own
|
|
7636
7858
|
// output — but only at these exact paths, not at every directory that shares the name.
|
|
7637
7859
|
toolOwnedPaths: [config.outDir, config.tmpDir].map(
|
|
7638
|
-
(directory) =>
|
|
7860
|
+
(directory) => path13__namespace.relative(config.cwd, path13__namespace.resolve(config.cwd, directory)).replace(/\\/g, "/")
|
|
7639
7861
|
).filter((relative11) => relative11.length > 0 && !relative11.startsWith(".."))
|
|
7640
7862
|
});
|
|
7641
7863
|
const files = [];
|
|
@@ -7656,12 +7878,12 @@ function generateSnapshot(configInput, options) {
|
|
|
7656
7878
|
let totalSizeBytes = 0;
|
|
7657
7879
|
let largeFileCount = 0;
|
|
7658
7880
|
for (const relativePath of collection.files) {
|
|
7659
|
-
const absolutePath =
|
|
7881
|
+
const absolutePath = path13__namespace.join(config.cwd, relativePath);
|
|
7660
7882
|
let stats;
|
|
7661
7883
|
try {
|
|
7662
|
-
stats =
|
|
7884
|
+
stats = fs12__namespace.statSync(absolutePath);
|
|
7663
7885
|
if (!stats.isFile()) {
|
|
7664
|
-
const nestedRepository = stats.isDirectory() &&
|
|
7886
|
+
const nestedRepository = stats.isDirectory() && fs12__namespace.existsSync(path13__namespace.join(absolutePath, ".git"));
|
|
7665
7887
|
skipped.push(
|
|
7666
7888
|
nestedRepository ? {
|
|
7667
7889
|
path: relativePath,
|
|
@@ -7681,7 +7903,7 @@ function generateSnapshot(configInput, options) {
|
|
|
7681
7903
|
}
|
|
7682
7904
|
let buffer;
|
|
7683
7905
|
try {
|
|
7684
|
-
buffer =
|
|
7906
|
+
buffer = fs12__namespace.readFileSync(absolutePath);
|
|
7685
7907
|
} catch {
|
|
7686
7908
|
skipped.push({ path: relativePath, reason: "read-error" });
|
|
7687
7909
|
continue;
|
|
@@ -8011,12 +8233,12 @@ function generateSnapshot(configInput, options) {
|
|
|
8011
8233
|
let stagingDir = null;
|
|
8012
8234
|
try {
|
|
8013
8235
|
ensureParentDirectory(outDir, "outDir");
|
|
8014
|
-
|
|
8236
|
+
fs12__namespace.mkdirSync(tmpDir, { recursive: true });
|
|
8015
8237
|
cleanStaleRunDirs(tmpDir);
|
|
8016
8238
|
const snapshotId = crypto2__namespace.randomUUID();
|
|
8017
8239
|
const createdAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
8018
|
-
stagingDir =
|
|
8019
|
-
|
|
8240
|
+
stagingDir = path13__namespace.join(tmpDir, `${RUN_DIR_PREFIX}${process.pid}-${snapshotId.slice(0, 8)}`);
|
|
8241
|
+
fs12__namespace.mkdirSync(stagingDir);
|
|
8020
8242
|
writeOwnershipMarker(stagingDir, {
|
|
8021
8243
|
generator: GENERATOR_NAME,
|
|
8022
8244
|
version: GENERATOR_VERSION,
|
|
@@ -8026,41 +8248,41 @@ function generateSnapshot(configInput, options) {
|
|
|
8026
8248
|
id: snapshotId,
|
|
8027
8249
|
pid: process.pid
|
|
8028
8250
|
});
|
|
8029
|
-
const partsDir =
|
|
8030
|
-
const reportsDir =
|
|
8031
|
-
if (artifacts.parts)
|
|
8251
|
+
const partsDir = path13__namespace.join(stagingDir, "parts");
|
|
8252
|
+
const reportsDir = path13__namespace.join(stagingDir, "reports");
|
|
8253
|
+
if (artifacts.parts) fs12__namespace.mkdirSync(partsDir, { recursive: true });
|
|
8032
8254
|
if (artifacts.navigation || artifacts.projectTree || artifacts.audit) {
|
|
8033
|
-
|
|
8255
|
+
fs12__namespace.mkdirSync(reportsDir, { recursive: true });
|
|
8034
8256
|
}
|
|
8035
8257
|
if (artifacts.parts) {
|
|
8036
8258
|
for (const part of parts) {
|
|
8037
|
-
|
|
8259
|
+
fs12__namespace.writeFileSync(path13__namespace.join(partsDir, part.filename), part.markdown, "utf8");
|
|
8038
8260
|
}
|
|
8039
8261
|
}
|
|
8040
8262
|
if (projectTree !== null) {
|
|
8041
|
-
|
|
8263
|
+
fs12__namespace.writeFileSync(path13__namespace.join(reportsDir, "project-tree.md"), projectTree, "utf8");
|
|
8042
8264
|
}
|
|
8043
8265
|
if (artifacts.navigation) {
|
|
8044
|
-
|
|
8266
|
+
fs12__namespace.writeFileSync(path13__namespace.join(reportsDir, "navigation.md"), generateNavigation(manifest), "utf8");
|
|
8045
8267
|
}
|
|
8046
8268
|
if (artifacts.audit) {
|
|
8047
|
-
|
|
8048
|
-
|
|
8269
|
+
fs12__namespace.writeFileSync(
|
|
8270
|
+
path13__namespace.join(reportsDir, "audit.md"),
|
|
8049
8271
|
generateAuditReport(manifest, secretFindings, config.secretRules),
|
|
8050
8272
|
"utf8"
|
|
8051
8273
|
);
|
|
8052
8274
|
}
|
|
8053
8275
|
if (artifacts.readme) {
|
|
8054
|
-
|
|
8276
|
+
fs12__namespace.writeFileSync(path13__namespace.join(stagingDir, "README.md"), generateReadme(manifest, artifacts), "utf8");
|
|
8055
8277
|
}
|
|
8056
8278
|
if (artifacts.manifest) {
|
|
8057
|
-
|
|
8279
|
+
fs12__namespace.writeFileSync(path13__namespace.join(stagingDir, "manifest.json"), JSON.stringify(manifest, null, 2), "utf8");
|
|
8058
8280
|
}
|
|
8059
8281
|
if (monolithJson !== null) {
|
|
8060
|
-
|
|
8282
|
+
fs12__namespace.writeFileSync(path13__namespace.join(stagingDir, "full-codebase.json"), monolithJson, "utf8");
|
|
8061
8283
|
}
|
|
8062
8284
|
if (monolithMarkdown !== null) {
|
|
8063
|
-
|
|
8285
|
+
fs12__namespace.writeFileSync(path13__namespace.join(stagingDir, "full-codebase.md"), monolithMarkdown, "utf8");
|
|
8064
8286
|
}
|
|
8065
8287
|
writeOwnershipMarker(stagingDir, markerPayload(stagingDir, "complete", snapshotId, createdAt));
|
|
8066
8288
|
swapIntoPlace(stagingDir, outDir);
|
|
@@ -8069,7 +8291,7 @@ function generateSnapshot(configInput, options) {
|
|
|
8069
8291
|
const pendingHook = runAfterGenerate(config, manifest);
|
|
8070
8292
|
const shipHookState = () => {
|
|
8071
8293
|
if (artifacts.manifest && manifest.warnings.length !== warningsBeforeHook) {
|
|
8072
|
-
writeManifestAtomically(
|
|
8294
|
+
writeManifestAtomically(path13__namespace.join(outDir, "manifest.json"), manifest);
|
|
8073
8295
|
}
|
|
8074
8296
|
writeOwnershipMarker(outDir, markerPayload(outDir, "complete", snapshotId, createdAt));
|
|
8075
8297
|
};
|
|
@@ -8092,7 +8314,7 @@ function generateSnapshot(configInput, options) {
|
|
|
8092
8314
|
} catch (err) {
|
|
8093
8315
|
if (stagingDir !== null) {
|
|
8094
8316
|
try {
|
|
8095
|
-
|
|
8317
|
+
fs12__namespace.rmSync(stagingDir, { recursive: true, force: true });
|
|
8096
8318
|
} catch {
|
|
8097
8319
|
}
|
|
8098
8320
|
}
|
|
@@ -8189,9 +8411,9 @@ function foldForComparison(value) {
|
|
|
8189
8411
|
return process.platform === "win32" || process.platform === "darwin" ? value.toLowerCase() : value;
|
|
8190
8412
|
}
|
|
8191
8413
|
function canonicalPath(value) {
|
|
8192
|
-
const absolute =
|
|
8414
|
+
const absolute = path13__namespace.resolve(value);
|
|
8193
8415
|
try {
|
|
8194
|
-
return
|
|
8416
|
+
return fs12__namespace.realpathSync(absolute);
|
|
8195
8417
|
} catch {
|
|
8196
8418
|
return absolute;
|
|
8197
8419
|
}
|
|
@@ -8199,17 +8421,17 @@ function canonicalPath(value) {
|
|
|
8199
8421
|
function isInside2(parent, child) {
|
|
8200
8422
|
const foldedParent = foldForComparison(parent);
|
|
8201
8423
|
const foldedChild = foldForComparison(child);
|
|
8202
|
-
return foldedChild === foldedParent || foldedChild.startsWith(`${foldedParent}${
|
|
8424
|
+
return foldedChild === foldedParent || foldedChild.startsWith(`${foldedParent}${path13__namespace.sep}`);
|
|
8203
8425
|
}
|
|
8204
8426
|
function resolveRoot(requested, context) {
|
|
8205
8427
|
if (requested !== void 0 && (typeof requested !== "string" || requested.trim().length === 0)) {
|
|
8206
8428
|
return { ok: false, message: '"root" must be a non-empty string when provided.' };
|
|
8207
8429
|
}
|
|
8208
8430
|
const wanted = typeof requested === "string" ? requested.trim() : context.cwd;
|
|
8209
|
-
const absolute =
|
|
8431
|
+
const absolute = path13__namespace.resolve(context.cwd, wanted);
|
|
8210
8432
|
let stats;
|
|
8211
8433
|
try {
|
|
8212
|
-
stats =
|
|
8434
|
+
stats = fs12__namespace.statSync(absolute);
|
|
8213
8435
|
} catch {
|
|
8214
8436
|
return { ok: false, message: `"${wanted}" does not exist, so it cannot be a repository root.` };
|
|
8215
8437
|
}
|
|
@@ -8260,14 +8482,14 @@ async function openWorkspace(root, overrides = {}) {
|
|
|
8260
8482
|
}
|
|
8261
8483
|
var manifestCache = /* @__PURE__ */ new Map();
|
|
8262
8484
|
function manifestPathFor(workspace) {
|
|
8263
|
-
return
|
|
8485
|
+
return path13__namespace.resolve(workspace.root, workspace.config.outDir, "manifest.json");
|
|
8264
8486
|
}
|
|
8265
8487
|
function readManifest3(workspace) {
|
|
8266
8488
|
const file = manifestPathFor(workspace);
|
|
8267
|
-
const shown =
|
|
8489
|
+
const shown = path13__namespace.relative(workspace.root, file).split(path13__namespace.sep).join("/") || file;
|
|
8268
8490
|
let stats;
|
|
8269
8491
|
try {
|
|
8270
|
-
stats =
|
|
8492
|
+
stats = fs12__namespace.statSync(file);
|
|
8271
8493
|
} catch {
|
|
8272
8494
|
return {
|
|
8273
8495
|
ok: false,
|
|
@@ -8281,7 +8503,7 @@ function readManifest3(workspace) {
|
|
|
8281
8503
|
}
|
|
8282
8504
|
let raw;
|
|
8283
8505
|
try {
|
|
8284
|
-
raw =
|
|
8506
|
+
raw = fs12__namespace.readFileSync(file, "utf8");
|
|
8285
8507
|
} catch (error) {
|
|
8286
8508
|
return {
|
|
8287
8509
|
ok: false,
|
|
@@ -8339,7 +8561,7 @@ function formatBytes(bytes) {
|
|
|
8339
8561
|
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
8340
8562
|
}
|
|
8341
8563
|
function relativeFor(workspace, absolute) {
|
|
8342
|
-
return
|
|
8564
|
+
return path13__namespace.relative(workspace.root, absolute).split(path13__namespace.sep).join("/");
|
|
8343
8565
|
}
|
|
8344
8566
|
function capped(values, limit = 20) {
|
|
8345
8567
|
return { count: values.length, sample: values.slice(0, limit) };
|
|
@@ -8358,12 +8580,12 @@ function summarizeDrift(drift) {
|
|
|
8358
8580
|
function toRelativePath(root, value) {
|
|
8359
8581
|
const cleaned = value.trim();
|
|
8360
8582
|
if (cleaned.length === 0) return null;
|
|
8361
|
-
if (!
|
|
8583
|
+
if (!path13__namespace.isAbsolute(cleaned)) {
|
|
8362
8584
|
return cleaned.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
8363
8585
|
}
|
|
8364
|
-
const relative11 =
|
|
8365
|
-
if (relative11.startsWith("..") ||
|
|
8366
|
-
return relative11.split(
|
|
8586
|
+
const relative11 = path13__namespace.relative(root, cleaned);
|
|
8587
|
+
if (relative11.startsWith("..") || path13__namespace.isAbsolute(relative11)) return null;
|
|
8588
|
+
return relative11.split(path13__namespace.sep).join("/");
|
|
8367
8589
|
}
|
|
8368
8590
|
function symbolsOf(entry) {
|
|
8369
8591
|
const summary = entry.summary;
|
|
@@ -8574,7 +8796,7 @@ var generateTool = {
|
|
|
8574
8796
|
return failure(error instanceof Error ? error.message : String(error));
|
|
8575
8797
|
}
|
|
8576
8798
|
forgetManifest(manifestPathFor(workspace));
|
|
8577
|
-
const written = relativeFor(workspace,
|
|
8799
|
+
const written = relativeFor(workspace, path13__namespace.resolve(workspace.root, workspace.config.outDir));
|
|
8578
8800
|
const lines = [
|
|
8579
8801
|
`Wrote ${written}/`,
|
|
8580
8802
|
`Files: ${manifest.counts.totalFiles} included, ${manifest.counts.skippedCount} skipped, ${plural(manifest.counts.partsCount, "part")}`,
|
|
@@ -8839,10 +9061,10 @@ var readTool = {
|
|
|
8839
9061
|
`${relativePath} is not in the snapshot. Call snapshot_locate to find the path, or snapshot_explain to learn why it was excluded.`
|
|
8840
9062
|
);
|
|
8841
9063
|
}
|
|
8842
|
-
const partPath =
|
|
9064
|
+
const partPath = path13__namespace.resolve(workspace.root, workspace.config.outDir, "parts", entry.part);
|
|
8843
9065
|
let partText;
|
|
8844
9066
|
try {
|
|
8845
|
-
partText =
|
|
9067
|
+
partText = fs12__namespace.readFileSync(partPath, "utf8");
|
|
8846
9068
|
} catch {
|
|
8847
9069
|
return failure(
|
|
8848
9070
|
`${entry.part} could not be read, so the snapshot is damaged. Run snapshot_generate to rebuild it.`
|
|
@@ -9100,6 +9322,7 @@ var VALIDATE_OPTIONS = [
|
|
|
9100
9322
|
"no-config",
|
|
9101
9323
|
"discovery",
|
|
9102
9324
|
"format",
|
|
9325
|
+
"no-update-check",
|
|
9103
9326
|
"mode",
|
|
9104
9327
|
"help",
|
|
9105
9328
|
"version"
|
|
@@ -9123,6 +9346,7 @@ var COMMAND_OPTION_SCOPE = {
|
|
|
9123
9346
|
"watch",
|
|
9124
9347
|
"autopilot",
|
|
9125
9348
|
"no-install",
|
|
9349
|
+
"no-update-check",
|
|
9126
9350
|
"help",
|
|
9127
9351
|
"version"
|
|
9128
9352
|
],
|
|
@@ -9138,6 +9362,7 @@ var COMMAND_OPTION_SCOPE = {
|
|
|
9138
9362
|
"skip-artifacts",
|
|
9139
9363
|
"only-artifacts",
|
|
9140
9364
|
"no-config",
|
|
9365
|
+
"no-update-check",
|
|
9141
9366
|
"format",
|
|
9142
9367
|
"mode",
|
|
9143
9368
|
"help",
|
|
@@ -9155,12 +9380,13 @@ var COMMAND_OPTION_SCOPE = {
|
|
|
9155
9380
|
"only-artifacts",
|
|
9156
9381
|
"no-config",
|
|
9157
9382
|
"discovery",
|
|
9383
|
+
"no-update-check",
|
|
9158
9384
|
"format",
|
|
9159
9385
|
"mode",
|
|
9160
9386
|
"help",
|
|
9161
9387
|
"version"
|
|
9162
9388
|
],
|
|
9163
|
-
diff: ["format", "mode", "no-config", "help", "version"],
|
|
9389
|
+
diff: ["format", "mode", "no-config", "no-update-check", "help", "version"],
|
|
9164
9390
|
describe: ["format", "mode", "help", "version"],
|
|
9165
9391
|
init: [
|
|
9166
9392
|
"cwd",
|
|
@@ -9175,6 +9401,7 @@ var COMMAND_OPTION_SCOPE = {
|
|
|
9175
9401
|
"yes",
|
|
9176
9402
|
"force",
|
|
9177
9403
|
"dry-run",
|
|
9404
|
+
"no-update-check",
|
|
9178
9405
|
"format",
|
|
9179
9406
|
"mode",
|
|
9180
9407
|
"help",
|
|
@@ -9198,6 +9425,7 @@ var COMMAND_OPTION_SCOPE = {
|
|
|
9198
9425
|
"force",
|
|
9199
9426
|
"no-install",
|
|
9200
9427
|
"dry-run",
|
|
9428
|
+
"no-update-check",
|
|
9201
9429
|
"format",
|
|
9202
9430
|
"mode",
|
|
9203
9431
|
"help",
|
|
@@ -9630,6 +9858,13 @@ function buildAgentContract() {
|
|
|
9630
9858
|
default: false,
|
|
9631
9859
|
appliesTo: optionAppliesTo("no-install"),
|
|
9632
9860
|
summary: "Skip installing the dependency before generating: `setup`, or `generate --autopilot` (CI, offline, or a lockfile you do not want a package manager to touch)."
|
|
9861
|
+
},
|
|
9862
|
+
{
|
|
9863
|
+
flag: "--no-update-check",
|
|
9864
|
+
type: "boolean",
|
|
9865
|
+
default: false,
|
|
9866
|
+
appliesTo: optionAppliesTo("no-update-check"),
|
|
9867
|
+
summary: "Skip the once-a-day check for a newer published version. The check is already skipped when stdout is not a terminal, in CI, in a JSON invocation, and in `mcp`, which makes no network requests."
|
|
9633
9868
|
}
|
|
9634
9869
|
],
|
|
9635
9870
|
presets: PRESETS.map((preset) => ({
|
|
@@ -9917,17 +10152,17 @@ var LEGACY_AGENTS_MARKER = "<!-- codebase-snapshot:skill:start -->";
|
|
|
9917
10152
|
function targetPath(cwd, target) {
|
|
9918
10153
|
switch (target) {
|
|
9919
10154
|
case "claude":
|
|
9920
|
-
return
|
|
10155
|
+
return path13__namespace.join(cwd, ".claude", "skills", SKILL_NAME, "SKILL.md");
|
|
9921
10156
|
case "cursor":
|
|
9922
|
-
return
|
|
10157
|
+
return path13__namespace.join(cwd, ".cursor", "rules", `${SKILL_NAME}.mdc`);
|
|
9923
10158
|
}
|
|
9924
10159
|
}
|
|
9925
10160
|
function assertWritableInsideRepository(cwd, filePath) {
|
|
9926
|
-
const root =
|
|
9927
|
-
const shown =
|
|
10161
|
+
const root = fs12__namespace.realpathSync(cwd);
|
|
10162
|
+
const shown = path13__namespace.relative(root, filePath) || filePath;
|
|
9928
10163
|
let stat = null;
|
|
9929
10164
|
try {
|
|
9930
|
-
stat =
|
|
10165
|
+
stat = fs12__namespace.lstatSync(filePath);
|
|
9931
10166
|
} catch {
|
|
9932
10167
|
stat = null;
|
|
9933
10168
|
}
|
|
@@ -9943,32 +10178,32 @@ function assertWritableInsideRepository(cwd, filePath) {
|
|
|
9943
10178
|
}
|
|
9944
10179
|
let existing = filePath;
|
|
9945
10180
|
const missing = [];
|
|
9946
|
-
while (!
|
|
9947
|
-
missing.unshift(
|
|
9948
|
-
const parent =
|
|
10181
|
+
while (!fs12__namespace.existsSync(existing)) {
|
|
10182
|
+
missing.unshift(path13__namespace.basename(existing));
|
|
10183
|
+
const parent = path13__namespace.dirname(existing);
|
|
9949
10184
|
if (parent === existing) break;
|
|
9950
10185
|
existing = parent;
|
|
9951
10186
|
}
|
|
9952
|
-
const realAncestor =
|
|
9953
|
-
const resolved = missing.length === 0 ? realAncestor :
|
|
9954
|
-
if (resolved !== root && !resolved.startsWith(`${root}${
|
|
10187
|
+
const realAncestor = fs12__namespace.realpathSync(existing);
|
|
10188
|
+
const resolved = missing.length === 0 ? realAncestor : path13__namespace.join(realAncestor, ...missing);
|
|
10189
|
+
if (resolved !== root && !resolved.startsWith(`${root}${path13__namespace.sep}`)) {
|
|
9955
10190
|
throw new Error(
|
|
9956
10191
|
`${REFUSED}: ${shown} resolves outside the repository (${resolved}). Move it back inside ${root}, or remove the link, and run again.`
|
|
9957
10192
|
);
|
|
9958
10193
|
}
|
|
9959
10194
|
}
|
|
9960
10195
|
function writeIfChanged(target, filePath, content) {
|
|
9961
|
-
const existing =
|
|
10196
|
+
const existing = fs12__namespace.existsSync(filePath) ? fs12__namespace.readFileSync(filePath, "utf8") : null;
|
|
9962
10197
|
if (existing === content) return { target, path: filePath, action: "unchanged" };
|
|
9963
|
-
|
|
9964
|
-
|
|
10198
|
+
fs12__namespace.mkdirSync(path13__namespace.dirname(filePath), { recursive: true });
|
|
10199
|
+
fs12__namespace.writeFileSync(filePath, content, "utf8");
|
|
9965
10200
|
return { target, path: filePath, action: existing === null ? "created" : "updated" };
|
|
9966
10201
|
}
|
|
9967
10202
|
function legacyAgentsNote(cwd) {
|
|
9968
|
-
const filePath =
|
|
10203
|
+
const filePath = path13__namespace.join(cwd, "AGENTS.md");
|
|
9969
10204
|
try {
|
|
9970
|
-
if (!
|
|
9971
|
-
if (!
|
|
10205
|
+
if (!fs12__namespace.existsSync(filePath)) return null;
|
|
10206
|
+
if (!fs12__namespace.readFileSync(filePath, "utf8").includes(LEGACY_AGENTS_MARKER)) return null;
|
|
9972
10207
|
} catch {
|
|
9973
10208
|
return null;
|
|
9974
10209
|
}
|
|
@@ -9980,9 +10215,9 @@ function installSkill(cwd, target = "all") {
|
|
|
9980
10215
|
const notes = [];
|
|
9981
10216
|
const wanted = target === "all" ? ["claude", "cursor"] : [target];
|
|
9982
10217
|
for (const item of wanted) assertWritableInsideRepository(cwd, targetPath(cwd, item));
|
|
9983
|
-
const createsSomething = wanted.some((item) => !
|
|
10218
|
+
const createsSomething = wanted.some((item) => !fs12__namespace.existsSync(targetPath(cwd, item)));
|
|
9984
10219
|
if (createsSomething) {
|
|
9985
|
-
assertWritableInsideRepository(cwd,
|
|
10220
|
+
assertWritableInsideRepository(cwd, path13__namespace.join(cwd, ".gitignore"));
|
|
9986
10221
|
}
|
|
9987
10222
|
for (const item of wanted) {
|
|
9988
10223
|
written.push(writeIfChanged(item, targetPath(cwd, item), skill));
|
|
@@ -10117,52 +10352,52 @@ function validateArguments(schema, value) {
|
|
|
10117
10352
|
}
|
|
10118
10353
|
return problems;
|
|
10119
10354
|
}
|
|
10120
|
-
function checkValue(
|
|
10355
|
+
function checkValue(path19, schema, value) {
|
|
10121
10356
|
if (schema.enum && !schema.enum.includes(value)) {
|
|
10122
|
-
return [`"${
|
|
10357
|
+
return [`"${path19}" must be one of: ${schema.enum.join(", ")}`];
|
|
10123
10358
|
}
|
|
10124
10359
|
switch (schema.type) {
|
|
10125
10360
|
case "string": {
|
|
10126
|
-
if (typeof value !== "string") return [`"${
|
|
10361
|
+
if (typeof value !== "string") return [`"${path19}" must be a string`];
|
|
10127
10362
|
const problems = [];
|
|
10128
10363
|
if (schema.minLength !== void 0 && value.length < schema.minLength) {
|
|
10129
|
-
problems.push(`"${
|
|
10364
|
+
problems.push(`"${path19}" must be at least ${schema.minLength} character(s)`);
|
|
10130
10365
|
}
|
|
10131
10366
|
if (schema.maxLength !== void 0 && value.length > schema.maxLength) {
|
|
10132
|
-
problems.push(`"${
|
|
10367
|
+
problems.push(`"${path19}" must be at most ${schema.maxLength} character(s)`);
|
|
10133
10368
|
}
|
|
10134
10369
|
return problems;
|
|
10135
10370
|
}
|
|
10136
10371
|
case "number":
|
|
10137
10372
|
case "integer": {
|
|
10138
10373
|
if (typeof value !== "number" || Number.isNaN(value)) {
|
|
10139
|
-
return [`"${
|
|
10374
|
+
return [`"${path19}" must be a number`];
|
|
10140
10375
|
}
|
|
10141
10376
|
if (schema.type === "integer" && !Number.isInteger(value)) {
|
|
10142
|
-
return [`"${
|
|
10377
|
+
return [`"${path19}" must be an integer`];
|
|
10143
10378
|
}
|
|
10144
10379
|
const problems = [];
|
|
10145
10380
|
if (schema.minimum !== void 0 && value < schema.minimum) {
|
|
10146
|
-
problems.push(`"${
|
|
10381
|
+
problems.push(`"${path19}" must be >= ${schema.minimum}`);
|
|
10147
10382
|
}
|
|
10148
10383
|
if (schema.maximum !== void 0 && value > schema.maximum) {
|
|
10149
|
-
problems.push(`"${
|
|
10384
|
+
problems.push(`"${path19}" must be <= ${schema.maximum}`);
|
|
10150
10385
|
}
|
|
10151
10386
|
return problems;
|
|
10152
10387
|
}
|
|
10153
10388
|
case "boolean":
|
|
10154
|
-
return typeof value === "boolean" ? [] : [`"${
|
|
10389
|
+
return typeof value === "boolean" ? [] : [`"${path19}" must be a boolean`];
|
|
10155
10390
|
case "array": {
|
|
10156
|
-
if (!Array.isArray(value)) return [`"${
|
|
10391
|
+
if (!Array.isArray(value)) return [`"${path19}" must be an array`];
|
|
10157
10392
|
if (!schema.items) return [];
|
|
10158
10393
|
const problems = [];
|
|
10159
10394
|
value.forEach((item, index) => {
|
|
10160
|
-
problems.push(...checkValue(`${
|
|
10395
|
+
problems.push(...checkValue(`${path19}[${index}]`, schema.items, item));
|
|
10161
10396
|
});
|
|
10162
10397
|
return problems;
|
|
10163
10398
|
}
|
|
10164
10399
|
case "object":
|
|
10165
|
-
return isJsonObject(value) ? [] : [`"${
|
|
10400
|
+
return isJsonObject(value) ? [] : [`"${path19}" must be an object`];
|
|
10166
10401
|
default:
|
|
10167
10402
|
return [];
|
|
10168
10403
|
}
|
|
@@ -10176,6 +10411,18 @@ function applyDefaults(schema, value) {
|
|
|
10176
10411
|
}
|
|
10177
10412
|
return out;
|
|
10178
10413
|
}
|
|
10414
|
+
function coerceNumericStrings(schema, value) {
|
|
10415
|
+
const out = { ...value };
|
|
10416
|
+
for (const [key, propertySchema] of Object.entries(schema.properties)) {
|
|
10417
|
+
const raw = out[key];
|
|
10418
|
+
if (typeof raw !== "string") continue;
|
|
10419
|
+
if (propertySchema.type !== "number" && propertySchema.type !== "integer") continue;
|
|
10420
|
+
if (raw.trim().length === 0) continue;
|
|
10421
|
+
const parsed = Number(raw);
|
|
10422
|
+
if (Number.isFinite(parsed)) out[key] = parsed;
|
|
10423
|
+
}
|
|
10424
|
+
return out;
|
|
10425
|
+
}
|
|
10179
10426
|
|
|
10180
10427
|
// src/mcp/server.ts
|
|
10181
10428
|
function capabilities() {
|
|
@@ -10264,7 +10511,8 @@ function createMcpServer(options) {
|
|
|
10264
10511
|
if (!isJsonObject(rawArguments)) {
|
|
10265
10512
|
return errorResponse(id, ERROR_CODES.invalidParams, '"arguments" must be a JSON object.');
|
|
10266
10513
|
}
|
|
10267
|
-
const
|
|
10514
|
+
const supplied = coerceNumericStrings(tool.inputSchema, rawArguments);
|
|
10515
|
+
const problems = validateArguments(tool.inputSchema, supplied);
|
|
10268
10516
|
if (problems.length > 0) {
|
|
10269
10517
|
return ok(
|
|
10270
10518
|
id,
|
|
@@ -10276,7 +10524,7 @@ function createMcpServer(options) {
|
|
|
10276
10524
|
modern
|
|
10277
10525
|
);
|
|
10278
10526
|
}
|
|
10279
|
-
const args = applyDefaults(tool.inputSchema,
|
|
10527
|
+
const args = applyDefaults(tool.inputSchema, supplied);
|
|
10280
10528
|
let outcome;
|
|
10281
10529
|
try {
|
|
10282
10530
|
outcome = await tool.handler(args, options.context);
|
|
@@ -10474,7 +10722,7 @@ async function workspaceFor(context) {
|
|
|
10474
10722
|
}
|
|
10475
10723
|
function readFileIfPresent(file) {
|
|
10476
10724
|
try {
|
|
10477
|
-
return
|
|
10725
|
+
return fs12__namespace.readFileSync(file, "utf8");
|
|
10478
10726
|
} catch {
|
|
10479
10727
|
return null;
|
|
10480
10728
|
}
|
|
@@ -10553,7 +10801,7 @@ function buildResourceProvider() {
|
|
|
10553
10801
|
const report = REPORT_URIS.get(uri);
|
|
10554
10802
|
if (report) {
|
|
10555
10803
|
const text2 = readFileIfPresent(
|
|
10556
|
-
|
|
10804
|
+
path13__namespace.resolve(workspace.root, workspace.config.outDir, "reports", report.file)
|
|
10557
10805
|
);
|
|
10558
10806
|
if (text2 === null) return null;
|
|
10559
10807
|
return { uri, mimeType: "text/markdown", text: capUtf8(text2, MAX_RESOURCE_BYTES).text };
|
|
@@ -10572,7 +10820,7 @@ function buildResourceProvider() {
|
|
|
10572
10820
|
const part = read.manifest.parts.find((candidate) => candidate.index === index);
|
|
10573
10821
|
if (!part) return null;
|
|
10574
10822
|
const text2 = readFileIfPresent(
|
|
10575
|
-
|
|
10823
|
+
path13__namespace.resolve(workspace.root, workspace.config.outDir, "parts", part.filename)
|
|
10576
10824
|
);
|
|
10577
10825
|
if (text2 === null) return null;
|
|
10578
10826
|
return { uri, mimeType: "text/markdown", text: capUtf8(text2, MAX_RESOURCE_BYTES).text };
|
|
@@ -10810,6 +11058,7 @@ var CLI_OPTIONS = {
|
|
|
10810
11058
|
install: { type: "boolean" },
|
|
10811
11059
|
"no-install": { type: "boolean" },
|
|
10812
11060
|
target: { type: "string" },
|
|
11061
|
+
"no-update-check": { type: "boolean" },
|
|
10813
11062
|
help: { type: "boolean", short: "h" },
|
|
10814
11063
|
version: { type: "boolean", short: "v" }
|
|
10815
11064
|
};
|
|
@@ -10884,6 +11133,8 @@ Options:
|
|
|
10884
11133
|
--install Write the skill into the repository instead of printing
|
|
10885
11134
|
--target <name> claude | cursor | all (default: all)
|
|
10886
11135
|
|
|
11136
|
+
--no-update-check Skip the daily check for a newer published version
|
|
11137
|
+
|
|
10887
11138
|
-h, --help Display this help message
|
|
10888
11139
|
-v, --version Display version
|
|
10889
11140
|
|
|
@@ -10960,10 +11211,10 @@ function parseCliArgs(argv) {
|
|
|
10960
11211
|
}
|
|
10961
11212
|
if (values.cwd !== void 0) {
|
|
10962
11213
|
const target = String(values.cwd);
|
|
10963
|
-
if (!
|
|
11214
|
+
if (!fs12__namespace.existsSync(target)) {
|
|
10964
11215
|
throw new UsageError(`--cwd directory does not exist: ${target}`);
|
|
10965
11216
|
}
|
|
10966
|
-
if (!
|
|
11217
|
+
if (!fs12__namespace.statSync(target).isDirectory()) {
|
|
10967
11218
|
throw new UsageError(`--cwd is not a directory: ${target}`);
|
|
10968
11219
|
}
|
|
10969
11220
|
}
|
|
@@ -11109,7 +11360,7 @@ function parseCliArgs(argv) {
|
|
|
11109
11360
|
install: values.install === true,
|
|
11110
11361
|
noInstall: values["no-install"] === true,
|
|
11111
11362
|
target: values.target === void 0 ? void 0 : String(values.target),
|
|
11112
|
-
cwd: values.cwd === void 0 ? process.cwd() :
|
|
11363
|
+
cwd: values.cwd === void 0 ? process.cwd() : path13__namespace.resolve(String(values.cwd)),
|
|
11113
11364
|
outDir: values["out-dir"] === void 0 ? void 0 : String(values["out-dir"]),
|
|
11114
11365
|
includeMonolith: values["include-monolith"] === true || onlyNamesMonolith === true ? true : void 0,
|
|
11115
11366
|
includeSensitiveFiles: values["include-sensitive-files"] === true ? true : void 0,
|
|
@@ -11166,24 +11417,24 @@ function splitList(value) {
|
|
|
11166
11417
|
return value.split(",").map((entry) => entry.trim()).filter(Boolean);
|
|
11167
11418
|
}
|
|
11168
11419
|
function displayOutPath(cwd, outDir, ...segments) {
|
|
11169
|
-
const absolute =
|
|
11170
|
-
const relative11 =
|
|
11171
|
-
if (relative11 && !relative11.startsWith("..") && !
|
|
11420
|
+
const absolute = path13__namespace.resolve(cwd, outDir, ...segments);
|
|
11421
|
+
const relative11 = path13__namespace.relative(cwd, absolute);
|
|
11422
|
+
if (relative11 && !relative11.startsWith("..") && !path13__namespace.isAbsolute(relative11)) return relative11;
|
|
11172
11423
|
return absolute;
|
|
11173
11424
|
}
|
|
11174
11425
|
function nextStepHint(cwd, scriptsAddedNow) {
|
|
11175
11426
|
let hasScript = scriptsAddedNow;
|
|
11176
11427
|
if (!hasScript) {
|
|
11177
11428
|
try {
|
|
11178
|
-
const parsed = JSON.parse(
|
|
11429
|
+
const parsed = JSON.parse(fs12__namespace.readFileSync(path13__namespace.join(cwd, "package.json"), "utf8"));
|
|
11179
11430
|
hasScript = typeof parsed.scripts?.snapshot === "string";
|
|
11180
11431
|
} catch {
|
|
11181
11432
|
hasScript = false;
|
|
11182
11433
|
}
|
|
11183
11434
|
}
|
|
11184
11435
|
if (!hasScript) return `npx ${GENERATOR_NAME} generate`;
|
|
11185
|
-
const bin =
|
|
11186
|
-
const installed =
|
|
11436
|
+
const bin = path13__namespace.join(cwd, "node_modules", ".bin", "codebase-snapshot");
|
|
11437
|
+
const installed = fs12__namespace.existsSync(bin) || fs12__namespace.existsSync(`${bin}.cmd`);
|
|
11187
11438
|
return installed ? "npm run snapshot" : "npm install && npm run snapshot";
|
|
11188
11439
|
}
|
|
11189
11440
|
function presetSummary(init) {
|
|
@@ -11213,7 +11464,7 @@ async function runInitCommand(invocation) {
|
|
|
11213
11464
|
info(result.configText);
|
|
11214
11465
|
return 0;
|
|
11215
11466
|
}
|
|
11216
|
-
info(`\u2705 Created ${
|
|
11467
|
+
info(`\u2705 Created ${path13__namespace.basename(result.configPath)} (${presetSummary(result)})`);
|
|
11217
11468
|
if (result.scripts.length > 0) info(` Added npm scripts: ${result.scripts.join(", ")}`);
|
|
11218
11469
|
if (result.dependency.added && result.dependency.range !== null) {
|
|
11219
11470
|
info(` Added devDependency: ${result.dependency.name} ${result.dependency.range}`);
|
|
@@ -11233,7 +11484,7 @@ async function runInitCommand(invocation) {
|
|
|
11233
11484
|
}
|
|
11234
11485
|
}
|
|
11235
11486
|
function detectPackageManager(cwd) {
|
|
11236
|
-
const has = (name) =>
|
|
11487
|
+
const has = (name) => fs12__namespace.existsSync(path13__namespace.join(cwd, name));
|
|
11237
11488
|
if (has("bun.lockb") || has("bun.lock")) return { name: "bun", command: "bun", args: ["install"] };
|
|
11238
11489
|
if (has("pnpm-lock.yaml")) return { name: "pnpm", command: "pnpm", args: ["install"] };
|
|
11239
11490
|
if (has("yarn.lock")) return { name: "yarn", command: "yarn", args: ["install"] };
|
|
@@ -11322,7 +11573,7 @@ async function runSetupCommand(invocation, options = {}) {
|
|
|
11322
11573
|
}
|
|
11323
11574
|
info("\n\u{1F9EA} Dry run \u2014 setup would:");
|
|
11324
11575
|
info(
|
|
11325
|
-
` 1. ${init.reused ? `keep ${
|
|
11576
|
+
` 1. ${init.reused ? `keep ${path13__namespace.basename(init.configPath)}` : `write ${path13__namespace.basename(init.configPath)} (preset: ${init.preset})`}`
|
|
11326
11577
|
);
|
|
11327
11578
|
info(" 2. add the npm scripts, the devDependency and the .gitignore entries");
|
|
11328
11579
|
if (manager !== null) info(` 3. install with ${manager}`);
|
|
@@ -11334,9 +11585,9 @@ async function runSetupCommand(invocation, options = {}) {
|
|
|
11334
11585
|
if (invocation.format !== "json") {
|
|
11335
11586
|
if (!interactive) info(`\u{1F680} Setup for: ${invocation.cwd}`);
|
|
11336
11587
|
if (init.reused) {
|
|
11337
|
-
info(`\u267B Keeping ${
|
|
11588
|
+
info(`\u267B Keeping ${path13__namespace.basename(init.configPath)} (${presetSummary(init)})`);
|
|
11338
11589
|
} else {
|
|
11339
|
-
info(`\u2705 Created ${
|
|
11590
|
+
info(`\u2705 Created ${path13__namespace.basename(init.configPath)} (${presetSummary(init)})`);
|
|
11340
11591
|
}
|
|
11341
11592
|
if (init.scripts.length > 0) info(` Added npm scripts: ${init.scripts.join(", ")}`);
|
|
11342
11593
|
if (init.dependency.added && init.dependency.range !== null) {
|
|
@@ -11444,7 +11695,7 @@ function runSkillCommand(invocation) {
|
|
|
11444
11695
|
}
|
|
11445
11696
|
info(`\u2705 Agent skill installed (${SKILL_NAME}):`);
|
|
11446
11697
|
for (const item of result.written) {
|
|
11447
|
-
const shown =
|
|
11698
|
+
const shown = path13__namespace.relative(invocation.cwd, item.path) || item.path;
|
|
11448
11699
|
info(` - ${item.action.padEnd(9)} ${shown}`);
|
|
11449
11700
|
}
|
|
11450
11701
|
if (result.gitignored.length > 0) {
|
|
@@ -11508,6 +11759,17 @@ function requestsJsonFormat(argv) {
|
|
|
11508
11759
|
return format === "json";
|
|
11509
11760
|
}
|
|
11510
11761
|
async function main(argv = process.argv.slice(2)) {
|
|
11762
|
+
const pending = process.stdout.isTTY === true && shouldCheck(argv, process.env) ? checkForUpdate({ current: GENERATOR_VERSION, cacheFile: cacheFilePath() }) : null;
|
|
11763
|
+
const code = await runCommand(argv);
|
|
11764
|
+
if (pending) {
|
|
11765
|
+
const notice = await pending;
|
|
11766
|
+
if (notice) process.stderr.write(`
|
|
11767
|
+
${formatUpdateNotice(notice)}
|
|
11768
|
+
`);
|
|
11769
|
+
}
|
|
11770
|
+
return code;
|
|
11771
|
+
}
|
|
11772
|
+
async function runCommand(argv) {
|
|
11511
11773
|
let invocation;
|
|
11512
11774
|
try {
|
|
11513
11775
|
invocation = parseCliArgs(argv);
|
|
@@ -11540,7 +11802,7 @@ ${USAGE}
|
|
|
11540
11802
|
return runSkillCommand(invocation);
|
|
11541
11803
|
}
|
|
11542
11804
|
if (invocation.command === "mcp") {
|
|
11543
|
-
return await runStdioServer({ cwd:
|
|
11805
|
+
return await runStdioServer({ cwd: path13__namespace.resolve(invocation.cwd) });
|
|
11544
11806
|
}
|
|
11545
11807
|
if (invocation.command === "setup") {
|
|
11546
11808
|
return runSetupCommand(invocation);
|
|
@@ -11557,7 +11819,7 @@ ${USAGE}
|
|
|
11557
11819
|
warn("\u274C The config file could not be read. Fix it, or delete it to use the defaults.");
|
|
11558
11820
|
return 1;
|
|
11559
11821
|
}
|
|
11560
|
-
if (loaded.file) info(`\u2699 Using config ${
|
|
11822
|
+
if (loaded.file) info(`\u2699 Using config ${path13__namespace.relative(process.cwd(), loaded.file) || loaded.file}`);
|
|
11561
11823
|
const resolved = resolveConfig(
|
|
11562
11824
|
loaded.config,
|
|
11563
11825
|
{
|
|
@@ -11579,10 +11841,10 @@ ${USAGE}
|
|
|
11579
11841
|
if (invocation.command === "validate") {
|
|
11580
11842
|
const result = validateSnapshot(resolved);
|
|
11581
11843
|
if (result.valid) {
|
|
11582
|
-
const manifestPath =
|
|
11844
|
+
const manifestPath = path13__namespace.resolve(resolved.cwd, resolved.outDir, "manifest.json");
|
|
11583
11845
|
let manifest;
|
|
11584
11846
|
try {
|
|
11585
|
-
manifest = JSON.parse(
|
|
11847
|
+
manifest = JSON.parse(fs12__namespace.readFileSync(manifestPath, "utf8"));
|
|
11586
11848
|
} catch {
|
|
11587
11849
|
manifest = void 0;
|
|
11588
11850
|
}
|
|
@@ -11595,13 +11857,13 @@ ${USAGE}
|
|
|
11595
11857
|
return result.valid ? 0 : 1;
|
|
11596
11858
|
}
|
|
11597
11859
|
if (invocation.command === "report") {
|
|
11598
|
-
const manifestPath =
|
|
11599
|
-
if (!
|
|
11860
|
+
const manifestPath = path13__namespace.resolve(resolved.cwd, resolved.outDir, "manifest.json");
|
|
11861
|
+
if (!fs12__namespace.existsSync(manifestPath)) {
|
|
11600
11862
|
return fail(invocation.format, `Manifest not found at ${manifestPath}. Run generate first.`);
|
|
11601
11863
|
}
|
|
11602
11864
|
let manifest;
|
|
11603
11865
|
try {
|
|
11604
|
-
manifest = JSON.parse(
|
|
11866
|
+
manifest = JSON.parse(fs12__namespace.readFileSync(manifestPath, "utf8"));
|
|
11605
11867
|
} catch (err) {
|
|
11606
11868
|
return fail(invocation.format, `Could not read ${manifestPath}: ${err.message}`);
|
|
11607
11869
|
}
|
|
@@ -11765,20 +12027,20 @@ function finishWatchRun(state, now) {
|
|
|
11765
12027
|
};
|
|
11766
12028
|
}
|
|
11767
12029
|
function comparablePath(value) {
|
|
11768
|
-
const absolute =
|
|
12030
|
+
const absolute = path13__namespace.resolve(value);
|
|
11769
12031
|
return process.platform === "win32" ? absolute.toLowerCase() : absolute;
|
|
11770
12032
|
}
|
|
11771
12033
|
function isSameOrInside(parent, candidate) {
|
|
11772
|
-
const relative11 =
|
|
11773
|
-
return relative11 === "" || relative11 !== ".." && !relative11.startsWith(`..${
|
|
12034
|
+
const relative11 = path13__namespace.relative(parent, candidate);
|
|
12035
|
+
return relative11 === "" || relative11 !== ".." && !relative11.startsWith(`..${path13__namespace.sep}`) && !path13__namespace.isAbsolute(relative11);
|
|
11774
12036
|
}
|
|
11775
12037
|
function isGeneratedWatchPath(candidate, paths) {
|
|
11776
|
-
const absolute = comparablePath(
|
|
11777
|
-
const outDir = comparablePath(
|
|
11778
|
-
const tmpDir = comparablePath(
|
|
12038
|
+
const absolute = comparablePath(path13__namespace.resolve(paths.cwd, candidate));
|
|
12039
|
+
const outDir = comparablePath(path13__namespace.resolve(paths.cwd, paths.outDir));
|
|
12040
|
+
const tmpDir = comparablePath(path13__namespace.resolve(paths.cwd, paths.tmpDir));
|
|
11779
12041
|
if (isSameOrInside(outDir, absolute) || isSameOrInside(tmpDir, absolute)) return true;
|
|
11780
|
-
const parent =
|
|
11781
|
-
if (parent ===
|
|
12042
|
+
const parent = path13__namespace.dirname(absolute);
|
|
12043
|
+
if (parent === path13__namespace.dirname(outDir) && path13__namespace.basename(absolute).startsWith(`${path13__namespace.basename(outDir)}.backup-`)) {
|
|
11782
12044
|
return true;
|
|
11783
12045
|
}
|
|
11784
12046
|
return absolute.split(/[\\/]+/).some((segment) => VCS_SEGMENTS.has(segment));
|
|
@@ -11795,8 +12057,8 @@ function decideWatchEvent(state, event, paths) {
|
|
|
11795
12057
|
return { state, action: "schedule" };
|
|
11796
12058
|
}
|
|
11797
12059
|
async function runWatchLoop(invocation, resolved) {
|
|
11798
|
-
const outDir =
|
|
11799
|
-
const tmpDir =
|
|
12060
|
+
const outDir = path13__namespace.resolve(resolved.cwd, resolved.outDir);
|
|
12061
|
+
const tmpDir = path13__namespace.resolve(resolved.cwd, resolved.tmpDir);
|
|
11800
12062
|
const paths = { cwd: resolved.cwd, outDir, tmpDir };
|
|
11801
12063
|
let state = initialWatchState();
|
|
11802
12064
|
let timer = null;
|
|
@@ -11861,11 +12123,11 @@ async function runWatchLoop(invocation, resolved) {
|
|
|
11861
12123
|
};
|
|
11862
12124
|
info("\u{1F440} Watching for changes. Press Ctrl+C to stop.");
|
|
11863
12125
|
void regenerate();
|
|
11864
|
-
const watcher =
|
|
12126
|
+
const watcher = fs12__namespace.watch(resolved.cwd, { recursive: true }, (_event, filename) => {
|
|
11865
12127
|
const decision = decideWatchEvent(
|
|
11866
12128
|
state,
|
|
11867
12129
|
{
|
|
11868
|
-
path: filename ?
|
|
12130
|
+
path: filename ? path13__namespace.resolve(resolved.cwd, filename.toString()) : null,
|
|
11869
12131
|
now: performance.now()
|
|
11870
12132
|
},
|
|
11871
12133
|
paths
|
|
@@ -11893,7 +12155,7 @@ async function runWatchLoop(invocation, resolved) {
|
|
|
11893
12155
|
return 0;
|
|
11894
12156
|
}
|
|
11895
12157
|
var entryFile = process.argv[1] ?? "";
|
|
11896
|
-
var entryName =
|
|
12158
|
+
var entryName = path13__namespace.basename(entryFile).toLowerCase();
|
|
11897
12159
|
var invokedDirectly = entryName === "cli.js" || entryName === "cli.cjs";
|
|
11898
12160
|
if (invokedDirectly) {
|
|
11899
12161
|
void main().then(
|