@momomemory/opencode-momo 0.1.2 → 0.1.3
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 +18 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +229 -85
- package/dist/config.d.ts +2 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/index.js +82 -64
- package/dist/services/jsonc.d.ts +5 -4
- package/dist/services/jsonc.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -156,10 +156,27 @@ Configuration is stored in `~/.config/opencode/momo.jsonc`:
|
|
|
156
156
|
// Momo server URL
|
|
157
157
|
"baseUrl": "http://localhost:3000",
|
|
158
158
|
// API key for authentication
|
|
159
|
-
"apiKey": "your-key-here"
|
|
159
|
+
"apiKey": "your-key-here",
|
|
160
|
+
// Optional override for user memory container tag
|
|
161
|
+
"containerTagUser": "",
|
|
162
|
+
// Optional override for project memory container tag
|
|
163
|
+
"containerTagProject": ""
|
|
160
164
|
}
|
|
161
165
|
```
|
|
162
166
|
|
|
167
|
+
### Project-local config (optional)
|
|
168
|
+
|
|
169
|
+
You can also place config in your project root as `.momo.jsonc` (preferred) or `momo.jsonc`.
|
|
170
|
+
This is useful when you want a stable `containerTagProject` for a specific repo.
|
|
171
|
+
|
|
172
|
+
### Config precedence
|
|
173
|
+
|
|
174
|
+
Highest to lowest precedence:
|
|
175
|
+
1. Environment variables (`MOMO_*`)
|
|
176
|
+
2. Project-local config (`.momo.jsonc` / `momo.jsonc`)
|
|
177
|
+
3. Global config (`~/.config/opencode/momo.jsonc`)
|
|
178
|
+
4. Built-in defaults
|
|
179
|
+
|
|
163
180
|
### Environment Variables
|
|
164
181
|
|
|
165
182
|
The following variables can be used to override configuration:
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AA2IA;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CA+CjE;AA0ID;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG;IACpD,WAAW,EAAE,OAAO,CAAC;IACrB,gBAAgB,EAAE,OAAO,CAAC;CAC3B,CAWA;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7C,IAAI,CA6CN"}
|
package/dist/cli.js
CHANGED
|
@@ -17,74 +17,73 @@ import { join } from "node:path";
|
|
|
17
17
|
import { homedir } from "node:os";
|
|
18
18
|
|
|
19
19
|
// src/services/jsonc.ts
|
|
20
|
-
function stripJsoncComments(
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
20
|
+
function stripJsoncComments(input) {
|
|
21
|
+
var Mode;
|
|
22
|
+
((Mode2) => {
|
|
23
|
+
Mode2[Mode2["Code"] = 0] = "Code";
|
|
24
|
+
Mode2[Mode2["String"] = 1] = "String";
|
|
25
|
+
Mode2[Mode2["LineComment"] = 2] = "LineComment";
|
|
26
|
+
Mode2[Mode2["BlockComment"] = 3] = "BlockComment";
|
|
27
|
+
})(Mode ||= {});
|
|
28
|
+
const out = [];
|
|
29
|
+
let mode = 0 /* Code */;
|
|
30
|
+
for (let i = 0;i < input.length; i++) {
|
|
31
|
+
const ch = input[i];
|
|
32
|
+
const next = input[i + 1];
|
|
33
|
+
if (mode === 1 /* String */) {
|
|
34
|
+
out.push(ch);
|
|
35
|
+
if (ch === "\\") {
|
|
36
|
+
if (next !== undefined) {
|
|
37
|
+
out.push(next);
|
|
38
|
+
i++;
|
|
39
39
|
}
|
|
40
|
-
result += char;
|
|
41
|
-
i++;
|
|
42
40
|
continue;
|
|
43
41
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
result += char;
|
|
47
|
-
i++;
|
|
48
|
-
continue;
|
|
49
|
-
}
|
|
50
|
-
if (!inSingleLineComment && !inMultiLineComment) {
|
|
51
|
-
if (char === "/" && nextChar === "/") {
|
|
52
|
-
inSingleLineComment = true;
|
|
53
|
-
i += 2;
|
|
54
|
-
continue;
|
|
55
|
-
}
|
|
56
|
-
if (char === "/" && nextChar === "*") {
|
|
57
|
-
inMultiLineComment = true;
|
|
58
|
-
i += 2;
|
|
59
|
-
continue;
|
|
42
|
+
if (ch === '"') {
|
|
43
|
+
mode = 0 /* Code */;
|
|
60
44
|
}
|
|
45
|
+
continue;
|
|
61
46
|
}
|
|
62
|
-
if (
|
|
63
|
-
if (
|
|
47
|
+
if (mode === 2 /* LineComment */) {
|
|
48
|
+
if (ch === `
|
|
64
49
|
`) {
|
|
65
|
-
|
|
66
|
-
|
|
50
|
+
mode = 0 /* Code */;
|
|
51
|
+
out.push(`
|
|
52
|
+
`);
|
|
67
53
|
}
|
|
68
|
-
i++;
|
|
69
54
|
continue;
|
|
70
55
|
}
|
|
71
|
-
if (
|
|
72
|
-
if (
|
|
73
|
-
|
|
74
|
-
i
|
|
56
|
+
if (mode === 3 /* BlockComment */) {
|
|
57
|
+
if (ch === "*" && next === "/") {
|
|
58
|
+
mode = 0 /* Code */;
|
|
59
|
+
i++;
|
|
75
60
|
continue;
|
|
76
61
|
}
|
|
77
|
-
if (
|
|
62
|
+
if (ch === `
|
|
78
63
|
`) {
|
|
79
|
-
|
|
64
|
+
out.push(`
|
|
65
|
+
`);
|
|
80
66
|
}
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
if (ch === '"') {
|
|
70
|
+
mode = 1 /* String */;
|
|
71
|
+
out.push(ch);
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
if (ch === "/" && next === "/") {
|
|
75
|
+
mode = 2 /* LineComment */;
|
|
76
|
+
i++;
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
if (ch === "/" && next === "*") {
|
|
80
|
+
mode = 3 /* BlockComment */;
|
|
81
81
|
i++;
|
|
82
82
|
continue;
|
|
83
83
|
}
|
|
84
|
-
|
|
85
|
-
i++;
|
|
84
|
+
out.push(ch);
|
|
86
85
|
}
|
|
87
|
-
return
|
|
86
|
+
return out.join("").replace(/,\s*([}\]])/g, "$1");
|
|
88
87
|
}
|
|
89
88
|
|
|
90
89
|
// src/config.ts
|
|
@@ -159,6 +158,8 @@ bunx @momomemory/opencode-momo configure
|
|
|
159
158
|
Or set environment variables:
|
|
160
159
|
- \`MOMO_BASE_URL\` - Momo server URL (default: http://localhost:3000)
|
|
161
160
|
- \`MOMO_API_KEY\` - API key for authentication
|
|
161
|
+
- \`MOMO_CONTAINER_TAG_USER\` - Optional user container tag override
|
|
162
|
+
- \`MOMO_CONTAINER_TAG_PROJECT\` - Optional project container tag override
|
|
162
163
|
|
|
163
164
|
After configuration, restart OpenCode to activate.
|
|
164
165
|
`;
|
|
@@ -206,53 +207,186 @@ async function promptInput(question, defaultValue) {
|
|
|
206
207
|
}
|
|
207
208
|
function registerPluginInConfig(configDir) {
|
|
208
209
|
const configPath = join2(configDir, "opencode.jsonc");
|
|
209
|
-
if (existsSync(configPath)) {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
}
|
|
214
|
-
if (content.includes('"plugin"')) {
|
|
215
|
-
const newContent = content.replace(/("plugin"\s*:\s*\[)([^\]]*?)(\])/, (_match, start, middle, end) => {
|
|
216
|
-
const trimmed = middle.trim();
|
|
217
|
-
if (trimmed === "") {
|
|
218
|
-
return `${start}
|
|
210
|
+
if (!existsSync(configPath)) {
|
|
211
|
+
mkdirSync(configDir, { recursive: true });
|
|
212
|
+
const newConfig = `{
|
|
213
|
+
"plugin": [
|
|
219
214
|
"${PLUGIN_NAME}"
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
215
|
+
]
|
|
216
|
+
}
|
|
217
|
+
`;
|
|
218
|
+
writeFileSync(configPath, newConfig, "utf-8");
|
|
219
|
+
return true;
|
|
220
|
+
}
|
|
221
|
+
const content = readFileSync(configPath, "utf-8");
|
|
222
|
+
if (content.includes(PLUGIN_NAME)) {
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
const pluginArrayStart = findPluginArrayStart(content);
|
|
226
|
+
if (pluginArrayStart !== -1) {
|
|
227
|
+
const pluginArrayEnd = findMatchingBracket(content, pluginArrayStart);
|
|
228
|
+
if (pluginArrayEnd !== -1) {
|
|
229
|
+
const before = content.slice(0, pluginArrayStart + 1);
|
|
230
|
+
const middle = content.slice(pluginArrayStart + 1, pluginArrayEnd);
|
|
231
|
+
const after = content.slice(pluginArrayEnd);
|
|
232
|
+
const middleTrimmed = middle.trim();
|
|
233
|
+
const appended = middleTrimmed.length === 0 ? `
|
|
234
|
+
"${PLUGIN_NAME}"
|
|
235
|
+
` : `${middle.replace(/\s*$/, "")},
|
|
223
236
|
"${PLUGIN_NAME}"
|
|
224
|
-
|
|
225
|
-
});
|
|
226
|
-
writeFileSync(configPath, newContent, "utf-8");
|
|
237
|
+
`;
|
|
238
|
+
writeFileSync(configPath, `${before}${appended}${after}`, "utf-8");
|
|
227
239
|
return true;
|
|
228
240
|
}
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
]
|
|
234
|
-
}`);
|
|
235
|
-
writeFileSync(configPath, insertContent, "utf-8");
|
|
236
|
-
} else {
|
|
237
|
-
const withComma = content.replace(/(\S)\s*\}\s*$/, `$1,
|
|
241
|
+
}
|
|
242
|
+
const rootClose = findRootObjectClose(content);
|
|
243
|
+
if (rootClose === -1) {
|
|
244
|
+
const rebuilt = `{
|
|
238
245
|
"plugin": [
|
|
239
246
|
"${PLUGIN_NAME}"
|
|
240
247
|
]
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
|
|
248
|
+
}
|
|
249
|
+
`;
|
|
250
|
+
writeFileSync(configPath, rebuilt, "utf-8");
|
|
244
251
|
return true;
|
|
245
252
|
}
|
|
246
|
-
|
|
247
|
-
const
|
|
253
|
+
const head = content.slice(0, rootClose).replace(/\s*$/, "");
|
|
254
|
+
const needsComma = !head.endsWith("{") && !head.endsWith(",");
|
|
255
|
+
const insertion = `${needsComma ? "," : ""}
|
|
248
256
|
"plugin": [
|
|
249
257
|
"${PLUGIN_NAME}"
|
|
250
258
|
]
|
|
251
|
-
}
|
|
252
259
|
`;
|
|
253
|
-
|
|
260
|
+
const tail = content.slice(rootClose);
|
|
261
|
+
writeFileSync(configPath, `${head}${insertion}${tail}`, "utf-8");
|
|
254
262
|
return true;
|
|
255
263
|
}
|
|
264
|
+
function findPluginArrayStart(content) {
|
|
265
|
+
const keyMatch = /"plugin"\s*:/.exec(content);
|
|
266
|
+
if (!keyMatch)
|
|
267
|
+
return -1;
|
|
268
|
+
const start = keyMatch.index + keyMatch[0].length;
|
|
269
|
+
for (let i = start;i < content.length; i++) {
|
|
270
|
+
const ch = content[i];
|
|
271
|
+
if (!ch || /\s/.test(ch))
|
|
272
|
+
continue;
|
|
273
|
+
return ch === "[" ? i : -1;
|
|
274
|
+
}
|
|
275
|
+
return -1;
|
|
276
|
+
}
|
|
277
|
+
function findMatchingBracket(content, openIndex) {
|
|
278
|
+
let depth = 0;
|
|
279
|
+
let inString = false;
|
|
280
|
+
let inLineComment = false;
|
|
281
|
+
let inBlockComment = false;
|
|
282
|
+
for (let i = openIndex;i < content.length; i++) {
|
|
283
|
+
const ch = content[i];
|
|
284
|
+
const next = content[i + 1];
|
|
285
|
+
if (inLineComment) {
|
|
286
|
+
if (ch === `
|
|
287
|
+
`)
|
|
288
|
+
inLineComment = false;
|
|
289
|
+
continue;
|
|
290
|
+
}
|
|
291
|
+
if (inBlockComment) {
|
|
292
|
+
if (ch === "*" && next === "/") {
|
|
293
|
+
inBlockComment = false;
|
|
294
|
+
i++;
|
|
295
|
+
}
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
if (inString) {
|
|
299
|
+
if (ch === "\\") {
|
|
300
|
+
i++;
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
303
|
+
if (ch === '"')
|
|
304
|
+
inString = false;
|
|
305
|
+
continue;
|
|
306
|
+
}
|
|
307
|
+
if (ch === '"') {
|
|
308
|
+
inString = true;
|
|
309
|
+
continue;
|
|
310
|
+
}
|
|
311
|
+
if (ch === "/" && next === "/") {
|
|
312
|
+
inLineComment = true;
|
|
313
|
+
i++;
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
if (ch === "/" && next === "*") {
|
|
317
|
+
inBlockComment = true;
|
|
318
|
+
i++;
|
|
319
|
+
continue;
|
|
320
|
+
}
|
|
321
|
+
if (ch === "[") {
|
|
322
|
+
depth++;
|
|
323
|
+
continue;
|
|
324
|
+
}
|
|
325
|
+
if (ch === "]") {
|
|
326
|
+
depth--;
|
|
327
|
+
if (depth === 0)
|
|
328
|
+
return i;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
return -1;
|
|
332
|
+
}
|
|
333
|
+
function findRootObjectClose(content) {
|
|
334
|
+
let depth = 0;
|
|
335
|
+
let inString = false;
|
|
336
|
+
let inLineComment = false;
|
|
337
|
+
let inBlockComment = false;
|
|
338
|
+
let rootClose = -1;
|
|
339
|
+
for (let i = 0;i < content.length; i++) {
|
|
340
|
+
const ch = content[i];
|
|
341
|
+
const next = content[i + 1];
|
|
342
|
+
if (inLineComment) {
|
|
343
|
+
if (ch === `
|
|
344
|
+
`)
|
|
345
|
+
inLineComment = false;
|
|
346
|
+
continue;
|
|
347
|
+
}
|
|
348
|
+
if (inBlockComment) {
|
|
349
|
+
if (ch === "*" && next === "/") {
|
|
350
|
+
inBlockComment = false;
|
|
351
|
+
i++;
|
|
352
|
+
}
|
|
353
|
+
continue;
|
|
354
|
+
}
|
|
355
|
+
if (inString) {
|
|
356
|
+
if (ch === "\\") {
|
|
357
|
+
i++;
|
|
358
|
+
continue;
|
|
359
|
+
}
|
|
360
|
+
if (ch === '"')
|
|
361
|
+
inString = false;
|
|
362
|
+
continue;
|
|
363
|
+
}
|
|
364
|
+
if (ch === '"') {
|
|
365
|
+
inString = true;
|
|
366
|
+
continue;
|
|
367
|
+
}
|
|
368
|
+
if (ch === "/" && next === "/") {
|
|
369
|
+
inLineComment = true;
|
|
370
|
+
i++;
|
|
371
|
+
continue;
|
|
372
|
+
}
|
|
373
|
+
if (ch === "/" && next === "*") {
|
|
374
|
+
inBlockComment = true;
|
|
375
|
+
i++;
|
|
376
|
+
continue;
|
|
377
|
+
}
|
|
378
|
+
if (ch === "{") {
|
|
379
|
+
depth++;
|
|
380
|
+
continue;
|
|
381
|
+
}
|
|
382
|
+
if (ch === "}") {
|
|
383
|
+
depth--;
|
|
384
|
+
if (depth === 0)
|
|
385
|
+
rootClose = i;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
return rootClose;
|
|
389
|
+
}
|
|
256
390
|
function writeCommandFiles(configDir) {
|
|
257
391
|
const commandDir = join2(configDir, "command");
|
|
258
392
|
mkdirSync(commandDir, { recursive: true });
|
|
@@ -286,7 +420,7 @@ function writeMomoConfig(configDir, options) {
|
|
|
286
420
|
containerTagProject: priorContainerTagProject ?? ""
|
|
287
421
|
};
|
|
288
422
|
const lines = ["{"];
|
|
289
|
-
lines.push(" // Momo server URL");
|
|
423
|
+
lines.push(" // Momo server URL (default: http://localhost:3000)");
|
|
290
424
|
lines.push(` "baseUrl": ${JSON.stringify(config.baseUrl)},`);
|
|
291
425
|
lines.push(" // API key for authentication (leave empty if your server has auth disabled)");
|
|
292
426
|
lines.push(` "apiKey": ${JSON.stringify(config.apiKey)},`);
|
|
@@ -294,6 +428,8 @@ function writeMomoConfig(configDir, options) {
|
|
|
294
428
|
lines.push(` "containerTagUser": ${JSON.stringify(config.containerTagUser)},`);
|
|
295
429
|
lines.push(" // Optional override for project memory container tag (default: auto-derived from project directory)");
|
|
296
430
|
lines.push(` "containerTagProject": ${JSON.stringify(config.containerTagProject)}`);
|
|
431
|
+
lines.push(" // Note: project-local config files (.momo.jsonc / momo.jsonc) override this global file,");
|
|
432
|
+
lines.push(" // and MOMO_* environment variables override both.");
|
|
297
433
|
lines.push("}");
|
|
298
434
|
lines.push("");
|
|
299
435
|
writeFileSync(configPath, lines.join(`
|
|
@@ -331,6 +467,14 @@ async function runInstall(flags) {
|
|
|
331
467
|
writeCommandFiles(configDir);
|
|
332
468
|
console.log(` ✓ Created ${join2(configDir, "command", "momo-init.md")}`);
|
|
333
469
|
console.log(` ✓ Created ${join2(configDir, "command", "momo-configure.md")}`);
|
|
470
|
+
const momoConfigPath = join2(configDir, "momo.jsonc");
|
|
471
|
+
const hadMomoConfig = existsSync(momoConfigPath);
|
|
472
|
+
writeMomoConfig(configDir, {});
|
|
473
|
+
if (hadMomoConfig) {
|
|
474
|
+
console.log(` ✓ Updated ${momoConfigPath}`);
|
|
475
|
+
} else {
|
|
476
|
+
console.log(` ✓ Created ${momoConfigPath}`);
|
|
477
|
+
}
|
|
334
478
|
console.log(`
|
|
335
479
|
✅ Installation complete!
|
|
336
480
|
|
|
@@ -375,7 +519,7 @@ async function runConfigure(flags) {
|
|
|
375
519
|
Restart OpenCode to apply changes.`);
|
|
376
520
|
}
|
|
377
521
|
function printHelp() {
|
|
378
|
-
console.log(`opencode-momo v0.1.
|
|
522
|
+
console.log(`opencode-momo v0.1.3
|
|
379
523
|
|
|
380
524
|
OpenCode plugin that gives coding agents persistent memory using Momo.
|
|
381
525
|
|
package/dist/config.d.ts
CHANGED
|
@@ -5,6 +5,6 @@ export interface MomoConfig {
|
|
|
5
5
|
containerTagProject?: string;
|
|
6
6
|
}
|
|
7
7
|
export declare function getConfigDir(): string;
|
|
8
|
-
export declare function loadConfig(): MomoConfig;
|
|
9
|
-
export declare function isConfigured(): boolean;
|
|
8
|
+
export declare function loadConfig(directory?: string): MomoConfig;
|
|
9
|
+
export declare function isConfigured(directory?: string): boolean;
|
|
10
10
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAWD,wBAAgB,YAAY,IAAI,MAAM,CAMrC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAWD,wBAAgB,YAAY,IAAI,MAAM,CAMrC;AAiCD,wBAAgB,UAAU,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,UAAU,CAmBzD;AAED,wBAAgB,YAAY,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAGxD"}
|
package/dist/index.js
CHANGED
|
@@ -13416,79 +13416,78 @@ class MomoClient {
|
|
|
13416
13416
|
}
|
|
13417
13417
|
}
|
|
13418
13418
|
// src/config.ts
|
|
13419
|
-
import { readFileSync } from "node:fs";
|
|
13419
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
13420
13420
|
import { join } from "node:path";
|
|
13421
13421
|
import { homedir } from "node:os";
|
|
13422
13422
|
|
|
13423
13423
|
// src/services/jsonc.ts
|
|
13424
|
-
function stripJsoncComments(
|
|
13425
|
-
|
|
13426
|
-
|
|
13427
|
-
|
|
13428
|
-
|
|
13429
|
-
|
|
13430
|
-
|
|
13431
|
-
|
|
13432
|
-
|
|
13433
|
-
|
|
13434
|
-
|
|
13435
|
-
|
|
13436
|
-
|
|
13437
|
-
|
|
13438
|
-
|
|
13439
|
-
|
|
13440
|
-
|
|
13441
|
-
|
|
13442
|
-
|
|
13443
|
-
}
|
|
13444
|
-
result += char;
|
|
13445
|
-
i++;
|
|
13446
|
-
continue;
|
|
13447
|
-
}
|
|
13448
|
-
}
|
|
13449
|
-
if (inString) {
|
|
13450
|
-
result += char;
|
|
13451
|
-
i++;
|
|
13452
|
-
continue;
|
|
13453
|
-
}
|
|
13454
|
-
if (!inSingleLineComment && !inMultiLineComment) {
|
|
13455
|
-
if (char === "/" && nextChar === "/") {
|
|
13456
|
-
inSingleLineComment = true;
|
|
13457
|
-
i += 2;
|
|
13424
|
+
function stripJsoncComments(input) {
|
|
13425
|
+
var Mode;
|
|
13426
|
+
((Mode2) => {
|
|
13427
|
+
Mode2[Mode2["Code"] = 0] = "Code";
|
|
13428
|
+
Mode2[Mode2["String"] = 1] = "String";
|
|
13429
|
+
Mode2[Mode2["LineComment"] = 2] = "LineComment";
|
|
13430
|
+
Mode2[Mode2["BlockComment"] = 3] = "BlockComment";
|
|
13431
|
+
})(Mode ||= {});
|
|
13432
|
+
const out = [];
|
|
13433
|
+
let mode = 0 /* Code */;
|
|
13434
|
+
for (let i = 0;i < input.length; i++) {
|
|
13435
|
+
const ch = input[i];
|
|
13436
|
+
const next = input[i + 1];
|
|
13437
|
+
if (mode === 1 /* String */) {
|
|
13438
|
+
out.push(ch);
|
|
13439
|
+
if (ch === "\\") {
|
|
13440
|
+
if (next !== undefined) {
|
|
13441
|
+
out.push(next);
|
|
13442
|
+
i++;
|
|
13443
|
+
}
|
|
13458
13444
|
continue;
|
|
13459
13445
|
}
|
|
13460
|
-
if (
|
|
13461
|
-
|
|
13462
|
-
i += 2;
|
|
13463
|
-
continue;
|
|
13446
|
+
if (ch === '"') {
|
|
13447
|
+
mode = 0 /* Code */;
|
|
13464
13448
|
}
|
|
13449
|
+
continue;
|
|
13465
13450
|
}
|
|
13466
|
-
if (
|
|
13467
|
-
if (
|
|
13451
|
+
if (mode === 2 /* LineComment */) {
|
|
13452
|
+
if (ch === `
|
|
13468
13453
|
`) {
|
|
13469
|
-
|
|
13470
|
-
|
|
13454
|
+
mode = 0 /* Code */;
|
|
13455
|
+
out.push(`
|
|
13456
|
+
`);
|
|
13471
13457
|
}
|
|
13472
|
-
i++;
|
|
13473
13458
|
continue;
|
|
13474
13459
|
}
|
|
13475
|
-
if (
|
|
13476
|
-
if (
|
|
13477
|
-
|
|
13478
|
-
i
|
|
13460
|
+
if (mode === 3 /* BlockComment */) {
|
|
13461
|
+
if (ch === "*" && next === "/") {
|
|
13462
|
+
mode = 0 /* Code */;
|
|
13463
|
+
i++;
|
|
13479
13464
|
continue;
|
|
13480
13465
|
}
|
|
13481
|
-
if (
|
|
13466
|
+
if (ch === `
|
|
13482
13467
|
`) {
|
|
13483
|
-
|
|
13468
|
+
out.push(`
|
|
13469
|
+
`);
|
|
13484
13470
|
}
|
|
13471
|
+
continue;
|
|
13472
|
+
}
|
|
13473
|
+
if (ch === '"') {
|
|
13474
|
+
mode = 1 /* String */;
|
|
13475
|
+
out.push(ch);
|
|
13476
|
+
continue;
|
|
13477
|
+
}
|
|
13478
|
+
if (ch === "/" && next === "/") {
|
|
13479
|
+
mode = 2 /* LineComment */;
|
|
13480
|
+
i++;
|
|
13481
|
+
continue;
|
|
13482
|
+
}
|
|
13483
|
+
if (ch === "/" && next === "*") {
|
|
13484
|
+
mode = 3 /* BlockComment */;
|
|
13485
13485
|
i++;
|
|
13486
13486
|
continue;
|
|
13487
13487
|
}
|
|
13488
|
-
|
|
13489
|
-
i++;
|
|
13488
|
+
out.push(ch);
|
|
13490
13489
|
}
|
|
13491
|
-
return
|
|
13490
|
+
return out.join("").replace(/,\s*([}\]])/g, "$1");
|
|
13492
13491
|
}
|
|
13493
13492
|
|
|
13494
13493
|
// src/config.ts
|
|
@@ -13502,6 +13501,9 @@ function getConfigDir() {
|
|
|
13502
13501
|
}
|
|
13503
13502
|
function readConfigFile() {
|
|
13504
13503
|
const configPath = join(getConfigDir(), "momo.jsonc");
|
|
13504
|
+
return readJsoncConfigFile(configPath);
|
|
13505
|
+
}
|
|
13506
|
+
function readJsoncConfigFile(configPath) {
|
|
13505
13507
|
try {
|
|
13506
13508
|
const raw = readFileSync(configPath, "utf-8");
|
|
13507
13509
|
const stripped = stripJsoncComments(raw);
|
|
@@ -13510,19 +13512,35 @@ function readConfigFile() {
|
|
|
13510
13512
|
return {};
|
|
13511
13513
|
}
|
|
13512
13514
|
}
|
|
13513
|
-
function
|
|
13514
|
-
|
|
13515
|
+
function readProjectConfigFile(directory) {
|
|
13516
|
+
if (!directory)
|
|
13517
|
+
return {};
|
|
13518
|
+
const dotPath = join(directory, ".momo.jsonc");
|
|
13519
|
+
if (existsSync(dotPath)) {
|
|
13520
|
+
return readJsoncConfigFile(dotPath);
|
|
13521
|
+
}
|
|
13522
|
+
const plainPath = join(directory, "momo.jsonc");
|
|
13523
|
+
if (existsSync(plainPath)) {
|
|
13524
|
+
return readJsoncConfigFile(plainPath);
|
|
13525
|
+
}
|
|
13526
|
+
return {};
|
|
13527
|
+
}
|
|
13528
|
+
function loadConfig(directory) {
|
|
13529
|
+
const globalConfig2 = readConfigFile();
|
|
13530
|
+
const projectConfig = readProjectConfigFile(directory);
|
|
13515
13531
|
const envApiKey = process.env.MOMO_API_KEY;
|
|
13516
13532
|
const envBaseUrl = process.env.MOMO_BASE_URL;
|
|
13533
|
+
const envContainerTagUser = process.env.MOMO_CONTAINER_TAG_USER;
|
|
13534
|
+
const envContainerTagProject = process.env.MOMO_CONTAINER_TAG_PROJECT;
|
|
13517
13535
|
return {
|
|
13518
|
-
apiKey: envApiKey ??
|
|
13519
|
-
baseUrl: envBaseUrl ??
|
|
13520
|
-
containerTagUser:
|
|
13521
|
-
containerTagProject:
|
|
13536
|
+
apiKey: envApiKey ?? projectConfig.apiKey ?? globalConfig2.apiKey,
|
|
13537
|
+
baseUrl: envBaseUrl ?? projectConfig.baseUrl ?? globalConfig2.baseUrl ?? DEFAULT_BASE_URL,
|
|
13538
|
+
containerTagUser: envContainerTagUser ?? projectConfig.containerTagUser ?? globalConfig2.containerTagUser,
|
|
13539
|
+
containerTagProject: envContainerTagProject ?? projectConfig.containerTagProject ?? globalConfig2.containerTagProject
|
|
13522
13540
|
};
|
|
13523
13541
|
}
|
|
13524
|
-
function isConfigured() {
|
|
13525
|
-
const config2 = loadConfig();
|
|
13542
|
+
function isConfigured(directory) {
|
|
13543
|
+
const config2 = loadConfig(directory);
|
|
13526
13544
|
return config2.apiKey != null && config2.apiKey.length > 0;
|
|
13527
13545
|
}
|
|
13528
13546
|
|
|
@@ -13701,8 +13719,8 @@ var HELP_TEXT = `**Momo Memory Commands**
|
|
|
13701
13719
|
- \`momo({ mode: "forget", memoryId: "mem_abc123" })\`
|
|
13702
13720
|
`;
|
|
13703
13721
|
var MomoPlugin = async (ctx) => {
|
|
13704
|
-
const config2 = loadConfig();
|
|
13705
|
-
const configured = isConfigured();
|
|
13722
|
+
const config2 = loadConfig(ctx.directory);
|
|
13723
|
+
const configured = isConfigured(ctx.directory);
|
|
13706
13724
|
let momo;
|
|
13707
13725
|
if (configured) {
|
|
13708
13726
|
momo = new MomoClient({
|
|
@@ -13716,7 +13734,7 @@ var MomoPlugin = async (ctx) => {
|
|
|
13716
13734
|
});
|
|
13717
13735
|
function requireMomo() {
|
|
13718
13736
|
if (!momo) {
|
|
13719
|
-
throw new Error("Momo is not configured. Set MOMO_API_KEY
|
|
13737
|
+
throw new Error("Momo is not configured. Set MOMO_API_KEY or configure ~/.config/opencode/momo.jsonc (or project-local .momo.jsonc).");
|
|
13720
13738
|
}
|
|
13721
13739
|
return momo;
|
|
13722
13740
|
}
|
package/dist/services/jsonc.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Remove JSONC comments and trailing commas.
|
|
3
|
+
*
|
|
4
|
+
* This parser is intentionally lightweight and keeps string literals intact,
|
|
5
|
+
* including escaped quotes and URLs.
|
|
5
6
|
*/
|
|
6
|
-
export declare function stripJsoncComments(
|
|
7
|
+
export declare function stripJsoncComments(input: string): string;
|
|
7
8
|
//# sourceMappingURL=jsonc.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jsonc.d.ts","sourceRoot":"","sources":["../../src/services/jsonc.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"jsonc.d.ts","sourceRoot":"","sources":["../../src/services/jsonc.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAgFxD"}
|