@cortexkit/opencode-magic-context 0.8.6 → 0.8.7

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 CHANGED
@@ -147,6 +147,12 @@ Use `--force` to force-clear the plugin cache even when versions match (fixes br
147
147
  bunx @cortexkit/opencode-magic-context@latest doctor --force
148
148
  ```
149
149
 
150
+ Hit a real bug? Use `--issue` to collect environment, sanitized config, and the last 200 log lines into a ready-to-submit report. It can also open the issue directly via `gh` if you have it installed:
151
+
152
+ ```bash
153
+ bunx @cortexkit/opencode-magic-context@latest doctor --issue
154
+ ```
155
+
150
156
  ---
151
157
 
152
158
  ## What Your Agent Gets
@@ -0,0 +1,49 @@
1
+ import { type ConfigPaths } from "./config-paths";
2
+ export interface DiagnosticReport {
3
+ timestamp: string;
4
+ platform: string;
5
+ arch: string;
6
+ nodeVersion: string;
7
+ pluginVersion: string;
8
+ opencodeInstalled: boolean;
9
+ opencodeVersion: string | null;
10
+ configPaths: ConfigPaths;
11
+ opencodeConfigHasPlugin: boolean;
12
+ tuiConfigHasPlugin: boolean;
13
+ magicContextConfig: {
14
+ exists: boolean;
15
+ parseError?: string;
16
+ flags: Record<string, unknown>;
17
+ };
18
+ pluginCache: {
19
+ path: string;
20
+ cached?: string;
21
+ latest?: string;
22
+ };
23
+ storageDir: {
24
+ path: string;
25
+ exists: boolean;
26
+ contextDbSizeBytes: number;
27
+ };
28
+ conflicts: {
29
+ hasConflict: boolean;
30
+ reasons: string[];
31
+ };
32
+ logFile: {
33
+ path: string;
34
+ exists: boolean;
35
+ sizeKb: number;
36
+ };
37
+ historianDumps: {
38
+ dir: string;
39
+ count: number;
40
+ recent: {
41
+ name: string;
42
+ ageMinutes: number;
43
+ sizeKb: number;
44
+ }[];
45
+ };
46
+ }
47
+ export declare function collectDiagnostics(): Promise<DiagnosticReport>;
48
+ export declare function renderDiagnosticsMarkdown(report: DiagnosticReport): string;
49
+ //# sourceMappingURL=diagnostics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../../src/cli/diagnostics.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,WAAW,EAAqB,MAAM,gBAAgB,CAAC;AAMrE,MAAM,WAAW,gBAAgB;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,WAAW,EAAE,WAAW,CAAC;IACzB,uBAAuB,EAAE,OAAO,CAAC;IACjC,kBAAkB,EAAE,OAAO,CAAC;IAC5B,kBAAkB,EAAE;QAChB,MAAM,EAAE,OAAO,CAAC;QAChB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAClC,CAAC;IACF,WAAW,EAAE;QACT,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,UAAU,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,OAAO,CAAC;QAChB,kBAAkB,EAAE,MAAM,CAAC;KAC9B,CAAC;IACF,SAAS,EAAE;QACP,WAAW,EAAE,OAAO,CAAC;QACrB,OAAO,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC;IACF,OAAO,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,OAAO,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,cAAc,EAAE;QACZ,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,UAAU,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;KAClE,CAAC;CACL;AAgKD,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,gBAAgB,CAAC,CA+CpE;AASD,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAwE1E"}
@@ -1,4 +1,5 @@
1
1
  export declare function runDoctor(options?: {
2
2
  force?: boolean;
3
+ issue?: boolean;
3
4
  }): Promise<number>;
4
5
  //# sourceMappingURL=doctor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"AA2GA,wBAAsB,SAAS,CAAC,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAuMlF"}
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"AA4MA,wBAAsB,SAAS,CAC3B,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GACnD,OAAO,CAAC,MAAM,CAAC,CA2MjB"}
@@ -0,0 +1,12 @@
1
+ import { type DiagnosticReport } from "./diagnostics";
2
+ /**
3
+ * Replace absolute home paths and usernames in captured log lines so users
4
+ * can share reports publicly without leaking their local paths.
5
+ */
6
+ export declare function sanitizeLogContent(content: string): string;
7
+ export interface BundledIssueReport {
8
+ path: string;
9
+ bodyMarkdown: string;
10
+ }
11
+ export declare function bundleIssueReport(report: DiagnosticReport, description: string, _title: string): Promise<BundledIssueReport>;
12
+ //# sourceMappingURL=logs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logs.d.ts","sourceRoot":"","sources":["../../src/cli/logs.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,gBAAgB,EAA6B,MAAM,eAAe,CAAC;AAMjF;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAe1D;AAeD,MAAM,WAAW,kBAAkB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;CACxB;AAED,wBAAsB,iBAAiB,CACnC,MAAM,EAAE,gBAAgB,EACxB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,GACf,OAAO,CAAC,kBAAkB,CAAC,CAsC7B"}
@@ -1,6 +1,11 @@
1
1
  import { intro, log, note, outro, spinner } from "@clack/prompts";
2
2
  export { intro, log, note, outro, spinner };
3
3
  export declare function confirm(message: string, defaultYes?: boolean): Promise<boolean>;
4
+ export declare function text(message: string, options?: {
5
+ placeholder?: string;
6
+ initialValue?: string;
7
+ validate?: (value: string) => string | undefined;
8
+ }): Promise<string>;
4
9
  export declare function selectOne(message: string, options: {
5
10
  label: string;
6
11
  value: string;
@@ -1 +1 @@
1
- {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/cli/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,KAAK,EAEL,GAAG,EACH,IAAI,EACJ,KAAK,EAEL,OAAO,EACV,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAS5C,wBAAsB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,UAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAOlF;AAED,wBAAsB,SAAS,CAC3B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,EAAE,GACnE,OAAO,CAAC,MAAM,CAAC,CAWjB"}
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/cli/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,KAAK,EAEL,GAAG,EACH,IAAI,EACJ,KAAK,EAEL,OAAO,EACV,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAS5C,wBAAsB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,UAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAOlF;AAED,wBAAsB,IAAI,CACtB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;IACL,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;CAC/C,GACP,OAAO,CAAC,MAAM,CAAC,CAejB;AAED,wBAAsB,SAAS,CAC3B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,EAAE,GACnE,OAAO,CAAC,MAAM,CAAC,CAWjB"}
package/dist/cli.js CHANGED
@@ -7849,11 +7849,12 @@ var require_src3 = __commonJS((exports, module) => {
7849
7849
  });
7850
7850
 
7851
7851
  // src/cli/doctor.ts
7852
- var import_comment_json2 = __toESM(require_src2(), 1);
7853
- import { existsSync as existsSync5, readdirSync, readFileSync as readFileSync3, rmSync, statSync, writeFileSync as writeFileSync3 } from "node:fs";
7854
- import { createRequire as createRequire2 } from "node:module";
7855
- import { homedir as homedir3, platform, tmpdir as tmpdir2 } from "node:os";
7856
- import { join as join7 } from "node:path";
7852
+ var import_comment_json3 = __toESM(require_src2(), 1);
7853
+ import { execSync as execSync2, spawnSync } from "node:child_process";
7854
+ import { existsSync as existsSync7, readdirSync as readdirSync2, readFileSync as readFileSync5, rmSync, statSync as statSync2, writeFileSync as writeFileSync4 } from "node:fs";
7855
+ import { createRequire as createRequire3 } from "node:module";
7856
+ import { homedir as homedir5, platform, tmpdir as tmpdir3 } from "node:os";
7857
+ import { join as join9 } from "node:path";
7857
7858
 
7858
7859
  // src/shared/conflict-detector.ts
7859
7860
  import { join as join2 } from "node:path";
@@ -8476,6 +8477,13 @@ function detectConfigPaths() {
8476
8477
  };
8477
8478
  }
8478
8479
 
8480
+ // src/cli/diagnostics.ts
8481
+ var import_comment_json2 = __toESM(require_src2(), 1);
8482
+ import { existsSync as existsSync5, readdirSync, readFileSync as readFileSync3, statSync } from "node:fs";
8483
+ import { createRequire as createRequire2 } from "node:module";
8484
+ import { homedir as homedir3, tmpdir as tmpdir2, userInfo } from "node:os";
8485
+ import { join as join7 } from "node:path";
8486
+
8479
8487
  // src/cli/opencode-helpers.ts
8480
8488
  import { execSync } from "node:child_process";
8481
8489
  function isOpenCodeInstalled() {
@@ -8552,6 +8560,329 @@ function buildModelSelection(allModels, role) {
8552
8560
  return result;
8553
8561
  }
8554
8562
 
8563
+ // src/cli/diagnostics.ts
8564
+ var PLUGIN_NAME2 = "@cortexkit/opencode-magic-context";
8565
+ var PLUGIN_ENTRY_WITH_VERSION = `${PLUGIN_NAME2}@latest`;
8566
+ function getSelfVersion() {
8567
+ const require2 = createRequire2(import.meta.url);
8568
+ for (const relPath of ["../../package.json", "../package.json"]) {
8569
+ try {
8570
+ const pkg = require2(relPath);
8571
+ if (typeof pkg.version === "string" && pkg.version.length > 0) {
8572
+ return pkg.version;
8573
+ }
8574
+ } catch {}
8575
+ }
8576
+ return "unknown";
8577
+ }
8578
+ function getOpenCodeCacheDir() {
8579
+ const xdgCache = process.env.XDG_CACHE_HOME;
8580
+ if (xdgCache)
8581
+ return join7(xdgCache, "opencode");
8582
+ if (process.platform === "win32") {
8583
+ const localAppData = process.env.LOCALAPPDATA ?? join7(homedir3(), "AppData", "Local");
8584
+ return join7(localAppData, "opencode");
8585
+ }
8586
+ return join7(homedir3(), ".cache", "opencode");
8587
+ }
8588
+ function getPluginCacheInfo() {
8589
+ const path2 = join7(getOpenCodeCacheDir(), "packages", PLUGIN_ENTRY_WITH_VERSION);
8590
+ let cached;
8591
+ try {
8592
+ const installedPkgPath = join7(path2, "node_modules", "@cortexkit", "opencode-magic-context", "package.json");
8593
+ if (existsSync5(installedPkgPath)) {
8594
+ const pkg = JSON.parse(readFileSync3(installedPkgPath, "utf-8"));
8595
+ cached = typeof pkg.version === "string" ? pkg.version : undefined;
8596
+ }
8597
+ } catch {
8598
+ cached = undefined;
8599
+ }
8600
+ return { path: path2, cached, latest: getSelfVersion() };
8601
+ }
8602
+ function getStorageDir() {
8603
+ const dataHome = process.env.XDG_DATA_HOME || join7(homedir3(), ".local", "share");
8604
+ return join7(dataHome, "opencode", "storage", "plugin", "magic-context");
8605
+ }
8606
+ function fileSize(path2) {
8607
+ try {
8608
+ return existsSync5(path2) ? statSync(path2).size : 0;
8609
+ } catch {
8610
+ return 0;
8611
+ }
8612
+ }
8613
+ function escapeRegex(value) {
8614
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
8615
+ }
8616
+ function sanitizeString(value) {
8617
+ const home = homedir3();
8618
+ const username = userInfo().username;
8619
+ let sanitized = value;
8620
+ if (home) {
8621
+ sanitized = sanitized.replace(new RegExp(escapeRegex(home), "g"), "~");
8622
+ }
8623
+ sanitized = sanitized.replace(/\/Users\/[^/]+\//g, "/Users/<USER>/");
8624
+ sanitized = sanitized.replace(/\/home\/[^/]+\//g, "/home/<USER>/");
8625
+ sanitized = sanitized.replace(/C:\\Users\\[^\\]+\\/g, "C:\\Users\\<USER>\\");
8626
+ if (username) {
8627
+ sanitized = sanitized.replace(new RegExp(escapeRegex(username), "g"), "<USER>");
8628
+ }
8629
+ return sanitized;
8630
+ }
8631
+ function sanitizeValue(value) {
8632
+ if (typeof value === "string")
8633
+ return sanitizeString(value);
8634
+ if (Array.isArray(value))
8635
+ return value.map(sanitizeValue);
8636
+ if (value && typeof value === "object") {
8637
+ return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, sanitizeValue(entry)]));
8638
+ }
8639
+ return value;
8640
+ }
8641
+ function readConfig2(path2) {
8642
+ if (!existsSync5(path2))
8643
+ return { value: null };
8644
+ try {
8645
+ const raw = readFileSync3(path2, "utf-8");
8646
+ const value = import_comment_json2.parse(raw);
8647
+ return { value };
8648
+ } catch (error) {
8649
+ return { value: null, error: error instanceof Error ? error.message : String(error) };
8650
+ }
8651
+ }
8652
+ function configHasPluginEntry(config) {
8653
+ const plugins = Array.isArray(config?.plugin) ? config.plugin : [];
8654
+ return plugins.some((entry) => {
8655
+ if (typeof entry !== "string")
8656
+ return false;
8657
+ if (entry === PLUGIN_NAME2)
8658
+ return true;
8659
+ if (entry.startsWith(`${PLUGIN_NAME2}@`))
8660
+ return true;
8661
+ if (entry.includes("opencode-magic-context"))
8662
+ return true;
8663
+ return false;
8664
+ });
8665
+ }
8666
+ function collectHistorianDumps() {
8667
+ const dir = join7(tmpdir2(), "magic-context-historian");
8668
+ if (!existsSync5(dir)) {
8669
+ return { dir, count: 0, recent: [] };
8670
+ }
8671
+ try {
8672
+ const entries = readdirSync(dir).filter((name) => name.endsWith(".xml")).map((name) => {
8673
+ const stat = statSync(join7(dir, name));
8674
+ return {
8675
+ name,
8676
+ mtime: stat.mtimeMs,
8677
+ sizeKb: Math.round(stat.size / 1024)
8678
+ };
8679
+ }).sort((a, b) => b.mtime - a.mtime);
8680
+ const now = Date.now();
8681
+ const recent = entries.slice(0, 3).map((entry) => ({
8682
+ name: entry.name,
8683
+ ageMinutes: Math.round((now - entry.mtime) / 60000),
8684
+ sizeKb: entry.sizeKb
8685
+ }));
8686
+ return { dir, count: entries.length, recent };
8687
+ } catch {
8688
+ return { dir, count: 0, recent: [] };
8689
+ }
8690
+ }
8691
+ async function collectDiagnostics() {
8692
+ const pluginVersion = getSelfVersion();
8693
+ const configPaths = detectConfigPaths();
8694
+ const opencodeConfig = readConfig2(configPaths.opencodeConfig);
8695
+ const tuiConfig = readConfig2(configPaths.tuiConfig);
8696
+ const magicContextConfig = readConfig2(configPaths.magicContextConfig);
8697
+ const storageDirPath = getStorageDir();
8698
+ const contextDbPath = join7(storageDirPath, "context.db");
8699
+ const logPath = join7(tmpdir2(), "magic-context.log");
8700
+ const logFileSize = existsSync5(logPath) ? statSync(logPath).size : 0;
8701
+ const conflictResult = detectConflicts(process.cwd());
8702
+ return {
8703
+ timestamp: new Date().toISOString(),
8704
+ platform: process.platform,
8705
+ arch: process.arch,
8706
+ nodeVersion: process.version,
8707
+ pluginVersion,
8708
+ opencodeInstalled: isOpenCodeInstalled(),
8709
+ opencodeVersion: getOpenCodeVersion(),
8710
+ configPaths,
8711
+ opencodeConfigHasPlugin: configHasPluginEntry(opencodeConfig.value),
8712
+ tuiConfigHasPlugin: configHasPluginEntry(tuiConfig.value),
8713
+ magicContextConfig: {
8714
+ exists: existsSync5(configPaths.magicContextConfig),
8715
+ ...magicContextConfig.error ? { parseError: magicContextConfig.error } : {},
8716
+ flags: sanitizeValue(magicContextConfig.value ?? {}) ?? {}
8717
+ },
8718
+ pluginCache: getPluginCacheInfo(),
8719
+ storageDir: {
8720
+ path: storageDirPath,
8721
+ exists: existsSync5(storageDirPath),
8722
+ contextDbSizeBytes: fileSize(contextDbPath)
8723
+ },
8724
+ conflicts: {
8725
+ hasConflict: conflictResult.hasConflict,
8726
+ reasons: conflictResult.reasons
8727
+ },
8728
+ logFile: {
8729
+ path: logPath,
8730
+ exists: existsSync5(logPath),
8731
+ sizeKb: Math.round(logFileSize / 1024)
8732
+ },
8733
+ historianDumps: collectHistorianDumps()
8734
+ };
8735
+ }
8736
+ function formatBytes(bytes) {
8737
+ if (bytes < 1024)
8738
+ return `${bytes} B`;
8739
+ if (bytes < 1024 * 1024)
8740
+ return `${(bytes / 1024).toFixed(1)} KB`;
8741
+ if (bytes < 1024 * 1024 * 1024)
8742
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
8743
+ return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
8744
+ }
8745
+ function renderDiagnosticsMarkdown(report) {
8746
+ const configPaths = {
8747
+ configDir: sanitizeString(report.configPaths.configDir),
8748
+ opencodeConfig: sanitizeString(report.configPaths.opencodeConfig),
8749
+ opencodeConfigFormat: report.configPaths.opencodeConfigFormat,
8750
+ magicContextConfig: sanitizeString(report.configPaths.magicContextConfig),
8751
+ tuiConfig: sanitizeString(report.configPaths.tuiConfig),
8752
+ tuiConfigFormat: report.configPaths.tuiConfigFormat,
8753
+ omoConfig: report.configPaths.omoConfig ? sanitizeString(report.configPaths.omoConfig) : null
8754
+ };
8755
+ const pluginCache = {
8756
+ path: sanitizeString(report.pluginCache.path),
8757
+ cached: report.pluginCache.cached ?? null,
8758
+ latest: report.pluginCache.latest ?? null
8759
+ };
8760
+ const storage = {
8761
+ path: sanitizeString(report.storageDir.path),
8762
+ exists: report.storageDir.exists,
8763
+ context_db_size: formatBytes(report.storageDir.contextDbSizeBytes)
8764
+ };
8765
+ const historianDumps = {
8766
+ dir: sanitizeString(report.historianDumps.dir),
8767
+ count: report.historianDumps.count,
8768
+ recent: report.historianDumps.recent
8769
+ };
8770
+ return [
8771
+ `- Timestamp: ${report.timestamp}`,
8772
+ `- Plugin: v${report.pluginVersion}`,
8773
+ `- OS: ${report.platform} ${report.arch}`,
8774
+ `- Node: ${report.nodeVersion}`,
8775
+ `- OpenCode installed: ${report.opencodeInstalled}${report.opencodeVersion ? ` (${report.opencodeVersion})` : ""}`,
8776
+ `- Plugin registered in opencode config: ${report.opencodeConfigHasPlugin}`,
8777
+ `- Plugin registered in tui config: ${report.tuiConfigHasPlugin}`,
8778
+ `- magic-context.jsonc parse error: ${report.magicContextConfig.parseError ?? "none"}`,
8779
+ `- Conflicts detected: ${report.conflicts.hasConflict ? report.conflicts.reasons.join("; ") : "none"}`,
8780
+ "",
8781
+ "### Config paths",
8782
+ "```json",
8783
+ JSON.stringify(configPaths, null, 2),
8784
+ "```",
8785
+ "",
8786
+ "### magic-context.jsonc flags",
8787
+ "```jsonc",
8788
+ JSON.stringify(report.magicContextConfig.flags, null, 2),
8789
+ "```",
8790
+ "",
8791
+ "### Plugin cache",
8792
+ "```json",
8793
+ JSON.stringify(pluginCache, null, 2),
8794
+ "```",
8795
+ "",
8796
+ "### Storage",
8797
+ "```json",
8798
+ JSON.stringify(storage, null, 2),
8799
+ "```",
8800
+ "",
8801
+ "### Historian dumps",
8802
+ "```json",
8803
+ JSON.stringify(historianDumps, null, 2),
8804
+ "```",
8805
+ "",
8806
+ "### Log file",
8807
+ `- Path: ${sanitizeString(report.logFile.path)}`,
8808
+ `- Exists: ${report.logFile.exists}`,
8809
+ `- Size: ${report.logFile.sizeKb} KB`
8810
+ ].join(`
8811
+ `);
8812
+ }
8813
+
8814
+ // src/cli/logs.ts
8815
+ import { readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "node:fs";
8816
+ import { homedir as homedir4, userInfo as userInfo2 } from "node:os";
8817
+ import { join as join8 } from "node:path";
8818
+ function escapeRegex2(value) {
8819
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
8820
+ }
8821
+ function sanitizeLogContent(content) {
8822
+ const home = homedir4();
8823
+ const username = userInfo2().username;
8824
+ let sanitized = content;
8825
+ if (home) {
8826
+ sanitized = sanitized.replace(new RegExp(escapeRegex2(home), "g"), "~");
8827
+ }
8828
+ sanitized = sanitized.replace(/\/Users\/[^/]+\//g, "/Users/<USER>/");
8829
+ sanitized = sanitized.replace(/\/home\/[^/]+\//g, "/home/<USER>/");
8830
+ sanitized = sanitized.replace(/C:\\Users\\[^\\]+\\/g, "C:\\Users\\<USER>\\");
8831
+ if (username) {
8832
+ sanitized = sanitized.replace(new RegExp(escapeRegex2(username), "g"), "<USER>");
8833
+ }
8834
+ return sanitized;
8835
+ }
8836
+ function formatTimestamp(date) {
8837
+ const pad = (value) => String(value).padStart(2, "0");
8838
+ return [
8839
+ String(date.getFullYear()),
8840
+ pad(date.getMonth() + 1),
8841
+ pad(date.getDate()),
8842
+ "-",
8843
+ pad(date.getHours()),
8844
+ pad(date.getMinutes()),
8845
+ pad(date.getSeconds())
8846
+ ].join("");
8847
+ }
8848
+ async function bundleIssueReport(report, description, _title) {
8849
+ const LOG_TAIL_LINES = 200;
8850
+ const logLines = report.logFile.exists ? readFileSync4(report.logFile.path, "utf-8").split(/\r?\n/) : [];
8851
+ const recentLog = sanitizeLogContent(logLines.slice(-LOG_TAIL_LINES).join(`
8852
+ `)).trim();
8853
+ const configBody = JSON.stringify(report.magicContextConfig.flags, null, 2);
8854
+ const sanitizedConfigPath = report.configPaths.magicContextConfig.replace(homedir4(), "~");
8855
+ const bodyMarkdown = [
8856
+ "## Description",
8857
+ description,
8858
+ "",
8859
+ "## Environment",
8860
+ `- Plugin: v${report.pluginVersion}`,
8861
+ `- OS: ${report.platform} ${report.arch}`,
8862
+ `- Node: ${report.nodeVersion}`,
8863
+ `- OpenCode: ${report.opencodeVersion ?? "not installed"}`,
8864
+ "",
8865
+ "## Configuration",
8866
+ `Config from \`${sanitizedConfigPath}\`:`,
8867
+ "```jsonc",
8868
+ configBody,
8869
+ "```",
8870
+ "",
8871
+ "## Diagnostics",
8872
+ renderDiagnosticsMarkdown(report),
8873
+ "",
8874
+ `## Log (last ${LOG_TAIL_LINES} lines, sanitized)`,
8875
+ "```",
8876
+ recentLog || "<no log output>",
8877
+ "```"
8878
+ ].join(`
8879
+ `);
8880
+ const path2 = join8(process.cwd(), `magic-context-issue-${formatTimestamp(new Date)}.md`);
8881
+ writeFileSync3(path2, `${bodyMarkdown}
8882
+ `);
8883
+ return { path: path2, bodyMarkdown };
8884
+ }
8885
+
8555
8886
  // ../../node_modules/.bun/@clack+core@1.1.0/node_modules/@clack/core/dist/index.mjs
8556
8887
  var import_sisteransi = __toESM(require_src3(), 1);
8557
8888
  import { styleText as D } from "node:util";
@@ -9100,6 +9431,27 @@ class Tt extends B {
9100
9431
  });
9101
9432
  }
9102
9433
  }
