mindgraph-mcp 0.14.7 → 0.14.9
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 +28 -7
- package/dist/cli.js +251 -93
- package/dist/index.js +47 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/mindgraph-mcp)
|
|
4
4
|
[](LICENSE)
|
|
5
5
|
|
|
6
|
-
Model Context Protocol server for [MindGraph](https://mindgraph.cloud) — plug your persistent, structured knowledge graph into Claude Desktop, Claude Code, and any MCP-compatible client.
|
|
6
|
+
Model Context Protocol server for [MindGraph](https://mindgraph.cloud) — plug your persistent, structured knowledge graph into Claude Desktop, Claude Code, Codex, and any MCP-compatible client.
|
|
7
7
|
|
|
8
8
|
## Install
|
|
9
9
|
|
|
@@ -77,7 +77,10 @@ which state you're in).
|
|
|
77
77
|
|
|
78
78
|
The hooks open/rebind a Session at start and inject the current work brief,
|
|
79
79
|
stamp every MindGraph tool call with verified session/repo/commit provenance,
|
|
80
|
-
and prompt one reflection checkpoint before a substantial session ends.
|
|
80
|
+
and prompt one reflection checkpoint before a substantial session ends. A
|
|
81
|
+
session automatically re-claims only *this* agent's own prior work; other
|
|
82
|
+
tasks appear in the brief as context, and the agent claims one deliberately
|
|
83
|
+
when it starts that work. They
|
|
81
84
|
**fail open** — if MindGraph is unreachable, your coding session is never
|
|
82
85
|
blocked. `--scope project` (with `--project-dir`) installs into a single
|
|
83
86
|
repository's `.claude/settings.json` instead; `uninstall-hooks` reverses either
|
|
@@ -87,18 +90,36 @@ project settings.
|
|
|
87
90
|
|
|
88
91
|
### Coding agents (Codex)
|
|
89
92
|
|
|
90
|
-
|
|
93
|
+
Codex gets the same durable work substrate through its native command hooks.
|
|
94
|
+
Register the MCP server with a distinct agent identity, then install the hooks:
|
|
91
95
|
|
|
92
96
|
```bash
|
|
93
97
|
codex mcp add mindgraph --env MINDGRAPH_API_KEY=mg_your_key_here \
|
|
94
98
|
--env MINDGRAPH_PROFILE=coding --env MINDGRAPH_HARNESS=codex \
|
|
99
|
+
--env MINDGRAPH_AGENT_ID=codex:your-name \
|
|
95
100
|
-- npx -y mindgraph-mcp@latest
|
|
101
|
+
|
|
102
|
+
npx -y mindgraph-mcp install-hooks --harness codex --scope user \
|
|
103
|
+
--api-key mg_your_key_here --agent-id codex:your-name
|
|
96
104
|
```
|
|
97
105
|
|
|
98
106
|
(or the equivalent `[mcp_servers.mindgraph]` block in Codex's `config.toml`).
|
|
99
|
-
The
|
|
100
|
-
|
|
101
|
-
|
|
107
|
+
The installer copies the pinned self-contained runner to
|
|
108
|
+
`~/.mindgraph/bin/mindgraph-hook.cjs`, merge-safely upserts only entries marked
|
|
109
|
+
`--owner mindgraph`, and writes user hooks to `$CODEX_HOME/hooks.json`
|
|
110
|
+
(`~/.codex/hooks.json` by default). Use `--scope project --project-dir …` for
|
|
111
|
+
`<project>/.codex/hooks.json`. Re-run the install command to refresh owned
|
|
112
|
+
entries; foreign hooks are never changed. Codex requires newly installed or
|
|
113
|
+
changed command hooks to be reviewed with `/hooks` before they run.
|
|
114
|
+
|
|
115
|
+
At SessionStart the adapter opens/rebinds the graph Session and injects one
|
|
116
|
+
bounded work brief, re-claiming only this agent's own prior work.
|
|
117
|
+
PreToolUse replaces forged/absent invocation provenance
|
|
118
|
+
while preserving model-selected work targets, PostToolUse updates only the
|
|
119
|
+
disposable runtime ledger, Stop runs the once-per-session reflection
|
|
120
|
+
checkpoint, and SessionEnd performs best-effort cleanup. All paths fail open:
|
|
121
|
+
missing credentials or an unreachable MindGraph return Codex's no-op response
|
|
122
|
+
and never block the coding session.
|
|
102
123
|
|
|
103
124
|
## What You Get
|
|
104
125
|
|
|
@@ -146,7 +167,7 @@ mindgraph-mcp install Install into Claude Desktop config
|
|
|
146
167
|
mindgraph-mcp install-code Install into Claude Code (--hooks: also install session hooks)
|
|
147
168
|
mindgraph-mcp uninstall Remove from Claude Desktop config
|
|
148
169
|
mindgraph-mcp uninstall-code Remove from Claude Code
|
|
149
|
-
mindgraph-mcp install-hooks Install
|
|
170
|
+
mindgraph-mcp install-hooks Install coding hooks (--harness claude-code|codex)
|
|
150
171
|
mindgraph-mcp uninstall-hooks Remove MindGraph-owned hook entries
|
|
151
172
|
mindgraph-mcp status Show installation status
|
|
152
173
|
```
|
package/dist/cli.js
CHANGED
|
@@ -2651,6 +2651,38 @@ async function handleCommit(client2, args) {
|
|
|
2651
2651
|
return err3(`Unknown commit action: ${action}`);
|
|
2652
2652
|
}
|
|
2653
2653
|
}
|
|
2654
|
+
async function repositoryScopeUidsForTask(client2, options) {
|
|
2655
|
+
const scopeUids = [...new Set(options.scopeUids ?? [])];
|
|
2656
|
+
const cwd = options.invocationContext?.cwd;
|
|
2657
|
+
const repoId = options.invocationContext?.repoId;
|
|
2658
|
+
if (!options.repo && !cwd && !repoId) {
|
|
2659
|
+
return options.scopeUids;
|
|
2660
|
+
}
|
|
2661
|
+
const agentId = options.agentId ?? process.env.MINDGRAPH_AGENT_ID ?? "mcp";
|
|
2662
|
+
const fallbackSpaceUid = options.repoSpaceUid ?? `space:agent:${agentId}`;
|
|
2663
|
+
const env = { ...process.env };
|
|
2664
|
+
if (!options.repo && repoId) {
|
|
2665
|
+
env.MINDGRAPH_REPO_ID = repoId;
|
|
2666
|
+
}
|
|
2667
|
+
const adapter = new CodegraphAdapter({
|
|
2668
|
+
cwd: cwd ?? process.cwd(),
|
|
2669
|
+
env
|
|
2670
|
+
});
|
|
2671
|
+
const repository = await adapter.resolveRepository(options.repo, fallbackSpaceUid);
|
|
2672
|
+
const anchored = await anchorRepository(
|
|
2673
|
+
client2,
|
|
2674
|
+
repository,
|
|
2675
|
+
repository.spaceUid ?? fallbackSpaceUid,
|
|
2676
|
+
agentId
|
|
2677
|
+
);
|
|
2678
|
+
if (!anchored.uid) {
|
|
2679
|
+
throw new Error(
|
|
2680
|
+
`repository scope ${repository.repoId} could not be materialized (${anchored.status ?? "missing uid"})`
|
|
2681
|
+
);
|
|
2682
|
+
}
|
|
2683
|
+
scopeUids.push(anchored.uid);
|
|
2684
|
+
return [...new Set(scopeUids)];
|
|
2685
|
+
}
|
|
2654
2686
|
async function handlePlan(client2, args) {
|
|
2655
2687
|
const {
|
|
2656
2688
|
action,
|
|
@@ -2681,6 +2713,9 @@ async function handlePlan(client2, args) {
|
|
|
2681
2713
|
release_lease,
|
|
2682
2714
|
override_reason,
|
|
2683
2715
|
scope_uids,
|
|
2716
|
+
repo,
|
|
2717
|
+
repo_space_uid,
|
|
2718
|
+
invocation_context,
|
|
2684
2719
|
limit,
|
|
2685
2720
|
confidence,
|
|
2686
2721
|
salience,
|
|
@@ -2710,7 +2745,14 @@ async function handlePlan(client2, args) {
|
|
|
2710
2745
|
case "checkpoint_iteration":
|
|
2711
2746
|
case "block_task":
|
|
2712
2747
|
case "complete_task":
|
|
2713
|
-
case "abandon_iteration":
|
|
2748
|
+
case "abandon_iteration": {
|
|
2749
|
+
const resolvedScopeUids = action === "create_task" ? await repositoryScopeUidsForTask(client2, {
|
|
2750
|
+
scopeUids: scope_uids,
|
|
2751
|
+
repo,
|
|
2752
|
+
repoSpaceUid: repo_space_uid,
|
|
2753
|
+
invocationContext: invocation_context,
|
|
2754
|
+
agentId: agent_id
|
|
2755
|
+
}) : scope_uids;
|
|
2714
2756
|
return ok3(
|
|
2715
2757
|
await client2.plan({
|
|
2716
2758
|
action,
|
|
@@ -2738,7 +2780,7 @@ async function handlePlan(client2, args) {
|
|
|
2738
2780
|
allow_takeover,
|
|
2739
2781
|
release_lease,
|
|
2740
2782
|
override_reason,
|
|
2741
|
-
scope_uids,
|
|
2783
|
+
scope_uids: resolvedScopeUids,
|
|
2742
2784
|
limit,
|
|
2743
2785
|
input_snapshot,
|
|
2744
2786
|
output_snapshot,
|
|
@@ -2753,6 +2795,7 @@ async function handlePlan(client2, args) {
|
|
|
2753
2795
|
agent_id
|
|
2754
2796
|
})
|
|
2755
2797
|
);
|
|
2798
|
+
}
|
|
2756
2799
|
// Execution tracking
|
|
2757
2800
|
case "start_execution":
|
|
2758
2801
|
return ok3(
|
|
@@ -3310,6 +3353,7 @@ var init_tools = __esm({
|
|
|
3310
3353
|
"use strict";
|
|
3311
3354
|
init_error_detail();
|
|
3312
3355
|
init_code_tool();
|
|
3356
|
+
init_codegraph();
|
|
3313
3357
|
init_sync_tool();
|
|
3314
3358
|
TOOLS = [
|
|
3315
3359
|
{
|
|
@@ -3774,7 +3818,7 @@ var init_tools = __esm({
|
|
|
3774
3818
|
scope_uids: {
|
|
3775
3819
|
type: "array",
|
|
3776
3820
|
items: { type: "string" },
|
|
3777
|
-
description: "
|
|
3821
|
+
description: "Required target UIDs for create_task and ordinary target UIDs that bound deterministic resume selection"
|
|
3778
3822
|
},
|
|
3779
3823
|
limit: {
|
|
3780
3824
|
type: "number",
|
|
@@ -4917,7 +4961,7 @@ Capture knowledge when the user shares something worth remembering:
|
|
|
4917
4961
|
server = new import_server.Server(
|
|
4918
4962
|
{
|
|
4919
4963
|
name: "mindgraph",
|
|
4920
|
-
version: "0.14.
|
|
4964
|
+
version: "0.14.9"
|
|
4921
4965
|
},
|
|
4922
4966
|
{
|
|
4923
4967
|
capabilities: {
|
|
@@ -5182,7 +5226,7 @@ function saveHookEnv(env, dir) {
|
|
|
5182
5226
|
// src/cli-args.ts
|
|
5183
5227
|
function parseArgs(argv) {
|
|
5184
5228
|
const args = argv.slice(2);
|
|
5185
|
-
let
|
|
5229
|
+
let command2 = "serve";
|
|
5186
5230
|
let apiKey = process.env.MINDGRAPH_API_KEY;
|
|
5187
5231
|
let baseUrl = process.env.MINDGRAPH_BASE_URL;
|
|
5188
5232
|
let scope = "project";
|
|
@@ -5224,16 +5268,16 @@ function parseArgs(argv) {
|
|
|
5224
5268
|
break;
|
|
5225
5269
|
case "--help":
|
|
5226
5270
|
case "-h":
|
|
5227
|
-
|
|
5271
|
+
command2 = "help";
|
|
5228
5272
|
break;
|
|
5229
5273
|
default:
|
|
5230
5274
|
if (!arg.startsWith("-")) {
|
|
5231
|
-
|
|
5275
|
+
command2 = arg;
|
|
5232
5276
|
}
|
|
5233
5277
|
break;
|
|
5234
5278
|
}
|
|
5235
5279
|
}
|
|
5236
|
-
return { command, apiKey, baseUrl, scope, projectDir, harness, hooks, agentId };
|
|
5280
|
+
return { command: command2, apiKey, baseUrl, scope, projectDir, harness, hooks, agentId };
|
|
5237
5281
|
}
|
|
5238
5282
|
function mcpAddFailureOutput(e) {
|
|
5239
5283
|
const err5 = e;
|
|
@@ -5247,16 +5291,17 @@ function classifyMcpAddFailure(e) {
|
|
|
5247
5291
|
return "other";
|
|
5248
5292
|
}
|
|
5249
5293
|
|
|
5250
|
-
// src/
|
|
5294
|
+
// src/hook-core.ts
|
|
5251
5295
|
var import_node_crypto2 = __toESM(require("crypto"));
|
|
5252
5296
|
var import_node_fs3 = __toESM(require("fs"));
|
|
5253
5297
|
var import_node_os3 = __toESM(require("os"));
|
|
5254
5298
|
var import_node_path3 = __toESM(require("path"));
|
|
5255
5299
|
var import_node_child_process2 = require("child_process");
|
|
5256
5300
|
init_codegraph();
|
|
5257
|
-
|
|
5301
|
+
var NOOP = { kind: "noop" };
|
|
5302
|
+
function defaultLedger(sessionId, options) {
|
|
5258
5303
|
return {
|
|
5259
|
-
harness:
|
|
5304
|
+
harness: options.harness,
|
|
5260
5305
|
harnessSessionId: sessionId,
|
|
5261
5306
|
materialToolCalls: 0,
|
|
5262
5307
|
mutatingOperations: 0,
|
|
@@ -5273,7 +5318,8 @@ function runtimeDir(options) {
|
|
|
5273
5318
|
return options.runtimeDir || process.env.MINDGRAPH_RUNTIME_DIR || import_node_path3.default.join(import_node_os3.default.homedir(), ".mindgraph", "runtime");
|
|
5274
5319
|
}
|
|
5275
5320
|
function ledgerPath(sessionId, options) {
|
|
5276
|
-
const
|
|
5321
|
+
const harness = "harness" in options ? options.harness : "claude-code";
|
|
5322
|
+
const key = import_node_crypto2.default.createHash("sha256").update(`${harness}\0${sessionId}`).digest("hex");
|
|
5277
5323
|
return import_node_path3.default.join(runtimeDir(options), `${key}.json`);
|
|
5278
5324
|
}
|
|
5279
5325
|
function waitBriefly(ms) {
|
|
@@ -5302,10 +5348,10 @@ function withLedger(sessionId, options, update) {
|
|
|
5302
5348
|
}
|
|
5303
5349
|
}
|
|
5304
5350
|
if (lockFd === void 0) {
|
|
5305
|
-
return update(defaultLedger(sessionId));
|
|
5351
|
+
return update(defaultLedger(sessionId, options));
|
|
5306
5352
|
}
|
|
5307
5353
|
try {
|
|
5308
|
-
let ledger = defaultLedger(sessionId);
|
|
5354
|
+
let ledger = defaultLedger(sessionId, options);
|
|
5309
5355
|
try {
|
|
5310
5356
|
ledger = {
|
|
5311
5357
|
...ledger,
|
|
@@ -5356,8 +5402,9 @@ async function invocationContext(input, options) {
|
|
|
5356
5402
|
workspaceFile: options.workspaceFile
|
|
5357
5403
|
}).resolveRepository();
|
|
5358
5404
|
return {
|
|
5359
|
-
harness:
|
|
5405
|
+
harness: options.harness,
|
|
5360
5406
|
harnessSessionId: input.session_id,
|
|
5407
|
+
harnessTurnId: input.turn_id,
|
|
5361
5408
|
cwd: input.cwd,
|
|
5362
5409
|
repoId: repository.repoId,
|
|
5363
5410
|
branch: gitValue(input.cwd, ["branch", "--show-current"]),
|
|
@@ -5434,13 +5481,21 @@ async function repositoryScopeUids(input, client2, options, agentId) {
|
|
|
5434
5481
|
)
|
|
5435
5482
|
];
|
|
5436
5483
|
}
|
|
5484
|
+
function isOwnPriorWork(brief, agentId) {
|
|
5485
|
+
const reason = string(brief?.selection_reason);
|
|
5486
|
+
if (reason === "owned_live_lease" || reason === "same_agent_session_rebind") {
|
|
5487
|
+
return true;
|
|
5488
|
+
}
|
|
5489
|
+
return string(object(brief?.lease)?.lease_owner_agent_id) === agentId;
|
|
5490
|
+
}
|
|
5437
5491
|
async function sessionStart(input, client2, options) {
|
|
5438
|
-
const agentId = options.agentId || process.env.MINDGRAPH_AGENT_ID ||
|
|
5492
|
+
const agentId = options.agentId || process.env.MINDGRAPH_AGENT_ID || options.harness;
|
|
5493
|
+
const harnessLabel = options.harness === "claude-code" ? "Claude Code" : "Codex";
|
|
5439
5494
|
const opened = object(
|
|
5440
5495
|
await client2.session({
|
|
5441
5496
|
action: "open",
|
|
5442
|
-
label:
|
|
5443
|
-
harness:
|
|
5497
|
+
label: `${harnessLabel} ${input.session_id}`,
|
|
5498
|
+
harness: options.harness,
|
|
5444
5499
|
harness_session_id: input.session_id,
|
|
5445
5500
|
model: input.model,
|
|
5446
5501
|
agent_id: agentId
|
|
@@ -5458,7 +5513,7 @@ async function sessionStart(input, client2, options) {
|
|
|
5458
5513
|
);
|
|
5459
5514
|
const task = object(brief?.task);
|
|
5460
5515
|
const lease = object(brief?.lease);
|
|
5461
|
-
if (sessionUid && string(task?.uid) && number(task?.version)) {
|
|
5516
|
+
if (sessionUid && string(task?.uid) && number(task?.version) && isOwnPriorWork(brief, agentId)) {
|
|
5462
5517
|
try {
|
|
5463
5518
|
const claimed = object(
|
|
5464
5519
|
await client2.plan({
|
|
@@ -5483,7 +5538,11 @@ async function sessionStart(input, client2, options) {
|
|
|
5483
5538
|
} catch {
|
|
5484
5539
|
}
|
|
5485
5540
|
}
|
|
5486
|
-
|
|
5541
|
+
const briefText = boundedBrief(brief || { status: "no_eligible_work" });
|
|
5542
|
+
const briefHash = import_node_crypto2.default.createHash("sha256").update(briefText).digest("hex");
|
|
5543
|
+
const shouldInject = withLedger(input.session_id, options, (ledger) => {
|
|
5544
|
+
const changed = ledger.lastBriefHash !== briefHash;
|
|
5545
|
+
const reinjectCompact = options.reinjectUnchangedCompact && input.source === "compact";
|
|
5487
5546
|
ledger.sessionUid = sessionUid;
|
|
5488
5547
|
ledger.baselineWorktree = worktreeState(input.cwd);
|
|
5489
5548
|
const selectedTask = object(brief?.task);
|
|
@@ -5495,14 +5554,10 @@ async function sessionStart(input, client2, options) {
|
|
|
5495
5554
|
ledger.leaseEpoch = number(selectedLease?.lease_epoch);
|
|
5496
5555
|
ledger.leaseExpiresAt = number(selectedLease?.lease_expires_at);
|
|
5497
5556
|
ledger.executionUid = string(object(brief?.active_execution)?.uid) || string(latest?.uid);
|
|
5498
|
-
|
|
5557
|
+
ledger.lastBriefHash = briefHash;
|
|
5558
|
+
return changed || reinjectCompact;
|
|
5499
5559
|
});
|
|
5500
|
-
return {
|
|
5501
|
-
hookSpecificOutput: {
|
|
5502
|
-
hookEventName: "SessionStart",
|
|
5503
|
-
additionalContext: boundedBrief(brief || { status: "no_eligible_work" })
|
|
5504
|
-
}
|
|
5505
|
-
};
|
|
5560
|
+
return shouldInject ? { kind: "context", context: briefText } : NOOP;
|
|
5506
5561
|
}
|
|
5507
5562
|
async function preTool(input, options) {
|
|
5508
5563
|
const original = { ...input.tool_input || {} };
|
|
@@ -5527,12 +5582,7 @@ async function preTool(input, options) {
|
|
|
5527
5582
|
if (ledger.taskVersion !== void 0 && updatedInput.expected_version === void 0) {
|
|
5528
5583
|
updatedInput.expected_version = ledger.taskVersion;
|
|
5529
5584
|
}
|
|
5530
|
-
return {
|
|
5531
|
-
hookSpecificOutput: {
|
|
5532
|
-
hookEventName: "PreToolUse",
|
|
5533
|
-
updatedInput
|
|
5534
|
-
}
|
|
5535
|
-
};
|
|
5585
|
+
return { kind: "rewrite", updatedInput };
|
|
5536
5586
|
}
|
|
5537
5587
|
async function postTool(input, client2, options) {
|
|
5538
5588
|
const name = input.tool_name || "";
|
|
@@ -5543,7 +5593,7 @@ async function postTool(input, client2, options) {
|
|
|
5543
5593
|
let heartbeat;
|
|
5544
5594
|
withLedger(input.session_id, options, (ledger) => {
|
|
5545
5595
|
ledger.materialToolCalls += 1;
|
|
5546
|
-
if (["Edit", "Write", "NotebookEdit"].includes(name) || name === "Bash" && action !== "read") {
|
|
5596
|
+
if (["Edit", "Write", "NotebookEdit", "apply_patch"].includes(name) || name === "Bash" && action !== "read") {
|
|
5547
5597
|
ledger.mutatingOperations += 1;
|
|
5548
5598
|
}
|
|
5549
5599
|
if (name.includes("mindgraph_capture") && !payload?.error) {
|
|
@@ -5583,7 +5633,7 @@ async function postTool(input, client2, options) {
|
|
|
5583
5633
|
expected_version: heartbeat.taskVersion,
|
|
5584
5634
|
lease_epoch: heartbeat.leaseEpoch,
|
|
5585
5635
|
idempotency_key: `hook-heartbeat:${input.session_id}:${heartbeat.taskUid}:${Math.floor(nowSeconds / 60)}`,
|
|
5586
|
-
agent_id: options.agentId ||
|
|
5636
|
+
agent_id: options.agentId || options.harness
|
|
5587
5637
|
})
|
|
5588
5638
|
);
|
|
5589
5639
|
withLedger(input.session_id, options, (ledger) => {
|
|
@@ -5593,24 +5643,25 @@ async function postTool(input, client2, options) {
|
|
|
5593
5643
|
} catch {
|
|
5594
5644
|
}
|
|
5595
5645
|
}
|
|
5596
|
-
return
|
|
5646
|
+
return NOOP;
|
|
5597
5647
|
}
|
|
5598
5648
|
function stop(input, options) {
|
|
5599
|
-
if (input.stop_hook_active) return
|
|
5649
|
+
if (input.stop_hook_active) return NOOP;
|
|
5600
5650
|
return withLedger(input.session_id, options, (ledger) => {
|
|
5601
5651
|
const changed = ledger.mutatingOperations >= 2 || ledger.baselineWorktree !== "unknown" && worktreeState(input.cwd) !== ledger.baselineWorktree;
|
|
5602
5652
|
const substantial = Boolean(ledger.executionUid) || changed;
|
|
5603
5653
|
if (!substantial || ledger.iterationCheckpointed || ledger.memoryWritten || ledger.stopNudged) {
|
|
5604
|
-
return
|
|
5654
|
+
return NOOP;
|
|
5605
5655
|
}
|
|
5606
5656
|
ledger.stopNudged = true;
|
|
5607
5657
|
return {
|
|
5608
|
-
|
|
5658
|
+
kind: "block",
|
|
5609
5659
|
reason: "Substantial work is still uncheckpointed. Checkpoint the active iteration, capture one durable lesson/decision/risk, or explicitly state that nothing durable changed. If a local harness task should become authoritative outside this list, promote it once with a stable idempotency key; otherwise do not copy it."
|
|
5610
5660
|
};
|
|
5611
5661
|
});
|
|
5612
5662
|
}
|
|
5613
5663
|
async function sessionEnd(input, client2, options) {
|
|
5664
|
+
const harnessLabel = options.harness === "claude-code" ? "Claude Code" : "Codex";
|
|
5614
5665
|
const ledger = readLedger(input.session_id, options);
|
|
5615
5666
|
if (ledger.executionUid && ledger.taskUid && ledger.sessionUid && ledger.taskVersion !== void 0 && ledger.leaseEpoch !== void 0) {
|
|
5616
5667
|
try {
|
|
@@ -5622,9 +5673,9 @@ async function sessionEnd(input, client2, options) {
|
|
|
5622
5673
|
expected_version: ledger.taskVersion,
|
|
5623
5674
|
lease_epoch: ledger.leaseEpoch,
|
|
5624
5675
|
release_lease: true,
|
|
5625
|
-
summary:
|
|
5676
|
+
summary: `${harnessLabel} SessionEnd: ${input.reason || "interrupted"}`,
|
|
5626
5677
|
idempotency_key: `session-end:${input.session_id}:${ledger.executionUid}`,
|
|
5627
|
-
agent_id: options.agentId ||
|
|
5678
|
+
agent_id: options.agentId || options.harness
|
|
5628
5679
|
});
|
|
5629
5680
|
} catch {
|
|
5630
5681
|
}
|
|
@@ -5634,19 +5685,19 @@ async function sessionEnd(input, client2, options) {
|
|
|
5634
5685
|
await client2.session({
|
|
5635
5686
|
action: "close",
|
|
5636
5687
|
session_uid: ledger.sessionUid,
|
|
5637
|
-
agent_id: options.agentId ||
|
|
5688
|
+
agent_id: options.agentId || options.harness
|
|
5638
5689
|
});
|
|
5639
5690
|
} catch {
|
|
5640
5691
|
}
|
|
5641
5692
|
}
|
|
5642
|
-
return
|
|
5693
|
+
return NOOP;
|
|
5643
5694
|
}
|
|
5644
|
-
async function
|
|
5695
|
+
async function runHookCore(input, client2, options) {
|
|
5645
5696
|
switch (input.hook_event_name) {
|
|
5646
5697
|
case "SessionStart":
|
|
5647
5698
|
return sessionStart(input, client2, options);
|
|
5648
5699
|
case "PreToolUse":
|
|
5649
|
-
if (!input.tool_name?.startsWith("mcp__mindgraph__")) return
|
|
5700
|
+
if (!input.tool_name?.startsWith("mcp__mindgraph__")) return NOOP;
|
|
5650
5701
|
return preTool(input, options);
|
|
5651
5702
|
case "PostToolUse":
|
|
5652
5703
|
return postTool(input, client2, options);
|
|
@@ -5655,19 +5706,19 @@ async function runClaudeHook(input, client2, options = {}) {
|
|
|
5655
5706
|
ledger.nativeTasksCreated += 1;
|
|
5656
5707
|
return void 0;
|
|
5657
5708
|
});
|
|
5658
|
-
return
|
|
5709
|
+
return NOOP;
|
|
5659
5710
|
case "TaskCompleted":
|
|
5660
5711
|
withLedger(input.session_id, options, (ledger) => {
|
|
5661
5712
|
ledger.nativeTasksTerminal += 1;
|
|
5662
5713
|
return void 0;
|
|
5663
5714
|
});
|
|
5664
|
-
return
|
|
5715
|
+
return NOOP;
|
|
5665
5716
|
case "Stop":
|
|
5666
5717
|
return stop(input, options);
|
|
5667
5718
|
case "SessionEnd":
|
|
5668
5719
|
return sessionEnd(input, client2, options);
|
|
5669
5720
|
default:
|
|
5670
|
-
return
|
|
5721
|
+
return NOOP;
|
|
5671
5722
|
}
|
|
5672
5723
|
}
|
|
5673
5724
|
async function readHookInput(stream = process.stdin) {
|
|
@@ -5678,6 +5729,68 @@ async function readHookInput(stream = process.stdin) {
|
|
|
5678
5729
|
return JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
5679
5730
|
}
|
|
5680
5731
|
|
|
5732
|
+
// src/claude-hooks.ts
|
|
5733
|
+
async function runClaudeHook(input, client2, options = {}) {
|
|
5734
|
+
const output = await runHookCore(input, client2, {
|
|
5735
|
+
...options,
|
|
5736
|
+
harness: "claude-code",
|
|
5737
|
+
// D10: compaction is a new Claude context boundary, so the same brief must
|
|
5738
|
+
// be re-injected even when its content hash is unchanged.
|
|
5739
|
+
reinjectUnchangedCompact: true
|
|
5740
|
+
});
|
|
5741
|
+
switch (output.kind) {
|
|
5742
|
+
case "context":
|
|
5743
|
+
return {
|
|
5744
|
+
hookSpecificOutput: {
|
|
5745
|
+
hookEventName: "SessionStart",
|
|
5746
|
+
additionalContext: output.context
|
|
5747
|
+
}
|
|
5748
|
+
};
|
|
5749
|
+
case "rewrite":
|
|
5750
|
+
return {
|
|
5751
|
+
hookSpecificOutput: {
|
|
5752
|
+
hookEventName: "PreToolUse",
|
|
5753
|
+
updatedInput: output.updatedInput
|
|
5754
|
+
}
|
|
5755
|
+
};
|
|
5756
|
+
case "block":
|
|
5757
|
+
return { decision: "block", reason: output.reason };
|
|
5758
|
+
case "noop":
|
|
5759
|
+
return {};
|
|
5760
|
+
}
|
|
5761
|
+
}
|
|
5762
|
+
|
|
5763
|
+
// src/codex-hooks.ts
|
|
5764
|
+
async function runCodexHook(input, client2, options = {}) {
|
|
5765
|
+
const output = await runHookCore(input, client2, {
|
|
5766
|
+
...options,
|
|
5767
|
+
harness: "codex",
|
|
5768
|
+
// B7's native contract suppresses repeated unchanged brief injections.
|
|
5769
|
+
reinjectUnchangedCompact: false
|
|
5770
|
+
});
|
|
5771
|
+
switch (output.kind) {
|
|
5772
|
+
case "context":
|
|
5773
|
+
return {
|
|
5774
|
+
hookSpecificOutput: {
|
|
5775
|
+
hookEventName: "SessionStart",
|
|
5776
|
+
additionalContext: output.context
|
|
5777
|
+
}
|
|
5778
|
+
};
|
|
5779
|
+
case "rewrite":
|
|
5780
|
+
return {
|
|
5781
|
+
hookSpecificOutput: {
|
|
5782
|
+
hookEventName: "PreToolUse",
|
|
5783
|
+
permissionDecision: "allow",
|
|
5784
|
+
updatedInput: output.updatedInput
|
|
5785
|
+
}
|
|
5786
|
+
};
|
|
5787
|
+
case "block":
|
|
5788
|
+
return { decision: "block", reason: output.reason };
|
|
5789
|
+
case "noop":
|
|
5790
|
+
return {};
|
|
5791
|
+
}
|
|
5792
|
+
}
|
|
5793
|
+
|
|
5681
5794
|
// src/hook-installer.ts
|
|
5682
5795
|
var import_node_fs4 = __toESM(require("fs"));
|
|
5683
5796
|
var import_node_os4 = __toESM(require("os"));
|
|
@@ -5685,59 +5798,78 @@ var import_node_path4 = __toESM(require("path"));
|
|
|
5685
5798
|
var import_node_crypto3 = __toESM(require("crypto"));
|
|
5686
5799
|
var OWNER_MARKER = "--owner mindgraph";
|
|
5687
5800
|
var RUNNER_RELATIVE = ".mindgraph/bin/mindgraph-hook.cjs";
|
|
5688
|
-
|
|
5801
|
+
function command(harness) {
|
|
5802
|
+
return `node "$HOME/${RUNNER_RELATIVE}" hook --harness ${harness} --owner mindgraph`;
|
|
5803
|
+
}
|
|
5804
|
+
function windowsCommand(harness) {
|
|
5805
|
+
return `node "%USERPROFILE%\\.mindgraph\\bin\\mindgraph-hook.cjs" hook --harness ${harness} --owner mindgraph`;
|
|
5806
|
+
}
|
|
5689
5807
|
function installHookRunner(sourceFile, homeDir) {
|
|
5690
5808
|
const target = import_node_path4.default.join(homeDir || import_node_os4.default.homedir(), RUNNER_RELATIVE);
|
|
5691
5809
|
import_node_fs4.default.mkdirSync(import_node_path4.default.dirname(target), { recursive: true });
|
|
5692
5810
|
import_node_fs4.default.copyFileSync(sourceFile, target);
|
|
5693
5811
|
return target;
|
|
5694
5812
|
}
|
|
5695
|
-
function
|
|
5696
|
-
|
|
5697
|
-
|
|
5698
|
-
} catch {
|
|
5813
|
+
function settingsPath(harness, scope, projectDir = process.cwd(), codexHomeDir = process.env.CODEX_HOME || import_node_path4.default.join(import_node_os4.default.homedir(), ".codex")) {
|
|
5814
|
+
if (harness === "codex") {
|
|
5815
|
+
return scope === "user" ? import_node_path4.default.join(codexHomeDir, "hooks.json") : import_node_path4.default.join(projectDir, ".codex", "hooks.json");
|
|
5699
5816
|
}
|
|
5700
|
-
}
|
|
5701
|
-
function settingsPath(scope, projectDir = process.cwd()) {
|
|
5702
5817
|
return scope === "user" ? import_node_path4.default.join(import_node_os4.default.homedir(), ".claude", "settings.json") : import_node_path4.default.join(projectDir, ".claude", "settings.json");
|
|
5703
5818
|
}
|
|
5704
5819
|
function readSettings(file) {
|
|
5705
5820
|
if (!import_node_fs4.default.existsSync(file)) return {};
|
|
5706
5821
|
return JSON.parse(import_node_fs4.default.readFileSync(file, "utf8"));
|
|
5707
5822
|
}
|
|
5708
|
-
function ownedHook(timeout) {
|
|
5823
|
+
function ownedHook(harness, timeout, additionalContextLimit) {
|
|
5709
5824
|
return {
|
|
5710
5825
|
type: "command",
|
|
5711
|
-
command:
|
|
5826
|
+
command: command(harness),
|
|
5827
|
+
...harness === "codex" ? { commandWindows: windowsCommand(harness) } : {},
|
|
5712
5828
|
timeout,
|
|
5713
|
-
statusMessage: "Syncing MindGraph session context"
|
|
5829
|
+
statusMessage: "Syncing MindGraph session context",
|
|
5830
|
+
...additionalContextLimit === void 0 ? {} : { additionalContextLimit }
|
|
5714
5831
|
};
|
|
5715
5832
|
}
|
|
5716
|
-
function desiredEntries() {
|
|
5717
|
-
|
|
5833
|
+
function desiredEntries(harness) {
|
|
5834
|
+
const common = {
|
|
5718
5835
|
SessionStart: [
|
|
5719
5836
|
{
|
|
5720
|
-
matcher: "startup|resume|clear|compact|fork",
|
|
5721
|
-
|
|
5837
|
+
matcher: harness === "claude-code" ? "startup|resume|clear|compact|fork" : "startup|resume|clear|compact",
|
|
5838
|
+
// B7 live acceptance caught cold SessionStart calls crossing the
|
|
5839
|
+
// inherited 20s edge in both harnesses: the hooks correctly failed
|
|
5840
|
+
// open, but no brief reached the model. The same installed runner
|
|
5841
|
+
// completed in 16.84s once warm. Keep a 30s cold-tenant margin.
|
|
5842
|
+
hooks: [
|
|
5843
|
+
ownedHook(
|
|
5844
|
+
harness,
|
|
5845
|
+
30,
|
|
5846
|
+
harness === "codex" ? 3e3 : void 0
|
|
5847
|
+
)
|
|
5848
|
+
]
|
|
5722
5849
|
}
|
|
5723
5850
|
],
|
|
5724
5851
|
PreToolUse: [
|
|
5725
5852
|
{
|
|
5726
5853
|
matcher: "mcp__mindgraph__.*",
|
|
5727
|
-
hooks: [ownedHook(3)]
|
|
5854
|
+
hooks: [ownedHook(harness, 3)]
|
|
5728
5855
|
}
|
|
5729
5856
|
],
|
|
5730
|
-
PostToolUse: [{ matcher: ".*", hooks: [ownedHook(5)] }],
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
5857
|
+
PostToolUse: [{ matcher: ".*", hooks: [ownedHook(harness, 5)] }],
|
|
5858
|
+
Stop: [{ hooks: [ownedHook(harness, 5)] }],
|
|
5859
|
+
SessionEnd: [
|
|
5860
|
+
{ hooks: [ownedHook(harness, harness === "codex" ? 3 : 8)] }
|
|
5861
|
+
]
|
|
5735
5862
|
};
|
|
5863
|
+
return harness === "claude-code" ? {
|
|
5864
|
+
...common,
|
|
5865
|
+
TaskCreated: [{ hooks: [ownedHook(harness, 3)] }],
|
|
5866
|
+
TaskCompleted: [{ hooks: [ownedHook(harness, 3)] }]
|
|
5867
|
+
} : common;
|
|
5736
5868
|
}
|
|
5737
5869
|
function hookCommand(value) {
|
|
5738
5870
|
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
5739
|
-
const
|
|
5740
|
-
return typeof
|
|
5871
|
+
const command2 = value.command;
|
|
5872
|
+
return typeof command2 === "string" ? command2 : void 0;
|
|
5741
5873
|
}
|
|
5742
5874
|
function entryHasOwnedHook(value) {
|
|
5743
5875
|
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
@@ -5753,13 +5885,13 @@ function writeSettings(file, settings) {
|
|
|
5753
5885
|
});
|
|
5754
5886
|
import_node_fs4.default.renameSync(temporary, file);
|
|
5755
5887
|
}
|
|
5756
|
-
function
|
|
5757
|
-
const file = settingsPath(scope, projectDir);
|
|
5888
|
+
function installHooks(harness, scope, projectDir = process.cwd(), codexHomeDir) {
|
|
5889
|
+
const file = settingsPath(harness, scope, projectDir, codexHomeDir);
|
|
5758
5890
|
const settings = readSettings(file);
|
|
5759
5891
|
const hooks = settings.hooks && typeof settings.hooks === "object" && !Array.isArray(settings.hooks) ? settings.hooks : {};
|
|
5760
5892
|
let added = 0;
|
|
5761
5893
|
let updated = 0;
|
|
5762
|
-
for (const [event, wanted] of Object.entries(desiredEntries())) {
|
|
5894
|
+
for (const [event, wanted] of Object.entries(desiredEntries(harness))) {
|
|
5763
5895
|
const current = Array.isArray(hooks[event]) ? [...hooks[event]] : [];
|
|
5764
5896
|
const kept = current.filter((entry) => !entryHasOwnedHook(entry));
|
|
5765
5897
|
const hadOwned = kept.length !== current.length;
|
|
@@ -5774,8 +5906,8 @@ function installClaudeHooks(scope, projectDir = process.cwd()) {
|
|
|
5774
5906
|
writeSettings(file, settings);
|
|
5775
5907
|
return { path: file, added, updated };
|
|
5776
5908
|
}
|
|
5777
|
-
function
|
|
5778
|
-
const file = settingsPath(scope, projectDir);
|
|
5909
|
+
function uninstallHooks(harness, scope, projectDir = process.cwd(), codexHomeDir) {
|
|
5910
|
+
const file = settingsPath(harness, scope, projectDir, codexHomeDir);
|
|
5779
5911
|
if (!import_node_fs4.default.existsSync(file)) return { path: file, removed: 0 };
|
|
5780
5912
|
const settings = readSettings(file);
|
|
5781
5913
|
const hooks = settings.hooks && typeof settings.hooks === "object" && !Array.isArray(settings.hooks) ? settings.hooks : {};
|
|
@@ -5810,6 +5942,18 @@ function uninstallClaudeHooks(scope, projectDir = process.cwd()) {
|
|
|
5810
5942
|
writeSettings(file, settings);
|
|
5811
5943
|
return { path: file, removed };
|
|
5812
5944
|
}
|
|
5945
|
+
function installClaudeHooks(scope, projectDir = process.cwd()) {
|
|
5946
|
+
return installHooks("claude-code", scope, projectDir);
|
|
5947
|
+
}
|
|
5948
|
+
function uninstallClaudeHooks(scope, projectDir = process.cwd()) {
|
|
5949
|
+
return uninstallHooks("claude-code", scope, projectDir);
|
|
5950
|
+
}
|
|
5951
|
+
function installCodexHooks(scope, projectDir = process.cwd(), codexHomeDir) {
|
|
5952
|
+
return installHooks("codex", scope, projectDir, codexHomeDir);
|
|
5953
|
+
}
|
|
5954
|
+
function uninstallCodexHooks(scope, projectDir = process.cwd(), codexHomeDir) {
|
|
5955
|
+
return uninstallHooks("codex", scope, projectDir, codexHomeDir);
|
|
5956
|
+
}
|
|
5813
5957
|
|
|
5814
5958
|
// src/cli.ts
|
|
5815
5959
|
function getClaudeDesktopConfigPath() {
|
|
@@ -6019,8 +6163,8 @@ USAGE:
|
|
|
6019
6163
|
mindgraph-mcp install-code Install into Claude Code (--hooks: + session hooks)
|
|
6020
6164
|
mindgraph-mcp uninstall Remove from Claude Desktop config
|
|
6021
6165
|
mindgraph-mcp uninstall-code Remove from Claude Code
|
|
6022
|
-
mindgraph-mcp install-hooks --harness claude-code [--scope user|project]
|
|
6023
|
-
mindgraph-mcp uninstall-hooks --harness claude-code [--scope user|project]
|
|
6166
|
+
mindgraph-mcp install-hooks --harness claude-code|codex [--scope user|project]
|
|
6167
|
+
mindgraph-mcp uninstall-hooks --harness claude-code|codex [--scope user|project]
|
|
6024
6168
|
mindgraph-mcp status Show installation status
|
|
6025
6169
|
|
|
6026
6170
|
OPTIONS:
|
|
@@ -6028,7 +6172,7 @@ OPTIONS:
|
|
|
6028
6172
|
--base-url <url> Custom API base URL (default: https://api.mindgraph.cloud)
|
|
6029
6173
|
--scope <scope> Hook settings scope: project (default) or user
|
|
6030
6174
|
--project-dir <dir> Project root for project-scoped hooks
|
|
6031
|
-
--harness <name> Hook harness (
|
|
6175
|
+
--harness <name> Hook harness (claude-code or codex)
|
|
6032
6176
|
--help, -h Show this help message
|
|
6033
6177
|
|
|
6034
6178
|
EXAMPLES:
|
|
@@ -6166,8 +6310,8 @@ async function interactiveInit(baseUrl) {
|
|
|
6166
6310
|
console.log("\nDone! Your knowledge graph is now connected.");
|
|
6167
6311
|
}
|
|
6168
6312
|
async function main2() {
|
|
6169
|
-
const { command, apiKey, baseUrl, scope, projectDir, harness, hooks, agentId } = parseArgs(process.argv);
|
|
6170
|
-
switch (
|
|
6313
|
+
const { command: command2, apiKey, baseUrl, scope, projectDir, harness, hooks, agentId } = parseArgs(process.argv);
|
|
6314
|
+
switch (command2) {
|
|
6171
6315
|
case "help":
|
|
6172
6316
|
printUsage();
|
|
6173
6317
|
break;
|
|
@@ -6200,14 +6344,15 @@ async function main2() {
|
|
|
6200
6344
|
uninstallClaudeCode();
|
|
6201
6345
|
break;
|
|
6202
6346
|
case "install-hooks": {
|
|
6203
|
-
|
|
6204
|
-
|
|
6347
|
+
const hookHarness = harness || "claude-code";
|
|
6348
|
+
if (hookHarness !== "claude-code" && hookHarness !== "codex") {
|
|
6349
|
+
throw new Error("--harness must be claude-code or codex");
|
|
6205
6350
|
}
|
|
6206
6351
|
const runner = installHookRunner(__filename);
|
|
6207
6352
|
console.log(`Installed pinned hook runner at ${runner}`);
|
|
6208
|
-
const result = installClaudeHooks(scope, projectDir);
|
|
6353
|
+
const result = hookHarness === "codex" ? installCodexHooks(scope, projectDir) : installClaudeHooks(scope, projectDir);
|
|
6209
6354
|
console.log(
|
|
6210
|
-
`Installed ${result.added} and refreshed ${result.updated} MindGraph Claude Code hook entries in ${result.path}`
|
|
6355
|
+
`Installed ${result.added} and refreshed ${result.updated} MindGraph ${hookHarness === "codex" ? "Codex" : "Claude Code"} hook entries in ${result.path}`
|
|
6211
6356
|
);
|
|
6212
6357
|
printCodegraphStatus();
|
|
6213
6358
|
if (apiKey || baseUrl || agentId) {
|
|
@@ -6221,18 +6366,22 @@ async function main2() {
|
|
|
6221
6366
|
break;
|
|
6222
6367
|
}
|
|
6223
6368
|
case "uninstall-hooks": {
|
|
6224
|
-
|
|
6225
|
-
|
|
6369
|
+
const hookHarness = harness || "claude-code";
|
|
6370
|
+
if (hookHarness !== "claude-code" && hookHarness !== "codex") {
|
|
6371
|
+
throw new Error("--harness must be claude-code or codex");
|
|
6226
6372
|
}
|
|
6227
|
-
|
|
6228
|
-
const result = uninstallClaudeHooks(scope, projectDir);
|
|
6373
|
+
const result = hookHarness === "codex" ? uninstallCodexHooks(scope, projectDir) : uninstallClaudeHooks(scope, projectDir);
|
|
6229
6374
|
console.log(
|
|
6230
|
-
`Removed ${result.removed} MindGraph Claude Code hooks from ${result.path}`
|
|
6375
|
+
`Removed ${result.removed} MindGraph ${hookHarness === "codex" ? "Codex" : "Claude Code"} hooks from ${result.path}`
|
|
6231
6376
|
);
|
|
6232
6377
|
break;
|
|
6233
6378
|
}
|
|
6234
6379
|
case "hook": {
|
|
6235
6380
|
const stored = loadHookEnv();
|
|
6381
|
+
const hookHarness = harness || "claude-code";
|
|
6382
|
+
if (hookHarness !== "claude-code" && hookHarness !== "codex") {
|
|
6383
|
+
throw new Error("--harness must be claude-code or codex");
|
|
6384
|
+
}
|
|
6236
6385
|
const hookApiKey = apiKey ?? stored.apiKey;
|
|
6237
6386
|
const hookBaseUrl = baseUrl ?? stored.baseUrl;
|
|
6238
6387
|
if (!hookApiKey) {
|
|
@@ -6248,9 +6397,18 @@ async function main2() {
|
|
|
6248
6397
|
maxRetries: 0,
|
|
6249
6398
|
telemetrySurface: "mcp"
|
|
6250
6399
|
});
|
|
6251
|
-
const
|
|
6252
|
-
agentId: process.env.MINDGRAPH_AGENT_ID || stored.agentId ||
|
|
6253
|
-
}
|
|
6400
|
+
const hookOptions = {
|
|
6401
|
+
agentId: process.env.MINDGRAPH_AGENT_ID || stored.agentId || hookHarness
|
|
6402
|
+
};
|
|
6403
|
+
const output = hookHarness === "codex" ? await runCodexHook(
|
|
6404
|
+
input,
|
|
6405
|
+
client2,
|
|
6406
|
+
hookOptions
|
|
6407
|
+
) : await runClaudeHook(
|
|
6408
|
+
input,
|
|
6409
|
+
client2,
|
|
6410
|
+
hookOptions
|
|
6411
|
+
);
|
|
6254
6412
|
process.stdout.write(`${JSON.stringify(output)}
|
|
6255
6413
|
`);
|
|
6256
6414
|
} catch {
|
|
@@ -6266,7 +6424,7 @@ async function main2() {
|
|
|
6266
6424
|
break;
|
|
6267
6425
|
}
|
|
6268
6426
|
default:
|
|
6269
|
-
console.error(`Unknown command: ${
|
|
6427
|
+
console.error(`Unknown command: ${command2}`);
|
|
6270
6428
|
printUsage();
|
|
6271
6429
|
process.exit(1);
|
|
6272
6430
|
}
|
package/dist/index.js
CHANGED
|
@@ -1889,7 +1889,7 @@ var TOOLS = [
|
|
|
1889
1889
|
scope_uids: {
|
|
1890
1890
|
type: "array",
|
|
1891
1891
|
items: { type: "string" },
|
|
1892
|
-
description: "
|
|
1892
|
+
description: "Required target UIDs for create_task and ordinary target UIDs that bound deterministic resume selection"
|
|
1893
1893
|
},
|
|
1894
1894
|
limit: {
|
|
1895
1895
|
type: "number",
|
|
@@ -2687,6 +2687,38 @@ async function handleCommit(client2, args) {
|
|
|
2687
2687
|
return err3(`Unknown commit action: ${action}`);
|
|
2688
2688
|
}
|
|
2689
2689
|
}
|
|
2690
|
+
async function repositoryScopeUidsForTask(client2, options) {
|
|
2691
|
+
const scopeUids = [...new Set(options.scopeUids ?? [])];
|
|
2692
|
+
const cwd = options.invocationContext?.cwd;
|
|
2693
|
+
const repoId = options.invocationContext?.repoId;
|
|
2694
|
+
if (!options.repo && !cwd && !repoId) {
|
|
2695
|
+
return options.scopeUids;
|
|
2696
|
+
}
|
|
2697
|
+
const agentId = options.agentId ?? process.env.MINDGRAPH_AGENT_ID ?? "mcp";
|
|
2698
|
+
const fallbackSpaceUid = options.repoSpaceUid ?? `space:agent:${agentId}`;
|
|
2699
|
+
const env = { ...process.env };
|
|
2700
|
+
if (!options.repo && repoId) {
|
|
2701
|
+
env.MINDGRAPH_REPO_ID = repoId;
|
|
2702
|
+
}
|
|
2703
|
+
const adapter = new CodegraphAdapter({
|
|
2704
|
+
cwd: cwd ?? process.cwd(),
|
|
2705
|
+
env
|
|
2706
|
+
});
|
|
2707
|
+
const repository = await adapter.resolveRepository(options.repo, fallbackSpaceUid);
|
|
2708
|
+
const anchored = await anchorRepository(
|
|
2709
|
+
client2,
|
|
2710
|
+
repository,
|
|
2711
|
+
repository.spaceUid ?? fallbackSpaceUid,
|
|
2712
|
+
agentId
|
|
2713
|
+
);
|
|
2714
|
+
if (!anchored.uid) {
|
|
2715
|
+
throw new Error(
|
|
2716
|
+
`repository scope ${repository.repoId} could not be materialized (${anchored.status ?? "missing uid"})`
|
|
2717
|
+
);
|
|
2718
|
+
}
|
|
2719
|
+
scopeUids.push(anchored.uid);
|
|
2720
|
+
return [...new Set(scopeUids)];
|
|
2721
|
+
}
|
|
2690
2722
|
async function handlePlan(client2, args) {
|
|
2691
2723
|
const {
|
|
2692
2724
|
action,
|
|
@@ -2717,6 +2749,9 @@ async function handlePlan(client2, args) {
|
|
|
2717
2749
|
release_lease,
|
|
2718
2750
|
override_reason,
|
|
2719
2751
|
scope_uids,
|
|
2752
|
+
repo,
|
|
2753
|
+
repo_space_uid,
|
|
2754
|
+
invocation_context,
|
|
2720
2755
|
limit,
|
|
2721
2756
|
confidence,
|
|
2722
2757
|
salience,
|
|
@@ -2746,7 +2781,14 @@ async function handlePlan(client2, args) {
|
|
|
2746
2781
|
case "checkpoint_iteration":
|
|
2747
2782
|
case "block_task":
|
|
2748
2783
|
case "complete_task":
|
|
2749
|
-
case "abandon_iteration":
|
|
2784
|
+
case "abandon_iteration": {
|
|
2785
|
+
const resolvedScopeUids = action === "create_task" ? await repositoryScopeUidsForTask(client2, {
|
|
2786
|
+
scopeUids: scope_uids,
|
|
2787
|
+
repo,
|
|
2788
|
+
repoSpaceUid: repo_space_uid,
|
|
2789
|
+
invocationContext: invocation_context,
|
|
2790
|
+
agentId: agent_id
|
|
2791
|
+
}) : scope_uids;
|
|
2750
2792
|
return ok3(
|
|
2751
2793
|
await client2.plan({
|
|
2752
2794
|
action,
|
|
@@ -2774,7 +2816,7 @@ async function handlePlan(client2, args) {
|
|
|
2774
2816
|
allow_takeover,
|
|
2775
2817
|
release_lease,
|
|
2776
2818
|
override_reason,
|
|
2777
|
-
scope_uids,
|
|
2819
|
+
scope_uids: resolvedScopeUids,
|
|
2778
2820
|
limit,
|
|
2779
2821
|
input_snapshot,
|
|
2780
2822
|
output_snapshot,
|
|
@@ -2789,6 +2831,7 @@ async function handlePlan(client2, args) {
|
|
|
2789
2831
|
agent_id
|
|
2790
2832
|
})
|
|
2791
2833
|
);
|
|
2834
|
+
}
|
|
2792
2835
|
// Execution tracking
|
|
2793
2836
|
case "start_execution":
|
|
2794
2837
|
return ok3(
|
|
@@ -3955,7 +3998,7 @@ if (PROFILE === "coding") {
|
|
|
3955
3998
|
var server = new import_server.Server(
|
|
3956
3999
|
{
|
|
3957
4000
|
name: "mindgraph",
|
|
3958
|
-
version: "0.14.
|
|
4001
|
+
version: "0.14.9"
|
|
3959
4002
|
},
|
|
3960
4003
|
{
|
|
3961
4004
|
capabilities: {
|