@gmickel/gno 1.21.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 +26 -2
- package/assets/skill/SKILL.md +15 -0
- package/package.json +2 -1
- package/spec/cli.md +80 -20
- package/spec/evals-agentic.md +83 -0
- package/spec/evals.md +6 -0
- package/spec/mcp.md +18 -0
- package/spec/output-schemas/publish-artifact.schema.json +284 -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/publish/artifact-validation.ts +259 -0
- package/src/publish/artifact.ts +234 -118
- package/src/publish/export-service.ts +5 -9
- package/src/publish/metadata.ts +195 -0
- 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
|
@@ -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
|
// ─────────────────────────────────────────────────────────────────────────────
|
package/src/cli/program.ts
CHANGED
|
@@ -32,7 +32,9 @@ import { CliError } from "./errors";
|
|
|
32
32
|
import {
|
|
33
33
|
assertFormatSupported,
|
|
34
34
|
CMD,
|
|
35
|
+
collectRepeatableValue,
|
|
35
36
|
getDefaultLimit,
|
|
37
|
+
parseCliProjectAffinityOptions,
|
|
36
38
|
parseOptionalFloat,
|
|
37
39
|
parsePositiveInt,
|
|
38
40
|
} from "./options";
|
|
@@ -594,6 +596,13 @@ function wireSearchCommands(program: Command): void {
|
|
|
594
596
|
)
|
|
595
597
|
.option("--tags-all <tags>", "require ALL tags (comma-separated)")
|
|
596
598
|
.option("--tags-any <tags>", "require ANY tag (comma-separated)")
|
|
599
|
+
.option(
|
|
600
|
+
"--project-root <path>",
|
|
601
|
+
"trusted project root (repeatable; replaces cwd affinity)",
|
|
602
|
+
collectRepeatableValue,
|
|
603
|
+
[]
|
|
604
|
+
)
|
|
605
|
+
.option("--no-project-affinity", "disable project-aware ranking")
|
|
597
606
|
.option("--full", "include full content")
|
|
598
607
|
.option("--line-numbers", "include line numbers in output")
|
|
599
608
|
.option("--json", "JSON output")
|
|
@@ -641,6 +650,7 @@ function wireSearchCommands(program: Command): void {
|
|
|
641
650
|
: getDefaultLimit(format);
|
|
642
651
|
const categories = parseCsvValues(cmdOpts.category);
|
|
643
652
|
const exclude = parseCsvValues(cmdOpts.exclude);
|
|
653
|
+
const projectAffinity = parseCliProjectAffinityOptions(cmdOpts);
|
|
644
654
|
|
|
645
655
|
const { search, formatSearch } = await import("./commands/search");
|
|
646
656
|
const result = await search(queryText, {
|
|
@@ -658,6 +668,7 @@ function wireSearchCommands(program: Command): void {
|
|
|
658
668
|
exclude,
|
|
659
669
|
tagsAll,
|
|
660
670
|
tagsAny,
|
|
671
|
+
...projectAffinity,
|
|
661
672
|
full: Boolean(cmdOpts.full),
|
|
662
673
|
lineNumbers: Boolean(cmdOpts.lineNumbers),
|
|
663
674
|
json: format === "json",
|
|
@@ -714,6 +725,13 @@ function wireSearchCommands(program: Command): void {
|
|
|
714
725
|
)
|
|
715
726
|
.option("--tags-all <tags>", "require ALL tags (comma-separated)")
|
|
716
727
|
.option("--tags-any <tags>", "require ANY tag (comma-separated)")
|
|
728
|
+
.option(
|
|
729
|
+
"--project-root <path>",
|
|
730
|
+
"trusted project root (repeatable; replaces cwd affinity)",
|
|
731
|
+
collectRepeatableValue,
|
|
732
|
+
[]
|
|
733
|
+
)
|
|
734
|
+
.option("--no-project-affinity", "disable project-aware ranking")
|
|
717
735
|
.option("--full", "include full content")
|
|
718
736
|
.option("--line-numbers", "include line numbers in output")
|
|
719
737
|
.option("--json", "JSON output")
|
|
@@ -759,6 +777,7 @@ function wireSearchCommands(program: Command): void {
|
|
|
759
777
|
: getDefaultLimit(format);
|
|
760
778
|
const categories = parseCsvValues(cmdOpts.category);
|
|
761
779
|
const exclude = parseCsvValues(cmdOpts.exclude);
|
|
780
|
+
const projectAffinity = parseCliProjectAffinityOptions(cmdOpts);
|
|
762
781
|
|
|
763
782
|
const { vsearch, formatVsearch } = await import("./commands/vsearch");
|
|
764
783
|
const result = await vsearch(queryText, {
|
|
@@ -776,6 +795,7 @@ function wireSearchCommands(program: Command): void {
|
|
|
776
795
|
exclude,
|
|
777
796
|
tagsAll,
|
|
778
797
|
tagsAny,
|
|
798
|
+
...projectAffinity,
|
|
779
799
|
full: Boolean(cmdOpts.full),
|
|
780
800
|
lineNumbers: Boolean(cmdOpts.lineNumbers),
|
|
781
801
|
json: format === "json",
|
|
@@ -827,6 +847,13 @@ function wireSearchCommands(program: Command): void {
|
|
|
827
847
|
)
|
|
828
848
|
.option("--tags-all <tags>", "require ALL tags (comma-separated)")
|
|
829
849
|
.option("--tags-any <tags>", "require ANY tag (comma-separated)")
|
|
850
|
+
.option(
|
|
851
|
+
"--project-root <path>",
|
|
852
|
+
"trusted project root (repeatable; replaces cwd affinity)",
|
|
853
|
+
collectRepeatableValue,
|
|
854
|
+
[]
|
|
855
|
+
)
|
|
856
|
+
.option("--no-project-affinity", "disable project-aware ranking")
|
|
830
857
|
.option("--full", "include full content")
|
|
831
858
|
.option("--line-numbers", "include line numbers in output")
|
|
832
859
|
.option("--fast", "skip expansion and reranking (fastest, ~0.7s)")
|
|
@@ -931,6 +958,7 @@ function wireSearchCommands(program: Command): void {
|
|
|
931
958
|
: undefined;
|
|
932
959
|
const categories = parseCsvValues(cmdOpts.category);
|
|
933
960
|
const exclude = parseCsvValues(cmdOpts.exclude);
|
|
961
|
+
const projectAffinity = parseCliProjectAffinityOptions(cmdOpts);
|
|
934
962
|
|
|
935
963
|
const depthPolicy = resolveDepthPolicy({
|
|
936
964
|
presetId: activePresetId,
|
|
@@ -960,6 +988,7 @@ function wireSearchCommands(program: Command): void {
|
|
|
960
988
|
exclude,
|
|
961
989
|
tagsAll,
|
|
962
990
|
tagsAny,
|
|
991
|
+
...projectAffinity,
|
|
963
992
|
noExpand: depthPolicy.noExpand,
|
|
964
993
|
noRerank: depthPolicy.noRerank,
|
|
965
994
|
graph: Boolean(cmdOpts.graph),
|
|
@@ -995,6 +1024,7 @@ function wireSearchCommands(program: Command): void {
|
|
|
995
1024
|
exclude,
|
|
996
1025
|
tagsAll,
|
|
997
1026
|
tagsAny,
|
|
1027
|
+
...projectAffinity,
|
|
998
1028
|
full: Boolean(cmdOpts.full),
|
|
999
1029
|
lineNumbers: Boolean(cmdOpts.lineNumbers),
|
|
1000
1030
|
noExpand: depthPolicy.noExpand,
|
|
@@ -1121,6 +1151,13 @@ function wireSearchCommands(program: Command): void {
|
|
|
1121
1151
|
.option("--context-budget-bytes <num>", "verified Context byte budget")
|
|
1122
1152
|
.option("--min-score <score>", "minimum retrieval score (0-1)")
|
|
1123
1153
|
.option("--graph", "include bounded graph expansion")
|
|
1154
|
+
.option(
|
|
1155
|
+
"--project-root <path>",
|
|
1156
|
+
"trusted project root (repeatable; replaces cwd affinity)",
|
|
1157
|
+
collectRepeatableValue,
|
|
1158
|
+
[]
|
|
1159
|
+
)
|
|
1160
|
+
.option("--no-project-affinity", "disable project-aware ranking")
|
|
1124
1161
|
.option("--show-sources", "show all retrieved sources (not just cited)")
|
|
1125
1162
|
.option("--json", "JSON output")
|
|
1126
1163
|
.option("--md", "Markdown output")
|
|
@@ -1169,6 +1206,7 @@ function wireSearchCommands(program: Command): void {
|
|
|
1169
1206
|
}
|
|
1170
1207
|
const categories = parseCsvValues(cmdOpts.category);
|
|
1171
1208
|
const exclude = parseCsvValues(cmdOpts.exclude);
|
|
1209
|
+
const projectAffinity = parseCliProjectAffinityOptions(cmdOpts);
|
|
1172
1210
|
|
|
1173
1211
|
let queryModes: import("../pipeline/types").QueryModeInput[] | undefined;
|
|
1174
1212
|
if (Array.isArray(cmdOpts.queryMode) && cmdOpts.queryMode.length > 0) {
|
|
@@ -1229,6 +1267,7 @@ function wireSearchCommands(program: Command): void {
|
|
|
1229
1267
|
maxAnswerTokens,
|
|
1230
1268
|
contextBudgetTokens,
|
|
1231
1269
|
contextBudgetBytes,
|
|
1270
|
+
...projectAffinity,
|
|
1232
1271
|
showSources,
|
|
1233
1272
|
json: format === "json",
|
|
1234
1273
|
md: format === "md",
|
|
@@ -1974,6 +2013,13 @@ function wireManagementCommands(program: Command): void {
|
|
|
1974
2013
|
.option("--since <date>", "modified-at lower bound")
|
|
1975
2014
|
.option("--until <date>", "modified-at upper bound")
|
|
1976
2015
|
.option("--graph", "enable graph neighbor expansion")
|
|
2016
|
+
.option(
|
|
2017
|
+
"--project-root <path>",
|
|
2018
|
+
"trusted project root (repeatable; replaces cwd affinity)",
|
|
2019
|
+
collectRepeatableValue,
|
|
2020
|
+
[]
|
|
2021
|
+
)
|
|
2022
|
+
.option("--no-project-affinity", "disable project-aware ranking")
|
|
1977
2023
|
.option("--fast", "use lexical-first fast retrieval")
|
|
1978
2024
|
.option("--thorough", "use a wider retrieval pool")
|
|
1979
2025
|
.option("-n, --limit <num>", "maximum retrieved results")
|
|
@@ -1991,6 +2037,7 @@ function wireManagementCommands(program: Command): void {
|
|
|
1991
2037
|
throw new CliError("VALIDATION", "Choose either --fast or --thorough");
|
|
1992
2038
|
}
|
|
1993
2039
|
const globals = getGlobals();
|
|
2040
|
+
const projectAffinity = parseCliProjectAffinityOptions(cmdOpts);
|
|
1994
2041
|
const { contextBuild } = await import("./commands/context-build");
|
|
1995
2042
|
let queryModes: import("../pipeline/types").QueryModeInput[] | undefined;
|
|
1996
2043
|
if (Array.isArray(cmdOpts.queryMode) && cmdOpts.queryMode.length > 0) {
|
|
@@ -2022,6 +2069,7 @@ function wireManagementCommands(program: Command): void {
|
|
|
2022
2069
|
true
|
|
2023
2070
|
),
|
|
2024
2071
|
query: cmdOpts.query as string | undefined,
|
|
2072
|
+
...projectAffinity,
|
|
2025
2073
|
queryModes,
|
|
2026
2074
|
collections: cmdOpts.collection as string[],
|
|
2027
2075
|
uriPrefix: cmdOpts.uriPrefix as string | undefined,
|
package/src/config/defaults.ts
CHANGED
|
@@ -4,7 +4,12 @@
|
|
|
4
4
|
* @module src/config/defaults
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
CONFIG_VERSION,
|
|
9
|
+
type Config,
|
|
10
|
+
DEFAULT_FTS_TOKENIZER,
|
|
11
|
+
PROJECT_AFFINITY_MAX_CONTRIBUTION,
|
|
12
|
+
} from "./types";
|
|
8
13
|
|
|
9
14
|
/**
|
|
10
15
|
* Create a default config object.
|
|
@@ -17,5 +22,9 @@ export function createDefaultConfig(): Config {
|
|
|
17
22
|
collections: [],
|
|
18
23
|
contexts: [],
|
|
19
24
|
contentTypes: [],
|
|
25
|
+
projectAffinity: {
|
|
26
|
+
enabled: true,
|
|
27
|
+
contribution: PROJECT_AFFINITY_MAX_CONTRIBUTION,
|
|
28
|
+
},
|
|
20
29
|
};
|
|
21
30
|
}
|