@cortexkit/opencode-magic-context 0.2.4 → 0.2.6
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 +3 -3
- package/dist/cli/config-paths.d.ts.map +1 -1
- package/dist/cli/opencode-helpers.d.ts.map +1 -1
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli.js +120 -60
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -99,9 +99,9 @@ Create `magic-context.jsonc` in your project root, `.opencode/`, or `~/.config/o
|
|
|
99
99
|
|
|
100
100
|
That's it. Everything else has sensible defaults. Project config merges on top of user-wide settings.
|
|
101
101
|
|
|
102
|
-
### Oh-My-OpenCode Users
|
|
102
|
+
### Oh-My-OpenCode / Oh-My-OpenAgent Users
|
|
103
103
|
|
|
104
|
-
If you use [oh-my-
|
|
104
|
+
If you use [oh-my-openagent](https://github.com/code-yeongyu/oh-my-openagent) (formerly oh-my-opencode), disable the hooks that conflict with Magic Context in your `oh-my-openagent.json`:
|
|
105
105
|
|
|
106
106
|
```json
|
|
107
107
|
{
|
|
@@ -113,7 +113,7 @@ If you use [oh-my-opencode](https://github.com/code-yeongyu/oh-my-opencode), dis
|
|
|
113
113
|
}
|
|
114
114
|
```
|
|
115
115
|
|
|
116
|
-
The setup wizard handles this automatically if it detects an oh-my-opencode config.
|
|
116
|
+
The setup wizard handles this automatically if it detects an oh-my-openagent or oh-my-opencode config.
|
|
117
117
|
|
|
118
118
|
---
|
|
119
119
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-paths.d.ts","sourceRoot":"","sources":["../../src/cli/config-paths.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,WAAW;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,oBAAoB,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;IAChD,kBAAkB,EAAE,MAAM,CAAC;IAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;
|
|
1
|
+
{"version":3,"file":"config-paths.d.ts","sourceRoot":"","sources":["../../src/cli/config-paths.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,WAAW;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,oBAAoB,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;IAChD,kBAAkB,EAAE,MAAM,CAAC;IAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAmCD,wBAAgB,iBAAiB,IAAI,WAAW,CA2B/C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opencode-helpers.d.ts","sourceRoot":"","sources":["../../src/cli/opencode-helpers.ts"],"names":[],"mappings":"AAEA,wBAAgB,mBAAmB,IAAI,OAAO,CAO7C;AAED,wBAAgB,kBAAkB,IAAI,MAAM,GAAG,IAAI,CAMlD;AAED,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CAU7C;AAED,2CAA2C;AAC3C,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAU7E;AAED,2CAA2C;AAC3C,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CASvD;AAED,uDAAuD;AACvD,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAE3E;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAC/B,SAAS,EAAE,MAAM,EAAE,EACnB,IAAI,EAAE,WAAW,GAAG,SAAS,GAAG,UAAU,GAC3C;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"opencode-helpers.d.ts","sourceRoot":"","sources":["../../src/cli/opencode-helpers.ts"],"names":[],"mappings":"AAEA,wBAAgB,mBAAmB,IAAI,OAAO,CAO7C;AAED,wBAAgB,kBAAkB,IAAI,MAAM,GAAG,IAAI,CAMlD;AAED,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CAU7C;AAED,2CAA2C;AAC3C,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAU7E;AAED,2CAA2C;AAC3C,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CASvD;AAED,uDAAuD;AACvD,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAE3E;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAC/B,SAAS,EAAE,MAAM,EAAE,EACnB,IAAI,EAAE,WAAW,GAAG,SAAS,GAAG,UAAU,GAC3C;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,EAAE,CA0D3D"}
|
package/dist/cli/setup.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/cli/setup.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/cli/setup.ts"],"names":[],"mappings":"AAgMA,wBAAsB,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC,CAmKhD"}
|
package/dist/cli.js
CHANGED
|
@@ -116,6 +116,8 @@ function getConfigDir() {
|
|
|
116
116
|
}
|
|
117
117
|
function findOmoConfig(configDir) {
|
|
118
118
|
const locations = [
|
|
119
|
+
join(configDir, "oh-my-openagent.jsonc"),
|
|
120
|
+
join(configDir, "oh-my-openagent.json"),
|
|
119
121
|
join(configDir, "oh-my-opencode.jsonc"),
|
|
120
122
|
join(configDir, "oh-my-opencode.json")
|
|
121
123
|
];
|
|
@@ -179,64 +181,49 @@ function getAvailableModels() {
|
|
|
179
181
|
function buildModelSelection(allModels, role) {
|
|
180
182
|
const result = [];
|
|
181
183
|
const added = new Set;
|
|
182
|
-
const addIfAvailable = (pattern,
|
|
184
|
+
const addIfAvailable = (pattern, hint) => {
|
|
183
185
|
const matches = allModels.filter((m) => m === pattern || m.endsWith(`/${pattern}`));
|
|
184
186
|
for (const m of matches) {
|
|
185
187
|
if (!added.has(m)) {
|
|
186
188
|
added.add(m);
|
|
187
189
|
result.push({
|
|
188
|
-
label: m,
|
|
190
|
+
label: hint ? `${m} — ${hint}` : m,
|
|
189
191
|
value: m,
|
|
190
|
-
recommended:
|
|
192
|
+
recommended: result.length === 0
|
|
191
193
|
});
|
|
192
194
|
}
|
|
193
195
|
}
|
|
194
196
|
};
|
|
195
197
|
if (role === "historian") {
|
|
196
|
-
addIfAvailable("claude-sonnet-4
|
|
197
|
-
addIfAvailable("claude-sonnet-4-
|
|
198
|
-
addIfAvailable("
|
|
199
|
-
addIfAvailable("gpt-5.4");
|
|
200
|
-
addIfAvailable("
|
|
201
|
-
addIfAvailable("minimax-m2.7");
|
|
202
|
-
|
|
203
|
-
if (!added.has(m)) {
|
|
204
|
-
added.add(m);
|
|
205
|
-
result.push({ label: `${m} (free with Copilot)`, value: m });
|
|
206
|
-
}
|
|
207
|
-
}
|
|
198
|
+
addIfAvailable("github-copilot/claude-sonnet-4.6", "per-request billing");
|
|
199
|
+
addIfAvailable("anthropic/claude-sonnet-4-6");
|
|
200
|
+
addIfAvailable("github-copilot/gpt-5.4", "per-request billing");
|
|
201
|
+
addIfAvailable("openai/gpt-5.4");
|
|
202
|
+
addIfAvailable("github-copilot/gemini-3.1-pro-preview", "per-request billing");
|
|
203
|
+
addIfAvailable("opencode-go/minimax-m2.7");
|
|
204
|
+
addIfAvailable("opencode-go/glm-5");
|
|
208
205
|
} else if (role === "dreamer") {
|
|
209
206
|
for (const m of allModels.filter((m2) => m2.startsWith("ollama/"))) {
|
|
210
207
|
if (!added.has(m)) {
|
|
211
208
|
added.add(m);
|
|
212
|
-
result.push({ label: `${m}
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
addIfAvailable("claude-sonnet-4-6", result.length === 0);
|
|
216
|
-
addIfAvailable("gemini-3-flash");
|
|
217
|
-
addIfAvailable("glm-5");
|
|
218
|
-
addIfAvailable("minimax-m2.7");
|
|
219
|
-
addIfAvailable("gpt-5.4-mini");
|
|
220
|
-
for (const m of allModels.filter((m2) => m2.startsWith("github-copilot/"))) {
|
|
221
|
-
if (!added.has(m)) {
|
|
222
|
-
added.add(m);
|
|
223
|
-
result.push({ label: `${m} (free with Copilot)`, value: m });
|
|
209
|
+
result.push({ label: `${m} — local`, value: m, recommended: result.length === 0 });
|
|
224
210
|
}
|
|
225
211
|
}
|
|
212
|
+
addIfAvailable("github-copilot/claude-sonnet-4.6", "per-request billing");
|
|
213
|
+
addIfAvailable("anthropic/claude-sonnet-4-6");
|
|
214
|
+
addIfAvailable("github-copilot/gemini-3-flash-preview", "per-request billing");
|
|
215
|
+
addIfAvailable("opencode-go/glm-5");
|
|
216
|
+
addIfAvailable("opencode-go/minimax-m2.7");
|
|
226
217
|
} else if (role === "sidekick") {
|
|
227
218
|
for (const m of allModels.filter((m2) => m2.startsWith("cerebras/"))) {
|
|
228
219
|
if (!added.has(m)) {
|
|
229
220
|
added.add(m);
|
|
230
|
-
result.push({
|
|
231
|
-
label: `${m} (fastest)`,
|
|
232
|
-
value: m,
|
|
233
|
-
recommended: result.length === 0
|
|
234
|
-
});
|
|
221
|
+
result.push({ label: m, value: m, recommended: result.length === 0 });
|
|
235
222
|
}
|
|
236
223
|
}
|
|
237
|
-
addIfAvailable("gpt-5-nano");
|
|
238
|
-
addIfAvailable("gemini-3-flash");
|
|
239
|
-
addIfAvailable("gpt-5
|
|
224
|
+
addIfAvailable("opencode/gpt-5-nano");
|
|
225
|
+
addIfAvailable("github-copilot/gemini-3-flash-preview");
|
|
226
|
+
addIfAvailable("github-copilot/gpt-5-mini");
|
|
240
227
|
}
|
|
241
228
|
return result;
|
|
242
229
|
}
|
|
@@ -1293,69 +1280,130 @@ function ensureDir(dir) {
|
|
|
1293
1280
|
mkdirSync(dir, { recursive: true });
|
|
1294
1281
|
}
|
|
1295
1282
|
}
|
|
1296
|
-
function
|
|
1297
|
-
|
|
1283
|
+
function stripJsoncToJson(text) {
|
|
1284
|
+
let result = "";
|
|
1285
|
+
let i = 0;
|
|
1286
|
+
let inString = false;
|
|
1287
|
+
let escaped = false;
|
|
1288
|
+
while (i < text.length) {
|
|
1289
|
+
const ch = text[i];
|
|
1290
|
+
if (escaped) {
|
|
1291
|
+
result += ch;
|
|
1292
|
+
escaped = false;
|
|
1293
|
+
i++;
|
|
1294
|
+
continue;
|
|
1295
|
+
}
|
|
1296
|
+
if (inString) {
|
|
1297
|
+
if (ch === "\\")
|
|
1298
|
+
escaped = true;
|
|
1299
|
+
else if (ch === '"')
|
|
1300
|
+
inString = false;
|
|
1301
|
+
result += ch;
|
|
1302
|
+
i++;
|
|
1303
|
+
continue;
|
|
1304
|
+
}
|
|
1305
|
+
if (ch === "/" && text[i + 1] === "/") {
|
|
1306
|
+
while (i < text.length && text[i] !== `
|
|
1307
|
+
`)
|
|
1308
|
+
i++;
|
|
1309
|
+
continue;
|
|
1310
|
+
}
|
|
1311
|
+
if (ch === "/" && text[i + 1] === "*") {
|
|
1312
|
+
i += 2;
|
|
1313
|
+
while (i < text.length && !(text[i] === "*" && text[i + 1] === "/"))
|
|
1314
|
+
i++;
|
|
1315
|
+
i += 2;
|
|
1316
|
+
continue;
|
|
1317
|
+
}
|
|
1318
|
+
if (ch === '"')
|
|
1319
|
+
inString = true;
|
|
1320
|
+
result += ch;
|
|
1321
|
+
i++;
|
|
1322
|
+
}
|
|
1323
|
+
return result.replace(/,(\s*[}\]])/g, "$1");
|
|
1298
1324
|
}
|
|
1299
1325
|
function readJsonc(path) {
|
|
1300
1326
|
const content = readFileSync(path, "utf-8");
|
|
1301
1327
|
try {
|
|
1302
|
-
return JSON.parse(
|
|
1303
|
-
} catch {
|
|
1304
|
-
|
|
1328
|
+
return JSON.parse(stripJsoncToJson(content));
|
|
1329
|
+
} catch (err) {
|
|
1330
|
+
console.error(` ⚠ Failed to parse ${path}: ${err instanceof Error ? err.message : err}`);
|
|
1331
|
+
return null;
|
|
1305
1332
|
}
|
|
1306
1333
|
}
|
|
1307
|
-
function writeJsonc(path, data) {
|
|
1308
|
-
writeFileSync(path, `${JSON.stringify(data, null, 2)}
|
|
1309
|
-
`);
|
|
1310
|
-
}
|
|
1311
1334
|
function addPluginToOpenCodeConfig(configPath, format) {
|
|
1312
1335
|
ensureDir(dirname(configPath));
|
|
1313
1336
|
if (format === "none") {
|
|
1314
|
-
const
|
|
1337
|
+
const config = {
|
|
1315
1338
|
plugin: [PLUGIN_NAME],
|
|
1316
1339
|
compaction: { auto: false, prune: false }
|
|
1317
1340
|
};
|
|
1318
|
-
|
|
1341
|
+
writeFileSync(configPath, `${JSON.stringify(config, null, 2)}
|
|
1342
|
+
`);
|
|
1343
|
+
return;
|
|
1344
|
+
}
|
|
1345
|
+
const existing = readJsonc(configPath);
|
|
1346
|
+
if (!existing) {
|
|
1347
|
+
R2.warn(`Could not parse ${configPath} — skipping to avoid data loss`);
|
|
1319
1348
|
return;
|
|
1320
1349
|
}
|
|
1321
|
-
const
|
|
1322
|
-
const plugins = config.plugin ?? [];
|
|
1350
|
+
const plugins = existing.plugin ?? [];
|
|
1323
1351
|
const hasPlugin = plugins.some((p) => p === PLUGIN_NAME || p.startsWith(`${PLUGIN_NAME}@`));
|
|
1324
1352
|
if (!hasPlugin) {
|
|
1325
1353
|
plugins.push(PLUGIN_NAME);
|
|
1326
|
-
config.plugin = plugins;
|
|
1327
1354
|
}
|
|
1328
|
-
|
|
1355
|
+
existing.plugin = plugins;
|
|
1356
|
+
const compaction = existing.compaction ?? {};
|
|
1329
1357
|
compaction.auto = false;
|
|
1330
1358
|
compaction.prune = false;
|
|
1331
|
-
|
|
1332
|
-
|
|
1359
|
+
existing.compaction = compaction;
|
|
1360
|
+
writeFileSync(configPath, `${JSON.stringify(existing, null, 2)}
|
|
1361
|
+
`);
|
|
1333
1362
|
}
|
|
1334
1363
|
function writeMagicContextConfig(configPath, options) {
|
|
1335
|
-
const config = {};
|
|
1364
|
+
const config = (existsSync2(configPath) ? readJsonc(configPath) : null) ?? {};
|
|
1336
1365
|
if (options.historianModel) {
|
|
1337
|
-
config.historian
|
|
1366
|
+
const historian = config.historian ?? {};
|
|
1367
|
+
historian.model = options.historianModel;
|
|
1368
|
+
config.historian = historian;
|
|
1338
1369
|
}
|
|
1339
1370
|
if (options.dreamerEnabled) {
|
|
1340
|
-
const dreamer =
|
|
1371
|
+
const dreamer = config.dreamer ?? {};
|
|
1372
|
+
dreamer.enabled = true;
|
|
1341
1373
|
if (options.dreamerModel) {
|
|
1342
1374
|
dreamer.model = options.dreamerModel;
|
|
1343
1375
|
}
|
|
1344
1376
|
config.dreamer = dreamer;
|
|
1345
1377
|
} else {
|
|
1346
|
-
config.dreamer
|
|
1378
|
+
const dreamer = config.dreamer ?? {};
|
|
1379
|
+
dreamer.enabled = false;
|
|
1380
|
+
config.dreamer = dreamer;
|
|
1347
1381
|
}
|
|
1348
1382
|
if (options.sidekickEnabled) {
|
|
1349
|
-
const sidekick =
|
|
1383
|
+
const sidekick = config.sidekick ?? {};
|
|
1384
|
+
sidekick.enabled = true;
|
|
1350
1385
|
if (options.sidekickModel) {
|
|
1351
1386
|
sidekick.model = options.sidekickModel;
|
|
1352
1387
|
}
|
|
1353
1388
|
config.sidekick = sidekick;
|
|
1354
1389
|
}
|
|
1355
|
-
|
|
1390
|
+
if (options.claudeMax) {
|
|
1391
|
+
const cacheTtl = config.cache_ttl ?? {};
|
|
1392
|
+
if (!cacheTtl.default)
|
|
1393
|
+
cacheTtl.default = "5m";
|
|
1394
|
+
cacheTtl["anthropic/claude-sonnet-4-6"] = "59m";
|
|
1395
|
+
cacheTtl["anthropic/claude-opus-4-6"] = "59m";
|
|
1396
|
+
config.cache_ttl = cacheTtl;
|
|
1397
|
+
}
|
|
1398
|
+
writeFileSync(configPath, `${JSON.stringify(config, null, 2)}
|
|
1399
|
+
`);
|
|
1356
1400
|
}
|
|
1357
1401
|
function disableOmoHooks(omoConfigPath) {
|
|
1358
1402
|
const config = readJsonc(omoConfigPath);
|
|
1403
|
+
if (!config) {
|
|
1404
|
+
R2.warn(`Could not parse ${omoConfigPath} — skipping to avoid data loss`);
|
|
1405
|
+
return;
|
|
1406
|
+
}
|
|
1359
1407
|
const disabledHooks = config.disabled_hooks ?? [];
|
|
1360
1408
|
const hooksToDisable = [
|
|
1361
1409
|
"context-window-monitor",
|
|
@@ -1368,7 +1416,8 @@ function disableOmoHooks(omoConfigPath) {
|
|
|
1368
1416
|
}
|
|
1369
1417
|
}
|
|
1370
1418
|
config.disabled_hooks = disabledHooks;
|
|
1371
|
-
|
|
1419
|
+
writeFileSync(omoConfigPath, `${JSON.stringify(config, null, 2)}
|
|
1420
|
+
`);
|
|
1372
1421
|
}
|
|
1373
1422
|
async function runSetup() {
|
|
1374
1423
|
Wt2("Magic Context — Setup");
|
|
@@ -1440,12 +1489,23 @@ async function runSetup() {
|
|
|
1440
1489
|
} else if (sidekickEnabled) {
|
|
1441
1490
|
R2.info("Using built-in fallback chain for sidekick");
|
|
1442
1491
|
}
|
|
1492
|
+
const hasAnthropic = allModels.some((m) => m.startsWith("anthropic/"));
|
|
1493
|
+
let claudeMax = false;
|
|
1494
|
+
if (hasAnthropic) {
|
|
1495
|
+
R2.message(`Claude Max/Pro subscribers get extended prompt caching (up to 1 hour).
|
|
1496
|
+
` + "This lets Magic Context defer context operations much longer, saving money.");
|
|
1497
|
+
claudeMax = await confirm("Do you have a Claude Max or Pro subscription?", false);
|
|
1498
|
+
if (claudeMax) {
|
|
1499
|
+
R2.success("Cache TTL set to 59m for Anthropic models");
|
|
1500
|
+
}
|
|
1501
|
+
}
|
|
1443
1502
|
writeMagicContextConfig(paths.magicContextConfig, {
|
|
1444
1503
|
historianModel,
|
|
1445
1504
|
dreamerEnabled,
|
|
1446
1505
|
dreamerModel,
|
|
1447
1506
|
sidekickEnabled,
|
|
1448
|
-
sidekickModel
|
|
1507
|
+
sidekickModel,
|
|
1508
|
+
claudeMax
|
|
1449
1509
|
});
|
|
1450
1510
|
R2.success(`Config written to ${paths.magicContextConfig}`);
|
|
1451
1511
|
if (paths.omoConfig) {
|
package/package.json
CHANGED