mindgraph-mcp 0.19.0 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -3
- package/dist/cli.js +1055 -225
- package/dist/index.js +1008 -183
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -83,12 +83,12 @@ var init_dist = __esm({
|
|
|
83
83
|
for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
|
|
84
84
|
const res = await fetch(url, init);
|
|
85
85
|
if (!res.ok) {
|
|
86
|
-
const
|
|
86
|
+
const text22 = await res.text().catch(() => "");
|
|
87
87
|
let parsed;
|
|
88
88
|
try {
|
|
89
|
-
parsed = JSON.parse(
|
|
89
|
+
parsed = JSON.parse(text22);
|
|
90
90
|
} catch {
|
|
91
|
-
parsed =
|
|
91
|
+
parsed = text22;
|
|
92
92
|
}
|
|
93
93
|
const err5 = new MindGraphError(
|
|
94
94
|
`${method} ${path8} failed: ${res.status}`,
|
|
@@ -104,9 +104,9 @@ var init_dist = __esm({
|
|
|
104
104
|
}
|
|
105
105
|
throw err5;
|
|
106
106
|
}
|
|
107
|
-
const
|
|
108
|
-
if (!
|
|
109
|
-
return JSON.parse(
|
|
107
|
+
const text2 = await res.text();
|
|
108
|
+
if (!text2) return void 0;
|
|
109
|
+
return JSON.parse(text2);
|
|
110
110
|
}
|
|
111
111
|
throw lastError;
|
|
112
112
|
}
|
|
@@ -232,10 +232,10 @@ var init_dist = __esm({
|
|
|
232
232
|
* Resolve text to an existing entity via alias matching.
|
|
233
233
|
* Returns `{ uid: string | null }`.
|
|
234
234
|
*/
|
|
235
|
-
async resolveEntity(
|
|
235
|
+
async resolveEntity(text2, agentId) {
|
|
236
236
|
return this.post("/reality/entity", {
|
|
237
237
|
action: "resolve",
|
|
238
|
-
text,
|
|
238
|
+
text: text2,
|
|
239
239
|
agent_id: agentId
|
|
240
240
|
});
|
|
241
241
|
}
|
|
@@ -243,10 +243,10 @@ var init_dist = __esm({
|
|
|
243
243
|
* Fuzzy-match text against existing entities.
|
|
244
244
|
* Returns `{ matches: [{ uid, label, score }] }`.
|
|
245
245
|
*/
|
|
246
|
-
async fuzzyResolveEntity(
|
|
246
|
+
async fuzzyResolveEntity(text2, limit = 5, agentId) {
|
|
247
247
|
return this.post("/reality/entity", {
|
|
248
248
|
action: "fuzzy_resolve",
|
|
249
|
-
text,
|
|
249
|
+
text: text2,
|
|
250
250
|
limit,
|
|
251
251
|
agent_id: agentId
|
|
252
252
|
});
|
|
@@ -545,8 +545,8 @@ var init_dist = __esm({
|
|
|
545
545
|
async getAliases(uid) {
|
|
546
546
|
return this.get(`/aliases/${seg(uid)}`);
|
|
547
547
|
}
|
|
548
|
-
async resolveAlias(
|
|
549
|
-
return this.get(`/resolve?text=${encodeURIComponent(
|
|
548
|
+
async resolveAlias(text2) {
|
|
549
|
+
return this.get(`/resolve?text=${encodeURIComponent(text2)}`);
|
|
550
550
|
}
|
|
551
551
|
// ---- Export / Import ----
|
|
552
552
|
async exportGraph() {
|
|
@@ -1163,29 +1163,29 @@ async function runProcess(executable, args, timeoutMs, env, cwd) {
|
|
|
1163
1163
|
child.stderr.on("data", collect(stderr));
|
|
1164
1164
|
child.on("error", (cause) => {
|
|
1165
1165
|
clearTimeout(timer);
|
|
1166
|
-
const
|
|
1167
|
-
|
|
1168
|
-
rejectPromise(
|
|
1166
|
+
const error2 = new Error(cause.message);
|
|
1167
|
+
error2.kind = cause.code === "ENOENT" ? "absent" : "command_failed";
|
|
1168
|
+
rejectPromise(error2);
|
|
1169
1169
|
});
|
|
1170
1170
|
child.on("close", (code) => {
|
|
1171
1171
|
clearTimeout(timer);
|
|
1172
1172
|
if (timedOut) {
|
|
1173
|
-
const
|
|
1174
|
-
|
|
1175
|
-
rejectPromise(
|
|
1173
|
+
const error2 = new Error(`command timed out after ${timeoutMs}ms`);
|
|
1174
|
+
error2.kind = "timeout";
|
|
1175
|
+
rejectPromise(error2);
|
|
1176
1176
|
return;
|
|
1177
1177
|
}
|
|
1178
1178
|
if (outputBytes > MAX_OUTPUT_BYTES) {
|
|
1179
|
-
const
|
|
1180
|
-
|
|
1181
|
-
rejectPromise(
|
|
1179
|
+
const error2 = new Error("codegraph output exceeded 5 MiB");
|
|
1180
|
+
error2.kind = "command_failed";
|
|
1181
|
+
rejectPromise(error2);
|
|
1182
1182
|
return;
|
|
1183
1183
|
}
|
|
1184
1184
|
if (code !== 0) {
|
|
1185
|
-
const
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
rejectPromise(
|
|
1185
|
+
const error2 = new Error(Buffer.concat(stderr).toString("utf8").trim());
|
|
1186
|
+
error2.kind = "command_failed";
|
|
1187
|
+
error2.exitCode = code;
|
|
1188
|
+
rejectPromise(error2);
|
|
1189
1189
|
return;
|
|
1190
1190
|
}
|
|
1191
1191
|
resolvePromise(Buffer.concat(stdout).toString("utf8"));
|
|
@@ -1213,9 +1213,7 @@ function codeRefIdentityKey(ref) {
|
|
|
1213
1213
|
qualified_name: ref.qualifiedName,
|
|
1214
1214
|
disambiguator: {
|
|
1215
1215
|
signature: ref.signature ?? "",
|
|
1216
|
-
path: ref.path
|
|
1217
|
-
start_line: ref.startLine,
|
|
1218
|
-
end_line: ref.endLine
|
|
1216
|
+
path: ref.path
|
|
1219
1217
|
}
|
|
1220
1218
|
};
|
|
1221
1219
|
}
|
|
@@ -2104,7 +2102,7 @@ async function anchorCodeRef(client2, ref, repositoryUid, spaceUid, agentId) {
|
|
|
2104
2102
|
identity_space_uid: spaceUid,
|
|
2105
2103
|
agent_id: agentId
|
|
2106
2104
|
});
|
|
2107
|
-
if (response.uid) {
|
|
2105
|
+
if (response.uid && response.created !== false && response.status !== "existing") {
|
|
2108
2106
|
await client2.entity({
|
|
2109
2107
|
action: "relate",
|
|
2110
2108
|
source_uid: response.uid,
|
|
@@ -2739,8 +2737,8 @@ async function handleSyncTool(client2, args) {
|
|
|
2739
2737
|
}
|
|
2740
2738
|
}
|
|
2741
2739
|
return ok2(await remote.memorySync(request));
|
|
2742
|
-
} catch (
|
|
2743
|
-
return err2("sync_failed", errorDetail(
|
|
2740
|
+
} catch (error2) {
|
|
2741
|
+
return err2("sync_failed", errorDetail(error2));
|
|
2744
2742
|
}
|
|
2745
2743
|
}
|
|
2746
2744
|
async function scanRepository(remote, repository, requested, provider, agentId) {
|
|
@@ -2874,12 +2872,22 @@ function str(value) {
|
|
|
2874
2872
|
function num(value) {
|
|
2875
2873
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
2876
2874
|
}
|
|
2875
|
+
function edgeTypeName(value) {
|
|
2876
|
+
return str(value) ?? str(obj(value)?.Custom);
|
|
2877
|
+
}
|
|
2878
|
+
function renderBudget(requested) {
|
|
2879
|
+
if (requested === void 0 || !Number.isFinite(requested)) return RENDER_CHAR_BUDGET;
|
|
2880
|
+
return Math.min(
|
|
2881
|
+
RENDER_CHAR_BUDGET,
|
|
2882
|
+
Math.max(MIN_RENDER_CHAR_BUDGET, Math.floor(requested))
|
|
2883
|
+
);
|
|
2884
|
+
}
|
|
2877
2885
|
function clip(value, max, state) {
|
|
2878
|
-
const
|
|
2879
|
-
if (!
|
|
2880
|
-
if (
|
|
2886
|
+
const text2 = str(value);
|
|
2887
|
+
if (!text2) return void 0;
|
|
2888
|
+
if (text2.length <= max) return text2;
|
|
2881
2889
|
state.bounded = true;
|
|
2882
|
-
return `${
|
|
2890
|
+
return `${text2.slice(0, max - 1)}\u2026`;
|
|
2883
2891
|
}
|
|
2884
2892
|
function isNodeShaped(value) {
|
|
2885
2893
|
const node = obj(value);
|
|
@@ -3001,7 +3009,7 @@ function relationshipItems(edges, labelByUid, state, options) {
|
|
|
3001
3009
|
for (const raw of edges) {
|
|
3002
3010
|
const edge = obj(raw);
|
|
3003
3011
|
if (!edge) continue;
|
|
3004
|
-
const type =
|
|
3012
|
+
const type = edgeTypeName(edge.edge_type) || "?";
|
|
3005
3013
|
const from = str(edge.from_uid);
|
|
3006
3014
|
const to = str(edge.to_uid);
|
|
3007
3015
|
if (CURATION_EDGE_TYPES.has(type)) continue;
|
|
@@ -3014,25 +3022,29 @@ function relationshipItems(edges, labelByUid, state, options) {
|
|
|
3014
3022
|
if (lines.length > RELATIONSHIP_MAX) {
|
|
3015
3023
|
state.bounded = true;
|
|
3016
3024
|
const extra = lines.length - RELATIONSHIP_MAX;
|
|
3025
|
+
state.omitted += extra;
|
|
3017
3026
|
return [...lines.slice(0, RELATIONSHIP_MAX), `- (+${extra} more relationships)`];
|
|
3018
3027
|
}
|
|
3019
3028
|
return lines;
|
|
3020
3029
|
}
|
|
3021
|
-
function assemble(header, sections, state) {
|
|
3030
|
+
function assemble(header, sections, state, maxChars) {
|
|
3031
|
+
const budget = renderBudget(maxChars);
|
|
3032
|
+
const packingBudget = Math.max(header.length, budget - BOUNDED_MARKER_RESERVE);
|
|
3022
3033
|
const lines = [header];
|
|
3023
3034
|
let used = header.length;
|
|
3024
3035
|
for (const section of sections) {
|
|
3025
3036
|
if (section.items.length === 0 && !section.heading) continue;
|
|
3026
3037
|
const headingCost = section.heading.length + 2;
|
|
3027
|
-
if (used + headingCost >
|
|
3038
|
+
if (used + headingCost > packingBudget) {
|
|
3028
3039
|
state.bounded = true;
|
|
3040
|
+
state.omitted += Math.max(1, section.items.length);
|
|
3029
3041
|
continue;
|
|
3030
3042
|
}
|
|
3031
3043
|
let sectionUsed = 0;
|
|
3032
3044
|
const kept = [];
|
|
3033
3045
|
let dropped = 0;
|
|
3034
3046
|
for (const item of section.items) {
|
|
3035
|
-
if (used + headingCost + sectionUsed + item.length + 1 >
|
|
3047
|
+
if (used + headingCost + sectionUsed + item.length + 1 > packingBudget) {
|
|
3036
3048
|
dropped += 1;
|
|
3037
3049
|
continue;
|
|
3038
3050
|
}
|
|
@@ -3041,13 +3053,17 @@ function assemble(header, sections, state) {
|
|
|
3041
3053
|
}
|
|
3042
3054
|
if (kept.length === 0 && section.items.length > 0) {
|
|
3043
3055
|
state.bounded = true;
|
|
3056
|
+
state.omitted += dropped;
|
|
3044
3057
|
continue;
|
|
3045
3058
|
}
|
|
3046
3059
|
if (dropped > 0) {
|
|
3047
3060
|
state.bounded = true;
|
|
3061
|
+
state.omitted += dropped;
|
|
3048
3062
|
const marker = `(+${dropped} more not shown)`;
|
|
3049
|
-
|
|
3050
|
-
|
|
3063
|
+
if (used + headingCost + sectionUsed + marker.length + 1 <= packingBudget) {
|
|
3064
|
+
kept.push(marker);
|
|
3065
|
+
sectionUsed += marker.length + 1;
|
|
3066
|
+
}
|
|
3051
3067
|
}
|
|
3052
3068
|
lines.push(
|
|
3053
3069
|
section.items.length === 0 ? section.heading : section.heading ? `${section.heading}
|
|
@@ -3057,10 +3073,10 @@ ${kept.join("\n")}` : kept.join("\n")
|
|
|
3057
3073
|
}
|
|
3058
3074
|
if (state.bounded) {
|
|
3059
3075
|
lines.push(
|
|
3060
|
-
|
|
3076
|
+
`\u2026[rendered context bounded to ${budget} chars; ${state.omitted} item(s) omitted \u2014 fetch full node content by uid, narrow the query, raise max_output_chars, or pass format: "json" for the raw response]`
|
|
3061
3077
|
);
|
|
3062
3078
|
}
|
|
3063
|
-
return lines.join("\n\n");
|
|
3079
|
+
return lines.join("\n\n").slice(0, budget);
|
|
3064
3080
|
}
|
|
3065
3081
|
function policySections(payload, state) {
|
|
3066
3082
|
const policies = Array.isArray(payload.applicable_policies) ? payload.applicable_policies : [];
|
|
@@ -3081,7 +3097,7 @@ function hiddenSections(payload) {
|
|
|
3081
3097
|
}
|
|
3082
3098
|
];
|
|
3083
3099
|
}
|
|
3084
|
-
function renderContext(response) {
|
|
3100
|
+
function renderContext(response, maxChars) {
|
|
3085
3101
|
const payload = obj(response);
|
|
3086
3102
|
if (!payload) return void 0;
|
|
3087
3103
|
const graph = obj(payload.graph);
|
|
@@ -3091,7 +3107,7 @@ function renderContext(response) {
|
|
|
3091
3107
|
const infraOnly = shaped.length - nodes.length;
|
|
3092
3108
|
const articles = Array.isArray(payload.articles) ? payload.articles : [];
|
|
3093
3109
|
const chunks = Array.isArray(payload.chunks) ? payload.chunks : [];
|
|
3094
|
-
const state = { bounded: false };
|
|
3110
|
+
const state = { bounded: false, omitted: 0 };
|
|
3095
3111
|
const sections = [];
|
|
3096
3112
|
if (articles.length > 0) {
|
|
3097
3113
|
sections.push({
|
|
@@ -3134,11 +3150,129 @@ ${clip(article.content, ARTICLE_MAX, state) || ""}`
|
|
|
3134
3150
|
return "No results found for this search.";
|
|
3135
3151
|
}
|
|
3136
3152
|
if (nodes.length === 0 && articles.length === 0 && chunks.length === 0) {
|
|
3137
|
-
return assemble(
|
|
3153
|
+
return assemble(
|
|
3154
|
+
"# Retrieved context\n\nNo graph results matched this search.",
|
|
3155
|
+
sections,
|
|
3156
|
+
state,
|
|
3157
|
+
maxChars
|
|
3158
|
+
);
|
|
3159
|
+
}
|
|
3160
|
+
return assemble("# Retrieved context", sections, state, maxChars);
|
|
3161
|
+
}
|
|
3162
|
+
function resumeEntry(raw, state, fallbackType) {
|
|
3163
|
+
const wrapper = obj(raw);
|
|
3164
|
+
if (!wrapper) return void 0;
|
|
3165
|
+
const value = obj(wrapper.node) ?? wrapper;
|
|
3166
|
+
if (isNodeShaped(value)) return nodeLines(value, state);
|
|
3167
|
+
const uid = str(value.uid);
|
|
3168
|
+
const props = obj(value.props);
|
|
3169
|
+
const label = clip(value.label, LABEL_MAX, state) ?? clip(value.name, LABEL_MAX, state) ?? clip(value.title, LABEL_MAX, state) ?? clip(value.action, LABEL_MAX, state) ?? fallbackType;
|
|
3170
|
+
const status = str(value.status) ?? str(props?.status);
|
|
3171
|
+
const summary = clip(value.summary, SUMMARY_MAX, state) ?? clip(value.description, SUMMARY_MAX, state) ?? clip(value.content, SUMMARY_MAX, state) ?? clip(value.outcome_summary, SUMMARY_MAX, state) ?? clip(props?.summary, SUMMARY_MAX, state);
|
|
3172
|
+
const details = [
|
|
3173
|
+
status ? `status ${status}` : void 0,
|
|
3174
|
+
str(value.path) ? `path ${str(value.path)}` : void 0,
|
|
3175
|
+
str(value.symbol) ? `symbol ${str(value.symbol)}` : void 0
|
|
3176
|
+
].filter(Boolean);
|
|
3177
|
+
const head = `- **${label}**${uid ? ` [${uid}]` : ""}${details.length > 0 ? ` (${details.join(", ")})` : ""}`;
|
|
3178
|
+
return summary && summary !== label ? `${head}: ${summary}` : head;
|
|
3179
|
+
}
|
|
3180
|
+
function resumeSection(heading, values, state, fallbackType) {
|
|
3181
|
+
const items = values.map((value) => resumeEntry(value, state, fallbackType)).filter((value) => Boolean(value));
|
|
3182
|
+
return items.length > 0 ? { heading, items } : void 0;
|
|
3183
|
+
}
|
|
3184
|
+
function renderResumeContext(response, maxChars) {
|
|
3185
|
+
const payload = obj(response);
|
|
3186
|
+
if (!payload) return void 0;
|
|
3187
|
+
const state = { bounded: false, omitted: 0 };
|
|
3188
|
+
const status = str(payload.status);
|
|
3189
|
+
if (!payload.task && status === "no_eligible_work") {
|
|
3190
|
+
const scopedOut = Array.isArray(payload.scoped_out_tasks) ? payload.scoped_out_tasks.length : 0;
|
|
3191
|
+
const note = scopedOut > 0 ? ` ${scopedOut} task(s) exist outside the requested scope.` : "";
|
|
3192
|
+
return assemble(
|
|
3193
|
+
"# Resume context",
|
|
3194
|
+
[{ heading: `No eligible work was found in the requested scope.${note}`, items: [] }],
|
|
3195
|
+
state,
|
|
3196
|
+
maxChars
|
|
3197
|
+
);
|
|
3138
3198
|
}
|
|
3139
|
-
|
|
3199
|
+
const sections = [];
|
|
3200
|
+
const push = (section) => {
|
|
3201
|
+
if (section) sections.push(section);
|
|
3202
|
+
};
|
|
3203
|
+
push(resumeSection("## Current task", [payload.task], state, "Task"));
|
|
3204
|
+
push(
|
|
3205
|
+
resumeSection(
|
|
3206
|
+
"## Goal and project",
|
|
3207
|
+
[payload.goal, payload.project].filter(Boolean),
|
|
3208
|
+
state,
|
|
3209
|
+
"Scope"
|
|
3210
|
+
)
|
|
3211
|
+
);
|
|
3212
|
+
push(resumeSection("## Plan", [payload.plan], state, "Plan"));
|
|
3213
|
+
push(
|
|
3214
|
+
resumeSection(
|
|
3215
|
+
"## Next steps",
|
|
3216
|
+
Array.isArray(payload.next_steps) ? payload.next_steps : [],
|
|
3217
|
+
state,
|
|
3218
|
+
"Next step"
|
|
3219
|
+
)
|
|
3220
|
+
);
|
|
3221
|
+
push(
|
|
3222
|
+
resumeSection(
|
|
3223
|
+
"## Blockers",
|
|
3224
|
+
Array.isArray(payload.blockers) ? payload.blockers : [],
|
|
3225
|
+
state,
|
|
3226
|
+
"Blocker"
|
|
3227
|
+
)
|
|
3228
|
+
);
|
|
3229
|
+
const knowledge = obj(payload.knowledge);
|
|
3230
|
+
push(
|
|
3231
|
+
resumeSection(
|
|
3232
|
+
"## Relevant lessons and risks",
|
|
3233
|
+
[
|
|
3234
|
+
...Array.isArray(knowledge?.lessons) ? knowledge.lessons : [],
|
|
3235
|
+
...Array.isArray(knowledge?.risks) ? knowledge.risks : []
|
|
3236
|
+
],
|
|
3237
|
+
state,
|
|
3238
|
+
"Knowledge"
|
|
3239
|
+
)
|
|
3240
|
+
);
|
|
3241
|
+
push(
|
|
3242
|
+
resumeSection(
|
|
3243
|
+
"## Active execution",
|
|
3244
|
+
[payload.active_execution].filter(Boolean),
|
|
3245
|
+
state,
|
|
3246
|
+
"Execution"
|
|
3247
|
+
)
|
|
3248
|
+
);
|
|
3249
|
+
push(
|
|
3250
|
+
resumeSection(
|
|
3251
|
+
"## Recent executions",
|
|
3252
|
+
Array.isArray(payload.recent_executions) ? payload.recent_executions : [],
|
|
3253
|
+
state,
|
|
3254
|
+
"Execution"
|
|
3255
|
+
)
|
|
3256
|
+
);
|
|
3257
|
+
push(
|
|
3258
|
+
resumeSection(
|
|
3259
|
+
"## Code targets",
|
|
3260
|
+
Array.isArray(payload.code_targets) ? payload.code_targets : [],
|
|
3261
|
+
state,
|
|
3262
|
+
"Code target"
|
|
3263
|
+
)
|
|
3264
|
+
);
|
|
3265
|
+
push(resumeSection("## Lease", [payload.lease].filter(Boolean), state, "Lease"));
|
|
3266
|
+
const warning = clip(payload.warning, SUMMARY_MAX, state);
|
|
3267
|
+
if (warning) sections.push({ heading: "## Warning", items: [`- ${warning}`] });
|
|
3268
|
+
const selectionReason = clip(payload.selection_reason, SUMMARY_MAX, state);
|
|
3269
|
+
if (selectionReason) {
|
|
3270
|
+
sections.push({ heading: "## Selection", items: [`- ${selectionReason}`] });
|
|
3271
|
+
}
|
|
3272
|
+
if (sections.length === 0) return void 0;
|
|
3273
|
+
return assemble("# Resume context", sections, state, maxChars);
|
|
3140
3274
|
}
|
|
3141
|
-
function renderNodeList(response, title, limit) {
|
|
3275
|
+
function renderNodeList(response, title, limit, maxChars) {
|
|
3142
3276
|
let candidates = [];
|
|
3143
3277
|
if (Array.isArray(response)) {
|
|
3144
3278
|
candidates = response;
|
|
@@ -3156,8 +3290,9 @@ function renderNodeList(response, title, limit) {
|
|
|
3156
3290
|
let nodes = candidates.map(unwrapSearchResult).filter((node) => Boolean(node));
|
|
3157
3291
|
if (nodes.length === 0) return void 0;
|
|
3158
3292
|
const total = nodes.length;
|
|
3159
|
-
const state = { bounded: false };
|
|
3293
|
+
const state = { bounded: false, omitted: 0 };
|
|
3160
3294
|
if (limit !== void 0 && limit > 0 && nodes.length > limit) {
|
|
3295
|
+
state.omitted += nodes.length - limit;
|
|
3161
3296
|
nodes = nodes.slice(0, limit);
|
|
3162
3297
|
state.bounded = true;
|
|
3163
3298
|
}
|
|
@@ -3166,18 +3301,23 @@ function renderNodeList(response, title, limit) {
|
|
|
3166
3301
|
return assemble(
|
|
3167
3302
|
`# ${title} (${shown === total ? total : `${shown} of ${total}`})`,
|
|
3168
3303
|
sections,
|
|
3169
|
-
state
|
|
3304
|
+
state,
|
|
3305
|
+
maxChars
|
|
3170
3306
|
);
|
|
3171
3307
|
}
|
|
3172
|
-
function renderTraversal(response) {
|
|
3308
|
+
function renderTraversal(response, maxChars) {
|
|
3309
|
+
const directSteps = Array.isArray(response) ? response : void 0;
|
|
3173
3310
|
const payload = obj(response);
|
|
3174
|
-
if (!payload) return void 0;
|
|
3175
|
-
const
|
|
3311
|
+
if (!payload && !directSteps) return void 0;
|
|
3312
|
+
const body = payload ?? {};
|
|
3313
|
+
const container = obj(body.graph) ?? body;
|
|
3176
3314
|
const rawNodes = Array.isArray(container.nodes) ? container.nodes : [];
|
|
3177
3315
|
const nodes = rawNodes.filter(isNodeShaped);
|
|
3178
|
-
const paths = Array.isArray(
|
|
3179
|
-
|
|
3180
|
-
const
|
|
3316
|
+
const paths = Array.isArray(body.paths) ? body.paths : [];
|
|
3317
|
+
const hasSteps = directSteps !== void 0 || Object.hasOwn(body, "steps");
|
|
3318
|
+
const rawSteps = directSteps ?? (Array.isArray(body.steps) ? body.steps : []);
|
|
3319
|
+
if (nodes.length === 0 && paths.length === 0 && !hasSteps) return void 0;
|
|
3320
|
+
const state = { bounded: false, omitted: 0 };
|
|
3181
3321
|
const sections = [];
|
|
3182
3322
|
const labelByUid = /* @__PURE__ */ new Map();
|
|
3183
3323
|
for (const node of nodes) labelByUid.set(str(node.uid), str(node.label) || "?");
|
|
@@ -3201,6 +3341,42 @@ function renderTraversal(response) {
|
|
|
3201
3341
|
});
|
|
3202
3342
|
sections.push({ heading: "## Paths", items });
|
|
3203
3343
|
}
|
|
3344
|
+
if (hasSteps) {
|
|
3345
|
+
const stepItems = rawSteps.map((raw) => obj(raw)).filter((step) => Boolean(step)).map((step) => {
|
|
3346
|
+
const depth = num(step.depth);
|
|
3347
|
+
const uid = str(step.node_uid) ?? str(step.uid) ?? str(step.edge_to_uid) ?? "?";
|
|
3348
|
+
const parent = str(step.parent_uid) ?? str(step.edge_from_uid);
|
|
3349
|
+
const label = str(step.label) || "(unlabeled)";
|
|
3350
|
+
const relation = edgeTypeName(step.edge_type);
|
|
3351
|
+
const role = str(step.traversal_role);
|
|
3352
|
+
const type = str(step.node_type) ?? str(obj(step.node_type)?.Custom);
|
|
3353
|
+
const cost = num(step.path_cost);
|
|
3354
|
+
const confidence = num(step.path_confidence);
|
|
3355
|
+
const prefix = [
|
|
3356
|
+
depth !== void 0 ? `depth ${depth}` : void 0,
|
|
3357
|
+
role,
|
|
3358
|
+
relation ? `\u2014${relation}\u2192` : void 0
|
|
3359
|
+
].filter(Boolean).join(" ");
|
|
3360
|
+
const meta = [
|
|
3361
|
+
type,
|
|
3362
|
+
parent ? `parent ${parent}` : void 0,
|
|
3363
|
+
cost !== void 0 ? `cost ${cost}` : void 0,
|
|
3364
|
+
confidence !== void 0 ? `confidence ${confidence}` : void 0
|
|
3365
|
+
].filter(Boolean).join(", ");
|
|
3366
|
+
return `- ${prefix ? `${prefix}: ` : ""}**${label}** [${uid}]${meta ? ` (${meta})` : ""}`;
|
|
3367
|
+
});
|
|
3368
|
+
if (stepItems.length > 0) {
|
|
3369
|
+
sections.push({ heading: "## Traversal steps", items: stepItems });
|
|
3370
|
+
} else {
|
|
3371
|
+
const start = str(body.start_uid) || "?";
|
|
3372
|
+
const end = str(body.end_uid);
|
|
3373
|
+
const mode2 = str(body.mode);
|
|
3374
|
+
sections.push({
|
|
3375
|
+
heading: mode2 === "path" && end ? `No path found from [${start}] to [${end}].` : `No traversal steps returned from [${start}].`,
|
|
3376
|
+
items: []
|
|
3377
|
+
});
|
|
3378
|
+
}
|
|
3379
|
+
}
|
|
3204
3380
|
if (nodes.length > 0) {
|
|
3205
3381
|
sections.push(...groupedNodeSections(nodes, state, "## Nodes\n\n"));
|
|
3206
3382
|
const relationships = relationshipItems(
|
|
@@ -3212,7 +3388,13 @@ function renderTraversal(response) {
|
|
|
3212
3388
|
sections.push({ heading: "## Relationships", items: relationships });
|
|
3213
3389
|
}
|
|
3214
3390
|
}
|
|
3215
|
-
|
|
3391
|
+
const mode = str(body.mode);
|
|
3392
|
+
return assemble(
|
|
3393
|
+
`# Graph traversal${mode ? ` (${mode})` : ""}`,
|
|
3394
|
+
sections,
|
|
3395
|
+
state,
|
|
3396
|
+
maxChars
|
|
3397
|
+
);
|
|
3216
3398
|
}
|
|
3217
3399
|
function neighborLine(value) {
|
|
3218
3400
|
const node = obj(value);
|
|
@@ -3233,7 +3415,7 @@ function renderOntologyAnswer(response) {
|
|
|
3233
3415
|
if (objects.length === 0 && cognitiveEmpty && provenance.length === 0) {
|
|
3234
3416
|
return hasQuerySignature ? "No matching domain objects." : void 0;
|
|
3235
3417
|
}
|
|
3236
|
-
const state = { bounded: false };
|
|
3418
|
+
const state = { bounded: false, omitted: 0 };
|
|
3237
3419
|
const sections = [];
|
|
3238
3420
|
if (objects.length > 0) {
|
|
3239
3421
|
sections.push(...groupedNodeSections(objects, state));
|
|
@@ -3299,7 +3481,7 @@ function renderObjectList(response, title) {
|
|
|
3299
3481
|
if (items.length === 0) {
|
|
3300
3482
|
return rawItems ? `# ${title} (0 results)` : void 0;
|
|
3301
3483
|
}
|
|
3302
|
-
const state = { bounded: false };
|
|
3484
|
+
const state = { bounded: false, omitted: 0 };
|
|
3303
3485
|
const sections = groupedNodeSections(items, state);
|
|
3304
3486
|
const total = num(payload.total_count);
|
|
3305
3487
|
const truncations = Array.isArray(payload.truncation_reasons) ? payload.truncation_reasons.filter((reason) => typeof reason === "string") : [];
|
|
@@ -3314,7 +3496,7 @@ function renderJobs(response) {
|
|
|
3314
3496
|
const jobs = Array.isArray(response) ? response : obj(response)?.jobs;
|
|
3315
3497
|
if (!Array.isArray(jobs)) return void 0;
|
|
3316
3498
|
if (jobs.length === 0) return "No ingestion jobs.";
|
|
3317
|
-
const state = { bounded: false };
|
|
3499
|
+
const state = { bounded: false, omitted: 0 };
|
|
3318
3500
|
const sorted = jobs.map((raw) => obj(raw)).filter((job) => Boolean(job)).sort((a, b) => (num(b.created_at) ?? 0) - (num(a.created_at) ?? 0));
|
|
3319
3501
|
const shown = sorted.slice(0, JOBS_RENDER_MAX);
|
|
3320
3502
|
if (shown.length < sorted.length) state.bounded = true;
|
|
@@ -3340,7 +3522,7 @@ function renderJobs(response) {
|
|
|
3340
3522
|
function renderSignals(response) {
|
|
3341
3523
|
const payload = obj(response);
|
|
3342
3524
|
if (!payload) return void 0;
|
|
3343
|
-
const state = { bounded: false };
|
|
3525
|
+
const state = { bounded: false, omitted: 0 };
|
|
3344
3526
|
const sections = [];
|
|
3345
3527
|
for (const [key, value] of Object.entries(payload)) {
|
|
3346
3528
|
if (!Array.isArray(value) || value.length === 0) continue;
|
|
@@ -3364,7 +3546,7 @@ function renderSignals(response) {
|
|
|
3364
3546
|
if (sections.length === 0) return void 0;
|
|
3365
3547
|
return assemble("# Synthesis signals", sections, state);
|
|
3366
3548
|
}
|
|
3367
|
-
var LABEL_MAX, SUMMARY_MAX, QUOTE_MAX, ARTICLE_MAX, CHUNK_MAX, RELATIONSHIP_MAX, RENDER_CHAR_BUDGET, CURATION_EDGE_TYPES, INFRA_NODE_TYPES, JOBS_RENDER_MAX;
|
|
3549
|
+
var LABEL_MAX, SUMMARY_MAX, QUOTE_MAX, ARTICLE_MAX, CHUNK_MAX, RELATIONSHIP_MAX, RENDER_CHAR_BUDGET, MIN_RENDER_CHAR_BUDGET, BOUNDED_MARKER_RESERVE, CURATION_EDGE_TYPES, INFRA_NODE_TYPES, JOBS_RENDER_MAX;
|
|
3368
3550
|
var init_render = __esm({
|
|
3369
3551
|
"src/render.ts"() {
|
|
3370
3552
|
"use strict";
|
|
@@ -3375,13 +3557,570 @@ var init_render = __esm({
|
|
|
3375
3557
|
CHUNK_MAX = 6e3;
|
|
3376
3558
|
RELATIONSHIP_MAX = 40;
|
|
3377
3559
|
RENDER_CHAR_BUDGET = 24e3;
|
|
3560
|
+
MIN_RENDER_CHAR_BUDGET = 512;
|
|
3561
|
+
BOUNDED_MARKER_RESERVE = 220;
|
|
3378
3562
|
CURATION_EDGE_TYPES = /* @__PURE__ */ new Set(["POSSIBLE_DUPLICATE", "PossibleDuplicate"]);
|
|
3379
3563
|
INFRA_NODE_TYPES = /* @__PURE__ */ new Set(["Chunk", "Document", "Article"]);
|
|
3380
3564
|
JOBS_RENDER_MAX = 20;
|
|
3381
3565
|
}
|
|
3382
3566
|
});
|
|
3383
3567
|
|
|
3568
|
+
// src/memory-tool.ts
|
|
3569
|
+
function obj2(value) {
|
|
3570
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
3571
|
+
}
|
|
3572
|
+
function text(value) {
|
|
3573
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
3574
|
+
}
|
|
3575
|
+
function stableJson(value) {
|
|
3576
|
+
if (Array.isArray(value)) return `[${value.map(stableJson).join(",")}]`;
|
|
3577
|
+
if (value && typeof value === "object") {
|
|
3578
|
+
return `{${Object.entries(value).filter(([, item]) => item !== void 0).sort(([left], [right]) => left.localeCompare(right)).map(([key, item]) => `${JSON.stringify(key)}:${stableJson(item)}`).join(",")}}`;
|
|
3579
|
+
}
|
|
3580
|
+
return JSON.stringify(value);
|
|
3581
|
+
}
|
|
3582
|
+
function sha2562(value) {
|
|
3583
|
+
return (0, import_node_crypto7.createHash)("sha256").update(value).digest("hex");
|
|
3584
|
+
}
|
|
3585
|
+
function outputBudget(value) {
|
|
3586
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return DEFAULT_OUTPUT_CHARS;
|
|
3587
|
+
return Math.min(MAX_OUTPUT_CHARS, Math.max(MIN_OUTPUT_CHARS, Math.floor(value)));
|
|
3588
|
+
}
|
|
3589
|
+
function defined(values) {
|
|
3590
|
+
return Object.fromEntries(Object.entries(values).filter(([, value]) => value !== void 0));
|
|
3591
|
+
}
|
|
3592
|
+
function memoryStatus(config = {}) {
|
|
3593
|
+
return {
|
|
3594
|
+
schema_version: RESULT_SCHEMA_VERSION,
|
|
3595
|
+
action: "status",
|
|
3596
|
+
profile: "M0",
|
|
3597
|
+
server: defined({
|
|
3598
|
+
name: "mindgraph-mcp",
|
|
3599
|
+
version: config.serverVersion ?? "unknown",
|
|
3600
|
+
base_url: config.baseUrl
|
|
3601
|
+
}),
|
|
3602
|
+
integration: {
|
|
3603
|
+
adapter_state: "model_controlled",
|
|
3604
|
+
harness: config.harness ?? "generic",
|
|
3605
|
+
configured_tool_profile: config.profile ?? "general",
|
|
3606
|
+
automatic_capture: false,
|
|
3607
|
+
automatic_delivery: false,
|
|
3608
|
+
delivery_verification: "unsupported",
|
|
3609
|
+
curator_mode: "disabled"
|
|
3610
|
+
},
|
|
3611
|
+
scope: defined({ org_id: config.orgId, agent_id: config.agentId }),
|
|
3612
|
+
capabilities: {
|
|
3613
|
+
status: true,
|
|
3614
|
+
topic_context: true,
|
|
3615
|
+
authoritative_resume_context: true,
|
|
3616
|
+
bounded_rendering: true,
|
|
3617
|
+
structured_content: true,
|
|
3618
|
+
typed_explicit_writes: true,
|
|
3619
|
+
lifecycle_event_ingest: false,
|
|
3620
|
+
automatic_context_injection: false,
|
|
3621
|
+
curator_mutation: false
|
|
3622
|
+
},
|
|
3623
|
+
degradation: [
|
|
3624
|
+
{
|
|
3625
|
+
code: "automatic_capture_unavailable",
|
|
3626
|
+
message: "M0 does not observe host lifecycle events; explicit typed write tools remain available."
|
|
3627
|
+
},
|
|
3628
|
+
{
|
|
3629
|
+
code: "delivery_unverified",
|
|
3630
|
+
message: "A successful MCP read does not prove that the host injected or used the returned context."
|
|
3631
|
+
},
|
|
3632
|
+
{
|
|
3633
|
+
code: "curator_disabled",
|
|
3634
|
+
message: "Curator proposals and autonomous mutation are not enabled in M0."
|
|
3635
|
+
}
|
|
3636
|
+
]
|
|
3637
|
+
};
|
|
3638
|
+
}
|
|
3639
|
+
function nodeType(node) {
|
|
3640
|
+
const raw = node.node_type;
|
|
3641
|
+
if (typeof raw === "string") return raw;
|
|
3642
|
+
return text(obj2(raw)?.Custom) ?? "Node";
|
|
3643
|
+
}
|
|
3644
|
+
function compactItem(raw, fallbackType) {
|
|
3645
|
+
const wrapper = obj2(raw);
|
|
3646
|
+
if (!wrapper) return void 0;
|
|
3647
|
+
const value = obj2(wrapper.node) ?? obj2(wrapper.object) ?? wrapper;
|
|
3648
|
+
const uid = text(value.uid) ?? text(value.chunk_uid);
|
|
3649
|
+
if (!uid) return void 0;
|
|
3650
|
+
return defined({
|
|
3651
|
+
uid,
|
|
3652
|
+
type: fallbackType ?? nodeType(value),
|
|
3653
|
+
label: text(value.label) ?? text(value.document_title),
|
|
3654
|
+
truth_status: text(value.truth_status) ?? text(obj2(value.props)?.truth_status),
|
|
3655
|
+
superseded: value.superseded === true ? true : void 0,
|
|
3656
|
+
currently_valid: value.currently_valid === false ? false : void 0,
|
|
3657
|
+
valid_at_time: value.valid_at_time === false ? false : void 0,
|
|
3658
|
+
retrieval_origin: text(value.retrieval_origin),
|
|
3659
|
+
retrieval_depth: typeof value.retrieval_depth === "number" ? value.retrieval_depth : void 0
|
|
3660
|
+
});
|
|
3661
|
+
}
|
|
3662
|
+
function topicCandidates(raw) {
|
|
3663
|
+
const payload = obj2(raw);
|
|
3664
|
+
if (!payload) return [];
|
|
3665
|
+
const graph = obj2(payload.graph);
|
|
3666
|
+
const items = [];
|
|
3667
|
+
for (const article of Array.isArray(payload.articles) ? payload.articles : []) {
|
|
3668
|
+
const item = compactItem(article, "Article");
|
|
3669
|
+
if (item) items.push(item);
|
|
3670
|
+
}
|
|
3671
|
+
const rawNodes = Array.isArray(graph?.nodes) ? graph.nodes : [];
|
|
3672
|
+
const labels = /* @__PURE__ */ new Map();
|
|
3673
|
+
for (const node of rawNodes) {
|
|
3674
|
+
const item = compactItem(node);
|
|
3675
|
+
if (item) {
|
|
3676
|
+
if (HIDDEN_CONTEXT_NODE_TYPES.has(text(item.type) ?? "")) continue;
|
|
3677
|
+
items.push(item);
|
|
3678
|
+
const uid = text(item.uid);
|
|
3679
|
+
const label = text(item.label);
|
|
3680
|
+
if (uid && label) labels.set(uid, label);
|
|
3681
|
+
}
|
|
3682
|
+
}
|
|
3683
|
+
for (const rawEdge of Array.isArray(graph?.edges) ? graph.edges : []) {
|
|
3684
|
+
const edge = obj2(rawEdge);
|
|
3685
|
+
const fromUid = text(edge?.from_uid);
|
|
3686
|
+
const toUid = text(edge?.to_uid);
|
|
3687
|
+
const edgeType = text(edge?.edge_type) ?? text(obj2(edge?.edge_type)?.Custom);
|
|
3688
|
+
if (!fromUid || !toUid || !edgeType || HIDDEN_CONTEXT_EDGE_TYPES.has(edgeType) || !labels.has(fromUid) || !labels.has(toUid)) {
|
|
3689
|
+
continue;
|
|
3690
|
+
}
|
|
3691
|
+
items.push(
|
|
3692
|
+
defined({
|
|
3693
|
+
type: "Relationship",
|
|
3694
|
+
from_uid: fromUid,
|
|
3695
|
+
to_uid: toUid,
|
|
3696
|
+
edge_type: edgeType,
|
|
3697
|
+
from_label: labels.get(fromUid),
|
|
3698
|
+
to_label: labels.get(toUid)
|
|
3699
|
+
})
|
|
3700
|
+
);
|
|
3701
|
+
}
|
|
3702
|
+
for (const chunk of Array.isArray(payload.chunks) ? payload.chunks : []) {
|
|
3703
|
+
const item = compactItem(chunk, "SourceExcerpt");
|
|
3704
|
+
if (item) items.push(item);
|
|
3705
|
+
}
|
|
3706
|
+
return items;
|
|
3707
|
+
}
|
|
3708
|
+
function resumeCandidates(raw) {
|
|
3709
|
+
const payload = obj2(raw);
|
|
3710
|
+
if (!payload) return [];
|
|
3711
|
+
const items = [];
|
|
3712
|
+
for (const key of ["task", "goal", "project", "plan", "active_execution", "lease"]) {
|
|
3713
|
+
const item = compactItem(payload[key], key);
|
|
3714
|
+
if (item) items.push(item);
|
|
3715
|
+
}
|
|
3716
|
+
for (const key of ["next_steps", "recent_executions", "blockers", "code_targets"]) {
|
|
3717
|
+
for (const value of Array.isArray(payload[key]) ? payload[key] : []) {
|
|
3718
|
+
const item = compactItem(value, key.replace(/s$/, ""));
|
|
3719
|
+
if (item) items.push(item);
|
|
3720
|
+
}
|
|
3721
|
+
}
|
|
3722
|
+
const knowledge = obj2(payload.knowledge);
|
|
3723
|
+
for (const key of ["lessons", "risks"]) {
|
|
3724
|
+
for (const value of Array.isArray(knowledge?.[key]) ? knowledge[key] : []) {
|
|
3725
|
+
const item = compactItem(value, key.replace(/s$/, ""));
|
|
3726
|
+
if (item) items.push(item);
|
|
3727
|
+
}
|
|
3728
|
+
}
|
|
3729
|
+
return items;
|
|
3730
|
+
}
|
|
3731
|
+
function visibleItems(candidates, rendered2) {
|
|
3732
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3733
|
+
return candidates.filter((item) => {
|
|
3734
|
+
const uid = text(item.uid);
|
|
3735
|
+
if (uid) {
|
|
3736
|
+
if (seen.has(uid) || !rendered2.includes(`[${uid}]`)) return false;
|
|
3737
|
+
seen.add(uid);
|
|
3738
|
+
return true;
|
|
3739
|
+
}
|
|
3740
|
+
if (item.type === "Relationship") {
|
|
3741
|
+
const from = text(item.from_label);
|
|
3742
|
+
const to = text(item.to_label);
|
|
3743
|
+
const edgeType = text(item.edge_type);
|
|
3744
|
+
if (!from || !to || !edgeType) return false;
|
|
3745
|
+
const key = `${text(item.from_uid)}:${edgeType}:${text(item.to_uid)}`;
|
|
3746
|
+
if (seen.has(key) || !rendered2.includes(`${from} \u2014${edgeType}\u2192 ${to}`)) return false;
|
|
3747
|
+
seen.add(key);
|
|
3748
|
+
return true;
|
|
3749
|
+
}
|
|
3750
|
+
return false;
|
|
3751
|
+
});
|
|
3752
|
+
}
|
|
3753
|
+
function latestTimestamp(value) {
|
|
3754
|
+
let latest;
|
|
3755
|
+
const visit = (current) => {
|
|
3756
|
+
if (Array.isArray(current)) {
|
|
3757
|
+
for (const item of current) visit(item);
|
|
3758
|
+
return;
|
|
3759
|
+
}
|
|
3760
|
+
const record = obj2(current);
|
|
3761
|
+
if (!record) return;
|
|
3762
|
+
for (const [key, item] of Object.entries(record)) {
|
|
3763
|
+
if (["updated_at", "created_at", "completed_at", "started_at", "observed_at"].includes(key) && typeof item === "string" && !Number.isNaN(Date.parse(item)) && (!latest || Date.parse(item) > Date.parse(latest))) {
|
|
3764
|
+
latest = item;
|
|
3765
|
+
}
|
|
3766
|
+
visit(item);
|
|
3767
|
+
}
|
|
3768
|
+
};
|
|
3769
|
+
visit(value);
|
|
3770
|
+
return latest;
|
|
3771
|
+
}
|
|
3772
|
+
function contextWarnings(raw, rendered2, available, returned) {
|
|
3773
|
+
const warnings = [
|
|
3774
|
+
{
|
|
3775
|
+
code: "delivery_unverified",
|
|
3776
|
+
message: "The MCP server returned this context but cannot verify that the host injected or used it."
|
|
3777
|
+
}
|
|
3778
|
+
];
|
|
3779
|
+
const serialized = JSON.stringify(raw);
|
|
3780
|
+
if (available > returned || rendered2.includes("item(s) omitted")) {
|
|
3781
|
+
warnings.push({
|
|
3782
|
+
code: "context_bounded",
|
|
3783
|
+
message: `${Math.max(0, available - returned)} structured item(s) were omitted from the rendered context.`
|
|
3784
|
+
});
|
|
3785
|
+
}
|
|
3786
|
+
if (/"superseded":true/.test(serialized)) {
|
|
3787
|
+
warnings.push({ code: "superseded_items_present", message: "Some retrieved items are superseded." });
|
|
3788
|
+
}
|
|
3789
|
+
if (/"currently_valid":false|"valid_at_time":false/.test(serialized)) {
|
|
3790
|
+
warnings.push({
|
|
3791
|
+
code: "validity_warning",
|
|
3792
|
+
message: "Some retrieved items are outside their current or requested validity window."
|
|
3793
|
+
});
|
|
3794
|
+
}
|
|
3795
|
+
const payload = obj2(raw);
|
|
3796
|
+
if (payload?.truncated === true || obj2(payload?.truncation)) {
|
|
3797
|
+
const truncation = obj2(payload?.truncation);
|
|
3798
|
+
if (payload?.truncated === true || Object.values(truncation ?? {}).some(Boolean)) {
|
|
3799
|
+
warnings.push({ code: "source_truncated", message: "The authoritative source reported truncated fields." });
|
|
3800
|
+
}
|
|
3801
|
+
}
|
|
3802
|
+
if (text(payload?.warning)) {
|
|
3803
|
+
warnings.push({ code: "source_warning", message: text(payload?.warning) });
|
|
3804
|
+
}
|
|
3805
|
+
return warnings;
|
|
3806
|
+
}
|
|
3807
|
+
function error(message) {
|
|
3808
|
+
return {
|
|
3809
|
+
content: [{ type: "text", text: JSON.stringify({ error: message }) }],
|
|
3810
|
+
isError: true
|
|
3811
|
+
};
|
|
3812
|
+
}
|
|
3813
|
+
async function handleMemoryTool(client2, args, config = {}) {
|
|
3814
|
+
const action = text(args.action);
|
|
3815
|
+
if (action === "status") {
|
|
3816
|
+
const status = memoryStatus({ ...config, agentId: text(args.agent_id) ?? config.agentId });
|
|
3817
|
+
return {
|
|
3818
|
+
content: [{ type: "text", text: JSON.stringify(status) }],
|
|
3819
|
+
structuredContent: status
|
|
3820
|
+
};
|
|
3821
|
+
}
|
|
3822
|
+
if (action !== "context") {
|
|
3823
|
+
return error("action must be 'status' or 'context'");
|
|
3824
|
+
}
|
|
3825
|
+
const mode = text(args.mode) ?? (text(args.query) ? "topic" : void 0);
|
|
3826
|
+
if (!mode || !["topic", "continuity", "resume"].includes(mode)) {
|
|
3827
|
+
return error("action='context' requires mode='topic', 'continuity', or 'resume'");
|
|
3828
|
+
}
|
|
3829
|
+
const budget = outputBudget(args.max_output_chars);
|
|
3830
|
+
const agentId = text(args.agent_id) ?? config.agentId;
|
|
3831
|
+
let raw;
|
|
3832
|
+
let rendered2;
|
|
3833
|
+
let strategy;
|
|
3834
|
+
let candidates;
|
|
3835
|
+
if (mode === "topic") {
|
|
3836
|
+
const query = text(args.query);
|
|
3837
|
+
if (!query) return error("mode='topic' requires a non-empty query of 1-3 discriminating keywords");
|
|
3838
|
+
const limit = typeof args.limit === "number" && Number.isFinite(args.limit) ? Math.min(50, Math.max(1, Math.floor(args.limit))) : 8;
|
|
3839
|
+
const request = defined({
|
|
3840
|
+
query,
|
|
3841
|
+
project_uid: text(args.project_uid),
|
|
3842
|
+
node_limit: limit,
|
|
3843
|
+
node_types: Array.isArray(args.node_types) ? args.node_types.map(String) : void 0,
|
|
3844
|
+
layer: text(args.layer),
|
|
3845
|
+
chunk_limit: args.include_chunks === true ? limit : 0,
|
|
3846
|
+
article_limit: args.include_documents === true ? limit : 0,
|
|
3847
|
+
valid_at: text(args.valid_at),
|
|
3848
|
+
include_graph: true,
|
|
3849
|
+
graph_expansion_limit: typeof args.graph_expansion_limit === "number" ? args.graph_expansion_limit : 3,
|
|
3850
|
+
graph_max_depth: typeof args.graph_max_depth === "number" ? args.graph_max_depth : 2
|
|
3851
|
+
});
|
|
3852
|
+
raw = await client2.retrieveContext(request);
|
|
3853
|
+
rendered2 = renderContext(raw, budget) ?? "No results found for this search.";
|
|
3854
|
+
strategy = "retrieve_context";
|
|
3855
|
+
candidates = topicCandidates(raw);
|
|
3856
|
+
} else {
|
|
3857
|
+
const scopeUids = Array.from(
|
|
3858
|
+
/* @__PURE__ */ new Set([
|
|
3859
|
+
...Array.isArray(args.scope_uids) ? args.scope_uids.map(String) : [],
|
|
3860
|
+
...text(args.project_uid) ? [text(args.project_uid)] : []
|
|
3861
|
+
])
|
|
3862
|
+
);
|
|
3863
|
+
raw = await client2.plan(
|
|
3864
|
+
defined({
|
|
3865
|
+
action: "resume_work",
|
|
3866
|
+
task_uid: text(args.task_uid),
|
|
3867
|
+
session_uid: text(args.session_uid),
|
|
3868
|
+
scope_uids: scopeUids.length > 0 ? scopeUids : void 0,
|
|
3869
|
+
limit: 1,
|
|
3870
|
+
agent_id: agentId
|
|
3871
|
+
})
|
|
3872
|
+
);
|
|
3873
|
+
rendered2 = renderResumeContext(raw, budget) ?? "No eligible work was found in the requested scope.";
|
|
3874
|
+
strategy = "resume_work";
|
|
3875
|
+
candidates = resumeCandidates(raw);
|
|
3876
|
+
}
|
|
3877
|
+
const items = visibleItems(candidates, rendered2);
|
|
3878
|
+
const renderedHash = sha2562(rendered2);
|
|
3879
|
+
const scope = defined({
|
|
3880
|
+
org_id: config.orgId,
|
|
3881
|
+
agent_id: agentId,
|
|
3882
|
+
harness: config.harness ?? "generic",
|
|
3883
|
+
project_uid: text(args.project_uid),
|
|
3884
|
+
task_uid: text(args.task_uid),
|
|
3885
|
+
session_uid: text(args.session_uid),
|
|
3886
|
+
scope_uids: Array.isArray(args.scope_uids) ? args.scope_uids.map(String) : void 0
|
|
3887
|
+
});
|
|
3888
|
+
const contextId = `ctx_${sha2562(
|
|
3889
|
+
stableJson({ mode, scope, strategy, query: text(args.query), rendered_hash: renderedHash })
|
|
3890
|
+
).slice(0, 24)}`;
|
|
3891
|
+
const bounded = candidates.length > items.length || rendered2.includes("item(s) omitted");
|
|
3892
|
+
const result = {
|
|
3893
|
+
schema_version: RESULT_SCHEMA_VERSION,
|
|
3894
|
+
action: "context",
|
|
3895
|
+
context_id: contextId,
|
|
3896
|
+
mode,
|
|
3897
|
+
scope,
|
|
3898
|
+
rendered_context: rendered2,
|
|
3899
|
+
rendered_hash: renderedHash,
|
|
3900
|
+
items,
|
|
3901
|
+
retrieval_trace: defined({
|
|
3902
|
+
strategy,
|
|
3903
|
+
query: text(args.query),
|
|
3904
|
+
project_uid: text(args.project_uid),
|
|
3905
|
+
task_uid: text(args.task_uid),
|
|
3906
|
+
session_uid: text(args.session_uid),
|
|
3907
|
+
node_types: Array.isArray(args.node_types) ? args.node_types.map(String) : void 0,
|
|
3908
|
+
graph_expansion_limit: mode === "topic" ? args.graph_expansion_limit ?? 3 : void 0,
|
|
3909
|
+
graph_max_depth: mode === "topic" ? args.graph_max_depth ?? 2 : void 0,
|
|
3910
|
+
available_items: candidates.length,
|
|
3911
|
+
returned_items: items.length,
|
|
3912
|
+
omitted_items: Math.max(0, candidates.length - items.length)
|
|
3913
|
+
}),
|
|
3914
|
+
budget: {
|
|
3915
|
+
unit: "characters",
|
|
3916
|
+
requested_chars: budget,
|
|
3917
|
+
used_chars: rendered2.length,
|
|
3918
|
+
available_items: candidates.length,
|
|
3919
|
+
returned_items: items.length,
|
|
3920
|
+
omitted_items: Math.max(0, candidates.length - items.length),
|
|
3921
|
+
bounded
|
|
3922
|
+
},
|
|
3923
|
+
freshness: defined({
|
|
3924
|
+
valid_at: text(args.valid_at),
|
|
3925
|
+
latest_source_timestamp: latestTimestamp(raw)
|
|
3926
|
+
}),
|
|
3927
|
+
warnings: contextWarnings(raw, rendered2, candidates.length, items.length)
|
|
3928
|
+
};
|
|
3929
|
+
return {
|
|
3930
|
+
content: [{ type: "text", text: rendered2 }],
|
|
3931
|
+
structuredContent: result
|
|
3932
|
+
};
|
|
3933
|
+
}
|
|
3934
|
+
var import_node_crypto7, RESULT_SCHEMA_VERSION, DEFAULT_OUTPUT_CHARS, MIN_OUTPUT_CHARS, MAX_OUTPUT_CHARS, HIDDEN_CONTEXT_NODE_TYPES, HIDDEN_CONTEXT_EDGE_TYPES, MEMORY_TOOL;
|
|
3935
|
+
var init_memory_tool = __esm({
|
|
3936
|
+
"src/memory-tool.ts"() {
|
|
3937
|
+
"use strict";
|
|
3938
|
+
import_node_crypto7 = require("crypto");
|
|
3939
|
+
init_render();
|
|
3940
|
+
RESULT_SCHEMA_VERSION = "mindgraph.memory.result.v1";
|
|
3941
|
+
DEFAULT_OUTPUT_CHARS = 8e3;
|
|
3942
|
+
MIN_OUTPUT_CHARS = 512;
|
|
3943
|
+
MAX_OUTPUT_CHARS = 24e3;
|
|
3944
|
+
HIDDEN_CONTEXT_NODE_TYPES = /* @__PURE__ */ new Set(["Chunk", "Document", "Article"]);
|
|
3945
|
+
HIDDEN_CONTEXT_EDGE_TYPES = /* @__PURE__ */ new Set(["POSSIBLE_DUPLICATE", "PossibleDuplicate"]);
|
|
3946
|
+
MEMORY_TOOL = {
|
|
3947
|
+
name: "mindgraph_memory",
|
|
3948
|
+
description: "Read the portable MindGraph memory surface. Use action='context' with mode='resume' or 'continuity' for authoritative task-first work state, and mode='topic' with a short keyword query for prior knowledge relevant to the user's request. Use action='status' to inspect integration capabilities and limitations. This tool never writes; durable capture and correction use the existing typed MindGraph write tools.",
|
|
3949
|
+
inputSchema: {
|
|
3950
|
+
type: "object",
|
|
3951
|
+
properties: {
|
|
3952
|
+
action: {
|
|
3953
|
+
type: "string",
|
|
3954
|
+
enum: ["status", "context"],
|
|
3955
|
+
description: "Read integration status or bounded memory context"
|
|
3956
|
+
},
|
|
3957
|
+
mode: {
|
|
3958
|
+
type: "string",
|
|
3959
|
+
enum: ["topic", "continuity", "resume"],
|
|
3960
|
+
description: "Context strategy. topic uses query-shaped retrieval; continuity/resume use authoritative task-first resume_work."
|
|
3961
|
+
},
|
|
3962
|
+
query: {
|
|
3963
|
+
type: "string",
|
|
3964
|
+
description: "Required for mode='topic': 1-3 discriminating BM25 keywords, not a full sentence"
|
|
3965
|
+
},
|
|
3966
|
+
project_uid: { type: "string", description: "Optional project scope" },
|
|
3967
|
+
task_uid: { type: "string", description: "Optional task scope for resume context" },
|
|
3968
|
+
session_uid: { type: "string", description: "Optional durable session scope" },
|
|
3969
|
+
scope_uids: {
|
|
3970
|
+
type: "array",
|
|
3971
|
+
items: { type: "string" },
|
|
3972
|
+
description: "Optional explicit graph scopes for continuity/resume"
|
|
3973
|
+
},
|
|
3974
|
+
node_types: {
|
|
3975
|
+
type: "array",
|
|
3976
|
+
items: { type: "string" },
|
|
3977
|
+
description: "Optional node-type filter for topic context"
|
|
3978
|
+
},
|
|
3979
|
+
layer: {
|
|
3980
|
+
type: "string",
|
|
3981
|
+
enum: ["reality", "epistemic", "intent", "action", "memory", "agent"],
|
|
3982
|
+
description: "Optional cognitive-layer filter for topic context"
|
|
3983
|
+
},
|
|
3984
|
+
limit: {
|
|
3985
|
+
type: "integer",
|
|
3986
|
+
minimum: 1,
|
|
3987
|
+
maximum: 50,
|
|
3988
|
+
default: 8,
|
|
3989
|
+
description: "Maximum direct graph items requested before bounded expansion"
|
|
3990
|
+
},
|
|
3991
|
+
include_chunks: {
|
|
3992
|
+
type: "boolean",
|
|
3993
|
+
default: false,
|
|
3994
|
+
description: "Include bounded source excerpts when topic summaries are insufficient"
|
|
3995
|
+
},
|
|
3996
|
+
include_documents: {
|
|
3997
|
+
type: "boolean",
|
|
3998
|
+
default: false,
|
|
3999
|
+
description: "Include bounded knowledge articles for topic context"
|
|
4000
|
+
},
|
|
4001
|
+
valid_at: {
|
|
4002
|
+
type: "string",
|
|
4003
|
+
description: "Optional ISO timestamp for time-aware topic retrieval"
|
|
4004
|
+
},
|
|
4005
|
+
graph_expansion_limit: {
|
|
4006
|
+
type: "integer",
|
|
4007
|
+
minimum: 0,
|
|
4008
|
+
maximum: 20,
|
|
4009
|
+
default: 3,
|
|
4010
|
+
description: "Bounded graph neighbors added after direct topic matches"
|
|
4011
|
+
},
|
|
4012
|
+
graph_max_depth: {
|
|
4013
|
+
type: "integer",
|
|
4014
|
+
minimum: 0,
|
|
4015
|
+
maximum: 5,
|
|
4016
|
+
default: 2,
|
|
4017
|
+
description: "Maximum graph-expansion depth for topic context"
|
|
4018
|
+
},
|
|
4019
|
+
max_output_chars: {
|
|
4020
|
+
type: "integer",
|
|
4021
|
+
minimum: MIN_OUTPUT_CHARS,
|
|
4022
|
+
maximum: MAX_OUTPUT_CHARS,
|
|
4023
|
+
default: DEFAULT_OUTPUT_CHARS,
|
|
4024
|
+
description: "Hard character budget for model-ready context; whole items are retained or omitted"
|
|
4025
|
+
},
|
|
4026
|
+
agent_id: { type: "string", description: "Agent identity" }
|
|
4027
|
+
},
|
|
4028
|
+
required: ["action"]
|
|
4029
|
+
},
|
|
4030
|
+
outputSchema: {
|
|
4031
|
+
type: "object",
|
|
4032
|
+
properties: {
|
|
4033
|
+
schema_version: { type: "string", const: RESULT_SCHEMA_VERSION },
|
|
4034
|
+
action: { type: "string", enum: ["status", "context"] },
|
|
4035
|
+
profile: { type: "string" },
|
|
4036
|
+
server: { type: "object" },
|
|
4037
|
+
integration: { type: "object" },
|
|
4038
|
+
capabilities: { type: "object" },
|
|
4039
|
+
degradation: { type: "array", items: { type: "object" } },
|
|
4040
|
+
context_id: { type: "string" },
|
|
4041
|
+
mode: { type: "string", enum: ["topic", "continuity", "resume"] },
|
|
4042
|
+
scope: { type: "object" },
|
|
4043
|
+
rendered_context: { type: "string" },
|
|
4044
|
+
rendered_hash: { type: "string" },
|
|
4045
|
+
items: { type: "array", items: { type: "object" } },
|
|
4046
|
+
retrieval_trace: { type: "object" },
|
|
4047
|
+
budget: { type: "object" },
|
|
4048
|
+
freshness: { type: "object" },
|
|
4049
|
+
warnings: { type: "array", items: { type: "object" } }
|
|
4050
|
+
},
|
|
4051
|
+
required: ["schema_version", "action"],
|
|
4052
|
+
oneOf: [
|
|
4053
|
+
{
|
|
4054
|
+
properties: { action: { const: "status" } },
|
|
4055
|
+
required: ["profile", "server", "integration", "scope", "capabilities", "degradation"]
|
|
4056
|
+
},
|
|
4057
|
+
{
|
|
4058
|
+
properties: { action: { const: "context" } },
|
|
4059
|
+
required: [
|
|
4060
|
+
"context_id",
|
|
4061
|
+
"mode",
|
|
4062
|
+
"scope",
|
|
4063
|
+
"rendered_context",
|
|
4064
|
+
"rendered_hash",
|
|
4065
|
+
"items",
|
|
4066
|
+
"retrieval_trace",
|
|
4067
|
+
"budget",
|
|
4068
|
+
"freshness",
|
|
4069
|
+
"warnings"
|
|
4070
|
+
]
|
|
4071
|
+
}
|
|
4072
|
+
]
|
|
4073
|
+
},
|
|
4074
|
+
annotations: {
|
|
4075
|
+
readOnlyHint: true,
|
|
4076
|
+
destructiveHint: false,
|
|
4077
|
+
idempotentHint: true,
|
|
4078
|
+
openWorldHint: false
|
|
4079
|
+
}
|
|
4080
|
+
};
|
|
4081
|
+
}
|
|
4082
|
+
});
|
|
4083
|
+
|
|
3384
4084
|
// src/tools.ts
|
|
4085
|
+
function stableJson2(value) {
|
|
4086
|
+
if (Array.isArray(value)) return `[${value.map(stableJson2).join(",")}]`;
|
|
4087
|
+
if (value && typeof value === "object") {
|
|
4088
|
+
return `{${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, item]) => `${JSON.stringify(key)}:${stableJson2(item)}`).join(",")}}`;
|
|
4089
|
+
}
|
|
4090
|
+
return JSON.stringify(value);
|
|
4091
|
+
}
|
|
4092
|
+
function defaultWriteIdempotencyKey(tool, args) {
|
|
4093
|
+
if (typeof args.idempotency_key === "string") return args.idempotency_key;
|
|
4094
|
+
const context = args.invocation_context;
|
|
4095
|
+
const sessionId = context?.harnessSessionId;
|
|
4096
|
+
if (typeof sessionId !== "string" || sessionId.length === 0) return void 0;
|
|
4097
|
+
const canonicalArgs = Object.fromEntries(
|
|
4098
|
+
Object.entries(args).filter(
|
|
4099
|
+
([key]) => key !== "invocation_context" && key !== "idempotency_key"
|
|
4100
|
+
)
|
|
4101
|
+
);
|
|
4102
|
+
return (0, import_node_crypto8.createHash)("sha256").update(
|
|
4103
|
+
stableJson2({
|
|
4104
|
+
harness_session_id: sessionId,
|
|
4105
|
+
harness_turn_id: context?.harnessTurnId ?? null,
|
|
4106
|
+
tool,
|
|
4107
|
+
action: args.action ?? null,
|
|
4108
|
+
args: canonicalArgs
|
|
4109
|
+
})
|
|
4110
|
+
).digest("hex");
|
|
4111
|
+
}
|
|
4112
|
+
function resolutionFields(args) {
|
|
4113
|
+
return Object.fromEntries(
|
|
4114
|
+
[
|
|
4115
|
+
"idempotency_key",
|
|
4116
|
+
"reuse_uid",
|
|
4117
|
+
"supersedes_uid",
|
|
4118
|
+
"contradicts_uid",
|
|
4119
|
+
"confirm_new",
|
|
4120
|
+
"on_near_duplicate"
|
|
4121
|
+
].filter((key) => args[key] !== void 0).map((key) => [key, args[key]])
|
|
4122
|
+
);
|
|
4123
|
+
}
|
|
3385
4124
|
function toolsForProfile(profile = process.env.MINDGRAPH_PROFILE || "general") {
|
|
3386
4125
|
if (profile === "coding") return TOOLS;
|
|
3387
4126
|
return TOOLS.filter(
|
|
@@ -3395,8 +4134,8 @@ function ok3(data) {
|
|
|
3395
4134
|
}
|
|
3396
4135
|
function renderedResult(format, raw, render) {
|
|
3397
4136
|
if (format === "json") return ok3(raw);
|
|
3398
|
-
const
|
|
3399
|
-
return
|
|
4137
|
+
const text2 = render(raw);
|
|
4138
|
+
return text2 !== void 0 ? { content: [{ type: "text", text: text2 }] } : ok3(raw);
|
|
3400
4139
|
}
|
|
3401
4140
|
function err3(message) {
|
|
3402
4141
|
return {
|
|
@@ -3404,8 +4143,22 @@ function err3(message) {
|
|
|
3404
4143
|
isError: true
|
|
3405
4144
|
};
|
|
3406
4145
|
}
|
|
3407
|
-
async function handleTool(client2, name, args) {
|
|
4146
|
+
async function handleTool(client2, name, args, memoryConfig = {}) {
|
|
3408
4147
|
try {
|
|
4148
|
+
if (["mindgraph_capture", "mindgraph_reason", "mindgraph_commit"].includes(name) && args.action !== "get_open_decisions") {
|
|
4149
|
+
const key = defaultWriteIdempotencyKey(name, args);
|
|
4150
|
+
if (key) args = { ...args, idempotency_key: key };
|
|
4151
|
+
const dispositions = [
|
|
4152
|
+
args.reuse_uid,
|
|
4153
|
+
args.supersedes_uid,
|
|
4154
|
+
args.contradicts_uid,
|
|
4155
|
+
args.confirm_new === true ? true : void 0,
|
|
4156
|
+
args.on_near_duplicate
|
|
4157
|
+
].filter((value) => value !== void 0);
|
|
4158
|
+
if (dispositions.length > 1) {
|
|
4159
|
+
return err3("resolution dispositions are mutually exclusive");
|
|
4160
|
+
}
|
|
4161
|
+
}
|
|
3409
4162
|
let result;
|
|
3410
4163
|
switch (name) {
|
|
3411
4164
|
case "mindgraph_capture":
|
|
@@ -3423,6 +4176,9 @@ async function handleTool(client2, name, args) {
|
|
|
3423
4176
|
case "mindgraph_retrieve":
|
|
3424
4177
|
result = await handleRetrieve(client2, args);
|
|
3425
4178
|
break;
|
|
4179
|
+
case "mindgraph_memory":
|
|
4180
|
+
result = await handleMemoryTool(client2, args, memoryConfig);
|
|
4181
|
+
break;
|
|
3426
4182
|
case "mindgraph_series_query":
|
|
3427
4183
|
result = await handleSeriesQuery(client2, args);
|
|
3428
4184
|
break;
|
|
@@ -3504,7 +4260,11 @@ async function handleCapture(client2, args) {
|
|
|
3504
4260
|
work_uid,
|
|
3505
4261
|
execution_uid,
|
|
3506
4262
|
idempotency_key,
|
|
4263
|
+
reuse_uid,
|
|
3507
4264
|
supersedes_uid,
|
|
4265
|
+
contradicts_uid,
|
|
4266
|
+
confirm_new,
|
|
4267
|
+
on_near_duplicate,
|
|
3508
4268
|
summarizes_uids,
|
|
3509
4269
|
entity_type,
|
|
3510
4270
|
source_uid,
|
|
@@ -3528,7 +4288,11 @@ async function handleCapture(client2, args) {
|
|
|
3528
4288
|
work_uid,
|
|
3529
4289
|
execution_uid,
|
|
3530
4290
|
idempotency_key,
|
|
4291
|
+
reuse_uid,
|
|
3531
4292
|
supersedes_uid,
|
|
4293
|
+
contradicts_uid,
|
|
4294
|
+
confirm_new,
|
|
4295
|
+
on_near_duplicate,
|
|
3532
4296
|
summarizes_uids,
|
|
3533
4297
|
props,
|
|
3534
4298
|
agent_id
|
|
@@ -3574,27 +4338,32 @@ async function handleCapture(client2, args) {
|
|
|
3574
4338
|
const journalProps = { content };
|
|
3575
4339
|
if (mood) journalProps.mood = mood;
|
|
3576
4340
|
if (tags) journalProps.tags = tags;
|
|
3577
|
-
return ok3(await client2.journal(label, journalProps, {
|
|
4341
|
+
return ok3(await client2.journal(label, journalProps, {
|
|
4342
|
+
agent_id,
|
|
4343
|
+
idempotency_key,
|
|
4344
|
+
reuse_uid,
|
|
4345
|
+
supersedes_uid,
|
|
4346
|
+
contradicts_uid,
|
|
4347
|
+
confirm_new,
|
|
4348
|
+
on_near_duplicate
|
|
4349
|
+
}));
|
|
3578
4350
|
}
|
|
3579
4351
|
case "entity": {
|
|
3580
4352
|
const type = entity_type || "concept";
|
|
3581
4353
|
const entityProps = { ...props };
|
|
3582
4354
|
if (summary) entityProps.description = summary;
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
default:
|
|
3596
|
-
return ok3(await client2.findOrCreateConcept(label, entityProps, agent_id));
|
|
3597
|
-
}
|
|
4355
|
+
return ok3(await client2.entity({
|
|
4356
|
+
action: "create",
|
|
4357
|
+
label,
|
|
4358
|
+
props: { ...entityProps, entity_type: type },
|
|
4359
|
+
agent_id,
|
|
4360
|
+
idempotency_key,
|
|
4361
|
+
reuse_uid,
|
|
4362
|
+
supersedes_uid,
|
|
4363
|
+
contradicts_uid,
|
|
4364
|
+
confirm_new,
|
|
4365
|
+
on_near_duplicate
|
|
4366
|
+
}));
|
|
3598
4367
|
}
|
|
3599
4368
|
case "observation":
|
|
3600
4369
|
return ok3(
|
|
@@ -3605,7 +4374,13 @@ async function handleCapture(client2, args) {
|
|
|
3605
4374
|
confidence,
|
|
3606
4375
|
salience,
|
|
3607
4376
|
props,
|
|
3608
|
-
agent_id
|
|
4377
|
+
agent_id,
|
|
4378
|
+
idempotency_key,
|
|
4379
|
+
reuse_uid,
|
|
4380
|
+
supersedes_uid,
|
|
4381
|
+
contradicts_uid,
|
|
4382
|
+
confirm_new,
|
|
4383
|
+
on_near_duplicate
|
|
3609
4384
|
})
|
|
3610
4385
|
);
|
|
3611
4386
|
case "source":
|
|
@@ -3617,7 +4392,13 @@ async function handleCapture(client2, args) {
|
|
|
3617
4392
|
confidence,
|
|
3618
4393
|
salience,
|
|
3619
4394
|
props,
|
|
3620
|
-
agent_id
|
|
4395
|
+
agent_id,
|
|
4396
|
+
idempotency_key,
|
|
4397
|
+
reuse_uid,
|
|
4398
|
+
supersedes_uid,
|
|
4399
|
+
contradicts_uid,
|
|
4400
|
+
confirm_new,
|
|
4401
|
+
on_near_duplicate
|
|
3621
4402
|
})
|
|
3622
4403
|
);
|
|
3623
4404
|
case "snippet":
|
|
@@ -3630,26 +4411,38 @@ async function handleCapture(client2, args) {
|
|
|
3630
4411
|
confidence,
|
|
3631
4412
|
salience,
|
|
3632
4413
|
props,
|
|
3633
|
-
agent_id
|
|
4414
|
+
agent_id,
|
|
4415
|
+
idempotency_key,
|
|
4416
|
+
reuse_uid,
|
|
4417
|
+
supersedes_uid,
|
|
4418
|
+
contradicts_uid,
|
|
4419
|
+
confirm_new,
|
|
4420
|
+
on_near_duplicate
|
|
3634
4421
|
})
|
|
3635
4422
|
);
|
|
3636
4423
|
case "concept":
|
|
3637
|
-
return ok3(
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
4424
|
+
return ok3(await client2.entity({
|
|
4425
|
+
action: "create",
|
|
4426
|
+
label,
|
|
4427
|
+
props: {
|
|
4428
|
+
...props,
|
|
4429
|
+
entity_type: "concept",
|
|
4430
|
+
...summary ? { description: summary } : {}
|
|
4431
|
+
},
|
|
4432
|
+
agent_id,
|
|
4433
|
+
idempotency_key,
|
|
4434
|
+
reuse_uid,
|
|
4435
|
+
supersedes_uid,
|
|
4436
|
+
contradicts_uid,
|
|
4437
|
+
confirm_new,
|
|
4438
|
+
on_near_duplicate
|
|
4439
|
+
}));
|
|
3648
4440
|
default:
|
|
3649
4441
|
return err3(`Unknown capture action: ${action}`);
|
|
3650
4442
|
}
|
|
3651
4443
|
}
|
|
3652
4444
|
async function handleReason(client2, args) {
|
|
4445
|
+
const resolution = resolutionFields(args);
|
|
3653
4446
|
const {
|
|
3654
4447
|
action,
|
|
3655
4448
|
label,
|
|
@@ -3682,7 +4475,8 @@ async function handleReason(client2, args) {
|
|
|
3682
4475
|
...warrant.content ? { props: { content: warrant.content } } : {}
|
|
3683
4476
|
} : void 0,
|
|
3684
4477
|
argument,
|
|
3685
|
-
agent_id
|
|
4478
|
+
agent_id,
|
|
4479
|
+
...resolution
|
|
3686
4480
|
})
|
|
3687
4481
|
);
|
|
3688
4482
|
}
|
|
@@ -3695,11 +4489,13 @@ async function handleReason(client2, args) {
|
|
|
3695
4489
|
confidence,
|
|
3696
4490
|
salience,
|
|
3697
4491
|
props,
|
|
3698
|
-
agent_id
|
|
4492
|
+
agent_id,
|
|
4493
|
+
...resolution
|
|
3699
4494
|
})
|
|
3700
4495
|
);
|
|
3701
4496
|
}
|
|
3702
4497
|
async function handleCommit(client2, args) {
|
|
4498
|
+
const resolution = resolutionFields(args);
|
|
3703
4499
|
const {
|
|
3704
4500
|
action,
|
|
3705
4501
|
label,
|
|
@@ -3730,16 +4526,17 @@ async function handleCommit(client2, args) {
|
|
|
3730
4526
|
confidence,
|
|
3731
4527
|
salience,
|
|
3732
4528
|
props,
|
|
3733
|
-
agent_id
|
|
4529
|
+
agent_id,
|
|
4530
|
+
...resolution
|
|
3734
4531
|
})
|
|
3735
4532
|
);
|
|
3736
4533
|
case "open_decision":
|
|
3737
4534
|
if (!label) return err3("label is required for open_decision");
|
|
3738
|
-
return ok3(await client2.openDecision(label, { summary, props, agent_id }));
|
|
4535
|
+
return ok3(await client2.openDecision(label, { summary, props, agent_id, ...resolution }));
|
|
3739
4536
|
case "add_option":
|
|
3740
4537
|
if (!decision_uid) return err3("decision_uid is required for add_option");
|
|
3741
4538
|
if (!label) return err3("label is required for add_option");
|
|
3742
|
-
return ok3(await client2.addOption(decision_uid, label, { summary, props, agent_id }));
|
|
4539
|
+
return ok3(await client2.addOption(decision_uid, label, { summary, props, agent_id, ...resolution }));
|
|
3743
4540
|
case "add_constraint":
|
|
3744
4541
|
if (!decision_uid) return err3("decision_uid is required for add_constraint");
|
|
3745
4542
|
return ok3(
|
|
@@ -3749,7 +4546,8 @@ async function handleCommit(client2, args) {
|
|
|
3749
4546
|
decision_uid,
|
|
3750
4547
|
summary,
|
|
3751
4548
|
props,
|
|
3752
|
-
agent_id
|
|
4549
|
+
agent_id,
|
|
4550
|
+
...resolution
|
|
3753
4551
|
})
|
|
3754
4552
|
);
|
|
3755
4553
|
case "resolve_decision":
|
|
@@ -3763,7 +4561,8 @@ async function handleCommit(client2, args) {
|
|
|
3763
4561
|
as_of_date,
|
|
3764
4562
|
session_id,
|
|
3765
4563
|
retrieval_trace_id,
|
|
3766
|
-
agent_id
|
|
4564
|
+
agent_id,
|
|
4565
|
+
...resolution
|
|
3767
4566
|
})
|
|
3768
4567
|
);
|
|
3769
4568
|
case "get_open_decisions":
|
|
@@ -3844,7 +4643,7 @@ async function handlePlan(client2, args) {
|
|
|
3844
4643
|
output_snapshot,
|
|
3845
4644
|
side_effects,
|
|
3846
4645
|
outcome,
|
|
3847
|
-
error,
|
|
4646
|
+
error: error2,
|
|
3848
4647
|
next_action,
|
|
3849
4648
|
checkpoint_summary,
|
|
3850
4649
|
test_summary,
|
|
@@ -3907,7 +4706,7 @@ async function handlePlan(client2, args) {
|
|
|
3907
4706
|
output_snapshot,
|
|
3908
4707
|
side_effects,
|
|
3909
4708
|
outcome,
|
|
3910
|
-
error,
|
|
4709
|
+
error: error2,
|
|
3911
4710
|
next_action,
|
|
3912
4711
|
checkpoint_summary,
|
|
3913
4712
|
test_summary,
|
|
@@ -3956,7 +4755,7 @@ async function handlePlan(client2, args) {
|
|
|
3956
4755
|
output_snapshot,
|
|
3957
4756
|
side_effects,
|
|
3958
4757
|
outcome,
|
|
3959
|
-
error,
|
|
4758
|
+
error: error2,
|
|
3960
4759
|
props,
|
|
3961
4760
|
agent_id
|
|
3962
4761
|
})
|
|
@@ -4042,6 +4841,7 @@ async function handleRetrieve(client2, args) {
|
|
|
4042
4841
|
const {
|
|
4043
4842
|
action,
|
|
4044
4843
|
format,
|
|
4844
|
+
max_output_chars,
|
|
4045
4845
|
query,
|
|
4046
4846
|
start_uid,
|
|
4047
4847
|
end_uid,
|
|
@@ -4096,7 +4896,7 @@ async function handleRetrieve(client2, args) {
|
|
|
4096
4896
|
graph_expansion_limit: graph_expansion_limit ?? 3,
|
|
4097
4897
|
graph_max_depth: graph_max_depth ?? 2
|
|
4098
4898
|
}),
|
|
4099
|
-
renderContext
|
|
4899
|
+
(raw) => renderContext(raw, max_output_chars)
|
|
4100
4900
|
);
|
|
4101
4901
|
case "text":
|
|
4102
4902
|
if (!query) return err3("query is required for text search");
|
|
@@ -4110,7 +4910,7 @@ async function handleRetrieve(client2, args) {
|
|
|
4110
4910
|
explain,
|
|
4111
4911
|
agent_id
|
|
4112
4912
|
}),
|
|
4113
|
-
(raw) => renderNodeList(raw, `Text search: ${query}
|
|
4913
|
+
(raw) => renderNodeList(raw, `Text search: ${query}`, void 0, max_output_chars)
|
|
4114
4914
|
);
|
|
4115
4915
|
case "semantic":
|
|
4116
4916
|
if (!query) return err3("query is required for semantic search");
|
|
@@ -4124,7 +4924,7 @@ async function handleRetrieve(client2, args) {
|
|
|
4124
4924
|
explain,
|
|
4125
4925
|
agent_id
|
|
4126
4926
|
}),
|
|
4127
|
-
(raw) => renderNodeList(raw, `Semantic search: ${query}
|
|
4927
|
+
(raw) => renderNodeList(raw, `Semantic search: ${query}`, void 0, max_output_chars)
|
|
4128
4928
|
);
|
|
4129
4929
|
case "hybrid":
|
|
4130
4930
|
if (!query) return err3("query is required for hybrid search");
|
|
@@ -4139,7 +4939,7 @@ async function handleRetrieve(client2, args) {
|
|
|
4139
4939
|
agent_id
|
|
4140
4940
|
}),
|
|
4141
4941
|
// With explain, per-leg scoring must survive — raw JSON only.
|
|
4142
|
-
explain ? () => void 0 : (raw) => renderNodeList(raw, `Hybrid search: ${query}
|
|
4942
|
+
explain ? () => void 0 : (raw) => renderNodeList(raw, `Hybrid search: ${query}`, void 0, max_output_chars)
|
|
4143
4943
|
);
|
|
4144
4944
|
// Structured queries. These go through the generic /retrieve action
|
|
4145
4945
|
// dispatch rather than the SDK's no-argument convenience methods — the
|
|
@@ -4157,7 +4957,7 @@ async function handleRetrieve(client2, args) {
|
|
|
4157
4957
|
offset,
|
|
4158
4958
|
agent_id
|
|
4159
4959
|
}),
|
|
4160
|
-
(raw) => renderNodeList(raw, action.replace(/_/g, " "), limit)
|
|
4960
|
+
(raw) => renderNodeList(raw, action.replace(/_/g, " "), limit, max_output_chars)
|
|
4161
4961
|
);
|
|
4162
4962
|
case "stale_derivations":
|
|
4163
4963
|
return rendered2(
|
|
@@ -4166,7 +4966,7 @@ async function handleRetrieve(client2, args) {
|
|
|
4166
4966
|
limit,
|
|
4167
4967
|
offset
|
|
4168
4968
|
}),
|
|
4169
|
-
(raw) => renderNodeList(raw, "stale derivations", limit)
|
|
4969
|
+
(raw) => renderNodeList(raw, "stale derivations", limit, max_output_chars)
|
|
4170
4970
|
);
|
|
4171
4971
|
case "preferences":
|
|
4172
4972
|
return rendered2(
|
|
@@ -4176,7 +4976,7 @@ async function handleRetrieve(client2, args) {
|
|
|
4176
4976
|
limit,
|
|
4177
4977
|
agent_id
|
|
4178
4978
|
}),
|
|
4179
|
-
(raw) => renderNodeList(raw, "Preferences", limit)
|
|
4979
|
+
(raw) => renderNodeList(raw, "Preferences", limit, max_output_chars)
|
|
4180
4980
|
);
|
|
4181
4981
|
case "layer":
|
|
4182
4982
|
if (!layer) return err3("layer is required for layer retrieval");
|
|
@@ -4188,7 +4988,7 @@ async function handleRetrieve(client2, args) {
|
|
|
4188
4988
|
node_types,
|
|
4189
4989
|
agent_id
|
|
4190
4990
|
}),
|
|
4191
|
-
(raw) => renderNodeList(raw, `Layer: ${layer}`, limit)
|
|
4991
|
+
(raw) => renderNodeList(raw, `Layer: ${layer}`, limit, max_output_chars)
|
|
4192
4992
|
);
|
|
4193
4993
|
case "recent":
|
|
4194
4994
|
return rendered2(
|
|
@@ -4202,7 +5002,7 @@ async function handleRetrieve(client2, args) {
|
|
|
4202
5002
|
created_before,
|
|
4203
5003
|
agent_id
|
|
4204
5004
|
}),
|
|
4205
|
-
(raw) => renderNodeList(raw, "Recently ingested", limit)
|
|
5005
|
+
(raw) => renderNodeList(raw, "Recently ingested", limit, max_output_chars)
|
|
4206
5006
|
);
|
|
4207
5007
|
// Document inventory
|
|
4208
5008
|
case "document_index":
|
|
@@ -4211,7 +5011,7 @@ async function handleRetrieve(client2, args) {
|
|
|
4211
5011
|
node_type: "Document",
|
|
4212
5012
|
limit: limit ?? 100
|
|
4213
5013
|
}),
|
|
4214
|
-
(raw) => renderNodeList(raw, "Ingested documents")
|
|
5014
|
+
(raw) => renderNodeList(raw, "Ingested documents", void 0, max_output_chars)
|
|
4215
5015
|
);
|
|
4216
5016
|
// Graph traversal
|
|
4217
5017
|
case "chain":
|
|
@@ -4225,7 +5025,7 @@ async function handleRetrieve(client2, args) {
|
|
|
4225
5025
|
include_provenance,
|
|
4226
5026
|
max_nodes
|
|
4227
5027
|
}),
|
|
4228
|
-
renderTraversal
|
|
5028
|
+
(raw) => renderTraversal(raw, max_output_chars)
|
|
4229
5029
|
);
|
|
4230
5030
|
case "neighborhood":
|
|
4231
5031
|
if (!start_uid) return err3("start_uid is required for neighborhood traversal");
|
|
@@ -4240,7 +5040,7 @@ async function handleRetrieve(client2, args) {
|
|
|
4240
5040
|
include_provenance,
|
|
4241
5041
|
max_nodes
|
|
4242
5042
|
}),
|
|
4243
|
-
renderTraversal
|
|
5043
|
+
(raw) => renderTraversal(raw, max_output_chars)
|
|
4244
5044
|
);
|
|
4245
5045
|
case "path":
|
|
4246
5046
|
if (!start_uid) return err3("start_uid is required for path traversal");
|
|
@@ -4257,7 +5057,7 @@ async function handleRetrieve(client2, args) {
|
|
|
4257
5057
|
include_provenance,
|
|
4258
5058
|
max_nodes
|
|
4259
5059
|
}),
|
|
4260
|
-
renderTraversal
|
|
5060
|
+
(raw) => renderTraversal(raw, max_output_chars)
|
|
4261
5061
|
);
|
|
4262
5062
|
case "subgraph":
|
|
4263
5063
|
if (!start_uid) return err3("start_uid is required for subgraph traversal");
|
|
@@ -4272,7 +5072,7 @@ async function handleRetrieve(client2, args) {
|
|
|
4272
5072
|
include_provenance,
|
|
4273
5073
|
max_nodes
|
|
4274
5074
|
}),
|
|
4275
|
-
renderTraversal
|
|
5075
|
+
(raw) => renderTraversal(raw, max_output_chars)
|
|
4276
5076
|
);
|
|
4277
5077
|
case "top_k_paths":
|
|
4278
5078
|
if (!start_uid) return err3("start_uid is required for top_k_paths");
|
|
@@ -4288,7 +5088,7 @@ async function handleRetrieve(client2, args) {
|
|
|
4288
5088
|
edge_types,
|
|
4289
5089
|
exclude_edge_types
|
|
4290
5090
|
}),
|
|
4291
|
-
renderTraversal
|
|
5091
|
+
(raw) => renderTraversal(raw, max_output_chars)
|
|
4292
5092
|
);
|
|
4293
5093
|
default:
|
|
4294
5094
|
return err3(`Unknown retrieve action: ${action}`);
|
|
@@ -4544,15 +5344,44 @@ async function handleOntology(client2, args) {
|
|
|
4544
5344
|
return err3(`Unknown ontology action: ${action}`);
|
|
4545
5345
|
}
|
|
4546
5346
|
}
|
|
4547
|
-
var TOOLS, INVOCATION_CONTEXT_SCHEMA;
|
|
5347
|
+
var import_node_crypto8, RESOLUTION_PROPERTIES, TOOLS, INVOCATION_CONTEXT_SCHEMA;
|
|
4548
5348
|
var init_tools = __esm({
|
|
4549
5349
|
"src/tools.ts"() {
|
|
4550
5350
|
"use strict";
|
|
5351
|
+
import_node_crypto8 = require("crypto");
|
|
4551
5352
|
init_error_detail();
|
|
4552
5353
|
init_code_tool();
|
|
4553
5354
|
init_codegraph();
|
|
4554
5355
|
init_sync_tool();
|
|
5356
|
+
init_memory_tool();
|
|
4555
5357
|
init_render();
|
|
5358
|
+
RESOLUTION_PROPERTIES = {
|
|
5359
|
+
idempotency_key: {
|
|
5360
|
+
type: "string",
|
|
5361
|
+
description: "Stable retry key; a mismatched replay is rejected"
|
|
5362
|
+
},
|
|
5363
|
+
reuse_uid: {
|
|
5364
|
+
type: "string",
|
|
5365
|
+
description: "Reuse this live same-scope node after a duplicate response"
|
|
5366
|
+
},
|
|
5367
|
+
supersedes_uid: {
|
|
5368
|
+
type: "string",
|
|
5369
|
+
description: "Create and mark this same-scope node as superseded"
|
|
5370
|
+
},
|
|
5371
|
+
contradicts_uid: {
|
|
5372
|
+
type: "string",
|
|
5373
|
+
description: "Create and mark this same-scope node as contradicted"
|
|
5374
|
+
},
|
|
5375
|
+
confirm_new: {
|
|
5376
|
+
type: "boolean",
|
|
5377
|
+
description: "Confirm that the new fact is genuinely distinct"
|
|
5378
|
+
},
|
|
5379
|
+
on_near_duplicate: {
|
|
5380
|
+
type: "string",
|
|
5381
|
+
enum: ["create"],
|
|
5382
|
+
description: "Alias for confirm_new on a near-duplicate response"
|
|
5383
|
+
}
|
|
5384
|
+
};
|
|
4556
5385
|
TOOLS = [
|
|
4557
5386
|
{
|
|
4558
5387
|
name: "mindgraph_capture",
|
|
@@ -4617,14 +5446,7 @@ var init_tools = __esm({
|
|
|
4617
5446
|
type: "string",
|
|
4618
5447
|
description: "Material Execution that produced the lesson"
|
|
4619
5448
|
},
|
|
4620
|
-
|
|
4621
|
-
type: "string",
|
|
4622
|
-
description: "Stable retry key for an intentional capture"
|
|
4623
|
-
},
|
|
4624
|
-
supersedes_uid: {
|
|
4625
|
-
type: "string",
|
|
4626
|
-
description: "Earlier capture corrected or superseded by this one"
|
|
4627
|
-
},
|
|
5449
|
+
...RESOLUTION_PROPERTIES,
|
|
4628
5450
|
summarizes_uids: {
|
|
4629
5451
|
type: "array",
|
|
4630
5452
|
items: { type: "string" },
|
|
@@ -4722,6 +5544,7 @@ var init_tools = __esm({
|
|
|
4722
5544
|
inputSchema: {
|
|
4723
5545
|
type: "object",
|
|
4724
5546
|
properties: {
|
|
5547
|
+
...RESOLUTION_PROPERTIES,
|
|
4725
5548
|
action: {
|
|
4726
5549
|
type: "string",
|
|
4727
5550
|
enum: [
|
|
@@ -4816,6 +5639,7 @@ var init_tools = __esm({
|
|
|
4816
5639
|
inputSchema: {
|
|
4817
5640
|
type: "object",
|
|
4818
5641
|
properties: {
|
|
5642
|
+
...RESOLUTION_PROPERTIES,
|
|
4819
5643
|
action: {
|
|
4820
5644
|
type: "string",
|
|
4821
5645
|
enum: [
|
|
@@ -5174,6 +5998,12 @@ var init_tools = __esm({
|
|
|
5174
5998
|
enum: ["text", "json"],
|
|
5175
5999
|
description: "Output format (default 'text'): a compact rendered context block \u2014 labels, uids, summaries, status tags, relationships. Pass 'json' for the raw server response (full props, source-chunk offsets, retrieval metadata)."
|
|
5176
6000
|
},
|
|
6001
|
+
max_output_chars: {
|
|
6002
|
+
type: "integer",
|
|
6003
|
+
minimum: 512,
|
|
6004
|
+
maximum: 24e3,
|
|
6005
|
+
description: "Hard character budget for rendered text output (512-24000; default 24000). Normal per-field clipping still applies. Whole evidence items are then kept or omitted rather than cut to satisfy this budget; the final marker reports omissions. Ignored when format='json'."
|
|
6006
|
+
},
|
|
5177
6007
|
query: {
|
|
5178
6008
|
type: "string",
|
|
5179
6009
|
description: "Search query \u2014 for 'text'/'context': 1-3 BM25 keywords, drop filler words. For 'semantic'/'hybrid': natural language is OK since it uses vector similarity."
|
|
@@ -5600,6 +6430,7 @@ var init_tools = __esm({
|
|
|
5600
6430
|
required: ["action"]
|
|
5601
6431
|
}
|
|
5602
6432
|
},
|
|
6433
|
+
MEMORY_TOOL,
|
|
5603
6434
|
SYNC_TOOL,
|
|
5604
6435
|
CODE_TOOL
|
|
5605
6436
|
];
|
|
@@ -5620,7 +6451,7 @@ var init_tools = __esm({
|
|
|
5620
6451
|
}
|
|
5621
6452
|
};
|
|
5622
6453
|
for (const tool of TOOLS) {
|
|
5623
|
-
if (tool.name === "mindgraph_retrieve") continue;
|
|
6454
|
+
if (tool.name === "mindgraph_retrieve" || tool.name === "mindgraph_memory") continue;
|
|
5624
6455
|
const schema = tool.inputSchema;
|
|
5625
6456
|
if (schema.properties && !schema.properties.invocation_context) {
|
|
5626
6457
|
schema.properties.invocation_context = INVOCATION_CONTEXT_SCHEMA;
|
|
@@ -5674,8 +6505,8 @@ async function getGeneratedTools(client2) {
|
|
|
5674
6505
|
cache = { tools, byName, fetchedAt: Date.now() };
|
|
5675
6506
|
retryNotBefore = 0;
|
|
5676
6507
|
return { tools, byName };
|
|
5677
|
-
} catch (
|
|
5678
|
-
if (
|
|
6508
|
+
} catch (error2) {
|
|
6509
|
+
if (error2 instanceof DuplicateGeneratedToolError) throw error2;
|
|
5679
6510
|
retryNotBefore = Date.now() + FAILURE_COOLDOWN_MS;
|
|
5680
6511
|
return cache ? { tools: cache.tools, byName: cache.byName } : EMPTY;
|
|
5681
6512
|
}
|
|
@@ -5788,8 +6619,8 @@ var init_generated_tools = __esm({
|
|
|
5788
6619
|
});
|
|
5789
6620
|
rendered = (format, raw, render) => {
|
|
5790
6621
|
if (format === "json") return ok4(raw);
|
|
5791
|
-
const
|
|
5792
|
-
return
|
|
6622
|
+
const text2 = render(raw);
|
|
6623
|
+
return text2 !== void 0 ? { content: [{ type: "text", text: text2 }] } : ok4(raw);
|
|
5793
6624
|
};
|
|
5794
6625
|
err4 = (message) => ({
|
|
5795
6626
|
content: [{ type: "text", text: JSON.stringify({ error: message }) }],
|
|
@@ -5838,6 +6669,7 @@ function unsupportedResponse(status, body) {
|
|
|
5838
6669
|
return lower.includes("unknown governance action") || lower.includes("unknown action") || lower.includes("invalid_governance_action");
|
|
5839
6670
|
}
|
|
5840
6671
|
function toolMutability(toolName, action) {
|
|
6672
|
+
if (toolName === "mindgraph_memory") return "read";
|
|
5841
6673
|
if (toolName === "mindgraph_retrieve") return "read";
|
|
5842
6674
|
if (toolName === "mindgraph_series_query") return "read";
|
|
5843
6675
|
if (toolName === "mindgraph_plan") {
|
|
@@ -5921,8 +6753,8 @@ async function checkMcpGovernance(toolName, args, config) {
|
|
|
5921
6753
|
response = candidate;
|
|
5922
6754
|
body = candidateBody;
|
|
5923
6755
|
break;
|
|
5924
|
-
} catch (
|
|
5925
|
-
lastFailure =
|
|
6756
|
+
} catch (error2) {
|
|
6757
|
+
lastFailure = error2 instanceof Error ? error2.message : String(error2);
|
|
5926
6758
|
if (attempt < retryDelays.length) {
|
|
5927
6759
|
await sleep(retryDelays[attempt]);
|
|
5928
6760
|
continue;
|
|
@@ -6067,8 +6899,10 @@ function json(uri, data) {
|
|
|
6067
6899
|
contents: [{ uri, mimeType: "application/json", text: JSON.stringify(data) }]
|
|
6068
6900
|
};
|
|
6069
6901
|
}
|
|
6070
|
-
async function readResource(client2, uri) {
|
|
6902
|
+
async function readResource(client2, uri, memoryConfig = {}) {
|
|
6071
6903
|
switch (uri) {
|
|
6904
|
+
case "mindgraph://memory/status":
|
|
6905
|
+
return json(uri, memoryStatus(memoryConfig));
|
|
6072
6906
|
case "mindgraph://stats":
|
|
6073
6907
|
return json(uri, await client2.stats());
|
|
6074
6908
|
case "mindgraph://goals":
|
|
@@ -6100,23 +6934,32 @@ async function readResource(client2, uri) {
|
|
|
6100
6934
|
}
|
|
6101
6935
|
throw new Error(`Unknown resource: ${uri}`);
|
|
6102
6936
|
}
|
|
6103
|
-
async function readGovernedResource(client2, uri, governanceConfig) {
|
|
6937
|
+
async function readGovernedResource(client2, uri, governanceConfig, memoryConfig = {}) {
|
|
6938
|
+
const toolName = uri === "mindgraph://memory/status" ? "mindgraph_memory" : RESOURCE_GOVERNANCE_TOOL;
|
|
6939
|
+
const toolArgs = uri === "mindgraph://memory/status" ? { action: "status" } : {};
|
|
6104
6940
|
const governance = await checkMcpGovernance(
|
|
6105
|
-
|
|
6106
|
-
|
|
6941
|
+
toolName,
|
|
6942
|
+
toolArgs,
|
|
6107
6943
|
{ ...governanceConfig, context: { resource_uri: uri } }
|
|
6108
6944
|
);
|
|
6109
6945
|
if (!governance.allowed) {
|
|
6110
6946
|
throw new Error(governance.message);
|
|
6111
6947
|
}
|
|
6112
|
-
return readResource(client2, uri);
|
|
6948
|
+
return readResource(client2, uri, memoryConfig);
|
|
6113
6949
|
}
|
|
6114
6950
|
var RESOURCES, RESOURCE_TEMPLATES, RESOURCE_GOVERNANCE_TOOL;
|
|
6115
6951
|
var init_resources = __esm({
|
|
6116
6952
|
"src/resources.ts"() {
|
|
6117
6953
|
"use strict";
|
|
6118
6954
|
init_governance();
|
|
6955
|
+
init_memory_tool();
|
|
6119
6956
|
RESOURCES = [
|
|
6957
|
+
{
|
|
6958
|
+
uri: "mindgraph://memory/status",
|
|
6959
|
+
name: "Memory Integration Status",
|
|
6960
|
+
description: "Portable memory profile, adapter state, supported capabilities, and explicit limitations",
|
|
6961
|
+
mimeType: "application/json"
|
|
6962
|
+
},
|
|
6120
6963
|
{
|
|
6121
6964
|
uri: "mindgraph://stats",
|
|
6122
6965
|
name: "Graph Statistics",
|
|
@@ -6178,10 +7021,10 @@ async function main() {
|
|
|
6178
7021
|
const transport = new import_stdio.StdioServerTransport();
|
|
6179
7022
|
await server.connect(transport);
|
|
6180
7023
|
console.error(
|
|
6181
|
-
`MindGraph MCP server v${"0.
|
|
7024
|
+
`MindGraph MCP server v${"0.20.0"} running on stdio (${BASE_URL})`
|
|
6182
7025
|
);
|
|
6183
7026
|
}
|
|
6184
|
-
var import_server, import_stdio, import_types, import_node_path6, API_KEY, BASE_URL, AGENT_ID, ORG_ID, PROFILE, HARNESS, client, INSTRUCTIONS, RUNNER_REFRESH, HOOK_SKEW_NOTE, server, GOVERNANCE_CONFIG, PROMPTS;
|
|
7027
|
+
var import_server, import_stdio, import_types, import_node_path6, API_KEY, BASE_URL, AGENT_ID, ORG_ID, PROFILE, HARNESS, client, INSTRUCTIONS, RUNNER_REFRESH, HOOK_SKEW_NOTE, server, GOVERNANCE_CONFIG, MEMORY_RUNTIME_CONFIG, PROMPTS;
|
|
6185
7028
|
var init_src = __esm({
|
|
6186
7029
|
"src/index.ts"() {
|
|
6187
7030
|
"use strict";
|
|
@@ -6219,56 +7062,29 @@ var init_src = __esm({
|
|
|
6219
7062
|
});
|
|
6220
7063
|
INSTRUCTIONS = `You have access to a persistent knowledge graph via MindGraph, plus any ontology tools generated by the active schema.
|
|
6221
7064
|
|
|
6222
|
-
##
|
|
6223
|
-
|
|
6224
|
-
When the user asks about something, your FIRST and ONLY action should be a SINGLE \`mindgraph_retrieve\` call with action "context" and keyword terms from their message. Nothing else first.
|
|
6225
|
-
|
|
6226
|
-
**NEVER do any of these before addressing the user's topic:**
|
|
6227
|
-
- Do NOT retrieve active_goals, open_questions, contradictions, or weak_claims
|
|
6228
|
-
- Do NOT follow a "session lifecycle" or "warm-up" sequence
|
|
6229
|
-
- Do NOT make multiple serial retrieve calls when one "context" call covers it
|
|
6230
|
-
|
|
6231
|
-
There is no session to open. There is no context to pre-load. Just search for what the user asked about.
|
|
7065
|
+
## Default memory workflow: orient \u2192 answer \u2192 preserve
|
|
6232
7066
|
|
|
6233
|
-
**
|
|
6234
|
-
\u2713 CORRECT: \`mindgraph_retrieve({action: "context", query: "Indian philosophy Taoism"})\`
|
|
6235
|
-
\u2717 WRONG: First retrieve active_goals, then open_questions, then search
|
|
6236
|
-
\u2717 WRONG: \`mindgraph_retrieve({action: "context", query: "Tell me about Indian philosophy and Taoism"})\` \u2014 natural language won't match BM25
|
|
7067
|
+
**Orient only when prior durable state may matter.** Self-contained questions do not require a memory call or a warm-up sequence.
|
|
6237
7068
|
|
|
6238
|
-
|
|
7069
|
+
- Resuming work, asking what was in progress, or continuing a task: call \`mindgraph_memory\` once with action \`context\` and mode \`resume\` or \`continuity\`. This uses authoritative, task-first, lease-aware work state.
|
|
7070
|
+
- Asking about a topic that may depend on prior knowledge: call \`mindgraph_memory\` once with action \`context\`, mode \`topic\`, and 1\u20133 discriminating keywords.
|
|
7071
|
+
- Asking about integration capability or automatic behavior: call \`mindgraph_memory\` with action \`status\`.
|
|
7072
|
+
- Use the comprehensive read tools below only when the high-level result is insufficient or the user asks for a specific graph operation.
|
|
6239
7073
|
|
|
6240
|
-
**
|
|
6241
|
-
Use \`action: "context"\` with keywords. By default this returns only graph nodes \u2014 structured knowledge with labels, summaries, types, confidence scores, and edges. This is usually sufficient and keeps results compact.
|
|
7074
|
+
**Answer from the bounded result.** Treat superseded, refuted, or out-of-validity items as warnings, not current facts. Retrieval proves only that the server returned context; it does not prove that a host automatically injected or used it.
|
|
6242
7075
|
|
|
6243
|
-
**
|
|
6244
|
-
If you need the original source text behind a node (for verbatim quotes, citations, or when graph summaries lack detail), use \`action: "context"\` with \`include_chunks: true\`. This adds full document chunks (400-800 words each) to the response.
|
|
7076
|
+
**Preserve selectively after material durable change.** Use the existing typed write tool for a fact, correction, decision, work-state transition, or reusable lesson. Do not write ephemeral conversation, routine mechanics, unsupported guesses, or information already represented accurately. An explicit no-write is the correct outcome when nothing durable changed.
|
|
6245
7077
|
|
|
6246
|
-
|
|
6247
|
-
- \`action: "document_index"\` \u2014 list all ingested documents (titles, dates, UIDs) to see what's in the graph
|
|
7078
|
+
## Topic retrieval details
|
|
6248
7079
|
|
|
6249
|
-
|
|
7080
|
+
Topic context is graph-only by default. Set \`include_chunks: true\` only for source text needed for quotes, citations, or missing detail. Query with a few proper nouns or technical terms rather than a full sentence. If keyword retrieval fails, use \`mindgraph_retrieve\` with \`semantic\` or \`hybrid\`; use \`document_index\` to inspect ingested sources.
|
|
6250
7081
|
|
|
6251
|
-
|
|
7082
|
+
## Comprehensive read tools
|
|
6252
7083
|
|
|
6253
|
-
|
|
6254
|
-
-
|
|
6255
|
-
-
|
|
6256
|
-
-
|
|
6257
|
-
|
|
6258
|
-
If keyword search returns no results, escalate:
|
|
6259
|
-
1. Try synonyms (e.g. \`"global warming"\` instead of \`"climate change"\`)
|
|
6260
|
-
2. Use \`action: "semantic"\` \u2014 vector similarity, natural language OK (e.g. \`"ways to manage stress"\` finds "mental health" nodes)
|
|
6261
|
-
3. Use \`action: "hybrid"\` \u2014 combines BM25 + semantic for best coverage
|
|
6262
|
-
|
|
6263
|
-
## When to READ
|
|
6264
|
-
|
|
6265
|
-
- User asks about topic X \u2192 \`mindgraph_retrieve\` action "context", query "X keywords"
|
|
6266
|
-
- User asks "what documents are in my graph?" \u2192 action "document_index"
|
|
6267
|
-
- User explicitly asks "what are my goals?" \u2192 action "active_goals"
|
|
6268
|
-
- User explicitly asks about open questions \u2192 action "open_questions"
|
|
6269
|
-
- User asks for advice or a recommendation ("suggest a hotel", "what should I read?") \u2192 action "preferences", query "topic keywords" \u2014 tailor the answer to what they like
|
|
6270
|
-
- Explore around a known node \u2192 action "neighborhood" with start_uid
|
|
6271
|
-
- Find connections between nodes \u2192 action "path" with start_uid + end_uid
|
|
7084
|
+
- Explicit graph inventory or state questions \u2192 the matching \`mindgraph_retrieve\` action such as \`document_index\`, \`active_goals\`, or \`open_questions\`
|
|
7085
|
+
- Advice or recommendations \u2192 \`mindgraph_retrieve\` action \`preferences\`, with topic keywords
|
|
7086
|
+
- Explore around a known node \u2192 \`mindgraph_retrieve\` action \`neighborhood\` with start_uid
|
|
7087
|
+
- Find connections between nodes \u2192 \`mindgraph_retrieve\` action \`path\` with start_uid + end_uid
|
|
6272
7088
|
|
|
6273
7089
|
## When to WRITE
|
|
6274
7090
|
|
|
@@ -6303,13 +7119,14 @@ Capture knowledge when the user shares something worth remembering:
|
|
|
6303
7119
|
|
|
6304
7120
|
## Coding profile
|
|
6305
7121
|
|
|
6306
|
-
**
|
|
6307
|
-
- "What was I working on?" / current work state / resuming anything: call \`
|
|
7122
|
+
**Coding recall order:**
|
|
7123
|
+
- "What was I working on?" / current work state / resuming anything: call \`mindgraph_memory\` action \`context\`, mode \`resume\` FIRST. It delegates to structural \`resume_work\`; never answer work state from keyword search ("recent work" famously retrieves people named Work).
|
|
6308
7124
|
- Knowledge about specific code (a function, file, or route): \`mindgraph_code\` action \`recall\` \u2014 anchor-based, not keyword-based.
|
|
6309
7125
|
- Broad knowledge searches: \`mindgraph_retrieve\` as usual, but when searching for work artifacts pass node_types filters (Task, Lesson, RiskAssessment, Claim) to keep personal-graph content out of engineering answers.
|
|
6310
7126
|
|
|
6311
7127
|
- Use mindgraph_sync for explicit, one-way project memory-file imports. It discovers and hashes files, but you deliberately map durable assertions with record; it never writes graph state back to files.
|
|
6312
7128
|
- Capture corrections, decisions with rationale, fixes that survived meaningful failed attempts, durable invariants/preferences, and blockers with evidence.
|
|
7129
|
+
- If a write returns \`near_duplicate\`, choose \`reuse_uid\` or \`supersedes_uid\`; use \`confirm_new\` only for genuinely distinct facts.
|
|
6313
7130
|
- Do not capture routine mechanics, transient command output, facts cheaply derivable from code, unsupported speculation as high-confidence lessons, or completion without evidence.
|
|
6314
7131
|
- Adapter context is owned by ${HARNESS}; omit invocation_context because hooks replace it.`;
|
|
6315
7132
|
} else {
|
|
@@ -6319,7 +7136,7 @@ Capture knowledge when the user shares something worth remembering:
|
|
|
6319
7136
|
}
|
|
6320
7137
|
RUNNER_REFRESH = (() => {
|
|
6321
7138
|
try {
|
|
6322
|
-
return refreshHookRunner("0.
|
|
7139
|
+
return refreshHookRunner("0.20.0", import_node_path6.default.join(__dirname, "cli.js"));
|
|
6323
7140
|
} catch {
|
|
6324
7141
|
return void 0;
|
|
6325
7142
|
}
|
|
@@ -6333,12 +7150,12 @@ Capture knowledge when the user shares something worth remembering:
|
|
|
6333
7150
|
}
|
|
6334
7151
|
})();
|
|
6335
7152
|
console.error(
|
|
6336
|
-
`[mindgraph-mcp] refreshed pinned hook runner ${RUNNER_REFRESH.runnerVersion ? `v${RUNNER_REFRESH.runnerVersion}` : "(pre-sidecar)"} \u2192 v${"0.
|
|
7153
|
+
`[mindgraph-mcp] refreshed pinned hook runner ${RUNNER_REFRESH.runnerVersion ? `v${RUNNER_REFRESH.runnerVersion}` : "(pre-sidecar)"} \u2192 v${"0.20.0"}` + (refreshedSettings.length > 0 ? `; refreshed owned hook entries in ${refreshedSettings.join(", ")}` : "")
|
|
6337
7154
|
);
|
|
6338
7155
|
}
|
|
6339
7156
|
HOOK_SKEW_NOTE = (() => {
|
|
6340
7157
|
try {
|
|
6341
|
-
return versionSkewNote("0.
|
|
7158
|
+
return versionSkewNote("0.20.0");
|
|
6342
7159
|
} catch {
|
|
6343
7160
|
return void 0;
|
|
6344
7161
|
}
|
|
@@ -6352,7 +7169,7 @@ ${HOOK_SKEW_NOTE}`;
|
|
|
6352
7169
|
server = new import_server.Server(
|
|
6353
7170
|
{
|
|
6354
7171
|
name: "mindgraph",
|
|
6355
|
-
version: "0.
|
|
7172
|
+
version: "0.20.0"
|
|
6356
7173
|
},
|
|
6357
7174
|
{
|
|
6358
7175
|
capabilities: {
|
|
@@ -6376,6 +7193,14 @@ ${HOOK_SKEW_NOTE}`;
|
|
|
6376
7193
|
return process.env.MINDGRAPH_GOVERNANCE === "off";
|
|
6377
7194
|
}
|
|
6378
7195
|
};
|
|
7196
|
+
MEMORY_RUNTIME_CONFIG = {
|
|
7197
|
+
serverVersion: "0.20.0",
|
|
7198
|
+
baseUrl: BASE_URL,
|
|
7199
|
+
profile: PROFILE,
|
|
7200
|
+
harness: HARNESS,
|
|
7201
|
+
orgId: ORG_ID,
|
|
7202
|
+
agentId: AGENT_ID
|
|
7203
|
+
};
|
|
6379
7204
|
server.setRequestHandler(import_types.CallToolRequestSchema, async (request) => {
|
|
6380
7205
|
const { name, arguments: args } = request.params;
|
|
6381
7206
|
const rawArgs = { ...args || {} };
|
|
@@ -6395,7 +7220,7 @@ ${HOOK_SKEW_NOTE}`;
|
|
|
6395
7220
|
if (desc) {
|
|
6396
7221
|
return handleGeneratedTool(client, desc, rawArgs);
|
|
6397
7222
|
}
|
|
6398
|
-
return handleTool(client, name, toolArgs);
|
|
7223
|
+
return handleTool(client, name, toolArgs, MEMORY_RUNTIME_CONFIG);
|
|
6399
7224
|
});
|
|
6400
7225
|
PROMPTS = [
|
|
6401
7226
|
{
|
|
@@ -6560,10 +7385,15 @@ ${conversation}`
|
|
|
6560
7385
|
return { resourceTemplates: RESOURCE_TEMPLATES };
|
|
6561
7386
|
});
|
|
6562
7387
|
server.setRequestHandler(import_types.ReadResourceRequestSchema, async (request) => {
|
|
6563
|
-
return readGovernedResource(
|
|
7388
|
+
return readGovernedResource(
|
|
7389
|
+
client,
|
|
7390
|
+
request.params.uri,
|
|
7391
|
+
GOVERNANCE_CONFIG,
|
|
7392
|
+
MEMORY_RUNTIME_CONFIG
|
|
7393
|
+
);
|
|
6564
7394
|
});
|
|
6565
|
-
main().catch((
|
|
6566
|
-
console.error("Fatal error:",
|
|
7395
|
+
main().catch((error2) => {
|
|
7396
|
+
console.error("Fatal error:", error2);
|
|
6567
7397
|
process.exit(1);
|
|
6568
7398
|
});
|
|
6569
7399
|
}
|
|
@@ -6761,12 +7591,12 @@ function scalar(raw) {
|
|
|
6761
7591
|
}
|
|
6762
7592
|
return trimmed;
|
|
6763
7593
|
}
|
|
6764
|
-
function parseSkillMd(
|
|
6765
|
-
if (!
|
|
6766
|
-
const end =
|
|
7594
|
+
function parseSkillMd(text2) {
|
|
7595
|
+
if (!text2.startsWith("---\n")) return null;
|
|
7596
|
+
const end = text2.indexOf("\n---\n", 4);
|
|
6767
7597
|
if (end < 0) return null;
|
|
6768
|
-
const frontmatter =
|
|
6769
|
-
const body =
|
|
7598
|
+
const frontmatter = text2.slice(4, end + 1);
|
|
7599
|
+
const body = text2.slice(end + 5).replace(/^\n/, "").replace(/\n$/, "");
|
|
6770
7600
|
const entries = [];
|
|
6771
7601
|
for (const line of frontmatter.split("\n")) {
|
|
6772
7602
|
const top = /^([A-Za-z0-9_-]+):(.*)$/.exec(line);
|
|
@@ -6812,8 +7642,8 @@ ${line}`;
|
|
|
6812
7642
|
return result;
|
|
6813
7643
|
}
|
|
6814
7644
|
var STATE_FILE = ".mindgraph-skills-state.json";
|
|
6815
|
-
function sha256(
|
|
6816
|
-
return (0, import_node_crypto2.createHash)("sha256").update(
|
|
7645
|
+
function sha256(text2) {
|
|
7646
|
+
return (0, import_node_crypto2.createHash)("sha256").update(text2).digest("hex");
|
|
6817
7647
|
}
|
|
6818
7648
|
function loadState(dir) {
|
|
6819
7649
|
try {
|
|
@@ -6959,13 +7789,13 @@ async function skillsPush(api, skillPath) {
|
|
|
6959
7789
|
if (isSymlink(file)) {
|
|
6960
7790
|
return { outcome: "error", message: `${file} is a symlink; refusing` };
|
|
6961
7791
|
}
|
|
6962
|
-
let
|
|
7792
|
+
let text2;
|
|
6963
7793
|
try {
|
|
6964
|
-
|
|
7794
|
+
text2 = fs2.readFileSync(file, "utf8");
|
|
6965
7795
|
} catch {
|
|
6966
7796
|
return { outcome: "error", message: `could not read ${file}` };
|
|
6967
7797
|
}
|
|
6968
|
-
const parsed = parseSkillMd(
|
|
7798
|
+
const parsed = parseSkillMd(text2);
|
|
6969
7799
|
if (!parsed) {
|
|
6970
7800
|
return {
|
|
6971
7801
|
outcome: "error",
|
|
@@ -7083,8 +7913,8 @@ function withLedger(sessionId, options, update) {
|
|
|
7083
7913
|
try {
|
|
7084
7914
|
lockFd = import_node_fs3.default.openSync(lock, "wx", 384);
|
|
7085
7915
|
break;
|
|
7086
|
-
} catch (
|
|
7087
|
-
if (
|
|
7916
|
+
} catch (error2) {
|
|
7917
|
+
if (error2.code !== "EEXIST") throw error2;
|
|
7088
7918
|
try {
|
|
7089
7919
|
if (Date.now() - import_node_fs3.default.statSync(lock).mtimeMs > 3e3) import_node_fs3.default.unlinkSync(lock);
|
|
7090
7920
|
} catch {
|
|
@@ -7189,11 +8019,11 @@ var BRIEF_CHAR_BUDGET = 9e3;
|
|
|
7189
8019
|
function renderBrief(brief, meta) {
|
|
7190
8020
|
let bounded = false;
|
|
7191
8021
|
const clipTracked = (value, max) => {
|
|
7192
|
-
const
|
|
7193
|
-
if (!
|
|
7194
|
-
if (
|
|
8022
|
+
const text2 = string(value);
|
|
8023
|
+
if (!text2) return void 0;
|
|
8024
|
+
if (text2.length <= max) return text2;
|
|
7195
8025
|
bounded = true;
|
|
7196
|
-
return `${
|
|
8026
|
+
return `${text2.slice(0, max - 1)}\u2026`;
|
|
7197
8027
|
};
|
|
7198
8028
|
const nodeLine = (value, summaryMax) => {
|
|
7199
8029
|
const node = object(value);
|
|
@@ -7352,9 +8182,9 @@ async function repositoryScopeUids(input, client2, options, agentId) {
|
|
|
7352
8182
|
`${repository.repoId}: ${string(payload?.status) || "unresolved"}`
|
|
7353
8183
|
);
|
|
7354
8184
|
return void 0;
|
|
7355
|
-
} catch (
|
|
8185
|
+
} catch (error2) {
|
|
7356
8186
|
failures.push(
|
|
7357
|
-
`${repository.repoId}: ${
|
|
8187
|
+
`${repository.repoId}: ${error2?.message || "resolve failed"}`
|
|
7358
8188
|
);
|
|
7359
8189
|
return void 0;
|
|
7360
8190
|
}
|
|
@@ -7378,12 +8208,12 @@ function hasMindgraphServer(servers) {
|
|
|
7378
8208
|
for (const [name, entry] of Object.entries(servers)) {
|
|
7379
8209
|
if (name === "mindgraph") return true;
|
|
7380
8210
|
const cfg = entry && typeof entry === "object" ? entry : void 0;
|
|
7381
|
-
const
|
|
8211
|
+
const text2 = [
|
|
7382
8212
|
String(cfg?.command ?? ""),
|
|
7383
8213
|
Array.isArray(cfg?.args) ? cfg.args.join(" ") : "",
|
|
7384
8214
|
String(cfg?.url ?? "")
|
|
7385
8215
|
].join(" ");
|
|
7386
|
-
if (
|
|
8216
|
+
if (text2.includes("mindgraph-mcp")) return true;
|
|
7387
8217
|
}
|
|
7388
8218
|
return false;
|
|
7389
8219
|
}
|
|
@@ -7613,7 +8443,7 @@ async function postTool(input, client2, options) {
|
|
|
7613
8443
|
ledger.mutatingOperations += 1;
|
|
7614
8444
|
}
|
|
7615
8445
|
if (!payload?.error) {
|
|
7616
|
-
if (name.includes("mindgraph_capture") && ["lesson", "journal", "skill"].includes(action || "") || name.includes("mindgraph_commit") && action === "resolve_decision" || name.includes("mindgraph_plan") && action === "assess_risk") {
|
|
8446
|
+
if (name.includes("mindgraph_capture") && (["lesson", "journal", "skill"].includes(action || "") || ["observation", "entity"].includes(action || "") && (Array.isArray(args.code_refs) || typeof args.supersedes_uid === "string")) || name.includes("mindgraph_commit") && action === "resolve_decision" || name.includes("mindgraph_plan") && action === "assess_risk") {
|
|
7617
8447
|
ledger.memoryWritten = true;
|
|
7618
8448
|
}
|
|
7619
8449
|
}
|
|
@@ -7894,7 +8724,7 @@ async function runCodexHook(input, client2, options = {}) {
|
|
|
7894
8724
|
|
|
7895
8725
|
// src/cli.ts
|
|
7896
8726
|
init_hook_installer();
|
|
7897
|
-
function recordHookHealth(harness,
|
|
8727
|
+
function recordHookHealth(harness, error2) {
|
|
7898
8728
|
try {
|
|
7899
8729
|
const dir = process.env.MINDGRAPH_RUNTIME_DIR || path7.join(os4.homedir(), ".mindgraph", "runtime");
|
|
7900
8730
|
fs6.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
@@ -7908,7 +8738,7 @@ function recordHookHealth(harness, error) {
|
|
|
7908
8738
|
file,
|
|
7909
8739
|
`${JSON.stringify({
|
|
7910
8740
|
harness,
|
|
7911
|
-
lastError:
|
|
8741
|
+
lastError: error2.slice(0, 500),
|
|
7912
8742
|
lastFailureAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7913
8743
|
consecutiveFailures: failures + 1
|
|
7914
8744
|
})}
|
|
@@ -8131,7 +8961,7 @@ function withHooksFlag() {
|
|
|
8131
8961
|
}
|
|
8132
8962
|
function finishCodeInstall(apiKey, baseUrl, withHooks, agentId) {
|
|
8133
8963
|
if (withHooks) {
|
|
8134
|
-
const runner = installHookRunner(__filename, void 0, "0.
|
|
8964
|
+
const runner = installHookRunner(__filename, void 0, "0.20.0");
|
|
8135
8965
|
console.log(`Installed pinned hook runner at ${runner}`);
|
|
8136
8966
|
const result = installClaudeHooks("user");
|
|
8137
8967
|
console.log(
|
|
@@ -8446,7 +9276,7 @@ ${total} skill(s) synced.`);
|
|
|
8446
9276
|
if (hookHarness !== "claude-code" && hookHarness !== "codex") {
|
|
8447
9277
|
throw new Error("--harness must be claude-code or codex");
|
|
8448
9278
|
}
|
|
8449
|
-
const runner = installHookRunner(__filename, void 0, "0.
|
|
9279
|
+
const runner = installHookRunner(__filename, void 0, "0.20.0");
|
|
8450
9280
|
console.log(`Installed pinned hook runner at ${runner}`);
|
|
8451
9281
|
const result = hookHarness === "codex" ? installCodexHooks(scope, projectDir) : installClaudeHooks(scope, projectDir);
|
|
8452
9282
|
console.log(
|
|
@@ -8527,13 +9357,13 @@ ${total} skill(s) synced.`);
|
|
|
8527
9357
|
process.stdout.write(`${JSON.stringify(output)}
|
|
8528
9358
|
`);
|
|
8529
9359
|
clearHookHealth(hookHarness);
|
|
8530
|
-
} catch (
|
|
9360
|
+
} catch (error2) {
|
|
8531
9361
|
recordHookHealth(
|
|
8532
9362
|
hookHarness,
|
|
8533
|
-
|
|
9363
|
+
error2?.message || "hook failed"
|
|
8534
9364
|
);
|
|
8535
9365
|
console.error(
|
|
8536
|
-
`mindgraph-hook: failing open (${
|
|
9366
|
+
`mindgraph-hook: failing open (${error2?.message || "unknown error"})`
|
|
8537
9367
|
);
|
|
8538
9368
|
process.stdout.write("{}\n");
|
|
8539
9369
|
}
|
|
@@ -8552,7 +9382,7 @@ ${total} skill(s) synced.`);
|
|
|
8552
9382
|
process.exit(1);
|
|
8553
9383
|
}
|
|
8554
9384
|
}
|
|
8555
|
-
main2().catch((
|
|
8556
|
-
console.error("Error:",
|
|
9385
|
+
main2().catch((error2) => {
|
|
9386
|
+
console.error("Error:", error2.message || error2);
|
|
8557
9387
|
process.exit(1);
|
|
8558
9388
|
});
|