mind-palace-graph 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/INSTALL.md +387 -0
- package/README.md +602 -0
- package/dist/api.d.ts +682 -0
- package/dist/api.js +660 -0
- package/dist/api.js.map +1 -0
- package/dist/cli.d.ts +95 -0
- package/dist/cli.js +856 -0
- package/dist/cli.js.map +1 -0
- package/dist/format.d.ts +16 -0
- package/dist/format.js +199 -0
- package/dist/format.js.map +1 -0
- package/dist/fuzzy.d.ts +45 -0
- package/dist/fuzzy.js +150 -0
- package/dist/fuzzy.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +528 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-server.d.ts +24 -0
- package/dist/mcp-server.js +187 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/mind-palace.d.ts +148 -0
- package/dist/mind-palace.js +780 -0
- package/dist/mind-palace.js.map +1 -0
- package/dist/nodes.d.ts +57 -0
- package/dist/nodes.js +220 -0
- package/dist/nodes.js.map +1 -0
- package/dist/pagination.d.ts +41 -0
- package/dist/pagination.js +63 -0
- package/dist/pagination.js.map +1 -0
- package/dist/palace-format.d.ts +30 -0
- package/dist/palace-format.js +146 -0
- package/dist/palace-format.js.map +1 -0
- package/dist/rg.d.ts +34 -0
- package/dist/rg.js +288 -0
- package/dist/rg.js.map +1 -0
- package/dist/sources.d.ts +87 -0
- package/dist/sources.js +457 -0
- package/dist/sources.js.map +1 -0
- package/dist/tokens.d.ts +35 -0
- package/dist/tokens.js +95 -0
- package/dist/tokens.js.map +1 -0
- package/dist/types.d.ts +236 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/package.json +67 -0
- package/skills/mpg-context/SKILL.md +556 -0
- package/skills/mpg-context/references/anti-patterns.md +133 -0
- package/skills/mpg-context/references/integration.md +123 -0
- package/skills/mpg-context/references/mind-palace.md +217 -0
- package/skills/mpg-context/references/multi-agent.md +147 -0
- package/skills/mpg-context/references/sources.md +120 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,856 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI argument parser and configuration resolution.
|
|
3
|
+
*
|
|
4
|
+
* We hand-roll the parser to avoid a dependency. The grammar is:
|
|
5
|
+
*
|
|
6
|
+
* mpg [pattern] [options]
|
|
7
|
+
*
|
|
8
|
+
* Pattern is the first positional argument. Options are flags below.
|
|
9
|
+
* The parser applies effort presets, then CLI overrides, then
|
|
10
|
+
* validates the final config.
|
|
11
|
+
*/
|
|
12
|
+
export const EFFORT_PRESETS = {
|
|
13
|
+
scan: { before: 20, after: 20, maxNodes: 100000 },
|
|
14
|
+
quick: { before: 200, after: 200, maxNodes: 10 },
|
|
15
|
+
normal: { before: 500, after: 500, maxNodes: 30 },
|
|
16
|
+
deep: { before: 2000, after: 2000, maxNodes: 100 },
|
|
17
|
+
auto: { before: 500, after: 500, maxNodes: 30 },
|
|
18
|
+
};
|
|
19
|
+
export const HELP = `mpg — node-centric context retrieval for LLM harnesses
|
|
20
|
+
|
|
21
|
+
USAGE
|
|
22
|
+
mpg <pattern> [options]
|
|
23
|
+
|
|
24
|
+
Pattern is a regular expression (ripgrep syntax). Use -F/--fixed-strings
|
|
25
|
+
for literal matching.
|
|
26
|
+
|
|
27
|
+
SOURCES (at least one is required unless reading stdin)
|
|
28
|
+
-i, --in <path> [<path>...] Path(s), file(s), or glob(s) to search.
|
|
29
|
+
Repeatable. Greedy: consumes non-flag args.
|
|
30
|
+
Accepts: a file, a directory (recurses),
|
|
31
|
+
a glob, @file (read paths from a file),
|
|
32
|
+
@- (read paths from stdin), or a
|
|
33
|
+
comma-separated list.
|
|
34
|
+
Paths can also be passed as trailing
|
|
35
|
+
positionals: mpg "TODO" src/ test/
|
|
36
|
+
--cmd <command> Search the stdout of a shell command
|
|
37
|
+
--stdin Read content from stdin (auto-detected when piped)
|
|
38
|
+
-u, --url <url> Search the body of an HTTP(S) URL
|
|
39
|
+
|
|
40
|
+
NODE SIZING
|
|
41
|
+
-b, --before <tokens> Tokens of context before each match [default: 500]
|
|
42
|
+
-a, --after <tokens> Tokens of context after each match [default: 500]
|
|
43
|
+
-n, --max-nodes <n> Maximum number of nodes to return [default: 30]
|
|
44
|
+
--max-tokens <n> Total token budget across all nodes
|
|
45
|
+
--strategy <mode> How to use --max-tokens: fill|deep [default: fill]
|
|
46
|
+
-e, --effort <level> Preset: scan|quick|normal|deep|auto [default: quick]
|
|
47
|
+
scan=20t/uncapped (index mode: every hit gets a
|
|
48
|
+
tiny disambiguating window; matches rg recall
|
|
49
|
+
AND precision regardless of hit count; combine
|
|
50
|
+
with --sort recent for a time-ordered index)
|
|
51
|
+
quick=200t/10n, normal=500t/30n, deep=2000t/100n
|
|
52
|
+
--sort <mode> default|recent|oldest [default: default]
|
|
53
|
+
Order returned nodes by source file mtime.
|
|
54
|
+
Pairs naturally with scan: "scan + --sort recent"
|
|
55
|
+
gives you the most-recently-changed hits first
|
|
56
|
+
(a time-ordered memory index). Paginate to dig
|
|
57
|
+
back into history.
|
|
58
|
+
--window-curve <fn> flat|linear|log [default: flat]
|
|
59
|
+
Per-node token-window decay across the result list.
|
|
60
|
+
flat: every node gets the full window (classic).
|
|
61
|
+
linear: full at rank 0, decays to ~10% at last rank.
|
|
62
|
+
log: window = full / log2(rank+2). Gentler decay.
|
|
63
|
+
Combine with --sort recent for "rich context on
|
|
64
|
+
what just changed, tight window on older history."
|
|
65
|
+
--clip <N> Sub-line clip mode. Drops line context; trims the
|
|
66
|
+
matched line itself to N chars around the matched
|
|
67
|
+
span (with ellipsis markers). Cheapest possible
|
|
68
|
+
node — for disambiguation, not synthesis.
|
|
69
|
+
Combine with --effort scan for a minimal index
|
|
70
|
+
(~30 tokens per hit at N=20).
|
|
71
|
+
--fuzzy Typo-tolerant search. Transforms a literal pattern
|
|
72
|
+
so up to 2 extra chars may appear between each
|
|
73
|
+
letter. Skipped if the pattern already looks like
|
|
74
|
+
a regex. Pure plain-text patterns only.
|
|
75
|
+
Default is quick: small windows, small node cap.
|
|
76
|
+
"Scan first, dig deeper" is the recommended pattern
|
|
77
|
+
for agents — start with scan or quick; bump to
|
|
78
|
+
normal or deep only when the small result was
|
|
79
|
+
ambiguous. Use multiple targeted parallel calls
|
|
80
|
+
instead of one huge deep call.
|
|
81
|
+
|
|
82
|
+
OUTPUT
|
|
83
|
+
-f, --format <fmt> llm|markdown|json|text [default: llm]
|
|
84
|
+
--json Alias for --format json (matches rg/gh/jq).
|
|
85
|
+
--color / --no-color Force or disable ANSI color [default: auto]
|
|
86
|
+
|
|
87
|
+
SEARCH OPTIONS (forwarded to ripgrep)
|
|
88
|
+
-I, --ignore-case Case-insensitive match
|
|
89
|
+
-w, --word Match whole words only
|
|
90
|
+
-F, --fixed-strings Treat pattern as literal
|
|
91
|
+
-U, --multiline Allow multi-line patterns
|
|
92
|
+
--hidden Search hidden files and directories
|
|
93
|
+
--no-ignore Don't respect .gitignore
|
|
94
|
+
--include <glob> Include files matching glob (repeatable)
|
|
95
|
+
--exclude <glob> Exclude files matching glob (repeatable)
|
|
96
|
+
--type <lang> ripgrep file type filter (e.g. ts, rust, py)
|
|
97
|
+
|
|
98
|
+
OTHER
|
|
99
|
+
-h, --help Show this help
|
|
100
|
+
-v, --version Show version
|
|
101
|
+
|
|
102
|
+
PAGINATION (for finer-grained traversal of large result sets)
|
|
103
|
+
--page <n> Show only the Nth page of results (1-indexed).
|
|
104
|
+
When set, paginates nodes (in search and
|
|
105
|
+
--mp-get) or stashes (in --mp-list).
|
|
106
|
+
--page-size <n> Items per page (default 10 for nodes,
|
|
107
|
+
20 for stashes).
|
|
108
|
+
--all Disable pagination; return everything.
|
|
109
|
+
|
|
110
|
+
MIND PALACE (the LLM's instantiable short-term memory)
|
|
111
|
+
A mind palace is a JSON file (default ./.mpg/mind-palace.json) that
|
|
112
|
+
holds named "stashes" of search results. The LLM harness can stash
|
|
113
|
+
results, recall them, and compose them across multiple invocations.
|
|
114
|
+
|
|
115
|
+
--mp-stash <name> <note> Stash the current search's results
|
|
116
|
+
under <name> with <note>. Adds to an
|
|
117
|
+
existing stash by default (dedup by
|
|
118
|
+
file:line); pass --mp-replace to
|
|
119
|
+
overwrite.
|
|
120
|
+
--mp-stash-tag <tag> Tag the stash (repeatable).
|
|
121
|
+
--mp-replace Replace an existing stash outright.
|
|
122
|
+
--mp-list [--mp-list-tag t] List all stashes (optionally filtered
|
|
123
|
+
by tag).
|
|
124
|
+
--mp-get <name> Print a stash. Default: **card view**
|
|
125
|
+
(note, tags, relations, sources,
|
|
126
|
+
counts — no per-node context). Add
|
|
127
|
+
--with-nodes or --full to include
|
|
128
|
+
the captured node block (the legacy
|
|
129
|
+
behavior). Card view is what an agent
|
|
130
|
+
almost always wants; the nodes block
|
|
131
|
+
is 5–6× more expensive in tokens.
|
|
132
|
+
--with-nodes, --full Opt-in to the full node dump on
|
|
133
|
+
--mp-get. Synonyms.
|
|
134
|
+
--mp-drop <name> Remove a stash from the palace.
|
|
135
|
+
--mp-from <name> Use a stashed file list as the search
|
|
136
|
+
target. The search re-runs fresh.
|
|
137
|
+
--mp-compose <a> <b> ... Union of multiple stashes' file lists
|
|
138
|
+
as the search target.
|
|
139
|
+
--mp-path <file> Path to the mind-palace.json file
|
|
140
|
+
(default: ./.mpg/mind-palace.json,
|
|
141
|
+
or the closest one walking up from
|
|
142
|
+
CWD). Use this for isolated sessions.
|
|
143
|
+
|
|
144
|
+
PRUNING & TTL (keep the palace from growing unbounded)
|
|
145
|
+
--mp-ttl <duration> Auto-expiry for this stash (e.g. 2h,
|
|
146
|
+
7d, 30m). The stash is marked with
|
|
147
|
+
expires_at; expired stashes can be
|
|
148
|
+
cleaned with --mp-prune-expired.
|
|
149
|
+
--mp-prune-older-than <d> Remove stashes older than duration.
|
|
150
|
+
--mp-prune-keep <n> Keep only the n most recent stashes.
|
|
151
|
+
--mp-prune-tag <tag> Remove all stashes with a given tag.
|
|
152
|
+
--mp-prune-expired Remove all expired stashes (those
|
|
153
|
+
whose --mp-ttl has elapsed).
|
|
154
|
+
--mp-prune-all Remove all stashes.
|
|
155
|
+
--mp-prune-dry-run Show what would be removed.
|
|
156
|
+
--mp-prune-confirm Required for --mp-prune-all.
|
|
157
|
+
|
|
158
|
+
RELATIONSHIPS (make the "graph" in mind-palace-graph real)
|
|
159
|
+
--mp-link <from> <to> <type> [note]
|
|
160
|
+
Create a directed edge between stashes.
|
|
161
|
+
Types: depends-on, related-to, see-also,
|
|
162
|
+
parent-of, child-of, supersedes, or
|
|
163
|
+
any custom string.
|
|
164
|
+
--mp-unlink <from> <to> Remove a relationship.
|
|
165
|
+
--mp-related <name> Show all stashes connected to <name>
|
|
166
|
+
(both inbound and outbound edges).
|
|
167
|
+
--mp-graph <name> [depth] Traversal graph from <name> up to
|
|
168
|
+
[depth] levels (default 3).
|
|
169
|
+
|
|
170
|
+
EXAMPLES
|
|
171
|
+
# Find TODOs in src/, with 500 tokens of context, up to 20 nodes
|
|
172
|
+
mpg "TODO" --in src/ --max-nodes 20
|
|
173
|
+
|
|
174
|
+
# Paginate: 5 nodes per page, start at page 1
|
|
175
|
+
mpg "TODO" --in src/ --max-nodes 100 --page 1 --page-size 5
|
|
176
|
+
|
|
177
|
+
# Browse a large stash 5 nodes at a time
|
|
178
|
+
mpg --mp-get auth-issues --page 2 --page-size 5
|
|
179
|
+
|
|
180
|
+
# Browse a long list of stashes
|
|
181
|
+
mpg --mp-list --page 1 --page-size 20
|
|
182
|
+
|
|
183
|
+
# Stash this search's results into the mind palace
|
|
184
|
+
mpg "TODO" --in src/ --mp-stash auth-todos "Auth TODOs to review"
|
|
185
|
+
|
|
186
|
+
# Use a stashed file list as the search target
|
|
187
|
+
mpg "rate" --mp-from auth-todos
|
|
188
|
+
|
|
189
|
+
# Search across multiple stashes' file lists
|
|
190
|
+
mpg "error" --mp-compose auth-todos perf-hotspots
|
|
191
|
+
|
|
192
|
+
# List all stashes
|
|
193
|
+
mpg --mp-list
|
|
194
|
+
|
|
195
|
+
# Inspect a stash
|
|
196
|
+
mpg --mp-get auth-todos
|
|
197
|
+
|
|
198
|
+
# Free a slot
|
|
199
|
+
mpg --mp-drop auth-todos
|
|
200
|
+
|
|
201
|
+
# Multiple paths in one flag (greedy)
|
|
202
|
+
mpg "TODO" --in src/ test/ docs/
|
|
203
|
+
|
|
204
|
+
# Trailing positional paths (rg-style)
|
|
205
|
+
mpg "TODO" src/ test/
|
|
206
|
+
|
|
207
|
+
# Read path list from a file
|
|
208
|
+
mpg "TODO" --in @filelist.txt
|
|
209
|
+
|
|
210
|
+
# Read path list from stdin
|
|
211
|
+
echo -e "src/\ntest/" | mpg "TODO" --in @-
|
|
212
|
+
|
|
213
|
+
# Comma-separated
|
|
214
|
+
mpg "TODO" --in src/,test/,docs/
|
|
215
|
+
|
|
216
|
+
# Quick recon: narrow context, 5 nodes
|
|
217
|
+
mpg "auth" --in . --effort quick --max-nodes 5
|
|
218
|
+
|
|
219
|
+
# Deep dive: wide context, capped at 16k tokens
|
|
220
|
+
mpg "session" --in src/auth/ --effort deep --max-tokens 16000
|
|
221
|
+
|
|
222
|
+
# Search the output of a command
|
|
223
|
+
mpg "error" --cmd "git log --oneline -100"
|
|
224
|
+
|
|
225
|
+
# Pipe content in
|
|
226
|
+
cat README.md | mpg "install"
|
|
227
|
+
|
|
228
|
+
# JSON for programmatic harness integration
|
|
229
|
+
mpg "TODO" --in src/ --format json
|
|
230
|
+
|
|
231
|
+
# Markdown for pasting into a doc or chat
|
|
232
|
+
mpg "TODO" --in src/ --format markdown
|
|
233
|
+
`;
|
|
234
|
+
export function parseArgs(argv) {
|
|
235
|
+
const args = {
|
|
236
|
+
inPaths: [],
|
|
237
|
+
stdin: false,
|
|
238
|
+
hidden: false,
|
|
239
|
+
noIgnore: false,
|
|
240
|
+
ignoreCase: false,
|
|
241
|
+
word: false,
|
|
242
|
+
fixedStrings: false,
|
|
243
|
+
multiline: false,
|
|
244
|
+
includeGlobs: [],
|
|
245
|
+
excludeGlobs: [],
|
|
246
|
+
mpStashTags: [],
|
|
247
|
+
mpStashReplace: false,
|
|
248
|
+
mpList: false,
|
|
249
|
+
mpListTags: [],
|
|
250
|
+
mpCompose: [],
|
|
251
|
+
mpExceptNames: [],
|
|
252
|
+
mpIntersect: [],
|
|
253
|
+
mpPruneAll: false,
|
|
254
|
+
mpPruneExpired: false,
|
|
255
|
+
mpPruneConfirm: false,
|
|
256
|
+
mpPruneDryRun: false,
|
|
257
|
+
mpGraphDepth: 3,
|
|
258
|
+
all: false,
|
|
259
|
+
ls: false,
|
|
260
|
+
mpStashLocations: false,
|
|
261
|
+
mpGetWithNodes: false,
|
|
262
|
+
noAutoTune: false,
|
|
263
|
+
fuzzy: false,
|
|
264
|
+
help: false,
|
|
265
|
+
version: false,
|
|
266
|
+
};
|
|
267
|
+
let i = 0;
|
|
268
|
+
while (i < argv.length) {
|
|
269
|
+
const a = argv[i];
|
|
270
|
+
// Long options with --no- prefix (boolean negation).
|
|
271
|
+
if (a === "--no-color") {
|
|
272
|
+
args.color = false;
|
|
273
|
+
i++;
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
if (a === "--color") {
|
|
277
|
+
args.color = true;
|
|
278
|
+
i++;
|
|
279
|
+
continue;
|
|
280
|
+
}
|
|
281
|
+
if (a === "-h" || a === "--help") {
|
|
282
|
+
args.help = true;
|
|
283
|
+
i++;
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
286
|
+
if (a === "-v" || a === "--version") {
|
|
287
|
+
args.version = true;
|
|
288
|
+
i++;
|
|
289
|
+
continue;
|
|
290
|
+
}
|
|
291
|
+
if (a === "-i" || a === "--in") {
|
|
292
|
+
// Greedy: consume every subsequent non-flag arg as a path.
|
|
293
|
+
// This lets users write `--in src/ test/ docs/` and get three paths.
|
|
294
|
+
// To pass a path starting with `-`, prefix it with `./` or use
|
|
295
|
+
// `--in=./-weird-name`. We also support comma-separated and the
|
|
296
|
+
// special `@file` / `@-` syntax (see resolveInputList).
|
|
297
|
+
i++;
|
|
298
|
+
while (i < argv.length && !argv[i].startsWith("-")) {
|
|
299
|
+
for (const p of argv[i].split(",").filter(Boolean)) {
|
|
300
|
+
args.inPaths.push(p);
|
|
301
|
+
}
|
|
302
|
+
i++;
|
|
303
|
+
}
|
|
304
|
+
continue;
|
|
305
|
+
}
|
|
306
|
+
if (a === "--cmd") {
|
|
307
|
+
args.cmd = requireValue(a, argv, ++i);
|
|
308
|
+
i++;
|
|
309
|
+
continue;
|
|
310
|
+
}
|
|
311
|
+
if (a === "--stdin") {
|
|
312
|
+
args.stdin = true;
|
|
313
|
+
i++;
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
if (a === "-u" || a === "--url") {
|
|
317
|
+
args.url = requireValue(a, argv, ++i);
|
|
318
|
+
i++;
|
|
319
|
+
continue;
|
|
320
|
+
}
|
|
321
|
+
if (a === "-b" || a === "--before") {
|
|
322
|
+
args.before = parseInt(requireValue(a, argv, ++i), 10);
|
|
323
|
+
i++;
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
if (a === "-a" || a === "--after") {
|
|
327
|
+
args.after = parseInt(requireValue(a, argv, ++i), 10);
|
|
328
|
+
i++;
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
if (a === "-n" || a === "--max-nodes") {
|
|
332
|
+
args.maxNodes = parseInt(requireValue(a, argv, ++i), 10);
|
|
333
|
+
i++;
|
|
334
|
+
continue;
|
|
335
|
+
}
|
|
336
|
+
if (a === "--max-tokens") {
|
|
337
|
+
args.maxTokens = parseInt(requireValue(a, argv, ++i), 10);
|
|
338
|
+
i++;
|
|
339
|
+
continue;
|
|
340
|
+
}
|
|
341
|
+
if (a === "--strategy") {
|
|
342
|
+
const v = requireValue(a, argv, ++i);
|
|
343
|
+
if (v !== "fill" && v !== "deep")
|
|
344
|
+
throw new Error(`--strategy must be fill or deep, got: ${v}`);
|
|
345
|
+
args.strategy = v;
|
|
346
|
+
i++;
|
|
347
|
+
continue;
|
|
348
|
+
}
|
|
349
|
+
if (a === "-e" || a === "--effort") {
|
|
350
|
+
const v = requireValue(a, argv, ++i);
|
|
351
|
+
if (!["scan", "quick", "normal", "deep", "auto"].includes(v)) {
|
|
352
|
+
throw new Error(`--effort must be scan|quick|normal|deep|auto, got: ${v}`);
|
|
353
|
+
}
|
|
354
|
+
args.effort = v;
|
|
355
|
+
i++;
|
|
356
|
+
continue;
|
|
357
|
+
}
|
|
358
|
+
if (a === "-f" || a === "--format") {
|
|
359
|
+
const v = requireValue(a, argv, ++i);
|
|
360
|
+
if (!["llm", "markdown", "json", "text"].includes(v)) {
|
|
361
|
+
throw new Error(`--format must be llm|markdown|json|text, got: ${v}`);
|
|
362
|
+
}
|
|
363
|
+
args.format = v;
|
|
364
|
+
i++;
|
|
365
|
+
continue;
|
|
366
|
+
}
|
|
367
|
+
// Common ecosystem alias — rg/gh/jq all use --json as a shorthand.
|
|
368
|
+
if (a === "--json") {
|
|
369
|
+
args.format = "json";
|
|
370
|
+
i++;
|
|
371
|
+
continue;
|
|
372
|
+
}
|
|
373
|
+
if (a === "-I" || a === "--ignore-case") {
|
|
374
|
+
args.ignoreCase = true;
|
|
375
|
+
i++;
|
|
376
|
+
continue;
|
|
377
|
+
}
|
|
378
|
+
if (a === "-w" || a === "--word") {
|
|
379
|
+
args.word = true;
|
|
380
|
+
i++;
|
|
381
|
+
continue;
|
|
382
|
+
}
|
|
383
|
+
if (a === "-F" || a === "--fixed-strings") {
|
|
384
|
+
args.fixedStrings = true;
|
|
385
|
+
i++;
|
|
386
|
+
continue;
|
|
387
|
+
}
|
|
388
|
+
if (a === "-U" || a === "--multiline") {
|
|
389
|
+
args.multiline = true;
|
|
390
|
+
i++;
|
|
391
|
+
continue;
|
|
392
|
+
}
|
|
393
|
+
if (a === "--hidden") {
|
|
394
|
+
args.hidden = true;
|
|
395
|
+
i++;
|
|
396
|
+
continue;
|
|
397
|
+
}
|
|
398
|
+
if (a === "--no-ignore") {
|
|
399
|
+
args.noIgnore = true;
|
|
400
|
+
i++;
|
|
401
|
+
continue;
|
|
402
|
+
}
|
|
403
|
+
if (a === "--include") {
|
|
404
|
+
args.includeGlobs.push(requireValue(a, argv, ++i));
|
|
405
|
+
i++;
|
|
406
|
+
continue;
|
|
407
|
+
}
|
|
408
|
+
if (a === "--exclude") {
|
|
409
|
+
args.excludeGlobs.push(requireValue(a, argv, ++i));
|
|
410
|
+
i++;
|
|
411
|
+
continue;
|
|
412
|
+
}
|
|
413
|
+
if (a === "--type") {
|
|
414
|
+
args.type = requireValue(a, argv, ++i);
|
|
415
|
+
i++;
|
|
416
|
+
continue;
|
|
417
|
+
}
|
|
418
|
+
// Mind palace flags.
|
|
419
|
+
if (a === "--mp-stash") {
|
|
420
|
+
// Consume two args: name and note.
|
|
421
|
+
args.mpStashName = requireValue(a, argv, ++i);
|
|
422
|
+
i++;
|
|
423
|
+
args.mpStashNote = requireValue("--mp-stash <note>", argv, i);
|
|
424
|
+
i++;
|
|
425
|
+
continue;
|
|
426
|
+
}
|
|
427
|
+
if (a === "--mp-stash-note") {
|
|
428
|
+
args.mpStashNote = requireValue(a, argv, ++i);
|
|
429
|
+
i++;
|
|
430
|
+
continue;
|
|
431
|
+
}
|
|
432
|
+
if (a === "--mp-stash-tag" || a === "--mp-tag") {
|
|
433
|
+
args.mpStashTags.push(requireValue(a, argv, ++i));
|
|
434
|
+
i++;
|
|
435
|
+
continue;
|
|
436
|
+
}
|
|
437
|
+
if (a === "--mp-replace") {
|
|
438
|
+
args.mpStashReplace = true;
|
|
439
|
+
i++;
|
|
440
|
+
continue;
|
|
441
|
+
}
|
|
442
|
+
if (a === "--mp-list") {
|
|
443
|
+
args.mpList = true;
|
|
444
|
+
i++;
|
|
445
|
+
continue;
|
|
446
|
+
}
|
|
447
|
+
if (a === "--mp-list-tag") {
|
|
448
|
+
args.mpListTags.push(requireValue(a, argv, ++i));
|
|
449
|
+
i++;
|
|
450
|
+
continue;
|
|
451
|
+
}
|
|
452
|
+
if (a === "--mp-get") {
|
|
453
|
+
args.mpGet = requireValue(a, argv, ++i);
|
|
454
|
+
i++;
|
|
455
|
+
continue;
|
|
456
|
+
}
|
|
457
|
+
if (a === "--with-nodes" || a === "--full") {
|
|
458
|
+
args.mpGetWithNodes = true;
|
|
459
|
+
i++;
|
|
460
|
+
continue;
|
|
461
|
+
}
|
|
462
|
+
if (a === "--mp-drop") {
|
|
463
|
+
args.mpDrop = requireValue(a, argv, ++i);
|
|
464
|
+
i++;
|
|
465
|
+
continue;
|
|
466
|
+
}
|
|
467
|
+
if (a === "--mp-from") {
|
|
468
|
+
args.mpFrom = requireValue(a, argv, ++i);
|
|
469
|
+
i++;
|
|
470
|
+
continue;
|
|
471
|
+
}
|
|
472
|
+
if (a === "--mp-compose") {
|
|
473
|
+
// Greedy: take every non-flag arg as a stash name.
|
|
474
|
+
i++;
|
|
475
|
+
while (i < argv.length && !argv[i].startsWith("-")) {
|
|
476
|
+
for (const p of argv[i].split(",").filter(Boolean)) {
|
|
477
|
+
args.mpCompose.push(p);
|
|
478
|
+
}
|
|
479
|
+
i++;
|
|
480
|
+
}
|
|
481
|
+
continue;
|
|
482
|
+
}
|
|
483
|
+
if (a === "--mp-except") {
|
|
484
|
+
args.mpExcept = requireValue(a, argv, ++i);
|
|
485
|
+
i++;
|
|
486
|
+
// Greedy remainder = the stashes to exclude.
|
|
487
|
+
while (i < argv.length && !argv[i].startsWith("-")) {
|
|
488
|
+
for (const p of argv[i].split(",").filter(Boolean)) {
|
|
489
|
+
args.mpExceptNames.push(p);
|
|
490
|
+
}
|
|
491
|
+
i++;
|
|
492
|
+
}
|
|
493
|
+
continue;
|
|
494
|
+
}
|
|
495
|
+
if (a === "--mp-intersect") {
|
|
496
|
+
// Greedy: take every non-flag arg as a stash name.
|
|
497
|
+
i++;
|
|
498
|
+
while (i < argv.length && !argv[i].startsWith("-")) {
|
|
499
|
+
for (const p of argv[i].split(",").filter(Boolean)) {
|
|
500
|
+
args.mpIntersect.push(p);
|
|
501
|
+
}
|
|
502
|
+
i++;
|
|
503
|
+
}
|
|
504
|
+
continue;
|
|
505
|
+
}
|
|
506
|
+
if (a === "--mp-path") {
|
|
507
|
+
args.mpPath = requireValue(a, argv, ++i);
|
|
508
|
+
i++;
|
|
509
|
+
continue;
|
|
510
|
+
}
|
|
511
|
+
if (a === "--mp-ttl") {
|
|
512
|
+
args.mpTtl = requireValue(a, argv, ++i);
|
|
513
|
+
i++;
|
|
514
|
+
continue;
|
|
515
|
+
}
|
|
516
|
+
// Pruning.
|
|
517
|
+
if (a === "--mp-prune-older-than") {
|
|
518
|
+
args.mpPruneOlderThan = requireValue(a, argv, ++i);
|
|
519
|
+
i++;
|
|
520
|
+
continue;
|
|
521
|
+
}
|
|
522
|
+
if (a === "--mp-prune-keep") {
|
|
523
|
+
args.mpPruneKeep = parseInt(requireValue(a, argv, ++i), 10);
|
|
524
|
+
i++;
|
|
525
|
+
continue;
|
|
526
|
+
}
|
|
527
|
+
if (a === "--mp-prune-tag") {
|
|
528
|
+
args.mpPruneTag = requireValue(a, argv, ++i);
|
|
529
|
+
i++;
|
|
530
|
+
continue;
|
|
531
|
+
}
|
|
532
|
+
if (a === "--mp-prune-all") {
|
|
533
|
+
args.mpPruneAll = true;
|
|
534
|
+
i++;
|
|
535
|
+
continue;
|
|
536
|
+
}
|
|
537
|
+
if (a === "--mp-prune-expired") {
|
|
538
|
+
args.mpPruneExpired = true;
|
|
539
|
+
i++;
|
|
540
|
+
continue;
|
|
541
|
+
}
|
|
542
|
+
if (a === "--mp-prune-confirm") {
|
|
543
|
+
args.mpPruneConfirm = true;
|
|
544
|
+
i++;
|
|
545
|
+
continue;
|
|
546
|
+
}
|
|
547
|
+
if (a === "--mp-prune-dry-run") {
|
|
548
|
+
args.mpPruneDryRun = true;
|
|
549
|
+
i++;
|
|
550
|
+
continue;
|
|
551
|
+
}
|
|
552
|
+
// Relationships.
|
|
553
|
+
if (a === "--mp-link") {
|
|
554
|
+
args.mpLinkFrom = requireValue(a, argv, ++i);
|
|
555
|
+
i++;
|
|
556
|
+
args.mpLinkTo = requireValue("--mp-link <to>", argv, i);
|
|
557
|
+
i++;
|
|
558
|
+
args.mpLinkType = requireValue("--mp-link <type>", argv, i);
|
|
559
|
+
i++;
|
|
560
|
+
// Optional note.
|
|
561
|
+
if (i < argv.length && !argv[i].startsWith("-")) {
|
|
562
|
+
args.mpLinkNote = argv[i];
|
|
563
|
+
i++;
|
|
564
|
+
}
|
|
565
|
+
continue;
|
|
566
|
+
}
|
|
567
|
+
if (a === "--mp-unlink") {
|
|
568
|
+
args.mpUnlinkFrom = requireValue(a, argv, ++i);
|
|
569
|
+
i++;
|
|
570
|
+
args.mpUnlinkTo = requireValue("--mp-unlink <to>", argv, i);
|
|
571
|
+
i++;
|
|
572
|
+
continue;
|
|
573
|
+
}
|
|
574
|
+
if (a === "--mp-related") {
|
|
575
|
+
args.mpRelated = requireValue(a, argv, ++i);
|
|
576
|
+
i++;
|
|
577
|
+
continue;
|
|
578
|
+
}
|
|
579
|
+
if (a === "--mp-graph") {
|
|
580
|
+
args.mpGraph = requireValue(a, argv, ++i);
|
|
581
|
+
i++;
|
|
582
|
+
// Optional depth.
|
|
583
|
+
if (i < argv.length && !argv[i].startsWith("-")) {
|
|
584
|
+
args.mpGraphDepth = parseInt(argv[i], 10);
|
|
585
|
+
i++;
|
|
586
|
+
}
|
|
587
|
+
continue;
|
|
588
|
+
}
|
|
589
|
+
// Pagination.
|
|
590
|
+
if (a === "--page") {
|
|
591
|
+
args.page = parseInt(requireValue(a, argv, ++i), 10);
|
|
592
|
+
i++;
|
|
593
|
+
continue;
|
|
594
|
+
}
|
|
595
|
+
if (a === "--page-size") {
|
|
596
|
+
args.pageSize = parseInt(requireValue(a, argv, ++i), 10);
|
|
597
|
+
i++;
|
|
598
|
+
continue;
|
|
599
|
+
}
|
|
600
|
+
if (a === "--all") {
|
|
601
|
+
args.all = true;
|
|
602
|
+
i++;
|
|
603
|
+
continue;
|
|
604
|
+
}
|
|
605
|
+
if (a === "--no-auto-tune") {
|
|
606
|
+
args.noAutoTune = true;
|
|
607
|
+
i++;
|
|
608
|
+
continue;
|
|
609
|
+
}
|
|
610
|
+
if (a === "--sort") {
|
|
611
|
+
const v = requireValue(a, argv, ++i);
|
|
612
|
+
if (!["default", "recent", "oldest"].includes(v)) {
|
|
613
|
+
throw new Error(`--sort must be default|recent|oldest, got: ${v}`);
|
|
614
|
+
}
|
|
615
|
+
args.sort = v;
|
|
616
|
+
i++;
|
|
617
|
+
continue;
|
|
618
|
+
}
|
|
619
|
+
if (a === "--window-curve") {
|
|
620
|
+
const v = requireValue(a, argv, ++i);
|
|
621
|
+
if (!["flat", "linear", "log"].includes(v)) {
|
|
622
|
+
throw new Error(`--window-curve must be flat|linear|log, got: ${v}`);
|
|
623
|
+
}
|
|
624
|
+
args.windowCurve = v;
|
|
625
|
+
i++;
|
|
626
|
+
continue;
|
|
627
|
+
}
|
|
628
|
+
if (a === "--clip") {
|
|
629
|
+
const v = requireValue(a, argv, ++i);
|
|
630
|
+
const n = parseInt(v, 10);
|
|
631
|
+
if (!Number.isFinite(n) || n < 0) {
|
|
632
|
+
throw new Error(`--clip must be a non-negative integer, got: ${v}`);
|
|
633
|
+
}
|
|
634
|
+
args.clipChars = n;
|
|
635
|
+
i++;
|
|
636
|
+
continue;
|
|
637
|
+
}
|
|
638
|
+
if (a === "--fuzzy") {
|
|
639
|
+
args.fuzzy = true;
|
|
640
|
+
i++;
|
|
641
|
+
continue;
|
|
642
|
+
}
|
|
643
|
+
if (a === "--ls" || a === "--tree") {
|
|
644
|
+
args.ls = true;
|
|
645
|
+
i++;
|
|
646
|
+
continue;
|
|
647
|
+
}
|
|
648
|
+
if (a === "--mp-stash-locations") {
|
|
649
|
+
args.mpStashLocations = true;
|
|
650
|
+
i++;
|
|
651
|
+
continue;
|
|
652
|
+
}
|
|
653
|
+
// Positional: first non-flag is the pattern. Any subsequent
|
|
654
|
+
// non-flag args are treated as input paths (like `rg`).
|
|
655
|
+
if (!a.startsWith("-") && args.pattern === undefined) {
|
|
656
|
+
args.pattern = a;
|
|
657
|
+
i++;
|
|
658
|
+
continue;
|
|
659
|
+
}
|
|
660
|
+
if (!a.startsWith("-") && args.pattern !== undefined) {
|
|
661
|
+
// Trailing positionals after the pattern are paths.
|
|
662
|
+
for (const p of a.split(",").filter(Boolean)) {
|
|
663
|
+
args.inPaths.push(p);
|
|
664
|
+
}
|
|
665
|
+
i++;
|
|
666
|
+
continue;
|
|
667
|
+
}
|
|
668
|
+
throw new Error(`Unknown argument: ${a}`);
|
|
669
|
+
}
|
|
670
|
+
return args;
|
|
671
|
+
}
|
|
672
|
+
function requireValue(flag, argv, i) {
|
|
673
|
+
if (i >= argv.length)
|
|
674
|
+
throw new Error(`Missing value for ${flag}`);
|
|
675
|
+
return argv[i];
|
|
676
|
+
}
|
|
677
|
+
/** Resolve a RawArgs into a fully-specified config. */
|
|
678
|
+
export function resolveConfig(raw) {
|
|
679
|
+
if (raw.help)
|
|
680
|
+
throw new HelpRequestedError();
|
|
681
|
+
if (raw.version)
|
|
682
|
+
throw new VersionRequestedError();
|
|
683
|
+
// Pattern is optional: required for searches and for --mp-from /
|
|
684
|
+
// --mp-compose, but not for --mp-list, --mp-get, or --mp-drop.
|
|
685
|
+
const pattern = raw.pattern ?? process.env.MPG_PATTERN;
|
|
686
|
+
const needsPattern = !raw.ls && (raw.inPaths.length > 0 ||
|
|
687
|
+
raw.cmd !== undefined ||
|
|
688
|
+
raw.url !== undefined ||
|
|
689
|
+
raw.stdin ||
|
|
690
|
+
raw.mpFrom !== undefined ||
|
|
691
|
+
(raw.mpCompose && raw.mpCompose.length > 0) ||
|
|
692
|
+
raw.mpExcept !== undefined ||
|
|
693
|
+
(raw.mpIntersect && raw.mpIntersect.length > 0) ||
|
|
694
|
+
raw.mpStashName !== undefined);
|
|
695
|
+
if (needsPattern && !pattern) {
|
|
696
|
+
throw new Error("No pattern provided. Pass it as the first positional argument, e.g. `mpg \"TODO\"`.");
|
|
697
|
+
}
|
|
698
|
+
// Apply effort preset, then explicit overrides.
|
|
699
|
+
const effort = raw.effort ?? "quick";
|
|
700
|
+
const preset = EFFORT_PRESETS[effort];
|
|
701
|
+
const before = raw.before ?? preset.before;
|
|
702
|
+
const after = raw.after ?? preset.after;
|
|
703
|
+
const maxNodes = raw.maxNodes ?? preset.maxNodes;
|
|
704
|
+
const strategy = raw.strategy ?? "fill";
|
|
705
|
+
const format = raw.format ?? "llm";
|
|
706
|
+
const color = raw.color ?? (process.stdout.isTTY ?? false);
|
|
707
|
+
// Build the source input list. Resolution to actual Source objects
|
|
708
|
+
// happens in the orchestrator (index.ts) since some sources need
|
|
709
|
+
// async I/O (commands, urls, stdin).
|
|
710
|
+
const inputs = [];
|
|
711
|
+
if (raw.inPaths.length > 0) {
|
|
712
|
+
for (const p of raw.inPaths)
|
|
713
|
+
inputs.push({ type: "path", path: p });
|
|
714
|
+
}
|
|
715
|
+
if (raw.cmd)
|
|
716
|
+
inputs.push({ type: "command", command: raw.cmd });
|
|
717
|
+
if (raw.url)
|
|
718
|
+
inputs.push({ type: "url", url: raw.url });
|
|
719
|
+
if (raw.stdin || (!process.stdin.isTTY && inputs.length === 0 && !needsPattern)) {
|
|
720
|
+
inputs.push({ type: "stdin" });
|
|
721
|
+
}
|
|
722
|
+
// If --mp-from or --mp-compose is given, we still need a pattern but
|
|
723
|
+
// can skip the source check: the orchestrator will derive sources
|
|
724
|
+
// from the palace. The check below catches "no inputs AND no palace".
|
|
725
|
+
const hasPalaceInput = raw.mpFrom !== undefined ||
|
|
726
|
+
(raw.mpCompose && raw.mpCompose.length > 0) ||
|
|
727
|
+
raw.mpExcept !== undefined ||
|
|
728
|
+
(raw.mpIntersect && raw.mpIntersect.length > 0);
|
|
729
|
+
if (inputs.length === 0 && !hasPalaceInput && !raw.mpStashName && !raw.mpList && !raw.mpGet && !raw.mpDrop) {
|
|
730
|
+
throw new Error("No source provided. Use --in <path>, --cmd <command>, --url <url>, --mp-from, --mp-compose, or pipe via stdin.");
|
|
731
|
+
}
|
|
732
|
+
const rgOptions = {};
|
|
733
|
+
if (raw.ignoreCase)
|
|
734
|
+
rgOptions.case_insensitive = true;
|
|
735
|
+
if (raw.word)
|
|
736
|
+
rgOptions.word_match = true;
|
|
737
|
+
if (raw.fixedStrings)
|
|
738
|
+
rgOptions.fixed_strings = true;
|
|
739
|
+
if (raw.multiline)
|
|
740
|
+
rgOptions.multiline = true;
|
|
741
|
+
if (raw.hidden)
|
|
742
|
+
rgOptions.hidden = true;
|
|
743
|
+
if (raw.noIgnore)
|
|
744
|
+
rgOptions.no_ignore = true;
|
|
745
|
+
if (raw.includeGlobs.length > 0)
|
|
746
|
+
rgOptions.include_globs = raw.includeGlobs;
|
|
747
|
+
if (raw.excludeGlobs.length > 0)
|
|
748
|
+
rgOptions.exclude_globs = raw.excludeGlobs;
|
|
749
|
+
if (raw.type)
|
|
750
|
+
rgOptions.type = raw.type;
|
|
751
|
+
// Build mind palace ops object if any palace flag was given.
|
|
752
|
+
let mind_palace;
|
|
753
|
+
if (raw.mpStashName || raw.mpList || raw.mpGet || raw.mpDrop ||
|
|
754
|
+
raw.mpFrom || (raw.mpCompose && raw.mpCompose.length > 0) ||
|
|
755
|
+
raw.mpExcept || (raw.mpIntersect && raw.mpIntersect.length > 0) ||
|
|
756
|
+
raw.mpPruneOlderThan || raw.mpPruneKeep !== undefined || raw.mpPruneTag ||
|
|
757
|
+
raw.mpPruneAll || raw.mpPruneExpired || raw.mpTtl || raw.mpPath ||
|
|
758
|
+
raw.mpLinkFrom || raw.mpUnlinkFrom || raw.mpRelated || raw.mpGraph) {
|
|
759
|
+
mind_palace = {
|
|
760
|
+
path: raw.mpPath,
|
|
761
|
+
prune_all: raw.mpPruneAll,
|
|
762
|
+
prune_confirm: raw.mpPruneConfirm,
|
|
763
|
+
prune_dry_run: raw.mpPruneDryRun,
|
|
764
|
+
};
|
|
765
|
+
if (raw.mpStashName) {
|
|
766
|
+
mind_palace.stash = {
|
|
767
|
+
name: raw.mpStashName,
|
|
768
|
+
note: raw.mpStashNote ?? "",
|
|
769
|
+
tags: raw.mpStashTags,
|
|
770
|
+
replace: raw.mpStashReplace,
|
|
771
|
+
};
|
|
772
|
+
}
|
|
773
|
+
if (raw.mpList)
|
|
774
|
+
mind_palace.list = { tags: raw.mpListTags };
|
|
775
|
+
if (raw.mpGet)
|
|
776
|
+
mind_palace.get = { name: raw.mpGet, with_nodes: raw.mpGetWithNodes };
|
|
777
|
+
if (raw.mpDrop)
|
|
778
|
+
mind_palace.drop = raw.mpDrop;
|
|
779
|
+
if (raw.mpFrom)
|
|
780
|
+
mind_palace.from = raw.mpFrom;
|
|
781
|
+
if (raw.mpCompose && raw.mpCompose.length > 0)
|
|
782
|
+
mind_palace.compose = raw.mpCompose;
|
|
783
|
+
if (raw.mpExcept) {
|
|
784
|
+
mind_palace.except = { base: raw.mpExcept, exclude: raw.mpExceptNames };
|
|
785
|
+
}
|
|
786
|
+
if (raw.mpIntersect && raw.mpIntersect.length > 0) {
|
|
787
|
+
mind_palace.intersect = raw.mpIntersect;
|
|
788
|
+
}
|
|
789
|
+
if (raw.mpTtl)
|
|
790
|
+
mind_palace.ttl = raw.mpTtl;
|
|
791
|
+
// Relationships.
|
|
792
|
+
if (raw.mpLinkFrom && raw.mpLinkTo && raw.mpLinkType) {
|
|
793
|
+
mind_palace.link = {
|
|
794
|
+
from: raw.mpLinkFrom,
|
|
795
|
+
to: raw.mpLinkTo,
|
|
796
|
+
type: raw.mpLinkType,
|
|
797
|
+
note: raw.mpLinkNote ?? "",
|
|
798
|
+
};
|
|
799
|
+
}
|
|
800
|
+
if (raw.mpUnlinkFrom && raw.mpUnlinkTo) {
|
|
801
|
+
mind_palace.unlink = { from: raw.mpUnlinkFrom, to: raw.mpUnlinkTo };
|
|
802
|
+
}
|
|
803
|
+
if (raw.mpRelated)
|
|
804
|
+
mind_palace.related = raw.mpRelated;
|
|
805
|
+
if (raw.mpGraph)
|
|
806
|
+
mind_palace.graph = { name: raw.mpGraph, depth: raw.mpGraphDepth ?? 3 };
|
|
807
|
+
// Pruning.
|
|
808
|
+
if (raw.mpPruneOlderThan)
|
|
809
|
+
mind_palace.prune_older_than = raw.mpPruneOlderThan;
|
|
810
|
+
if (raw.mpPruneKeep !== undefined)
|
|
811
|
+
mind_palace.prune_keep = raw.mpPruneKeep;
|
|
812
|
+
if (raw.mpPruneTag)
|
|
813
|
+
mind_palace.prune_tag = raw.mpPruneTag;
|
|
814
|
+
if (raw.mpPruneAll)
|
|
815
|
+
mind_palace.prune_all = true;
|
|
816
|
+
if (raw.mpPruneExpired)
|
|
817
|
+
mind_palace.prune_expired = true;
|
|
818
|
+
mind_palace.prune_confirm = raw.mpPruneConfirm;
|
|
819
|
+
mind_palace.prune_dry_run = raw.mpPruneDryRun;
|
|
820
|
+
}
|
|
821
|
+
return {
|
|
822
|
+
...(pattern !== undefined ? { pattern } : {}),
|
|
823
|
+
before_tokens: before,
|
|
824
|
+
after_tokens: after,
|
|
825
|
+
max_nodes: maxNodes,
|
|
826
|
+
max_tokens: raw.maxTokens,
|
|
827
|
+
strategy,
|
|
828
|
+
effort,
|
|
829
|
+
format,
|
|
830
|
+
color,
|
|
831
|
+
inputs,
|
|
832
|
+
rg_options: rgOptions,
|
|
833
|
+
mind_palace,
|
|
834
|
+
page: raw.page,
|
|
835
|
+
page_size: raw.pageSize,
|
|
836
|
+
all: raw.all,
|
|
837
|
+
ls: raw.ls,
|
|
838
|
+
mp_stash_locations: raw.mpStashLocations,
|
|
839
|
+
no_auto_tune: raw.noAutoTune,
|
|
840
|
+
auto_tune_eligible: !raw.noAutoTune && raw.before === undefined && raw.after === undefined,
|
|
841
|
+
sort: raw.sort,
|
|
842
|
+
window_curve: raw.windowCurve,
|
|
843
|
+
clip_chars: raw.clipChars,
|
|
844
|
+
fuzzy: raw.fuzzy,
|
|
845
|
+
};
|
|
846
|
+
}
|
|
847
|
+
// (Intentionally no extra validation hook here — --page/--all
|
|
848
|
+
// compatibility is checked at apply time where the combination is
|
|
849
|
+
// actually meaningful.)
|
|
850
|
+
export class HelpRequestedError extends Error {
|
|
851
|
+
constructor() { super("help requested"); this.name = "HelpRequestedError"; }
|
|
852
|
+
}
|
|
853
|
+
export class VersionRequestedError extends Error {
|
|
854
|
+
constructor() { super("version requested"); this.name = "VersionRequestedError"; }
|
|
855
|
+
}
|
|
856
|
+
//# sourceMappingURL=cli.js.map
|