codebase-snapshot 0.9.9 → 0.9.12
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 +494 -0
- package/README.md +3 -3
- package/dist/bin.js +5227 -3461
- package/dist/{chunk-KUVFTJHK.js → chunk-3H45YMBG.js} +1848 -507
- package/dist/{chunk-HQBEQ67K.js → chunk-5OR3WVPW.js} +366 -84
- package/dist/cli.cjs +5245 -3499
- package/dist/cli.d.cts +282 -3
- package/dist/cli.d.ts +282 -3
- package/dist/cli.js +160 -38
- package/dist/generate-worker-D5Xgh27c.d.cts +57 -0
- package/dist/generate-worker-D5Xgh27c.d.ts +57 -0
- package/dist/index.cjs +1799 -504
- package/dist/index.d.cts +293 -4
- package/dist/index.d.ts +293 -4
- package/dist/index.js +1 -3
- package/dist/mcp.cjs +5670 -4877
- package/dist/mcp.d.cts +70 -2
- package/dist/mcp.d.ts +70 -2
- package/dist/mcp.js +2 -4
- package/dist/{types-Ca4PmkiQ.d.cts → types-CTewen3J.d.cts} +115 -2
- package/dist/{types-Ca4PmkiQ.d.ts → types-CTewen3J.d.ts} +115 -2
- package/docs/agent.md +1 -1
- package/docs/cli.md +21 -3
- package/docs/configuration.md +5 -0
- package/docs/how-to-feed-a-repo-to-claude.md +61 -0
- package/docs/mcp.md +23 -10
- package/docs/output.md +36 -4
- package/docs/stale-context-is-your-bug.md +13 -0
- package/docs/vs-repomix.md +1 -1
- package/package.json +5 -3
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { buildAgentContract, runStdioServer, COMMAND_OPTION_SCOPE, commandsForOption, SKILL_NAME, renderSkill, renderContractText } from './chunk-
|
|
2
|
-
|
|
1
|
+
import { buildAgentContract, runStdioServer, COMMAND_OPTION_SCOPE, commandsForOption, SKILL_NAME, renderSkill, renderContractText } from './chunk-5OR3WVPW.js';
|
|
2
|
+
export { buildAgentContract } from './chunk-5OR3WVPW.js';
|
|
3
|
+
import { shouldCheck, checkForUpdate, GENERATOR_VERSION, cacheFilePath, formatUpdateNotice, installKind, loadConfigFileDetailed, resolveConfig, validateSnapshot, describeManifestShapeProblem, explainPath, compareManifests, loadManifest, renderDiffText, generateSnapshot, formatNumber, isDiscoveryMode, ARTIFACT_NAMES, getPreset, unknownPresetMessage, GENERATOR_NAME, runInit, installPreCommitHook, PromptCancelled, planFirstRun, isEffectivelyEmpty, isInteractive, defaultIO, hasPriorSnapshot, DEFAULT_ANSWERS, findConfigFile, firstRunMessage, parseByteSize, gitignorePath, appendGitignoreEntries, escapeControls, MIN_MAX_PART_TOKENS, MIN_MAX_PART_BYTES, renderExplainText } from './chunk-3H45YMBG.js';
|
|
3
4
|
import { spawnSync } from 'child_process';
|
|
4
5
|
import * as fs from 'fs';
|
|
5
6
|
import * as path2 from 'path';
|
|
@@ -136,6 +137,7 @@ var CLI_OPTIONS = {
|
|
|
136
137
|
watch: { type: "boolean" },
|
|
137
138
|
"no-config": { type: "boolean" },
|
|
138
139
|
discovery: { type: "string" },
|
|
140
|
+
"max-part-tokens": { type: "string" },
|
|
139
141
|
preset: { type: "string" },
|
|
140
142
|
include: { type: "string" },
|
|
141
143
|
exclude: { type: "string" },
|
|
@@ -146,6 +148,12 @@ var CLI_OPTIONS = {
|
|
|
146
148
|
"no-install": { type: "boolean" },
|
|
147
149
|
target: { type: "string" },
|
|
148
150
|
"no-update-check": { type: "boolean" },
|
|
151
|
+
"install-hook": { type: "boolean" },
|
|
152
|
+
"changed-since": { type: "string" },
|
|
153
|
+
"with-dependents": { type: "boolean" },
|
|
154
|
+
staged: { type: "boolean" },
|
|
155
|
+
skeleton: { type: "boolean" },
|
|
156
|
+
sarif: { type: "boolean" },
|
|
149
157
|
help: { type: "boolean", short: "h" },
|
|
150
158
|
version: { type: "boolean", short: "v" }
|
|
151
159
|
};
|
|
@@ -185,7 +193,13 @@ Options:
|
|
|
185
193
|
--max-monolith-bytes <n> Skip monolith artefacts larger than n bytes
|
|
186
194
|
--max-part-bytes <n> Maximum byte budget per markdown part (default: 307200).
|
|
187
195
|
Accepts units: 120k, 1.5mb
|
|
196
|
+
--max-part-tokens <n> Per-part budget in tokens; narrows --max-part-bytes
|
|
188
197
|
--large-file-bytes <n> Threshold for head/tail truncation (default: 204800)
|
|
198
|
+
--changed-since <ref> Only files changed since this git ref, plus untracked ones
|
|
199
|
+
--staged Only files staged for the next commit
|
|
200
|
+
--with-dependents With the two above: also include their importers
|
|
201
|
+
--skeleton Emit TypeScript signatures instead of bodies
|
|
202
|
+
--sarif Also write reports/audit.sarif for GitHub Code Scanning
|
|
189
203
|
--include-sensitive-files Emit .env / *.pem / .npmrc / credential files
|
|
190
204
|
--skip-artifacts <names> Comma-separated artifacts to omit
|
|
191
205
|
(readme, manifest, parts, navigation,
|
|
@@ -211,9 +225,12 @@ Options:
|
|
|
211
225
|
--exclude <globs> Comma-separated exclude patterns
|
|
212
226
|
--yes Accept every default without prompting
|
|
213
227
|
--force Overwrite an existing config
|
|
228
|
+
--install-hook Write .git/hooks/pre-commit so a stale snapshot cannot be
|
|
229
|
+
committed. An existing hook is never replaced.
|
|
214
230
|
|
|
215
231
|
setup only:
|
|
216
232
|
--no-install Skip installing the dependency before generating
|
|
233
|
+
--install-hook As for init
|
|
217
234
|
--preset / --include / --exclude / --force As for init
|
|
218
235
|
|
|
219
236
|
skill only:
|
|
@@ -241,12 +258,12 @@ function parsePositiveInteger(raw, optionName, minimum) {
|
|
|
241
258
|
}
|
|
242
259
|
return value;
|
|
243
260
|
}
|
|
244
|
-
function parseByteOption(raw, optionName, minimum) {
|
|
261
|
+
function parseByteOption(raw, optionName, minimum, unit = "byte count") {
|
|
245
262
|
if (raw === void 0) return void 0;
|
|
246
263
|
const value = parseByteSize(raw);
|
|
247
264
|
if (value === void 0 || !Number.isSafeInteger(value)) {
|
|
248
265
|
throw new UsageError(
|
|
249
|
-
`--${optionName} expects a
|
|
266
|
+
`--${optionName} expects a ${unit} such as 120000 or "120k", received "${raw}".`
|
|
250
267
|
);
|
|
251
268
|
}
|
|
252
269
|
if (value < minimum) {
|
|
@@ -402,8 +419,10 @@ function parseCliArgs(argv) {
|
|
|
402
419
|
throw new UsageError("--skip-artifacts and --only-artifacts cannot be combined.");
|
|
403
420
|
}
|
|
404
421
|
let skipArtifacts;
|
|
422
|
+
let onlyArtifacts;
|
|
405
423
|
if (rawOnly !== void 0) {
|
|
406
424
|
const keep = parseArtifactList(String(rawOnly), "--only-artifacts");
|
|
425
|
+
onlyArtifacts = keep;
|
|
407
426
|
onlyNamesMonolith = keep.includes("monolith");
|
|
408
427
|
skipArtifacts = ARTIFACT_NAMES.filter(
|
|
409
428
|
(name) => !keep.includes(name)
|
|
@@ -432,7 +451,7 @@ function parseCliArgs(argv) {
|
|
|
432
451
|
`${ignored.join(", ")} ${ignored.length === 1 ? "does" : "do"} not apply to \`${command}\` and ${ignored.length === 1 ? "was" : "were"} not applied. ${ignored.length === 1 ? "It is" : "They are"} accepted by: ${owners.join(", ")}.${hint}`
|
|
433
452
|
);
|
|
434
453
|
}
|
|
435
|
-
if (command === "init" && values.preset !== void 0) {
|
|
454
|
+
if ((command === "init" || command === "setup") && values.preset !== void 0) {
|
|
436
455
|
const requested = String(values.preset);
|
|
437
456
|
if (!getPreset(requested)) throw new UsageError(unknownPresetMessage(requested));
|
|
438
457
|
}
|
|
@@ -476,6 +495,15 @@ function parseCliArgs(argv) {
|
|
|
476
495
|
"max-part-bytes",
|
|
477
496
|
MIN_MAX_PART_BYTES
|
|
478
497
|
),
|
|
498
|
+
// Tokens are counted, so `32k` is a shorthand a context window is often named with; the
|
|
499
|
+
// same parser accepts a bare integer. The floor is the byte floor rewritten in tokens —
|
|
500
|
+
// clamping a smaller budget up to it accepted the flag and then applied a different number.
|
|
501
|
+
maxPartTokens: parseByteOption(
|
|
502
|
+
values["max-part-tokens"],
|
|
503
|
+
"max-part-tokens",
|
|
504
|
+
MIN_MAX_PART_TOKENS,
|
|
505
|
+
"token count"
|
|
506
|
+
),
|
|
479
507
|
largeFileBytes: parseByteOption(
|
|
480
508
|
values["large-file-bytes"],
|
|
481
509
|
"large-file-bytes",
|
|
@@ -487,7 +515,22 @@ function parseCliArgs(argv) {
|
|
|
487
515
|
1
|
|
488
516
|
),
|
|
489
517
|
skipArtifacts,
|
|
490
|
-
|
|
518
|
+
onlyArtifacts,
|
|
519
|
+
discovery: isDiscoveryMode(rawDiscovery) ? rawDiscovery : void 0,
|
|
520
|
+
noUpdateCheck: values["no-update-check"] === true,
|
|
521
|
+
installHook: values["install-hook"] === true,
|
|
522
|
+
changedSince: values["changed-since"] === void 0 ? void 0 : String(values["changed-since"]),
|
|
523
|
+
// `undefined` when the flag was not given, never `false`.
|
|
524
|
+
//
|
|
525
|
+
// `resolveConfig` reads these as `cliOptions.x ?? config.x`, so a `false` here is an
|
|
526
|
+
// *explicit override* — it beat `skeleton: true` in a `snapshot.config.ts` and turned the
|
|
527
|
+
// setting off without a word. Every run that did not pass the flag sent `false`, so a config
|
|
528
|
+
// file could not turn any of these four on at all, and a snapshot generated with `--skeleton`
|
|
529
|
+
// could never be validated against the config that describes it.
|
|
530
|
+
staged: values.staged === true ? true : void 0,
|
|
531
|
+
withDependents: values["with-dependents"] === true ? true : void 0,
|
|
532
|
+
skeleton: values.skeleton === true ? true : void 0,
|
|
533
|
+
sarif: values.sarif === true ? true : void 0
|
|
491
534
|
};
|
|
492
535
|
}
|
|
493
536
|
var HelpRequested = class extends Error {
|
|
@@ -557,18 +600,24 @@ async function runInitCommand(invocation) {
|
|
|
557
600
|
include: splitList(invocation.include),
|
|
558
601
|
exclude: splitList(invocation.exclude),
|
|
559
602
|
skipArtifacts: invocation.skipArtifacts,
|
|
603
|
+
onlyArtifacts: invocation.onlyArtifacts,
|
|
604
|
+
includeMonolith: invocation.includeMonolith,
|
|
560
605
|
includeSensitiveFiles: invocation.includeSensitiveFiles,
|
|
561
606
|
yes: invocation.yes,
|
|
562
607
|
force: invocation.force,
|
|
563
608
|
dryRun: invocation.dryRun
|
|
564
609
|
});
|
|
610
|
+
const hook = invocation.installHook === true ? installPreCommitHook(invocation.cwd, result.outDir) : null;
|
|
565
611
|
if (invocation.format === "json") {
|
|
566
|
-
process.stdout.write(
|
|
567
|
-
|
|
612
|
+
process.stdout.write(
|
|
613
|
+
`${JSON.stringify(hook === null ? result : { ...result, hook }, null, 2)}
|
|
614
|
+
`
|
|
615
|
+
);
|
|
568
616
|
return 0;
|
|
569
617
|
}
|
|
570
618
|
if (!result.written) {
|
|
571
619
|
info(result.configText);
|
|
620
|
+
if (hook) for (const note of hook.notes) info(` ${note}`);
|
|
572
621
|
return 0;
|
|
573
622
|
}
|
|
574
623
|
info(`\u2705 Created ${path2.basename(result.configPath)} (${presetSummary(result)})`);
|
|
@@ -580,6 +629,7 @@ async function runInitCommand(invocation) {
|
|
|
580
629
|
info(` Added to .gitignore: ${result.gitignoreEntries.join(", ")}`);
|
|
581
630
|
}
|
|
582
631
|
for (const note of result.notes) info(` \u26A0 ${note}`);
|
|
632
|
+
if (hook) for (const note of hook.notes) info(` ${note}`);
|
|
583
633
|
info("");
|
|
584
634
|
info(` Next: ${nextStepHint(invocation.cwd, result.scripts.length > 0)}`);
|
|
585
635
|
return 0;
|
|
@@ -649,15 +699,28 @@ async function runSetupCommand(invocation, options = {}) {
|
|
|
649
699
|
preset: invocation.preset,
|
|
650
700
|
outDir: invocation.outDir,
|
|
651
701
|
maxPartBytes: invocation.maxPartBytesRaw ?? invocation.maxPartBytes,
|
|
702
|
+
// Written into the config, not just forwarded to the generation below. A setting that
|
|
703
|
+
// reaches the snapshot but not the file beside it is drift the very next run reports:
|
|
704
|
+
// `setup --discovery walk --large-file-bytes 100000` used to exit 0 and then fail its own
|
|
705
|
+
// `validate` with three configuration mismatches.
|
|
706
|
+
maxPartTokens: invocation.maxPartTokens,
|
|
707
|
+
largeFileBytes: invocation.largeFileBytes,
|
|
708
|
+
maxMonolithBytes: invocation.maxMonolithBytes ?? void 0,
|
|
709
|
+
discovery: invocation.discovery,
|
|
710
|
+
skeleton: invocation.skeleton === true ? true : void 0,
|
|
711
|
+
sarif: invocation.sarif === true ? true : void 0,
|
|
652
712
|
include: splitList(invocation.include),
|
|
653
713
|
exclude: splitList(invocation.exclude),
|
|
654
714
|
skipArtifacts: invocation.skipArtifacts,
|
|
715
|
+
onlyArtifacts: invocation.onlyArtifacts,
|
|
716
|
+
includeMonolith: invocation.includeMonolith,
|
|
655
717
|
includeSensitiveFiles: invocation.includeSensitiveFiles,
|
|
656
718
|
yes: !interactive,
|
|
657
719
|
force: invocation.force,
|
|
658
720
|
reuseConfig: true,
|
|
659
721
|
dryRun: invocation.dryRun
|
|
660
722
|
});
|
|
723
|
+
const hook = invocation.installHook === true ? installPreCommitHook(invocation.cwd, init.outDir) : null;
|
|
661
724
|
if (invocation.dryRun) {
|
|
662
725
|
const manager = invocation.noInstall ? null : detectPackageManager(invocation.cwd).name;
|
|
663
726
|
if (invocation.format === "json") {
|
|
@@ -703,6 +766,7 @@ async function runSetupCommand(invocation, options = {}) {
|
|
|
703
766
|
if (init.gitignoreEntries.length > 0) {
|
|
704
767
|
info(` Added to .gitignore: ${init.gitignoreEntries.join(", ")}`);
|
|
705
768
|
}
|
|
769
|
+
if (hook) for (const note of hook.notes) info(` ${note}`);
|
|
706
770
|
}
|
|
707
771
|
let install = null;
|
|
708
772
|
if (invocation.noInstall) {
|
|
@@ -723,6 +787,20 @@ async function runSetupCommand(invocation, options = {}) {
|
|
|
723
787
|
if ((invocation.skipArtifacts ?? []).length > 0) {
|
|
724
788
|
generateArgs.push("--skip-artifacts", (invocation.skipArtifacts ?? []).join(","));
|
|
725
789
|
}
|
|
790
|
+
if (invocation.includeMonolith === true) generateArgs.push("--include-monolith");
|
|
791
|
+
if (invocation.discovery !== void 0) generateArgs.push("--discovery", invocation.discovery);
|
|
792
|
+
if (invocation.largeFileBytes !== void 0) {
|
|
793
|
+
generateArgs.push("--large-file-bytes", String(invocation.largeFileBytes));
|
|
794
|
+
}
|
|
795
|
+
if (invocation.maxMonolithBytes !== void 0 && invocation.maxMonolithBytes !== null) {
|
|
796
|
+
generateArgs.push("--max-monolith-bytes", String(invocation.maxMonolithBytes));
|
|
797
|
+
}
|
|
798
|
+
if (invocation.maxPartTokens !== void 0) {
|
|
799
|
+
generateArgs.push("--max-part-tokens", String(invocation.maxPartTokens));
|
|
800
|
+
}
|
|
801
|
+
if (invocation.skeleton === true) generateArgs.push("--skeleton");
|
|
802
|
+
if (invocation.sarif === true) generateArgs.push("--sarif");
|
|
803
|
+
if (invocation.noUpdateCheck) generateArgs.push("--no-update-check");
|
|
726
804
|
if (invocation.watch) generateArgs.push("--watch");
|
|
727
805
|
if (invocation.format === "json") {
|
|
728
806
|
const generated = await captureStdout(() => main(generateArgs));
|
|
@@ -743,7 +821,8 @@ async function runSetupCommand(invocation, options = {}) {
|
|
|
743
821
|
dependency: init.dependency,
|
|
744
822
|
gitignoreEntries: init.gitignoreEntries,
|
|
745
823
|
install,
|
|
746
|
-
notes: init.notes
|
|
824
|
+
notes: init.notes,
|
|
825
|
+
hook
|
|
747
826
|
},
|
|
748
827
|
manifest
|
|
749
828
|
},
|
|
@@ -938,10 +1017,16 @@ ${USAGE}
|
|
|
938
1017
|
includeMonolith: invocation.includeMonolith,
|
|
939
1018
|
includeSensitiveFiles: invocation.includeSensitiveFiles,
|
|
940
1019
|
maxPartBytes: invocation.maxPartBytes,
|
|
1020
|
+
maxPartTokens: invocation.maxPartTokens,
|
|
941
1021
|
largeFileBytes: invocation.largeFileBytes,
|
|
942
1022
|
maxMonolithBytes: invocation.maxMonolithBytes,
|
|
943
1023
|
skipArtifacts: invocation.skipArtifacts,
|
|
944
|
-
discovery: invocation.discovery
|
|
1024
|
+
discovery: invocation.discovery,
|
|
1025
|
+
changedSince: invocation.changedSince,
|
|
1026
|
+
staged: invocation.staged,
|
|
1027
|
+
withDependents: invocation.withDependents,
|
|
1028
|
+
skeleton: invocation.skeleton,
|
|
1029
|
+
sarif: invocation.sarif
|
|
945
1030
|
},
|
|
946
1031
|
invocation.cwd
|
|
947
1032
|
);
|
|
@@ -1017,6 +1102,10 @@ ${USAGE}
|
|
|
1017
1102
|
return fail(invocation.format, err.message);
|
|
1018
1103
|
}
|
|
1019
1104
|
}
|
|
1105
|
+
if (invocation.watch) {
|
|
1106
|
+
const problem = watchSupportProblem();
|
|
1107
|
+
if (problem !== null) return fail(invocation.format, problem);
|
|
1108
|
+
}
|
|
1020
1109
|
const started = performance.now();
|
|
1021
1110
|
info(`\u{1F4F8} ${invocation.dryRun ? "Planning snapshot (dry run)" : "Generating snapshot"} for: ${resolved.cwd}`);
|
|
1022
1111
|
info(
|
|
@@ -1057,7 +1146,11 @@ ${USAGE}
|
|
|
1057
1146
|
const reports = [
|
|
1058
1147
|
artifacts.projectTree && "project-tree",
|
|
1059
1148
|
artifacts.navigation && "navigation",
|
|
1060
|
-
artifacts.audit && "audit"
|
|
1149
|
+
artifacts.audit && "audit",
|
|
1150
|
+
// `--sarif` writes beside the audit rather than inside `artifacts`, so it is listed
|
|
1151
|
+
// here by hand. Without it a run that produced `reports/audit.sarif` still reported
|
|
1152
|
+
// that every artifact was disabled and only the ownership marker had been written.
|
|
1153
|
+
resolved.sarif === true && "audit.sarif"
|
|
1061
1154
|
].filter(Boolean);
|
|
1062
1155
|
if (reports.length > 0) {
|
|
1063
1156
|
info(
|
|
@@ -1104,7 +1197,7 @@ ${USAGE}
|
|
|
1104
1197
|
`);
|
|
1105
1198
|
}
|
|
1106
1199
|
if (invocation.watch) {
|
|
1107
|
-
return await runWatchLoop(invocation, resolved);
|
|
1200
|
+
return await runWatchLoop(invocation, resolved, { generatedAlready: true });
|
|
1108
1201
|
}
|
|
1109
1202
|
return manifest.validation.status === "passed" ? 0 : 1;
|
|
1110
1203
|
} catch (err) {
|
|
@@ -1163,10 +1256,22 @@ function decideWatchEvent(state, event, paths) {
|
|
|
1163
1256
|
}
|
|
1164
1257
|
return { state, action: "schedule" };
|
|
1165
1258
|
}
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1259
|
+
function watchPathsFor(config) {
|
|
1260
|
+
return {
|
|
1261
|
+
cwd: config.cwd,
|
|
1262
|
+
outDir: path2.resolve(config.cwd, config.outDir),
|
|
1263
|
+
tmpDir: path2.resolve(config.cwd, config.tmpDir)
|
|
1264
|
+
};
|
|
1265
|
+
}
|
|
1266
|
+
function watchSupportProblem(platform = process.platform, version = process.versions.node) {
|
|
1267
|
+
if (platform !== "linux") return null;
|
|
1268
|
+
const [major, minor] = version.split(".").map((part) => Number.parseInt(part, 10));
|
|
1269
|
+
if (!Number.isFinite(major)) return null;
|
|
1270
|
+
if (major > 20 || major === 20 && (minor ?? 0) >= 13) return null;
|
|
1271
|
+
return `--watch needs recursive directory watching, which Node only provides on Linux from 20.13 (this is ${version}). Re-run \`generate\` after each change, or upgrade to Node 20.13 or later.`;
|
|
1272
|
+
}
|
|
1273
|
+
async function runWatchLoop(invocation, resolved, options) {
|
|
1274
|
+
let paths = watchPathsFor(resolved);
|
|
1170
1275
|
let state = initialWatchState();
|
|
1171
1276
|
let timer = null;
|
|
1172
1277
|
let stopped = false;
|
|
@@ -1208,14 +1313,21 @@ async function runWatchLoop(invocation, resolved) {
|
|
|
1208
1313
|
includeMonolith: invocation.includeMonolith,
|
|
1209
1314
|
includeSensitiveFiles: invocation.includeSensitiveFiles,
|
|
1210
1315
|
maxPartBytes: invocation.maxPartBytes,
|
|
1316
|
+
maxPartTokens: invocation.maxPartTokens,
|
|
1211
1317
|
largeFileBytes: invocation.largeFileBytes,
|
|
1212
1318
|
maxMonolithBytes: invocation.maxMonolithBytes,
|
|
1213
1319
|
skipArtifacts: invocation.skipArtifacts,
|
|
1214
|
-
discovery: invocation.discovery
|
|
1320
|
+
discovery: invocation.discovery,
|
|
1321
|
+
changedSince: invocation.changedSince,
|
|
1322
|
+
staged: invocation.staged,
|
|
1323
|
+
withDependents: invocation.withDependents,
|
|
1324
|
+
skeleton: invocation.skeleton,
|
|
1325
|
+
sarif: invocation.sarif
|
|
1215
1326
|
},
|
|
1216
1327
|
invocation.cwd
|
|
1217
1328
|
);
|
|
1218
1329
|
const manifest = generateSnapshot(next, { dryRun: invocation.dryRun });
|
|
1330
|
+
paths = watchPathsFor(next);
|
|
1219
1331
|
const elapsed = ((performance.now() - started) / 1e3).toFixed(2);
|
|
1220
1332
|
info(
|
|
1221
1333
|
`\u267B\uFE0F ${(/* @__PURE__ */ new Date()).toISOString()} ${manifest.counts.totalFiles} file(s), ${manifest.counts.partsCount} part(s), ${manifest.validation.status} (${elapsed}s)`
|
|
@@ -1229,25 +1341,37 @@ async function runWatchLoop(invocation, resolved) {
|
|
|
1229
1341
|
}
|
|
1230
1342
|
};
|
|
1231
1343
|
info("\u{1F440} Watching for changes. Press Ctrl+C to stop.");
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
if (
|
|
1245
|
-
|
|
1246
|
-
|
|
1344
|
+
let watcher;
|
|
1345
|
+
try {
|
|
1346
|
+
watcher = fs.watch(resolved.cwd, { recursive: true }, (_event, filename) => {
|
|
1347
|
+
const decision = decideWatchEvent(
|
|
1348
|
+
state,
|
|
1349
|
+
{
|
|
1350
|
+
path: filename ? path2.resolve(resolved.cwd, filename.toString()) : null,
|
|
1351
|
+
now: performance.now()
|
|
1352
|
+
},
|
|
1353
|
+
paths
|
|
1354
|
+
);
|
|
1355
|
+
state = decision.state;
|
|
1356
|
+
if (decision.action === "pending") {
|
|
1357
|
+
if (timer) {
|
|
1358
|
+
clearTimeout(timer);
|
|
1359
|
+
timer = null;
|
|
1360
|
+
}
|
|
1361
|
+
return;
|
|
1247
1362
|
}
|
|
1248
|
-
|
|
1249
|
-
}
|
|
1250
|
-
|
|
1363
|
+
if (decision.action === "schedule") schedule();
|
|
1364
|
+
});
|
|
1365
|
+
} catch (err) {
|
|
1366
|
+
const code = err.code;
|
|
1367
|
+
const detail = code === "ENOSPC" ? "the operating system's file-watch limit is exhausted; raise it (`fs.inotify.max_user_watches` on Linux) or run `generate` by hand" : code === "ERR_FEATURE_UNAVAILABLE_ON_PLATFORM" ? watchSupportProblem() ?? "this platform has no recursive directory watching" : err.message;
|
|
1368
|
+
warn(`\u274C Could not start watching ${resolved.cwd}: ${detail}`);
|
|
1369
|
+
warn(" The snapshot that was just written is complete and valid.");
|
|
1370
|
+
return 1;
|
|
1371
|
+
}
|
|
1372
|
+
watcher.on("error", (err) => {
|
|
1373
|
+
info(`\u26A0 Watch error: ${err.message}`);
|
|
1374
|
+
info(" The watcher may have missed changes. Restart with Ctrl+C if they stop arriving.");
|
|
1251
1375
|
});
|
|
1252
1376
|
await new Promise((resolve2) => {
|
|
1253
1377
|
const stop = () => {
|
|
@@ -1277,6 +1401,4 @@ if (invokedDirectly) {
|
|
|
1277
1401
|
);
|
|
1278
1402
|
}
|
|
1279
1403
|
|
|
1280
|
-
export { UsageError, WATCH_DEBOUNCE_MS, WATCH_SETTLE_MS, beginWatchRun, cleanInstallEnv, decideWatchEvent, finishWatchRun, initialWatchState, isGeneratedWatchPath, main, parseByteOption, parseCliArgs, parsePositiveInteger };
|
|
1281
|
-
//# sourceMappingURL=cli.js.map
|
|
1282
|
-
//# sourceMappingURL=cli.js.map
|
|
1404
|
+
export { CLI_OPTIONS, UsageError, WATCH_DEBOUNCE_MS, WATCH_SETTLE_MS, beginWatchRun, cleanInstallEnv, decideWatchEvent, finishWatchRun, initialWatchState, isGeneratedWatchPath, main, parseByteOption, parseCliArgs, parsePositiveInteger, watchPathsFor, watchSupportProblem };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/** What the caller needs from a finished run; the whole manifest can be megabytes. */
|
|
2
|
+
interface GenerateSummary {
|
|
3
|
+
fingerprint: string;
|
|
4
|
+
totalFiles: number;
|
|
5
|
+
skippedCount: number;
|
|
6
|
+
partsCount: number;
|
|
7
|
+
parts: Array<{
|
|
8
|
+
filename: string;
|
|
9
|
+
byteSize: number;
|
|
10
|
+
}>;
|
|
11
|
+
totalContentBytes: number;
|
|
12
|
+
warnings: string[];
|
|
13
|
+
}
|
|
14
|
+
type WorkerResults = {
|
|
15
|
+
ok: true;
|
|
16
|
+
summary: GenerateSummary;
|
|
17
|
+
} | {
|
|
18
|
+
ok: false;
|
|
19
|
+
message: string;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* The absolute path of the package entry this process is running from.
|
|
23
|
+
*
|
|
24
|
+
* `__dirname` exists in the CJS build and `import.meta.url` in the ESM one, and `typeof` on an
|
|
25
|
+
* undeclared identifier does not throw — so this resolves correctly in both without a build-time
|
|
26
|
+
* substitution.
|
|
27
|
+
*/
|
|
28
|
+
/**
|
|
29
|
+
* Where the worker finds this package's entry: the path, and the URL the worker imports.
|
|
30
|
+
*
|
|
31
|
+
* Exported so the URL can be tested directly. The defect it fixes only shows up for an install
|
|
32
|
+
* path that contains a `#`, `?` or `%`, or on a Windows drive letter, and no test can move the
|
|
33
|
+
* package's own `dist/` to such a path.
|
|
34
|
+
*
|
|
35
|
+
* `pathToFileURL` rather than `` `file://${path}` ``: the interpolation form turns a Windows path
|
|
36
|
+
* into `file://C:/…`, whose **host** is the drive letter, reads a `#` as a fragment and a `?` as
|
|
37
|
+
* a query, and leaves a space unescaped. `config.ts` already carries this note for the same
|
|
38
|
+
* reason.
|
|
39
|
+
*/
|
|
40
|
+
declare function workerEntry(directory: string, isCjs: boolean): {
|
|
41
|
+
path: string;
|
|
42
|
+
url: string;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Generates in a worker and resolves with the summary.
|
|
46
|
+
*
|
|
47
|
+
* A worker that fails to start, exits without posting, or throws at the module level is reported
|
|
48
|
+
* as a tool failure naming the reason — never silently retried on the calling thread, because a
|
|
49
|
+
* quiet fallback would hide exactly the condition this exists to avoid.
|
|
50
|
+
*/
|
|
51
|
+
declare function generateInWorker(cwd: string, cliOptions: {
|
|
52
|
+
cwd: string;
|
|
53
|
+
maxPartBytes?: number;
|
|
54
|
+
outDir?: string;
|
|
55
|
+
}): Promise<WorkerResults>;
|
|
56
|
+
|
|
57
|
+
export { type GenerateSummary as G, type WorkerResults as W, generateInWorker as g, workerEntry as w };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/** What the caller needs from a finished run; the whole manifest can be megabytes. */
|
|
2
|
+
interface GenerateSummary {
|
|
3
|
+
fingerprint: string;
|
|
4
|
+
totalFiles: number;
|
|
5
|
+
skippedCount: number;
|
|
6
|
+
partsCount: number;
|
|
7
|
+
parts: Array<{
|
|
8
|
+
filename: string;
|
|
9
|
+
byteSize: number;
|
|
10
|
+
}>;
|
|
11
|
+
totalContentBytes: number;
|
|
12
|
+
warnings: string[];
|
|
13
|
+
}
|
|
14
|
+
type WorkerResults = {
|
|
15
|
+
ok: true;
|
|
16
|
+
summary: GenerateSummary;
|
|
17
|
+
} | {
|
|
18
|
+
ok: false;
|
|
19
|
+
message: string;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* The absolute path of the package entry this process is running from.
|
|
23
|
+
*
|
|
24
|
+
* `__dirname` exists in the CJS build and `import.meta.url` in the ESM one, and `typeof` on an
|
|
25
|
+
* undeclared identifier does not throw — so this resolves correctly in both without a build-time
|
|
26
|
+
* substitution.
|
|
27
|
+
*/
|
|
28
|
+
/**
|
|
29
|
+
* Where the worker finds this package's entry: the path, and the URL the worker imports.
|
|
30
|
+
*
|
|
31
|
+
* Exported so the URL can be tested directly. The defect it fixes only shows up for an install
|
|
32
|
+
* path that contains a `#`, `?` or `%`, or on a Windows drive letter, and no test can move the
|
|
33
|
+
* package's own `dist/` to such a path.
|
|
34
|
+
*
|
|
35
|
+
* `pathToFileURL` rather than `` `file://${path}` ``: the interpolation form turns a Windows path
|
|
36
|
+
* into `file://C:/…`, whose **host** is the drive letter, reads a `#` as a fragment and a `?` as
|
|
37
|
+
* a query, and leaves a space unescaped. `config.ts` already carries this note for the same
|
|
38
|
+
* reason.
|
|
39
|
+
*/
|
|
40
|
+
declare function workerEntry(directory: string, isCjs: boolean): {
|
|
41
|
+
path: string;
|
|
42
|
+
url: string;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Generates in a worker and resolves with the summary.
|
|
46
|
+
*
|
|
47
|
+
* A worker that fails to start, exits without posting, or throws at the module level is reported
|
|
48
|
+
* as a tool failure naming the reason — never silently retried on the calling thread, because a
|
|
49
|
+
* quiet fallback would hide exactly the condition this exists to avoid.
|
|
50
|
+
*/
|
|
51
|
+
declare function generateInWorker(cwd: string, cliOptions: {
|
|
52
|
+
cwd: string;
|
|
53
|
+
maxPartBytes?: number;
|
|
54
|
+
outDir?: string;
|
|
55
|
+
}): Promise<WorkerResults>;
|
|
56
|
+
|
|
57
|
+
export { type GenerateSummary as G, type WorkerResults as W, generateInWorker as g, workerEntry as w };
|