@gmickel/gno 1.22.0 → 1.23.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/README.md +16 -1
- package/assets/skill/SKILL.md +15 -0
- package/package.json +1 -1
- package/spec/cli.md +36 -20
- package/spec/evals-agentic.md +35 -0
- package/spec/evals.md +6 -0
- package/spec/mcp.md +18 -0
- package/spec/output-schemas/query-diagnose-v1.schema.json +123 -0
- package/spec/output-schemas/query-diagnose.schema.json +89 -2
- package/src/app/context-runtime-types.ts +3 -0
- package/src/app/context-runtime.ts +1 -0
- package/src/app/context-surface.ts +4 -2
- package/src/cli/commands/ask.ts +31 -20
- package/src/cli/commands/context-build.ts +17 -7
- package/src/cli/commands/query.ts +58 -37
- package/src/cli/commands/search.ts +29 -19
- package/src/cli/commands/vsearch.ts +31 -22
- package/src/cli/options.ts +39 -0
- package/src/cli/program.ts +48 -0
- package/src/config/defaults.ts +10 -1
- package/src/config/types.ts +71 -0
- package/src/core/project-affinity-surface.ts +114 -0
- package/src/core/project-affinity.ts +330 -0
- package/src/core/validation.ts +20 -1
- package/src/mcp/tools/ask.ts +10 -1
- package/src/mcp/tools/context.ts +18 -0
- package/src/mcp/tools/index.ts +13 -2
- package/src/mcp/tools/query.ts +12 -0
- package/src/mcp/tools/search.ts +7 -0
- package/src/mcp/tools/vsearch.ts +7 -0
- package/src/pipeline/diagnose.ts +48 -3
- package/src/pipeline/explain.ts +54 -13
- package/src/pipeline/hybrid.ts +100 -59
- package/src/pipeline/project-affinity.ts +162 -0
- package/src/pipeline/search.ts +76 -10
- package/src/pipeline/types.ts +9 -0
- package/src/pipeline/vsearch.ts +117 -91
- package/src/sdk/client.ts +80 -20
- package/src/sdk/index.ts +2 -0
- package/src/sdk/types.ts +20 -7
- package/src/serve/context-capsule.ts +18 -1
- package/src/serve/routes/api.ts +69 -0
package/src/cli/commands/ask.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* @module src/cli/commands/ask
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import type { CliProjectAffinityRequest } from "../../core/project-affinity-surface";
|
|
8
9
|
import type { RetrievalTraceSurfaceMetadata } from "../../core/retrieval-trace-session";
|
|
9
10
|
import type { RetrievalTraceSession } from "../../core/retrieval-trace-session";
|
|
10
11
|
import type {
|
|
@@ -15,6 +16,7 @@ import type {
|
|
|
15
16
|
import type { AskOptions, AskResult, Citation } from "../../pipeline/types";
|
|
16
17
|
|
|
17
18
|
import { buildVerifiedAsk } from "../../app/verified-ask";
|
|
19
|
+
import { resolveCliProjectAffinity } from "../../core/project-affinity-surface";
|
|
18
20
|
import {
|
|
19
21
|
finishRetrievalTraceAfterError,
|
|
20
22
|
retrievalTraceFilters,
|
|
@@ -46,24 +48,25 @@ export { formatAsk } from "./ask-format";
|
|
|
46
48
|
// Types
|
|
47
49
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
48
50
|
|
|
49
|
-
export type AskCommandOptions = AskOptions &
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
51
|
+
export type AskCommandOptions = Omit<AskOptions, "projectAffinity"> &
|
|
52
|
+
CliProjectAffinityRequest & {
|
|
53
|
+
/** Override config path */
|
|
54
|
+
configPath?: string;
|
|
55
|
+
/** Override embedding model */
|
|
56
|
+
embedModel?: string;
|
|
57
|
+
/** Override expansion model */
|
|
58
|
+
expandModel?: string;
|
|
59
|
+
/** Override answer generation model */
|
|
60
|
+
genModel?: string;
|
|
61
|
+
/** Override rerank model */
|
|
62
|
+
rerankModel?: string;
|
|
63
|
+
/** Output as JSON */
|
|
64
|
+
json?: boolean;
|
|
65
|
+
/** Output as Markdown */
|
|
66
|
+
md?: boolean;
|
|
67
|
+
/** Show all retrieved sources (not just cited) */
|
|
68
|
+
showSources?: boolean;
|
|
69
|
+
};
|
|
67
70
|
|
|
68
71
|
export type AskCommandResult =
|
|
69
72
|
| {
|
|
@@ -108,6 +111,12 @@ export async function ask(
|
|
|
108
111
|
let traceSession: RetrievalTraceSession | undefined;
|
|
109
112
|
|
|
110
113
|
try {
|
|
114
|
+
const { projectAffinityDisabled, projectRoots, ...askOptions } = options;
|
|
115
|
+
const projectAffinity = await resolveCliProjectAffinity(config, {
|
|
116
|
+
cwd: process.cwd(),
|
|
117
|
+
disabled: projectAffinityDisabled,
|
|
118
|
+
projectRoots,
|
|
119
|
+
});
|
|
111
120
|
const verificationRequested = options.verify === true;
|
|
112
121
|
const answerRequested =
|
|
113
122
|
verificationRequested || Boolean(options.answer && !options.noAnswer);
|
|
@@ -141,7 +150,7 @@ export async function ask(
|
|
|
141
150
|
store,
|
|
142
151
|
config,
|
|
143
152
|
query,
|
|
144
|
-
filters: retrievalTraceFilters({ ...
|
|
153
|
+
filters: retrievalTraceFilters({ ...askOptions, limit }),
|
|
145
154
|
pipeline: "ask",
|
|
146
155
|
indexName: globals.index,
|
|
147
156
|
modelUris: [embedUri, expandUri, answerUri, rerankUri].filter(
|
|
@@ -264,7 +273,7 @@ export async function ask(
|
|
|
264
273
|
if (verificationRequested && answerPort) {
|
|
265
274
|
const verified = await buildVerifiedAsk(
|
|
266
275
|
query,
|
|
267
|
-
{ ...
|
|
276
|
+
{ ...askOptions, limit, projectAffinity },
|
|
268
277
|
{
|
|
269
278
|
store,
|
|
270
279
|
config,
|
|
@@ -273,6 +282,7 @@ export async function ask(
|
|
|
273
282
|
embedPort,
|
|
274
283
|
rerankPort,
|
|
275
284
|
genPort: answerPort,
|
|
285
|
+
projectAffinity,
|
|
276
286
|
traceSession,
|
|
277
287
|
}
|
|
278
288
|
);
|
|
@@ -308,6 +318,7 @@ export async function ask(
|
|
|
308
318
|
noExpand: options.noExpand,
|
|
309
319
|
noRerank: options.noRerank,
|
|
310
320
|
candidateLimit: options.candidateLimit,
|
|
321
|
+
projectAffinity,
|
|
311
322
|
traceSession,
|
|
312
323
|
});
|
|
313
324
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/** Context Capsule build command over the shared application runtime. */
|
|
2
2
|
|
|
3
3
|
import type { ContextCapsuleBuildInput } from "../../app/context-runtime";
|
|
4
|
+
import type { CliProjectAffinityRequest } from "../../core/project-affinity-surface";
|
|
4
5
|
import type { RetrievalTraceSession } from "../../core/retrieval-trace-session";
|
|
5
6
|
import type { EmbeddingPort, RerankPort } from "../../llm/types";
|
|
6
7
|
import type { VectorIndexPort } from "../../store/vector";
|
|
@@ -11,6 +12,7 @@ import {
|
|
|
11
12
|
canonicalBuiltContextCapsuleJson,
|
|
12
13
|
validateContextCapsuleBuildInput,
|
|
13
14
|
} from "../../app/context-runtime";
|
|
15
|
+
import { resolveCliProjectAffinity } from "../../core/project-affinity-surface";
|
|
14
16
|
import {
|
|
15
17
|
finishRetrievalTraceAfterError,
|
|
16
18
|
startRetrievalTraceRequest,
|
|
@@ -27,10 +29,8 @@ import {
|
|
|
27
29
|
} from "../progress";
|
|
28
30
|
import { initStore } from "./shared";
|
|
29
31
|
|
|
30
|
-
export interface ContextBuildCommandOptions
|
|
31
|
-
ContextCapsuleBuildInput,
|
|
32
|
-
"goal"
|
|
33
|
-
> {
|
|
32
|
+
export interface ContextBuildCommandOptions
|
|
33
|
+
extends Omit<ContextCapsuleBuildInput, "goal">, CliProjectAffinityRequest {
|
|
34
34
|
configPath?: string;
|
|
35
35
|
format: "json" | "md";
|
|
36
36
|
}
|
|
@@ -64,8 +64,12 @@ export const contextBuild = async (
|
|
|
64
64
|
goal: string,
|
|
65
65
|
options: ContextBuildCommandOptions
|
|
66
66
|
): Promise<string> => {
|
|
67
|
+
const { projectAffinityDisabled, projectRoots, ...contextOptions } = options;
|
|
67
68
|
try {
|
|
68
|
-
validateContextCapsuleBuildInput(
|
|
69
|
+
validateContextCapsuleBuildInput(
|
|
70
|
+
{ goal, ...contextOptions },
|
|
71
|
+
options.indexName
|
|
72
|
+
);
|
|
69
73
|
} catch (error) {
|
|
70
74
|
throw contextCliError(error);
|
|
71
75
|
}
|
|
@@ -84,8 +88,13 @@ export const contextBuild = async (
|
|
|
84
88
|
let vectorIndex: VectorIndexPort | null = null;
|
|
85
89
|
let traceSession: RetrievalTraceSession | undefined;
|
|
86
90
|
try {
|
|
91
|
+
const projectAffinity = await resolveCliProjectAffinity(config, {
|
|
92
|
+
cwd: process.cwd(),
|
|
93
|
+
disabled: projectAffinityDisabled,
|
|
94
|
+
projectRoots,
|
|
95
|
+
});
|
|
87
96
|
validateContextCapsuleBuildInput(
|
|
88
|
-
{ goal, ...
|
|
97
|
+
{ goal, ...contextOptions },
|
|
89
98
|
options.indexName,
|
|
90
99
|
config.collections.map((collection) => collection.name)
|
|
91
100
|
);
|
|
@@ -163,7 +172,7 @@ export const contextBuild = async (
|
|
|
163
172
|
if (showProgress && progress) process.stderr.write("\n");
|
|
164
173
|
}
|
|
165
174
|
const capsule = await buildContextCapsule(
|
|
166
|
-
{ goal, ...
|
|
175
|
+
{ goal, ...contextOptions },
|
|
167
176
|
{
|
|
168
177
|
store,
|
|
169
178
|
config,
|
|
@@ -171,6 +180,7 @@ export const contextBuild = async (
|
|
|
171
180
|
vectorIndex,
|
|
172
181
|
embedPort,
|
|
173
182
|
rerankPort,
|
|
183
|
+
projectAffinity,
|
|
174
184
|
traceSession,
|
|
175
185
|
}
|
|
176
186
|
);
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* @module src/cli/commands/query
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import type { CliProjectAffinityRequest } from "../../core/project-affinity-surface";
|
|
8
9
|
import type { RetrievalTraceSurfaceMetadata } from "../../core/retrieval-trace-session";
|
|
9
10
|
import type { RetrievalTraceSession } from "../../core/retrieval-trace-session";
|
|
10
11
|
import type {
|
|
@@ -18,6 +19,7 @@ import {
|
|
|
18
19
|
fingerprintContentTypeRules,
|
|
19
20
|
normalizeContentTypes,
|
|
20
21
|
} from "../../config";
|
|
22
|
+
import { resolveCliProjectAffinity } from "../../core/project-affinity-surface";
|
|
21
23
|
import {
|
|
22
24
|
finishRetrievalTraceAfterError,
|
|
23
25
|
retrievalTraceFilters,
|
|
@@ -46,30 +48,31 @@ import { decorateSearchResultsForIndex, initStore } from "./shared";
|
|
|
46
48
|
// Types
|
|
47
49
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
48
50
|
|
|
49
|
-
export type QueryCommandOptions = HybridSearchOptions &
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
51
|
+
export type QueryCommandOptions = Omit<HybridSearchOptions, "projectAffinity"> &
|
|
52
|
+
CliProjectAffinityRequest & {
|
|
53
|
+
/** Override config path */
|
|
54
|
+
configPath?: string;
|
|
55
|
+
/** Index name */
|
|
56
|
+
indexName?: string;
|
|
57
|
+
/** Override embedding model */
|
|
58
|
+
embedModel?: string;
|
|
59
|
+
/** Override expansion model */
|
|
60
|
+
expandModel?: string;
|
|
61
|
+
/** Deprecated alias for expansion model */
|
|
62
|
+
genModel?: string;
|
|
63
|
+
/** Override rerank model */
|
|
64
|
+
rerankModel?: string;
|
|
65
|
+
/** Output as JSON */
|
|
66
|
+
json?: boolean;
|
|
67
|
+
/** Output as Markdown */
|
|
68
|
+
md?: boolean;
|
|
69
|
+
/** Output as CSV */
|
|
70
|
+
csv?: boolean;
|
|
71
|
+
/** Output as XML */
|
|
72
|
+
xml?: boolean;
|
|
73
|
+
/** Output files only */
|
|
74
|
+
files?: boolean;
|
|
75
|
+
};
|
|
73
76
|
|
|
74
77
|
export interface QueryFormatOptions {
|
|
75
78
|
format: "terminal" | "json" | "files" | "csv" | "md" | "xml";
|
|
@@ -86,16 +89,20 @@ export type QueryResult =
|
|
|
86
89
|
}
|
|
87
90
|
| { success: false; error: string };
|
|
88
91
|
|
|
89
|
-
export type QueryDiagnoseCommandOptions =
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
92
|
+
export type QueryDiagnoseCommandOptions = Omit<
|
|
93
|
+
HybridSearchOptions,
|
|
94
|
+
"projectAffinity"
|
|
95
|
+
> &
|
|
96
|
+
CliProjectAffinityRequest & {
|
|
97
|
+
target: string;
|
|
98
|
+
configPath?: string;
|
|
99
|
+
indexName?: string;
|
|
100
|
+
embedModel?: string;
|
|
101
|
+
expandModel?: string;
|
|
102
|
+
genModel?: string;
|
|
103
|
+
rerankModel?: string;
|
|
104
|
+
json?: boolean;
|
|
105
|
+
};
|
|
99
106
|
|
|
100
107
|
export interface QueryDiagnoseFormatOptions {
|
|
101
108
|
format: "terminal" | "json";
|
|
@@ -140,6 +147,12 @@ export async function query(
|
|
|
140
147
|
let traceSession: RetrievalTraceSession | undefined;
|
|
141
148
|
|
|
142
149
|
try {
|
|
150
|
+
const { projectAffinityDisabled, projectRoots, ...queryOptions } = options;
|
|
151
|
+
const projectAffinity = await resolveCliProjectAffinity(config, {
|
|
152
|
+
cwd: process.cwd(),
|
|
153
|
+
disabled: projectAffinityDisabled,
|
|
154
|
+
projectRoots,
|
|
155
|
+
});
|
|
143
156
|
const embedUri = resolveModelUri(
|
|
144
157
|
config,
|
|
145
158
|
"embed",
|
|
@@ -167,7 +180,7 @@ export async function query(
|
|
|
167
180
|
store,
|
|
168
181
|
config,
|
|
169
182
|
query: queryText,
|
|
170
|
-
filters: retrievalTraceFilters({ ...
|
|
183
|
+
filters: retrievalTraceFilters({ ...queryOptions, limit }),
|
|
171
184
|
pipeline: "hybrid",
|
|
172
185
|
indexName: options.indexName,
|
|
173
186
|
modelUris: [embedUri, expandUri, rerankUri].filter(
|
|
@@ -261,8 +274,9 @@ export async function query(
|
|
|
261
274
|
rerankPort,
|
|
262
275
|
};
|
|
263
276
|
const result = await searchHybrid(deps, queryText, {
|
|
264
|
-
...
|
|
277
|
+
...queryOptions,
|
|
265
278
|
limit,
|
|
279
|
+
projectAffinity,
|
|
266
280
|
traceSession,
|
|
267
281
|
});
|
|
268
282
|
|
|
@@ -318,6 +332,12 @@ export async function queryDiagnose(
|
|
|
318
332
|
let rerankPort: RerankPort | null = null;
|
|
319
333
|
|
|
320
334
|
try {
|
|
335
|
+
const { projectAffinityDisabled, projectRoots, ...queryOptions } = options;
|
|
336
|
+
const projectAffinity = await resolveCliProjectAffinity(config, {
|
|
337
|
+
cwd: process.cwd(),
|
|
338
|
+
disabled: projectAffinityDisabled,
|
|
339
|
+
projectRoots,
|
|
340
|
+
});
|
|
321
341
|
const globals = getGlobals();
|
|
322
342
|
const policy = resolveDownloadPolicy(process.env, {
|
|
323
343
|
offline: globals.offline,
|
|
@@ -415,7 +435,8 @@ export async function queryDiagnose(
|
|
|
415
435
|
rerankPort,
|
|
416
436
|
};
|
|
417
437
|
const result = await diagnoseQueryTarget(deps, queryText, {
|
|
418
|
-
...
|
|
438
|
+
...queryOptions,
|
|
439
|
+
projectAffinity,
|
|
419
440
|
contentTypeRules,
|
|
420
441
|
contentTypeRulesFingerprint:
|
|
421
442
|
fingerprintContentTypeRules(contentTypeRules),
|
|
@@ -5,12 +5,14 @@
|
|
|
5
5
|
* @module src/cli/commands/search
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import type { CliProjectAffinityRequest } from "../../core/project-affinity-surface";
|
|
8
9
|
import type {
|
|
9
10
|
RetrievalTraceSession,
|
|
10
11
|
RetrievalTraceSurfaceMetadata,
|
|
11
12
|
} from "../../core/retrieval-trace-session";
|
|
12
13
|
import type { SearchOptions, SearchResults } from "../../pipeline/types";
|
|
13
14
|
|
|
15
|
+
import { resolveCliProjectAffinity } from "../../core/project-affinity-surface";
|
|
14
16
|
import {
|
|
15
17
|
finishRetrievalTraceAfterError,
|
|
16
18
|
startRetrievalTraceRequest,
|
|
@@ -26,24 +28,25 @@ import { decorateSearchResultsForIndex, initStore } from "./shared";
|
|
|
26
28
|
// Types
|
|
27
29
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
28
30
|
|
|
29
|
-
export type SearchCommandOptions = SearchOptions &
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
31
|
+
export type SearchCommandOptions = Omit<SearchOptions, "projectAffinity"> &
|
|
32
|
+
CliProjectAffinityRequest & {
|
|
33
|
+
/** Override config path */
|
|
34
|
+
configPath?: string;
|
|
35
|
+
/** Index name */
|
|
36
|
+
indexName?: string;
|
|
37
|
+
/** Output as JSON */
|
|
38
|
+
json?: boolean;
|
|
39
|
+
/** Output as Markdown */
|
|
40
|
+
md?: boolean;
|
|
41
|
+
/** Output as CSV */
|
|
42
|
+
csv?: boolean;
|
|
43
|
+
/** Output as XML */
|
|
44
|
+
xml?: boolean;
|
|
45
|
+
/** Output files only */
|
|
46
|
+
files?: boolean;
|
|
47
|
+
/** Terminal hyperlink policy */
|
|
48
|
+
terminalLinks?: FormatOptions["terminalLinks"];
|
|
49
|
+
};
|
|
47
50
|
|
|
48
51
|
export type SearchResult =
|
|
49
52
|
| {
|
|
@@ -84,6 +87,12 @@ export async function search(
|
|
|
84
87
|
let traceSession: RetrievalTraceSession | undefined;
|
|
85
88
|
|
|
86
89
|
try {
|
|
90
|
+
const { projectAffinityDisabled, projectRoots, ...searchOptions } = options;
|
|
91
|
+
const projectAffinity = await resolveCliProjectAffinity(config, {
|
|
92
|
+
cwd: process.cwd(),
|
|
93
|
+
disabled: projectAffinityDisabled,
|
|
94
|
+
projectRoots,
|
|
95
|
+
});
|
|
87
96
|
const started = await startRetrievalTraceRequest({
|
|
88
97
|
store,
|
|
89
98
|
config,
|
|
@@ -109,8 +118,9 @@ export async function search(
|
|
|
109
118
|
if (!started.ok) return { success: false, error: started.error.message };
|
|
110
119
|
traceSession = started.value ?? undefined;
|
|
111
120
|
const result = await searchBm25(store, query, {
|
|
112
|
-
...
|
|
121
|
+
...searchOptions,
|
|
113
122
|
limit,
|
|
123
|
+
projectAffinity,
|
|
114
124
|
traceSession,
|
|
115
125
|
});
|
|
116
126
|
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* @module src/cli/commands/vsearch
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import type { CliProjectAffinityRequest } from "../../core/project-affinity-surface";
|
|
8
9
|
import type {
|
|
9
10
|
RetrievalTraceSession,
|
|
10
11
|
RetrievalTraceSurfaceMetadata,
|
|
@@ -12,6 +13,7 @@ import type {
|
|
|
12
13
|
import type { EmbeddingPort } from "../../llm/types";
|
|
13
14
|
import type { SearchOptions, SearchResults } from "../../pipeline/types";
|
|
14
15
|
|
|
16
|
+
import { resolveCliProjectAffinity } from "../../core/project-affinity-surface";
|
|
15
17
|
import {
|
|
16
18
|
finishRetrievalTraceAfterError,
|
|
17
19
|
retrievalTraceFilters,
|
|
@@ -35,26 +37,27 @@ import { decorateSearchResultsForIndex, initStore } from "./shared";
|
|
|
35
37
|
// Types
|
|
36
38
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
37
39
|
|
|
38
|
-
export type VsearchCommandOptions = SearchOptions &
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
40
|
+
export type VsearchCommandOptions = Omit<SearchOptions, "projectAffinity"> &
|
|
41
|
+
CliProjectAffinityRequest & {
|
|
42
|
+
/** Override config path */
|
|
43
|
+
configPath?: string;
|
|
44
|
+
/** Index name */
|
|
45
|
+
indexName?: string;
|
|
46
|
+
/** Override model URI */
|
|
47
|
+
model?: string;
|
|
48
|
+
/** Output as JSON */
|
|
49
|
+
json?: boolean;
|
|
50
|
+
/** Output as Markdown */
|
|
51
|
+
md?: boolean;
|
|
52
|
+
/** Output as CSV */
|
|
53
|
+
csv?: boolean;
|
|
54
|
+
/** Output as XML */
|
|
55
|
+
xml?: boolean;
|
|
56
|
+
/** Output files only */
|
|
57
|
+
files?: boolean;
|
|
58
|
+
/** Terminal hyperlink policy */
|
|
59
|
+
terminalLinks?: FormatOptions["terminalLinks"];
|
|
60
|
+
};
|
|
58
61
|
|
|
59
62
|
export type VsearchResult =
|
|
60
63
|
| {
|
|
@@ -96,6 +99,12 @@ export async function vsearch(
|
|
|
96
99
|
let traceSession: RetrievalTraceSession | undefined;
|
|
97
100
|
|
|
98
101
|
try {
|
|
102
|
+
const { projectAffinityDisabled, projectRoots, ...searchOptions } = options;
|
|
103
|
+
const projectAffinity = await resolveCliProjectAffinity(config, {
|
|
104
|
+
cwd: process.cwd(),
|
|
105
|
+
disabled: projectAffinityDisabled,
|
|
106
|
+
projectRoots,
|
|
107
|
+
});
|
|
99
108
|
// Get model URI from preset
|
|
100
109
|
const modelUri = resolveModelUri(
|
|
101
110
|
config,
|
|
@@ -107,7 +116,7 @@ export async function vsearch(
|
|
|
107
116
|
store,
|
|
108
117
|
config,
|
|
109
118
|
query,
|
|
110
|
-
filters: retrievalTraceFilters({ ...
|
|
119
|
+
filters: retrievalTraceFilters({ ...searchOptions, limit }),
|
|
111
120
|
pipeline: "vector",
|
|
112
121
|
indexName: options.indexName,
|
|
113
122
|
modelUris: [modelUri],
|
|
@@ -152,7 +161,7 @@ export async function vsearch(
|
|
|
152
161
|
deps,
|
|
153
162
|
query,
|
|
154
163
|
queryEmbedding,
|
|
155
|
-
{ ...
|
|
164
|
+
{ ...searchOptions, limit, projectAffinity, traceSession }
|
|
156
165
|
);
|
|
157
166
|
if (!result.ok) {
|
|
158
167
|
await traceSession?.finish("failed");
|
package/src/cli/options.ts
CHANGED
|
@@ -5,6 +5,10 @@
|
|
|
5
5
|
* @module src/cli/options
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import {
|
|
9
|
+
normalizeProjectAffinityValues,
|
|
10
|
+
ProjectAffinityInputError,
|
|
11
|
+
} from "../core/project-affinity-surface";
|
|
8
12
|
import { CliError } from "./errors";
|
|
9
13
|
|
|
10
14
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -13,6 +17,41 @@ import { CliError } from "./errors";
|
|
|
13
17
|
|
|
14
18
|
export type OutputFormat = "terminal" | "json" | "files" | "csv" | "md" | "xml";
|
|
15
19
|
|
|
20
|
+
export interface CliProjectAffinityOptions {
|
|
21
|
+
projectAffinityDisabled: boolean;
|
|
22
|
+
projectRoots: string[];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const collectRepeatableValue = (
|
|
26
|
+
value: string,
|
|
27
|
+
previous: string[] = []
|
|
28
|
+
): string[] => [...previous, value];
|
|
29
|
+
|
|
30
|
+
export const parseCliProjectAffinityOptions = (
|
|
31
|
+
options: Record<string, unknown>
|
|
32
|
+
): CliProjectAffinityOptions => {
|
|
33
|
+
try {
|
|
34
|
+
const projectRoots = normalizeProjectAffinityValues(
|
|
35
|
+
Array.isArray(options.projectRoot)
|
|
36
|
+
? (options.projectRoot as string[])
|
|
37
|
+
: undefined,
|
|
38
|
+
"project roots"
|
|
39
|
+
);
|
|
40
|
+
const projectAffinityDisabled = options.projectAffinity === false;
|
|
41
|
+
if (projectAffinityDisabled && projectRoots.length > 0) {
|
|
42
|
+
throw new ProjectAffinityInputError(
|
|
43
|
+
"--no-project-affinity cannot be combined with --project-root"
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
return { projectAffinityDisabled, projectRoots };
|
|
47
|
+
} catch (error) {
|
|
48
|
+
throw new CliError(
|
|
49
|
+
"VALIDATION",
|
|
50
|
+
error instanceof Error ? error.message : "Invalid project affinity input"
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
16
55
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
17
56
|
// Format Support Matrix (per spec/cli.md)
|
|
18
57
|
// ─────────────────────────────────────────────────────────────────────────────
|