@context-engine-bridge/context-engine-mcp-bridge 0.0.7 → 0.0.8
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/package.json +1 -1
- package/src/resultPathMapping.js +93 -21
package/package.json
CHANGED
package/src/resultPathMapping.js
CHANGED
|
@@ -55,17 +55,75 @@ function computeWorkspaceRelativePath(containerPath, hostPath) {
|
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
function remapRelatedPathToClient(p, workspaceRoot) {
|
|
59
|
+
try {
|
|
60
|
+
const s = typeof p === "string" ? p : "";
|
|
61
|
+
const root = typeof workspaceRoot === "string" ? workspaceRoot : "";
|
|
62
|
+
if (!s || !root) {
|
|
63
|
+
return p;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const sNorm = s.replace(/\\/g, path.sep);
|
|
67
|
+
if (sNorm.startsWith(root + path.sep) || sNorm === root) {
|
|
68
|
+
return sNorm;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (s.startsWith("/work/")) {
|
|
72
|
+
const rest = s.slice("/work/".length);
|
|
73
|
+
const parts = rest.split("/").filter(Boolean);
|
|
74
|
+
if (parts.length >= 2) {
|
|
75
|
+
const rel = parts.slice(1).join("/");
|
|
76
|
+
const relNative = _posixToNative(rel);
|
|
77
|
+
return path.join(root, relNative);
|
|
78
|
+
}
|
|
79
|
+
return p;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// If it's already a relative path, join it to the workspace root.
|
|
83
|
+
if (!s.startsWith("/") && !s.includes(":") && !s.includes("\\")) {
|
|
84
|
+
const relPosix = s.trim();
|
|
85
|
+
if (relPosix && relPosix !== "." && !relPosix.startsWith("../") && relPosix !== "..") {
|
|
86
|
+
const relNative = _posixToNative(relPosix);
|
|
87
|
+
const joined = path.join(root, relNative);
|
|
88
|
+
const relCheck = path.relative(root, joined);
|
|
89
|
+
if (relCheck && !relCheck.startsWith(`..${path.sep}`) && relCheck !== "..") {
|
|
90
|
+
return joined;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return p;
|
|
96
|
+
} catch {
|
|
97
|
+
return p;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
58
101
|
function remapHitPaths(hit, workspaceRoot) {
|
|
59
102
|
if (!hit || typeof hit !== "object") {
|
|
60
103
|
return hit;
|
|
61
104
|
}
|
|
62
|
-
const
|
|
63
|
-
|
|
105
|
+
const rawPath = typeof hit.path === "string" ? hit.path : "";
|
|
106
|
+
let hostPath = typeof hit.host_path === "string" ? hit.host_path : "";
|
|
107
|
+
let containerPath = typeof hit.container_path === "string" ? hit.container_path : "";
|
|
108
|
+
if (!hostPath && rawPath) {
|
|
109
|
+
hostPath = rawPath;
|
|
110
|
+
}
|
|
111
|
+
if (!containerPath && rawPath) {
|
|
112
|
+
containerPath = rawPath;
|
|
113
|
+
}
|
|
64
114
|
const relPath = computeWorkspaceRelativePath(containerPath, hostPath);
|
|
65
115
|
const out = { ...hit };
|
|
66
116
|
if (relPath) {
|
|
67
117
|
out.rel_path = relPath;
|
|
68
118
|
}
|
|
119
|
+
// Remap related_paths nested under each hit (repo_search/hybrid_search emit this per result).
|
|
120
|
+
try {
|
|
121
|
+
if (Array.isArray(out.related_paths)) {
|
|
122
|
+
out.related_paths = out.related_paths.map((p) => remapRelatedPathToClient(p, workspaceRoot));
|
|
123
|
+
}
|
|
124
|
+
} catch {
|
|
125
|
+
// ignore
|
|
126
|
+
}
|
|
69
127
|
if (workspaceRoot && relPath) {
|
|
70
128
|
try {
|
|
71
129
|
const relNative = _posixToNative(relPath);
|
|
@@ -107,18 +165,42 @@ function remapHitPaths(hit, workspaceRoot) {
|
|
|
107
165
|
}
|
|
108
166
|
}
|
|
109
167
|
const overridePath = envTruthy(process.env.CTXCE_BRIDGE_OVERRIDE_PATH, true);
|
|
110
|
-
if (overridePath
|
|
111
|
-
out.
|
|
168
|
+
if (overridePath) {
|
|
169
|
+
if (typeof out.client_path === "string" && out.client_path) {
|
|
170
|
+
out.path = out.client_path;
|
|
171
|
+
} else if (relPath) {
|
|
172
|
+
out.path = relPath;
|
|
173
|
+
}
|
|
112
174
|
}
|
|
113
175
|
return out;
|
|
114
176
|
}
|
|
115
177
|
|
|
116
|
-
function remapStringPath(p) {
|
|
178
|
+
function remapStringPath(p, workspaceRoot) {
|
|
117
179
|
try {
|
|
118
180
|
const s = typeof p === "string" ? p : "";
|
|
119
181
|
if (!s) {
|
|
120
182
|
return p;
|
|
121
183
|
}
|
|
184
|
+
// If this is already a path within the current client workspace, rewrite to a
|
|
185
|
+
// workspace-relative string when override is enabled.
|
|
186
|
+
try {
|
|
187
|
+
const root = typeof workspaceRoot === "string" ? workspaceRoot : "";
|
|
188
|
+
if (root) {
|
|
189
|
+
const sNorm = s.replace(/\\/g, path.sep);
|
|
190
|
+
if (sNorm.startsWith(root + path.sep) || sNorm === root) {
|
|
191
|
+
const relNative = path.relative(root, sNorm);
|
|
192
|
+
const relPosix = String(relNative).split(path.sep).join("/");
|
|
193
|
+
if (relPosix && !relPosix.startsWith("../") && relPosix !== "..") {
|
|
194
|
+
const override = envTruthy(process.env.CTXCE_BRIDGE_OVERRIDE_PATH, true);
|
|
195
|
+
if (override) {
|
|
196
|
+
return relPosix;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
} catch {
|
|
202
|
+
// ignore
|
|
203
|
+
}
|
|
122
204
|
if (s.startsWith("/work/")) {
|
|
123
205
|
const rest = s.slice("/work/".length);
|
|
124
206
|
const parts = rest.split("/").filter(Boolean);
|
|
@@ -191,18 +273,7 @@ function applyPathMappingToPayload(payload, workspaceRoot) {
|
|
|
191
273
|
out.citations = mapHitsArray(out.citations);
|
|
192
274
|
}
|
|
193
275
|
if (Array.isArray(out.related_paths)) {
|
|
194
|
-
out.related_paths = out.related_paths.map((p) =>
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
// context_search: {results:[{source:"code"|"memory", ...}]}
|
|
198
|
-
if (Array.isArray(out.results)) {
|
|
199
|
-
out.results = out.results.map((r) => {
|
|
200
|
-
if (!r || typeof r !== "object") {
|
|
201
|
-
return r;
|
|
202
|
-
}
|
|
203
|
-
// Only code results have path-like fields
|
|
204
|
-
return remapHitPaths(r, workspaceRoot);
|
|
205
|
-
});
|
|
276
|
+
out.related_paths = out.related_paths.map((p) => remapRelatedPathToClient(p, workspaceRoot));
|
|
206
277
|
}
|
|
207
278
|
|
|
208
279
|
// Some tools nest under {result:{...}}
|
|
@@ -242,24 +313,25 @@ export function maybeRemapToolResult(name, result, workspaceRoot) {
|
|
|
242
313
|
}
|
|
243
314
|
|
|
244
315
|
const mapped = applyPathMappingToPayload(parsed.value, workspaceRoot);
|
|
316
|
+
let outResult = result;
|
|
245
317
|
if (parsed.mode === "structured") {
|
|
246
|
-
|
|
318
|
+
outResult = { ...result, structuredContent: mapped };
|
|
247
319
|
}
|
|
248
320
|
|
|
249
321
|
// Replace text payload for clients that only read `content[].text`
|
|
250
322
|
try {
|
|
251
|
-
const content = Array.isArray(
|
|
323
|
+
const content = Array.isArray(outResult.content) ? outResult.content.slice() : [];
|
|
252
324
|
const idx = content.findIndex(
|
|
253
325
|
(c) => c && c.type === "text" && typeof c.text === "string",
|
|
254
326
|
);
|
|
255
327
|
if (idx >= 0) {
|
|
256
328
|
content[idx] = { ...content[idx], text: JSON.stringify(mapped) };
|
|
257
|
-
|
|
329
|
+
outResult = { ...outResult, content };
|
|
258
330
|
}
|
|
259
331
|
} catch {
|
|
260
332
|
// ignore
|
|
261
333
|
}
|
|
262
|
-
return
|
|
334
|
+
return outResult;
|
|
263
335
|
} catch {
|
|
264
336
|
return result;
|
|
265
337
|
}
|