@kb-labs/mind-entry 2.14.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 +218 -0
- package/dist/cli/commands/init.d.ts +24 -0
- package/dist/cli/commands/init.js +114 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/rag-index.d.ts +20 -0
- package/dist/cli/commands/rag-index.js +363 -0
- package/dist/cli/commands/rag-index.js.map +1 -0
- package/dist/cli/commands/rag-query.d.ts +25 -0
- package/dist/cli/commands/rag-query.js +670 -0
- package/dist/cli/commands/rag-query.js.map +1 -0
- package/dist/cli/commands/verify.d.ts +15 -0
- package/dist/cli/commands/verify.js +92 -0
- package/dist/cli/commands/verify.js.map +1 -0
- package/dist/index.d.ts +592 -0
- package/dist/index.js +1499 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest.v3.d.ts +52 -0
- package/dist/manifest.v3.js +180 -0
- package/dist/manifest.v3.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,670 @@
|
|
|
1
|
+
import { defineCommand, usePlatform, useLLM } from '@kb-labs/sdk';
|
|
2
|
+
import { createHash } from 'crypto';
|
|
3
|
+
import * as path2 from 'path';
|
|
4
|
+
import { readFile } from 'fs/promises';
|
|
5
|
+
import { loadManifest, MindEngine } from '@kb-labs/mind-engine';
|
|
6
|
+
import { isAgentError, createAgentQueryOrchestrator } from '@kb-labs/mind-orchestrator';
|
|
7
|
+
|
|
8
|
+
// src/cli/commands/rag-query.ts
|
|
9
|
+
var MIND_PRODUCT_ID = "mind";
|
|
10
|
+
async function createMindRuntime(options) {
|
|
11
|
+
const config = await resolveConfig(options.cwd, options.config);
|
|
12
|
+
const platform = options.platform ?? usePlatform();
|
|
13
|
+
const service = {
|
|
14
|
+
index: async (scopeId) => {
|
|
15
|
+
const scope = resolveScope(config, scopeId);
|
|
16
|
+
const engine = createEngine(config, scope, options.cwd, options.runtime, platform, options.onProgress);
|
|
17
|
+
await engine.init();
|
|
18
|
+
const stats = await engine.index(resolveSources(config, scope), {
|
|
19
|
+
scope,
|
|
20
|
+
workspaceRoot: options.cwd
|
|
21
|
+
});
|
|
22
|
+
return stats;
|
|
23
|
+
},
|
|
24
|
+
query: async (queryOptions) => {
|
|
25
|
+
if (queryOptions.productId && queryOptions.productId !== MIND_PRODUCT_ID) {
|
|
26
|
+
throw new Error(`Unsupported productId "${queryOptions.productId}". Expected "${MIND_PRODUCT_ID}".`);
|
|
27
|
+
}
|
|
28
|
+
const scope = resolveScope(config, queryOptions.scopeId);
|
|
29
|
+
const sources = resolveSources(config, scope);
|
|
30
|
+
const engine = createEngine(config, scope, options.cwd, options.runtime, platform, options.onProgress);
|
|
31
|
+
await engine.init();
|
|
32
|
+
const result = await engine.query(
|
|
33
|
+
{
|
|
34
|
+
text: queryOptions.text,
|
|
35
|
+
intent: queryOptions.intent ?? "summary",
|
|
36
|
+
limit: queryOptions.limit,
|
|
37
|
+
profileId: queryOptions.profileId,
|
|
38
|
+
metadata: queryOptions.metadata
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
scope,
|
|
42
|
+
sources,
|
|
43
|
+
workspaceRoot: options.cwd,
|
|
44
|
+
limit: queryOptions.limit,
|
|
45
|
+
profile: queryOptions.profileId ? { id: queryOptions.profileId } : void 0
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
return result;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
return {
|
|
52
|
+
service,
|
|
53
|
+
config
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
function createEngine(config, scope, cwd, runtime, platform, onProgress) {
|
|
57
|
+
const engineConfig = resolveEngineConfig(config, scope);
|
|
58
|
+
return new MindEngine(
|
|
59
|
+
{
|
|
60
|
+
id: engineConfig.id,
|
|
61
|
+
type: engineConfig.type,
|
|
62
|
+
options: {
|
|
63
|
+
...engineConfig.options ?? {},
|
|
64
|
+
_runtime: runtime,
|
|
65
|
+
platform: platform ?? void 0,
|
|
66
|
+
onProgress
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
workspaceRoot: cwd
|
|
71
|
+
}
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
function resolveSources(config, scope) {
|
|
75
|
+
if (!scope.sourceIds?.length) {
|
|
76
|
+
return config.sources;
|
|
77
|
+
}
|
|
78
|
+
const selected = config.sources.filter((source) => scope.sourceIds.includes(source.id));
|
|
79
|
+
if (!selected.length) {
|
|
80
|
+
throw new Error(`Scope "${scope.id}" does not reference existing sources.`);
|
|
81
|
+
}
|
|
82
|
+
return selected;
|
|
83
|
+
}
|
|
84
|
+
function resolveScope(config, scopeId) {
|
|
85
|
+
const scope = config.scopes.find((item) => item.id === scopeId);
|
|
86
|
+
if (!scope) {
|
|
87
|
+
throw new Error(`Scope "${scopeId}" is not defined in mind.scopes.`);
|
|
88
|
+
}
|
|
89
|
+
return scope;
|
|
90
|
+
}
|
|
91
|
+
function resolveEngineConfig(config, scope) {
|
|
92
|
+
const engineId = scope.defaultEngine ?? config.defaults?.fallbackEngineId ?? config.engines[0]?.id;
|
|
93
|
+
if (!engineId) {
|
|
94
|
+
throw new Error("No engines configured in mind config.");
|
|
95
|
+
}
|
|
96
|
+
const engine = config.engines.find((item) => item.id === engineId);
|
|
97
|
+
if (!engine) {
|
|
98
|
+
throw new Error(`Engine "${engineId}" referenced by scope "${scope.id}" does not exist.`);
|
|
99
|
+
}
|
|
100
|
+
return engine;
|
|
101
|
+
}
|
|
102
|
+
async function resolveConfig(cwd, provided) {
|
|
103
|
+
if (provided) {
|
|
104
|
+
return normalizeConfig(provided);
|
|
105
|
+
}
|
|
106
|
+
const configPath = await findConfigPath(cwd);
|
|
107
|
+
const raw = JSON.parse(await readFile(configPath, "utf8"));
|
|
108
|
+
return normalizeConfig(raw);
|
|
109
|
+
}
|
|
110
|
+
async function findConfigPath(cwd) {
|
|
111
|
+
const candidates = [
|
|
112
|
+
path2.resolve(cwd, ".kb/kb.config.json"),
|
|
113
|
+
path2.resolve(cwd, "kb.config.json")
|
|
114
|
+
];
|
|
115
|
+
for (const candidate of candidates) {
|
|
116
|
+
try {
|
|
117
|
+
await readFile(candidate, "utf8");
|
|
118
|
+
return candidate;
|
|
119
|
+
} catch {
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
throw new Error("No kb.config.json found. Expected .kb/kb.config.json or kb.config.json.");
|
|
123
|
+
}
|
|
124
|
+
function normalizeConfig(raw) {
|
|
125
|
+
const data = raw;
|
|
126
|
+
if (Array.isArray(data.profiles) && data.profiles.length > 0) {
|
|
127
|
+
const profile = data.profiles.find((p) => p.id === "default") ?? data.profiles[0];
|
|
128
|
+
const products = profile?.products;
|
|
129
|
+
const mindConfig = products?.[MIND_PRODUCT_ID];
|
|
130
|
+
if (!mindConfig) {
|
|
131
|
+
throw new Error("Config does not contain profiles[].products.mind section.");
|
|
132
|
+
}
|
|
133
|
+
return validateConfig(mindConfig);
|
|
134
|
+
}
|
|
135
|
+
if (data.mind && typeof data.mind === "object") {
|
|
136
|
+
return validateConfig(data.mind);
|
|
137
|
+
}
|
|
138
|
+
return validateConfig(data);
|
|
139
|
+
}
|
|
140
|
+
function validateConfig(config) {
|
|
141
|
+
if (!Array.isArray(config.sources) || !Array.isArray(config.scopes) || !Array.isArray(config.engines)) {
|
|
142
|
+
throw new Error("Invalid mind config: required arrays sources/scopes/engines are missing.");
|
|
143
|
+
}
|
|
144
|
+
return config;
|
|
145
|
+
}
|
|
146
|
+
var globalOrchestrator = null;
|
|
147
|
+
async function runRagQuery(options) {
|
|
148
|
+
const onProgressEvent = options.onProgress ? (event) => {
|
|
149
|
+
try {
|
|
150
|
+
const stageMap = {
|
|
151
|
+
"using_reasoning_engine": "Using reasoning engine",
|
|
152
|
+
"reasoning_completed": "Reasoning completed",
|
|
153
|
+
"analyzing_query_complexity": "Analyzing query complexity",
|
|
154
|
+
"query_is_simple": "Query is simple",
|
|
155
|
+
"planning_query": "Planning query",
|
|
156
|
+
"query_plan_generated": "Query plan generated",
|
|
157
|
+
"executing_subqueries": "Executing subqueries",
|
|
158
|
+
"subqueries_completed": "Subqueries completed",
|
|
159
|
+
"synthesizing_context": "Synthesizing context",
|
|
160
|
+
"context_synthesis_completed": "Context synthesis completed",
|
|
161
|
+
"generating_embedding": "Generating embeddings",
|
|
162
|
+
"performing_hybrid_search": "Performing hybrid search",
|
|
163
|
+
"searching_vector_store": "Searching vector store",
|
|
164
|
+
"search_completed": "Search completed",
|
|
165
|
+
"applying_popularity_boost": "Applying popularity boost",
|
|
166
|
+
"applying_query_pattern_boost": "Applying query pattern boost",
|
|
167
|
+
"re_ranking_results": "Re-ranking results",
|
|
168
|
+
"re_ranking_completed": "Re-ranking completed",
|
|
169
|
+
"compression_applied": "Compression applied",
|
|
170
|
+
"saving_query_history": "Saving query history"
|
|
171
|
+
};
|
|
172
|
+
const humanReadableStage = stageMap[event.stage] || event.stage;
|
|
173
|
+
let enhancedDetails = event.details;
|
|
174
|
+
if (event.metadata) {
|
|
175
|
+
if (event.metadata.subqueries && Array.isArray(event.metadata.subqueries)) {
|
|
176
|
+
const subqueryList = event.metadata.subqueries.slice(0, 3).join(", ");
|
|
177
|
+
const count = event.metadata.subqueries.length;
|
|
178
|
+
enhancedDetails = `${count} subqueries: ${subqueryList}${count > 3 ? "..." : ""}`;
|
|
179
|
+
} else if (typeof event.metadata.resultCount === "number") {
|
|
180
|
+
enhancedDetails = `${event.metadata.resultCount} results`;
|
|
181
|
+
} else if (typeof event.metadata.chunkCount === "number") {
|
|
182
|
+
enhancedDetails = `${event.metadata.chunkCount} chunks`;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
if (options.onProgress) {
|
|
186
|
+
options.onProgress(humanReadableStage, enhancedDetails);
|
|
187
|
+
}
|
|
188
|
+
} catch (error) {
|
|
189
|
+
}
|
|
190
|
+
} : void 0;
|
|
191
|
+
const originalRuntime = options.runtime;
|
|
192
|
+
const wrappedRuntime = originalRuntime ? {
|
|
193
|
+
...originalRuntime,
|
|
194
|
+
log: (level, message, meta) => {
|
|
195
|
+
if (level === "info" || level === "debug") {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
if (originalRuntime.log && (level === "warn" || level === "error")) {
|
|
199
|
+
originalRuntime.log(level, message, meta);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
} : void 0;
|
|
203
|
+
const runtime = await createMindRuntime({
|
|
204
|
+
cwd: options.cwd,
|
|
205
|
+
config: options.config,
|
|
206
|
+
runtime: wrappedRuntime,
|
|
207
|
+
onProgress: onProgressEvent,
|
|
208
|
+
platform: options.platform
|
|
209
|
+
});
|
|
210
|
+
options.onProgress?.("Initializing Mind runtime");
|
|
211
|
+
const defaultScopeId = runtime.config.scopes?.[0]?.id;
|
|
212
|
+
const scopeId = options.scopeId ?? defaultScopeId;
|
|
213
|
+
if (!scopeId) {
|
|
214
|
+
throw new Error(
|
|
215
|
+
"No mind scopes configured. Provide at least one scope in kb.config.json."
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
options.onProgress?.("Preparing query", `scope: ${scopeId}`);
|
|
219
|
+
options.onProgress?.("Searching Mind index");
|
|
220
|
+
const result = await runtime.service.query({
|
|
221
|
+
productId: MIND_PRODUCT_ID,
|
|
222
|
+
intent: options.intent ?? "summary",
|
|
223
|
+
scopeId,
|
|
224
|
+
text: options.text,
|
|
225
|
+
limit: options.limit,
|
|
226
|
+
profileId: options.profileId
|
|
227
|
+
});
|
|
228
|
+
options.onProgress?.("Processing results", `${result.chunks.length} chunks found`);
|
|
229
|
+
return {
|
|
230
|
+
scopeId,
|
|
231
|
+
result
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
async function runAgentRagQuery(options) {
|
|
235
|
+
const platformBroker = options.platform?.cache ? {
|
|
236
|
+
get: (key) => options.platform.cache.get(key),
|
|
237
|
+
set: (key, value, ttl) => options.platform.cache.set(key, value, ttl),
|
|
238
|
+
delete: (key) => options.platform.cache.delete(key)
|
|
239
|
+
} : void 0;
|
|
240
|
+
const ragLlm = useLLM({
|
|
241
|
+
execution: {
|
|
242
|
+
cache: {
|
|
243
|
+
mode: "prefer",
|
|
244
|
+
scope: "segments"
|
|
245
|
+
},
|
|
246
|
+
stream: {
|
|
247
|
+
mode: "prefer",
|
|
248
|
+
fallbackToComplete: true
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
globalOrchestrator = createAgentQueryOrchestrator({
|
|
253
|
+
llm: ragLlm,
|
|
254
|
+
// Fresh LLM with analytics wrapper + cache/stream policy
|
|
255
|
+
broker: options.broker ?? platformBroker,
|
|
256
|
+
// Pass broker for persistent caching
|
|
257
|
+
analyticsAdapter: options.platform?.analytics ?? null,
|
|
258
|
+
config: {
|
|
259
|
+
mode: options.mode ?? "auto",
|
|
260
|
+
autoDetectComplexity: true
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
const orchestrator = globalOrchestrator;
|
|
264
|
+
const runtime = await createMindRuntime({
|
|
265
|
+
cwd: options.cwd,
|
|
266
|
+
config: options.config,
|
|
267
|
+
runtime: options.runtime,
|
|
268
|
+
platform: options.platform
|
|
269
|
+
});
|
|
270
|
+
const defaultScopeId = runtime.config.scopes?.[0]?.id;
|
|
271
|
+
const scopeId = options.scopeId ?? defaultScopeId;
|
|
272
|
+
if (!scopeId) {
|
|
273
|
+
return {
|
|
274
|
+
error: {
|
|
275
|
+
code: "KNOWLEDGE_SCOPE_NOT_FOUND",
|
|
276
|
+
message: "No mind scopes configured. Provide at least one scope in kb.config.json.",
|
|
277
|
+
recoverable: false
|
|
278
|
+
},
|
|
279
|
+
meta: {
|
|
280
|
+
schemaVersion: "agent-response-v1",
|
|
281
|
+
requestId: `rq-${Date.now()}`,
|
|
282
|
+
mode: options.mode ?? "auto",
|
|
283
|
+
timingMs: 0,
|
|
284
|
+
cached: false
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
const cacheContext = await resolveCacheContext({
|
|
289
|
+
cwd: options.cwd,
|
|
290
|
+
scopeId,
|
|
291
|
+
config: runtime.config,
|
|
292
|
+
providedIndexRevision: options.indexRevision,
|
|
293
|
+
providedEngineConfigHash: options.engineConfigHash,
|
|
294
|
+
providedSourcesDigest: options.sourcesDigest
|
|
295
|
+
});
|
|
296
|
+
const queryFn = async (queryOptions) => {
|
|
297
|
+
const result = await runtime.service.query({
|
|
298
|
+
productId: MIND_PRODUCT_ID,
|
|
299
|
+
intent: queryOptions.intent ?? "search",
|
|
300
|
+
scopeId,
|
|
301
|
+
text: queryOptions.text,
|
|
302
|
+
limit: queryOptions.limit,
|
|
303
|
+
// Pass adaptive weights via metadata for mind-engine to use
|
|
304
|
+
metadata: {
|
|
305
|
+
agentMode: true,
|
|
306
|
+
consumer: "agent",
|
|
307
|
+
mode: options.mode ?? "auto",
|
|
308
|
+
...queryOptions.vectorWeight !== void 0 && queryOptions.keywordWeight !== void 0 ? {
|
|
309
|
+
vectorWeight: queryOptions.vectorWeight,
|
|
310
|
+
keywordWeight: queryOptions.keywordWeight
|
|
311
|
+
} : {}
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
return {
|
|
315
|
+
chunks: result.chunks,
|
|
316
|
+
metadata: result.metadata ?? {}
|
|
317
|
+
};
|
|
318
|
+
};
|
|
319
|
+
return orchestrator.query(
|
|
320
|
+
{
|
|
321
|
+
cwd: options.cwd,
|
|
322
|
+
scopeId,
|
|
323
|
+
text: options.text,
|
|
324
|
+
mode: options.mode,
|
|
325
|
+
indexRevision: cacheContext.indexRevision,
|
|
326
|
+
engineConfigHash: cacheContext.engineConfigHash,
|
|
327
|
+
sourcesDigest: cacheContext.sourcesDigest,
|
|
328
|
+
debug: options.debug
|
|
329
|
+
},
|
|
330
|
+
queryFn
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
async function resolveCacheContext(options) {
|
|
334
|
+
const manifestContext = await readCacheContextFromManifest(options.cwd, options.config, options.scopeId);
|
|
335
|
+
const indexRevision = options.providedIndexRevision ?? manifestContext.indexRevision;
|
|
336
|
+
const engineConfigHash = options.providedEngineConfigHash ?? manifestContext.engineConfigHash ?? computeEngineConfigHash(options.config, options.scopeId);
|
|
337
|
+
const sourcesDigest = options.providedSourcesDigest ?? manifestContext.sourcesDigest;
|
|
338
|
+
return {
|
|
339
|
+
indexRevision,
|
|
340
|
+
engineConfigHash,
|
|
341
|
+
sourcesDigest
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
function computeEngineConfigHash(config, scopeId) {
|
|
345
|
+
const scope = Array.isArray(config?.scopes) ? config.scopes.find((item) => item?.id === scopeId) : void 0;
|
|
346
|
+
const engineId = scope?.defaultEngine ?? config?.defaults?.fallbackEngineId ?? config?.engines?.[0]?.id;
|
|
347
|
+
const engine = Array.isArray(config?.engines) ? config.engines.find((item) => item?.id === engineId) : void 0;
|
|
348
|
+
if (!engine) {
|
|
349
|
+
return void 0;
|
|
350
|
+
}
|
|
351
|
+
const sanitized = {
|
|
352
|
+
id: engine.id,
|
|
353
|
+
type: engine.type,
|
|
354
|
+
options: sanitizeEngineOptionsForHash(engine.options ?? {})
|
|
355
|
+
};
|
|
356
|
+
return createHash("sha256").update(stableStringify(sanitized)).digest("hex");
|
|
357
|
+
}
|
|
358
|
+
async function readCacheContextFromManifest(cwd, config, scopeId) {
|
|
359
|
+
const scope = Array.isArray(config?.scopes) ? config.scopes.find((item) => item?.id === scopeId) : void 0;
|
|
360
|
+
const engineId = scope?.defaultEngine ?? config?.defaults?.fallbackEngineId ?? config?.engines?.[0]?.id;
|
|
361
|
+
const engine = Array.isArray(config?.engines) ? config.engines.find((item) => item?.id === engineId) : void 0;
|
|
362
|
+
const configuredIndexDir = typeof engine?.options?.indexDir === "string" ? engine.options.indexDir : ".kb/mind/rag";
|
|
363
|
+
const candidatePaths = [
|
|
364
|
+
path2.resolve(cwd, configuredIndexDir, scopeId, "manifest.json"),
|
|
365
|
+
path2.resolve(cwd, configuredIndexDir, "manifest.json"),
|
|
366
|
+
path2.resolve(cwd, ".kb/mind/indexes", scopeId, "manifest.json"),
|
|
367
|
+
path2.resolve(cwd, ".kb/mind/rag", scopeId, "manifest.json")
|
|
368
|
+
];
|
|
369
|
+
for (const manifestPath of candidatePaths) {
|
|
370
|
+
try {
|
|
371
|
+
const manifest = await loadManifest(manifestPath);
|
|
372
|
+
const indexRevision = manifest.indexRevision;
|
|
373
|
+
const engineConfigHash = manifest.engineConfigHash;
|
|
374
|
+
const sourcesDigest = manifest.sourcesDigest;
|
|
375
|
+
if (typeof indexRevision !== "string" || indexRevision.length === 0) {
|
|
376
|
+
throw new Error("missing indexRevision");
|
|
377
|
+
}
|
|
378
|
+
if (typeof engineConfigHash !== "string" || engineConfigHash.length === 0) {
|
|
379
|
+
throw new Error("missing engineConfigHash");
|
|
380
|
+
}
|
|
381
|
+
if (typeof sourcesDigest !== "string" || sourcesDigest.length === 0) {
|
|
382
|
+
throw new Error("missing sourcesDigest");
|
|
383
|
+
}
|
|
384
|
+
return {
|
|
385
|
+
found: true,
|
|
386
|
+
indexRevision,
|
|
387
|
+
engineConfigHash,
|
|
388
|
+
sourcesDigest
|
|
389
|
+
};
|
|
390
|
+
} catch (error) {
|
|
391
|
+
const code = error?.code;
|
|
392
|
+
if (code === "ENOENT") {
|
|
393
|
+
continue;
|
|
394
|
+
}
|
|
395
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
396
|
+
throw new Error(`Invalid index manifest at ${manifestPath}: ${message}`);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
return { found: false };
|
|
400
|
+
}
|
|
401
|
+
function sanitizeEngineOptionsForHash(options) {
|
|
402
|
+
const {
|
|
403
|
+
_runtime: _runtimeIgnored,
|
|
404
|
+
onProgress: _onProgressIgnored,
|
|
405
|
+
platform: _platformIgnored,
|
|
406
|
+
...rest
|
|
407
|
+
} = options;
|
|
408
|
+
return rest;
|
|
409
|
+
}
|
|
410
|
+
function stableStringify(value) {
|
|
411
|
+
return JSON.stringify(sortObjectDeep(value));
|
|
412
|
+
}
|
|
413
|
+
function sortObjectDeep(value) {
|
|
414
|
+
if (Array.isArray(value)) {
|
|
415
|
+
return value.map(sortObjectDeep);
|
|
416
|
+
}
|
|
417
|
+
if (value && typeof value === "object") {
|
|
418
|
+
const entries = Object.entries(value).sort(([a], [b]) => a.localeCompare(b)).map(([key, val]) => [key, sortObjectDeep(val)]);
|
|
419
|
+
return Object.fromEntries(entries);
|
|
420
|
+
}
|
|
421
|
+
return value;
|
|
422
|
+
}
|
|
423
|
+
var VALID_INTENTS = ["summary", "search", "similar", "nav"];
|
|
424
|
+
var VALID_MODES = ["instant", "auto", "thinking"];
|
|
425
|
+
var VALID_FORMATS = ["text", "json", "json-pretty"];
|
|
426
|
+
function isValidIntent(intent) {
|
|
427
|
+
return VALID_INTENTS.includes(intent);
|
|
428
|
+
}
|
|
429
|
+
function isValidMode(mode) {
|
|
430
|
+
return VALID_MODES.includes(mode);
|
|
431
|
+
}
|
|
432
|
+
function isValidFormat(format) {
|
|
433
|
+
return VALID_FORMATS.includes(format);
|
|
434
|
+
}
|
|
435
|
+
function truncateText(text, limit) {
|
|
436
|
+
if (text.length <= limit) {
|
|
437
|
+
return text;
|
|
438
|
+
}
|
|
439
|
+
return `${text.slice(0, limit - 3)}...`;
|
|
440
|
+
}
|
|
441
|
+
var rag_query_default = defineCommand({
|
|
442
|
+
id: "mind:rag-query",
|
|
443
|
+
description: "Run semantic RAG query on Mind index",
|
|
444
|
+
handler: {
|
|
445
|
+
async execute(ctx, input) {
|
|
446
|
+
const startTime = Date.now();
|
|
447
|
+
const { flags } = input;
|
|
448
|
+
const cwd = flags.cwd || ctx.cwd;
|
|
449
|
+
const scopeId = flags.scope;
|
|
450
|
+
const intent = flags.intent && isValidIntent(flags.intent) ? flags.intent : void 0;
|
|
451
|
+
const text = flags.text?.trim() || "";
|
|
452
|
+
const limit = flags.limit ? Math.max(1, flags.limit) : void 0;
|
|
453
|
+
const profileId = flags.profile;
|
|
454
|
+
const platform = usePlatform();
|
|
455
|
+
const mode = flags.mode && isValidMode(flags.mode) ? flags.mode : "auto";
|
|
456
|
+
let format = flags.format && isValidFormat(flags.format) ? flags.format : "text";
|
|
457
|
+
if (flags.json && format === "text") {
|
|
458
|
+
format = "json";
|
|
459
|
+
}
|
|
460
|
+
if (!text) {
|
|
461
|
+
if (flags.agent) {
|
|
462
|
+
console.log(JSON.stringify({
|
|
463
|
+
error: {
|
|
464
|
+
code: "INVALID_QUERY",
|
|
465
|
+
message: 'Provide --text "<query>" to run rag:query.',
|
|
466
|
+
recoverable: false
|
|
467
|
+
},
|
|
468
|
+
meta: {
|
|
469
|
+
schemaVersion: "agent-response-v1",
|
|
470
|
+
requestId: `rq-${Date.now()}`,
|
|
471
|
+
mode,
|
|
472
|
+
timingMs: 0,
|
|
473
|
+
cached: false
|
|
474
|
+
}
|
|
475
|
+
}));
|
|
476
|
+
ctx.trace?.addEvent?.("mind.rag-query.invalid", { reason: "missing-text" });
|
|
477
|
+
return { exitCode: 1, ok: false };
|
|
478
|
+
}
|
|
479
|
+
ctx.ui.error('Provide --text "<query>" to run rag:query.');
|
|
480
|
+
ctx.ui.info('Use: kb mind rag-query --text "your query"');
|
|
481
|
+
ctx.ui.info("Add --scope to search in specific scope");
|
|
482
|
+
ctx.ui.info("Add --intent to specify intent (summary, search, similar, nav)");
|
|
483
|
+
ctx.trace?.addEvent?.("mind.rag-query.invalid", { reason: "missing-text" });
|
|
484
|
+
return { exitCode: 1, ok: false };
|
|
485
|
+
}
|
|
486
|
+
if (flags.agent) {
|
|
487
|
+
try {
|
|
488
|
+
const result = await runAgentRagQuery({
|
|
489
|
+
cwd,
|
|
490
|
+
scopeId,
|
|
491
|
+
text,
|
|
492
|
+
mode,
|
|
493
|
+
debug: flags.debug,
|
|
494
|
+
broker: void 0,
|
|
495
|
+
// Gracefully falls back to in-memory
|
|
496
|
+
platform
|
|
497
|
+
// Pass platform for analytics adapter
|
|
498
|
+
});
|
|
499
|
+
platform?.analytics?.track?.("mind.rag-query", {
|
|
500
|
+
mode,
|
|
501
|
+
agent: true,
|
|
502
|
+
scopeId,
|
|
503
|
+
intent
|
|
504
|
+
}).catch(() => {
|
|
505
|
+
});
|
|
506
|
+
console.log(JSON.stringify(result));
|
|
507
|
+
if (isAgentError(result)) {
|
|
508
|
+
return { exitCode: 1, ok: false, result };
|
|
509
|
+
}
|
|
510
|
+
return { exitCode: 0, ok: true, result };
|
|
511
|
+
} catch (error) {
|
|
512
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
513
|
+
console.log(JSON.stringify({
|
|
514
|
+
error: {
|
|
515
|
+
code: "ENGINE_ERROR",
|
|
516
|
+
message,
|
|
517
|
+
recoverable: true
|
|
518
|
+
},
|
|
519
|
+
meta: {
|
|
520
|
+
schemaVersion: "agent-response-v1",
|
|
521
|
+
requestId: `rq-${Date.now()}`,
|
|
522
|
+
mode,
|
|
523
|
+
timingMs: Date.now() - startTime,
|
|
524
|
+
cached: false
|
|
525
|
+
}
|
|
526
|
+
}));
|
|
527
|
+
ctx.trace?.addEvent?.("mind.rag-query.agent.error", { error: message });
|
|
528
|
+
return { exitCode: 1, ok: false };
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
if (!flags.quiet && format === "text") {
|
|
532
|
+
ctx.ui.info("Initializing Mind RAG query...");
|
|
533
|
+
}
|
|
534
|
+
const formatElapsedTime = (ms) => {
|
|
535
|
+
const seconds = Math.floor(ms / 1e3);
|
|
536
|
+
if (seconds < 60) {
|
|
537
|
+
return `${seconds}s`;
|
|
538
|
+
}
|
|
539
|
+
const minutes = Math.floor(seconds / 60);
|
|
540
|
+
const remainingSeconds = seconds % 60;
|
|
541
|
+
return `${minutes}m ${remainingSeconds}s`;
|
|
542
|
+
};
|
|
543
|
+
let currentStage = "Initializing";
|
|
544
|
+
let lastProgressTime = Date.now();
|
|
545
|
+
try {
|
|
546
|
+
const result = await runRagQuery({
|
|
547
|
+
cwd,
|
|
548
|
+
scopeId,
|
|
549
|
+
text,
|
|
550
|
+
intent,
|
|
551
|
+
limit,
|
|
552
|
+
profileId,
|
|
553
|
+
platform,
|
|
554
|
+
// Pass platform for analytics adapter
|
|
555
|
+
runtime: void 0,
|
|
556
|
+
// Runtime context not available in CLI
|
|
557
|
+
onProgress: (stage, details) => {
|
|
558
|
+
if (flags.quiet || format === "json" || format === "json-pretty") {
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
561
|
+
currentStage = details ? `${stage}: ${details}` : stage;
|
|
562
|
+
const now = Date.now();
|
|
563
|
+
if (now - lastProgressTime >= 1e3) {
|
|
564
|
+
const elapsed = now - startTime;
|
|
565
|
+
const elapsedStr = formatElapsedTime(elapsed);
|
|
566
|
+
ctx.ui.info(`${currentStage} [${elapsedStr}]`);
|
|
567
|
+
lastProgressTime = now;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
});
|
|
571
|
+
const timing = Date.now() - startTime;
|
|
572
|
+
ctx.trace?.addEvent?.("mind.rag-query.complete", {
|
|
573
|
+
mode,
|
|
574
|
+
scopeId,
|
|
575
|
+
chunks: result.result.chunks.length,
|
|
576
|
+
timingMs: timing
|
|
577
|
+
});
|
|
578
|
+
if (format === "json" || format === "json-pretty") {
|
|
579
|
+
if (result.result.metadata?.jsonResponse) {
|
|
580
|
+
const jsonResponse = result.result.metadata.jsonResponse;
|
|
581
|
+
if (format === "json-pretty") {
|
|
582
|
+
ctx.ui.info(JSON.stringify(jsonResponse, null, 2));
|
|
583
|
+
} else {
|
|
584
|
+
ctx.ui.info(JSON.stringify(jsonResponse));
|
|
585
|
+
}
|
|
586
|
+
} else {
|
|
587
|
+
ctx.ui.info(JSON.stringify({
|
|
588
|
+
ok: true,
|
|
589
|
+
scopeId: result.scopeId,
|
|
590
|
+
intent: result.result.query.intent,
|
|
591
|
+
chunks: result.result.chunks,
|
|
592
|
+
contextText: result.result.contextText
|
|
593
|
+
}));
|
|
594
|
+
}
|
|
595
|
+
} else if (!flags.quiet) {
|
|
596
|
+
const topChunk = result.result.chunks[0];
|
|
597
|
+
const sections = [
|
|
598
|
+
{
|
|
599
|
+
header: "Summary",
|
|
600
|
+
items: [
|
|
601
|
+
`Scope: ${result.scopeId}`,
|
|
602
|
+
`Intent: ${result.result.query.intent}`,
|
|
603
|
+
`Chunks returned: ${result.result.chunks.length}`
|
|
604
|
+
]
|
|
605
|
+
}
|
|
606
|
+
];
|
|
607
|
+
if (topChunk) {
|
|
608
|
+
sections.push({
|
|
609
|
+
header: "Top chunk",
|
|
610
|
+
items: [
|
|
611
|
+
`${topChunk.path} #${topChunk.span.startLine}-${topChunk.span.endLine}`,
|
|
612
|
+
truncateText(topChunk.text, 400)
|
|
613
|
+
]
|
|
614
|
+
});
|
|
615
|
+
} else {
|
|
616
|
+
sections.push({
|
|
617
|
+
items: ["No matching chunks found."]
|
|
618
|
+
});
|
|
619
|
+
}
|
|
620
|
+
if (result.result.contextText && result.result.contextText.length > 0) {
|
|
621
|
+
const contextPreview = result.result.contextText.length > 2e3 ? result.result.contextText.substring(0, 2e3) + "..." : result.result.contextText;
|
|
622
|
+
sections.push({
|
|
623
|
+
header: `Synthesized context (${result.result.contextText.length} chars)`,
|
|
624
|
+
items: [contextPreview]
|
|
625
|
+
});
|
|
626
|
+
}
|
|
627
|
+
ctx.ui.success("Query completed", {
|
|
628
|
+
title: "Mind RAG Query",
|
|
629
|
+
sections,
|
|
630
|
+
timing
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
platform?.analytics?.track?.("mind.rag-query", {
|
|
634
|
+
mode,
|
|
635
|
+
agent: false,
|
|
636
|
+
scopeId,
|
|
637
|
+
intent
|
|
638
|
+
}).catch(() => {
|
|
639
|
+
});
|
|
640
|
+
return { exitCode: 0, ok: true, result };
|
|
641
|
+
} catch (error) {
|
|
642
|
+
const timing = Date.now() - startTime;
|
|
643
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
644
|
+
ctx.trace?.addEvent?.("mind.rag-query.error", { error: message, timingMs: timing });
|
|
645
|
+
if (format === "json" || format === "json-pretty") {
|
|
646
|
+
ctx.ui.info(JSON.stringify({
|
|
647
|
+
ok: false,
|
|
648
|
+
error: message,
|
|
649
|
+
timingMs: timing
|
|
650
|
+
}));
|
|
651
|
+
} else if (!flags.quiet) {
|
|
652
|
+
ctx.ui.error(`Query failed: ${message}`);
|
|
653
|
+
}
|
|
654
|
+
platform?.analytics?.track?.("mind.rag-query", {
|
|
655
|
+
mode,
|
|
656
|
+
agent: false,
|
|
657
|
+
scopeId,
|
|
658
|
+
intent,
|
|
659
|
+
error: true
|
|
660
|
+
}).catch(() => {
|
|
661
|
+
});
|
|
662
|
+
return { exitCode: 1, ok: false };
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
});
|
|
667
|
+
|
|
668
|
+
export { rag_query_default as default };
|
|
669
|
+
//# sourceMappingURL=rag-query.js.map
|
|
670
|
+
//# sourceMappingURL=rag-query.js.map
|