@gmickel/gno 1.18.0 → 1.20.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 +14 -7
- package/assets/skill/SKILL.md +54 -12
- package/assets/skill/mcp-reference.md +7 -2
- package/assets/skill/recipes/citation-and-provenance.md +32 -9
- package/package.json +2 -1
- package/spec/AGENTS.md +83 -0
- package/spec/CLAUDE.md +83 -0
- package/spec/bench-fixture.schema.json +137 -0
- package/spec/cli.md +2919 -0
- package/spec/db/schema.sql +442 -0
- package/spec/evals-agentic.md +592 -0
- package/spec/evals.md +1106 -0
- package/spec/mcp.md +2279 -0
- package/spec/output-schemas/activation-verification.schema.json +515 -0
- package/spec/output-schemas/ask.schema.json +564 -0
- package/spec/output-schemas/backlinks.schema.json +131 -0
- package/spec/output-schemas/bench-result.schema.json +120 -0
- package/spec/output-schemas/capture-receipt.schema.json +143 -0
- package/spec/output-schemas/claim-verification.schema.json +291 -0
- package/spec/output-schemas/collection-list.schema.json +45 -0
- package/spec/output-schemas/context-capsule-v1.schema.json +726 -0
- package/spec/output-schemas/context-capsule-verification.schema.json +1338 -0
- package/spec/output-schemas/context-list.schema.json +21 -0
- package/spec/output-schemas/doctor.schema.json +313 -0
- package/spec/output-schemas/error.schema.json +30 -0
- package/spec/output-schemas/expansion.schema.json +37 -0
- package/spec/output-schemas/get.schema.json +140 -0
- package/spec/output-schemas/graph-query.schema.json +99 -0
- package/spec/output-schemas/graph.schema.json +371 -0
- package/spec/output-schemas/links-list.schema.json +186 -0
- package/spec/output-schemas/mcp-add-collection-result.schema.json +23 -0
- package/spec/output-schemas/mcp-capture-result.schema.json +152 -0
- package/spec/output-schemas/mcp-http-error.schema.json +30 -0
- package/spec/output-schemas/mcp-job-list.schema.json +58 -0
- package/spec/output-schemas/mcp-job-status.schema.json +224 -0
- package/spec/output-schemas/mcp-remove-result.schema.json +39 -0
- package/spec/output-schemas/mcp-sync-result.schema.json +41 -0
- package/spec/output-schemas/mcp-tag-result.schema.json +33 -0
- package/spec/output-schemas/models-list.schema.json +93 -0
- package/spec/output-schemas/multi-get.schema.json +103 -0
- package/spec/output-schemas/process-status.schema.json +119 -0
- package/spec/output-schemas/query-diagnose.schema.json +123 -0
- package/spec/output-schemas/resident-status.schema.json +154 -0
- package/spec/output-schemas/retrieval-trace-common.schema.json +492 -0
- package/spec/output-schemas/retrieval-trace-delete.schema.json +16 -0
- package/spec/output-schemas/retrieval-trace-export.schema.json +61 -0
- package/spec/output-schemas/retrieval-trace-filters.schema.json +139 -0
- package/spec/output-schemas/retrieval-trace-judgment.schema.json +15 -0
- package/spec/output-schemas/retrieval-trace-list.schema.json +18 -0
- package/spec/output-schemas/retrieval-trace-payloads.schema.json +178 -0
- package/spec/output-schemas/retrieval-trace-purge.schema.json +31 -0
- package/spec/output-schemas/retrieval-trace-qrels.schema.json +303 -0
- package/spec/output-schemas/retrieval-trace-replay.schema.json +286 -0
- package/spec/output-schemas/retrieval-trace-show.schema.json +69 -0
- package/spec/output-schemas/retrieval-trace-summary.schema.json +65 -0
- package/spec/output-schemas/search-result.schema.json +154 -0
- package/spec/output-schemas/search-results.schema.json +338 -0
- package/spec/output-schemas/similar.schema.json +84 -0
- package/spec/output-schemas/status.schema.json +676 -0
- package/spec/output-schemas/tags-list.schema.json +48 -0
- package/src/app/context-runtime-contract.ts +10 -5
- package/src/app/context-runtime-input.ts +29 -1
- package/src/app/context-runtime-types.ts +7 -0
- package/src/app/context-runtime.ts +20 -2
- package/src/app/context-surface.ts +4 -0
- package/src/app/verified-ask.ts +291 -0
- package/src/cli/commands/ask-format.ts +255 -0
- package/src/cli/commands/ask.ts +144 -183
- package/src/cli/commands/context-build.ts +56 -9
- package/src/cli/commands/get.ts +64 -3
- package/src/cli/commands/query.ts +62 -23
- package/src/cli/commands/replay.ts +140 -0
- package/src/cli/commands/search.ts +48 -3
- package/src/cli/commands/shared.ts +3 -1
- package/src/cli/commands/trace.ts +200 -0
- package/src/cli/commands/vsearch.ts +75 -53
- package/src/cli/program.ts +287 -1
- package/src/config/index.ts +9 -0
- package/src/config/retrieval-traces.ts +56 -0
- package/src/config/types.ts +4 -0
- package/src/core/context-budget.ts +6 -0
- package/src/core/context-capsule-retrieval-schema.ts +4 -0
- package/src/core/context-capsule-schema.ts +17 -0
- package/src/core/context-capsule-validation.ts +3 -2
- package/src/core/context-capsule.ts +18 -0
- package/src/core/context-compiler.ts +44 -25
- package/src/core/context-evidence.ts +6 -0
- package/src/core/retrieval-qrels.ts +405 -0
- package/src/core/retrieval-replay-candidate.ts +368 -0
- package/src/core/retrieval-replay-types.ts +109 -0
- package/src/core/retrieval-replay-validation.ts +89 -0
- package/src/core/retrieval-replay.ts +441 -0
- package/src/core/retrieval-trace-evidence-origin.ts +178 -0
- package/src/core/retrieval-trace-export.ts +113 -0
- package/src/core/retrieval-trace-filter-normalization.ts +27 -0
- package/src/core/retrieval-trace-filters.ts +19 -0
- package/src/core/retrieval-trace-management-helpers.ts +247 -0
- package/src/core/retrieval-trace-management-types.ts +132 -0
- package/src/core/retrieval-trace-management.ts +422 -0
- package/src/core/retrieval-trace-request.ts +141 -0
- package/src/core/retrieval-trace-session.ts +507 -0
- package/src/core/retrieval-trace.ts +472 -0
- package/src/llm/errors.ts +10 -1
- package/src/llm/httpGeneration.ts +11 -1
- package/src/llm/nodeLlamaCpp/generation.ts +54 -10
- package/src/llm/types.ts +6 -0
- package/src/mcp/tools/ask.ts +228 -0
- package/src/mcp/tools/context.ts +87 -15
- package/src/mcp/tools/get.ts +35 -1
- package/src/mcp/tools/index.ts +83 -0
- package/src/mcp/tools/query.ts +95 -64
- package/src/mcp/tools/search.ts +36 -13
- package/src/mcp/tools/trace.ts +143 -0
- package/src/mcp/tools/vsearch.ts +71 -38
- package/src/pipeline/answer.ts +167 -26
- package/src/pipeline/claim-verification-schema.ts +235 -0
- package/src/pipeline/claim-verification.ts +487 -0
- package/src/pipeline/claim-verifier.ts +474 -0
- package/src/pipeline/graph-retrieval.ts +15 -1
- package/src/pipeline/hybrid.ts +151 -43
- package/src/pipeline/search.ts +36 -3
- package/src/pipeline/trace-metadata.ts +47 -0
- package/src/pipeline/types.ts +68 -0
- package/src/pipeline/vsearch.ts +101 -38
- package/src/sdk/client.ts +415 -73
- package/src/sdk/documents.ts +48 -1
- package/src/sdk/index.ts +17 -0
- package/src/sdk/types.ts +28 -0
- package/src/serve/context-capsule.ts +67 -8
- package/src/serve/public/app.tsx +12 -1
- package/src/serve/public/components/AskVerificationPanel.tsx +189 -0
- package/src/serve/public/globals.built.css +1 -1
- package/src/serve/public/lib/workspace-tabs.ts +2 -0
- package/src/serve/public/pages/Ask.tsx +42 -4
- package/src/serve/public/pages/Dashboard.tsx +10 -0
- package/src/serve/public/pages/TraceHistory.tsx +478 -0
- package/src/serve/public/pages/trace-history-detail.tsx +224 -0
- package/src/serve/retrieval-trace.ts +28 -0
- package/src/serve/routes/api.ts +508 -68
- package/src/serve/routes/traces.ts +156 -0
- package/src/serve/server.ts +87 -2
- package/src/store/index.ts +31 -0
- package/src/store/migrations/014-retrieval-traces.ts +303 -0
- package/src/store/migrations/index.ts +2 -0
- package/src/store/retrieval-trace-codec.ts +384 -0
- package/src/store/sqlite/adapter.ts +153 -1
- package/src/store/sqlite/retrieval-trace-management-store.ts +341 -0
- package/src/store/sqlite/retrieval-trace-retention.ts +349 -0
- package/src/store/sqlite/retrieval-trace-rows.ts +267 -0
- package/src/store/sqlite/retrieval-trace-store.ts +515 -0
- package/src/store/types.ts +297 -0
- package/src/store/vector/sqlite-vec.ts +76 -1
- package/src/store/vector/types.ts +1 -1
package/src/mcp/tools/query.ts
CHANGED
|
@@ -26,6 +26,15 @@ import {
|
|
|
26
26
|
normalizeContentTypes,
|
|
27
27
|
} from "../../config";
|
|
28
28
|
import { resolveDepthPolicy } from "../../core/depth-policy";
|
|
29
|
+
import {
|
|
30
|
+
finishRetrievalTraceAfterError,
|
|
31
|
+
retrievalTraceFilters,
|
|
32
|
+
startRetrievalTraceRequest,
|
|
33
|
+
} from "../../core/retrieval-trace-request";
|
|
34
|
+
import {
|
|
35
|
+
attachRetrievalTraceMetadata,
|
|
36
|
+
type RetrievalTraceSession,
|
|
37
|
+
} from "../../core/retrieval-trace-session";
|
|
29
38
|
import { normalizeStructuredQueryInput } from "../../core/structured-query";
|
|
30
39
|
import { LlmAdapter } from "../../llm/nodeLlamaCpp/adapter";
|
|
31
40
|
import { resolveDownloadPolicy } from "../../llm/policy";
|
|
@@ -195,26 +204,79 @@ export function handleQuery(
|
|
|
195
204
|
: undefined;
|
|
196
205
|
|
|
197
206
|
const preset = getActivePreset(ctx.config);
|
|
198
|
-
const llm = new LlmAdapter(ctx.config);
|
|
199
|
-
|
|
200
|
-
// Resolve download policy from env (MCP has no CLI flags)
|
|
201
|
-
const policy = resolveDownloadPolicy(process.env, {});
|
|
202
|
-
|
|
203
|
-
// Non-TTY progress for MCP (periodic lines to stderr, not \r)
|
|
204
|
-
const downloadProgress = createNonTtyProgressRenderer();
|
|
205
207
|
|
|
206
208
|
let embedPort: EmbeddingPort | null = null;
|
|
207
209
|
let expandPort: GenerationPort | null = null;
|
|
208
210
|
let rerankPort: RerankPort | null = null;
|
|
209
211
|
let vectorIndex: VectorIndexPort | null = null;
|
|
212
|
+
let traceSession: RetrievalTraceSession | undefined;
|
|
210
213
|
const embedUri = resolveModelUri(
|
|
211
214
|
ctx.config,
|
|
212
215
|
"embed",
|
|
213
216
|
undefined,
|
|
214
217
|
args.collection
|
|
215
218
|
);
|
|
219
|
+
const hasStructuredModes = Boolean(queryModes?.length);
|
|
220
|
+
const depthPolicy = resolveDepthPolicy({
|
|
221
|
+
presetId: preset.id,
|
|
222
|
+
fast: args.fast,
|
|
223
|
+
thorough: args.thorough,
|
|
224
|
+
expand: args.expand,
|
|
225
|
+
rerank: args.rerank,
|
|
226
|
+
candidateLimit: args.candidateLimit,
|
|
227
|
+
hasStructuredModes,
|
|
228
|
+
});
|
|
229
|
+
const { noExpand, noRerank } = depthPolicy;
|
|
230
|
+
const expandUri =
|
|
231
|
+
!noExpand && !hasStructuredModes
|
|
232
|
+
? resolveModelUri(ctx.config, "expand", undefined, args.collection)
|
|
233
|
+
: undefined;
|
|
234
|
+
const rerankUri = !noRerank
|
|
235
|
+
? resolveModelUri(ctx.config, "rerank", undefined, args.collection)
|
|
236
|
+
: undefined;
|
|
237
|
+
const options = {
|
|
238
|
+
limit: args.limit ?? 5,
|
|
239
|
+
minScore: args.minScore,
|
|
240
|
+
collection: args.collection,
|
|
241
|
+
queryLanguageHint: args.lang,
|
|
242
|
+
intent: args.intent,
|
|
243
|
+
candidateLimit: depthPolicy.candidateLimit,
|
|
244
|
+
exclude: args.exclude,
|
|
245
|
+
since: args.since,
|
|
246
|
+
until: args.until,
|
|
247
|
+
categories: args.categories,
|
|
248
|
+
author: args.author,
|
|
249
|
+
noExpand,
|
|
250
|
+
noRerank,
|
|
251
|
+
graph: args.graph === true,
|
|
252
|
+
noGraph: args.noGraph || args.fast,
|
|
253
|
+
queryModes,
|
|
254
|
+
tagsAll: normalizeTagFilters(args.tagsAll),
|
|
255
|
+
tagsAny: normalizeTagFilters(args.tagsAny),
|
|
256
|
+
};
|
|
216
257
|
|
|
217
258
|
try {
|
|
259
|
+
const traceStart = await startRetrievalTraceRequest({
|
|
260
|
+
store: ctx.store,
|
|
261
|
+
config: ctx.config,
|
|
262
|
+
query: queryText,
|
|
263
|
+
filters: retrievalTraceFilters(options),
|
|
264
|
+
pipeline: "hybrid",
|
|
265
|
+
indexName: ctx.indexName,
|
|
266
|
+
modelUris: [embedUri, expandUri, rerankUri].filter(
|
|
267
|
+
(value): value is string => Boolean(value)
|
|
268
|
+
),
|
|
269
|
+
});
|
|
270
|
+
if (!traceStart.ok) throw new Error(traceStart.error.message);
|
|
271
|
+
traceSession = traceStart.value ?? undefined;
|
|
272
|
+
const llm = new LlmAdapter(ctx.config);
|
|
273
|
+
|
|
274
|
+
// Resolve download policy from env (MCP has no CLI flags)
|
|
275
|
+
const policy = resolveDownloadPolicy(process.env, {});
|
|
276
|
+
|
|
277
|
+
// Non-TTY progress for MCP (periodic lines to stderr, not \r)
|
|
278
|
+
const downloadProgress = createNonTtyProgressRenderer();
|
|
279
|
+
|
|
218
280
|
// Create embedding port (for vector search) - optional
|
|
219
281
|
const embedResult = await llm.createEmbeddingPort(embedUri, {
|
|
220
282
|
policy,
|
|
@@ -224,41 +286,23 @@ export function handleQuery(
|
|
|
224
286
|
embedPort = embedResult.value;
|
|
225
287
|
}
|
|
226
288
|
|
|
227
|
-
const hasStructuredModes = Boolean(queryModes?.length);
|
|
228
|
-
const depthPolicy = resolveDepthPolicy({
|
|
229
|
-
presetId: preset.id,
|
|
230
|
-
fast: args.fast,
|
|
231
|
-
thorough: args.thorough,
|
|
232
|
-
expand: args.expand,
|
|
233
|
-
rerank: args.rerank,
|
|
234
|
-
candidateLimit: args.candidateLimit,
|
|
235
|
-
hasStructuredModes,
|
|
236
|
-
});
|
|
237
|
-
const { noExpand, noRerank } = depthPolicy;
|
|
238
|
-
|
|
239
289
|
// Create expansion port - optional
|
|
240
|
-
if (
|
|
241
|
-
const genResult = await llm.createExpansionPort(
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
onProgress: (progress) => downloadProgress("expand", progress),
|
|
246
|
-
}
|
|
247
|
-
);
|
|
290
|
+
if (expandUri) {
|
|
291
|
+
const genResult = await llm.createExpansionPort(expandUri, {
|
|
292
|
+
policy,
|
|
293
|
+
onProgress: (progress) => downloadProgress("expand", progress),
|
|
294
|
+
});
|
|
248
295
|
if (genResult.ok) {
|
|
249
296
|
expandPort = genResult.value;
|
|
250
297
|
}
|
|
251
298
|
}
|
|
252
299
|
|
|
253
300
|
// Create rerank port - optional
|
|
254
|
-
if (
|
|
255
|
-
const rerankResult = await llm.createRerankPort(
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
onProgress: (progress) => downloadProgress("rerank", progress),
|
|
260
|
-
}
|
|
261
|
-
);
|
|
301
|
+
if (rerankUri) {
|
|
302
|
+
const rerankResult = await llm.createRerankPort(rerankUri, {
|
|
303
|
+
policy,
|
|
304
|
+
onProgress: (progress) => downloadProgress("rerank", progress),
|
|
305
|
+
});
|
|
262
306
|
if (rerankResult.ok) {
|
|
263
307
|
rerankPort = rerankResult.value;
|
|
264
308
|
}
|
|
@@ -289,28 +333,9 @@ export function handleQuery(
|
|
|
289
333
|
rerankPort,
|
|
290
334
|
};
|
|
291
335
|
|
|
292
|
-
// Note: per spec, lang is a "hint" for query, not a filter
|
|
293
|
-
// Pass as queryLanguageHint to affect expansion prompt selection
|
|
294
|
-
// but NOT retrieval filtering (that would be options.lang)
|
|
295
336
|
const result = await searchHybrid(deps, queryText, {
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
collection: args.collection,
|
|
299
|
-
queryLanguageHint: args.lang, // Affects expansion prompt, not retrieval
|
|
300
|
-
intent: args.intent,
|
|
301
|
-
candidateLimit: depthPolicy.candidateLimit,
|
|
302
|
-
exclude: args.exclude,
|
|
303
|
-
since: args.since,
|
|
304
|
-
until: args.until,
|
|
305
|
-
categories: args.categories,
|
|
306
|
-
author: args.author,
|
|
307
|
-
noExpand,
|
|
308
|
-
noRerank,
|
|
309
|
-
graph: args.graph === true,
|
|
310
|
-
noGraph: args.noGraph || args.fast,
|
|
311
|
-
queryModes,
|
|
312
|
-
tagsAll: normalizeTagFilters(args.tagsAll),
|
|
313
|
-
tagsAny: normalizeTagFilters(args.tagsAny),
|
|
337
|
+
...options,
|
|
338
|
+
traceSession,
|
|
314
339
|
});
|
|
315
340
|
|
|
316
341
|
if (!result.ok) {
|
|
@@ -320,15 +345,21 @@ export function handleQuery(
|
|
|
320
345
|
// Enrich with absPath
|
|
321
346
|
const enrichedResults = enrichWithAbsPath(result.value.results, ctx);
|
|
322
347
|
|
|
323
|
-
return
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
348
|
+
return attachRetrievalTraceMetadata(
|
|
349
|
+
{
|
|
350
|
+
...result.value,
|
|
351
|
+
results: enrichedResults,
|
|
352
|
+
meta: {
|
|
353
|
+
...result.value.meta,
|
|
354
|
+
// Add queryLanguage hint if provided
|
|
355
|
+
...(args.lang ? { queryLanguage: args.lang } : {}),
|
|
356
|
+
},
|
|
330
357
|
},
|
|
331
|
-
|
|
358
|
+
traceSession
|
|
359
|
+
);
|
|
360
|
+
} catch (cause) {
|
|
361
|
+
await finishRetrievalTraceAfterError(traceSession, cause);
|
|
362
|
+
throw cause;
|
|
332
363
|
} finally {
|
|
333
364
|
if (embedPort) {
|
|
334
365
|
await embedPort.dispose();
|
package/src/mcp/tools/search.ts
CHANGED
|
@@ -6,10 +6,17 @@
|
|
|
6
6
|
|
|
7
7
|
import { join as pathJoin } from "node:path";
|
|
8
8
|
|
|
9
|
+
import type { RetrievalTraceSession } from "../../core/retrieval-trace-session";
|
|
9
10
|
import type { SearchResult, SearchResults } from "../../pipeline/types";
|
|
10
11
|
import type { ToolContext } from "../server";
|
|
11
12
|
|
|
12
13
|
import { decorateUriForIndex, parseUri } from "../../app/constants";
|
|
14
|
+
import {
|
|
15
|
+
finishRetrievalTraceAfterError,
|
|
16
|
+
retrievalTraceFilters,
|
|
17
|
+
startRetrievalTraceRequest,
|
|
18
|
+
} from "../../core/retrieval-trace-request";
|
|
19
|
+
import { attachRetrievalTraceMetadata } from "../../core/retrieval-trace-session";
|
|
13
20
|
import { searchBm25 } from "../../pipeline/search";
|
|
14
21
|
import { normalizeTagFilters, runTool, type ToolResult } from "./index";
|
|
15
22
|
|
|
@@ -106,7 +113,7 @@ export function handleSearch(
|
|
|
106
113
|
}
|
|
107
114
|
}
|
|
108
115
|
|
|
109
|
-
const
|
|
116
|
+
const options = {
|
|
110
117
|
limit: args.limit ?? 5,
|
|
111
118
|
minScore: args.minScore,
|
|
112
119
|
collection: args.collection,
|
|
@@ -119,19 +126,35 @@ export function handleSearch(
|
|
|
119
126
|
author: args.author,
|
|
120
127
|
tagsAll: normalizeTagFilters(args.tagsAll),
|
|
121
128
|
tagsAny: normalizeTagFilters(args.tagsAny),
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
if (!result.ok) {
|
|
125
|
-
throw new Error(result.error.message);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// Enrich with absPath
|
|
129
|
-
const enrichedResults = enrichWithAbsPath(result.value.results, ctx);
|
|
130
|
-
|
|
131
|
-
return {
|
|
132
|
-
...result.value,
|
|
133
|
-
results: enrichedResults,
|
|
134
129
|
};
|
|
130
|
+
let traceSession: RetrievalTraceSession | undefined;
|
|
131
|
+
try {
|
|
132
|
+
const traceStart = await startRetrievalTraceRequest({
|
|
133
|
+
store: ctx.store,
|
|
134
|
+
config: ctx.config,
|
|
135
|
+
query: args.query,
|
|
136
|
+
filters: retrievalTraceFilters(options),
|
|
137
|
+
pipeline: "bm25",
|
|
138
|
+
indexName: ctx.indexName,
|
|
139
|
+
});
|
|
140
|
+
if (!traceStart.ok) throw new Error(traceStart.error.message);
|
|
141
|
+
traceSession = traceStart.value ?? undefined;
|
|
142
|
+
const result = await searchBm25(ctx.store, args.query, {
|
|
143
|
+
...options,
|
|
144
|
+
traceSession,
|
|
145
|
+
});
|
|
146
|
+
if (!result.ok) throw new Error(result.error.message);
|
|
147
|
+
return attachRetrievalTraceMetadata(
|
|
148
|
+
{
|
|
149
|
+
...result.value,
|
|
150
|
+
results: enrichWithAbsPath(result.value.results, ctx),
|
|
151
|
+
},
|
|
152
|
+
traceSession
|
|
153
|
+
);
|
|
154
|
+
} catch (cause) {
|
|
155
|
+
await finishRetrievalTraceAfterError(traceSession, cause);
|
|
156
|
+
throw cause;
|
|
157
|
+
}
|
|
135
158
|
},
|
|
136
159
|
formatSearchResults
|
|
137
160
|
);
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/** MCP tools for explicit local retrieval-trace management. */
|
|
2
|
+
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
|
|
5
|
+
import type {
|
|
6
|
+
RetrievalTraceExportRequest,
|
|
7
|
+
RetrievalTraceLabelRequest,
|
|
8
|
+
} from "../../core/retrieval-trace-management";
|
|
9
|
+
import type { StoreResult } from "../../store/types";
|
|
10
|
+
import type { ToolContext } from "../server";
|
|
11
|
+
|
|
12
|
+
import { withWriteLock } from "../../core/file-lock";
|
|
13
|
+
import { RetrievalTraceManagementService } from "../../core/retrieval-trace-management";
|
|
14
|
+
import { runTool, type ToolResult } from "./index";
|
|
15
|
+
|
|
16
|
+
export const traceListInputSchema = z.object({
|
|
17
|
+
limit: z.number().int().min(1).max(1000).default(50),
|
|
18
|
+
cursor: z.string().min(1).max(512).optional(),
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
export const traceShowInputSchema = z.object({
|
|
22
|
+
traceId: z.string().min(1).max(128),
|
|
23
|
+
detailLimit: z.number().int().min(1).max(5000).default(500),
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
export const traceLabelInputSchema = z.object({
|
|
27
|
+
traceId: z.string().min(1).max(128),
|
|
28
|
+
label: z.enum(["relevant", "irrelevant", "missing_expected"]),
|
|
29
|
+
targetRef: z.string().min(1).max(4096),
|
|
30
|
+
targetKind: z.enum(["document", "chunk", "span"]).optional(),
|
|
31
|
+
startLine: z.number().int().positive().optional(),
|
|
32
|
+
endLine: z.number().int().positive().optional(),
|
|
33
|
+
sourceHash: z
|
|
34
|
+
.string()
|
|
35
|
+
.regex(/^[a-f0-9]{64}$/)
|
|
36
|
+
.optional(),
|
|
37
|
+
docid: z.string().min(1).max(256).optional(),
|
|
38
|
+
idempotencyKey: z.string().min(1).max(256).optional(),
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
export const traceExportInputSchema = z.object({
|
|
42
|
+
traceIds: z.array(z.string().min(1).max(128)).min(1).max(1000),
|
|
43
|
+
format: z.literal("agentic-receipt").default("agentic-receipt"),
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
export const traceDeleteInputSchema = z.object({
|
|
47
|
+
traceId: z.string().min(1).max(128),
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
export const tracePurgeInputSchema = z.object({
|
|
51
|
+
confirm: z.literal(true),
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const unwrap = <T>(result: StoreResult<T>): T => {
|
|
55
|
+
if (result.ok) return result.value;
|
|
56
|
+
throw new Error(`${result.error.code}: ${result.error.message}`);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const jsonText = (value: unknown): string => JSON.stringify(value, null, 2);
|
|
60
|
+
|
|
61
|
+
const writeDisabled = (): never => {
|
|
62
|
+
throw new Error(
|
|
63
|
+
"WRITE_DISABLED: Trace mutations require gateway.enableWrite or --mcp-enable-write"
|
|
64
|
+
);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export const handleTraceList = (
|
|
68
|
+
args: z.infer<typeof traceListInputSchema>,
|
|
69
|
+
ctx: ToolContext
|
|
70
|
+
): Promise<ToolResult> =>
|
|
71
|
+
runTool(
|
|
72
|
+
ctx,
|
|
73
|
+
"gno_trace_list",
|
|
74
|
+
async () =>
|
|
75
|
+
unwrap(await new RetrievalTraceManagementService(ctx.store).list(args)),
|
|
76
|
+
jsonText
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
export const handleTraceShow = (
|
|
80
|
+
args: z.infer<typeof traceShowInputSchema>,
|
|
81
|
+
ctx: ToolContext
|
|
82
|
+
): Promise<ToolResult> =>
|
|
83
|
+
runTool(
|
|
84
|
+
ctx,
|
|
85
|
+
"gno_trace_show",
|
|
86
|
+
async () =>
|
|
87
|
+
unwrap(
|
|
88
|
+
await new RetrievalTraceManagementService(ctx.store).show(
|
|
89
|
+
args.traceId,
|
|
90
|
+
{ detailLimit: args.detailLimit }
|
|
91
|
+
)
|
|
92
|
+
),
|
|
93
|
+
jsonText
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
const runTraceWrite = <T>(
|
|
97
|
+
ctx: ToolContext,
|
|
98
|
+
name: string,
|
|
99
|
+
operation: (
|
|
100
|
+
service: RetrievalTraceManagementService
|
|
101
|
+
) => Promise<StoreResult<T>>
|
|
102
|
+
): Promise<ToolResult> =>
|
|
103
|
+
runTool(
|
|
104
|
+
ctx,
|
|
105
|
+
name,
|
|
106
|
+
async () => {
|
|
107
|
+
if (!ctx.enableWrite) return writeDisabled();
|
|
108
|
+
return withWriteLock(ctx.writeLockPath, async () =>
|
|
109
|
+
unwrap(await operation(new RetrievalTraceManagementService(ctx.store)))
|
|
110
|
+
);
|
|
111
|
+
},
|
|
112
|
+
jsonText
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
export const handleTraceLabel = (
|
|
116
|
+
args: z.infer<typeof traceLabelInputSchema>,
|
|
117
|
+
ctx: ToolContext
|
|
118
|
+
): Promise<ToolResult> =>
|
|
119
|
+
runTraceWrite(ctx, "gno_trace_label", (service) =>
|
|
120
|
+
service.label(args as RetrievalTraceLabelRequest)
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
export const handleTraceExport = (
|
|
124
|
+
args: z.infer<typeof traceExportInputSchema>,
|
|
125
|
+
ctx: ToolContext
|
|
126
|
+
): Promise<ToolResult> =>
|
|
127
|
+
runTraceWrite(ctx, "gno_trace_export", (service) =>
|
|
128
|
+
service.export(args as RetrievalTraceExportRequest)
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
export const handleTraceDelete = (
|
|
132
|
+
args: z.infer<typeof traceDeleteInputSchema>,
|
|
133
|
+
ctx: ToolContext
|
|
134
|
+
): Promise<ToolResult> =>
|
|
135
|
+
runTraceWrite(ctx, "gno_trace_delete", (service) =>
|
|
136
|
+
service.delete(args.traceId)
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
export const handleTracePurge = (
|
|
140
|
+
_args: z.infer<typeof tracePurgeInputSchema>,
|
|
141
|
+
ctx: ToolContext
|
|
142
|
+
): Promise<ToolResult> =>
|
|
143
|
+
runTraceWrite(ctx, "gno_trace_purge", (service) => service.purge());
|
package/src/mcp/tools/vsearch.ts
CHANGED
|
@@ -6,11 +6,21 @@
|
|
|
6
6
|
|
|
7
7
|
import { join as pathJoin } from "node:path";
|
|
8
8
|
|
|
9
|
+
import type { EmbeddingPort } from "../../llm/types";
|
|
9
10
|
import type { SearchResult, SearchResults } from "../../pipeline/types";
|
|
10
11
|
import type { ToolContext } from "../server";
|
|
11
12
|
|
|
12
13
|
import { decorateUriForIndex, parseUri } from "../../app/constants";
|
|
13
14
|
import { createNonTtyProgressRenderer } from "../../cli/progress";
|
|
15
|
+
import {
|
|
16
|
+
finishRetrievalTraceAfterError,
|
|
17
|
+
retrievalTraceFilters,
|
|
18
|
+
startRetrievalTraceRequest,
|
|
19
|
+
} from "../../core/retrieval-trace-request";
|
|
20
|
+
import {
|
|
21
|
+
attachRetrievalTraceMetadata,
|
|
22
|
+
type RetrievalTraceSession,
|
|
23
|
+
} from "../../core/retrieval-trace-session";
|
|
14
24
|
import { LlmAdapter } from "../../llm/nodeLlamaCpp/adapter";
|
|
15
25
|
import { resolveDownloadPolicy } from "../../llm/policy";
|
|
16
26
|
import { resolveModelUri } from "../../llm/registry";
|
|
@@ -125,29 +135,55 @@ export function handleVsearch(
|
|
|
125
135
|
undefined,
|
|
126
136
|
args.collection
|
|
127
137
|
);
|
|
138
|
+
const options = {
|
|
139
|
+
limit: args.limit ?? 5,
|
|
140
|
+
minScore: args.minScore,
|
|
141
|
+
collection: args.collection,
|
|
142
|
+
intent: args.intent,
|
|
143
|
+
exclude: args.exclude,
|
|
144
|
+
since: args.since,
|
|
145
|
+
until: args.until,
|
|
146
|
+
categories: args.categories,
|
|
147
|
+
author: args.author,
|
|
148
|
+
tagsAll: normalizeTagFilters(args.tagsAll),
|
|
149
|
+
tagsAny: normalizeTagFilters(args.tagsAny),
|
|
150
|
+
};
|
|
151
|
+
let traceSession: RetrievalTraceSession | undefined;
|
|
152
|
+
const traceStart = await startRetrievalTraceRequest({
|
|
153
|
+
store: ctx.store,
|
|
154
|
+
config: ctx.config,
|
|
155
|
+
query: args.query,
|
|
156
|
+
filters: retrievalTraceFilters(options),
|
|
157
|
+
pipeline: "vector",
|
|
158
|
+
indexName: ctx.indexName,
|
|
159
|
+
modelUris: [modelUri],
|
|
160
|
+
});
|
|
161
|
+
if (!traceStart.ok) throw new Error(traceStart.error.message);
|
|
162
|
+
traceSession = traceStart.value ?? undefined;
|
|
128
163
|
|
|
129
|
-
|
|
130
|
-
const policy = resolveDownloadPolicy(process.env, {});
|
|
164
|
+
let embedPort: EmbeddingPort | null = null;
|
|
131
165
|
|
|
132
|
-
|
|
133
|
-
|
|
166
|
+
try {
|
|
167
|
+
// Resolve download policy from env (MCP has no CLI flags)
|
|
168
|
+
const policy = resolveDownloadPolicy(process.env, {});
|
|
134
169
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
const embedResult = await llm.createEmbeddingPort(modelUri, {
|
|
138
|
-
policy,
|
|
139
|
-
onProgress: (progress) => downloadProgress("embed", progress),
|
|
140
|
-
});
|
|
141
|
-
if (!embedResult.ok) {
|
|
142
|
-
throw new Error(
|
|
143
|
-
`Failed to load embedding model: ${embedResult.error.message}. ` +
|
|
144
|
-
"Ensure models are downloaded with: gno models pull"
|
|
145
|
-
);
|
|
146
|
-
}
|
|
170
|
+
// Non-TTY progress for MCP (periodic lines to stderr, not \r)
|
|
171
|
+
const downloadProgress = createNonTtyProgressRenderer();
|
|
147
172
|
|
|
148
|
-
|
|
173
|
+
// Create LLM adapter for embeddings
|
|
174
|
+
const llm = new LlmAdapter(ctx.config);
|
|
175
|
+
const embedResult = await llm.createEmbeddingPort(modelUri, {
|
|
176
|
+
policy,
|
|
177
|
+
onProgress: (progress) => downloadProgress("embed", progress),
|
|
178
|
+
});
|
|
179
|
+
if (!embedResult.ok) {
|
|
180
|
+
throw new Error(
|
|
181
|
+
`Failed to load embedding model: ${embedResult.error.message}. ` +
|
|
182
|
+
"Ensure models are downloaded with: gno models pull"
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
embedPort = embedResult.value;
|
|
149
186
|
|
|
150
|
-
try {
|
|
151
187
|
// Embed query with contextual formatting
|
|
152
188
|
const queryEmbedResult = await embedPort.embed(
|
|
153
189
|
formatQueryForEmbedding(args.query, embedPort.modelUri)
|
|
@@ -196,17 +232,8 @@ export function handleVsearch(
|
|
|
196
232
|
args.query,
|
|
197
233
|
queryEmbedding,
|
|
198
234
|
{
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
collection: args.collection,
|
|
202
|
-
intent: args.intent,
|
|
203
|
-
exclude: args.exclude,
|
|
204
|
-
since: args.since,
|
|
205
|
-
until: args.until,
|
|
206
|
-
categories: args.categories,
|
|
207
|
-
author: args.author,
|
|
208
|
-
tagsAll: normalizeTagFilters(args.tagsAll),
|
|
209
|
-
tagsAny: normalizeTagFilters(args.tagsAny),
|
|
235
|
+
...options,
|
|
236
|
+
traceSession,
|
|
210
237
|
}
|
|
211
238
|
);
|
|
212
239
|
|
|
@@ -217,17 +244,23 @@ export function handleVsearch(
|
|
|
217
244
|
// Enrich with absPath
|
|
218
245
|
const enrichedResults = enrichWithAbsPath(result.value.results, ctx);
|
|
219
246
|
|
|
220
|
-
return
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
247
|
+
return attachRetrievalTraceMetadata(
|
|
248
|
+
{
|
|
249
|
+
...result.value,
|
|
250
|
+
results: enrichedResults,
|
|
251
|
+
meta: {
|
|
252
|
+
...result.value.meta,
|
|
253
|
+
// Add queryLanguage hint if provided (per spec, lang is a hint for vsearch)
|
|
254
|
+
...(args.lang ? { queryLanguage: args.lang } : {}),
|
|
255
|
+
},
|
|
227
256
|
},
|
|
228
|
-
|
|
257
|
+
traceSession
|
|
258
|
+
);
|
|
259
|
+
} catch (cause) {
|
|
260
|
+
await finishRetrievalTraceAfterError(traceSession, cause);
|
|
261
|
+
throw cause;
|
|
229
262
|
} finally {
|
|
230
|
-
await embedPort
|
|
263
|
+
await embedPort?.dispose();
|
|
231
264
|
}
|
|
232
265
|
},
|
|
233
266
|
formatSearchResults
|