9434
+ class $t extends B {
9435
+ get userInputWithCursor() {
9436
+ if (this.state === "submit")
9437
+ return this.userInput;
9438
+ const e = this.userInput;
9439
+ if (this.cursor >= e.length)
9440
+ return `${this.userInput}█`;
9441
+ const s = e.slice(0, this.cursor), [i, ...r] = e.slice(this.cursor);
9442
+ return `${s}${D("inverse", i)}${r.join("")}`;
9443
+ }
9444
+ get cursor() {
9445
+ return this._cursor;
9446
+ }
9447
+ constructor(e) {
9448
+ super({ ...e, initialUserInput: e.initialUserInput ?? e.initialValue }), this.on("userInput", (s) => {
9449
+ this._setValue(s);
9450
+ }), this.on("finalize", () => {
9451
+ this.value || (this.value = e.defaultValue), this.value === undefined && (this.value = "");
9452
+ });
9453
+ }
9454
+ }
9103
9455
 
9104
9456
  // ../../node_modules/.bun/@clack+prompts@1.1.0/node_modules/@clack/prompts/dist/index.mjs
9105
9457
  import { styleText as t, stripVTControlCharacters as ue } from "node:util";
@@ -9568,6 +9920,35 @@ ${n}
9568
9920
  } }).prompt();
