@gmickel/gno 1.39.0 → 1.39.2
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/browser-extension/artifacts/{gno-browser-clipper-v1.39.0.zip → gno-browser-clipper-v1.39.2.zip} +0 -0
- package/browser-extension/artifacts/gno-browser-clipper-v1.39.2.zip.sha256 +1 -0
- package/browser-extension/dist/manifest.json +1 -1
- package/package.json +1 -1
- package/spec/cli.md +29 -24
- package/src/cli/program.ts +265 -225
- package/src/cli/query-text.ts +41 -0
- package/browser-extension/artifacts/gno-browser-clipper-v1.39.0.zip.sha256 +0 -1
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
82afff37d4a331933c19bebb9c73972fd6eb665ffd1444bbdf65cfb0220dd692 gno-browser-clipper-v1.39.2.zip
|
package/package.json
CHANGED
package/spec/cli.md
CHANGED
|
@@ -1194,34 +1194,36 @@ BM25 keyword search over indexed documents.
|
|
|
1194
1194
|
**Synopsis:**
|
|
1195
1195
|
|
|
1196
1196
|
```bash
|
|
1197
|
-
gno search <
|
|
1197
|
+
gno search [query] [--query-file <path>] [-n <num>] [--min-score <num>] [-c <collection>] [--since <date>] [--until <date>] [--category <values>] [--author <text>] [--intent <text>] [--exclude <values>] [--tags-all <tags>] [--tags-any <tags>] [--full] [--line-numbers] [--lang <bcp47>] [--json|--files|--csv|--md|--xml]
|
|
1198
1198
|
```
|
|
1199
1199
|
|
|
1200
1200
|
**Arguments:**
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
|
1201
|
+
|
|
1202
|
+
| Arg | Type | Description |
|
|
1203
|
+
| --------- | ------ | -------------------------------------------------------------------- |
|
|
1204
|
+
| `[query]` | string | Search query. Optional when `--query-file` is set. Do not pass both. |
|
|
1204
1205
|
|
|
1205
1206
|
**Options:**
|
|
1206
1207
|
|
|
1207
|
-
| Option | Type | Default | Description
|
|
1208
|
-
| ----------------------- | -------- | ------------------------- |
|
|
1209
|
-
|
|
|
1210
|
-
|
|
|
1211
|
-
|
|
|
1212
|
-
|
|
|
1213
|
-
| `--
|
|
1214
|
-
| `--
|
|
1215
|
-
| `--
|
|
1216
|
-
| `--
|
|
1217
|
-
| `--
|
|
1218
|
-
| `--
|
|
1219
|
-
| `--tags-
|
|
1220
|
-
| `--
|
|
1221
|
-
| `--
|
|
1222
|
-
| `--
|
|
1223
|
-
| `--
|
|
1224
|
-
| `--
|
|
1208
|
+
| Option | Type | Default | Description |
|
|
1209
|
+
| ----------------------- | -------- | ------------------------- | -------------------------------------------------------------------------------------------------------------------- |
|
|
1210
|
+
| `--query-file` | string | none | Read the query from a file; `-` reads stdin so the query never appears on argv. Do not also pass a positional query. |
|
|
1211
|
+
| `-n` | integer | 5 (20 for --json/--files) | Max results |
|
|
1212
|
+
| `--min-score` | number | 0 | Minimum score threshold |
|
|
1213
|
+
| `-c, --collection` | string | all | Filter to collection |
|
|
1214
|
+
| `--since` | string | none | Modified-at lower bound (ISO date/time or relative token) |
|
|
1215
|
+
| `--until` | string | none | Modified-at upper bound (ISO date/time or relative token) |
|
|
1216
|
+
| `--category` | string | none | Filter to docs with matching category/content type (comma-separated) |
|
|
1217
|
+
| `--author` | string | none | Filter to docs where author contains value (case-insensitive) |
|
|
1218
|
+
| `--intent` | string | none | Disambiguating context for ambiguous queries; steers snippets without being searched directly |
|
|
1219
|
+
| `--exclude` | string | none | Hard-prune docs containing any comma-separated term in title/path/body |
|
|
1220
|
+
| `--tags-all` | string | none | Filter to docs with ALL tags (comma-separated) |
|
|
1221
|
+
| `--tags-any` | string | none | Filter to docs with ANY tag (comma-separated) |
|
|
1222
|
+
| `--project-root` | string[] | cwd | Trusted project root; repeatable, replaces default cwd/repository affinity |
|
|
1223
|
+
| `--no-project-affinity` | boolean | false | Disable project-aware soft ranking; invalid with `--project-root` |
|
|
1224
|
+
| `--full` | boolean | false | Include full mirror content instead of snippet |
|
|
1225
|
+
| `--line-numbers` | boolean | false | Include line numbers in output |
|
|
1226
|
+
| `--lang` | string | auto | Language filter/hint (BCP-47) |
|
|
1225
1227
|
|
|
1226
1228
|
**Scoring:**
|
|
1227
1229
|
|
|
@@ -1336,15 +1338,18 @@ Hybrid search combining BM25 and vector retrieval with optional expansion and re
|
|
|
1336
1338
|
**Synopsis:**
|
|
1337
1339
|
|
|
1338
1340
|
```bash
|
|
1339
|
-
gno query <
|
|
1341
|
+
gno query [query...] [--query-file <path>] [-n <num>] [--min-score <num>] [-c <collection>] [--since <date>] [--until <date>] [--category <values>] [--author <text>] [--intent <text>] [--exclude <values>] [-C <num>] [--tags-all <tags>] [--tags-any <tags>] [--full] [--line-numbers] [--lang <bcp47>] [--no-expand] [--no-rerank] [--graph] [--no-graph] [--query-mode <mode:text>]... [--explain] [--json|--files|--csv|--md|--xml]
|
|
1340
1342
|
gno query diagnose <query> --target <doc> [-n <num>] [--min-score <num>] [-c <collection>] [--since <date>] [--until <date>] [--category <values>] [--author <text>] [--intent <text>] [--exclude <values>] [-C <num>] [--tags-all <tags>] [--tags-any <tags>] [--lang <bcp47>] [--no-expand] [--no-rerank] [--graph] [--no-graph] [--json]
|
|
1341
1343
|
```
|
|
1342
1344
|
|
|
1345
|
+
The positional query is optional when `--query-file` is set. Do not pass both. `--query-file` is invalid on `query diagnose`.
|
|
1346
|
+
|
|
1343
1347
|
**Options:** Same as `gno search`, plus:
|
|
1344
1348
|
|
|
1345
1349
|
**Additional Options:**
|
|
1346
1350
|
| Option | Type | Description |
|
|
1347
1351
|
|--------|------|-------------|
|
|
1352
|
+
| `--query-file` | string | Same as `gno search`: read the query from a file (`-` is stdin). Invalid with a positional query and invalid on `query diagnose`. |
|
|
1348
1353
|
| `--no-expand` | boolean | Disable query expansion |
|
|
1349
1354
|
| `--no-rerank` | boolean | Disable cross-encoder reranking |
|
|
1350
1355
|
| `--graph` | boolean | Explicitly enable the default bounded one-hop graph neighbor expansion |
|
|
@@ -1357,7 +1362,7 @@ gno query diagnose <query> --target <doc> [-n <num>] [--min-score <num>] [-c <co
|
|
|
1357
1362
|
| `--target` | ref | Required for `query diagnose`; target document to diagnose |
|
|
1358
1363
|
|
|
1359
1364
|
`query diagnose` accepts the same `--project-root` and
|
|
1360
|
-
`--no-project-affinity` controls as `query`.
|
|
1365
|
+
`--no-project-affinity` controls as `query`. It rejects `--query-file`.
|
|
1361
1366
|
|
|
1362
1367
|
**Compatibility / Migration:**
|
|
1363
1368
|
|
package/src/cli/program.ts
CHANGED
|
@@ -46,6 +46,7 @@ import {
|
|
|
46
46
|
parseOptionalFloat,
|
|
47
47
|
parsePositiveInt,
|
|
48
48
|
} from "./options";
|
|
49
|
+
import { resolveCliQueryText } from "./query-text";
|
|
49
50
|
|
|
50
51
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
51
52
|
// Global State (set by preAction hook)
|
|
@@ -625,8 +626,12 @@ function wireTraceCommands(program: Command): void {
|
|
|
625
626
|
function wireSearchCommands(program: Command): void {
|
|
626
627
|
// search - BM25 keyword search
|
|
627
628
|
program
|
|
628
|
-
.command("search
|
|
629
|
+
.command("search [query]")
|
|
629
630
|
.description("BM25 keyword search")
|
|
631
|
+
.option(
|
|
632
|
+
"--query-file <path>",
|
|
633
|
+
"read query from file; use - for stdin (keeps the query off argv)"
|
|
634
|
+
)
|
|
630
635
|
.option("-n, --limit <num>", "max results")
|
|
631
636
|
.option("--min-score <num>", "minimum score threshold")
|
|
632
637
|
.option("-c, --collection <name>", "filter by collection")
|
|
@@ -662,95 +667,104 @@ function wireSearchCommands(program: Command): void {
|
|
|
662
667
|
.option("--csv", "CSV output")
|
|
663
668
|
.option("--xml", "XML output")
|
|
664
669
|
.option("--files", "file paths only")
|
|
665
|
-
.action(
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
670
|
+
.action(
|
|
671
|
+
async (
|
|
672
|
+
queryText: string | undefined,
|
|
673
|
+
cmdOpts: Record<string, unknown>
|
|
674
|
+
) => {
|
|
675
|
+
const format = getFormat(cmdOpts);
|
|
676
|
+
assertFormatSupported(CMD.search, format);
|
|
677
|
+
const globals = getGlobals();
|
|
678
|
+
queryText = await resolveCliQueryText(queryText, cmdOpts.queryFile);
|
|
674
679
|
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
}
|
|
680
|
+
// Validate empty query
|
|
681
|
+
if (!queryText.trim()) {
|
|
682
|
+
throw new CliError("VALIDATION", "Query cannot be empty");
|
|
683
|
+
}
|
|
680
684
|
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
? parseAndValidateTagFilter(cmdOpts.tagsAny as string)
|
|
690
|
-
: undefined;
|
|
691
|
-
} catch (error) {
|
|
692
|
-
throw new CliError(
|
|
693
|
-
"VALIDATION",
|
|
694
|
-
error instanceof Error ? error.message : "Invalid tag filter"
|
|
695
|
-
);
|
|
696
|
-
}
|
|
685
|
+
// Validate minScore range
|
|
686
|
+
const minScore = parseOptionalFloat("min-score", cmdOpts.minScore);
|
|
687
|
+
if (minScore !== undefined && (minScore < 0 || minScore > 1)) {
|
|
688
|
+
throw new CliError(
|
|
689
|
+
"VALIDATION",
|
|
690
|
+
"--min-score must be between 0 and 1"
|
|
691
|
+
);
|
|
692
|
+
}
|
|
697
693
|
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
:
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
694
|
+
// Parse and validate tag filters
|
|
695
|
+
let tagsAll: string[] | undefined;
|
|
696
|
+
let tagsAny: string[] | undefined;
|
|
697
|
+
try {
|
|
698
|
+
tagsAll = cmdOpts.tagsAll
|
|
699
|
+
? parseAndValidateTagFilter(cmdOpts.tagsAll as string)
|
|
700
|
+
: undefined;
|
|
701
|
+
tagsAny = cmdOpts.tagsAny
|
|
702
|
+
? parseAndValidateTagFilter(cmdOpts.tagsAny as string)
|
|
703
|
+
: undefined;
|
|
704
|
+
} catch (error) {
|
|
705
|
+
throw new CliError(
|
|
706
|
+
"VALIDATION",
|
|
707
|
+
error instanceof Error ? error.message : "Invalid tag filter"
|
|
708
|
+
);
|
|
709
|
+
}
|
|
706
710
|
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
711
|
+
const limit = cmdOpts.limit
|
|
712
|
+
? parsePositiveInt("limit", cmdOpts.limit)
|
|
713
|
+
: cmdOpts.verify
|
|
714
|
+
? 5
|
|
715
|
+
: getDefaultLimit(format);
|
|
716
|
+
const categories = parseCsvValues(cmdOpts.category);
|
|
717
|
+
const exclude = parseCsvValues(cmdOpts.exclude);
|
|
718
|
+
const projectAffinity = parseCliProjectAffinityOptions(cmdOpts);
|
|
719
|
+
|
|
720
|
+
const { search, formatSearch } = await import("./commands/search");
|
|
721
|
+
const result = await search(queryText, {
|
|
722
|
+
configPath: globals.config,
|
|
723
|
+
indexName: globals.index,
|
|
724
|
+
limit,
|
|
725
|
+
minScore,
|
|
726
|
+
collection: cmdOpts.collection as string | undefined,
|
|
727
|
+
lang: cmdOpts.lang as string | undefined,
|
|
728
|
+
since: cmdOpts.since as string | undefined,
|
|
729
|
+
until: cmdOpts.until as string | undefined,
|
|
730
|
+
categories,
|
|
731
|
+
author: cmdOpts.author as string | undefined,
|
|
732
|
+
intent: cmdOpts.intent as string | undefined,
|
|
733
|
+
exclude,
|
|
734
|
+
tagsAll,
|
|
735
|
+
tagsAny,
|
|
736
|
+
...projectAffinity,
|
|
737
|
+
full: Boolean(cmdOpts.full),
|
|
738
|
+
lineNumbers: Boolean(cmdOpts.lineNumbers),
|
|
739
|
+
json: format === "json",
|
|
740
|
+
md: format === "md",
|
|
741
|
+
csv: format === "csv",
|
|
742
|
+
xml: format === "xml",
|
|
743
|
+
files: format === "files",
|
|
744
|
+
});
|
|
732
745
|
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
746
|
+
// Check success before printing - stdout is for successful outputs only
|
|
747
|
+
if (!result.success) {
|
|
748
|
+
// Map validation errors to exit code 1
|
|
749
|
+
throw new CliError(
|
|
750
|
+
result.isValidation ? "VALIDATION" : "RUNTIME",
|
|
751
|
+
result.error
|
|
752
|
+
);
|
|
753
|
+
}
|
|
754
|
+
const output = formatSearch(result, {
|
|
755
|
+
json: format === "json",
|
|
756
|
+
md: format === "md",
|
|
757
|
+
csv: format === "csv",
|
|
758
|
+
xml: format === "xml",
|
|
759
|
+
files: format === "files",
|
|
760
|
+
full: Boolean(cmdOpts.full),
|
|
761
|
+
lineNumbers: Boolean(cmdOpts.lineNumbers),
|
|
762
|
+
terminalLinks: await resolveTerminalLinkPolicy(format),
|
|
763
|
+
});
|
|
764
|
+
await writeOutput(output, format);
|
|
765
|
+
writeRetrievalTraceReceipt(result.metadata);
|
|
740
766
|
}
|
|
741
|
-
|
|
742
|
-
json: format === "json",
|
|
743
|
-
md: format === "md",
|
|
744
|
-
csv: format === "csv",
|
|
745
|
-
xml: format === "xml",
|
|
746
|
-
files: format === "files",
|
|
747
|
-
full: Boolean(cmdOpts.full),
|
|
748
|
-
lineNumbers: Boolean(cmdOpts.lineNumbers),
|
|
749
|
-
terminalLinks: await resolveTerminalLinkPolicy(format),
|
|
750
|
-
});
|
|
751
|
-
await writeOutput(output, format);
|
|
752
|
-
writeRetrievalTraceReceipt(result.metadata);
|
|
753
|
-
});
|
|
767
|
+
);
|
|
754
768
|
|
|
755
769
|
// vsearch - Vector similarity search
|
|
756
770
|
program
|
|
@@ -876,8 +890,12 @@ function wireSearchCommands(program: Command): void {
|
|
|
876
890
|
|
|
877
891
|
// query - Hybrid search with expansion and reranking
|
|
878
892
|
program
|
|
879
|
-
.command("query
|
|
893
|
+
.command("query [query...]")
|
|
880
894
|
.description("Hybrid search with expansion and reranking")
|
|
895
|
+
.option(
|
|
896
|
+
"--query-file <path>",
|
|
897
|
+
"read query from file; use - for stdin (keeps the query off argv)"
|
|
898
|
+
)
|
|
881
899
|
.option("-n, --limit <num>", "max results")
|
|
882
900
|
.option("--min-score <num>", "minimum score threshold")
|
|
883
901
|
.option("-c, --collection <name>", "filter by collection")
|
|
@@ -931,103 +949,158 @@ function wireSearchCommands(program: Command): void {
|
|
|
931
949
|
.option("--csv", "CSV output")
|
|
932
950
|
.option("--xml", "XML output")
|
|
933
951
|
.option("--files", "file paths only")
|
|
934
|
-
.action(
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
952
|
+
.action(
|
|
953
|
+
async (
|
|
954
|
+
queryParts: string[] | undefined,
|
|
955
|
+
cmdOpts: Record<string, unknown>
|
|
956
|
+
) => {
|
|
957
|
+
const parts = queryParts ?? [];
|
|
958
|
+
const format = getFormat(cmdOpts);
|
|
959
|
+
const isDiagnose = parts[0] === "diagnose" && Boolean(cmdOpts.target);
|
|
960
|
+
assertFormatSupported(
|
|
961
|
+
isDiagnose ? CMD.queryDiagnose : CMD.query,
|
|
962
|
+
format
|
|
963
|
+
);
|
|
964
|
+
const diagnoseFormat = format === "json" ? "json" : "terminal";
|
|
965
|
+
const globals = getGlobals();
|
|
966
|
+
if (isDiagnose && cmdOpts.queryFile) {
|
|
967
|
+
throw new CliError(
|
|
968
|
+
"VALIDATION",
|
|
969
|
+
"query diagnose does not accept --query-file"
|
|
970
|
+
);
|
|
971
|
+
}
|
|
972
|
+
let queryText = isDiagnose
|
|
973
|
+
? parts.slice(1).join(" ")
|
|
974
|
+
: await resolveCliQueryText(parts.join(" "), cmdOpts.queryFile);
|
|
944
975
|
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
976
|
+
// Validate empty query
|
|
977
|
+
if (!queryText.trim()) {
|
|
978
|
+
throw new CliError("VALIDATION", "Query cannot be empty");
|
|
979
|
+
}
|
|
949
980
|
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
981
|
+
// Validate minScore range
|
|
982
|
+
const minScore = parseOptionalFloat("min-score", cmdOpts.minScore);
|
|
983
|
+
if (minScore !== undefined && (minScore < 0 || minScore > 1)) {
|
|
984
|
+
throw new CliError(
|
|
985
|
+
"VALIDATION",
|
|
986
|
+
"--min-score must be between 0 and 1"
|
|
987
|
+
);
|
|
988
|
+
}
|
|
955
989
|
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
990
|
+
// Parse optional structured query modes
|
|
991
|
+
let queryModes:
|
|
992
|
+
| import("../pipeline/types").QueryModeInput[]
|
|
993
|
+
| undefined;
|
|
994
|
+
if (Array.isArray(cmdOpts.queryMode) && cmdOpts.queryMode.length > 0) {
|
|
995
|
+
const { parseQueryModeSpecs } =
|
|
996
|
+
await import("../pipeline/query-modes");
|
|
997
|
+
const parsed = parseQueryModeSpecs(cmdOpts.queryMode as string[]);
|
|
998
|
+
if (!parsed.ok) {
|
|
999
|
+
throw new CliError("VALIDATION", parsed.error.message);
|
|
1000
|
+
}
|
|
1001
|
+
queryModes = parsed.value;
|
|
963
1002
|
}
|
|
964
|
-
queryModes = parsed.value;
|
|
965
|
-
}
|
|
966
1003
|
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
1004
|
+
const { normalizeStructuredQueryInput } =
|
|
1005
|
+
await import("../core/structured-query");
|
|
1006
|
+
const normalizedInput = normalizeStructuredQueryInput(
|
|
1007
|
+
queryText,
|
|
1008
|
+
queryModes ?? []
|
|
1009
|
+
);
|
|
1010
|
+
if (!normalizedInput.ok) {
|
|
1011
|
+
throw new CliError("VALIDATION", normalizedInput.error.message);
|
|
1012
|
+
}
|
|
1013
|
+
queryText = normalizedInput.value.query;
|
|
1014
|
+
queryModes =
|
|
1015
|
+
normalizedInput.value.queryModes.length > 0
|
|
1016
|
+
? normalizedInput.value.queryModes
|
|
1017
|
+
: undefined;
|
|
981
1018
|
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
1019
|
+
// Parse and validate tag filters
|
|
1020
|
+
let tagsAll: string[] | undefined;
|
|
1021
|
+
let tagsAny: string[] | undefined;
|
|
1022
|
+
try {
|
|
1023
|
+
tagsAll = cmdOpts.tagsAll
|
|
1024
|
+
? parseAndValidateTagFilter(cmdOpts.tagsAll as string)
|
|
1025
|
+
: undefined;
|
|
1026
|
+
tagsAny = cmdOpts.tagsAny
|
|
1027
|
+
? parseAndValidateTagFilter(cmdOpts.tagsAny as string)
|
|
1028
|
+
: undefined;
|
|
1029
|
+
} catch (error) {
|
|
1030
|
+
throw new CliError(
|
|
1031
|
+
"VALIDATION",
|
|
1032
|
+
error instanceof Error ? error.message : "Invalid tag filter"
|
|
1033
|
+
);
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
const limit = cmdOpts.limit
|
|
1037
|
+
? parsePositiveInt("limit", cmdOpts.limit)
|
|
1038
|
+
: getDefaultLimit(format);
|
|
1039
|
+
const { loadConfig } = await import("../config");
|
|
1040
|
+
const { getActivePreset } = await import("../llm/registry");
|
|
1041
|
+
const configResult = await loadConfig(globals.config);
|
|
1042
|
+
const activePresetId = configResult.ok
|
|
1043
|
+
? getActivePreset(configResult.value).id
|
|
1044
|
+
: "slim-tuned";
|
|
1045
|
+
const candidateLimit = cmdOpts.candidateLimit
|
|
1046
|
+
? parsePositiveInt("candidate-limit", cmdOpts.candidateLimit)
|
|
991
1047
|
: undefined;
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
1048
|
+
const categories = parseCsvValues(cmdOpts.category);
|
|
1049
|
+
const exclude = parseCsvValues(cmdOpts.exclude);
|
|
1050
|
+
const projectAffinity = parseCliProjectAffinityOptions(cmdOpts);
|
|
1051
|
+
|
|
1052
|
+
const depthPolicy = resolveDepthPolicy({
|
|
1053
|
+
presetId: activePresetId,
|
|
1054
|
+
fast: Boolean(cmdOpts.fast),
|
|
1055
|
+
thorough: Boolean(cmdOpts.thorough),
|
|
1056
|
+
expand: cmdOpts.expand === false ? false : undefined,
|
|
1057
|
+
rerank: cmdOpts.rerank === false ? false : undefined,
|
|
1058
|
+
candidateLimit,
|
|
1059
|
+
});
|
|
998
1060
|
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1061
|
+
if (isDiagnose) {
|
|
1062
|
+
const { queryDiagnose, formatQueryDiagnose } =
|
|
1063
|
+
await import("./commands/query");
|
|
1064
|
+
const result = await queryDiagnose(queryText, {
|
|
1065
|
+
configPath: globals.config,
|
|
1066
|
+
indexName: globals.index,
|
|
1067
|
+
target: cmdOpts.target as string,
|
|
1068
|
+
limit,
|
|
1069
|
+
minScore,
|
|
1070
|
+
collection: cmdOpts.collection as string | undefined,
|
|
1071
|
+
lang: cmdOpts.lang as string | undefined,
|
|
1072
|
+
since: cmdOpts.since as string | undefined,
|
|
1073
|
+
until: cmdOpts.until as string | undefined,
|
|
1074
|
+
categories,
|
|
1075
|
+
author: cmdOpts.author as string | undefined,
|
|
1076
|
+
intent: cmdOpts.intent as string | undefined,
|
|
1077
|
+
exclude,
|
|
1078
|
+
tagsAll,
|
|
1079
|
+
tagsAny,
|
|
1080
|
+
...projectAffinity,
|
|
1081
|
+
noExpand: depthPolicy.noExpand,
|
|
1082
|
+
noRerank: depthPolicy.noRerank,
|
|
1083
|
+
graph: cmdOpts.graph !== false,
|
|
1084
|
+
noGraph: Boolean(cmdOpts.fast) || cmdOpts.graph === false,
|
|
1085
|
+
candidateLimit: depthPolicy.candidateLimit,
|
|
1086
|
+
queryModes,
|
|
1087
|
+
json: diagnoseFormat === "json",
|
|
1088
|
+
});
|
|
1014
1089
|
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1090
|
+
if (!result.success) {
|
|
1091
|
+
throw new CliError("RUNTIME", result.error);
|
|
1092
|
+
}
|
|
1093
|
+
await writeOutput(
|
|
1094
|
+
formatQueryDiagnose(result, { format: diagnoseFormat }),
|
|
1095
|
+
diagnoseFormat
|
|
1096
|
+
);
|
|
1097
|
+
return;
|
|
1098
|
+
}
|
|
1023
1099
|
|
|
1024
|
-
|
|
1025
|
-
const
|
|
1026
|
-
await import("./commands/query");
|
|
1027
|
-
const result = await queryDiagnose(queryText, {
|
|
1100
|
+
const { query, formatQuery } = await import("./commands/query");
|
|
1101
|
+
const result = await query(queryText, {
|
|
1028
1102
|
configPath: globals.config,
|
|
1029
1103
|
indexName: globals.index,
|
|
1030
|
-
target: cmdOpts.target as string,
|
|
1031
1104
|
limit,
|
|
1032
1105
|
minScore,
|
|
1033
1106
|
collection: cmdOpts.collection as string | undefined,
|
|
@@ -1041,70 +1114,35 @@ function wireSearchCommands(program: Command): void {
|
|
|
1041
1114
|
tagsAll,
|
|
1042
1115
|
tagsAny,
|
|
1043
1116
|
...projectAffinity,
|
|
1117
|
+
full: Boolean(cmdOpts.full),
|
|
1118
|
+
lineNumbers: Boolean(cmdOpts.lineNumbers),
|
|
1044
1119
|
noExpand: depthPolicy.noExpand,
|
|
1045
1120
|
noRerank: depthPolicy.noRerank,
|
|
1046
1121
|
graph: cmdOpts.graph !== false,
|
|
1047
1122
|
noGraph: Boolean(cmdOpts.fast) || cmdOpts.graph === false,
|
|
1048
1123
|
candidateLimit: depthPolicy.candidateLimit,
|
|
1049
1124
|
queryModes,
|
|
1050
|
-
|
|
1125
|
+
explain: Boolean(cmdOpts.explain),
|
|
1126
|
+
json: format === "json",
|
|
1127
|
+
md: format === "md",
|
|
1128
|
+
csv: format === "csv",
|
|
1129
|
+
xml: format === "xml",
|
|
1130
|
+
files: format === "files",
|
|
1051
1131
|
});
|
|
1052
1132
|
|
|
1053
1133
|
if (!result.success) {
|
|
1054
1134
|
throw new CliError("RUNTIME", result.error);
|
|
1055
1135
|
}
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
const result = await query(queryText, {
|
|
1065
|
-
configPath: globals.config,
|
|
1066
|
-
indexName: globals.index,
|
|
1067
|
-
limit,
|
|
1068
|
-
minScore,
|
|
1069
|
-
collection: cmdOpts.collection as string | undefined,
|
|
1070
|
-
lang: cmdOpts.lang as string | undefined,
|
|
1071
|
-
since: cmdOpts.since as string | undefined,
|
|
1072
|
-
until: cmdOpts.until as string | undefined,
|
|
1073
|
-
categories,
|
|
1074
|
-
author: cmdOpts.author as string | undefined,
|
|
1075
|
-
intent: cmdOpts.intent as string | undefined,
|
|
1076
|
-
exclude,
|
|
1077
|
-
tagsAll,
|
|
1078
|
-
tagsAny,
|
|
1079
|
-
...projectAffinity,
|
|
1080
|
-
full: Boolean(cmdOpts.full),
|
|
1081
|
-
lineNumbers: Boolean(cmdOpts.lineNumbers),
|
|
1082
|
-
noExpand: depthPolicy.noExpand,
|
|
1083
|
-
noRerank: depthPolicy.noRerank,
|
|
1084
|
-
graph: cmdOpts.graph !== false,
|
|
1085
|
-
noGraph: Boolean(cmdOpts.fast) || cmdOpts.graph === false,
|
|
1086
|
-
candidateLimit: depthPolicy.candidateLimit,
|
|
1087
|
-
queryModes,
|
|
1088
|
-
explain: Boolean(cmdOpts.explain),
|
|
1089
|
-
json: format === "json",
|
|
1090
|
-
md: format === "md",
|
|
1091
|
-
csv: format === "csv",
|
|
1092
|
-
xml: format === "xml",
|
|
1093
|
-
files: format === "files",
|
|
1094
|
-
});
|
|
1095
|
-
|
|
1096
|
-
if (!result.success) {
|
|
1097
|
-
throw new CliError("RUNTIME", result.error);
|
|
1136
|
+
const output = formatQuery(result, {
|
|
1137
|
+
format,
|
|
1138
|
+
full: Boolean(cmdOpts.full),
|
|
1139
|
+
lineNumbers: Boolean(cmdOpts.lineNumbers),
|
|
1140
|
+
terminalLinks: await resolveTerminalLinkPolicy(format),
|
|
1141
|
+
});
|
|
1142
|
+
await writeOutput(output, format);
|
|
1143
|
+
writeRetrievalTraceReceipt(result.metadata);
|
|
1098
1144
|
}
|
|
1099
|
-
|
|
1100
|
-
format,
|
|
1101
|
-
full: Boolean(cmdOpts.full),
|
|
1102
|
-
lineNumbers: Boolean(cmdOpts.lineNumbers),
|
|
1103
|
-
terminalLinks: await resolveTerminalLinkPolicy(format),
|
|
1104
|
-
});
|
|
1105
|
-
await writeOutput(output, format);
|
|
1106
|
-
writeRetrievalTraceReceipt(result.metadata);
|
|
1107
|
-
});
|
|
1145
|
+
);
|
|
1108
1146
|
|
|
1109
1147
|
// bench - Retrieval benchmark fixture runner
|
|
1110
1148
|
program
|
|
@@ -3201,7 +3239,9 @@ function wireSkillCommands(program: Command): void {
|
|
|
3201
3239
|
| "hermes"
|
|
3202
3240
|
| "all",
|
|
3203
3241
|
force: Boolean(cmdOpts.force),
|
|
3204
|
-
json
|
|
3242
|
+
// The root program also defines a global --json and may consume the
|
|
3243
|
+
// flag; leave undefined here so the runner falls back to globals.
|
|
3244
|
+
json: cmdOpts.json === true ? true : undefined,
|
|
3205
3245
|
});
|
|
3206
3246
|
});
|
|
3207
3247
|
|
|
@@ -3252,7 +3292,7 @@ function wireSkillCommands(program: Command): void {
|
|
|
3252
3292
|
| "openclaw"
|
|
3253
3293
|
| "hermes"
|
|
3254
3294
|
| "all",
|
|
3255
|
-
json:
|
|
3295
|
+
json: cmdOpts.json === true ? true : undefined,
|
|
3256
3296
|
});
|
|
3257
3297
|
});
|
|
3258
3298
|
|
|
@@ -3316,7 +3356,7 @@ function wireSkillCommands(program: Command): void {
|
|
|
3316
3356
|
| "openclaw"
|
|
3317
3357
|
| "hermes"
|
|
3318
3358
|
| "all",
|
|
3319
|
-
json:
|
|
3359
|
+
json: cmdOpts.json === true ? true : undefined,
|
|
3320
3360
|
});
|
|
3321
3361
|
});
|
|
3322
3362
|
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve a search/query string from a positional argument or --query-file.
|
|
3
|
+
* `--query-file -` reads stdin so callers can keep the query off argv.
|
|
4
|
+
*
|
|
5
|
+
* @module src/cli/query-text
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { CliError } from "./errors";
|
|
9
|
+
|
|
10
|
+
const readQueryFile = async (path: string): Promise<string> => {
|
|
11
|
+
if (path.includes("\0")) {
|
|
12
|
+
throw new CliError("VALIDATION", "--query-file path is invalid");
|
|
13
|
+
}
|
|
14
|
+
try {
|
|
15
|
+
const raw =
|
|
16
|
+
path === "-" ? await Bun.stdin.text() : await Bun.file(path).text();
|
|
17
|
+
return raw.replace(/\s+$/u, "");
|
|
18
|
+
} catch (error) {
|
|
19
|
+
throw new CliError(
|
|
20
|
+
"VALIDATION",
|
|
21
|
+
error instanceof Error
|
|
22
|
+
? `Failed to read --query-file: ${error.message}`
|
|
23
|
+
: "Failed to read --query-file"
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const resolveCliQueryText = async (
|
|
29
|
+
positional: string | undefined,
|
|
30
|
+
queryFile: unknown
|
|
31
|
+
): Promise<string> => {
|
|
32
|
+
const file = typeof queryFile === "string" ? queryFile : "";
|
|
33
|
+
const pos = positional ?? "";
|
|
34
|
+
if (file !== "" && pos.trim() !== "") {
|
|
35
|
+
throw new CliError("VALIDATION", "Pass a query or --query-file, not both");
|
|
36
|
+
}
|
|
37
|
+
if (file !== "") {
|
|
38
|
+
return await readQueryFile(file);
|
|
39
|
+
}
|
|
40
|
+
return pos;
|
|
41
|
+
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
b3b2f2609cfe5c821eb9d22d76832b6ad329afa7496c0792e0dd4f5bd0f74fbc gno-browser-clipper-v1.39.0.zip
|