quilltap 4.9.0-dev.71 → 4.9.0-dev.85
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -182,6 +182,7 @@ quilltap docs export <mount> <outputDir> # Mount → directory
|
|
|
182
182
|
quilltap docs find <pattern> # Substring match on file names (--mount, --ext, --type, --limit)
|
|
183
183
|
quilltap docs grep <pattern> # Substring match on extracted text (--mount, --ignore-case, -l, --max, --context)
|
|
184
184
|
quilltap docs status # Per-mount extraction + embedding rollup (--mount, --top)
|
|
185
|
+
quilltap docs docker-mounts # Bind mounts filesystem stores need under Docker (--format args|json)
|
|
185
186
|
|
|
186
187
|
# Server-required
|
|
187
188
|
quilltap docs scan <mount> # Trigger a rescan
|
|
@@ -391,8 +392,11 @@ Fish picks new completion files up automatically — no shell restart needed.
|
|
|
391
392
|
|
|
392
393
|
- **Subcommands**: `quilltap d<TAB>` → `db docs`
|
|
393
394
|
- **Sub-verbs per namespace**: `quilltap db s<TAB>` → `schema show`
|
|
395
|
+
- **Flags per verb**: `quilltap docs docker-mounts --<TAB>` → the flags that verb accepts
|
|
394
396
|
- **Instance names**: `quilltap --instance Fr<TAB>` → registered instances
|
|
395
|
-
- **Mount names**: `quilltap docs ls
|
|
397
|
+
- **Mount names**: both `--mount` and the positional a verb takes — `quilltap docs ls Qu<TAB>`, and either end of `docs move`/`copy`/`link`
|
|
398
|
+
|
|
399
|
+
Completions **parse the line rather than counting words**, so a flag typed anywhere the CLI itself accepts one does not derail them: `quilltap docs --instance Friday <TAB>` still offers the `docs` verbs. bash and zsh also reuse the `-i` / `-d` / `--passphrase` already on the line when looking store names up, so the names offered come from the instance you are addressing rather than the default one. fish completes `--mount` but not the positionals, and always reads the default instance.
|
|
396
400
|
|
|
397
401
|
Dynamic completions shell out to `quilltap`'s own subcommands. If the active instance is encrypted and no passphrase is reachable, the completion silently returns nothing rather than prompting in the middle of a tab.
|
|
398
402
|
|
|
@@ -94,3 +94,98 @@ describe('every subcommand has its own completion arm', () => {
|
|
|
94
94
|
expect(noFlags).toEqual([]);
|
|
95
95
|
});
|
|
96
96
|
});
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* The arm-per-subcommand check above is still too coarse: `docs docker-mounts`
|
|
100
|
+
* had its own arm in all three shells while `--format`, its only flag, was
|
|
101
|
+
* offered by none of them. A flag documented in a subcommand's own `--help` is
|
|
102
|
+
* the contract the user reads, so that text is the source of truth here —
|
|
103
|
+
* whatever `--help` advertises, the three templates must offer.
|
|
104
|
+
*
|
|
105
|
+
* Each entry names the single function whose template literal prints that
|
|
106
|
+
* subcommand's help.
|
|
107
|
+
*/
|
|
108
|
+
const HELP_SOURCES = {
|
|
109
|
+
db: ['bin/quilltap.js', 'printDbHelp'],
|
|
110
|
+
docs: ['lib/docs-commands.js', 'printDocsHelp'],
|
|
111
|
+
memories: ['lib/memories-commands.js', 'printMemoriesHelp'],
|
|
112
|
+
themes: ['lib/theme-commands.js', 'printHelp'],
|
|
113
|
+
instances: ['lib/instances-commands.js', 'printHelp'],
|
|
114
|
+
logs: ['lib/logs-commands.js', 'printLogsHelp'],
|
|
115
|
+
migrations: ['lib/migrations-commands.js', 'printHelp'],
|
|
116
|
+
maintenance: ['lib/maintenance-commands.js', 'printHelp'],
|
|
117
|
+
'file-verify': ['lib/file-verify-commands.js', 'printHelp'],
|
|
118
|
+
'memory-diff': ['lib/memory-diff-command.js', 'printMemoryDiffHelp'],
|
|
119
|
+
'recall-replay': ['lib/recall-replay-command.js', 'printRecallReplayHelp'],
|
|
120
|
+
completion: ['lib/completion-commands.js', 'printCompletionHelp'],
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
const PKG_ROOT = path.join(__dirname, '..', '..');
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Long flags named anywhere in one subcommand's help text. The declaration
|
|
127
|
+
* pattern tolerates arbitrary whitespace and an `async`/parameter list, so
|
|
128
|
+
* reformatting a help function does not fail a test about its content.
|
|
129
|
+
*/
|
|
130
|
+
function flagsInHelp(relPath, fnName) {
|
|
131
|
+
const src = fs.readFileSync(path.join(PKG_ROOT, relPath), 'utf8');
|
|
132
|
+
const decl = String.raw`(?:async\s+)?function\s+${fnName}\s*\([^)]*\)\s*\{`;
|
|
133
|
+
const body = src.match(new RegExp(`${decl}([\\s\\S]*?)\\n\\}`));
|
|
134
|
+
if (!body) throw new Error(`Could not locate ${fnName}() in ${relPath}`);
|
|
135
|
+
return [...new Set(body[1].match(/--[a-z0-9][a-z0-9-]+/g) || [])].sort();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* `--max` is a prefix of `--max-nodes`, so a plain substring test passes for a
|
|
140
|
+
* flag that is not actually there. Require the match to end at a non-flag
|
|
141
|
+
* character.
|
|
142
|
+
*/
|
|
143
|
+
function mentionsFlag(haystack, flag) {
|
|
144
|
+
return new RegExp(`${flag}(?![a-z0-9-])`).test(haystack);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
describe('completions offer every flag the help text advertises', () => {
|
|
148
|
+
it('covers every subcommand in the dispatch table', () => {
|
|
149
|
+
// A new subcommand needs a help source here, or its flags go unchecked.
|
|
150
|
+
expect(Object.keys(HELP_SOURCES).sort()).toEqual([...SUBCOMMANDS].sort());
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
const cases = Object.entries(HELP_SOURCES).flatMap(([sub, [file, fn]]) =>
|
|
154
|
+
['bash', 'zsh', 'fish'].map((shell) => [sub, shell, file, fn])
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
it.each(cases)('%s: %s template offers every documented flag', (sub, shell, file, fn) => {
|
|
158
|
+
const tpl = fs.readFileSync(path.join(COMPLETION_DIR, `${shell}.template`), 'utf8');
|
|
159
|
+
// fish spells the flag `-l 'name'`, already an exact quoted token.
|
|
160
|
+
const present = (flag) =>
|
|
161
|
+
shell === 'fish' ? tpl.includes(`-l '${flag.slice(2)}'`) : mentionsFlag(tpl, flag);
|
|
162
|
+
const missing = flagsInHelp(file, fn).filter((flag) => !present(flag));
|
|
163
|
+
expect(missing).toEqual([]);
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* bash cannot infer which flags swallow the next word, so it carries explicit
|
|
169
|
+
* `vf_*` lists. A valued flag missing from its list makes the flag's value look
|
|
170
|
+
* like the subcommand's verb — the bug 101 failure mode. zsh and fish take the
|
|
171
|
+
* value from the flag's own spec, so only bash needs guarding.
|
|
172
|
+
*/
|
|
173
|
+
describe('bash knows which docs flags take a value', () => {
|
|
174
|
+
it('lists every valued docs flag in vf_docs', () => {
|
|
175
|
+
const tpl = fs.readFileSync(path.join(COMPLETION_DIR, 'bash.template'), 'utf8');
|
|
176
|
+
// The scanner reads `$vf_global$vf_docs`, so a flag in either list counts.
|
|
177
|
+
const vfGlobal = tpl.match(/local vf_global="([^"]*)"/);
|
|
178
|
+
const vfDocs = tpl.match(/local vf_docs="([^"]*)"/);
|
|
179
|
+
expect(vfGlobal).toBeTruthy();
|
|
180
|
+
expect(vfDocs).toBeTruthy();
|
|
181
|
+
const scanned = new Set(`${vfGlobal[1]} ${vfDocs[1]}`.trim().split(/\s+/));
|
|
182
|
+
// A docs flag zsh declares with a `:value:` spec is by definition valued.
|
|
183
|
+
const zsh = fs.readFileSync(path.join(COMPLETION_DIR, 'zsh.template'), 'utf8');
|
|
184
|
+
const docsOpts = zsh.match(/docs_opts=\(([\s\S]*?)\n \)/);
|
|
185
|
+
expect(docsOpts).toBeTruthy();
|
|
186
|
+
const valued = [...docsOpts[1].matchAll(/'(--[a-z0-9-]+)\[[^\]]*\]:[^']*'/g)].map((m) => m[1]);
|
|
187
|
+
expect(valued.length).toBeGreaterThan(5);
|
|
188
|
+
const missing = valued.filter((flag) => !scanned.has(flag));
|
|
189
|
+
expect(missing).toEqual([]);
|
|
190
|
+
});
|
|
191
|
+
});
|
|
@@ -70,7 +70,7 @@ _quilltap_complete() {
|
|
|
70
70
|
# `quilltap docs --limit 5 <TAB>` used to lose the verb list.
|
|
71
71
|
local vf_global=" -d --data-dir -i --instance -p --port --passphrase "
|
|
72
72
|
local vf_db=" --limit --grep --character --project --about --source --chat --message --field --tail --last --from --type --out --id --count "
|
|
73
|
-
local vf_docs=" --mount --folder --type --ext --limit --max --context --top --threshold --sort --depth --max-nodes "
|
|
73
|
+
local vf_docs=" --mount --folder --type --ext --limit --max --context --top --threshold --sort --depth --max-nodes --format "
|
|
74
74
|
local vf_themes=" -o --output -k --key -n --name "
|
|
75
75
|
local vf_memories=" -d --data-dir --instance --passphrase --port --character --about --source --chat --project --since --until --min-importance --min-reinforced --sort --limit --in --max --context --depth --max-nodes --top --threshold "
|
|
76
76
|
local vf_logs=" --stream --tail --grep "
|
|
@@ -193,6 +193,10 @@ _quilltap_complete() {
|
|
|
193
193
|
COMPREPLY=($(compgen -W "combined error stdout stderr startup" -- "$cur"))
|
|
194
194
|
return
|
|
195
195
|
;;
|
|
196
|
+
--format)
|
|
197
|
+
COMPREPLY=($(compgen -W "args json" -- "$cur"))
|
|
198
|
+
return
|
|
199
|
+
;;
|
|
196
200
|
esac
|
|
197
201
|
|
|
198
202
|
# Subcommand-specific completion
|
|
@@ -227,7 +231,8 @@ _quilltap_complete() {
|
|
|
227
231
|
local docs_verbs="list show files ls dir tree read export scan write delete mkdir move copy link rmdir mvdir status docker-mounts find grep reindex embed"
|
|
228
232
|
local docs_flags="--mount --instance --data-dir --passphrase --port --json --help \
|
|
229
233
|
--uri --base64 --force --rendered --links --folder --type --ext --limit --max --context --top --threshold \
|
|
230
|
-
--ignore-case -l --wait -R --recursive --sort -r --reverse --depth --max-nodes --long --semantic
|
|
234
|
+
--ignore-case -l --wait -R --recursive --sort -r --reverse --depth --max-nodes --long --semantic \
|
|
235
|
+
--format"
|
|
231
236
|
if [[ "$cur" == -* ]]; then
|
|
232
237
|
COMPREPLY=($(compgen -W "$docs_flags" -- "$cur"))
|
|
233
238
|
elif [[ -z "$subverb" ]]; then
|
|
@@ -184,6 +184,9 @@ complete -c quilltap -n '__quilltap_using_subcommand docs' -l 'depth' -d 'Maximu
|
|
|
184
184
|
complete -c quilltap -n '__quilltap_using_subcommand docs' -l 'max-nodes' -d 'Maximum graph nodes' -x
|
|
185
185
|
complete -c quilltap -n '__quilltap_using_subcommand docs' -l 'long' -d 'Long-form output'
|
|
186
186
|
complete -c quilltap -n '__quilltap_using_subcommand docs' -l 'semantic' -d 'Semantic search'
|
|
187
|
+
complete -c quilltap -n '__quilltap_using_subcommand docs' -l 'uri' -d 'Show canonical qtap:// URIs'
|
|
188
|
+
complete -c quilltap -n '__quilltap_using_subcommand docs' -l 'base64' -d 'Base64 transfer for binary files'
|
|
189
|
+
complete -c quilltap -n '__quilltap_using_subverb docs docker-mounts' -l 'format' -d 'Output shape' -x -a 'args json'
|
|
187
190
|
|
|
188
191
|
# ---------- themes verbs ----------
|
|
189
192
|
complete -c quilltap -n '__quilltap_using_subcommand themes' -f -a 'list' -d 'List themes'
|