9569
9921
  };
9570
9922
  var Qe = `${t("gray", h)} `;
9923
+ var Zt = (e) => new $t({ validate: e.validate, placeholder: e.placeholder, defaultValue: e.defaultValue, initialValue: e.initialValue, output: e.output, signal: e.signal, input: e.input, render() {
9924
+ const r = e?.withGuide ?? _.withGuide, s = `${`${r ? `${t("gray", h)}
9925
+ ` : ""}${W2(this.state)} `}${e.message}
9926
+ `, i = e.placeholder ? t("inverse", e.placeholder[0]) + t("dim", e.placeholder.slice(1)) : t(["inverse", "hidden"], "_"), a = this.userInput ? this.userInputWithCursor : i, o = this.value ?? "";
9927
+ switch (this.state) {
9928
+ case "error": {
9929
+ const u = this.error ? ` ${t("yellow", this.error)}` : "", l = r ? `${t("yellow", h)} ` : "", n = r ? t("yellow", x2) : "";
9930
+ return `${s.trim()}
9931
+ ${l}${a}
9932
+ ${n}${u}
9933
+ `;
9934
+ }
9935
+ case "submit": {
9936
+ const u = o ? ` ${t("dim", o)}` : "", l = r ? t("gray", h) : "";
9937
+ return `${s}${l}${u}`;
9938
+ }
9939
+ case "cancel": {
9940
+ const u = o ? ` ${t(["strikethrough", "dim"], o)}` : "", l = r ? t("gray", h) : "";
9941
+ return `${s}${l}${u}${o.trim() ? `
9942
+ ${l}` : ""}`;
9943
+ }
9944
+ default: {
9945
+ const u = r ? `${t("cyan", h)} ` : "", l = r ? t("cyan", x2) : "";
9946
+ return `${s}${u}${a}
9947
+ ${l}
9948
+ `;
9949
+ }
9950
+ }
9951
+ } }).prompt();
9571
9952
 
