@coreyuan/vector-mind 1.0.38 → 1.0.39
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 +44 -10
- package/dist/builtin-conventions.js +5 -0
- package/dist/builtin-conventions.js.map +1 -1
- package/dist/builtin-instructions.d.ts +1 -0
- package/dist/builtin-instructions.js +1 -0
- package/dist/builtin-instructions.js.map +1 -1
- package/dist/index.js +689 -163
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -14,9 +14,9 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
14
14
|
import { toJsonSchemaCompat } from "@modelcontextprotocol/sdk/server/zod-json-schema-compat.js";
|
|
15
15
|
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
16
16
|
import { BUILTIN_CONVENTIONS } from "./builtin-conventions.js";
|
|
17
|
-
import { BUILTIN_ARCHITECTURE_AND_CODE_ORGANIZATION_INSTRUCTIONS, BUILTIN_DESTRUCTIVE_OPERATION_GUARD_INSTRUCTIONS, BUILTIN_FRONTEND_OUTPUT_PURITY_INSTRUCTIONS, BUILTIN_LOW_OVERHEAD_WORKFLOW_INSTRUCTIONS, BUILTIN_PAYLOAD_GUARD_INSTRUCTIONS, BUILTIN_PLAN_LITE_INSTRUCTIONS, BUILTIN_THREAD_HANDOFF_SWITCH_INSTRUCTIONS, BUILTIN_WRITE_POLICY_INSTRUCTIONS, } from "./builtin-instructions.js";
|
|
17
|
+
import { BUILTIN_ARCHITECTURE_AND_CODE_ORGANIZATION_INSTRUCTIONS, BUILTIN_DESTRUCTIVE_OPERATION_GUARD_INSTRUCTIONS, BUILTIN_FRONTEND_OUTPUT_PURITY_INSTRUCTIONS, BUILTIN_GIT_COMMIT_SUMMARY_INSTRUCTIONS, BUILTIN_LOW_OVERHEAD_WORKFLOW_INSTRUCTIONS, BUILTIN_PAYLOAD_GUARD_INSTRUCTIONS, BUILTIN_PLAN_LITE_INSTRUCTIONS, BUILTIN_THREAD_HANDOFF_SWITCH_INSTRUCTIONS, BUILTIN_WRITE_POLICY_INSTRUCTIONS, } from "./builtin-instructions.js";
|
|
18
18
|
const SERVER_NAME = "vector-mind";
|
|
19
|
-
const SERVER_VERSION = "1.0.
|
|
19
|
+
const SERVER_VERSION = "1.0.39";
|
|
20
20
|
const rootFromEnv = process.env.VECTORMIND_ROOT?.trim() ?? "";
|
|
21
21
|
const prettyJsonOutput = ["1", "true", "on", "yes"].includes((process.env.VECTORMIND_PRETTY_JSON ?? "").trim().toLowerCase());
|
|
22
22
|
const debugLogEnabled = ["1", "true", "on", "yes"].includes((process.env.VECTORMIND_DEBUG_LOG ?? "").trim().toLowerCase());
|
|
@@ -181,6 +181,10 @@ let deleteOldestPendingChangesStmt = null;
|
|
|
181
181
|
let deleteSymbolsForFileStmt;
|
|
182
182
|
let upsertSymbolStmt;
|
|
183
183
|
let searchSymbolsStmt;
|
|
184
|
+
let insertTokenSavingsStmt;
|
|
185
|
+
let summarizeTokenSavingsStmt;
|
|
186
|
+
let summarizeTokenSavingsByToolStmt;
|
|
187
|
+
let listRecentTokenSavingsStmt;
|
|
184
188
|
let indexFileSymbolsTx = null;
|
|
185
189
|
let activitySeq = 0;
|
|
186
190
|
const activityLog = [];
|
|
@@ -1149,6 +1153,9 @@ function removeFileIndexes(absPath) {
|
|
|
1149
1153
|
const ProjectRootArgSchema = z.object({
|
|
1150
1154
|
project_root: z.string().optional(),
|
|
1151
1155
|
});
|
|
1156
|
+
const OutputFormatSchema = z.object({
|
|
1157
|
+
format: z.enum(["compact", "json"]).optional().default("compact"),
|
|
1158
|
+
});
|
|
1152
1159
|
const StartRequirementArgsSchema = ProjectRootArgSchema.merge(z.object({
|
|
1153
1160
|
title: z.string().min(1),
|
|
1154
1161
|
background: z.string().optional().default(""),
|
|
@@ -1159,10 +1166,10 @@ const SyncChangeIntentArgsSchema = ProjectRootArgSchema.merge(z.object({
|
|
|
1159
1166
|
files: z.array(z.string().min(1)).optional(),
|
|
1160
1167
|
affected_files: z.array(z.string().min(1)).optional(),
|
|
1161
1168
|
}));
|
|
1162
|
-
const QueryCodebaseArgsSchema = ProjectRootArgSchema.merge(z.object({
|
|
1169
|
+
const QueryCodebaseArgsSchema = ProjectRootArgSchema.merge(OutputFormatSchema).merge(z.object({
|
|
1163
1170
|
query: z.string().min(1),
|
|
1164
1171
|
}));
|
|
1165
|
-
const GrepArgsSchema = ProjectRootArgSchema.merge(z.object({
|
|
1172
|
+
const GrepArgsSchema = ProjectRootArgSchema.merge(OutputFormatSchema).merge(z.object({
|
|
1166
1173
|
// Pattern to search for. Defaults to regex mode for parity with tools like ripgrep.
|
|
1167
1174
|
query: z.string().min(1),
|
|
1168
1175
|
mode: z.enum(["regex", "literal"]).optional().default("regex"),
|
|
@@ -1179,7 +1186,7 @@ const GrepArgsSchema = ProjectRootArgSchema.merge(z.object({
|
|
|
1179
1186
|
// Compatibility knob for the indexed fallback when ripgrep is unavailable.
|
|
1180
1187
|
max_candidates: z.number().int().min(1).max(50_000).optional(),
|
|
1181
1188
|
}));
|
|
1182
|
-
const ReadFileLinesArgsSchema = ProjectRootArgSchema.merge(z.object({
|
|
1189
|
+
const ReadFileLinesArgsSchema = ProjectRootArgSchema.merge(OutputFormatSchema).merge(z.object({
|
|
1183
1190
|
// Relative to project_root, or an absolute path under project_root.
|
|
1184
1191
|
path: z.string().min(1),
|
|
1185
1192
|
from_line: z.number().int().min(1).optional().default(1),
|
|
@@ -1190,7 +1197,7 @@ const ReadFileLinesArgsSchema = ProjectRootArgSchema.merge(z.object({
|
|
|
1190
1197
|
max_lines: z.number().int().min(1).max(2000).optional().default(400),
|
|
1191
1198
|
max_chars: z.number().int().min(200).max(200_000).optional().default(20_000),
|
|
1192
1199
|
}));
|
|
1193
|
-
const ReadFileTextArgsSchema = ProjectRootArgSchema.merge(z.object({
|
|
1200
|
+
const ReadFileTextArgsSchema = ProjectRootArgSchema.merge(OutputFormatSchema).merge(z.object({
|
|
1194
1201
|
// Relative to project_root, or an absolute path under project_root.
|
|
1195
1202
|
path: z.string().min(1),
|
|
1196
1203
|
// Character offset in the decoded UTF-8 text.
|
|
@@ -1200,14 +1207,14 @@ const ReadFileTextArgsSchema = ProjectRootArgSchema.merge(z.object({
|
|
|
1200
1207
|
// Safety guard for raw reads; use read_file_lines on larger files.
|
|
1201
1208
|
max_file_bytes: z.number().int().min(1_000).max(5_000_000).optional().default(1_000_000),
|
|
1202
1209
|
}));
|
|
1203
|
-
const ReadCodexTextFileArgsSchema = ProjectRootArgSchema.merge(z.object({
|
|
1210
|
+
const ReadCodexTextFileArgsSchema = ProjectRootArgSchema.merge(OutputFormatSchema).merge(z.object({
|
|
1204
1211
|
// Absolute path, file:// URI, or a path under CODEX_HOME / AGENTS_HOME allowed roots.
|
|
1205
1212
|
path: z.string().min(1),
|
|
1206
1213
|
offset: z.number().int().min(0).optional().default(0),
|
|
1207
1214
|
max_chars: z.number().int().min(1).max(200_000).optional().default(20_000),
|
|
1208
1215
|
max_file_bytes: z.number().int().min(1_000).max(5_000_000).optional().default(1_000_000),
|
|
1209
1216
|
}));
|
|
1210
|
-
const ListProjectFilesArgsSchema = ProjectRootArgSchema.merge(z.object({
|
|
1217
|
+
const ListProjectFilesArgsSchema = ProjectRootArgSchema.merge(OutputFormatSchema).merge(z.object({
|
|
1211
1218
|
// Relative directory/file path under project_root. "." means the project root.
|
|
1212
1219
|
path: z.string().optional().default("."),
|
|
1213
1220
|
recursive: z.boolean().optional().default(false),
|
|
@@ -1242,24 +1249,24 @@ const UpsertConventionArgsSchema = ProjectRootArgSchema.merge(z.object({
|
|
|
1242
1249
|
content: z.string().min(1),
|
|
1243
1250
|
tags: z.array(z.string().min(1)).optional(),
|
|
1244
1251
|
}));
|
|
1245
|
-
const DEFAULT_PENDING_LIMIT =
|
|
1252
|
+
const DEFAULT_PENDING_LIMIT = 10;
|
|
1246
1253
|
const MAX_PENDING_LIMIT = 2000;
|
|
1247
1254
|
const PendingPagingSchema = z.object({
|
|
1248
1255
|
pending_offset: z.number().int().min(0).optional().default(0),
|
|
1249
1256
|
pending_limit: z.number().int().min(1).max(MAX_PENDING_LIMIT).optional().default(DEFAULT_PENDING_LIMIT),
|
|
1250
1257
|
});
|
|
1251
|
-
const DEFAULT_PREVIEW_CHARS =
|
|
1258
|
+
const DEFAULT_PREVIEW_CHARS = 120;
|
|
1252
1259
|
const PreviewSchema = z.object({
|
|
1253
1260
|
preview_chars: z.number().int().min(50).max(10_000).optional().default(DEFAULT_PREVIEW_CHARS),
|
|
1254
1261
|
});
|
|
1255
|
-
const DEFAULT_CONTENT_MAX_CHARS =
|
|
1262
|
+
const DEFAULT_CONTENT_MAX_CHARS = 1200;
|
|
1256
1263
|
const ContentMaxSchema = z.object({
|
|
1257
1264
|
content_max_chars: z.number().int().min(0).max(200_000).optional().default(DEFAULT_CONTENT_MAX_CHARS),
|
|
1258
1265
|
});
|
|
1259
|
-
const DEFAULT_RECENT_REQUIREMENTS =
|
|
1260
|
-
const DEFAULT_RECENT_CHANGES_PER_REQ =
|
|
1261
|
-
const DEFAULT_RECENT_NOTES =
|
|
1262
|
-
const DEFAULT_CONVENTIONS_LIMIT =
|
|
1266
|
+
const DEFAULT_RECENT_REQUIREMENTS = 2;
|
|
1267
|
+
const DEFAULT_RECENT_CHANGES_PER_REQ = 3;
|
|
1268
|
+
const DEFAULT_RECENT_NOTES = 3;
|
|
1269
|
+
const DEFAULT_CONVENTIONS_LIMIT = 0;
|
|
1263
1270
|
const BrainDumpLimitsSchema = z.object({
|
|
1264
1271
|
requirements_limit: z.number().int().min(1).max(20).optional().default(DEFAULT_RECENT_REQUIREMENTS),
|
|
1265
1272
|
changes_limit: z.number().int().min(1).max(100).optional().default(DEFAULT_RECENT_CHANGES_PER_REQ),
|
|
@@ -1285,6 +1292,7 @@ const GetActivitySummaryArgsSchema = ProjectRootArgSchema.merge(z.object({
|
|
|
1285
1292
|
}));
|
|
1286
1293
|
const ClearActivityLogArgsSchema = ProjectRootArgSchema;
|
|
1287
1294
|
const GetBrainDumpArgsSchema = ProjectRootArgSchema.merge(PendingPagingSchema)
|
|
1295
|
+
.merge(OutputFormatSchema)
|
|
1288
1296
|
.merge(PreviewSchema)
|
|
1289
1297
|
.merge(ContentMaxSchema)
|
|
1290
1298
|
.merge(BrainDumpLimitsSchema)
|
|
@@ -1293,16 +1301,17 @@ const GetBrainDumpArgsSchema = ProjectRootArgSchema.merge(PendingPagingSchema)
|
|
|
1293
1301
|
}));
|
|
1294
1302
|
const BootstrapContextArgsSchema = ProjectRootArgSchema.merge(z.object({
|
|
1295
1303
|
query: z.string().optional(),
|
|
1296
|
-
top_k: z.number().int().min(1).max(50).optional().default(
|
|
1304
|
+
top_k: z.number().int().min(1).max(50).optional().default(3),
|
|
1297
1305
|
kinds: z.array(z.string().min(1)).optional(),
|
|
1298
1306
|
include_content: z.boolean().optional().default(false),
|
|
1299
1307
|
pending_offset: z.number().int().min(0).optional().default(0),
|
|
1300
1308
|
pending_limit: z.number().int().min(1).max(MAX_PENDING_LIMIT).optional().default(DEFAULT_PENDING_LIMIT),
|
|
1301
1309
|
})
|
|
1310
|
+
.merge(OutputFormatSchema)
|
|
1302
1311
|
.merge(PreviewSchema)
|
|
1303
1312
|
.merge(ContentMaxSchema)
|
|
1304
1313
|
.merge(BrainDumpLimitsSchema));
|
|
1305
|
-
const SemanticSearchArgsSchema = ProjectRootArgSchema.merge(z.object({
|
|
1314
|
+
const SemanticSearchArgsSchema = ProjectRootArgSchema.merge(OutputFormatSchema).merge(z.object({
|
|
1306
1315
|
query: z.string().min(1),
|
|
1307
1316
|
top_k: z.number().int().min(1).max(50).optional().default(8),
|
|
1308
1317
|
kinds: z.array(z.string().min(1)).optional(),
|
|
@@ -1311,6 +1320,21 @@ const SemanticSearchArgsSchema = ProjectRootArgSchema.merge(z.object({
|
|
|
1311
1320
|
content_max_chars: z.number().int().min(0).max(200_000).optional().default(DEFAULT_CONTENT_MAX_CHARS),
|
|
1312
1321
|
}));
|
|
1313
1322
|
const ProjectRootOnlyArgsSchema = ProjectRootArgSchema;
|
|
1323
|
+
const GetTokenSavingsArgsSchema = ProjectRootArgSchema.merge(z.object({
|
|
1324
|
+
limit: z.number().int().min(1).max(100).optional().default(10),
|
|
1325
|
+
format: z.enum(["compact", "json"]).optional().default("compact"),
|
|
1326
|
+
}));
|
|
1327
|
+
const DetectRtkArgsSchema = ProjectRootArgSchema;
|
|
1328
|
+
const InstallRtkArgsSchema = ProjectRootArgSchema.merge(z.object({
|
|
1329
|
+
dry_run: z.boolean().optional().default(true),
|
|
1330
|
+
method: z.enum(["auto", "cargo", "brew", "shell_script"]).optional().default("auto"),
|
|
1331
|
+
init: z
|
|
1332
|
+
.enum(["none", "global_no_patch", "global_auto_patch", "global_hook_only", "local"])
|
|
1333
|
+
.optional()
|
|
1334
|
+
.default("none"),
|
|
1335
|
+
uninstall_wrong_cargo_rtk: z.boolean().optional().default(false),
|
|
1336
|
+
timeout_ms: z.number().int().min(10_000).max(1_800_000).optional().default(600_000),
|
|
1337
|
+
}));
|
|
1314
1338
|
const ReadMemoryItemArgsSchema = ProjectRootArgSchema.merge(z.object({
|
|
1315
1339
|
id: z.number().int().positive(),
|
|
1316
1340
|
offset: z.number().int().min(0).optional().default(0),
|
|
@@ -1335,6 +1359,408 @@ function safeJson(value) {
|
|
|
1335
1359
|
function toolJson(value) {
|
|
1336
1360
|
return JSON.stringify(value, null, prettyJsonOutput ? 2 : undefined);
|
|
1337
1361
|
}
|
|
1362
|
+
function estimateTokens(text) {
|
|
1363
|
+
if (!text)
|
|
1364
|
+
return 0;
|
|
1365
|
+
return Math.ceil(text.length / 4);
|
|
1366
|
+
}
|
|
1367
|
+
function recordTokenSavings(tool, rawText, outputText) {
|
|
1368
|
+
if (!db || !insertTokenSavingsStmt)
|
|
1369
|
+
return;
|
|
1370
|
+
const rawTokens = estimateTokens(rawText);
|
|
1371
|
+
const outputTokens = estimateTokens(outputText);
|
|
1372
|
+
const savedTokens = Math.max(0, rawTokens - outputTokens);
|
|
1373
|
+
const savingsPct = rawTokens > 0 ? (savedTokens / rawTokens) * 100 : 0;
|
|
1374
|
+
try {
|
|
1375
|
+
insertTokenSavingsStmt.run(tool, rawTokens, outputTokens, savedTokens, savingsPct);
|
|
1376
|
+
}
|
|
1377
|
+
catch (err) {
|
|
1378
|
+
console.error("[vectormind] token savings record failed:", err);
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
function toolText(tool, rawValue, compactText, format = "compact") {
|
|
1382
|
+
const rawText = toolJson(rawValue);
|
|
1383
|
+
if (format === "json")
|
|
1384
|
+
return rawText;
|
|
1385
|
+
recordTokenSavings(tool, rawText, compactText);
|
|
1386
|
+
return compactText;
|
|
1387
|
+
}
|
|
1388
|
+
function toolCompactOrJson(tool, rawValue, compactText, format) {
|
|
1389
|
+
return toolText(tool, rawValue, compactText, format);
|
|
1390
|
+
}
|
|
1391
|
+
function oneLine(input, max = 120) {
|
|
1392
|
+
const text = (input ?? "").replace(/\s+/g, " ").trim();
|
|
1393
|
+
if (text.length <= max)
|
|
1394
|
+
return text;
|
|
1395
|
+
return `${text.slice(0, Math.max(0, max - 3))}...`;
|
|
1396
|
+
}
|
|
1397
|
+
function compactMemoryLabel(item, max = 120) {
|
|
1398
|
+
const title = item.title ? ` ${oneLine(item.title, 48)}` : "";
|
|
1399
|
+
const loc = item.file_path ? ` ${item.file_path}${item.start_line != null ? `:${item.start_line}` : ""}` : "";
|
|
1400
|
+
const body = item.preview ? ` — ${oneLine(item.preview, max)}` : "";
|
|
1401
|
+
return `#${item.id} ${item.kind}${title}${loc}${body}`;
|
|
1402
|
+
}
|
|
1403
|
+
function compactRequirementLabel(req) {
|
|
1404
|
+
const ctx = req.context_preview ? ` — ${oneLine(req.context_preview, 100)}` : "";
|
|
1405
|
+
const mem = req.memory_item_id ? ` mem#${req.memory_item_id}` : "";
|
|
1406
|
+
return `req#${req.id}${mem} [${req.status}] ${oneLine(req.title, 80)}${ctx}`;
|
|
1407
|
+
}
|
|
1408
|
+
function compactChangeLabel(change) {
|
|
1409
|
+
return `change#${change.id} ${change.file_path}: ${oneLine(change.intent_preview, 120)}`;
|
|
1410
|
+
}
|
|
1411
|
+
function compactPendingLabel(p) {
|
|
1412
|
+
return `${p.last_event} ${p.file_path}`;
|
|
1413
|
+
}
|
|
1414
|
+
function compactSemanticSearchText(data) {
|
|
1415
|
+
const lines = [
|
|
1416
|
+
`semantic ${data.mode} ${data.matches.length}/${data.top_k} q="${oneLine(data.query, 100)}"`,
|
|
1417
|
+
];
|
|
1418
|
+
for (const m of data.matches.slice(0, data.top_k)) {
|
|
1419
|
+
lines.push(`- score=${m.score.toFixed(3)} ${compactMemoryLabel(m.item, 160)}`);
|
|
1420
|
+
}
|
|
1421
|
+
if (!data.matches.length)
|
|
1422
|
+
lines.push("- no matches");
|
|
1423
|
+
lines.push("hint: use format=json for full metadata; read_memory_item(id) for full content");
|
|
1424
|
+
return lines.join("\n");
|
|
1425
|
+
}
|
|
1426
|
+
function compactGrepText(data) {
|
|
1427
|
+
const total = data.total_matches ?? data.matches.length;
|
|
1428
|
+
const fallback = data.fallback_reason ? ` fallback=${data.fallback_reason}` : "";
|
|
1429
|
+
const candidateText = data.candidates ? ` candidates=${data.candidates.scanned}/${data.candidates.total}` : "";
|
|
1430
|
+
const lines = [
|
|
1431
|
+
`grep ${data.backend}${fallback} mode=${data.mode} matches=${data.matches.length}/${total} truncated=${data.truncated}${candidateText} q="${oneLine(data.query, 100)}"`,
|
|
1432
|
+
];
|
|
1433
|
+
if (data.ripgrep_error)
|
|
1434
|
+
lines.push(`ripgrep_error ${oneLine(data.ripgrep_error, 180)}`);
|
|
1435
|
+
for (const m of data.matches.slice(0, 80)) {
|
|
1436
|
+
lines.push(`${m.file_path}:${m.line}:${m.col}: ${oneLine(m.preview, 220)}`);
|
|
1437
|
+
}
|
|
1438
|
+
if (!data.matches.length)
|
|
1439
|
+
lines.push("- no matches");
|
|
1440
|
+
if (data.truncated)
|
|
1441
|
+
lines.push("hint: refine query/include_paths or raise max_results; use format=json for full match objects");
|
|
1442
|
+
return lines.join("\n");
|
|
1443
|
+
}
|
|
1444
|
+
function compactListProjectFilesText(data) {
|
|
1445
|
+
const lines = [
|
|
1446
|
+
`files path=${data.path} kind=${data.path_kind} returned=${data.returned} scanned=${data.scanned} recursive=${data.recursive} depth=${data.max_depth} truncated=${data.truncated}`,
|
|
1447
|
+
];
|
|
1448
|
+
for (const e of data.entries.slice(0, 200)) {
|
|
1449
|
+
const stat = e.size != null ? ` ${e.size}B` : "";
|
|
1450
|
+
lines.push(`${e.kind === "dir" ? "d" : "f"} ${e.path}${stat}`);
|
|
1451
|
+
}
|
|
1452
|
+
if (!data.entries.length)
|
|
1453
|
+
lines.push("- empty");
|
|
1454
|
+
if (data.truncated)
|
|
1455
|
+
lines.push("hint: narrow path/filters or raise max_results; use format=json for full entry metadata");
|
|
1456
|
+
return lines.join("\n");
|
|
1457
|
+
}
|
|
1458
|
+
function compactReadTextFileText(data) {
|
|
1459
|
+
const offset = data.offset != null ? ` offset=${data.offset}` : "";
|
|
1460
|
+
const header = `file ${data.file_path}${offset} chars=${data.returned_chars}/${data.total_chars} truncated=${data.truncated}`;
|
|
1461
|
+
const hint = data.truncated ? "\nhint: continue with offset or read_file_lines; use format=json for metadata fields" : "";
|
|
1462
|
+
return `${header}\n${data.text}${hint}`;
|
|
1463
|
+
}
|
|
1464
|
+
function compactReadFileLinesText(data) {
|
|
1465
|
+
const header = `lines ${data.file_path}:${data.from_line}-${data.to_line} returned=${data.returned} truncated=${data.truncated}`;
|
|
1466
|
+
const hint = data.truncated ? "\nhint: narrow range or raise max_lines/max_chars; use format=json for metadata fields" : "";
|
|
1467
|
+
return `${header}\n${data.text}${hint}`;
|
|
1468
|
+
}
|
|
1469
|
+
function compactQueryCodebaseText(data) {
|
|
1470
|
+
const lines = [`query_codebase matches=${data.matches.length} q="${oneLine(data.query, 100)}"`];
|
|
1471
|
+
for (const m of data.matches.slice(0, 50)) {
|
|
1472
|
+
lines.push(`${m.file_path}: ${m.type} ${m.name}${m.signature ? ` — ${oneLine(m.signature, 160)}` : ""}`);
|
|
1473
|
+
}
|
|
1474
|
+
if (!data.matches.length)
|
|
1475
|
+
lines.push("- no matches");
|
|
1476
|
+
return lines.join("\n");
|
|
1477
|
+
}
|
|
1478
|
+
function compactBootstrapText(data) {
|
|
1479
|
+
const lines = [];
|
|
1480
|
+
lines.push(`ok ctx ${data.root_source} watcher=${data.watcher_enabled ? (data.watcher_ready ? "ready" : "starting") : "off"} root=${data.project_root}`);
|
|
1481
|
+
if (data.project_summary)
|
|
1482
|
+
lines.push(`summary ${compactMemoryLabel(data.project_summary, 140)}`);
|
|
1483
|
+
if (data.pending_total) {
|
|
1484
|
+
lines.push(`pending ${data.pending_changes.length}/${data.pending_total}${data.pending_truncated ? " truncated" : ""}: ${data.pending_changes
|
|
1485
|
+
.slice(0, 8)
|
|
1486
|
+
.map(compactPendingLabel)
|
|
1487
|
+
.join("; ")}`);
|
|
1488
|
+
}
|
|
1489
|
+
else {
|
|
1490
|
+
lines.push("pending 0");
|
|
1491
|
+
}
|
|
1492
|
+
if (data.items.length) {
|
|
1493
|
+
lines.push("requirements:");
|
|
1494
|
+
for (const item of data.items) {
|
|
1495
|
+
lines.push(`- ${compactRequirementLabel(item.requirement)}`);
|
|
1496
|
+
for (const c of item.recent_changes.slice(0, 3))
|
|
1497
|
+
lines.push(` - ${compactChangeLabel(c)}`);
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
else {
|
|
1501
|
+
lines.push("requirements: none");
|
|
1502
|
+
}
|
|
1503
|
+
if (data.recent_notes.length) {
|
|
1504
|
+
lines.push("notes:");
|
|
1505
|
+
for (const n of data.recent_notes.slice(0, 3))
|
|
1506
|
+
lines.push(`- ${compactMemoryLabel(n, 120)}`);
|
|
1507
|
+
}
|
|
1508
|
+
if (data.conventions.length) {
|
|
1509
|
+
lines.push(`conventions ${data.conventions.length}: ${data.conventions
|
|
1510
|
+
.slice(0, 5)
|
|
1511
|
+
.map((c) => c.title ?? `#${c.id}`)
|
|
1512
|
+
.join(", ")}`);
|
|
1513
|
+
}
|
|
1514
|
+
if (data.semantic) {
|
|
1515
|
+
lines.push(`semantic ${data.semantic.mode} ${data.semantic.matches.length}/${data.semantic.top_k} for "${oneLine(data.semantic.query, 80)}":`);
|
|
1516
|
+
for (const m of data.semantic.matches.slice(0, 5)) {
|
|
1517
|
+
lines.push(`- score=${m.score.toFixed(3)} ${compactMemoryLabel(m.item, 120)}`);
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
lines.push("hint: use format=json for full structured output; read_memory_item(id) for full content");
|
|
1521
|
+
return lines.join("\n");
|
|
1522
|
+
}
|
|
1523
|
+
function compactBrainDumpText(data) {
|
|
1524
|
+
return compactBootstrapText(data);
|
|
1525
|
+
}
|
|
1526
|
+
function detectRtk() {
|
|
1527
|
+
const command = process.platform === "win32" ? "rtk.exe" : "rtk";
|
|
1528
|
+
const result = spawnSync(command, ["--version"], {
|
|
1529
|
+
encoding: "utf8",
|
|
1530
|
+
timeout: 2000,
|
|
1531
|
+
windowsHide: true,
|
|
1532
|
+
});
|
|
1533
|
+
if (result.status === 0) {
|
|
1534
|
+
const gain = spawnSync(command, ["gain"], {
|
|
1535
|
+
encoding: "utf8",
|
|
1536
|
+
timeout: 5000,
|
|
1537
|
+
windowsHide: true,
|
|
1538
|
+
});
|
|
1539
|
+
const whereCommand = process.platform === "win32" ? "where.exe" : "which";
|
|
1540
|
+
const whereResult = spawnSync(whereCommand, [process.platform === "win32" ? "rtk.exe" : "rtk"], {
|
|
1541
|
+
encoding: "utf8",
|
|
1542
|
+
timeout: 2000,
|
|
1543
|
+
windowsHide: true,
|
|
1544
|
+
});
|
|
1545
|
+
const gainText = `${gain.stdout}${gain.stderr}`.trim();
|
|
1546
|
+
return {
|
|
1547
|
+
available: gain.status === 0,
|
|
1548
|
+
command,
|
|
1549
|
+
version: `${result.stdout}${result.stderr}`.trim(),
|
|
1550
|
+
gain_ok: gain.status === 0,
|
|
1551
|
+
gain_preview: oneLine(gainText, 240),
|
|
1552
|
+
path: whereResult.status === 0 ? oneLine(whereResult.stdout, 240) : undefined,
|
|
1553
|
+
note: gain.status === 0
|
|
1554
|
+
? "Prefer prefixing shell commands with rtk for compact outputs, e.g. rtk git status / rtk npm run build / rtk rg pattern ."
|
|
1555
|
+
: "An rtk binary exists, but `rtk gain` failed. This may be the wrong rtk project. Use install_rtk with uninstall_wrong_cargo_rtk=true only after confirming it is safe.",
|
|
1556
|
+
};
|
|
1557
|
+
}
|
|
1558
|
+
return {
|
|
1559
|
+
available: false,
|
|
1560
|
+
command,
|
|
1561
|
+
note: "rtk was not found on PATH. VectorMind compact MCP output still works; install rtk to compact shell command output too.",
|
|
1562
|
+
};
|
|
1563
|
+
}
|
|
1564
|
+
function commandExists(command) {
|
|
1565
|
+
const probe = process.platform === "win32" ? "where.exe" : "which";
|
|
1566
|
+
const result = spawnSync(probe, [command], { encoding: "utf8", timeout: 2000, windowsHide: true });
|
|
1567
|
+
return result.status === 0;
|
|
1568
|
+
}
|
|
1569
|
+
function runInstallStep(command, args, timeoutMs) {
|
|
1570
|
+
const result = spawnSync(command, args, {
|
|
1571
|
+
encoding: "utf8",
|
|
1572
|
+
timeout: timeoutMs,
|
|
1573
|
+
windowsHide: true,
|
|
1574
|
+
shell: false,
|
|
1575
|
+
});
|
|
1576
|
+
const output = `${result.stdout ?? ""}${result.stderr ?? ""}`.trim();
|
|
1577
|
+
return {
|
|
1578
|
+
command: [command, ...args].join(" "),
|
|
1579
|
+
status: result.status,
|
|
1580
|
+
ok: result.status === 0,
|
|
1581
|
+
output: oneLine(output, 1200),
|
|
1582
|
+
};
|
|
1583
|
+
}
|
|
1584
|
+
function chooseRtkInstallMethod(method) {
|
|
1585
|
+
if (method !== "auto")
|
|
1586
|
+
return method;
|
|
1587
|
+
if (process.platform === "darwin" && commandExists("brew"))
|
|
1588
|
+
return "brew";
|
|
1589
|
+
if (commandExists("cargo"))
|
|
1590
|
+
return "cargo";
|
|
1591
|
+
return "shell_script";
|
|
1592
|
+
}
|
|
1593
|
+
function buildRtkInstallPlan(args) {
|
|
1594
|
+
const method = chooseRtkInstallMethod(args.method);
|
|
1595
|
+
const commands = [];
|
|
1596
|
+
const notes = [];
|
|
1597
|
+
if (args.uninstall_wrong_cargo_rtk) {
|
|
1598
|
+
commands.push("cargo uninstall rtk");
|
|
1599
|
+
notes.push("Only use uninstall_wrong_cargo_rtk after verifying the existing rtk is the wrong Cargo package.");
|
|
1600
|
+
}
|
|
1601
|
+
if (method === "brew") {
|
|
1602
|
+
commands.push("brew install rtk");
|
|
1603
|
+
}
|
|
1604
|
+
else if (method === "cargo") {
|
|
1605
|
+
commands.push("cargo install --git https://github.com/rtk-ai/rtk");
|
|
1606
|
+
}
|
|
1607
|
+
else {
|
|
1608
|
+
if (process.platform === "win32") {
|
|
1609
|
+
notes.push("shell_script install is Linux/macOS-oriented; on Windows prefer method=cargo after installing Rust/Cargo.");
|
|
1610
|
+
commands.push("cargo install --git https://github.com/rtk-ai/rtk");
|
|
1611
|
+
}
|
|
1612
|
+
else {
|
|
1613
|
+
commands.push("curl -fsSL https://raw.githubusercontent.com/rtk-ai/rtk/master/install.sh | sh");
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
commands.push("rtk --version");
|
|
1617
|
+
commands.push("rtk gain");
|
|
1618
|
+
if (args.init === "global_no_patch")
|
|
1619
|
+
commands.push("rtk init -g --no-patch");
|
|
1620
|
+
if (args.init === "global_auto_patch")
|
|
1621
|
+
commands.push("rtk init -g --auto-patch");
|
|
1622
|
+
if (args.init === "global_hook_only")
|
|
1623
|
+
commands.push("rtk init -g --hook-only --no-patch");
|
|
1624
|
+
if (args.init === "local")
|
|
1625
|
+
commands.push("rtk init");
|
|
1626
|
+
if (args.init !== "none") {
|
|
1627
|
+
notes.push("rtk init may modify Claude/RTK configuration. Use init=none for binary-only installation.");
|
|
1628
|
+
}
|
|
1629
|
+
return { method, commands, notes };
|
|
1630
|
+
}
|
|
1631
|
+
function installRtk(args) {
|
|
1632
|
+
const detectedBefore = detectRtk();
|
|
1633
|
+
const plan = buildRtkInstallPlan(args);
|
|
1634
|
+
const steps = [];
|
|
1635
|
+
const notes = [...plan.notes];
|
|
1636
|
+
if (detectedBefore.available) {
|
|
1637
|
+
notes.push("rtk is already installed and verified with `rtk gain`; installation skipped.");
|
|
1638
|
+
return {
|
|
1639
|
+
ok: true,
|
|
1640
|
+
dry_run: args.dry_run,
|
|
1641
|
+
already_available: true,
|
|
1642
|
+
method: plan.method,
|
|
1643
|
+
commands: plan.commands,
|
|
1644
|
+
notes,
|
|
1645
|
+
steps,
|
|
1646
|
+
detected_before: detectedBefore,
|
|
1647
|
+
detected_after: detectedBefore,
|
|
1648
|
+
};
|
|
1649
|
+
}
|
|
1650
|
+
if (args.dry_run) {
|
|
1651
|
+
notes.push("dry_run=true: no command was executed. Call install_rtk with dry_run=false to install.");
|
|
1652
|
+
return {
|
|
1653
|
+
ok: true,
|
|
1654
|
+
dry_run: true,
|
|
1655
|
+
already_available: false,
|
|
1656
|
+
method: plan.method,
|
|
1657
|
+
commands: plan.commands,
|
|
1658
|
+
notes,
|
|
1659
|
+
steps,
|
|
1660
|
+
detected_before: detectedBefore,
|
|
1661
|
+
};
|
|
1662
|
+
}
|
|
1663
|
+
if (plan.method === "brew") {
|
|
1664
|
+
steps.push(runInstallStep("brew", ["install", "rtk"], args.timeout_ms));
|
|
1665
|
+
}
|
|
1666
|
+
else if (plan.method === "cargo") {
|
|
1667
|
+
if (args.uninstall_wrong_cargo_rtk) {
|
|
1668
|
+
steps.push(runInstallStep("cargo", ["uninstall", "rtk"], args.timeout_ms));
|
|
1669
|
+
}
|
|
1670
|
+
steps.push(runInstallStep("cargo", ["install", "--git", "https://github.com/rtk-ai/rtk"], args.timeout_ms));
|
|
1671
|
+
}
|
|
1672
|
+
else if (process.platform === "win32") {
|
|
1673
|
+
notes.push("Windows fallback uses Cargo because the upstream shell installer targets POSIX shells.");
|
|
1674
|
+
if (args.uninstall_wrong_cargo_rtk) {
|
|
1675
|
+
steps.push(runInstallStep("cargo", ["uninstall", "rtk"], args.timeout_ms));
|
|
1676
|
+
}
|
|
1677
|
+
steps.push(runInstallStep("cargo", ["install", "--git", "https://github.com/rtk-ai/rtk"], args.timeout_ms));
|
|
1678
|
+
}
|
|
1679
|
+
else {
|
|
1680
|
+
const script = "curl -fsSL https://raw.githubusercontent.com/rtk-ai/rtk/master/install.sh | sh";
|
|
1681
|
+
steps.push(runInstallStep("sh", ["-c", script], args.timeout_ms));
|
|
1682
|
+
}
|
|
1683
|
+
const detectedAfterInstall = detectRtk();
|
|
1684
|
+
if (detectedAfterInstall.available && args.init !== "none") {
|
|
1685
|
+
if (args.init === "global_no_patch")
|
|
1686
|
+
steps.push(runInstallStep("rtk", ["init", "-g", "--no-patch"], args.timeout_ms));
|
|
1687
|
+
if (args.init === "global_auto_patch")
|
|
1688
|
+
steps.push(runInstallStep("rtk", ["init", "-g", "--auto-patch"], args.timeout_ms));
|
|
1689
|
+
if (args.init === "global_hook_only") {
|
|
1690
|
+
steps.push(runInstallStep("rtk", ["init", "-g", "--hook-only", "--no-patch"], args.timeout_ms));
|
|
1691
|
+
}
|
|
1692
|
+
if (args.init === "local")
|
|
1693
|
+
steps.push(runInstallStep("rtk", ["init"], args.timeout_ms));
|
|
1694
|
+
}
|
|
1695
|
+
const detectedAfter = detectRtk();
|
|
1696
|
+
return {
|
|
1697
|
+
ok: detectedAfter.available,
|
|
1698
|
+
dry_run: false,
|
|
1699
|
+
already_available: false,
|
|
1700
|
+
method: plan.method,
|
|
1701
|
+
commands: plan.commands,
|
|
1702
|
+
notes,
|
|
1703
|
+
steps,
|
|
1704
|
+
detected_before: detectedBefore,
|
|
1705
|
+
detected_after: detectedAfter,
|
|
1706
|
+
};
|
|
1707
|
+
}
|
|
1708
|
+
function compactInstallRtkText(data) {
|
|
1709
|
+
const lines = [];
|
|
1710
|
+
lines.push(`install_rtk ok=${data.ok} dry_run=${data.dry_run} already_available=${data.already_available} method=${data.method}`);
|
|
1711
|
+
lines.push(`before available=${data.detected_before.available} version=${data.detected_before.version ?? "none"} gain_ok=${data.detected_before.gain_ok ?? false}`);
|
|
1712
|
+
if (data.detected_after) {
|
|
1713
|
+
lines.push(`after available=${data.detected_after.available} version=${data.detected_after.version ?? "none"} gain_ok=${data.detected_after.gain_ok ?? false}`);
|
|
1714
|
+
}
|
|
1715
|
+
if (data.commands.length) {
|
|
1716
|
+
lines.push("commands:");
|
|
1717
|
+
for (const command of data.commands)
|
|
1718
|
+
lines.push(`- ${command}`);
|
|
1719
|
+
}
|
|
1720
|
+
if (data.steps.length) {
|
|
1721
|
+
lines.push("steps:");
|
|
1722
|
+
for (const step of data.steps) {
|
|
1723
|
+
lines.push(`- ${step.ok ? "ok" : "fail"} [${step.status ?? "null"}] ${step.command}: ${oneLine(step.output, 240)}`);
|
|
1724
|
+
}
|
|
1725
|
+
}
|
|
1726
|
+
if (data.notes.length) {
|
|
1727
|
+
lines.push("notes:");
|
|
1728
|
+
for (const note of data.notes)
|
|
1729
|
+
lines.push(`- ${note}`);
|
|
1730
|
+
}
|
|
1731
|
+
return lines.join("\n");
|
|
1732
|
+
}
|
|
1733
|
+
function tokenSavingsSummary(limit) {
|
|
1734
|
+
const summary = summarizeTokenSavingsStmt.get();
|
|
1735
|
+
const by_tool = summarizeTokenSavingsByToolStmt.all(limit);
|
|
1736
|
+
const recent = listRecentTokenSavingsStmt.all(limit);
|
|
1737
|
+
return {
|
|
1738
|
+
ok: true,
|
|
1739
|
+
summary: summary ?? { calls: 0, raw_tokens: 0, output_tokens: 0, saved_tokens: 0, avg_savings_pct: 0 },
|
|
1740
|
+
by_tool,
|
|
1741
|
+
recent,
|
|
1742
|
+
};
|
|
1743
|
+
}
|
|
1744
|
+
function compactTokenSavingsText(data) {
|
|
1745
|
+
const s = data.summary;
|
|
1746
|
+
const pct = Number(s.raw_tokens) > 0 ? (Number(s.saved_tokens) / Number(s.raw_tokens)) * 100 : 0;
|
|
1747
|
+
const lines = [
|
|
1748
|
+
`token_savings calls=${s.calls} raw=${s.raw_tokens} out=${s.output_tokens} saved=${s.saved_tokens} (${pct.toFixed(1)}%)`,
|
|
1749
|
+
];
|
|
1750
|
+
if (data.by_tool.length) {
|
|
1751
|
+
lines.push("by_tool:");
|
|
1752
|
+
for (const t of data.by_tool.slice(0, 10)) {
|
|
1753
|
+
lines.push(`- ${t.tool}: calls=${t.calls} saved=${t.saved_tokens} raw=${t.raw_tokens} out=${t.output_tokens} avg=${Number(t.avg_savings_pct).toFixed(1)}%`);
|
|
1754
|
+
}
|
|
1755
|
+
}
|
|
1756
|
+
if (data.recent.length) {
|
|
1757
|
+
lines.push("recent:");
|
|
1758
|
+
for (const r of data.recent.slice(0, 10)) {
|
|
1759
|
+
lines.push(`- #${r.id} ${r.tool}: ${r.raw_tokens}->${r.output_tokens} saved=${r.saved_tokens}`);
|
|
1760
|
+
}
|
|
1761
|
+
}
|
|
1762
|
+
return lines.join("\n");
|
|
1763
|
+
}
|
|
1338
1764
|
function sliceTextForOutput(input, maxChars) {
|
|
1339
1765
|
const total = input.length;
|
|
1340
1766
|
if (maxChars <= 0)
|
|
@@ -2527,6 +2953,9 @@ function buildServerInstructions() {
|
|
|
2527
2953
|
"Built-in frontend output-purity policy:",
|
|
2528
2954
|
BUILTIN_FRONTEND_OUTPUT_PURITY_INSTRUCTIONS,
|
|
2529
2955
|
"",
|
|
2956
|
+
"Built-in git commit summary policy:",
|
|
2957
|
+
BUILTIN_GIT_COMMIT_SUMMARY_INSTRUCTIONS,
|
|
2958
|
+
"",
|
|
2530
2959
|
"Built-in low-overhead execution and heavy-thread policy:",
|
|
2531
2960
|
BUILTIN_LOW_OVERHEAD_WORKFLOW_INSTRUCTIONS,
|
|
2532
2961
|
"",
|
|
@@ -2537,11 +2966,14 @@ function buildServerInstructions() {
|
|
|
2537
2966
|
BUILTIN_THREAD_HANDOFF_SWITCH_INSTRUCTIONS,
|
|
2538
2967
|
"",
|
|
2539
2968
|
"Required workflow:",
|
|
2540
|
-
"-
|
|
2969
|
+
"- Tool outputs are compact by default. Pass format=json only when you need full structured data.",
|
|
2970
|
+
"- On every new conversation/session for analysis/design/development work: call bootstrap_context({ query: <current goal> }) first (or at least get_brain_dump()) to restore compact context and retrieve relevant matches from the local memory store (vector if enabled; otherwise FTS/LIKE).",
|
|
2541
2971
|
" - Output is compact by default. Use include_content=true only when you truly need full text (it increases tokens).",
|
|
2542
2972
|
" - Tune output size with: requirements_limit/changes_limit/notes_limit, preview_chars, pending_limit/pending_offset.",
|
|
2543
2973
|
" - Prefer read_memory_item(id, offset, limit) to fetch full text on demand instead of returning large content in other tool outputs.",
|
|
2544
2974
|
"- For pure execution-first tasks with explicit targets (for example compile/build/run/launch/package/publish/test rerun), you may skip retrieval and go straight to the minimum necessary shell or host tools unless code/context lookup is actually needed to unblock execution.",
|
|
2975
|
+
"- If rtk is installed and verified (detect_rtk with gain_ok=true), prefix shell commands with rtk where possible (rtk git status, rtk npm run build, rtk rg ...) so command output is compact before it reaches the model.",
|
|
2976
|
+
"- If rtk is missing and the user asks to install it, use install_rtk first with dry_run=true to show the exact commands; execute with dry_run=false only after the user clearly approves installation/init choices.",
|
|
2545
2977
|
"- To read local Codex skill/prompt/rule files (for example SKILL.md under CODEX_HOME or AGENTS_HOME), prefer read_codex_text_file({ path }) instead of assuming a filesystem MCP resource server exists.",
|
|
2546
2978
|
"- For project file/directory browsing, prefer list_project_files({ path, recursive?, max_depth? }) over shelling out to Get-ChildItem/ls. It respects ignore rules and keeps output bounded.",
|
|
2547
2979
|
"- For small/medium raw file reads, prefer read_file_text({ path, offset?, max_chars? }) over Get-Content -Raw. Use read_file_lines(...) when you need deterministic line ranges or the file may be large.",
|
|
@@ -2560,6 +2992,7 @@ function buildServerInstructions() {
|
|
|
2560
2992
|
"- When asked to locate code (class/function/type): call query_codebase(query) instead of guessing.",
|
|
2561
2993
|
"- When you need to recall relevant context from history/code/docs: call semantic_search(query, ...) instead of guessing.",
|
|
2562
2994
|
"- If the current thread is already heavy or the user reports it has become slow, switch to a lighter workflow: avoid redundant retrieval, keep outputs compact, and if the user refuses thread switching, continue in light mode without repeating the switch reminder in that same session.",
|
|
2995
|
+
"- Use get_token_savings({ format: 'compact' }) when you need to verify how many tokens VectorMind compact outputs saved.",
|
|
2563
2996
|
"",
|
|
2564
2997
|
"If tool output conflicts with assumptions, trust the tool output.",
|
|
2565
2998
|
].join("\n");
|
|
@@ -2808,6 +3241,22 @@ function initDatabase() {
|
|
|
2808
3241
|
|
|
2809
3242
|
CREATE INDEX IF NOT EXISTS idx_pending_changes_updated_at
|
|
2810
3243
|
ON pending_changes(updated_at DESC);
|
|
3244
|
+
|
|
3245
|
+
CREATE TABLE IF NOT EXISTS token_savings (
|
|
3246
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
3247
|
+
tool TEXT NOT NULL,
|
|
3248
|
+
raw_tokens INTEGER NOT NULL,
|
|
3249
|
+
output_tokens INTEGER NOT NULL,
|
|
3250
|
+
saved_tokens INTEGER NOT NULL,
|
|
3251
|
+
savings_pct REAL NOT NULL,
|
|
3252
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
3253
|
+
);
|
|
3254
|
+
|
|
3255
|
+
CREATE INDEX IF NOT EXISTS idx_token_savings_created_at
|
|
3256
|
+
ON token_savings(created_at DESC);
|
|
3257
|
+
|
|
3258
|
+
CREATE INDEX IF NOT EXISTS idx_token_savings_tool
|
|
3259
|
+
ON token_savings(tool);
|
|
2811
3260
|
`);
|
|
2812
3261
|
initMemoryItemsFts();
|
|
2813
3262
|
insertRequirementStmt = db.prepare(`INSERT INTO requirements (title, context_data, status) VALUES (?, ?, 'active')`);
|
|
@@ -2929,6 +3378,30 @@ function initDatabase() {
|
|
|
2929
3378
|
END,
|
|
2930
3379
|
name
|
|
2931
3380
|
LIMIT ?`);
|
|
3381
|
+
insertTokenSavingsStmt = db.prepare(`INSERT INTO token_savings (tool, raw_tokens, output_tokens, saved_tokens, savings_pct)
|
|
3382
|
+
VALUES (?, ?, ?, ?, ?)`);
|
|
3383
|
+
summarizeTokenSavingsStmt = db.prepare(`SELECT
|
|
3384
|
+
COUNT(*) as calls,
|
|
3385
|
+
COALESCE(SUM(raw_tokens), 0) as raw_tokens,
|
|
3386
|
+
COALESCE(SUM(output_tokens), 0) as output_tokens,
|
|
3387
|
+
COALESCE(SUM(saved_tokens), 0) as saved_tokens,
|
|
3388
|
+
COALESCE(AVG(savings_pct), 0) as avg_savings_pct
|
|
3389
|
+
FROM token_savings`);
|
|
3390
|
+
summarizeTokenSavingsByToolStmt = db.prepare(`SELECT
|
|
3391
|
+
tool,
|
|
3392
|
+
COUNT(*) as calls,
|
|
3393
|
+
COALESCE(SUM(raw_tokens), 0) as raw_tokens,
|
|
3394
|
+
COALESCE(SUM(output_tokens), 0) as output_tokens,
|
|
3395
|
+
COALESCE(SUM(saved_tokens), 0) as saved_tokens,
|
|
3396
|
+
COALESCE(AVG(savings_pct), 0) as avg_savings_pct
|
|
3397
|
+
FROM token_savings
|
|
3398
|
+
GROUP BY tool
|
|
3399
|
+
ORDER BY saved_tokens DESC, calls DESC
|
|
3400
|
+
LIMIT ?`);
|
|
3401
|
+
listRecentTokenSavingsStmt = db.prepare(`SELECT id, tool, raw_tokens, output_tokens, saved_tokens, savings_pct, created_at
|
|
3402
|
+
FROM token_savings
|
|
3403
|
+
ORDER BY created_at DESC, id DESC
|
|
3404
|
+
LIMIT ?`);
|
|
2932
3405
|
indexFileSymbolsTx = db.transaction((filePath, symbols) => {
|
|
2933
3406
|
deleteSymbolsForFileStmt.run(filePath);
|
|
2934
3407
|
for (const s of symbols) {
|
|
@@ -3123,6 +3596,21 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
3123
3596
|
description: "Clear the in-memory debug activity log. Enable logging with VECTORMIND_DEBUG_LOG=1.",
|
|
3124
3597
|
inputSchema: toJsonSchemaCompat(ClearActivityLogArgsSchema),
|
|
3125
3598
|
},
|
|
3599
|
+
{
|
|
3600
|
+
name: "detect_rtk",
|
|
3601
|
+
description: "Detect whether rtk is available on PATH. When available, prefer rtk-prefixed shell commands to reduce command-output tokens.",
|
|
3602
|
+
inputSchema: toJsonSchemaCompat(DetectRtkArgsSchema),
|
|
3603
|
+
},
|
|
3604
|
+
{
|
|
3605
|
+
name: "install_rtk",
|
|
3606
|
+
description: "Install the rtk-ai/rtk Rust Token Killer binary when it is missing. Defaults to dry_run=true and never patches hooks unless init is explicitly requested.",
|
|
3607
|
+
inputSchema: toJsonSchemaCompat(InstallRtkArgsSchema),
|
|
3608
|
+
},
|
|
3609
|
+
{
|
|
3610
|
+
name: "get_token_savings",
|
|
3611
|
+
description: "Show VectorMind compact-output token savings recorded by MCP tools. Use this to verify raw-vs-compact output reduction.",
|
|
3612
|
+
inputSchema: toJsonSchemaCompat(GetTokenSavingsArgsSchema),
|
|
3613
|
+
},
|
|
3126
3614
|
{
|
|
3127
3615
|
name: "grep",
|
|
3128
3616
|
description: "Repo text search with precise file/line/col matches, powered by ripgrep against real project files plus built-in noise filters. Falls back to indexed search only when ripgrep is unavailable.",
|
|
@@ -3525,43 +4013,45 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
3525
4013
|
semantic_mode: semantic?.mode ?? null,
|
|
3526
4014
|
semantic_matches: semantic?.matches?.length ?? 0,
|
|
3527
4015
|
});
|
|
4016
|
+
const outputValue = {
|
|
4017
|
+
ok: true,
|
|
4018
|
+
generated_at: new Date().toISOString(),
|
|
4019
|
+
project_root: projectRoot,
|
|
4020
|
+
root_source: rootSource,
|
|
4021
|
+
db_path: dbPath,
|
|
4022
|
+
watcher_enabled: !!watcher,
|
|
4023
|
+
watcher_ready: watcherReady,
|
|
4024
|
+
embeddings: {
|
|
4025
|
+
enabled: embeddingsEnabled,
|
|
4026
|
+
model: embedModelName,
|
|
4027
|
+
embed_files: embedFilesMode,
|
|
4028
|
+
},
|
|
4029
|
+
output: {
|
|
4030
|
+
format: args.format,
|
|
4031
|
+
include_content: includeContent,
|
|
4032
|
+
preview_chars: previewChars,
|
|
4033
|
+
content_max_chars: contentMaxChars,
|
|
4034
|
+
requirements_limit: requirementsLimit,
|
|
4035
|
+
changes_limit: changesLimit,
|
|
4036
|
+
notes_limit: notesLimit,
|
|
4037
|
+
conventions_limit: conventionsLimit,
|
|
4038
|
+
},
|
|
4039
|
+
project_summary,
|
|
4040
|
+
conventions,
|
|
4041
|
+
recent_notes,
|
|
4042
|
+
pending_total,
|
|
4043
|
+
pending_offset,
|
|
4044
|
+
pending_limit,
|
|
4045
|
+
pending_truncated,
|
|
4046
|
+
pending_changes,
|
|
4047
|
+
items,
|
|
4048
|
+
semantic,
|
|
4049
|
+
};
|
|
3528
4050
|
return {
|
|
3529
4051
|
content: [
|
|
3530
4052
|
{
|
|
3531
4053
|
type: "text",
|
|
3532
|
-
text:
|
|
3533
|
-
ok: true,
|
|
3534
|
-
generated_at: new Date().toISOString(),
|
|
3535
|
-
project_root: projectRoot,
|
|
3536
|
-
root_source: rootSource,
|
|
3537
|
-
db_path: dbPath,
|
|
3538
|
-
watcher_enabled: !!watcher,
|
|
3539
|
-
watcher_ready: watcherReady,
|
|
3540
|
-
embeddings: {
|
|
3541
|
-
enabled: embeddingsEnabled,
|
|
3542
|
-
model: embedModelName,
|
|
3543
|
-
embed_files: embedFilesMode,
|
|
3544
|
-
},
|
|
3545
|
-
output: {
|
|
3546
|
-
include_content: includeContent,
|
|
3547
|
-
preview_chars: previewChars,
|
|
3548
|
-
content_max_chars: contentMaxChars,
|
|
3549
|
-
requirements_limit: requirementsLimit,
|
|
3550
|
-
changes_limit: changesLimit,
|
|
3551
|
-
notes_limit: notesLimit,
|
|
3552
|
-
conventions_limit: conventionsLimit,
|
|
3553
|
-
},
|
|
3554
|
-
project_summary,
|
|
3555
|
-
conventions,
|
|
3556
|
-
recent_notes,
|
|
3557
|
-
pending_total,
|
|
3558
|
-
pending_offset,
|
|
3559
|
-
pending_limit,
|
|
3560
|
-
pending_truncated,
|
|
3561
|
-
pending_changes,
|
|
3562
|
-
items,
|
|
3563
|
-
semantic,
|
|
3564
|
-
}),
|
|
4054
|
+
text: toolText("bootstrap_context", outputValue, compactBootstrapText(outputValue), args.format),
|
|
3565
4055
|
},
|
|
3566
4056
|
],
|
|
3567
4057
|
};
|
|
@@ -3602,42 +4092,45 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
3602
4092
|
notes_returned: recent_notes.length,
|
|
3603
4093
|
conventions_returned: conventions.length,
|
|
3604
4094
|
});
|
|
4095
|
+
const outputValue = {
|
|
4096
|
+
ok: true,
|
|
4097
|
+
generated_at: new Date().toISOString(),
|
|
4098
|
+
project_root: projectRoot,
|
|
4099
|
+
root_source: rootSource,
|
|
4100
|
+
db_path: dbPath,
|
|
4101
|
+
watcher_enabled: !!watcher,
|
|
4102
|
+
watcher_ready: watcherReady,
|
|
4103
|
+
embeddings: {
|
|
4104
|
+
enabled: embeddingsEnabled,
|
|
4105
|
+
model: embedModelName,
|
|
4106
|
+
embed_files: embedFilesMode,
|
|
4107
|
+
},
|
|
4108
|
+
output: {
|
|
4109
|
+
format: args.format,
|
|
4110
|
+
include_content: includeContent,
|
|
4111
|
+
preview_chars: previewChars,
|
|
4112
|
+
content_max_chars: contentMaxChars,
|
|
4113
|
+
requirements_limit: requirementsLimit,
|
|
4114
|
+
changes_limit: changesLimit,
|
|
4115
|
+
notes_limit: notesLimit,
|
|
4116
|
+
conventions_limit: conventionsLimit,
|
|
4117
|
+
},
|
|
4118
|
+
project_summary,
|
|
4119
|
+
conventions,
|
|
4120
|
+
recent_notes,
|
|
4121
|
+
pending_total,
|
|
4122
|
+
pending_offset,
|
|
4123
|
+
pending_limit,
|
|
4124
|
+
pending_truncated,
|
|
4125
|
+
pending_changes,
|
|
4126
|
+
items,
|
|
4127
|
+
semantic: null,
|
|
4128
|
+
};
|
|
3605
4129
|
return {
|
|
3606
4130
|
content: [
|
|
3607
4131
|
{
|
|
3608
4132
|
type: "text",
|
|
3609
|
-
text:
|
|
3610
|
-
ok: true,
|
|
3611
|
-
generated_at: new Date().toISOString(),
|
|
3612
|
-
project_root: projectRoot,
|
|
3613
|
-
root_source: rootSource,
|
|
3614
|
-
db_path: dbPath,
|
|
3615
|
-
watcher_enabled: !!watcher,
|
|
3616
|
-
watcher_ready: watcherReady,
|
|
3617
|
-
embeddings: {
|
|
3618
|
-
enabled: embeddingsEnabled,
|
|
3619
|
-
model: embedModelName,
|
|
3620
|
-
embed_files: embedFilesMode,
|
|
3621
|
-
},
|
|
3622
|
-
output: {
|
|
3623
|
-
include_content: includeContent,
|
|
3624
|
-
preview_chars: previewChars,
|
|
3625
|
-
content_max_chars: contentMaxChars,
|
|
3626
|
-
requirements_limit: requirementsLimit,
|
|
3627
|
-
changes_limit: changesLimit,
|
|
3628
|
-
notes_limit: notesLimit,
|
|
3629
|
-
conventions_limit: conventionsLimit,
|
|
3630
|
-
},
|
|
3631
|
-
project_summary,
|
|
3632
|
-
conventions,
|
|
3633
|
-
recent_notes,
|
|
3634
|
-
pending_total,
|
|
3635
|
-
pending_offset,
|
|
3636
|
-
pending_limit,
|
|
3637
|
-
pending_truncated,
|
|
3638
|
-
pending_changes,
|
|
3639
|
-
items,
|
|
3640
|
-
}),
|
|
4133
|
+
text: toolText("get_brain_dump", outputValue, compactBrainDumpText(outputValue), args.format),
|
|
3641
4134
|
},
|
|
3642
4135
|
],
|
|
3643
4136
|
};
|
|
@@ -3818,6 +4311,31 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
3818
4311
|
clearActivityLog();
|
|
3819
4312
|
return { content: [{ type: "text", text: toolJson({ ok: true }) }] };
|
|
3820
4313
|
}
|
|
4314
|
+
if (toolName === "detect_rtk") {
|
|
4315
|
+
DetectRtkArgsSchema.parse(rawArgs);
|
|
4316
|
+
const result = detectRtk();
|
|
4317
|
+
const text = result.available
|
|
4318
|
+
? `rtk available: ${result.version ?? result.command}\ngain_ok=${result.gain_ok ?? false}${result.path ? ` path=${result.path}` : ""}\n${result.note}`
|
|
4319
|
+
: `rtk unavailable: ${result.command}\ngain_ok=${result.gain_ok ?? false}${result.version ? ` version=${result.version}` : ""}\n${result.note}`;
|
|
4320
|
+
return { content: [{ type: "text", text }] };
|
|
4321
|
+
}
|
|
4322
|
+
if (toolName === "install_rtk") {
|
|
4323
|
+
const args = InstallRtkArgsSchema.parse(rawArgs);
|
|
4324
|
+
const result = installRtk(args);
|
|
4325
|
+
return { content: [{ type: "text", text: compactInstallRtkText(result) }] };
|
|
4326
|
+
}
|
|
4327
|
+
if (toolName === "get_token_savings") {
|
|
4328
|
+
const args = GetTokenSavingsArgsSchema.parse(rawArgs);
|
|
4329
|
+
const result = tokenSavingsSummary(args.limit);
|
|
4330
|
+
return {
|
|
4331
|
+
content: [
|
|
4332
|
+
{
|
|
4333
|
+
type: "text",
|
|
4334
|
+
text: args.format === "json" ? toolJson(result) : compactTokenSavingsText(result),
|
|
4335
|
+
},
|
|
4336
|
+
],
|
|
4337
|
+
};
|
|
4338
|
+
}
|
|
3821
4339
|
if (toolName === "grep") {
|
|
3822
4340
|
const args = GrepArgsSchema.parse(rawArgs);
|
|
3823
4341
|
const q = args.query;
|
|
@@ -3851,24 +4369,25 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
3851
4369
|
total_matches: ripgrepResult.total_matches,
|
|
3852
4370
|
truncated: ripgrepResult.truncated,
|
|
3853
4371
|
});
|
|
4372
|
+
const outputValue = {
|
|
4373
|
+
ok: true,
|
|
4374
|
+
backend: ripgrepResult.backend,
|
|
4375
|
+
rg_command: ripgrepResult.rg_command,
|
|
4376
|
+
query: q,
|
|
4377
|
+
mode,
|
|
4378
|
+
case_sensitive: caseSensitive,
|
|
4379
|
+
smart_case: smartCase,
|
|
4380
|
+
include_paths: includePaths ?? [],
|
|
4381
|
+
exclude_paths: excludePaths ?? [],
|
|
4382
|
+
matches: ripgrepResult.matches,
|
|
4383
|
+
total_matches: ripgrepResult.total_matches,
|
|
4384
|
+
truncated: ripgrepResult.truncated,
|
|
4385
|
+
};
|
|
3854
4386
|
return {
|
|
3855
4387
|
content: [
|
|
3856
4388
|
{
|
|
3857
4389
|
type: "text",
|
|
3858
|
-
text:
|
|
3859
|
-
ok: true,
|
|
3860
|
-
backend: ripgrepResult.backend,
|
|
3861
|
-
rg_command: ripgrepResult.rg_command,
|
|
3862
|
-
query: q,
|
|
3863
|
-
mode,
|
|
3864
|
-
case_sensitive: caseSensitive,
|
|
3865
|
-
smart_case: smartCase,
|
|
3866
|
-
include_paths: includePaths ?? [],
|
|
3867
|
-
exclude_paths: excludePaths ?? [],
|
|
3868
|
-
matches: ripgrepResult.matches,
|
|
3869
|
-
total_matches: ripgrepResult.total_matches,
|
|
3870
|
-
truncated: ripgrepResult.truncated,
|
|
3871
|
-
}),
|
|
4390
|
+
text: toolCompactOrJson("grep", outputValue, compactGrepText(outputValue), args.format),
|
|
3872
4391
|
},
|
|
3873
4392
|
],
|
|
3874
4393
|
};
|
|
@@ -3945,28 +4464,29 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
3945
4464
|
matches: indexedResult.matches.length,
|
|
3946
4465
|
truncated: indexedResult.truncated,
|
|
3947
4466
|
});
|
|
4467
|
+
const outputValue = {
|
|
4468
|
+
ok: true,
|
|
4469
|
+
backend: indexedResult.backend,
|
|
4470
|
+
fallback_reason: "ripgrep_unavailable",
|
|
4471
|
+
ripgrep_error: ripgrepResult.error,
|
|
4472
|
+
ripgrep_attempts: ripgrepResult.attempts,
|
|
4473
|
+
query: q,
|
|
4474
|
+
mode,
|
|
4475
|
+
case_sensitive: caseSensitive,
|
|
4476
|
+
smart_case: smartCase,
|
|
4477
|
+
hint: indexedResult.hint,
|
|
4478
|
+
kinds,
|
|
4479
|
+
include_paths: includePaths ?? [],
|
|
4480
|
+
exclude_paths: excludePaths ?? [],
|
|
4481
|
+
candidates: indexedResult.candidates,
|
|
4482
|
+
matches: indexedResult.matches,
|
|
4483
|
+
truncated: indexedResult.truncated,
|
|
4484
|
+
};
|
|
3948
4485
|
return {
|
|
3949
4486
|
content: [
|
|
3950
4487
|
{
|
|
3951
4488
|
type: "text",
|
|
3952
|
-
text:
|
|
3953
|
-
ok: true,
|
|
3954
|
-
backend: indexedResult.backend,
|
|
3955
|
-
fallback_reason: "ripgrep_unavailable",
|
|
3956
|
-
ripgrep_error: ripgrepResult.error,
|
|
3957
|
-
ripgrep_attempts: ripgrepResult.attempts,
|
|
3958
|
-
query: q,
|
|
3959
|
-
mode,
|
|
3960
|
-
case_sensitive: caseSensitive,
|
|
3961
|
-
smart_case: smartCase,
|
|
3962
|
-
hint: indexedResult.hint,
|
|
3963
|
-
kinds,
|
|
3964
|
-
include_paths: includePaths ?? [],
|
|
3965
|
-
exclude_paths: excludePaths ?? [],
|
|
3966
|
-
candidates: indexedResult.candidates,
|
|
3967
|
-
matches: indexedResult.matches,
|
|
3968
|
-
truncated: indexedResult.truncated,
|
|
3969
|
-
}),
|
|
4489
|
+
text: toolCompactOrJson("grep", outputValue, compactGrepText(outputValue), args.format),
|
|
3970
4490
|
},
|
|
3971
4491
|
],
|
|
3972
4492
|
};
|
|
@@ -4018,28 +4538,29 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4018
4538
|
truncated: result.truncated,
|
|
4019
4539
|
path_kind: st.isFile() ? "file" : st.isDirectory() ? "dir" : "other",
|
|
4020
4540
|
});
|
|
4541
|
+
const outputValue = {
|
|
4542
|
+
ok: true,
|
|
4543
|
+
path: resolved.dbFilePath,
|
|
4544
|
+
path_kind: st.isFile() ? "file" : st.isDirectory() ? "dir" : "other",
|
|
4545
|
+
recursive: args.recursive,
|
|
4546
|
+
max_depth: args.recursive ? args.max_depth : 1,
|
|
4547
|
+
include_files: args.include_files,
|
|
4548
|
+
include_dirs: args.include_dirs,
|
|
4549
|
+
include_hidden: args.include_hidden,
|
|
4550
|
+
respect_ignore: args.respect_ignore,
|
|
4551
|
+
include_paths: includePaths ?? [],
|
|
4552
|
+
exclude_paths: excludePaths ?? [],
|
|
4553
|
+
extensions: extensions ?? [],
|
|
4554
|
+
returned: result.returned,
|
|
4555
|
+
scanned: result.scanned,
|
|
4556
|
+
truncated: result.truncated,
|
|
4557
|
+
entries: result.entries,
|
|
4558
|
+
};
|
|
4021
4559
|
return {
|
|
4022
4560
|
content: [
|
|
4023
4561
|
{
|
|
4024
4562
|
type: "text",
|
|
4025
|
-
text:
|
|
4026
|
-
ok: true,
|
|
4027
|
-
path: resolved.dbFilePath,
|
|
4028
|
-
path_kind: st.isFile() ? "file" : st.isDirectory() ? "dir" : "other",
|
|
4029
|
-
recursive: args.recursive,
|
|
4030
|
-
max_depth: args.recursive ? args.max_depth : 1,
|
|
4031
|
-
include_files: args.include_files,
|
|
4032
|
-
include_dirs: args.include_dirs,
|
|
4033
|
-
include_hidden: args.include_hidden,
|
|
4034
|
-
respect_ignore: args.respect_ignore,
|
|
4035
|
-
include_paths: includePaths ?? [],
|
|
4036
|
-
exclude_paths: excludePaths ?? [],
|
|
4037
|
-
extensions: extensions ?? [],
|
|
4038
|
-
returned: result.returned,
|
|
4039
|
-
scanned: result.scanned,
|
|
4040
|
-
truncated: result.truncated,
|
|
4041
|
-
entries: result.entries,
|
|
4042
|
-
}),
|
|
4563
|
+
text: toolCompactOrJson("list_project_files", outputValue, compactListProjectFilesText(outputValue), args.format),
|
|
4043
4564
|
},
|
|
4044
4565
|
],
|
|
4045
4566
|
};
|
|
@@ -4079,19 +4600,20 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4079
4600
|
total_chars: result.totalChars,
|
|
4080
4601
|
truncated: result.truncated,
|
|
4081
4602
|
});
|
|
4603
|
+
const outputValue = {
|
|
4604
|
+
ok: true,
|
|
4605
|
+
file_path: resolved.dbFilePath,
|
|
4606
|
+
offset: args.offset,
|
|
4607
|
+
returned_chars: result.returnedChars,
|
|
4608
|
+
total_chars: result.totalChars,
|
|
4609
|
+
truncated: result.truncated,
|
|
4610
|
+
text: result.text,
|
|
4611
|
+
};
|
|
4082
4612
|
return {
|
|
4083
4613
|
content: [
|
|
4084
4614
|
{
|
|
4085
4615
|
type: "text",
|
|
4086
|
-
text:
|
|
4087
|
-
ok: true,
|
|
4088
|
-
file_path: resolved.dbFilePath,
|
|
4089
|
-
offset: args.offset,
|
|
4090
|
-
returned_chars: result.returnedChars,
|
|
4091
|
-
total_chars: result.totalChars,
|
|
4092
|
-
truncated: result.truncated,
|
|
4093
|
-
text: result.text,
|
|
4094
|
-
}),
|
|
4616
|
+
text: toolCompactOrJson("read_file_text", outputValue, compactReadTextFileText(outputValue), args.format),
|
|
4095
4617
|
},
|
|
4096
4618
|
],
|
|
4097
4619
|
};
|
|
@@ -4138,20 +4660,21 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4138
4660
|
total_chars: result.totalChars,
|
|
4139
4661
|
truncated: result.truncated,
|
|
4140
4662
|
});
|
|
4663
|
+
const outputValue = {
|
|
4664
|
+
ok: true,
|
|
4665
|
+
file_path: resolved.displayPath,
|
|
4666
|
+
allowed_root: resolved.allowedRoot,
|
|
4667
|
+
offset: args.offset,
|
|
4668
|
+
returned_chars: result.returnedChars,
|
|
4669
|
+
total_chars: result.totalChars,
|
|
4670
|
+
truncated: result.truncated,
|
|
4671
|
+
text: result.text,
|
|
4672
|
+
};
|
|
4141
4673
|
return {
|
|
4142
4674
|
content: [
|
|
4143
4675
|
{
|
|
4144
4676
|
type: "text",
|
|
4145
|
-
text:
|
|
4146
|
-
ok: true,
|
|
4147
|
-
file_path: resolved.displayPath,
|
|
4148
|
-
allowed_root: resolved.allowedRoot,
|
|
4149
|
-
offset: args.offset,
|
|
4150
|
-
returned_chars: result.returnedChars,
|
|
4151
|
-
total_chars: result.totalChars,
|
|
4152
|
-
truncated: result.truncated,
|
|
4153
|
-
text: result.text,
|
|
4154
|
-
}),
|
|
4677
|
+
text: toolCompactOrJson("read_codex_text_file", outputValue, compactReadTextFileText(outputValue), args.format),
|
|
4155
4678
|
},
|
|
4156
4679
|
],
|
|
4157
4680
|
};
|
|
@@ -4213,19 +4736,20 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4213
4736
|
returned: result.returned,
|
|
4214
4737
|
truncated: result.truncated,
|
|
4215
4738
|
});
|
|
4739
|
+
const outputValue = {
|
|
4740
|
+
ok: true,
|
|
4741
|
+
file_path: resolved.dbFilePath,
|
|
4742
|
+
from_line: fromLine,
|
|
4743
|
+
to_line: toLine,
|
|
4744
|
+
returned: result.returned,
|
|
4745
|
+
truncated: result.truncated,
|
|
4746
|
+
text: result.text,
|
|
4747
|
+
};
|
|
4216
4748
|
return {
|
|
4217
4749
|
content: [
|
|
4218
4750
|
{
|
|
4219
4751
|
type: "text",
|
|
4220
|
-
text:
|
|
4221
|
-
ok: true,
|
|
4222
|
-
file_path: resolved.dbFilePath,
|
|
4223
|
-
from_line: fromLine,
|
|
4224
|
-
to_line: toLine,
|
|
4225
|
-
returned: result.returned,
|
|
4226
|
-
truncated: result.truncated,
|
|
4227
|
-
text: result.text,
|
|
4228
|
-
}),
|
|
4752
|
+
text: toolCompactOrJson("read_file_lines", outputValue, compactReadFileLinesText(outputValue), args.format),
|
|
4229
4753
|
},
|
|
4230
4754
|
],
|
|
4231
4755
|
};
|
|
@@ -4242,11 +4766,12 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4242
4766
|
matches: filtered.length,
|
|
4243
4767
|
sample: filtered.slice(0, 10).map((m) => ({ name: m.name, type: m.type, file_path: m.file_path })),
|
|
4244
4768
|
});
|
|
4769
|
+
const outputValue = { ok: true, query: q, matches: filtered };
|
|
4245
4770
|
return {
|
|
4246
4771
|
content: [
|
|
4247
4772
|
{
|
|
4248
4773
|
type: "text",
|
|
4249
|
-
text:
|
|
4774
|
+
text: toolCompactOrJson("query_codebase", outputValue, compactQueryCodebaseText(outputValue), args.format),
|
|
4250
4775
|
},
|
|
4251
4776
|
],
|
|
4252
4777
|
};
|
|
@@ -4345,11 +4870,12 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4345
4870
|
score: m.score,
|
|
4346
4871
|
})),
|
|
4347
4872
|
});
|
|
4873
|
+
const outputValue = { ok: true, ...result };
|
|
4348
4874
|
return {
|
|
4349
4875
|
content: [
|
|
4350
4876
|
{
|
|
4351
4877
|
type: "text",
|
|
4352
|
-
text:
|
|
4878
|
+
text: toolCompactOrJson("semantic_search", outputValue, compactSemanticSearchText(outputValue), args.format),
|
|
4353
4879
|
},
|
|
4354
4880
|
],
|
|
4355
4881
|
};
|