@gmickel/gno 1.8.0 → 1.10.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 +6 -2
- package/assets/skill/SKILL.md +41 -16
- package/assets/skill/cli-reference.md +39 -0
- package/assets/skill/examples.md +41 -0
- package/assets/skill/mcp-reference.md +13 -1
- package/package.json +1 -1
- package/src/cli/commands/capture.ts +9 -6
- package/src/cli/commands/graph.ts +89 -2
- package/src/cli/commands/index-cmd.ts +17 -6
- package/src/cli/commands/links.ts +237 -54
- package/src/cli/commands/query.ts +212 -0
- package/src/cli/commands/ref-parser.ts +8 -103
- package/src/cli/commands/shared.ts +17 -1
- package/src/cli/commands/update.ts +17 -6
- package/src/cli/options.ts +4 -0
- package/src/cli/program.ts +176 -9
- package/src/config/content-types.ts +154 -0
- package/src/config/defaults.ts +1 -0
- package/src/config/index.ts +14 -0
- package/src/config/loader.ts +11 -2
- package/src/config/types.ts +37 -1
- package/src/core/config-mutation.ts +14 -2
- package/src/core/graph-query.ts +137 -0
- package/src/core/graph-resolver.ts +117 -0
- package/src/core/note-presets.ts +61 -5
- package/src/core/ref-parser.ts +145 -0
- package/src/ingestion/frontmatter.ts +170 -2
- package/src/ingestion/index.ts +2 -0
- package/src/ingestion/sync-options.ts +29 -0
- package/src/ingestion/sync.ts +385 -17
- package/src/ingestion/types.ts +14 -0
- package/src/mcp/tools/add-collection.ts +8 -5
- package/src/mcp/tools/capture.ts +5 -2
- package/src/mcp/tools/get.ts +1 -1
- package/src/mcp/tools/index-cmd.ts +13 -7
- package/src/mcp/tools/index.ts +97 -10
- package/src/mcp/tools/links.ts +83 -1
- package/src/mcp/tools/multi-get.ts +1 -1
- package/src/mcp/tools/query.ts +207 -0
- package/src/mcp/tools/sync.ts +12 -6
- package/src/mcp/tools/workspace-write.ts +16 -10
- package/src/pipeline/diagnose.ts +302 -0
- package/src/pipeline/filters.ts +119 -0
- package/src/pipeline/hybrid.ts +92 -17
- package/src/pipeline/search.ts +2 -0
- package/src/pipeline/types.ts +34 -0
- package/src/pipeline/vsearch.ts +4 -0
- package/src/publish/export-service.ts +1 -1
- package/src/sdk/client.ts +51 -24
- package/src/sdk/documents.ts +2 -2
- package/src/serve/background-runtime.ts +18 -4
- package/src/serve/config-sync.ts +9 -2
- package/src/serve/routes/api.ts +244 -24
- package/src/serve/routes/graph.ts +173 -1
- package/src/serve/server.ts +24 -1
- package/src/serve/watch-service.ts +12 -2
- package/src/store/migrations/009-content-type-rule-fingerprint.ts +36 -0
- package/src/store/migrations/010-typed-edges.ts +67 -0
- package/src/store/migrations/011-doc-edge-traversal-indexes.ts +30 -0
- package/src/store/migrations/index.ts +16 -1
- package/src/store/sqlite/adapter.ts +853 -114
- package/src/store/types.ts +147 -0
package/src/pipeline/types.ts
CHANGED
|
@@ -43,6 +43,8 @@ export interface SearchResult {
|
|
|
43
43
|
score: number;
|
|
44
44
|
uri: string;
|
|
45
45
|
title?: string;
|
|
46
|
+
contentType?: string;
|
|
47
|
+
categories?: string[];
|
|
46
48
|
/** Best source line for editor/agent anchors (1-indexed) */
|
|
47
49
|
line?: number;
|
|
48
50
|
snippet: string;
|
|
@@ -102,6 +104,8 @@ export interface SearchMeta {
|
|
|
102
104
|
lines: ExplainLine[];
|
|
103
105
|
results: ExplainResult[];
|
|
104
106
|
};
|
|
107
|
+
/** Internal diagnose trace, only populated when diagnoseTrace is enabled */
|
|
108
|
+
trace?: QueryDiagnoseTrace;
|
|
105
109
|
}
|
|
106
110
|
|
|
107
111
|
/** Complete search results wrapper */
|
|
@@ -180,6 +184,8 @@ export type HybridSearchOptions = SearchOptions & {
|
|
|
180
184
|
noGraph?: boolean;
|
|
181
185
|
/** Language hint for prompt selection (does NOT filter retrieval, only affects expansion prompts) */
|
|
182
186
|
queryLanguageHint?: string;
|
|
187
|
+
/** Internal: capture per-stage candidates for query diagnose */
|
|
188
|
+
diagnoseTrace?: boolean;
|
|
183
189
|
};
|
|
184
190
|
|
|
185
191
|
/** Options for ask command */
|
|
@@ -256,6 +262,34 @@ export interface FusionCandidate {
|
|
|
256
262
|
sources: FusionSource[];
|
|
257
263
|
}
|
|
258
264
|
|
|
265
|
+
export type QueryDiagnoseStageId =
|
|
266
|
+
| "bm25"
|
|
267
|
+
| "vector"
|
|
268
|
+
| "fusion"
|
|
269
|
+
| "graph"
|
|
270
|
+
| "rerank";
|
|
271
|
+
|
|
272
|
+
export type QueryDiagnoseStageStatus = "active" | "skipped";
|
|
273
|
+
|
|
274
|
+
export interface QueryDiagnoseTraceCandidate {
|
|
275
|
+
mirrorHash: string;
|
|
276
|
+
seq: number;
|
|
277
|
+
rank: number;
|
|
278
|
+
score: number;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export interface QueryDiagnoseTraceStage {
|
|
282
|
+
id: QueryDiagnoseStageId;
|
|
283
|
+
status: QueryDiagnoseStageStatus;
|
|
284
|
+
reason?: string;
|
|
285
|
+
sourceCount: number;
|
|
286
|
+
candidates: QueryDiagnoseTraceCandidate[];
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
export interface QueryDiagnoseTrace {
|
|
290
|
+
stages: QueryDiagnoseTraceStage[];
|
|
291
|
+
}
|
|
292
|
+
|
|
259
293
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
260
294
|
// Rerank & Blending Types
|
|
261
295
|
// ─────────────────────────────────────────────────────────────────────────────
|
package/src/pipeline/vsearch.ts
CHANGED
|
@@ -227,6 +227,8 @@ export async function searchVectorWithEmbedding(
|
|
|
227
227
|
score,
|
|
228
228
|
uri: doc.uri,
|
|
229
229
|
title: doc.title ?? undefined,
|
|
230
|
+
contentType: doc.contentType ?? undefined,
|
|
231
|
+
categories: doc.categories ?? undefined,
|
|
230
232
|
line: chunk.startLine,
|
|
231
233
|
snippet: chunk.text,
|
|
232
234
|
snippetLanguage: chunk.language ?? undefined,
|
|
@@ -281,6 +283,8 @@ export async function searchVectorWithEmbedding(
|
|
|
281
283
|
score,
|
|
282
284
|
uri: doc.uri,
|
|
283
285
|
title: doc.title ?? undefined,
|
|
286
|
+
contentType: doc.contentType ?? undefined,
|
|
287
|
+
categories: doc.categories ?? undefined,
|
|
284
288
|
line: chunk.startLine,
|
|
285
289
|
snippet: fullContent ?? chunk.text,
|
|
286
290
|
snippetLanguage: chunk.language ?? undefined,
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import type { Collection } from "../config/types";
|
|
8
8
|
import type { DocumentRow, StorePort, TagRow } from "../store/types";
|
|
9
9
|
|
|
10
|
-
import { parseRef } from "../
|
|
10
|
+
import { parseRef } from "../core/ref-parser";
|
|
11
11
|
import { parseFrontmatter } from "../ingestion/frontmatter";
|
|
12
12
|
import { getContentBatch } from "../store/content-batch";
|
|
13
13
|
import {
|
package/src/sdk/client.ts
CHANGED
|
@@ -44,7 +44,11 @@ import {
|
|
|
44
44
|
getIndexDbPath,
|
|
45
45
|
parseUri,
|
|
46
46
|
} from "../app/constants";
|
|
47
|
-
import {
|
|
47
|
+
import {
|
|
48
|
+
ConfigSchema,
|
|
49
|
+
loadConfig,
|
|
50
|
+
normalizeConfigContentTypes,
|
|
51
|
+
} from "../config";
|
|
48
52
|
import {
|
|
49
53
|
buildCaptureReceipt,
|
|
50
54
|
type CapturePlan,
|
|
@@ -70,7 +74,11 @@ import { resolveNotePreset } from "../core/note-presets";
|
|
|
70
74
|
import { extractSections } from "../core/sections";
|
|
71
75
|
import { normalizeStructuredQueryInput } from "../core/structured-query";
|
|
72
76
|
import { parseAndValidateTagFilter } from "../core/tags";
|
|
73
|
-
import {
|
|
77
|
+
import {
|
|
78
|
+
defaultSyncService,
|
|
79
|
+
type SyncResult,
|
|
80
|
+
withContentTypeRules,
|
|
81
|
+
} from "../ingestion";
|
|
74
82
|
import { updateFrontmatterTags } from "../ingestion/frontmatter";
|
|
75
83
|
import { LlmAdapter } from "../llm/nodeLlamaCpp/adapter";
|
|
76
84
|
import { resolveDownloadPolicy } from "../llm/policy";
|
|
@@ -141,7 +149,7 @@ async function resolveClientState(
|
|
|
141
149
|
parsed.error.issues[0]?.message ?? "Invalid config"
|
|
142
150
|
);
|
|
143
151
|
}
|
|
144
|
-
config = parsed.data;
|
|
152
|
+
config = normalizeConfigContentTypes(parsed.data).config;
|
|
145
153
|
configPath = null;
|
|
146
154
|
configSource = "inline";
|
|
147
155
|
} else {
|
|
@@ -695,10 +703,17 @@ class GnoClientImpl implements GnoClient {
|
|
|
695
703
|
async update(options: GnoUpdateOptions = {}): Promise<SyncResult> {
|
|
696
704
|
this.assertOpen();
|
|
697
705
|
const collections = this.getCollections(options.collection);
|
|
698
|
-
return defaultSyncService.syncAll(
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
706
|
+
return defaultSyncService.syncAll(
|
|
707
|
+
collections,
|
|
708
|
+
this.store,
|
|
709
|
+
withContentTypeRules(
|
|
710
|
+
{
|
|
711
|
+
gitPull: options.gitPull,
|
|
712
|
+
runUpdateCmd: true,
|
|
713
|
+
},
|
|
714
|
+
this.config
|
|
715
|
+
)
|
|
716
|
+
);
|
|
702
717
|
}
|
|
703
718
|
|
|
704
719
|
async embed(options: GnoEmbedOptions = {}): Promise<GnoEmbedResult> {
|
|
@@ -808,10 +823,13 @@ class GnoClientImpl implements GnoClient {
|
|
|
808
823
|
collection,
|
|
809
824
|
this.store,
|
|
810
825
|
[plan.relPath],
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
826
|
+
withContentTypeRules(
|
|
827
|
+
{
|
|
828
|
+
runUpdateCmd: false,
|
|
829
|
+
gitPull: false,
|
|
830
|
+
},
|
|
831
|
+
this.config
|
|
832
|
+
)
|
|
815
833
|
);
|
|
816
834
|
const syncResult = syncResults[0];
|
|
817
835
|
if (!syncResult || syncResult.status === "error") {
|
|
@@ -903,10 +921,13 @@ class GnoClientImpl implements GnoClient {
|
|
|
903
921
|
collection,
|
|
904
922
|
this.store,
|
|
905
923
|
[plan.relPath],
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
924
|
+
withContentTypeRules(
|
|
925
|
+
{
|
|
926
|
+
runUpdateCmd: false,
|
|
927
|
+
gitPull: false,
|
|
928
|
+
},
|
|
929
|
+
this.config
|
|
930
|
+
)
|
|
910
931
|
);
|
|
911
932
|
const syncResult = syncResults[0];
|
|
912
933
|
const docResult = await this.store.getDocument(
|
|
@@ -987,9 +1008,11 @@ class GnoClientImpl implements GnoClient {
|
|
|
987
1008
|
const currentPath = `${collection.path}/${storedDoc.relPath}`;
|
|
988
1009
|
const nextPath = `${collection.path}/${plan.nextRelPath}`;
|
|
989
1010
|
await renameFilePath(currentPath, nextPath);
|
|
990
|
-
await defaultSyncService.syncCollection(
|
|
991
|
-
|
|
992
|
-
|
|
1011
|
+
await defaultSyncService.syncCollection(
|
|
1012
|
+
collection,
|
|
1013
|
+
this.store,
|
|
1014
|
+
withContentTypeRules({ runUpdateCmd: false }, this.config)
|
|
1015
|
+
);
|
|
993
1016
|
const linksResult = await this.store.getLinksForDoc(storedDoc.id);
|
|
994
1017
|
const backlinksResult = await this.store.getBacklinksForDoc(storedDoc.id);
|
|
995
1018
|
if (!linksResult.ok || !backlinksResult.ok) {
|
|
@@ -1044,9 +1067,11 @@ class GnoClientImpl implements GnoClient {
|
|
|
1044
1067
|
const nextPath = `${collection.path}/${plan.nextRelPath}`;
|
|
1045
1068
|
await mkdir(dirname(nextPath), { recursive: true });
|
|
1046
1069
|
await renameFilePath(currentPath, nextPath);
|
|
1047
|
-
await defaultSyncService.syncCollection(
|
|
1048
|
-
|
|
1049
|
-
|
|
1070
|
+
await defaultSyncService.syncCollection(
|
|
1071
|
+
collection,
|
|
1072
|
+
this.store,
|
|
1073
|
+
withContentTypeRules({ runUpdateCmd: false }, this.config)
|
|
1074
|
+
);
|
|
1050
1075
|
const linksResult = await this.store.getLinksForDoc(storedDoc.id);
|
|
1051
1076
|
const backlinksResult = await this.store.getBacklinksForDoc(storedDoc.id);
|
|
1052
1077
|
if (!linksResult.ok || !backlinksResult.ok) {
|
|
@@ -1113,9 +1138,11 @@ class GnoClientImpl implements GnoClient {
|
|
|
1113
1138
|
const nextPath = `${collection.path}/${plan.nextRelPath}`;
|
|
1114
1139
|
await mkdir(dirname(nextPath), { recursive: true });
|
|
1115
1140
|
await copyFilePath(currentPath, nextPath);
|
|
1116
|
-
await defaultSyncService.syncCollection(
|
|
1117
|
-
|
|
1118
|
-
|
|
1141
|
+
await defaultSyncService.syncCollection(
|
|
1142
|
+
collection,
|
|
1143
|
+
this.store,
|
|
1144
|
+
withContentTypeRules({ runUpdateCmd: false }, this.config)
|
|
1145
|
+
);
|
|
1119
1146
|
const linksResult = await this.store.getLinksForDoc(storedDoc.id);
|
|
1120
1147
|
const backlinksResult = await this.store.getBacklinksForDoc(storedDoc.id);
|
|
1121
1148
|
if (!linksResult.ok || !backlinksResult.ok) {
|
package/src/sdk/documents.ts
CHANGED
|
@@ -13,8 +13,8 @@ import type {
|
|
|
13
13
|
MultiGetResponse,
|
|
14
14
|
SkippedDoc,
|
|
15
15
|
} from "../cli/commands/multi-get";
|
|
16
|
-
import type { ParsedRef } from "../cli/commands/ref-parser";
|
|
17
16
|
import type { Config } from "../config/types";
|
|
17
|
+
import type { ParsedRef } from "../core/ref-parser";
|
|
18
18
|
import type { DocumentRow, StorePort } from "../store/types";
|
|
19
19
|
import type {
|
|
20
20
|
GnoGetOptions,
|
|
@@ -22,8 +22,8 @@ import type {
|
|
|
22
22
|
GnoMultiGetOptions,
|
|
23
23
|
} from "./types";
|
|
24
24
|
|
|
25
|
-
import { isGlobPattern, parseRef, splitRefs } from "../cli/commands/ref-parser";
|
|
26
25
|
import { getDocumentCapabilities } from "../core/document-capabilities";
|
|
26
|
+
import { isGlobPattern, parseRef, splitRefs } from "../core/ref-parser";
|
|
27
27
|
import { sdkError } from "./errors";
|
|
28
28
|
|
|
29
29
|
const URI_PREFIX_PATTERN = /^gno:\/\/[^/]+\//;
|
|
@@ -11,11 +11,13 @@ import type {
|
|
|
11
11
|
import { getIndexDbPath } from "../app/constants";
|
|
12
12
|
import {
|
|
13
13
|
ensureDirectories,
|
|
14
|
+
formatConfigWarnings,
|
|
14
15
|
getConfigPaths,
|
|
15
16
|
isInitialized,
|
|
16
17
|
loadConfig,
|
|
17
18
|
} from "../config";
|
|
18
19
|
import { defaultSyncService } from "../ingestion";
|
|
20
|
+
import { withContentTypeRules } from "../ingestion";
|
|
19
21
|
import { getActivePreset } from "../llm/registry";
|
|
20
22
|
import { SqliteAdapter } from "../store/sqlite/adapter";
|
|
21
23
|
import {
|
|
@@ -79,6 +81,7 @@ type BackgroundRuntimeDeps = {
|
|
|
79
81
|
scheduler: EmbedScheduler | null;
|
|
80
82
|
eventBus?: DocumentEventBus | null;
|
|
81
83
|
callbacks?: CollectionWatchCallbacks;
|
|
84
|
+
syncOptions?: Parameters<typeof withContentTypeRules>[0];
|
|
82
85
|
}) => CollectionWatchService;
|
|
83
86
|
};
|
|
84
87
|
|
|
@@ -103,6 +106,9 @@ export async function startBackgroundRuntime(
|
|
|
103
106
|
if (!configResult.ok) {
|
|
104
107
|
return { success: false, error: configResult.error.message };
|
|
105
108
|
}
|
|
109
|
+
for (const warning of formatConfigWarnings(configResult.warnings)) {
|
|
110
|
+
console.warn(warning);
|
|
111
|
+
}
|
|
106
112
|
const config = configResult.value;
|
|
107
113
|
|
|
108
114
|
if (options.requireCollections && config.collections.length === 0) {
|
|
@@ -171,6 +177,7 @@ export async function startBackgroundRuntime(
|
|
|
171
177
|
scheduler,
|
|
172
178
|
eventBus: options.eventBus ?? null,
|
|
173
179
|
callbacks: options.watchCallbacks,
|
|
180
|
+
syncOptions: withContentTypeRules({}, config),
|
|
174
181
|
});
|
|
175
182
|
watchService.start();
|
|
176
183
|
ctxHolder.watchService = watchService;
|
|
@@ -189,10 +196,17 @@ export async function startBackgroundRuntime(
|
|
|
189
196
|
eventBus: options.eventBus ?? null,
|
|
190
197
|
watchService,
|
|
191
198
|
async syncAll(syncOptions = {}) {
|
|
192
|
-
const syncResult = await syncAllService(
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
199
|
+
const syncResult = await syncAllService(
|
|
200
|
+
config.collections,
|
|
201
|
+
store,
|
|
202
|
+
withContentTypeRules(
|
|
203
|
+
{
|
|
204
|
+
gitPull: syncOptions.gitPull,
|
|
205
|
+
runUpdateCmd: syncOptions.runUpdateCmd,
|
|
206
|
+
},
|
|
207
|
+
config
|
|
208
|
+
)
|
|
209
|
+
);
|
|
196
210
|
|
|
197
211
|
let embedResult: EmbedResult | null = null;
|
|
198
212
|
if (syncOptions.triggerEmbed !== false) {
|
package/src/serve/config-sync.ts
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
type ApplyConfigResult,
|
|
15
15
|
type MutationResult,
|
|
16
16
|
} from "../core/config-mutation";
|
|
17
|
+
import { withContentTypeRules } from "../ingestion";
|
|
17
18
|
|
|
18
19
|
/**
|
|
19
20
|
* Apply a config mutation atomically with serialization.
|
|
@@ -53,7 +54,10 @@ export async function applyConfigChange(
|
|
|
53
54
|
);
|
|
54
55
|
|
|
55
56
|
if (result.ok) {
|
|
56
|
-
ctxHolder.watchService?.updateCollections(
|
|
57
|
+
ctxHolder.watchService?.updateCollections(
|
|
58
|
+
ctxHolder.config.collections,
|
|
59
|
+
withContentTypeRules({}, ctxHolder.config)
|
|
60
|
+
);
|
|
57
61
|
}
|
|
58
62
|
|
|
59
63
|
return result;
|
|
@@ -78,7 +82,10 @@ export async function applyConfigChangeTyped<T>(
|
|
|
78
82
|
);
|
|
79
83
|
|
|
80
84
|
if (result.ok) {
|
|
81
|
-
ctxHolder.watchService?.updateCollections(
|
|
85
|
+
ctxHolder.watchService?.updateCollections(
|
|
86
|
+
ctxHolder.config.collections,
|
|
87
|
+
withContentTypeRules({}, ctxHolder.config)
|
|
88
|
+
);
|
|
82
89
|
}
|
|
83
90
|
|
|
84
91
|
return result;
|