9572
9953
  // src/cli/prompts.ts
9573
9954
  function handleCancel(value) {
@@ -9584,6 +9965,20 @@ async function confirm(message, defaultYes = true) {
9584
9965
  handleCancel(result);
9585
9966
  return result;
9586
9967
  }
9968
+ async function text(message, options = {}) {
9969
+ const result = await Zt({
9970
+ message,
9971
+ placeholder: options.placeholder,
9972
+ initialValue: options.initialValue,
9973
+ validate: options.validate ? (value) => {
9974
+ const str = typeof value === "string" ? value : "";
9975
+ const error = options.validate?.(str);
9976
+ return error ?? undefined;
9977
+ } : undefined
9978
+ });
9979
+ handleCancel(result);
9980
+ return result;
9981
+ }
9587
9982
  async function selectOne(message, options) {
9588
9983
  const result = await Jt({
9589
9984
  message,
@@ -9598,36 +9993,36 @@ async function selectOne(message, options) {
9598
9993
  }
9599
9994
 
9600
9995
  // src/cli/doctor.ts
9601
- var PLUGIN_NAME2 = "@cortexkit/opencode-magic-context";
9602
- var PLUGIN_ENTRY_WITH_VERSION = `${PLUGIN_NAME2}@latest`;
9603
- function getOpenCodeCacheDir() {
9996
+ var PLUGIN_NAME3 = "@cortexkit/opencode-magic-context";
9997
+ var PLUGIN_ENTRY_WITH_VERSION2 = `${PLUGIN_NAME3}@latest`;
9998
+ function getOpenCodeCacheDir2() {
9604
9999
  const xdgCache = process.env.XDG_CACHE_HOME;
9605
10000
  if (xdgCache)
9606
- return join7(xdgCache, "opencode");
10001
+ return join9(xdgCache, "opencode");
9607
10002
  const os2 = platform();
9608
10003
  if (os2 === "win32") {
9609
- const localAppData = process.env.LOCALAPPDATA ?? join7(homedir3(), "AppData", "Local");
9610
- return join7(localAppData, "opencode");
10004
+ const localAppData = process.env.LOCALAPPDATA ?? join9(homedir5(), "AppData", "Local");
10005
+ return join9(localAppData, "opencode");
9611
10006
  }
9612
- return join7(homedir3(), ".cache", "opencode");
10007
+ return join9(homedir5(), ".cache", "opencode");
9613
10008
  }
9614
10009
  async function clearPluginCache(force = false) {
9615
- const cacheDir = getOpenCodeCacheDir();
9616
- const pluginCacheDir = join7(cacheDir, "packages", PLUGIN_ENTRY_WITH_VERSION);
9617
- if (!existsSync5(pluginCacheDir)) {
10010
+ const cacheDir = getOpenCodeCacheDir2();
10011
+ const pluginCacheDir = join9(cacheDir, "packages", PLUGIN_ENTRY_WITH_VERSION2);
10012
+ if (!existsSync7(pluginCacheDir)) {
9618
10013
  return { action: "not_found", path: pluginCacheDir };
9619
10014
  }
9620
10015
  let cachedVersion;
9621
10016
  try {
9622
- const installedPkgPath = join7(pluginCacheDir, "node_modules", "@cortexkit", "opencode-magic-context", "package.json");
9623
- if (existsSync5(installedPkgPath)) {
9624
- const pkg = JSON.parse(readFileSync3(installedPkgPath, "utf-8"));
10017
+ const installedPkgPath = join9(pluginCacheDir, "node_modules", "@cortexkit", "opencode-magic-context", "package.json");
10018
+ if (existsSync7(installedPkgPath)) {
10019
+ const pkg = JSON.parse(readFileSync5(installedPkgPath, "utf-8"));
9625
10020
  if (typeof pkg?.version === "string") {
9626
10021
  cachedVersion = pkg.version;
9627
10022
  }
9628
10023
  }
9629
10024
  } catch {}
9630
- const require2 = createRequire2(import.meta.url);
10025
+ const require2 = createRequire3(import.meta.url);
9631
10026
  let selfVersion;
9632
10027
  for (const relPath of ["../../package.json", "../package.json"]) {
9633
10028
  try {
@@ -9657,7 +10052,85 @@ async function clearPluginCache(force = false) {
9657
10052
  return { action: "error", path: pluginCacheDir, error: msg };
9658
10053
  }
9659
10054
  }
10055
+ function isGhInstalled() {
10056
+ try {
10057
+ execSync2("gh --version", { stdio: "pipe" });
10058
+ return true;
10059
+ } catch {
10060
+ return false;
10061
+ }
10062
+ }
10063
+ function openBrowser(url) {
10064
+ try {
10065
+ if (process.platform === "darwin") {
10066
+ const child = spawnSync("open", [url], { stdio: "ignore" });
10067
+ if (child.status === 0)
10068
+ return;
10069
+ } else if (process.platform === "linux") {
10070
+ const child = spawnSync("xdg-open", [url], { stdio: "ignore" });
10071
+ if (child.status === 0)
10072
+ return;
10073
+ } else if (process.platform === "win32") {
10074
+ const child = spawnSync("cmd", ["/c", "start", "", url], { stdio: "ignore" });
10075
+ if (child.status === 0)
10076
+ return;
10077
+ }
10078
+ } catch {}
10079
+ }
10080
+ async function runIssueFlow() {
10081
+ Wt2("Magic Context Issue Report");
10082
+ const title = await text("Issue title", {
10083
+ placeholder: "Short summary of the problem",
10084
+ validate: (value) => value.trim() ? undefined : "Title is required"
10085
+ });
10086
+ const description = await text("Issue description", {
10087
+ placeholder: "Describe what happened, what you expected, and repro steps",
10088
+ validate: (value) => value.trim() ? undefined : "Description is required"
10089
+ });
10090
+ const s = be();
10091
+ s.start("Collecting diagnostics");
10092
+ try {
10093
+ const report = await collectDiagnostics();
10094
+ const bundled = await bundleIssueReport(report, description, title);
10095
+ s.stop(`Report written to ${bundled.path}`);
10096
+ const shouldSubmit = await confirm("Submit this issue on GitHub now?", true);
10097
+ if (shouldSubmit && isGhInstalled()) {
10098
+ const result = spawnSync("gh", [
10099
+ "issue",
10100
+ "create",
10101
+ "-R",
10102
+ "cortexkit/opencode-magic-context",
10103
+ "--title",
10104
+ title,
10105
+ "--body-file",
10106
+ bundled.path
10107
+ ], { encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] });
10108
+ if (result.status === 0) {
10109
+ R2.success(result.stdout.trim());
10110
+ Gt("Issue submitted — thanks for the report!");
10111
+ return 0;
10112
+ }
10113
+ R2.warn(result.stderr.trim() || "gh issue create failed");
10114
+ } else if (shouldSubmit && !isGhInstalled()) {
10115
+ R2.warn("gh CLI not found — falling back to browser");
10116
+ }
10117
+ const url = `https://github.com/cortexkit/opencode-magic-context/issues/new?title=${encodeURIComponent(title)}&template=bug_report.yml`;
10118
+ R2.info(`Open this URL and paste the contents of ${bundled.path} into the Diagnostics field:`);
10119
+ R2.info(url);
10120
+ openBrowser(url);
10121
+ Gt("Issue report ready");
10122
+ return 0;
10123
+ } catch (error) {
10124
+ s.stop("Diagnostic collection failed");
10125
+ R2.error(error instanceof Error ? error.message : String(error));
10126
+ Gt("Issue report failed");
10127
+ return 1;
10128
+ }
10129
+ }
9660
10130
  async function runDoctor(options = {}) {
10131
+ if (options.issue) {
10132
+ return runIssueFlow();
10133
+ }
9661
10134
  Wt2("Magic Context Doctor");
9662
10135
  let issues = 0;
9663
10136
  let fixed = 0;
@@ -9674,7 +10147,7 @@ async function runDoctor(options = {}) {
9674
10147
  } else {
9675
10148
  R2.success(`OpenCode config: ${paths.opencodeConfig}`);
9676
10149
  }
9677
- if (existsSync5(paths.magicContextConfig)) {
10150
+ if (existsSync7(paths.magicContextConfig)) {
9678
10151
  R2.success(`Magic Context config: ${paths.magicContextConfig}`);
9679
10152
  } else {
9680
10153
  R2.warn(`No magic-context.jsonc found — using defaults`);
@@ -9682,17 +10155,17 @@ async function runDoctor(options = {}) {
9682
10155
  }
9683
10156
  if (paths.opencodeConfigFormat !== "none") {
9684
10157
  try {
9685
- const raw = readFileSync3(paths.opencodeConfig, "utf-8");
9686
- const config = import_comment_json2.parse(raw);
10158
+ const raw = readFileSync5(paths.opencodeConfig, "utf-8");
10159
+ const config = import_comment_json3.parse(raw);
9687
10160
  const plugins = Array.isArray(config?.plugin) ? config.plugin : [];
9688
- const hasPlugin = plugins.some((p) => typeof p === "string" && (p === PLUGIN_NAME2 || p.startsWith(`${PLUGIN_NAME2}@`) || p.includes("opencode-magic-context")));
10161
+ const hasPlugin = plugins.some((p) => typeof p === "string" && (p === PLUGIN_NAME3 || p.startsWith(`${PLUGIN_NAME3}@`) || p.includes("opencode-magic-context")));
9689
10162
  const configName = paths.opencodeConfigFormat === "jsonc" ? "opencode.jsonc" : "opencode.json";
9690
10163
  if (hasPlugin) {
9691
10164
  R2.success(`Plugin registered in ${configName}`);
9692
10165
  } else {
9693
- const updatedPlugins = [...plugins, PLUGIN_ENTRY_WITH_VERSION];
10166
+ const updatedPlugins = [...plugins, PLUGIN_ENTRY_WITH_VERSION2];
9694
10167
  config.plugin = updatedPlugins;
9695
- writeFileSync3(paths.opencodeConfig, `${import_comment_json2.stringify(config, null, 2)}
10168
+ writeFileSync4(paths.opencodeConfig, `${import_comment_json3.stringify(config, null, 2)}
9696
10169
  `);
9697
10170
  R2.success(`Added plugin to ${configName}`);
9698
10171
  fixed++;
@@ -9725,16 +10198,16 @@ async function runDoctor(options = {}) {
9725
10198
  R2.warn("Restart OpenCode to see the sidebar");
9726
10199
  fixed++;
9727
10200
  } else {
9728
- if (existsSync5(paths.tuiConfig)) {
10201
+ if (existsSync7(paths.tuiConfig)) {
9729
10202
  R2.success("TUI sidebar plugin configured");
9730
10203
  } else {
9731
10204
  R2.success("TUI sidebar plugin configured (tui.json created)");
9732
10205
  }
9733
10206
  }
9734
- if (existsSync5(paths.magicContextConfig)) {
10207
+ if (existsSync7(paths.magicContextConfig)) {
9735
10208
  try {
9736
- const mcRaw = readFileSync3(paths.magicContextConfig, "utf-8");
9737
- const mcConfig = import_comment_json2.parse(mcRaw);
10209
+ const mcRaw = readFileSync5(paths.magicContextConfig, "utf-8");
10210
+ const mcConfig = import_comment_json3.parse(mcRaw);
9738
10211
  const userMemObj = mcConfig?.experimental?.user_memories;
9739
10212
  const userMemEnabled = userMemObj?.enabled === true;
9740
10213
  const dreamerObj = mcConfig?.dreamer;
@@ -9760,20 +10233,20 @@ async function runDoctor(options = {}) {
9760
10233
  } else {
9761
10234
  R2.success("Plugin cache clean (no cached version found)");
9762
10235
  }
9763
- const logPath = join7(tmpdir2(), "magic-context.log");
9764
- if (existsSync5(logPath)) {
9765
- const logStat = statSync(logPath);
10236
+ const logPath = join9(tmpdir3(), "magic-context.log");
10237
+ if (existsSync7(logPath)) {
10238
+ const logStat = statSync2(logPath);
9766
10239
  const sizeKb = (logStat.size / 1024).toFixed(0);
9767
10240
  R2.info(`Log file: ${logPath} (${sizeKb} KB)`);
9768
10241
  } else {
9769
10242
  R2.info(`Log file: ${logPath} (not yet created)`);
9770
10243
  }
9771
- const historianDumpDir = join7(tmpdir2(), "magic-context-historian");
9772
- if (existsSync5(historianDumpDir)) {
10244
+ const historianDumpDir = join9(tmpdir3(), "magic-context-historian");
10245
+ if (existsSync7(historianDumpDir)) {
9773
10246
  try {
9774
- const dumps = readdirSync(historianDumpDir).filter((f) => f.endsWith(".xml")).map((f) => ({
10247
+ const dumps = readdirSync2(historianDumpDir).filter((f) => f.endsWith(".xml")).map((f) => ({
9775
10248
  name: f,
9776
- mtime: statSync(join7(historianDumpDir, f)).mtimeMs
10249
+ mtime: statSync2(join9(historianDumpDir, f)).mtimeMs
9777
10250
  })).sort((a, b) => b.mtime - a.mtime);
9778
10251
  if (dumps.length > 0) {
9779
10252
  R2.warn(`Historian debug dumps: ${dumps.length} file(s) in ${historianDumpDir}`);
@@ -9806,20 +10279,20 @@ async function runDoctor(options = {}) {
9806
10279
  }
9807
10280
 
9808
10281
  // src/cli/setup.ts
9809
- var import_comment_json3 = __toESM(require_src2(), 1);
9810
- import { existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "node:fs";
10282
+ var import_comment_json4 = __toESM(require_src2(), 1);
10283
+ import { existsSync as existsSync8, mkdirSync as mkdirSync3, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "node:fs";
9811
10284
  import { dirname as dirname3 } from "node:path";
9812
- var PLUGIN_NAME3 = "@cortexkit/opencode-magic-context";
10285
+ var PLUGIN_NAME4 = "@cortexkit/opencode-magic-context";
9813
10286
  var PLUGIN_ENTRY2 = "@cortexkit/opencode-magic-context@latest";
9814
10287
  function ensureDir(dir) {
9815
- if (!existsSync6(dir)) {
10288
+ if (!existsSync8(dir)) {
9816
10289
  mkdirSync3(dir, { recursive: true });
9817
10290
  }
9818
10291
  }
9819
10292
  function readJsonc(path2) {
9820
- const content = readFileSync4(path2, "utf-8");
10293
+ const content = readFileSync6(path2, "utf-8");
9821
10294
  try {
9822
- return import_comment_json3.parse(content);
10295
+ return import_comment_json4.parse(content);
9823
10296
  } catch (err) {
9824
10297
  console.error(` ⚠ Failed to parse ${path2}: ${err instanceof Error ? err.message : err}`);
9825
10298
  return null;
@@ -9832,7 +10305,7 @@ function addPluginToOpenCodeConfig(configPath, format) {
9832
10305
  plugin: [PLUGIN_ENTRY2],
9833
10306
  compaction: { auto: false, prune: false }
9834
10307
  };
9835
- writeFileSync4(configPath, `${import_comment_json3.stringify(config, null, 2)}
10308
+ writeFileSync5(configPath, `${import_comment_json4.stringify(config, null, 2)}
9836
10309
  `);
9837
10310
  return;
9838
10311
  }
@@ -9842,7 +10315,7 @@ function addPluginToOpenCodeConfig(configPath, format) {
9842
10315
  return;
9843
10316
  }
9844
10317
  const plugins = existing.plugin ?? [];
9845
- const hasPlugin = plugins.some((p) => p === PLUGIN_NAME3 || p.startsWith(`${PLUGIN_NAME3}@`));
10318
+ const hasPlugin = plugins.some((p) => p === PLUGIN_NAME4 || p.startsWith(`${PLUGIN_NAME4}@`));
9846
10319
  if (!hasPlugin) {
9847
10320
  plugins.push(PLUGIN_ENTRY2);
9848
10321
  }
@@ -9851,13 +10324,13 @@ function addPluginToOpenCodeConfig(configPath, format) {
9851
10324
  compaction.auto = false;
9852
10325
  compaction.prune = false;
9853
10326
  existing.compaction = compaction;
9854
- writeFileSync4(configPath, `${import_comment_json3.stringify(existing, null, 2)}
10327
+ writeFileSync5(configPath, `${import_comment_json4.stringify(existing, null, 2)}
9855
10328
  `);
9856
10329
  }
9857
10330
  function addPluginToTuiConfig(configPath, format) {
9858
10331
  ensureDir(dirname3(configPath));
9859
10332
  if (format === "none") {
9860
- writeFileSync4(configPath, `${import_comment_json3.stringify({ plugin: [PLUGIN_ENTRY2] }, null, 2)}
10333
+ writeFileSync5(configPath, `${import_comment_json4.stringify({ plugin: [PLUGIN_ENTRY2] }, null, 2)}
9861
10334
  `);
9862
10335
  return;
9863
10336
  }
@@ -9867,16 +10340,16 @@ function addPluginToTuiConfig(configPath, format) {
9867
10340
  return;
9868
10341
  }
9869
10342
  const plugins = existing.plugin ?? [];
9870
- const hasPlugin = plugins.some((p) => p === PLUGIN_NAME3 || p.startsWith(`${PLUGIN_NAME3}@`));
10343
+ const hasPlugin = plugins.some((p) => p === PLUGIN_NAME4 || p.startsWith(`${PLUGIN_NAME4}@`));
9871
10344
  if (!hasPlugin) {
9872
10345
  plugins.push(PLUGIN_ENTRY2);
9873
10346
  }
9874
10347
  existing.plugin = plugins;
9875
- writeFileSync4(configPath, `${import_comment_json3.stringify(existing, null, 2)}
10348
+ writeFileSync5(configPath, `${import_comment_json4.stringify(existing, null, 2)}
9876
10349
  `);
9877
10350
  }
9878
10351
  function writeMagicContextConfig(configPath, options) {
9879
- const config = (existsSync6(configPath) ? readJsonc(configPath) : null) ?? {};
10352
+ const config = (existsSync8(configPath) ? readJsonc(configPath) : null) ?? {};
9880
10353
  if (!config.$schema) {
9881
10354
  config.$schema = "https://raw.githubusercontent.com/cortexkit/opencode-magic-context/master/assets/magic-context.schema.json";
9882
10355
  }
@@ -9913,7 +10386,7 @@ function writeMagicContextConfig(configPath, options) {
9913
10386
  cacheTtl["anthropic/claude-opus-4-6"] = "59m";
9914
10387
  config.cache_ttl = cacheTtl;
9915
10388
  }
9916
- writeFileSync4(configPath, `${import_comment_json3.stringify(config, null, 2)}
10389
+ writeFileSync5(configPath, `${import_comment_json4.stringify(config, null, 2)}
9917
10390
  `);
9918
10391
  }
9919
10392
  async function runSetup() {
@@ -9942,7 +10415,7 @@ async function runSetup() {
9942
10415
  R2.warn("You can configure models manually in magic-context.jsonc later");
9943
10416
  }
9944
10417
  const paths = detectConfigPaths();
9945
- const hadExistingSetup = paths.opencodeConfigFormat !== "none" || existsSync6(paths.magicContextConfig) || paths.tuiConfigFormat !== "none";
10418
+ const hadExistingSetup = paths.opencodeConfigFormat !== "none" || existsSync8(paths.magicContextConfig) || paths.tuiConfigFormat !== "none";
9946
10419
  addPluginToOpenCodeConfig(paths.opencodeConfig, paths.opencodeConfigFormat);
9947
10420
  R2.success(`Plugin added to ${paths.opencodeConfig}`);
9948
10421
  R2.info("Disabled built-in compaction (auto=false, prune=false)");
@@ -9960,7 +10433,7 @@ async function runSetup() {
9960
10433
  if (shouldRemove) {
9961
10434
  plugins.splice(dcpIndex, 1);
9962
10435
  ocConfig.plugin = plugins;
9963
- writeFileSync4(paths.opencodeConfig, `${import_comment_json3.stringify(ocConfig, null, 2)}
10436
+ writeFileSync5(paths.opencodeConfig, `${import_comment_json4.stringify(ocConfig, null, 2)}
9964
10437
  `);
9965
10438
  R2.success("Removed opencode-dcp from plugin list");
9966
10439
  } else {
@@ -10076,7 +10549,7 @@ async function runSetup() {
10076
10549
  }
10077
10550
  }
10078
10551
  const summary = [
10079
- `Plugin: ${PLUGIN_NAME3}`,
10552
+ `Plugin: ${PLUGIN_NAME4}`,
10080
10553
  "Compaction: disabled",
10081
10554
  historianModel ? `Historian: ${historianModel}` : "Historian: fallback chain",
10082
10555
  dreamerEnabled ? `Dreamer: enabled${dreamerModel ? ` (${dreamerModel})` : ""}` : "Dreamer: disabled",
@@ -10087,8 +10560,8 @@ async function runSetup() {
10087
10560
  const shouldStar = await confirm("★ Star the repo on GitHub?", true);
10088
10561
  if (shouldStar) {
10089
10562
  try {
10090
- const { execSync: execSync2 } = await import("node:child_process");
10091
- execSync2("gh api --silent --method PUT /user/starred/cortexkit/opencode-magic-context", { stdio: "ignore", timeout: 1e4 });
10563
+ const { execSync: execSync3 } = await import("node:child_process");
10564
+ execSync3("gh api --silent --method PUT /user/starred/cortexkit/opencode-magic-context", { stdio: "ignore", timeout: 1e4 });
10092
10565
  R2.success("Thanks for starring! ★");
10093
10566
  } catch {
10094
10567
  R2.info(`Couldn't star automatically. You can star manually:
@@ -10105,7 +10578,8 @@ if (command === "setup") {
10105
10578
  runSetup().then((code) => process.exit(code));
10106
10579
  } else if (command === "doctor") {
10107
10580
  const force = process.argv.includes("--force");
10108
- runDoctor({ force }).then((code) => process.exit(code));
10581
+ const issue = process.argv.includes("--issue");
10582
+ runDoctor({ force, issue }).then((code) => process.exit(code));
10109
10583
  } else {
10110
10584
  console.log("");
10111
10585
  console.log(" Magic Context CLI");
@@ -10115,10 +10589,12 @@ if (command === "setup") {
10115
10589
  console.log(" setup Interactive setup wizard (first-time install)");
10116
10590
  console.log(" doctor Check and fix configuration issues");
10117
10591
  console.log(" doctor --force Force clear plugin cache (fixes broken dependencies)");
10592
+ console.log(" doctor --issue Collect diagnostics and open a GitHub issue");
10118
10593
  console.log("");
10119
10594
  console.log(" Usage:");
10120
10595
  console.log(" bunx @cortexkit/opencode-magic-context@latest setup");
10121
10596
  console.log(" bunx @cortexkit/opencode-magic-context@latest doctor");
10597
+ console.log(" bunx @cortexkit/opencode-magic-context@latest doctor --issue");
10122
10598
  console.log("");
10123
10599
  process.exit(command ? 1 : 0);
10124
10600
  }
@@ -1 +1 @@
1
- {"version":3,"file":"embedding-local.d.ts","sourceRoot":"","sources":["../../../../src/features/magic-context/memory/embedding-local.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAqG9D,qBAAa,sBAAuB,YAAW,iBAAiB;IAC5D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAkC;IAClD,OAAO,CAAC,WAAW,CAA8B;gBAErC,KAAK,SAAgC;IAK3C,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC;IA+C9B,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAyBjD,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,YAAY,GAAG,IAAI,CAAC,EAAE,CAAC;IA6B7D,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAqB9B,QAAQ,IAAI,OAAO;CAGtB"}
1
+ {"version":3,"file":"embedding-local.d.ts","sourceRoot":"","sources":["../../../../src/features/magic-context/memory/embedding-local.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAyH9D,qBAAa,sBAAuB,YAAW,iBAAiB;IAC5D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAkC;IAClD,OAAO,CAAC,WAAW,CAA8B;gBAErC,KAAK,SAAgC;IAK3C,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC;IA+E9B,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAyBjD,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,YAAY,GAAG,IAAI,CAAC,EAAE,CAAC;IA6B7D,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAqB9B,QAAQ,IAAI,OAAO;CAGtB"}
@@ -1 +1 @@
1
- {"version":3,"file":"strip-content.d.ts","sourceRoot":"","sources":["../../../src/hooks/magic-context/strip-content.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAwBpE;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CACvC,QAAQ,EAAE,WAAW,EAAE,EACvB,kBAAkB,EAAE,MAAM,GAC3B,MAAM,CAiDR;AAkBD;;;;GAIG;AACH,wBAAgB,+BAA+B,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,MAAM,CAiE/E;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAClC,QAAQ,EAAE,WAAW,EAAE,EACvB,kBAAkB,EAAE,GAAG,CAAC,WAAW,EAAE,gBAAgB,EAAE,CAAC,EACxD,iBAAiB,EAAE,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,EAC3C,kBAAkB,EAAE,MAAM,GAC3B,MAAM,CAuBR;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CACxC,QAAQ,EAAE,WAAW,EAAE,EACvB,iBAAiB,EAAE,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,EAC3C,kBAAkB,EAAE,MAAM,GAC3B,MAAM,CAmBR;AAED,wBAAgB,iBAAiB,CAC7B,QAAQ,EAAE,WAAW,EAAE,EACvB,kBAAkB,EAAE,GAAG,CAAC,WAAW,EAAE,gBAAgB,EAAE,CAAC,EACxD,iBAAiB,EAAE,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,EAC3C,iBAAiB,EAAE,MAAM,GAC1B,MAAM,CA2BR;AAYD,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,MAAM,CAuBrE;AAID,wBAAgB,mBAAmB,CAC/B,QAAQ,EAAE,WAAW,EAAE,EACvB,iBAAiB,EAAE,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,EAC3C,iBAAiB,EAAE,MAAM,GAC1B,MAAM,CAsBR;AAED,wBAAgB,oBAAoB,CAChC,QAAQ,EAAE,WAAW,EAAE,EACvB,SAAS,EAAE,MAAM,EACjB,iBAAiB,EAAE,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,GAC5C,MAAM,CAsBR;AAED,wBAAgB,oBAAoB,CAChC,QAAQ,EAAE,WAAW,EAAE,EACvB,SAAS,EAAE,MAAM,EACjB,iBAAiB,EAAE,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,GAC5C,MAAM,CAuCR"}
1
+ {"version":3,"file":"strip-content.d.ts","sourceRoot":"","sources":["../../../src/hooks/magic-context/strip-content.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAwBpE;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CACvC,QAAQ,EAAE,WAAW,EAAE,EACvB,kBAAkB,EAAE,MAAM,GAC3B,MAAM,CAiDR;AAkBD;;;;GAIG;AACH,wBAAgB,+BAA+B,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,MAAM,CAiE/E;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAClC,QAAQ,EAAE,WAAW,EAAE,EACvB,kBAAkB,EAAE,GAAG,CAAC,WAAW,EAAE,gBAAgB,EAAE,CAAC,EACxD,iBAAiB,EAAE,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,EAC3C,kBAAkB,EAAE,MAAM,GAC3B,MAAM,CAuBR;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CACxC,QAAQ,EAAE,WAAW,EAAE,EACvB,iBAAiB,EAAE,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,EAC3C,kBAAkB,EAAE,MAAM,GAC3B,MAAM,CAmBR;AAED,wBAAgB,iBAAiB,CAC7B,QAAQ,EAAE,WAAW,EAAE,EACvB,kBAAkB,EAAE,GAAG,CAAC,WAAW,EAAE,gBAAgB,EAAE,CAAC,EACxD,iBAAiB,EAAE,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,EAC3C,iBAAiB,EAAE,MAAM,GAC1B,MAAM,CA2BR;AAYD,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,MAAM,CAgCrE;AAID,wBAAgB,mBAAmB,CAC/B,QAAQ,EAAE,WAAW,EAAE,EACvB,iBAAiB,EAAE,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,EAC3C,iBAAiB,EAAE,MAAM,GAC1B,MAAM,CAsBR;AAED,wBAAgB,oBAAoB,CAChC,QAAQ,EAAE,WAAW,EAAE,EACvB,SAAS,EAAE,MAAM,EACjB,iBAAiB,EAAE,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,GAC5C,MAAM,CAsBR;AAED,wBAAgB,oBAAoB,CAChC,QAAQ,EAAE,WAAW,EAAE,EACvB,SAAS,EAAE,MAAM,EACjB,iBAAiB,EAAE,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,GAC5C,MAAM,CAuCR"}
package/dist/index.js CHANGED
@@ -16182,6 +16182,13 @@ async function withQuietConsole(fn) {
16182
16182
  console.error = origError;
16183
16183
  }
16184
16184
  }
16185
+ function isTransientLoadError(error48) {
16186
+ const message = error48 instanceof Error ? error48.message : String(error48 ?? "");
16187
+ if (!message)
16188
+ return false;
16189
+ const lower = message.toLowerCase();
16190
+ return lower.includes("protobuf parsing failed") || lower.includes("unable to get model file path or buffer") || lower.includes("ebusy") || lower.includes("resource busy") || lower.includes("resource temporarily unavailable");
16191
+ }
16185
16192
  function isArrayLikeNumber(value) {
16186
16193
  if (typeof value !== "object" || value === null || !("length" in value)) {
16187
16194
  return false;
@@ -16244,11 +16251,31 @@ class LocalEmbeddingProvider {
16244
16251
  env.logLevel = LogLevel.ERROR;
16245
16252
  }
16246
16253
  const createPipeline = transformersModule.pipeline;
16247
- this.pipeline = await withQuietConsole(() => createPipeline("feature-extraction", this.model, {
16248
- quantized: true,
16249
- dtype: "fp32"
16250
- }));
16251
- log(`[magic-context] embedding model loaded: ${this.model}`);
16254
+ const MAX_ATTEMPTS = 3;
16255
+ let lastError;
16256
+ for (let attempt = 1;attempt <= MAX_ATTEMPTS; attempt++) {
16257
+ try {
16258
+ this.pipeline = await withQuietConsole(() => createPipeline("feature-extraction", this.model, {
16259
+ quantized: true,
16260
+ dtype: "fp32"
16261
+ }));
16262
+ lastError = undefined;
16263
+ break;
16264
+ } catch (error48) {
16265
+ lastError = error48;
16266
+ if (!isTransientLoadError(error48) || attempt === MAX_ATTEMPTS) {
16267
+ break;
16268
+ }
16269
+ const delayMs = 300 * attempt + Math.floor(Math.random() * 200);
16270
+ log(`[magic-context] embedding model load attempt ${attempt}/${MAX_ATTEMPTS} failed transiently, retrying in ${delayMs}ms`);
16271
+ await new Promise((resolve2) => setTimeout(resolve2, delayMs));
16272
+ }
16273
+ }
16274
+ if (this.pipeline) {
16275
+ log(`[magic-context] embedding model loaded: ${this.model}`);
16276
+ } else {
16277
+ throw lastError ?? new Error("unknown embedding load failure");
16278
+ }
16252
16279
  } catch (error48) {
16253
16280
  log("[magic-context] embedding model failed to load:", error48);
16254
16281
  this.pipeline = null;
@@ -31788,7 +31815,7 @@ function findMaxTag(messageTagNumbers) {
31788
31815
  }
31789
31816
  return max;
31790
31817
  }
31791
- var CLEARED_REASONING_TYPES = new Set(["thinking", "reasoning", "redacted_thinking"]);
31818
+ var CLEARED_REASONING_TYPES = new Set(["thinking", "reasoning"]);
31792
31819
  function stripClearedReasoning(messages) {
31793
31820
  let stripped = 0;
31794
31821
  for (const message of messages) {
@@ -31801,6 +31828,8 @@ function stripClearedReasoning(messages) {
31801
31828
  const partType = part.type;
31802
31829
  if (!CLEARED_REASONING_TYPES.has(partType))
31803
31830
  return true;
31831
+ if (!("thinking" in part) && !("text" in part))
31832
+ return true;
31804
31833
  const thinking = "thinking" in part ? part.thinking : undefined;
31805
31834
  const text = "text" in part ? part.text : undefined;
31806
31835
  return thinking !== undefined && thinking !== "[cleared]" || text !== undefined && text !== "[cleared]";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/opencode-magic-context",
3
- "version": "0.8.6",
3
+ "version": "0.8.7",
4
4
  "type": "module",
5
5
  "description": "OpenCode plugin for Magic Context — cross-session memory and context management",
6
6
  "main": "dist/index.js",