@agentmemory/agentmemory 0.9.27 → 0.9.29
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/.env.example +15 -6
- package/AGENTS.md +7 -7
- package/README.md +292 -164
- package/dist/.env.example +15 -6
- package/dist/cli.d.mts.map +1 -1
- package/dist/cli.mjs +427 -177
- package/dist/cli.mjs.map +1 -1
- package/dist/{connect-bmZ5eqYN.mjs → connect-Qaeq15TQ.mjs} +717 -65
- package/dist/connect-Qaeq15TQ.mjs.map +1 -0
- package/dist/docker-compose.yml +2 -2
- package/dist/hooks/antigravity-bridge.d.mts +8 -0
- package/dist/hooks/antigravity-bridge.d.mts.map +1 -0
- package/dist/hooks/antigravity-bridge.mjs +114 -0
- package/dist/hooks/antigravity-bridge.mjs.map +1 -0
- package/dist/hooks/notification.mjs +21 -5
- package/dist/hooks/notification.mjs.map +1 -1
- package/dist/hooks/post-commit.mjs +15 -2
- package/dist/hooks/post-commit.mjs.map +1 -1
- package/dist/hooks/post-tool-failure.mjs +16 -4
- package/dist/hooks/post-tool-failure.mjs.map +1 -1
- package/dist/hooks/post-tool-use.mjs +16 -4
- package/dist/hooks/post-tool-use.mjs.map +1 -1
- package/dist/hooks/pre-compact.mjs +14 -3
- package/dist/hooks/pre-compact.mjs.map +1 -1
- package/dist/hooks/pre-tool-use.mjs +3 -2
- package/dist/hooks/pre-tool-use.mjs.map +1 -1
- package/dist/hooks/prompt-submit.mjs +16 -4
- package/dist/hooks/prompt-submit.mjs.map +1 -1
- package/dist/hooks/session-end.mjs +84 -19
- package/dist/hooks/session-end.mjs.map +1 -1
- package/dist/hooks/session-start.mjs +24 -5
- package/dist/hooks/session-start.mjs.map +1 -1
- package/dist/hooks/stop.mjs +3 -8
- package/dist/hooks/stop.mjs.map +1 -1
- package/dist/hooks/subagent-start.mjs +16 -4
- package/dist/hooks/subagent-start.mjs.map +1 -1
- package/dist/hooks/subagent-stop.mjs +16 -4
- package/dist/hooks/subagent-stop.mjs.map +1 -1
- package/dist/hooks/task-completed.mjs +16 -4
- package/dist/hooks/task-completed.mjs.map +1 -1
- package/dist/{image-refs-B5Zf_Djo.mjs → image-refs-BKLmp_sD.mjs} +4 -22
- package/dist/image-refs-BKLmp_sD.mjs.map +1 -0
- package/dist/image-refs-CJgZmb9X.mjs +34 -0
- package/dist/image-refs-CJgZmb9X.mjs.map +1 -0
- package/dist/index.mjs +1681 -911
- package/dist/index.mjs.map +1 -1
- package/dist/{image-store-Gpo2mgM9.mjs → keyed-mutex-DTHtcZrt.mjs} +14 -11
- package/dist/keyed-mutex-DTHtcZrt.mjs.map +1 -0
- package/dist/{logger-yHTcEBAI.mjs → logger-BEB7pCI9.mjs} +1 -1
- package/dist/{logger-yHTcEBAI.mjs.map → logger-BEB7pCI9.mjs.map} +1 -1
- package/dist/schema-BFZhNTF7.mjs +197 -0
- package/dist/schema-BFZhNTF7.mjs.map +1 -0
- package/dist/{src-MOg2zKJs.mjs → src-G7yt8gGm.mjs} +1521 -854
- package/dist/src-G7yt8gGm.mjs.map +1 -0
- package/dist/{standalone-BORXC71-.mjs → standalone-BqNJDJ04.mjs} +30 -16
- package/dist/standalone-BqNJDJ04.mjs.map +1 -0
- package/dist/standalone.d.mts.map +1 -1
- package/dist/standalone.mjs +55 -15
- package/dist/standalone.mjs.map +1 -1
- package/dist/{tools-registry-D8XVVPbJ.mjs → tools-registry-BV_2bu7z.mjs} +55 -17
- package/dist/tools-registry-BV_2bu7z.mjs.map +1 -0
- package/dist/viewer/favicon.svg +35 -1
- package/dist/viewer/index.html +473 -83
- package/docker-compose.yml +2 -2
- package/integrations/pi/README.md +77 -0
- package/integrations/pi/index.ts +403 -0
- package/integrations/pi/package.json +32 -0
- package/integrations/pi/security.ts +35 -0
- package/package.json +6 -4
- package/plugin/.claude-plugin/plugin.json +2 -2
- package/plugin/.codex-plugin/plugin.json +2 -2
- package/plugin/.devin-plugin/plugin.json +32 -0
- package/plugin/cursor/hooks.json +41 -0
- package/plugin/cursor/mcp.json +12 -0
- package/plugin/hooks/hooks.antigravity.json +43 -0
- package/plugin/hooks/hooks.devin.json +67 -0
- package/plugin/hooks/hooks.droid.json +55 -0
- package/plugin/opencode/README.md +1 -1
- package/plugin/opencode/agentmemory-capture.ts +73 -13
- package/plugin/opencode/plugin.json +1 -1
- package/plugin/plugin.json +2 -2
- package/plugin/scripts/antigravity-bridge.d.mts +8 -0
- package/plugin/scripts/antigravity-bridge.d.mts.map +1 -0
- package/plugin/scripts/antigravity-bridge.mjs +114 -0
- package/plugin/scripts/antigravity-bridge.mjs.map +1 -0
- package/plugin/scripts/notification.mjs +21 -5
- package/plugin/scripts/notification.mjs.map +1 -1
- package/plugin/scripts/post-commit.mjs +15 -2
- package/plugin/scripts/post-commit.mjs.map +1 -1
- package/plugin/scripts/post-tool-failure.mjs +16 -4
- package/plugin/scripts/post-tool-failure.mjs.map +1 -1
- package/plugin/scripts/post-tool-use.mjs +16 -4
- package/plugin/scripts/post-tool-use.mjs.map +1 -1
- package/plugin/scripts/pre-compact.mjs +14 -3
- package/plugin/scripts/pre-compact.mjs.map +1 -1
- package/plugin/scripts/pre-tool-use.mjs +3 -2
- package/plugin/scripts/pre-tool-use.mjs.map +1 -1
- package/plugin/scripts/prompt-submit.mjs +16 -4
- package/plugin/scripts/prompt-submit.mjs.map +1 -1
- package/plugin/scripts/session-end.mjs +84 -19
- package/plugin/scripts/session-end.mjs.map +1 -1
- package/plugin/scripts/session-start.mjs +24 -5
- package/plugin/scripts/session-start.mjs.map +1 -1
- package/plugin/scripts/stop.mjs +3 -8
- package/plugin/scripts/stop.mjs.map +1 -1
- package/plugin/scripts/subagent-start.mjs +16 -4
- package/plugin/scripts/subagent-start.mjs.map +1 -1
- package/plugin/scripts/subagent-stop.mjs +16 -4
- package/plugin/scripts/subagent-stop.mjs.map +1 -1
- package/plugin/scripts/task-completed.mjs +16 -4
- package/plugin/scripts/task-completed.mjs.map +1 -1
- package/plugin/skills/_shared/TROUBLESHOOTING.md +38 -0
- package/plugin/skills/agentmemory-agents/REFERENCE.md +31 -0
- package/plugin/skills/agentmemory-agents/SKILL.md +34 -0
- package/plugin/skills/agentmemory-architecture/SKILL.md +33 -0
- package/plugin/skills/agentmemory-config/REFERENCE.md +45 -0
- package/plugin/skills/agentmemory-config/SKILL.md +37 -0
- package/plugin/skills/agentmemory-hooks/REFERENCE.md +20 -0
- package/plugin/skills/agentmemory-hooks/SKILL.md +39 -0
- package/plugin/skills/agentmemory-mcp-tools/REFERENCE.md +66 -0
- package/plugin/skills/agentmemory-mcp-tools/SKILL.md +39 -0
- package/plugin/skills/agentmemory-rest-api/REFERENCE.md +142 -0
- package/plugin/skills/agentmemory-rest-api/SKILL.md +43 -0
- package/plugin/skills/commit-context/EXAMPLES.md +71 -0
- package/plugin/skills/commit-context/SKILL.md +53 -8
- package/plugin/skills/commit-history/EXAMPLES.md +71 -0
- package/plugin/skills/commit-history/SKILL.md +51 -9
- package/plugin/skills/forget/EXAMPLES.md +75 -0
- package/plugin/skills/forget/SKILL.md +57 -14
- package/plugin/skills/handoff/EXAMPLES.md +56 -0
- package/plugin/skills/handoff/SKILL.md +56 -9
- package/plugin/skills/lesson/SKILL.md +64 -0
- package/plugin/skills/memory-discipline/SKILL.md +57 -0
- package/plugin/skills/recall/EXAMPLES.md +74 -0
- package/plugin/skills/recall/SKILL.md +53 -11
- package/plugin/skills/recap/EXAMPLES.md +60 -0
- package/plugin/skills/recap/SKILL.md +51 -13
- package/plugin/skills/remember/EXAMPLES.md +67 -0
- package/plugin/skills/remember/SKILL.md +58 -17
- package/plugin/skills/session-history/EXAMPLES.md +59 -0
- package/plugin/skills/session-history/SKILL.md +54 -11
- package/plugin/skills/write-agentmemory-skill/SKILL.md +40 -0
- package/dist/connect-bmZ5eqYN.mjs.map +0 -1
- package/dist/image-refs-B5Zf_Djo.mjs.map +0 -1
- package/dist/image-store-Gpo2mgM9.mjs.map +0 -1
- package/dist/rolldown-runtime-twds-ZHy.mjs +0 -14
- package/dist/schema-CNiCWzV9.mjs +0 -78
- package/dist/schema-CNiCWzV9.mjs.map +0 -1
- package/dist/src-MOg2zKJs.mjs.map +0 -1
- package/dist/standalone-BORXC71-.mjs.map +0 -1
- package/dist/tools-registry-D8XVVPbJ.mjs.map +0 -1
- package/dist/version-9DNrRyph.mjs +0 -6
- package/dist/version-9DNrRyph.mjs.map +0 -1
- package/plugin/scripts/diagnostics.d.mts +0 -17
- package/plugin/scripts/diagnostics.d.mts.map +0 -1
- package/plugin/scripts/diagnostics.mjs.map +0 -1
|
@@ -1,9 +1,163 @@
|
|
|
1
|
-
import
|
|
1
|
+
import "node:module";
|
|
2
2
|
import { copyFileSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { dirname, join, resolve } from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import { homedir, platform } from "node:os";
|
|
6
6
|
import * as p from "@clack/prompts";
|
|
7
|
+
import pc from "picocolors";
|
|
8
|
+
//#region \0rolldown/runtime.js
|
|
9
|
+
var __defProp = Object.defineProperty;
|
|
10
|
+
var __exportAll = (all, no_symbols) => {
|
|
11
|
+
let target = {};
|
|
12
|
+
for (var name in all) __defProp(target, name, {
|
|
13
|
+
get: all[name],
|
|
14
|
+
enumerable: true
|
|
15
|
+
});
|
|
16
|
+
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
17
|
+
return target;
|
|
18
|
+
};
|
|
19
|
+
//#endregion
|
|
20
|
+
//#region src/cli/connect/guidelines.ts
|
|
21
|
+
const START = "<!-- agentmemory:start -->";
|
|
22
|
+
const END = "<!-- agentmemory:end -->";
|
|
23
|
+
const GUIDELINE_BODY = `## Agent memory (agentmemory)
|
|
24
|
+
|
|
25
|
+
You have persistent long-term memory via the agentmemory MCP server. Tools: \`memory_recall\`, \`memory_smart_search\`, \`memory_save\`, \`memory_sessions\`.
|
|
26
|
+
|
|
27
|
+
- At the START of a task, call \`memory_recall\` (or \`memory_smart_search\`) with the task context to load relevant past decisions, fixes, and preferences before asking the user to repeat anything.
|
|
28
|
+
- When you learn something durable (a decision, a fix, a gotcha, a user preference, a project convention), call \`memory_save\` to persist it.
|
|
29
|
+
- Prefer recalling over re-deriving, and save concise reusable facts rather than transcripts.`;
|
|
30
|
+
function guidelineTargets(home = homedir()) {
|
|
31
|
+
return {
|
|
32
|
+
cursor: {
|
|
33
|
+
projectPath: join(".cursor", "rules", "agentmemory.mdc"),
|
|
34
|
+
format: "mdc",
|
|
35
|
+
scope: "project",
|
|
36
|
+
source: "https://cursor.com/docs/rules"
|
|
37
|
+
},
|
|
38
|
+
cline: {
|
|
39
|
+
projectPath: join(".clinerules", "agentmemory.md"),
|
|
40
|
+
format: "rule",
|
|
41
|
+
scope: "project",
|
|
42
|
+
source: "https://docs.cline.bot/customization/cline-rules"
|
|
43
|
+
},
|
|
44
|
+
continue: {
|
|
45
|
+
projectPath: join(".continue", "rules", "00-agentmemory.md"),
|
|
46
|
+
format: "rule",
|
|
47
|
+
scope: "project",
|
|
48
|
+
source: "https://docs.continue.dev/customize/deep-dives/rules"
|
|
49
|
+
},
|
|
50
|
+
zed: {
|
|
51
|
+
globalPath: join(home, ".config", "zed", "AGENTS.md"),
|
|
52
|
+
projectPath: "AGENTS.md",
|
|
53
|
+
format: "block",
|
|
54
|
+
scope: "global",
|
|
55
|
+
source: "https://zed.dev/docs/ai/instructions"
|
|
56
|
+
},
|
|
57
|
+
warp: {
|
|
58
|
+
projectPath: "AGENTS.md",
|
|
59
|
+
format: "block",
|
|
60
|
+
scope: "project",
|
|
61
|
+
source: "https://docs.warp.dev/agent-platform/capabilities/rules"
|
|
62
|
+
},
|
|
63
|
+
kiro: {
|
|
64
|
+
globalPath: join(home, ".kiro", "steering", "agentmemory.md"),
|
|
65
|
+
projectPath: join(".kiro", "steering", "agentmemory.md"),
|
|
66
|
+
format: "steering",
|
|
67
|
+
scope: "global",
|
|
68
|
+
source: "https://kiro.dev/docs/steering"
|
|
69
|
+
},
|
|
70
|
+
"gemini-cli": {
|
|
71
|
+
globalPath: join(home, ".gemini", "GEMINI.md"),
|
|
72
|
+
projectPath: "GEMINI.md",
|
|
73
|
+
format: "block",
|
|
74
|
+
scope: "global",
|
|
75
|
+
source: "https://github.com/google-gemini/gemini-cli/blob/main/docs/cli/gemini-md.md"
|
|
76
|
+
},
|
|
77
|
+
qwen: {
|
|
78
|
+
globalPath: join(home, ".qwen", "QWEN.md"),
|
|
79
|
+
projectPath: "QWEN.md",
|
|
80
|
+
format: "block",
|
|
81
|
+
scope: "global",
|
|
82
|
+
source: "https://github.com/QwenLM/qwen-code/blob/main/docs/users/features/memory.md"
|
|
83
|
+
},
|
|
84
|
+
opencode: {
|
|
85
|
+
globalPath: join(home, ".config", "opencode", "AGENTS.md"),
|
|
86
|
+
projectPath: "AGENTS.md",
|
|
87
|
+
format: "block",
|
|
88
|
+
scope: "global",
|
|
89
|
+
source: "https://opencode.ai/docs/rules"
|
|
90
|
+
},
|
|
91
|
+
droid: {
|
|
92
|
+
globalPath: join(home, ".factory", "AGENTS.md"),
|
|
93
|
+
projectPath: "AGENTS.md",
|
|
94
|
+
format: "block",
|
|
95
|
+
scope: "global",
|
|
96
|
+
source: "https://docs.factory.ai/cli/configuration/agents-md"
|
|
97
|
+
},
|
|
98
|
+
antigravity: {
|
|
99
|
+
globalPath: join(home, ".gemini", "GEMINI.md"),
|
|
100
|
+
projectPath: join(".agents", "rules", "agentmemory.md"),
|
|
101
|
+
format: "block",
|
|
102
|
+
scope: "global",
|
|
103
|
+
source: "https://antigravity.google/docs/rules-workflows"
|
|
104
|
+
},
|
|
105
|
+
"antigravity-cli": {
|
|
106
|
+
globalPath: join(home, ".gemini", "GEMINI.md"),
|
|
107
|
+
projectPath: join(".agents", "rules", "agentmemory.md"),
|
|
108
|
+
format: "block",
|
|
109
|
+
scope: "global",
|
|
110
|
+
source: "https://antigravity.google/docs/rules-workflows"
|
|
111
|
+
},
|
|
112
|
+
"copilot-cli": {
|
|
113
|
+
globalPath: join(home, ".copilot", "copilot-instructions.md"),
|
|
114
|
+
projectPath: join(".github", "copilot-instructions.md"),
|
|
115
|
+
format: "block",
|
|
116
|
+
scope: "global",
|
|
117
|
+
source: "https://docs.github.com/en/copilot/how-tos/copilot-cli/customize-copilot/add-custom-instructions"
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function renderDedicated(format) {
|
|
122
|
+
if (format === "mdc") return `---\ndescription: agentmemory long-term memory usage\nalwaysApply: true\n---\n\n${GUIDELINE_BODY}\n`;
|
|
123
|
+
if (format === "steering") return `---\ninclusion: always\n---\n\n${GUIDELINE_BODY}\n`;
|
|
124
|
+
return `${GUIDELINE_BODY}\n`;
|
|
125
|
+
}
|
|
126
|
+
function upsertBlock(existing) {
|
|
127
|
+
const block = `${START}\n${GUIDELINE_BODY}\n${END}`;
|
|
128
|
+
const startIdx = existing.indexOf(START);
|
|
129
|
+
const endIdx = existing.indexOf(END);
|
|
130
|
+
if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) return existing.slice(0, startIdx) + block + existing.slice(endIdx + 24);
|
|
131
|
+
if (startIdx !== -1 || endIdx !== -1) return existing;
|
|
132
|
+
return `${existing}${existing.length === 0 || existing.endsWith("\n") ? "" : "\n"}${existing.length === 0 ? "" : "\n"}${block}\n`;
|
|
133
|
+
}
|
|
134
|
+
function writeGuideline(agentName, opts = { cwd: process.cwd() }) {
|
|
135
|
+
const target = guidelineTargets(opts.home ?? homedir())[agentName];
|
|
136
|
+
if (!target) return { kind: "no-target" };
|
|
137
|
+
const path = target.globalPath ?? join(opts.cwd, target.projectPath);
|
|
138
|
+
const dedicated = target.format !== "block";
|
|
139
|
+
const existing = existsSync(path) ? readFileSync(path, "utf8") : "";
|
|
140
|
+
const next = dedicated ? renderDedicated(target.format) : upsertBlock(existing);
|
|
141
|
+
if (existing === next) return {
|
|
142
|
+
kind: "unchanged",
|
|
143
|
+
path,
|
|
144
|
+
scope: target.scope
|
|
145
|
+
};
|
|
146
|
+
if (opts.dryRun) return {
|
|
147
|
+
kind: "would-write",
|
|
148
|
+
path,
|
|
149
|
+
scope: target.scope
|
|
150
|
+
};
|
|
151
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
152
|
+
writeFileSync(path, next, "utf8");
|
|
153
|
+
return {
|
|
154
|
+
kind: "written",
|
|
155
|
+
path,
|
|
156
|
+
scope: target.scope,
|
|
157
|
+
source: target.source
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
//#endregion
|
|
7
161
|
//#region src/cli/connect/util.ts
|
|
8
162
|
const AGENTMEMORY_MCP_BLOCK = {
|
|
9
163
|
command: "npx",
|
|
@@ -64,9 +218,12 @@ function readJsonSafe(path) {
|
|
|
64
218
|
}
|
|
65
219
|
}
|
|
66
220
|
function writeJsonAtomic(path, value) {
|
|
221
|
+
writeTextAtomic(path, `${JSON.stringify(value, null, 2)}\n`);
|
|
222
|
+
}
|
|
223
|
+
function writeTextAtomic(path, content) {
|
|
67
224
|
mkdirSync(dirname(path), { recursive: true });
|
|
68
225
|
const tmp = `${path}.tmp-${process.pid}-${Date.now()}`;
|
|
69
|
-
writeFileSync(tmp,
|
|
226
|
+
writeFileSync(tmp, content, "utf-8");
|
|
70
227
|
renameSync(tmp, path);
|
|
71
228
|
}
|
|
72
229
|
function logInstalled(label, target) {
|
|
@@ -80,7 +237,7 @@ function logBackup(target) {
|
|
|
80
237
|
}
|
|
81
238
|
//#endregion
|
|
82
239
|
//#region src/cli/connect/json-mcp-adapter.ts
|
|
83
|
-
function entryMatches$
|
|
240
|
+
function entryMatches$3(entry) {
|
|
84
241
|
if (!entry || typeof entry !== "object") return false;
|
|
85
242
|
const e = entry;
|
|
86
243
|
if (e["command"] !== "npx") return false;
|
|
@@ -91,6 +248,7 @@ function createJsonMcpAdapter(config) {
|
|
|
91
248
|
return {
|
|
92
249
|
name: config.name,
|
|
93
250
|
displayName: config.displayName,
|
|
251
|
+
category: config.category ?? "mcp",
|
|
94
252
|
...config.docs !== void 0 && { docs: config.docs },
|
|
95
253
|
...config.protocolNote !== void 0 && { protocolNote: config.protocolNote },
|
|
96
254
|
detect() {
|
|
@@ -100,9 +258,13 @@ function createJsonMcpAdapter(config) {
|
|
|
100
258
|
const existing = readJsonSafe(config.configPath);
|
|
101
259
|
const next = existing ? { ...existing } : {};
|
|
102
260
|
const servers = { ...next[wrapperKey] ?? {} };
|
|
103
|
-
const alreadyHas = entryMatches$
|
|
261
|
+
const alreadyHas = entryMatches$3(servers["agentmemory"]);
|
|
104
262
|
if (alreadyHas && !opts.force) {
|
|
105
263
|
logAlreadyWired(config.displayName, config.configPath);
|
|
264
|
+
if (opts.withHooks && config.installHooks) {
|
|
265
|
+
const hookResult = config.installHooks(opts);
|
|
266
|
+
if (hookResult.kind === "skipped") p.log.warn(`${config.displayName} hooks skipped: ${hookResult.reason}.`);
|
|
267
|
+
}
|
|
106
268
|
return {
|
|
107
269
|
kind: "already-wired",
|
|
108
270
|
mutatedPath: config.configPath
|
|
@@ -110,6 +272,10 @@ function createJsonMcpAdapter(config) {
|
|
|
110
272
|
}
|
|
111
273
|
if (opts.dryRun) {
|
|
112
274
|
p.log.info(`[dry-run] Would ${alreadyHas ? "overwrite" : "add"} ${wrapperKey}.agentmemory in ${config.configPath}`);
|
|
275
|
+
if (opts.withHooks && config.installHooks) {
|
|
276
|
+
const hookResult = config.installHooks(opts);
|
|
277
|
+
if (hookResult.kind === "skipped") p.log.warn(`${config.displayName} hooks skipped: ${hookResult.reason}.`);
|
|
278
|
+
}
|
|
113
279
|
return {
|
|
114
280
|
kind: "installed",
|
|
115
281
|
mutatedPath: config.configPath
|
|
@@ -127,7 +293,7 @@ function createJsonMcpAdapter(config) {
|
|
|
127
293
|
next[wrapperKey] = servers;
|
|
128
294
|
writeJsonAtomic(config.configPath, next);
|
|
129
295
|
const verifyServers = readJsonSafe(config.configPath)?.[wrapperKey];
|
|
130
|
-
if (!entryMatches$
|
|
296
|
+
if (!entryMatches$3(verifyServers?.["agentmemory"])) {
|
|
131
297
|
p.log.error(`Verification failed: ${config.configPath} did not contain ${wrapperKey}.agentmemory after write.`);
|
|
132
298
|
return {
|
|
133
299
|
kind: "skipped",
|
|
@@ -135,6 +301,10 @@ function createJsonMcpAdapter(config) {
|
|
|
135
301
|
};
|
|
136
302
|
}
|
|
137
303
|
logInstalled(config.displayName, config.configPath);
|
|
304
|
+
if (opts.withHooks && config.installHooks) {
|
|
305
|
+
const hookResult = config.installHooks(opts);
|
|
306
|
+
if (hookResult.kind === "skipped") p.log.warn(`${config.displayName} hooks skipped: ${hookResult.reason}. MCP wiring still applied.`);
|
|
307
|
+
}
|
|
138
308
|
return {
|
|
139
309
|
kind: "installed",
|
|
140
310
|
mutatedPath: config.configPath,
|
|
@@ -146,7 +316,7 @@ function createJsonMcpAdapter(config) {
|
|
|
146
316
|
//#endregion
|
|
147
317
|
//#region src/cli/connect/antigravity.ts
|
|
148
318
|
const ANTIGRAVITY_DIR = platform() === "darwin" ? join(homedir(), "Library", "Application Support", "Antigravity", "User") : join(homedir(), ".config", "Antigravity", "User");
|
|
149
|
-
const adapter$
|
|
319
|
+
const adapter$20 = createJsonMcpAdapter({
|
|
150
320
|
name: "antigravity",
|
|
151
321
|
displayName: "Antigravity",
|
|
152
322
|
detectDir: ANTIGRAVITY_DIR,
|
|
@@ -155,6 +325,84 @@ const adapter$16 = createJsonMcpAdapter({
|
|
|
155
325
|
protocolNote: "→ Using MCP via mcp_config.json. Antigravity replaces Gemini CLI (sunset 2026-06-18)."
|
|
156
326
|
});
|
|
157
327
|
//#endregion
|
|
328
|
+
//#region src/cli/connect/antigravity-hooks.ts
|
|
329
|
+
/** Tool events: `[ { matcher, hooks: [...] } ]`. */
|
|
330
|
+
const TOOL_EVENT_KEYS = new Set(["PreToolUse", "PostToolUse"]);
|
|
331
|
+
/** Lifecycle events: a flat `[ { type, command } ]` handler list. */
|
|
332
|
+
const LIFECYCLE_EVENT_KEYS = new Set([
|
|
333
|
+
"PreInvocation",
|
|
334
|
+
"PostInvocation",
|
|
335
|
+
"Stop"
|
|
336
|
+
]);
|
|
337
|
+
/** Events Antigravity dispatches. Anything else in a bundle is metadata. */
|
|
338
|
+
const EVENT_KEYS = new Set([...TOOL_EVENT_KEYS, ...LIFECYCLE_EVENT_KEYS]);
|
|
339
|
+
function buildMergedAntigravityHooks(existing, pluginRoot, manifestFile = "hooks.antigravity.json") {
|
|
340
|
+
const ours = JSON.parse(readFileSync(join(pluginRoot, "hooks", manifestFile), "utf-8"));
|
|
341
|
+
const scriptsDir = join(pluginRoot, "scripts");
|
|
342
|
+
const out = {};
|
|
343
|
+
for (const [name, bundle] of Object.entries(existing ?? {})) {
|
|
344
|
+
if (isAgentmemoryBundle(bundle, scriptsDir)) continue;
|
|
345
|
+
out[name] = bundle;
|
|
346
|
+
}
|
|
347
|
+
for (const [name, bundle] of Object.entries(ours)) out[name] = resolveBundle(bundle, pluginRoot);
|
|
348
|
+
return out;
|
|
349
|
+
}
|
|
350
|
+
/** True when `pluginRoot` cannot be expressed in an Antigravity `command`. */
|
|
351
|
+
function containsSpaces(pluginRoot) {
|
|
352
|
+
return /\s/.test(pluginRoot);
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Every handler in a bundle, across both event shapes: an entry that carries
|
|
356
|
+
* no `hooks` array is itself the handler.
|
|
357
|
+
*/
|
|
358
|
+
function allHandlers(bundle) {
|
|
359
|
+
const out = [];
|
|
360
|
+
for (const [key, value] of Object.entries(bundle)) {
|
|
361
|
+
if (!EVENT_KEYS.has(key) || !Array.isArray(value)) continue;
|
|
362
|
+
for (const entry of value) {
|
|
363
|
+
if (!entry || typeof entry !== "object") continue;
|
|
364
|
+
const nested = entry.hooks;
|
|
365
|
+
if (Array.isArray(nested)) out.push(...nested);
|
|
366
|
+
else out.push(entry);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
return out;
|
|
370
|
+
}
|
|
371
|
+
function isAgentmemoryBundle(bundle, scriptsDir) {
|
|
372
|
+
if (!bundle || typeof bundle !== "object" || Array.isArray(bundle)) return false;
|
|
373
|
+
const normalizedScriptsDir = normalizePathForCommandMatch$1(scriptsDir);
|
|
374
|
+
return allHandlers(bundle).some((handler) => normalizePathForCommandMatch$1(handler?.command ?? "").includes(normalizedScriptsDir));
|
|
375
|
+
}
|
|
376
|
+
function resolveBundle(bundle, pluginRoot) {
|
|
377
|
+
const out = {};
|
|
378
|
+
for (const [key, value] of Object.entries(bundle)) {
|
|
379
|
+
if (!EVENT_KEYS.has(key) || !Array.isArray(value)) {
|
|
380
|
+
out[key] = value;
|
|
381
|
+
continue;
|
|
382
|
+
}
|
|
383
|
+
if (LIFECYCLE_EVENT_KEYS.has(key)) {
|
|
384
|
+
out[key] = value.map((handler) => resolveHandler(handler, pluginRoot));
|
|
385
|
+
continue;
|
|
386
|
+
}
|
|
387
|
+
out[key] = value.map((entry) => {
|
|
388
|
+
const next = { hooks: entry.hooks.map((handler) => resolveHandler(handler, pluginRoot)) };
|
|
389
|
+
if (entry.matcher !== void 0) next.matcher = entry.matcher;
|
|
390
|
+
return next;
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
return out;
|
|
394
|
+
}
|
|
395
|
+
function resolveHandler(handler, pluginRoot) {
|
|
396
|
+
return {
|
|
397
|
+
type: handler.type,
|
|
398
|
+
command: handler.command.replace(/\$\{CLAUDE_PLUGIN_ROOT\}/g, () => pluginRoot),
|
|
399
|
+
...handler.timeout !== void 0 && { timeout: handler.timeout }
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
function normalizePathForCommandMatch$1(value) {
|
|
403
|
+
return value.replace(/\\/g, "/");
|
|
404
|
+
}
|
|
405
|
+
//#endregion
|
|
158
406
|
//#region src/cli/connect/codex-hooks.ts
|
|
159
407
|
/**
|
|
160
408
|
* Locate the bundled `plugin/` directory at runtime. Walks up from the
|
|
@@ -214,21 +462,78 @@ function normalizePathForCommandMatch(value) {
|
|
|
214
462
|
return value.replace(/\\/g, "/");
|
|
215
463
|
}
|
|
216
464
|
//#endregion
|
|
465
|
+
//#region src/cli/connect/antigravity-cli.ts
|
|
466
|
+
const GEMINI_DIR = join(homedir(), ".gemini");
|
|
467
|
+
const ANTIGRAVITY_CLI_DIR = join(GEMINI_DIR, "antigravity-cli");
|
|
468
|
+
const CUSTOMIZATION_DIR = join(GEMINI_DIR, "config");
|
|
469
|
+
const ANTIGRAVITY_CLI_HOOKS = join(CUSTOMIZATION_DIR, "hooks.json");
|
|
470
|
+
const adapter$19 = createJsonMcpAdapter({
|
|
471
|
+
name: "antigravity-cli",
|
|
472
|
+
displayName: "Antigravity CLI (agy)",
|
|
473
|
+
detectDir: ANTIGRAVITY_CLI_DIR,
|
|
474
|
+
configPath: join(CUSTOMIZATION_DIR, "mcp_config.json"),
|
|
475
|
+
docs: "https://github.com/rohitg00/agentmemory#other-agents",
|
|
476
|
+
protocolNote: "→ Using MCP via ~/.gemini/config/mcp_config.json (the agy CLI, not the Antigravity IDE — that one is `connect antigravity`). The `/mcp` slash command inside agy lists configured servers. Pass --with-hooks to also install the native ~/.gemini/config/hooks.json auto-capture hooks.",
|
|
477
|
+
installHooks: installAntigravityCliHooks
|
|
478
|
+
});
|
|
479
|
+
/**
|
|
480
|
+
* Merge the bundled `plugin/hooks/hooks.antigravity.json` into
|
|
481
|
+
* `~/.gemini/config/hooks.json`, replacing only the bundle agentmemory owns.
|
|
482
|
+
*/
|
|
483
|
+
function installAntigravityCliHooks(opts) {
|
|
484
|
+
let pluginRoot;
|
|
485
|
+
try {
|
|
486
|
+
pluginRoot = findPluginRoot();
|
|
487
|
+
} catch (err) {
|
|
488
|
+
return {
|
|
489
|
+
kind: "skipped",
|
|
490
|
+
reason: err instanceof Error ? err.message : String(err)
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
if (containsSpaces(pluginRoot)) return {
|
|
494
|
+
kind: "skipped",
|
|
495
|
+
reason: `Antigravity CLI cannot run hook commands whose path contains spaces, and agentmemory is installed at ${pluginRoot}. Reinstall it under a space-free path to use --with-hooks; MCP works either way.`
|
|
496
|
+
};
|
|
497
|
+
const existing = readJsonSafe(ANTIGRAVITY_CLI_HOOKS);
|
|
498
|
+
const merged = buildMergedAntigravityHooks(existing, pluginRoot);
|
|
499
|
+
if (opts.dryRun) {
|
|
500
|
+
p.log.info(`[dry-run] Would ${existing ? "merge" : "create"} ${ANTIGRAVITY_CLI_HOOKS} with ${Object.keys(merged).length} hook bundle(s)`);
|
|
501
|
+
return {
|
|
502
|
+
kind: "installed",
|
|
503
|
+
mutatedPath: ANTIGRAVITY_CLI_HOOKS
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
let backupPath;
|
|
507
|
+
if (existsSync(ANTIGRAVITY_CLI_HOOKS)) {
|
|
508
|
+
backupPath = backupFile(ANTIGRAVITY_CLI_HOOKS, "antigravity-cli-hooks", "json");
|
|
509
|
+
logBackup(backupPath);
|
|
510
|
+
} else mkdirSync(CUSTOMIZATION_DIR, { recursive: true });
|
|
511
|
+
writeJsonAtomic(ANTIGRAVITY_CLI_HOOKS, merged);
|
|
512
|
+
logInstalled("Antigravity CLI hooks", ANTIGRAVITY_CLI_HOOKS);
|
|
513
|
+
p.log.info("User-scope hooks reference absolute paths under the bundled plugin/ dir. Re-run `agentmemory connect antigravity-cli --with-hooks` after upgrading agentmemory to refresh them.");
|
|
514
|
+
return {
|
|
515
|
+
kind: "installed",
|
|
516
|
+
mutatedPath: ANTIGRAVITY_CLI_HOOKS,
|
|
517
|
+
...backupPath !== void 0 && { backupPath }
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
//#endregion
|
|
217
521
|
//#region src/cli/connect/claude-code.ts
|
|
218
522
|
const CLAUDE_DIR = join(homedir(), ".claude");
|
|
219
523
|
const CLAUDE_JSON = join(homedir(), ".claude.json");
|
|
220
524
|
const CLAUDE_SETTINGS = join(CLAUDE_DIR, "settings.json");
|
|
221
|
-
function entryMatches$
|
|
525
|
+
function entryMatches$2(entry) {
|
|
222
526
|
if (!entry || typeof entry !== "object") return false;
|
|
223
527
|
const e = entry;
|
|
224
528
|
if (e["command"] !== "npx") return false;
|
|
225
529
|
return (Array.isArray(e["args"]) ? e["args"] : []).includes("@agentmemory/mcp");
|
|
226
530
|
}
|
|
227
|
-
const adapter$
|
|
531
|
+
const adapter$18 = {
|
|
228
532
|
name: "claude-code",
|
|
229
533
|
displayName: "Claude Code",
|
|
534
|
+
category: "native",
|
|
230
535
|
docs: "https://github.com/rohitg00/agentmemory#claude-code-one-block-paste-it",
|
|
231
|
-
protocolNote: "→ Using MCP. Hooks are also available — see
|
|
536
|
+
protocolNote: "→ Using MCP. Hooks are also available — see https://github.com/rohitg00/agentmemory#claude-code-one-block-paste-it.",
|
|
232
537
|
detect() {
|
|
233
538
|
return existsSync(CLAUDE_DIR);
|
|
234
539
|
},
|
|
@@ -236,7 +541,7 @@ const adapter$15 = {
|
|
|
236
541
|
const existing = readJsonSafe(CLAUDE_JSON);
|
|
237
542
|
const next = existing ? { ...existing } : {};
|
|
238
543
|
const servers = { ...next.mcpServers ?? {} };
|
|
239
|
-
const alreadyHas = entryMatches$
|
|
544
|
+
const alreadyHas = entryMatches$2(servers["agentmemory"]);
|
|
240
545
|
if (alreadyHas && !opts.force) {
|
|
241
546
|
logAlreadyWired("Claude Code", CLAUDE_JSON);
|
|
242
547
|
if (opts.withHooks) {
|
|
@@ -266,7 +571,7 @@ const adapter$15 = {
|
|
|
266
571
|
servers["agentmemory"] = AGENTMEMORY_MCP_BLOCK;
|
|
267
572
|
next.mcpServers = servers;
|
|
268
573
|
writeJsonAtomic(CLAUDE_JSON, next);
|
|
269
|
-
if (!entryMatches$
|
|
574
|
+
if (!entryMatches$2(readJsonSafe(CLAUDE_JSON)?.mcpServers?.["agentmemory"])) {
|
|
270
575
|
p.log.error(`Verification failed: ${CLAUDE_JSON} did not contain mcpServers.agentmemory after write.`);
|
|
271
576
|
return {
|
|
272
577
|
kind: "skipped",
|
|
@@ -335,7 +640,7 @@ function installClaudeHooks(opts) {
|
|
|
335
640
|
}
|
|
336
641
|
//#endregion
|
|
337
642
|
//#region src/cli/connect/cline.ts
|
|
338
|
-
const adapter$
|
|
643
|
+
const adapter$17 = createJsonMcpAdapter({
|
|
339
644
|
name: "cline",
|
|
340
645
|
displayName: "Cline",
|
|
341
646
|
detectDir: join(homedir(), ".cline"),
|
|
@@ -347,13 +652,14 @@ const adapter$14 = createJsonMcpAdapter({
|
|
|
347
652
|
//#region src/cli/connect/copilot-cli.ts
|
|
348
653
|
const COPILOT_DIR = process.env["COPILOT_HOME"] || join(homedir(), ".copilot");
|
|
349
654
|
const COPILOT_MCP_JSON = join(COPILOT_DIR, "mcp-config.json");
|
|
350
|
-
function entryMatches(entry) {
|
|
655
|
+
function entryMatches$1(entry) {
|
|
351
656
|
if (!entry || typeof entry !== "object") return false;
|
|
352
657
|
return JSON.stringify(entry) === JSON.stringify(AGENTMEMORY_COPILOT_MCP_BLOCK);
|
|
353
658
|
}
|
|
354
|
-
const adapter$
|
|
659
|
+
const adapter$16 = {
|
|
355
660
|
name: "copilot-cli",
|
|
356
661
|
displayName: "GitHub Copilot CLI",
|
|
662
|
+
category: "native",
|
|
357
663
|
docs: "https://github.com/rohitg00/agentmemory#github-copilot-cli",
|
|
358
664
|
protocolNote: "→ Using MCP. Install the plugin too for full hooks/skills coverage.",
|
|
359
665
|
detect() {
|
|
@@ -363,7 +669,7 @@ const adapter$13 = {
|
|
|
363
669
|
const existing = readJsonSafe(COPILOT_MCP_JSON);
|
|
364
670
|
const next = existing ? { ...existing } : {};
|
|
365
671
|
const servers = { ...next.mcpServers ?? {} };
|
|
366
|
-
const alreadyHas = entryMatches(servers["agentmemory"]);
|
|
672
|
+
const alreadyHas = entryMatches$1(servers["agentmemory"]);
|
|
367
673
|
if (alreadyHas && !opts.force) {
|
|
368
674
|
logAlreadyWired("GitHub Copilot CLI", COPILOT_MCP_JSON);
|
|
369
675
|
return {
|
|
@@ -386,7 +692,7 @@ const adapter$13 = {
|
|
|
386
692
|
servers["agentmemory"] = AGENTMEMORY_COPILOT_MCP_BLOCK;
|
|
387
693
|
next.mcpServers = servers;
|
|
388
694
|
writeJsonAtomic(COPILOT_MCP_JSON, next);
|
|
389
|
-
if (!entryMatches(readJsonSafe(COPILOT_MCP_JSON)?.mcpServers?.["agentmemory"])) {
|
|
695
|
+
if (!entryMatches$1(readJsonSafe(COPILOT_MCP_JSON)?.mcpServers?.["agentmemory"])) {
|
|
390
696
|
p.log.error(`Verification failed: ${COPILOT_MCP_JSON} did not contain mcpServers.agentmemory after write.`);
|
|
391
697
|
return {
|
|
392
698
|
kind: "skipped",
|
|
@@ -433,9 +739,10 @@ function stripExistingBlock(toml) {
|
|
|
433
739
|
}
|
|
434
740
|
return out.join("\n").replace(/\n{3,}$/, "\n\n").trimEnd() + "\n";
|
|
435
741
|
}
|
|
436
|
-
const adapter$
|
|
742
|
+
const adapter$15 = {
|
|
437
743
|
name: "codex",
|
|
438
744
|
displayName: "Codex CLI",
|
|
745
|
+
category: "native",
|
|
439
746
|
docs: "https://github.com/rohitg00/agentmemory#codex-cli-codex-plugin-platform",
|
|
440
747
|
protocolNote: "→ Using MCP. Hooks ship via the Codex plugin; on Codex Desktop, also pass --with-hooks to install the global hooks.json workaround for openai/codex#16430.",
|
|
441
748
|
detect() {
|
|
@@ -519,7 +826,8 @@ function installCodexHooks(opts) {
|
|
|
519
826
|
}
|
|
520
827
|
writeJsonAtomic(CODEX_HOOKS, merged);
|
|
521
828
|
logInstalled("Codex hooks (workaround for openai/codex#16430)", CODEX_HOOKS);
|
|
522
|
-
p.log.
|
|
829
|
+
p.log.warn("Codex runs only trusted hooks: launch `codex` (the TUI) once and choose \"Trust all and continue\" at the \"Hooks need review\" prompt. `codex exec` never shows the prompt, so hooks stay inert until then.");
|
|
830
|
+
p.log.info("User-scope hooks reference absolute paths under the bundled plugin/ dir. Re-run `agentmemory connect codex --with-hooks` after upgrading agentmemory to refresh them, then re-approve in the TUI.");
|
|
523
831
|
return {
|
|
524
832
|
kind: "installed",
|
|
525
833
|
mutatedPath: CODEX_HOOKS,
|
|
@@ -557,9 +865,10 @@ function renderFreshYaml() {
|
|
|
557
865
|
""
|
|
558
866
|
].join("\n");
|
|
559
867
|
}
|
|
560
|
-
const adapter$
|
|
868
|
+
const adapter$14 = {
|
|
561
869
|
name: "continue",
|
|
562
870
|
displayName: "Continue",
|
|
871
|
+
category: "mcp",
|
|
563
872
|
docs: "https://github.com/rohitg00/agentmemory#other-agents",
|
|
564
873
|
protocolNote: "→ Using MCP via ~/.continue/config.yaml (preferred) or config.json (legacy, only when no yaml).",
|
|
565
874
|
detect() {
|
|
@@ -636,7 +945,7 @@ const adapter$11 = {
|
|
|
636
945
|
};
|
|
637
946
|
//#endregion
|
|
638
947
|
//#region src/cli/connect/cursor.ts
|
|
639
|
-
const adapter$
|
|
948
|
+
const adapter$13 = createJsonMcpAdapter({
|
|
640
949
|
name: "cursor",
|
|
641
950
|
displayName: "Cursor",
|
|
642
951
|
detectDir: join(homedir(), ".cursor"),
|
|
@@ -645,19 +954,225 @@ const adapter$10 = createJsonMcpAdapter({
|
|
|
645
954
|
protocolNote: "→ Using MCP (the only protocol Cursor speaks). Memory bridge runs at :3111 underneath."
|
|
646
955
|
});
|
|
647
956
|
//#endregion
|
|
957
|
+
//#region src/cli/connect/devin.ts
|
|
958
|
+
function devinDir() {
|
|
959
|
+
if (platform() === "win32") {
|
|
960
|
+
const appData = process.env["APPDATA"];
|
|
961
|
+
if (appData) return join(appData, "devin");
|
|
962
|
+
}
|
|
963
|
+
const xdg = process.env["XDG_CONFIG_HOME"];
|
|
964
|
+
return xdg ? join(xdg, "devin") : join(homedir(), ".config", "devin");
|
|
965
|
+
}
|
|
966
|
+
const DEVIN_DIR = devinDir();
|
|
967
|
+
const DEVIN_CONFIG = join(DEVIN_DIR, "config.json");
|
|
968
|
+
const adapter$12 = createJsonMcpAdapter({
|
|
969
|
+
name: "devin",
|
|
970
|
+
displayName: "Devin CLI",
|
|
971
|
+
detectDir: DEVIN_DIR,
|
|
972
|
+
configPath: DEVIN_CONFIG,
|
|
973
|
+
docs: "https://github.com/rohitg00/agentmemory#other-agents",
|
|
974
|
+
protocolNote: "→ Using MCP via the user config. Devin CLI migrates mcpServers into mcp_config.json on newer builds. Pass --with-hooks for native auto-capture.",
|
|
975
|
+
installHooks: installDevinHooks
|
|
976
|
+
});
|
|
977
|
+
function installDevinHooks(opts) {
|
|
978
|
+
let pluginRoot;
|
|
979
|
+
try {
|
|
980
|
+
pluginRoot = findPluginRoot();
|
|
981
|
+
} catch (err) {
|
|
982
|
+
return {
|
|
983
|
+
kind: "skipped",
|
|
984
|
+
reason: err instanceof Error ? err.message : String(err)
|
|
985
|
+
};
|
|
986
|
+
}
|
|
987
|
+
const existing = readJsonSafe(DEVIN_CONFIG) ?? {};
|
|
988
|
+
const merged = buildMergedHooks(existing["hooks"] ? { hooks: existing["hooks"] } : null, pluginRoot, "hooks.devin.json");
|
|
989
|
+
const next = {
|
|
990
|
+
...existing,
|
|
991
|
+
hooks: merged.hooks
|
|
992
|
+
};
|
|
993
|
+
if (opts.dryRun) {
|
|
994
|
+
p.log.info(`[dry-run] Would write ${Object.keys(merged.hooks).length} hook event(s) into ${DEVIN_CONFIG}`);
|
|
995
|
+
return {
|
|
996
|
+
kind: "installed",
|
|
997
|
+
mutatedPath: DEVIN_CONFIG
|
|
998
|
+
};
|
|
999
|
+
}
|
|
1000
|
+
let backupPath;
|
|
1001
|
+
if (existsSync(DEVIN_CONFIG)) {
|
|
1002
|
+
backupPath = backupFile(DEVIN_CONFIG, "devin-hooks", "json");
|
|
1003
|
+
logBackup(backupPath);
|
|
1004
|
+
} else mkdirSync(DEVIN_DIR, { recursive: true });
|
|
1005
|
+
writeJsonAtomic(DEVIN_CONFIG, next);
|
|
1006
|
+
logInstalled("Devin CLI hooks", DEVIN_CONFIG);
|
|
1007
|
+
p.log.info("Verify with `/hooks` inside devin. Re-run `agentmemory connect devin --with-hooks` after upgrading agentmemory so the plugin paths stay current.");
|
|
1008
|
+
return {
|
|
1009
|
+
kind: "installed",
|
|
1010
|
+
mutatedPath: DEVIN_CONFIG,
|
|
1011
|
+
...backupPath !== void 0 && { backupPath }
|
|
1012
|
+
};
|
|
1013
|
+
}
|
|
1014
|
+
//#endregion
|
|
648
1015
|
//#region src/cli/connect/droid.ts
|
|
649
|
-
const
|
|
1016
|
+
const DROID_DIR = join(homedir(), ".factory");
|
|
1017
|
+
const DROID_HOOKS = join(DROID_DIR, "hooks.json");
|
|
1018
|
+
const adapter$11 = createJsonMcpAdapter({
|
|
650
1019
|
name: "droid",
|
|
651
1020
|
displayName: "Droid (Factory.ai)",
|
|
652
|
-
detectDir:
|
|
653
|
-
configPath: join(
|
|
1021
|
+
detectDir: DROID_DIR,
|
|
1022
|
+
configPath: join(DROID_DIR, "mcp.json"),
|
|
654
1023
|
docs: "https://github.com/rohitg00/agentmemory#other-agents",
|
|
655
|
-
protocolNote: "→ Using MCP via ~/.factory/mcp.json. The `/mcp` slash command inside droid lists configured servers.",
|
|
656
|
-
extraEntryFields: { type: "stdio" }
|
|
1024
|
+
protocolNote: "→ Using MCP via ~/.factory/mcp.json. The `/mcp` slash command inside droid lists configured servers. Pass --with-hooks to also install the native ~/.factory/hooks.json auto-capture hooks.",
|
|
1025
|
+
extraEntryFields: { type: "stdio" },
|
|
1026
|
+
installHooks: installDroidHooks
|
|
657
1027
|
});
|
|
1028
|
+
/**
|
|
1029
|
+
* Merge the bundled `plugin/hooks/hooks.droid.json` into
|
|
1030
|
+
* `~/.factory/hooks.json`. Same idempotent merge/strip-by-script-path
|
|
1031
|
+
* behavior as the Codex and Claude Code hook installers: re-running keeps
|
|
1032
|
+
* user-authored hook entries and only replaces the ones agentmemory owns.
|
|
1033
|
+
*/
|
|
1034
|
+
function installDroidHooks(opts) {
|
|
1035
|
+
let pluginRoot;
|
|
1036
|
+
try {
|
|
1037
|
+
pluginRoot = findPluginRoot();
|
|
1038
|
+
} catch (err) {
|
|
1039
|
+
return {
|
|
1040
|
+
kind: "skipped",
|
|
1041
|
+
reason: err instanceof Error ? err.message : String(err)
|
|
1042
|
+
};
|
|
1043
|
+
}
|
|
1044
|
+
const existing = readJsonSafe(DROID_HOOKS);
|
|
1045
|
+
const merged = buildMergedHooks(existing, pluginRoot, "hooks.droid.json");
|
|
1046
|
+
if (opts.dryRun) {
|
|
1047
|
+
p.log.info(`[dry-run] Would ${existing ? "merge" : "create"} ${DROID_HOOKS} with ${Object.keys(merged.hooks).length} event(s)`);
|
|
1048
|
+
return {
|
|
1049
|
+
kind: "installed",
|
|
1050
|
+
mutatedPath: DROID_HOOKS
|
|
1051
|
+
};
|
|
1052
|
+
}
|
|
1053
|
+
let backupPath;
|
|
1054
|
+
if (existsSync(DROID_HOOKS)) {
|
|
1055
|
+
backupPath = backupFile(DROID_HOOKS, "droid-hooks", "json");
|
|
1056
|
+
logBackup(backupPath);
|
|
1057
|
+
} else mkdirSync(DROID_DIR, { recursive: true });
|
|
1058
|
+
writeJsonAtomic(DROID_HOOKS, merged);
|
|
1059
|
+
logInstalled("Droid hooks", DROID_HOOKS);
|
|
1060
|
+
p.log.info("User-scope hooks reference absolute paths under the bundled plugin/ dir. Re-run `agentmemory connect droid --with-hooks` after upgrading agentmemory to refresh them.");
|
|
1061
|
+
return {
|
|
1062
|
+
kind: "installed",
|
|
1063
|
+
mutatedPath: DROID_HOOKS,
|
|
1064
|
+
...backupPath !== void 0 && { backupPath }
|
|
1065
|
+
};
|
|
1066
|
+
}
|
|
1067
|
+
//#endregion
|
|
1068
|
+
//#region src/cli/connect/dsh.ts
|
|
1069
|
+
function dshHome() {
|
|
1070
|
+
return process.env["DSH_HOME"] || join(homedir(), ".dsh");
|
|
1071
|
+
}
|
|
1072
|
+
const MCP_BLOCK = `- insert:
|
|
1073
|
+
- id: agentmemory
|
|
1074
|
+
name: '@deepseek-ai/dsh-mcp-client'
|
|
1075
|
+
config:
|
|
1076
|
+
transport: stdio
|
|
1077
|
+
serverName: agentmemory
|
|
1078
|
+
command: npx
|
|
1079
|
+
args: ['-y', '@agentmemory/mcp']
|
|
1080
|
+
env:
|
|
1081
|
+
AGENTMEMORY_URL: http://localhost:3111
|
|
1082
|
+
`;
|
|
1083
|
+
const MCP_MARKER = "serverName: agentmemory";
|
|
1084
|
+
const HOOKS_MARKER = "id: agentmemory-hooks";
|
|
1085
|
+
function hooksBlock(hooksConfigPath) {
|
|
1086
|
+
return `- insert:
|
|
1087
|
+
- id: agentmemory-hooks
|
|
1088
|
+
name: '@deepseek-ai/dsh-hooks-claude-code'
|
|
1089
|
+
config:
|
|
1090
|
+
configPath: ${JSON.stringify(hooksConfigPath)}
|
|
1091
|
+
`;
|
|
1092
|
+
}
|
|
1093
|
+
function stripBlock(content, marker) {
|
|
1094
|
+
if (!content.includes(marker)) return content;
|
|
1095
|
+
const lines = content.split("\n");
|
|
1096
|
+
const markerIdx = lines.findIndex((l) => l.includes(marker));
|
|
1097
|
+
let start = markerIdx;
|
|
1098
|
+
while (start > 0 && !lines[start].startsWith("- ")) start--;
|
|
1099
|
+
let end = markerIdx + 1;
|
|
1100
|
+
while (end < lines.length && !lines[end].startsWith("- ")) end++;
|
|
1101
|
+
return lines.slice(0, start).concat(lines.slice(end)).join("\n").replace(/\n+$/, "\n");
|
|
1102
|
+
}
|
|
1103
|
+
function appendBlock(content, block) {
|
|
1104
|
+
const base = content.replace(/\n+$/, "\n");
|
|
1105
|
+
return base.trim() ? `${base}\n${block}` : block;
|
|
1106
|
+
}
|
|
1107
|
+
function installHooksFile(home) {
|
|
1108
|
+
const hooksPath = join(home, "agentmemory.hooks.json");
|
|
1109
|
+
const pluginRoot = findPluginRoot();
|
|
1110
|
+
writeJsonAtomic(hooksPath, buildMergedHooks(readJsonSafe(hooksPath), pluginRoot, "hooks.codex.json"));
|
|
1111
|
+
return hooksPath;
|
|
1112
|
+
}
|
|
1113
|
+
const adapter$10 = {
|
|
1114
|
+
name: "dsh",
|
|
1115
|
+
displayName: "DeepSeek Harness",
|
|
1116
|
+
docs: "https://github.com/rohitg00/agentmemory#other-agents",
|
|
1117
|
+
protocolNote: "→ Using MCP via $DSH_HOME/cordis.patch.yml (the home-level patch layer every profile loads). Tools appear as mcp__agentmemory__*. Pass --with-hooks to also wire auto-capture through Harness's Claude Code hook bridge.",
|
|
1118
|
+
category: "native",
|
|
1119
|
+
detect() {
|
|
1120
|
+
return existsSync(dshHome());
|
|
1121
|
+
},
|
|
1122
|
+
async install(opts) {
|
|
1123
|
+
const home = dshHome();
|
|
1124
|
+
const configPath = join(home, "cordis.patch.yml");
|
|
1125
|
+
const existing = existsSync(configPath) ? readFileSync(configPath, "utf-8") : "";
|
|
1126
|
+
const wantHooks = opts.withHooks === true;
|
|
1127
|
+
const hasMcp = existing.includes(MCP_MARKER);
|
|
1128
|
+
const hasHooks = existing.includes(HOOKS_MARKER);
|
|
1129
|
+
if (hasMcp && (!wantHooks || hasHooks) && !opts.force) {
|
|
1130
|
+
logAlreadyWired(this.displayName, configPath);
|
|
1131
|
+
return {
|
|
1132
|
+
kind: "already-wired",
|
|
1133
|
+
mutatedPath: configPath
|
|
1134
|
+
};
|
|
1135
|
+
}
|
|
1136
|
+
if (opts.dryRun) {
|
|
1137
|
+
p.log.info(`[dry-run] Would append the agentmemory mcp-client row${wantHooks ? " and the hooks-claude-code row" : ""} to ${configPath}`);
|
|
1138
|
+
return {
|
|
1139
|
+
kind: "installed",
|
|
1140
|
+
mutatedPath: configPath
|
|
1141
|
+
};
|
|
1142
|
+
}
|
|
1143
|
+
let backupPath;
|
|
1144
|
+
if (existsSync(configPath)) {
|
|
1145
|
+
backupPath = backupFile(configPath, this.name, "yml");
|
|
1146
|
+
logBackup(backupPath);
|
|
1147
|
+
} else mkdirSync(dirname(configPath), { recursive: true });
|
|
1148
|
+
let next = stripBlock(existing, MCP_MARKER);
|
|
1149
|
+
next = appendBlock(next, MCP_BLOCK);
|
|
1150
|
+
if (wantHooks) {
|
|
1151
|
+
const hooksPath = installHooksFile(home);
|
|
1152
|
+
next = stripBlock(next, HOOKS_MARKER);
|
|
1153
|
+
next = appendBlock(next, hooksBlock(hooksPath));
|
|
1154
|
+
p.log.info(`Hook manifest: ${hooksPath}`);
|
|
1155
|
+
}
|
|
1156
|
+
writeTextAtomic(configPath, next);
|
|
1157
|
+
const written = readFileSync(configPath, "utf-8");
|
|
1158
|
+
if (!written.includes(MCP_MARKER) || wantHooks && !written.includes(HOOKS_MARKER)) {
|
|
1159
|
+
p.log.error(`Verification failed: ${configPath} did not contain the agentmemory rows after write.`);
|
|
1160
|
+
return {
|
|
1161
|
+
kind: "skipped",
|
|
1162
|
+
reason: "verification-failed"
|
|
1163
|
+
};
|
|
1164
|
+
}
|
|
1165
|
+
logInstalled(this.displayName, configPath);
|
|
1166
|
+
return {
|
|
1167
|
+
kind: "installed",
|
|
1168
|
+
mutatedPath: configPath,
|
|
1169
|
+
backupPath
|
|
1170
|
+
};
|
|
1171
|
+
}
|
|
1172
|
+
};
|
|
658
1173
|
//#endregion
|
|
659
1174
|
//#region src/cli/connect/gemini-cli.ts
|
|
660
|
-
const adapter$
|
|
1175
|
+
const adapter$9 = createJsonMcpAdapter({
|
|
661
1176
|
name: "gemini-cli",
|
|
662
1177
|
displayName: "Gemini CLI",
|
|
663
1178
|
detectDir: join(homedir(), ".gemini"),
|
|
@@ -670,11 +1185,12 @@ const adapter$8 = createJsonMcpAdapter({
|
|
|
670
1185
|
const HERMES_DIR = join(homedir(), ".hermes");
|
|
671
1186
|
const HERMES_CONFIG = join(HERMES_DIR, "config.yaml");
|
|
672
1187
|
const DOCS$2 = "https://github.com/rohitg00/agentmemory/tree/main/integrations/hermes";
|
|
673
|
-
const adapter$
|
|
1188
|
+
const adapter$8 = {
|
|
674
1189
|
name: "hermes",
|
|
675
1190
|
displayName: "Hermes Agent",
|
|
1191
|
+
category: "native",
|
|
676
1192
|
docs: DOCS$2,
|
|
677
|
-
protocolNote: "→ Using MCP. Hooks are also available — see
|
|
1193
|
+
protocolNote: "→ Using MCP. Hooks are also available — see https://github.com/rohitg00/agentmemory/tree/main/integrations/hermes.",
|
|
678
1194
|
detect() {
|
|
679
1195
|
return existsSync(HERMES_DIR);
|
|
680
1196
|
},
|
|
@@ -701,7 +1217,7 @@ const adapter$7 = {
|
|
|
701
1217
|
};
|
|
702
1218
|
//#endregion
|
|
703
1219
|
//#region src/cli/connect/kiro.ts
|
|
704
|
-
const adapter$
|
|
1220
|
+
const adapter$7 = createJsonMcpAdapter({
|
|
705
1221
|
name: "kiro",
|
|
706
1222
|
displayName: "Kiro",
|
|
707
1223
|
detectDir: join(homedir(), ".kiro"),
|
|
@@ -711,21 +1227,94 @@ const adapter$6 = createJsonMcpAdapter({
|
|
|
711
1227
|
});
|
|
712
1228
|
//#endregion
|
|
713
1229
|
//#region src/cli/connect/openclaw.ts
|
|
714
|
-
const adapter$
|
|
1230
|
+
const adapter$6 = createJsonMcpAdapter({
|
|
715
1231
|
name: "openclaw",
|
|
716
1232
|
displayName: "OpenClaw",
|
|
1233
|
+
category: "native",
|
|
717
1234
|
detectDir: join(homedir(), ".openclaw"),
|
|
718
1235
|
configPath: join(homedir(), ".openclaw", "openclaw.json"),
|
|
719
1236
|
docs: "https://github.com/rohitg00/agentmemory/tree/main/integrations/openclaw",
|
|
720
|
-
protocolNote: "→ Using MCP. Hooks are also available — see
|
|
1237
|
+
protocolNote: "→ Using MCP. Hooks are also available — see https://github.com/rohitg00/agentmemory/tree/main/integrations/openclaw."
|
|
721
1238
|
});
|
|
722
1239
|
//#endregion
|
|
1240
|
+
//#region src/cli/connect/opencode.ts
|
|
1241
|
+
const CONFIG_PATH = join(homedir(), ".config", "opencode", "opencode.json");
|
|
1242
|
+
const DETECT_DIR = join(homedir(), ".config", "opencode");
|
|
1243
|
+
const OPENCODE_ENTRY = {
|
|
1244
|
+
type: "local",
|
|
1245
|
+
command: [
|
|
1246
|
+
"npx",
|
|
1247
|
+
"-y",
|
|
1248
|
+
"@agentmemory/mcp"
|
|
1249
|
+
],
|
|
1250
|
+
enabled: true
|
|
1251
|
+
};
|
|
1252
|
+
function entryMatches(entry) {
|
|
1253
|
+
if (!entry || typeof entry !== "object") return false;
|
|
1254
|
+
const command = entry["command"];
|
|
1255
|
+
return Array.isArray(command) && command.includes("@agentmemory/mcp");
|
|
1256
|
+
}
|
|
1257
|
+
const adapter$5 = {
|
|
1258
|
+
name: "opencode",
|
|
1259
|
+
displayName: "OpenCode",
|
|
1260
|
+
category: "mcp",
|
|
1261
|
+
docs: "https://github.com/rohitg00/agentmemory#other-agents",
|
|
1262
|
+
protocolNote: "Using MCP via ~/.config/opencode/opencode.json (top-level `mcp` key). For full auto-capture, also install the bundled plugin in plugin/opencode/.",
|
|
1263
|
+
detect() {
|
|
1264
|
+
return existsSync(DETECT_DIR);
|
|
1265
|
+
},
|
|
1266
|
+
async install(opts) {
|
|
1267
|
+
const existing = readJsonSafe(CONFIG_PATH);
|
|
1268
|
+
const next = existing ? { ...existing } : {};
|
|
1269
|
+
const existingMcp = next["mcp"];
|
|
1270
|
+
const mcp = existingMcp && typeof existingMcp === "object" && !Array.isArray(existingMcp) ? { ...existingMcp } : {};
|
|
1271
|
+
const alreadyHas = entryMatches(mcp["agentmemory"]);
|
|
1272
|
+
if (alreadyHas && !opts.force) {
|
|
1273
|
+
logAlreadyWired(this.displayName, CONFIG_PATH);
|
|
1274
|
+
return {
|
|
1275
|
+
kind: "already-wired",
|
|
1276
|
+
mutatedPath: CONFIG_PATH
|
|
1277
|
+
};
|
|
1278
|
+
}
|
|
1279
|
+
if (opts.dryRun) {
|
|
1280
|
+
p.log.info(`[dry-run] Would ${alreadyHas ? "overwrite" : "add"} mcp.agentmemory in ${CONFIG_PATH}`);
|
|
1281
|
+
return {
|
|
1282
|
+
kind: "installed",
|
|
1283
|
+
mutatedPath: CONFIG_PATH
|
|
1284
|
+
};
|
|
1285
|
+
}
|
|
1286
|
+
let backupPath;
|
|
1287
|
+
if (existsSync(CONFIG_PATH)) {
|
|
1288
|
+
backupPath = backupFile(CONFIG_PATH, this.name);
|
|
1289
|
+
logBackup(backupPath);
|
|
1290
|
+
} else mkdirSync(dirname(CONFIG_PATH), { recursive: true });
|
|
1291
|
+
mcp["agentmemory"] = { ...OPENCODE_ENTRY };
|
|
1292
|
+
next["mcp"] = mcp;
|
|
1293
|
+
writeJsonAtomic(CONFIG_PATH, next);
|
|
1294
|
+
const verifyMcp = readJsonSafe(CONFIG_PATH)?.["mcp"];
|
|
1295
|
+
if (!entryMatches(verifyMcp?.["agentmemory"])) {
|
|
1296
|
+
p.log.error(`Verification failed: ${CONFIG_PATH} did not contain mcp.agentmemory after write.`);
|
|
1297
|
+
return {
|
|
1298
|
+
kind: "skipped",
|
|
1299
|
+
reason: "verification-failed"
|
|
1300
|
+
};
|
|
1301
|
+
}
|
|
1302
|
+
logInstalled(this.displayName, CONFIG_PATH);
|
|
1303
|
+
return {
|
|
1304
|
+
kind: "installed",
|
|
1305
|
+
mutatedPath: CONFIG_PATH,
|
|
1306
|
+
...backupPath !== void 0 && { backupPath }
|
|
1307
|
+
};
|
|
1308
|
+
}
|
|
1309
|
+
};
|
|
1310
|
+
//#endregion
|
|
723
1311
|
//#region src/cli/connect/openhuman.ts
|
|
724
1312
|
const OPENHUMAN_DIR = join(homedir(), ".openhuman");
|
|
725
1313
|
const DOCS$1 = "https://github.com/tinyhumansai/openhuman";
|
|
726
1314
|
const adapter$4 = {
|
|
727
1315
|
name: "openhuman",
|
|
728
1316
|
displayName: "OpenHuman",
|
|
1317
|
+
category: "native",
|
|
729
1318
|
docs: DOCS$1,
|
|
730
1319
|
protocolNote: "→ Using native hooks (REST API at :3111). MCP not required.",
|
|
731
1320
|
detect() {
|
|
@@ -752,31 +1341,75 @@ const adapter$4 = {
|
|
|
752
1341
|
const PI_DIR = join(homedir(), ".pi");
|
|
753
1342
|
const PI_EXT_DIR = join(PI_DIR, "agent", "extensions", "agentmemory");
|
|
754
1343
|
const DOCS = "https://github.com/rohitg00/agentmemory/tree/main/integrations/pi";
|
|
1344
|
+
const EXT_FILES = ["index.ts", "security.ts"];
|
|
1345
|
+
function findPiSourceDir() {
|
|
1346
|
+
let packageRoot;
|
|
1347
|
+
try {
|
|
1348
|
+
packageRoot = dirname(findPluginRoot());
|
|
1349
|
+
} catch {
|
|
1350
|
+
return null;
|
|
1351
|
+
}
|
|
1352
|
+
const dir = join(packageRoot, "integrations", "pi");
|
|
1353
|
+
return EXT_FILES.every((f) => existsSync(join(dir, f))) ? dir : null;
|
|
1354
|
+
}
|
|
755
1355
|
const adapter$3 = {
|
|
756
1356
|
name: "pi",
|
|
757
1357
|
displayName: "pi",
|
|
1358
|
+
category: "native",
|
|
758
1359
|
docs: DOCS,
|
|
759
|
-
protocolNote: "→ Using native hooks
|
|
1360
|
+
protocolNote: "→ Using native lifecycle hooks against the REST API at :3111 (recall on agent start, capture on agent end, memory tools). MCP not required.",
|
|
760
1361
|
detect() {
|
|
761
1362
|
return existsSync(PI_DIR);
|
|
762
1363
|
},
|
|
763
|
-
async install(
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
"
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
"",
|
|
775
|
-
|
|
776
|
-
|
|
1364
|
+
async install(opts) {
|
|
1365
|
+
const sourceDir = findPiSourceDir();
|
|
1366
|
+
if (!sourceDir) {
|
|
1367
|
+
p.log.error("Bundled pi extension not found (integrations/pi missing from the install) — reinstall agentmemory.");
|
|
1368
|
+
return {
|
|
1369
|
+
kind: "skipped",
|
|
1370
|
+
reason: "bundled-extension-missing"
|
|
1371
|
+
};
|
|
1372
|
+
}
|
|
1373
|
+
const sources = EXT_FILES.map((f) => ({
|
|
1374
|
+
name: f,
|
|
1375
|
+
content: readFileSync(join(sourceDir, f), "utf-8"),
|
|
1376
|
+
target: join(PI_EXT_DIR, f)
|
|
1377
|
+
}));
|
|
1378
|
+
if (sources.every((s) => existsSync(s.target) && readFileSync(s.target, "utf-8") === s.content) && !opts.force) {
|
|
1379
|
+
logAlreadyWired(this.displayName, PI_EXT_DIR);
|
|
1380
|
+
return {
|
|
1381
|
+
kind: "already-wired",
|
|
1382
|
+
mutatedPath: PI_EXT_DIR
|
|
1383
|
+
};
|
|
1384
|
+
}
|
|
1385
|
+
if (opts.dryRun) {
|
|
1386
|
+
p.log.info(`[dry-run] Would install the pi extension (${EXT_FILES.join(", ")}) into ${PI_EXT_DIR}`);
|
|
1387
|
+
return {
|
|
1388
|
+
kind: "installed",
|
|
1389
|
+
mutatedPath: PI_EXT_DIR
|
|
1390
|
+
};
|
|
1391
|
+
}
|
|
1392
|
+
let backupPath;
|
|
1393
|
+
for (const s of sources) if (existsSync(s.target) && readFileSync(s.target, "utf-8") !== s.content) {
|
|
1394
|
+
const backup = backupFile(s.target, `${this.name}-${s.name.replace(/\.ts$/, "")}`, "ts");
|
|
1395
|
+
logBackup(backup);
|
|
1396
|
+
backupPath ??= backup;
|
|
1397
|
+
}
|
|
1398
|
+
mkdirSync(PI_EXT_DIR, { recursive: true });
|
|
1399
|
+
for (const s of sources) writeTextAtomic(s.target, s.content);
|
|
1400
|
+
if (!sources.every((s) => existsSync(s.target) && readFileSync(s.target, "utf-8") === s.content)) {
|
|
1401
|
+
p.log.error(`Verification failed: ${PI_EXT_DIR} does not match the bundled extension.`);
|
|
1402
|
+
return {
|
|
1403
|
+
kind: "skipped",
|
|
1404
|
+
reason: "verification-failed"
|
|
1405
|
+
};
|
|
1406
|
+
}
|
|
1407
|
+
logInstalled(this.displayName, PI_EXT_DIR);
|
|
1408
|
+
p.log.info("pi auto-discovers the extension on next launch; a running pi picks it up with /reload. Verify with /agentmemory-status.");
|
|
777
1409
|
return {
|
|
778
|
-
kind: "
|
|
779
|
-
|
|
1410
|
+
kind: "installed",
|
|
1411
|
+
mutatedPath: PI_EXT_DIR,
|
|
1412
|
+
backupPath
|
|
780
1413
|
};
|
|
781
1414
|
}
|
|
782
1415
|
};
|
|
@@ -822,21 +1455,25 @@ var connect_exports = /* @__PURE__ */ __exportAll({
|
|
|
822
1455
|
runConnect: () => runConnect
|
|
823
1456
|
});
|
|
824
1457
|
const ADAPTERS = [
|
|
1458
|
+
adapter$18,
|
|
1459
|
+
adapter$16,
|
|
825
1460
|
adapter$15,
|
|
826
1461
|
adapter$13,
|
|
827
1462
|
adapter$12,
|
|
828
|
-
adapter$
|
|
829
|
-
adapter$8,
|
|
1463
|
+
adapter$9,
|
|
830
1464
|
adapter$2,
|
|
831
|
-
adapter$
|
|
832
|
-
adapter$
|
|
1465
|
+
adapter$20,
|
|
1466
|
+
adapter$19,
|
|
1467
|
+
adapter$7,
|
|
833
1468
|
adapter$1,
|
|
1469
|
+
adapter$17,
|
|
834
1470
|
adapter$14,
|
|
835
|
-
adapter$11,
|
|
836
1471
|
adapter,
|
|
837
|
-
adapter$
|
|
1472
|
+
adapter$11,
|
|
1473
|
+
adapter$10,
|
|
838
1474
|
adapter$5,
|
|
839
|
-
adapter$
|
|
1475
|
+
adapter$6,
|
|
1476
|
+
adapter$8,
|
|
840
1477
|
adapter$3,
|
|
841
1478
|
adapter$4
|
|
842
1479
|
];
|
|
@@ -853,16 +1490,19 @@ function parseFlags(args) {
|
|
|
853
1490
|
let force = false;
|
|
854
1491
|
let all = false;
|
|
855
1492
|
let withHooks = false;
|
|
1493
|
+
let guidelines = true;
|
|
856
1494
|
for (const a of args) if (a === "--dry-run") dryRun = true;
|
|
857
1495
|
else if (a === "--force") force = true;
|
|
858
1496
|
else if (a === "--all") all = true;
|
|
859
1497
|
else if (a === "--with-hooks") withHooks = true;
|
|
1498
|
+
else if (a === "--no-guidelines") guidelines = false;
|
|
860
1499
|
else if (!a.startsWith("-")) positional.push(a);
|
|
861
1500
|
return {
|
|
862
1501
|
dryRun,
|
|
863
1502
|
force,
|
|
864
1503
|
all,
|
|
865
1504
|
withHooks,
|
|
1505
|
+
guidelines,
|
|
866
1506
|
positional
|
|
867
1507
|
};
|
|
868
1508
|
}
|
|
@@ -877,7 +1517,18 @@ async function runAdapter(adapter, opts) {
|
|
|
877
1517
|
p.log.step(`Wiring ${adapter.displayName}…`);
|
|
878
1518
|
if (adapter.protocolNote) p.log.message(adapter.protocolNote);
|
|
879
1519
|
try {
|
|
880
|
-
|
|
1520
|
+
const result = await adapter.install(opts);
|
|
1521
|
+
if (opts.guidelines !== false && (result.kind === "installed" || result.kind === "already-wired")) try {
|
|
1522
|
+
const g = writeGuideline(adapter.name, {
|
|
1523
|
+
cwd: process.cwd(),
|
|
1524
|
+
dryRun: opts.dryRun
|
|
1525
|
+
});
|
|
1526
|
+
if (g.kind === "written") p.log.message(` ${pc.dim("guideline")} ${g.scope} → ${g.path} (memory auto-use)`);
|
|
1527
|
+
else if (g.kind === "would-write") p.log.message(` ${pc.dim("[dry-run] guideline")} → ${g.path}`);
|
|
1528
|
+
} catch (gerr) {
|
|
1529
|
+
p.log.warn(`${adapter.displayName}: guideline not written (${gerr instanceof Error ? gerr.message : String(gerr)})`);
|
|
1530
|
+
}
|
|
1531
|
+
return result;
|
|
881
1532
|
} catch (err) {
|
|
882
1533
|
p.log.error(`${adapter.displayName}: ${err instanceof Error ? err.message : String(err)}`);
|
|
883
1534
|
return {
|
|
@@ -887,7 +1538,7 @@ async function runAdapter(adapter, opts) {
|
|
|
887
1538
|
}
|
|
888
1539
|
}
|
|
889
1540
|
async function runConnect(args) {
|
|
890
|
-
const { dryRun, force, all, withHooks, positional } = parseFlags(args);
|
|
1541
|
+
const { dryRun, force, all, withHooks, guidelines, positional } = parseFlags(args);
|
|
891
1542
|
const allowWindowsAdapter = positional.length === 1 && positional[0]?.toLowerCase() === "copilot-cli";
|
|
892
1543
|
if (platform() === "win32" && !allowWindowsAdapter) {
|
|
893
1544
|
p.intro("agentmemory connect");
|
|
@@ -898,7 +1549,8 @@ async function runConnect(args) {
|
|
|
898
1549
|
const opts = {
|
|
899
1550
|
dryRun,
|
|
900
1551
|
force,
|
|
901
|
-
withHooks
|
|
1552
|
+
withHooks,
|
|
1553
|
+
guidelines
|
|
902
1554
|
};
|
|
903
1555
|
p.intro("agentmemory connect");
|
|
904
1556
|
if (positional.length === 0 && !all) {
|
|
@@ -963,19 +1615,19 @@ async function runConnect(args) {
|
|
|
963
1615
|
function summarize(results) {
|
|
964
1616
|
const lines = results.map(({ name, result }) => {
|
|
965
1617
|
switch (result.kind) {
|
|
966
|
-
case "installed": return ` ✓ ${name}${result.mutatedPath ? ` → ${result.mutatedPath}` : ""}`;
|
|
967
|
-
case "already-wired": return ` ✓ ${name} (already wired)`;
|
|
968
|
-
case "stub": return ` ⚠ ${name} (manual install required: ${result.reason})`;
|
|
969
|
-
case "skipped": return ` ✗ ${name} (skipped: ${result.reason})`;
|
|
1618
|
+
case "installed": return ` ${pc.green("✓")} ${pc.bold(name)}${result.mutatedPath ? ` ${pc.dim("→")} ${pc.cyan(result.mutatedPath)}` : ""}`;
|
|
1619
|
+
case "already-wired": return ` ${pc.green("✓")} ${pc.bold(name)} ${pc.dim("(already wired)")}`;
|
|
1620
|
+
case "stub": return ` ${pc.yellow("⚠")} ${pc.bold(name)} ${pc.yellow(`(manual install required: ${result.reason})`)}`;
|
|
1621
|
+
case "skipped": return ` ${pc.red("✗")} ${pc.bold(name)} ${pc.dim(`(skipped: ${result.reason})`)}`;
|
|
970
1622
|
}
|
|
971
1623
|
});
|
|
972
1624
|
p.note(lines.join("\n"), "summary");
|
|
973
1625
|
const stubs = results.filter((r) => r.result.kind === "stub");
|
|
974
1626
|
if (stubs.length > 0) p.log.info(`${stubs.length} agent(s) require manual install — see docs links above.`);
|
|
975
|
-
if (results.some((r) => r.result.kind === "installed" || r.result.kind === "already-wired")) p.log.info("Next: install agentmemory's
|
|
1627
|
+
if (results.some((r) => r.result.kind === "installed" || r.result.kind === "already-wired")) p.log.info("Next: install agentmemory's 17 skills into the same agent(s) so they know when to call the tools:\n npx skills add rohitg00/agentmemory -y");
|
|
976
1628
|
p.outro("Restart any wired agent (or open a new session) to pick up agentmemory.");
|
|
977
1629
|
}
|
|
978
1630
|
//#endregion
|
|
979
|
-
export { resolveAdapter as n,
|
|
1631
|
+
export { runAdapter as a, resolveAdapter as i, connect_exports as n, knownAgents as r, ADAPTERS as t };
|
|
980
1632
|
|
|
981
|
-
//# sourceMappingURL=connect-
|
|
1633
|
+
//# sourceMappingURL=connect-Qaeq15TQ.mjs.map
|