@memrosetta/cli 0.4.0 → 0.4.2
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/dist/chunk-72IW6TAV.js +59 -0
- package/dist/chunk-MISLIVUL.js +70 -0
- package/dist/chunk-NU5ZJJXP.js +63 -0
- package/dist/chunk-SEPYQK3J.js +60 -0
- package/dist/clear-47OFIDME.js +39 -0
- package/dist/clear-5SZVGYBX.js +39 -0
- package/dist/compress-SEFTKZMU.js +33 -0
- package/dist/compress-YNY6YNFU.js +33 -0
- package/dist/count-AMSEVDWR.js +24 -0
- package/dist/count-Z67KBEMV.js +24 -0
- package/dist/feedback-QDOWDWHM.js +40 -0
- package/dist/feedback-XGBKFQXC.js +40 -0
- package/dist/get-NY5H3MUA.js +30 -0
- package/dist/hooks/on-prompt.js +2 -2
- package/dist/hooks/on-stop.js +2 -2
- package/dist/index.js +35 -18
- package/dist/ingest-GSJMWDV5.js +95 -0
- package/dist/ingest-TZEVA25F.js +95 -0
- package/dist/init-GRVRJ6RO.js +205 -0
- package/dist/init-LK4UQISR.js +205 -0
- package/dist/invalidate-BY5VNFSE.js +25 -0
- package/dist/maintain-SGM56XKE.js +37 -0
- package/dist/maintain-VX2VWB2L.js +37 -0
- package/dist/relate-L5464WV5.js +47 -0
- package/dist/relate-SGZLG7JU.js +47 -0
- package/dist/reset-CYY4KYAB.js +129 -0
- package/dist/search-BJ2YV5IS.js +48 -0
- package/dist/search-PT4POELX.js +48 -0
- package/dist/status-TVY32MZD.js +218 -0
- package/dist/store-2USP33HQ.js +91 -0
- package/dist/store-XCFYGYBE.js +91 -0
- package/dist/sync-643GTA5X.js +319 -0
- package/dist/sync-7TONPJBY.js +351 -0
- package/dist/sync-BPVMHW34.js +319 -0
- package/dist/sync-OZQLBYT2.js +317 -0
- package/dist/sync-WURX2HJZ.js +321 -0
- package/dist/working-memory-UYVEJJYW.js +53 -0
- package/dist/working-memory-VP6L2QV6.js +53 -0
- package/package.json +5 -4
package/dist/index.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
parseGlobalArgs
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-NU5ZJJXP.js";
|
|
5
5
|
import {
|
|
6
6
|
closeEngine
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-72IW6TAV.js";
|
|
8
8
|
import {
|
|
9
9
|
outputError
|
|
10
10
|
} from "./chunk-ET6TNQOJ.js";
|
|
11
|
-
import "./chunk-
|
|
11
|
+
import "./chunk-SEPYQK3J.js";
|
|
12
12
|
|
|
13
13
|
// src/index.ts
|
|
14
14
|
var HELP_TEXT = `memrosetta - AI long-term memory engine CLI
|
|
@@ -32,6 +32,7 @@ Commands:
|
|
|
32
32
|
maintain Run maintenance (recompute scores, update tiers, compress)
|
|
33
33
|
compress Run compression only
|
|
34
34
|
update Update to latest version
|
|
35
|
+
sync Manage multi-device sync (enable/disable/status/now/device-id)
|
|
35
36
|
|
|
36
37
|
Init Options:
|
|
37
38
|
(no flag) Initialize DB + MCP server (base setup)
|
|
@@ -54,6 +55,15 @@ Global Options:
|
|
|
54
55
|
--help, -h Show help
|
|
55
56
|
--version, -v Show version
|
|
56
57
|
|
|
58
|
+
Sync Subcommands:
|
|
59
|
+
memrosetta sync enable --server <url> # Enable sync, hidden API key prompt
|
|
60
|
+
memrosetta sync enable --server <url> --key-stdin # Read API key from stdin
|
|
61
|
+
memrosetta sync disable # Disable sync (keeps server/key)
|
|
62
|
+
memrosetta sync status # Show sync state + pending ops
|
|
63
|
+
memrosetta sync now # Push + pull now
|
|
64
|
+
memrosetta sync now --push-only # Push only
|
|
65
|
+
memrosetta sync device-id # Print current device id
|
|
66
|
+
|
|
57
67
|
Examples:
|
|
58
68
|
memrosetta init # DB + MCP server
|
|
59
69
|
memrosetta init --claude-code # DB + MCP + Claude Code hooks
|
|
@@ -65,6 +75,8 @@ Examples:
|
|
|
65
75
|
memrosetta reset --all # Remove all integrations
|
|
66
76
|
memrosetta store --user obst --content "Prefers TypeScript" --type preference
|
|
67
77
|
memrosetta search --user obst --query "language preference" --format text
|
|
78
|
+
memrosetta sync enable --server https://your-sync.example.com
|
|
79
|
+
memrosetta sync status --format text
|
|
68
80
|
`;
|
|
69
81
|
async function main() {
|
|
70
82
|
const rawArgs = process.argv.slice(2);
|
|
@@ -93,77 +105,77 @@ async function main() {
|
|
|
93
105
|
try {
|
|
94
106
|
switch (command) {
|
|
95
107
|
case "store": {
|
|
96
|
-
const mod = await import("./store-
|
|
108
|
+
const mod = await import("./store-2USP33HQ.js");
|
|
97
109
|
await mod.run(commandOptions);
|
|
98
110
|
break;
|
|
99
111
|
}
|
|
100
112
|
case "search": {
|
|
101
|
-
const mod = await import("./search-
|
|
113
|
+
const mod = await import("./search-PT4POELX.js");
|
|
102
114
|
await mod.run(commandOptions);
|
|
103
115
|
break;
|
|
104
116
|
}
|
|
105
117
|
case "ingest": {
|
|
106
|
-
const mod = await import("./ingest-
|
|
118
|
+
const mod = await import("./ingest-GSJMWDV5.js");
|
|
107
119
|
await mod.run(commandOptions);
|
|
108
120
|
break;
|
|
109
121
|
}
|
|
110
122
|
case "get": {
|
|
111
|
-
const mod = await import("./get-
|
|
123
|
+
const mod = await import("./get-NY5H3MUA.js");
|
|
112
124
|
await mod.run(commandOptions);
|
|
113
125
|
break;
|
|
114
126
|
}
|
|
115
127
|
case "count": {
|
|
116
|
-
const mod = await import("./count-
|
|
128
|
+
const mod = await import("./count-AMSEVDWR.js");
|
|
117
129
|
await mod.run(commandOptions);
|
|
118
130
|
break;
|
|
119
131
|
}
|
|
120
132
|
case "clear": {
|
|
121
|
-
const mod = await import("./clear-
|
|
133
|
+
const mod = await import("./clear-5SZVGYBX.js");
|
|
122
134
|
await mod.run(commandOptions);
|
|
123
135
|
break;
|
|
124
136
|
}
|
|
125
137
|
case "relate": {
|
|
126
|
-
const mod = await import("./relate-
|
|
138
|
+
const mod = await import("./relate-SGZLG7JU.js");
|
|
127
139
|
await mod.run(commandOptions);
|
|
128
140
|
break;
|
|
129
141
|
}
|
|
130
142
|
case "invalidate": {
|
|
131
|
-
const mod = await import("./invalidate-
|
|
143
|
+
const mod = await import("./invalidate-BY5VNFSE.js");
|
|
132
144
|
await mod.run(commandOptions);
|
|
133
145
|
break;
|
|
134
146
|
}
|
|
135
147
|
case "feedback": {
|
|
136
|
-
const mod = await import("./feedback-
|
|
148
|
+
const mod = await import("./feedback-XGBKFQXC.js");
|
|
137
149
|
await mod.run(commandOptions);
|
|
138
150
|
break;
|
|
139
151
|
}
|
|
140
152
|
case "working-memory": {
|
|
141
|
-
const mod = await import("./working-memory-
|
|
153
|
+
const mod = await import("./working-memory-UYVEJJYW.js");
|
|
142
154
|
await mod.run(commandOptions);
|
|
143
155
|
break;
|
|
144
156
|
}
|
|
145
157
|
case "maintain": {
|
|
146
|
-
const mod = await import("./maintain-
|
|
158
|
+
const mod = await import("./maintain-SGM56XKE.js");
|
|
147
159
|
await mod.run(commandOptions);
|
|
148
160
|
break;
|
|
149
161
|
}
|
|
150
162
|
case "compress": {
|
|
151
|
-
const mod = await import("./compress-
|
|
163
|
+
const mod = await import("./compress-YNY6YNFU.js");
|
|
152
164
|
await mod.run(commandOptions);
|
|
153
165
|
break;
|
|
154
166
|
}
|
|
155
167
|
case "status": {
|
|
156
|
-
const mod = await import("./status-
|
|
168
|
+
const mod = await import("./status-TVY32MZD.js");
|
|
157
169
|
await mod.run(commandOptions);
|
|
158
170
|
break;
|
|
159
171
|
}
|
|
160
172
|
case "init": {
|
|
161
|
-
const mod = await import("./init-
|
|
173
|
+
const mod = await import("./init-GRVRJ6RO.js");
|
|
162
174
|
await mod.run(commandOptions);
|
|
163
175
|
break;
|
|
164
176
|
}
|
|
165
177
|
case "reset": {
|
|
166
|
-
const mod = await import("./reset-
|
|
178
|
+
const mod = await import("./reset-CYY4KYAB.js");
|
|
167
179
|
await mod.run(commandOptions);
|
|
168
180
|
break;
|
|
169
181
|
}
|
|
@@ -172,6 +184,11 @@ async function main() {
|
|
|
172
184
|
await mod.run();
|
|
173
185
|
break;
|
|
174
186
|
}
|
|
187
|
+
case "sync": {
|
|
188
|
+
const mod = await import("./sync-7TONPJBY.js");
|
|
189
|
+
await mod.run(commandOptions);
|
|
190
|
+
break;
|
|
191
|
+
}
|
|
175
192
|
default:
|
|
176
193
|
outputError(`Unknown command: ${command}`, opts.format);
|
|
177
194
|
process.exitCode = 1;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import {
|
|
2
|
+
classifyTurn,
|
|
3
|
+
parseTranscriptContent
|
|
4
|
+
} from "./chunk-KR63XYFW.js";
|
|
5
|
+
import {
|
|
6
|
+
optionalOption
|
|
7
|
+
} from "./chunk-NU5ZJJXP.js";
|
|
8
|
+
import {
|
|
9
|
+
getEngine
|
|
10
|
+
} from "./chunk-72IW6TAV.js";
|
|
11
|
+
import {
|
|
12
|
+
output,
|
|
13
|
+
outputError
|
|
14
|
+
} from "./chunk-ET6TNQOJ.js";
|
|
15
|
+
import {
|
|
16
|
+
getDefaultUserId
|
|
17
|
+
} from "./chunk-SEPYQK3J.js";
|
|
18
|
+
|
|
19
|
+
// src/commands/ingest.ts
|
|
20
|
+
import { readFileSync } from "fs";
|
|
21
|
+
function turnsToMemories(turns, userId, namespace, sessionShort) {
|
|
22
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
23
|
+
const memories = [];
|
|
24
|
+
for (let i = 0; i < turns.length; i++) {
|
|
25
|
+
const turn = turns[i];
|
|
26
|
+
if (turn.content.length < 20) continue;
|
|
27
|
+
const content = turn.content.length > 500 ? turn.content.slice(0, 497) + "..." : turn.content;
|
|
28
|
+
memories.push({
|
|
29
|
+
userId,
|
|
30
|
+
namespace: namespace ?? `session-${sessionShort}`,
|
|
31
|
+
memoryType: classifyTurn(turn),
|
|
32
|
+
content,
|
|
33
|
+
documentDate: now,
|
|
34
|
+
sourceId: `cc-${sessionShort}-${i}`,
|
|
35
|
+
confidence: turn.role === "user" ? 0.9 : 0.8
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
return memories;
|
|
39
|
+
}
|
|
40
|
+
async function readStdin() {
|
|
41
|
+
const chunks = [];
|
|
42
|
+
for await (const chunk of process.stdin) {
|
|
43
|
+
chunks.push(chunk);
|
|
44
|
+
}
|
|
45
|
+
return Buffer.concat(chunks).toString("utf-8").trim();
|
|
46
|
+
}
|
|
47
|
+
async function run(options) {
|
|
48
|
+
const { args, format, db, noEmbeddings } = options;
|
|
49
|
+
const userId = optionalOption(args, "--user") ?? getDefaultUserId();
|
|
50
|
+
const file = optionalOption(args, "--file");
|
|
51
|
+
const namespace = optionalOption(args, "--namespace");
|
|
52
|
+
let content;
|
|
53
|
+
if (file) {
|
|
54
|
+
try {
|
|
55
|
+
content = readFileSync(file, "utf-8");
|
|
56
|
+
} catch (err) {
|
|
57
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
58
|
+
outputError(`Failed to read file: ${msg}`, format);
|
|
59
|
+
process.exitCode = 1;
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
} else {
|
|
63
|
+
content = await readStdin();
|
|
64
|
+
}
|
|
65
|
+
if (!content) {
|
|
66
|
+
outputError("No transcript content provided", format);
|
|
67
|
+
process.exitCode = 1;
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const parsed = parseTranscriptContent(content);
|
|
71
|
+
const sessionShort = parsed.sessionId ? parsed.sessionId.slice(0, 8) : "unknown";
|
|
72
|
+
const memories = turnsToMemories(
|
|
73
|
+
parsed.turns,
|
|
74
|
+
userId,
|
|
75
|
+
namespace,
|
|
76
|
+
sessionShort
|
|
77
|
+
);
|
|
78
|
+
if (memories.length === 0) {
|
|
79
|
+
output({ stored: 0, message: "No memories extracted from transcript" }, format);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const engine = await getEngine({ db, noEmbeddings });
|
|
83
|
+
const stored = await engine.storeBatch(memories);
|
|
84
|
+
output(
|
|
85
|
+
{
|
|
86
|
+
stored: stored.length,
|
|
87
|
+
sessionId: parsed.sessionId || void 0,
|
|
88
|
+
namespace: namespace ?? `session-${sessionShort}`
|
|
89
|
+
},
|
|
90
|
+
format
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
export {
|
|
94
|
+
run
|
|
95
|
+
};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import {
|
|
2
|
+
classifyTurn,
|
|
3
|
+
parseTranscriptContent
|
|
4
|
+
} from "./chunk-KR63XYFW.js";
|
|
5
|
+
import {
|
|
6
|
+
optionalOption
|
|
7
|
+
} from "./chunk-VZQURGWB.js";
|
|
8
|
+
import {
|
|
9
|
+
getEngine
|
|
10
|
+
} from "./chunk-72IW6TAV.js";
|
|
11
|
+
import {
|
|
12
|
+
output,
|
|
13
|
+
outputError
|
|
14
|
+
} from "./chunk-ET6TNQOJ.js";
|
|
15
|
+
import {
|
|
16
|
+
getDefaultUserId
|
|
17
|
+
} from "./chunk-SEPYQK3J.js";
|
|
18
|
+
|
|
19
|
+
// src/commands/ingest.ts
|
|
20
|
+
import { readFileSync } from "fs";
|
|
21
|
+
function turnsToMemories(turns, userId, namespace, sessionShort) {
|
|
22
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
23
|
+
const memories = [];
|
|
24
|
+
for (let i = 0; i < turns.length; i++) {
|
|
25
|
+
const turn = turns[i];
|
|
26
|
+
if (turn.content.length < 20) continue;
|
|
27
|
+
const content = turn.content.length > 500 ? turn.content.slice(0, 497) + "..." : turn.content;
|
|
28
|
+
memories.push({
|
|
29
|
+
userId,
|
|
30
|
+
namespace: namespace ?? `session-${sessionShort}`,
|
|
31
|
+
memoryType: classifyTurn(turn),
|
|
32
|
+
content,
|
|
33
|
+
documentDate: now,
|
|
34
|
+
sourceId: `cc-${sessionShort}-${i}`,
|
|
35
|
+
confidence: turn.role === "user" ? 0.9 : 0.8
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
return memories;
|
|
39
|
+
}
|
|
40
|
+
async function readStdin() {
|
|
41
|
+
const chunks = [];
|
|
42
|
+
for await (const chunk of process.stdin) {
|
|
43
|
+
chunks.push(chunk);
|
|
44
|
+
}
|
|
45
|
+
return Buffer.concat(chunks).toString("utf-8").trim();
|
|
46
|
+
}
|
|
47
|
+
async function run(options) {
|
|
48
|
+
const { args, format, db, noEmbeddings } = options;
|
|
49
|
+
const userId = optionalOption(args, "--user") ?? getDefaultUserId();
|
|
50
|
+
const file = optionalOption(args, "--file");
|
|
51
|
+
const namespace = optionalOption(args, "--namespace");
|
|
52
|
+
let content;
|
|
53
|
+
if (file) {
|
|
54
|
+
try {
|
|
55
|
+
content = readFileSync(file, "utf-8");
|
|
56
|
+
} catch (err) {
|
|
57
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
58
|
+
outputError(`Failed to read file: ${msg}`, format);
|
|
59
|
+
process.exitCode = 1;
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
} else {
|
|
63
|
+
content = await readStdin();
|
|
64
|
+
}
|
|
65
|
+
if (!content) {
|
|
66
|
+
outputError("No transcript content provided", format);
|
|
67
|
+
process.exitCode = 1;
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const parsed = parseTranscriptContent(content);
|
|
71
|
+
const sessionShort = parsed.sessionId ? parsed.sessionId.slice(0, 8) : "unknown";
|
|
72
|
+
const memories = turnsToMemories(
|
|
73
|
+
parsed.turns,
|
|
74
|
+
userId,
|
|
75
|
+
namespace,
|
|
76
|
+
sessionShort
|
|
77
|
+
);
|
|
78
|
+
if (memories.length === 0) {
|
|
79
|
+
output({ stored: 0, message: "No memories extracted from transcript" }, format);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const engine = await getEngine({ db, noEmbeddings });
|
|
83
|
+
const stored = await engine.storeBatch(memories);
|
|
84
|
+
output(
|
|
85
|
+
{
|
|
86
|
+
stored: stored.length,
|
|
87
|
+
sessionId: parsed.sessionId || void 0,
|
|
88
|
+
namespace: namespace ?? `session-${sessionShort}`
|
|
89
|
+
},
|
|
90
|
+
format
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
export {
|
|
94
|
+
run
|
|
95
|
+
};
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getAgentsMdPath,
|
|
3
|
+
getCodexConfigFilePath,
|
|
4
|
+
getCursorMcpConfigPath,
|
|
5
|
+
getCursorRulesPath,
|
|
6
|
+
getGeminiMdPath,
|
|
7
|
+
getGeminiSettingsFilePath,
|
|
8
|
+
getGenericMCPPath,
|
|
9
|
+
isClaudeCodeInstalled,
|
|
10
|
+
registerClaudeCodeHooks,
|
|
11
|
+
registerCodexMCP,
|
|
12
|
+
registerCursorMCP,
|
|
13
|
+
registerGeminiMCP,
|
|
14
|
+
registerGenericMCP,
|
|
15
|
+
updateClaudeMd
|
|
16
|
+
} from "./chunk-IS4IKWPL.js";
|
|
17
|
+
import {
|
|
18
|
+
hasFlag,
|
|
19
|
+
optionalOption
|
|
20
|
+
} from "./chunk-NU5ZJJXP.js";
|
|
21
|
+
import {
|
|
22
|
+
getDefaultDbPath,
|
|
23
|
+
getEngine
|
|
24
|
+
} from "./chunk-72IW6TAV.js";
|
|
25
|
+
import {
|
|
26
|
+
output
|
|
27
|
+
} from "./chunk-ET6TNQOJ.js";
|
|
28
|
+
import {
|
|
29
|
+
getConfig,
|
|
30
|
+
writeConfig
|
|
31
|
+
} from "./chunk-SEPYQK3J.js";
|
|
32
|
+
|
|
33
|
+
// src/commands/init.ts
|
|
34
|
+
import { existsSync } from "fs";
|
|
35
|
+
var LANG_FLAG_TO_PRESET = {
|
|
36
|
+
en: "en",
|
|
37
|
+
multi: "multilingual",
|
|
38
|
+
ko: "ko"
|
|
39
|
+
};
|
|
40
|
+
async function run(options) {
|
|
41
|
+
const { args, format, db, noEmbeddings } = options;
|
|
42
|
+
const wantClaudeCode = hasFlag(args, "--claude-code");
|
|
43
|
+
const wantCursor = hasFlag(args, "--cursor");
|
|
44
|
+
const wantCodex = hasFlag(args, "--codex");
|
|
45
|
+
const wantGemini = hasFlag(args, "--gemini");
|
|
46
|
+
const langFlag = optionalOption(args, "--lang");
|
|
47
|
+
const embeddingPreset = langFlag ? LANG_FLAG_TO_PRESET[langFlag] : void 0;
|
|
48
|
+
if (langFlag && !LANG_FLAG_TO_PRESET[langFlag]) {
|
|
49
|
+
process.stderr.write(
|
|
50
|
+
`Unknown --lang value: "${langFlag}". Supported: en, multi, ko
|
|
51
|
+
`
|
|
52
|
+
);
|
|
53
|
+
process.exitCode = 1;
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
{
|
|
57
|
+
const config2 = getConfig();
|
|
58
|
+
const updates = {};
|
|
59
|
+
if (db) {
|
|
60
|
+
updates.dbPath = db;
|
|
61
|
+
}
|
|
62
|
+
if (noEmbeddings) {
|
|
63
|
+
updates.enableEmbeddings = false;
|
|
64
|
+
}
|
|
65
|
+
if (embeddingPreset) {
|
|
66
|
+
updates.embeddingPreset = embeddingPreset;
|
|
67
|
+
}
|
|
68
|
+
if (Object.keys(updates).length > 0) {
|
|
69
|
+
writeConfig({ ...config2, ...updates });
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const config = getConfig();
|
|
73
|
+
const dbPath = db ?? config.dbPath ?? getDefaultDbPath();
|
|
74
|
+
const existed = existsSync(dbPath);
|
|
75
|
+
const engine = await getEngine({ db: dbPath, noEmbeddings });
|
|
76
|
+
await engine.close();
|
|
77
|
+
const result = {
|
|
78
|
+
database: {
|
|
79
|
+
path: dbPath,
|
|
80
|
+
created: !existed
|
|
81
|
+
},
|
|
82
|
+
integrations: {}
|
|
83
|
+
};
|
|
84
|
+
registerGenericMCP();
|
|
85
|
+
result.integrations.mcp = {
|
|
86
|
+
registered: true,
|
|
87
|
+
path: getGenericMCPPath()
|
|
88
|
+
};
|
|
89
|
+
if (wantClaudeCode) {
|
|
90
|
+
const hooksOk = registerClaudeCodeHooks();
|
|
91
|
+
const claudeMdOk = updateClaudeMd();
|
|
92
|
+
result.integrations.claudeCode = {
|
|
93
|
+
hooks: hooksOk,
|
|
94
|
+
mcp: true,
|
|
95
|
+
claudeMd: claudeMdOk
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
if (wantCursor) {
|
|
99
|
+
const cursorRulesUpdated = registerCursorMCP();
|
|
100
|
+
result.integrations.cursor = {
|
|
101
|
+
mcp: true,
|
|
102
|
+
path: getCursorMcpConfigPath(),
|
|
103
|
+
cursorRules: cursorRulesUpdated,
|
|
104
|
+
cursorRulesPath: getCursorRulesPath()
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
if (wantCodex) {
|
|
108
|
+
const agentsMdUpdated = registerCodexMCP();
|
|
109
|
+
result.integrations.codex = {
|
|
110
|
+
mcp: true,
|
|
111
|
+
path: getCodexConfigFilePath(),
|
|
112
|
+
agentsMd: agentsMdUpdated,
|
|
113
|
+
agentsMdPath: getAgentsMdPath()
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
if (wantGemini) {
|
|
117
|
+
const geminiMdUpdated = registerGeminiMCP();
|
|
118
|
+
result.integrations.gemini = {
|
|
119
|
+
mcp: true,
|
|
120
|
+
path: getGeminiSettingsFilePath(),
|
|
121
|
+
geminiMd: geminiMdUpdated,
|
|
122
|
+
geminiMdPath: getGeminiMdPath()
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
if (format === "text") {
|
|
126
|
+
printTextOutput(result, wantClaudeCode, wantCursor, wantCodex, wantGemini);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
output(result, format);
|
|
130
|
+
}
|
|
131
|
+
function printTextOutput(result, claudeCode, cursor, codex = false, gemini = false) {
|
|
132
|
+
const w = (s) => process.stdout.write(s);
|
|
133
|
+
w("\nMemRosetta initialized successfully.\n\n");
|
|
134
|
+
w(" What was set up:\n");
|
|
135
|
+
w(" ----------------------------------------\n");
|
|
136
|
+
w(` Database: ${result.database.path}`);
|
|
137
|
+
w(result.database.created ? " (created)\n" : " (already exists)\n");
|
|
138
|
+
w(` MCP Server: ${result.integrations.mcp.path} (always included)
|
|
139
|
+
`);
|
|
140
|
+
const currentConfig = getConfig();
|
|
141
|
+
if (currentConfig.embeddingPreset && currentConfig.embeddingPreset !== "en") {
|
|
142
|
+
const presetLabels = {
|
|
143
|
+
multilingual: "multilingual (multilingual-e5-small)",
|
|
144
|
+
ko: "Korean (ko-sroberta-multitask)"
|
|
145
|
+
};
|
|
146
|
+
w(` Embeddings: ${presetLabels[currentConfig.embeddingPreset] ?? currentConfig.embeddingPreset}
|
|
147
|
+
`);
|
|
148
|
+
}
|
|
149
|
+
if (claudeCode) {
|
|
150
|
+
const cc = result.integrations.claudeCode;
|
|
151
|
+
if (cc.hooks) {
|
|
152
|
+
w(" Stop Hook: ~/.claude/settings.json (auto-save on session end)\n");
|
|
153
|
+
} else if (!isClaudeCodeInstalled()) {
|
|
154
|
+
w(" Stop Hook: SKIPPED (Claude Code not found at ~/.claude)\n");
|
|
155
|
+
w(' Install Claude Code first, then run "memrosetta init --claude-code" again.\n');
|
|
156
|
+
}
|
|
157
|
+
if (cc.claudeMd) {
|
|
158
|
+
w(" CLAUDE.md: ~/.claude/CLAUDE.md (memory instructions added)\n");
|
|
159
|
+
} else {
|
|
160
|
+
w(" CLAUDE.md: already configured\n");
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
if (cursor) {
|
|
164
|
+
w(` Cursor MCP: ${result.integrations.cursor.path}
|
|
165
|
+
`);
|
|
166
|
+
if (result.integrations.cursor.cursorRules) {
|
|
167
|
+
w(` .cursorrules: ${result.integrations.cursor.cursorRulesPath} (memory instructions added)
|
|
168
|
+
`);
|
|
169
|
+
} else {
|
|
170
|
+
w(" .cursorrules: already configured\n");
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
if (codex) {
|
|
174
|
+
w(` Codex MCP: ${result.integrations.codex.path}
|
|
175
|
+
`);
|
|
176
|
+
if (result.integrations.codex.agentsMd) {
|
|
177
|
+
w(` AGENTS.md: ${result.integrations.codex.agentsMdPath} (memory instructions added)
|
|
178
|
+
`);
|
|
179
|
+
} else {
|
|
180
|
+
w(" AGENTS.md: already configured\n");
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
if (gemini) {
|
|
184
|
+
w(` Gemini MCP: ${result.integrations.gemini.path}
|
|
185
|
+
`);
|
|
186
|
+
if (result.integrations.gemini.geminiMd) {
|
|
187
|
+
w(` GEMINI.md: ${result.integrations.gemini.geminiMdPath} (memory instructions added)
|
|
188
|
+
`);
|
|
189
|
+
} else {
|
|
190
|
+
w(" GEMINI.md: already configured\n");
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
w("\n");
|
|
194
|
+
if (!claudeCode && !cursor && !codex && !gemini) {
|
|
195
|
+
w(" MCP is ready. Add --claude-code, --cursor, --codex, or --gemini for tool-specific setup.\n");
|
|
196
|
+
w(" Example: memrosetta init --claude-code\n");
|
|
197
|
+
w("\n");
|
|
198
|
+
}
|
|
199
|
+
if (claudeCode) {
|
|
200
|
+
w(" Restart Claude Code to activate.\n\n");
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
export {
|
|
204
|
+
run
|
|
205
|
+
};
|