@cortexkit/opencode-magic-context 0.14.2 → 0.15.1

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.
Files changed (45) hide show
  1. package/dist/cli/diagnostics.d.ts.map +1 -1
  2. package/dist/cli/doctor.d.ts.map +1 -1
  3. package/dist/cli.js +71 -82
  4. package/dist/config/schema/magic-context.d.ts +26 -0
  5. package/dist/config/schema/magic-context.d.ts.map +1 -1
  6. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  7. package/dist/features/magic-context/storage-tags.d.ts +8 -0
  8. package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
  9. package/dist/features/magic-context/storage.d.ts +1 -1
  10. package/dist/features/magic-context/storage.d.ts.map +1 -1
  11. package/dist/features/magic-context/tool-definition-tokens.d.ts +45 -0
  12. package/dist/features/magic-context/tool-definition-tokens.d.ts.map +1 -0
  13. package/dist/features/magic-context/types.d.ts +8 -0
  14. package/dist/features/magic-context/types.d.ts.map +1 -1
  15. package/dist/hooks/magic-context/caveman-cleanup.d.ts +86 -0
  16. package/dist/hooks/magic-context/caveman-cleanup.d.ts.map +1 -0
  17. package/dist/hooks/magic-context/heuristic-cleanup.d.ts +8 -0
  18. package/dist/hooks/magic-context/heuristic-cleanup.d.ts.map +1 -1
  19. package/dist/hooks/magic-context/hook.d.ts +4 -0
  20. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  21. package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
  22. package/dist/hooks/magic-context/tag-messages.d.ts +13 -1
  23. package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
  24. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +9 -0
  25. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  26. package/dist/hooks/magic-context/transform.d.ts +19 -0
  27. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +3624 -3395
  30. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  31. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  32. package/dist/shared/data-path.d.ts +12 -0
  33. package/dist/shared/data-path.d.ts.map +1 -1
  34. package/dist/shared/models-dev-cache.d.ts.map +1 -1
  35. package/dist/shared/rpc-types.d.ts +15 -5
  36. package/dist/shared/rpc-types.d.ts.map +1 -1
  37. package/dist/tui/data/context-db.d.ts.map +1 -1
  38. package/package.json +1 -1
  39. package/src/shared/data-path.test.ts +69 -0
  40. package/src/shared/data-path.ts +18 -0
  41. package/src/shared/models-dev-cache.ts +5 -10
  42. package/src/shared/rpc-types.ts +15 -5
  43. package/src/tui/data/context-db.ts +1 -0
  44. package/src/tui/index.tsx +13 -4
  45. package/src/tui/slots/sidebar-content.tsx +33 -11
@@ -1 +1 @@
1
- {"version":3,"file":"create-session-hooks.d.ts","sourceRoot":"","sources":["../../../src/plugin/hooks/create-session-hooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAU7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8CAA8C,CAAC;AACrF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE9C,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACrC,GAAG,EAAE,aAAa,CAAC;IACnB,YAAY,EAAE,wBAAwB,CAAC;IACvC,gBAAgB,EAAE,gBAAgB,CAAC;CACtC;;;;;;qBAmD4gD,CAAC;;;;;;;;;;;;qBAbz+C,CAAC;mBAAyB,CAAC;iBAChD,CAAX;iBAAuB,CAAC;0BAAc,CAAC;uBAAiB,CAAC;;;;;;0BAYokmB,CAAC;;;;;;EADlomB"}
1
+ {"version":3,"file":"create-session-hooks.d.ts","sourceRoot":"","sources":["../../../src/plugin/hooks/create-session-hooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAU7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8CAA8C,CAAC;AACrF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE9C,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACrC,GAAG,EAAE,aAAa,CAAC;IACnB,YAAY,EAAE,wBAAwB,CAAC;IACvC,gBAAgB,EAAE,gBAAgB,CAAC;CACtC;;;;;;qBAmD4gD,CAAC;;;;;;;;;;;;qBAbz+C,CAAC;mBAAyB,CAAC;iBAChD,CAAX;iBAAuB,CAAC;0BAAc,CAAC;uBAAiB,CAAC;;;;;;0BAYi0nB,CAAC;;;;;;EAD/3nB"}
@@ -1 +1 @@
1
- {"version":3,"file":"rpc-handlers.d.ts","sourceRoot":"","sources":["../../src/plugin/rpc-handlers.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAKzE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2CAA2C,CAAC;AAIlF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAsclE;;GAEG;AACH,wBAAgB,mBAAmB,CAC/B,SAAS,EAAE,qBAAqB,EAChC,IAAI,EAAE;IACF,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,MAAM,EAAE,OAAO,CAAC;IAChB,gBAAgB,EAAE,gBAAgB,CAAC;CACtC,GACF,IAAI,CAqGN"}
1
+ {"version":3,"file":"rpc-handlers.d.ts","sourceRoot":"","sources":["../../src/plugin/rpc-handlers.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAMzE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2CAA2C,CAAC;AAIlF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AA0elE;;GAEG;AACH,wBAAgB,mBAAmB,CAC/B,SAAS,EAAE,qBAAqB,EAChC,IAAI,EAAE;IACF,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,MAAM,EAAE,OAAO,CAAC;IAChB,gBAAgB,EAAE,gBAAgB,CAAC;CACtC,GACF,IAAI,CA4GN"}
@@ -1,3 +1,15 @@
1
1
  export declare function getDataDir(): string;
2
2
  export declare function getOpenCodeStorageDir(): string;
3
+ /**
4
+ * Resolve OpenCode's cache base directory.
5
+ *
6
+ * OpenCode uses the `xdg-basedir` package, which — on every platform, including
7
+ * Windows — falls back to `<homedir>/.cache` when `XDG_CACHE_HOME` is unset.
8
+ * A previous Windows-specific branch that resolved to `%LOCALAPPDATA%` did not
9
+ * match OpenCode's own resolution and caused `doctor --force` to target a
10
+ * non-existent directory, leaving the real cache at `C:\Users\<user>\.cache`
11
+ * untouched.
12
+ */
13
+ export declare function getCacheDir(): string;
14
+ export declare function getOpenCodeCacheDir(): string;
3
15
  //# sourceMappingURL=data-path.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"data-path.d.ts","sourceRoot":"","sources":["../../src/shared/data-path.ts"],"names":[],"mappings":"AAGA,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C"}
1
+ {"version":3,"file":"data-path.d.ts","sourceRoot":"","sources":["../../src/shared/data-path.ts"],"names":[],"mappings":"AAGA,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED;;;;;;;;;GASG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C"}
@@ -1 +1 @@
1
- {"version":3,"file":"models-dev-cache.d.ts","sourceRoot":"","sources":["../../src/shared/models-dev-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAQH,UAAU,kBAAkB;IACxB,MAAM,EAAE;QACJ,SAAS,EAAE,MAAM,OAAO,CAAC;YAAE,IAAI,CAAC,EAAE;gBAAE,SAAS,CAAC,EAAE,OAAO,CAAA;aAAE,CAAA;SAAE,CAAC,CAAC;KAChE,CAAC;CACL;AA2ND;;;;;;;;;;GAUG;AACH,wBAAsB,yBAAyB,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkDzF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAchG;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CACxC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,GAChB,MAAM,GAAG,SAAS,CAkBpB;AAED,4CAA4C;AAC5C,wBAAgB,mBAAmB,IAAI,IAAI,CAK1C;AAED,oDAAoD;AACpD,wBAAgB,sBAAsB,IAAI;IACtC,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACrB,CAOA"}
1
+ {"version":3,"file":"models-dev-cache.d.ts","sourceRoot":"","sources":["../../src/shared/models-dev-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AASH,UAAU,kBAAkB;IACxB,MAAM,EAAE;QACJ,SAAS,EAAE,MAAM,OAAO,CAAC;YAAE,IAAI,CAAC,EAAE;gBAAE,SAAS,CAAC,EAAE,OAAO,CAAA;aAAE,CAAA;SAAE,CAAC,CAAC;KAChE,CAAC;CACL;AAqND;;;;;;;;;;GAUG;AACH,wBAAsB,yBAAyB,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkDzF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAchG;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CACxC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,GAChB,MAAM,GAAG,SAAS,CAkBpB;AAED,4CAA4C;AAC5C,wBAAgB,mBAAmB,IAAI,IAAI,CAK1C;AAED,oDAAoD;AACpD,wBAAgB,sBAAsB,IAAI;IACtC,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACrB,CAOA"}
@@ -35,13 +35,23 @@ export interface SidebarSnapshot {
35
35
  */
36
36
  toolCallTokens: number;
37
37
  /**
38
- * Token estimate of tool schemas OpenCode sends alongside in the request
39
- * `tools` parameter (bash, edit, grep, MCP servers, ctx_* tools, etc.).
40
- * Computed as inputTokens systemPromptTokens messagesBlock −
41
- * toolCallTokens and clamped to 0. Display layer shows this as
42
- * "Tool Definitions". Includes tokenizer imprecision residual.
38
+ * Measured token cost of tool schemas (description + JSON-schema
39
+ * parameters) OpenCode sends in the request `tools` parameter. Populated
40
+ * by the `tool.definition` plugin hook, keyed by
41
+ * `{providerID, modelID, agentName}`. Zero until the first turn after
42
+ * plugin startup measures the current agent's tool set. Display layer
43
+ * shows this as "Tool Definitions".
43
44
  */
44
45
  toolDefinitionTokens: number;
46
+ /**
47
+ * Residual catch-all: provider-side wrapping not captured elsewhere —
48
+ * the JSON envelope around the `tools` array, tool-choice fields,
49
+ * provider-specific cache-control markers, tokenizer imprecision, etc.
50
+ * Computed as `inputTokens − systemPromptTokens − messagesBlock −
51
+ * toolCallTokens − toolDefinitionTokens` and clamped to ≥ 0. Display
52
+ * layer shows this as "Overhead".
53
+ */
54
+ overheadTokens: number;
45
55
  }
46
56
  export interface StatusDetail extends SidebarSnapshot {
47
57
  tagCounter: number;
@@ -1 +1 @@
1
- {"version":3,"file":"rpc-types.d.ts","sourceRoot":"","sources":["../../src/shared/rpc-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,eAAe;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,kBAAkB,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB;;;;;;OAMG;IACH,oBAAoB,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,YAAa,SAAQ,eAAe;IACjD,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,OAAO,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,oBAAoB,EAAE,YAAY,GAAG,QAAQ,CAAC;IAC9C;;;OAGG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,uBAAuB,EAAE,MAAM,CAAC;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED,MAAM,WAAW,sBAAsB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB"}
1
+ {"version":3,"file":"rpc-types.d.ts","sourceRoot":"","sources":["../../src/shared/rpc-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,eAAe;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,kBAAkB,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB;;;;;;;OAOG;IACH,oBAAoB,EAAE,MAAM,CAAC;IAC7B;;;;;;;OAOG;IACH,cAAc,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,YAAa,SAAQ,eAAe;IACjD,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,OAAO,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,oBAAoB,EAAE,YAAY,GAAG,QAAQ,CAAC;IAC9C;;;OAGG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,uBAAuB,EAAE,MAAM,CAAC;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED,MAAM,WAAW,sBAAsB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB"}
@@ -1 +1 @@
1
- {"version":3,"file":"context-db.d.ts","sourceRoot":"","sources":["../../../src/tui/data/context-db.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAA0B,eAAe,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEpG,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC;AAS9C,2DAA2D;AAC3D,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAGrD;AAED,+BAA+B;AAC/B,wBAAgB,QAAQ,IAAI,IAAI,CAG/B;AA2BD,sDAAsD;AACtD,wBAAsB,mBAAmB,CACrC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAClB,OAAO,CAAC,eAAe,CAAC,CAc1B;AAED,wDAAwD;AACxD,wBAAsB,gBAAgB,CAClC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,YAAY,CAAC,CA4CvB;AAED,qCAAqC;AACrC,wBAAsB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAQ5E;AAED,6CAA6C;AAC7C,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQvE;AAED,MAAM,WAAW,UAAU;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,yDAAyD;AACzD,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAchE"}
1
+ {"version":3,"file":"context-db.d.ts","sourceRoot":"","sources":["../../../src/tui/data/context-db.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAA0B,eAAe,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEpG,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC;AAS9C,2DAA2D;AAC3D,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAGrD;AAED,+BAA+B;AAC/B,wBAAgB,QAAQ,IAAI,IAAI,CAG/B;AA4BD,sDAAsD;AACtD,wBAAsB,mBAAmB,CACrC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAClB,OAAO,CAAC,eAAe,CAAC,CAc1B;AAED,wDAAwD;AACxD,wBAAsB,gBAAgB,CAClC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,YAAY,CAAC,CA4CvB;AAED,qCAAqC;AACrC,wBAAsB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAQ5E;AAED,6CAA6C;AAC7C,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQvE;AAED,MAAM,WAAW,UAAU;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,yDAAyD;AACzD,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAchE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/opencode-magic-context",
3
- "version": "0.14.2",
3
+ "version": "0.15.1",
4
4
  "type": "module",
5
5
  "description": "OpenCode plugin for Magic Context — cross-session memory and context management",
6
6
  "main": "dist/index.js",
@@ -0,0 +1,69 @@
1
+ import { afterEach, beforeEach, describe, expect, test } from "bun:test";
2
+ import * as os from "node:os";
3
+ import * as path from "node:path";
4
+ import { getCacheDir, getDataDir, getOpenCodeCacheDir, getOpenCodeStorageDir } from "./data-path";
5
+
6
+ const savedEnv = {
7
+ XDG_CACHE_HOME: process.env.XDG_CACHE_HOME,
8
+ XDG_DATA_HOME: process.env.XDG_DATA_HOME,
9
+ LOCALAPPDATA: process.env.LOCALAPPDATA,
10
+ };
11
+
12
+ describe("data-path", () => {
13
+ beforeEach(() => {
14
+ process.env.XDG_CACHE_HOME = undefined;
15
+ process.env.XDG_DATA_HOME = undefined;
16
+ process.env.LOCALAPPDATA = undefined;
17
+ // Bun's env handling: explicit delete for unset
18
+ delete process.env.XDG_CACHE_HOME;
19
+ delete process.env.XDG_DATA_HOME;
20
+ delete process.env.LOCALAPPDATA;
21
+ });
22
+
23
+ afterEach(() => {
24
+ if (savedEnv.XDG_CACHE_HOME !== undefined)
25
+ process.env.XDG_CACHE_HOME = savedEnv.XDG_CACHE_HOME;
26
+ if (savedEnv.XDG_DATA_HOME !== undefined)
27
+ process.env.XDG_DATA_HOME = savedEnv.XDG_DATA_HOME;
28
+ if (savedEnv.LOCALAPPDATA !== undefined) process.env.LOCALAPPDATA = savedEnv.LOCALAPPDATA;
29
+ });
30
+
31
+ test("getCacheDir falls back to <homedir>/.cache when XDG_CACHE_HOME is unset (all platforms)", () => {
32
+ // Matches OpenCode's xdg-basedir behavior on every platform, including
33
+ // Windows. A previous bug mapped Windows to %LOCALAPPDATA% and caused
34
+ // doctor --force to target a non-existent cache directory.
35
+ expect(getCacheDir()).toBe(path.join(os.homedir(), ".cache"));
36
+ });
37
+
38
+ test("getCacheDir honors XDG_CACHE_HOME when set", () => {
39
+ process.env.XDG_CACHE_HOME = "/tmp/custom-cache";
40
+ expect(getCacheDir()).toBe("/tmp/custom-cache");
41
+ });
42
+
43
+ test("getCacheDir ignores LOCALAPPDATA on Windows (must match OpenCode's xdg-basedir)", () => {
44
+ // Even with LOCALAPPDATA set, cache must go to ~/.cache to match
45
+ // OpenCode's own resolution. Otherwise doctor --force clears the
46
+ // wrong directory on Windows.
47
+ process.env.LOCALAPPDATA = "C:\\Users\\Test\\AppData\\Local";
48
+ expect(getCacheDir()).toBe(path.join(os.homedir(), ".cache"));
49
+ });
50
+
51
+ test("getOpenCodeCacheDir appends 'opencode' to the cache base", () => {
52
+ expect(getOpenCodeCacheDir()).toBe(path.join(os.homedir(), ".cache", "opencode"));
53
+ });
54
+
55
+ test("getOpenCodeCacheDir with XDG_CACHE_HOME set", () => {
56
+ process.env.XDG_CACHE_HOME = "/tmp/custom-cache";
57
+ expect(getOpenCodeCacheDir()).toBe(path.join("/tmp/custom-cache", "opencode"));
58
+ });
59
+
60
+ test("getDataDir falls back to <homedir>/.local/share when XDG_DATA_HOME is unset", () => {
61
+ expect(getDataDir()).toBe(path.join(os.homedir(), ".local", "share"));
62
+ });
63
+
64
+ test("getOpenCodeStorageDir composes correctly", () => {
65
+ expect(getOpenCodeStorageDir()).toBe(
66
+ path.join(os.homedir(), ".local", "share", "opencode", "storage"),
67
+ );
68
+ });
69
+ });
@@ -8,3 +8,21 @@ export function getDataDir(): string {
8
8
  export function getOpenCodeStorageDir(): string {
9
9
  return path.join(getDataDir(), "opencode", "storage");
10
10
  }
11
+
12
+ /**
13
+ * Resolve OpenCode's cache base directory.
14
+ *
15
+ * OpenCode uses the `xdg-basedir` package, which — on every platform, including
16
+ * Windows — falls back to `<homedir>/.cache` when `XDG_CACHE_HOME` is unset.
17
+ * A previous Windows-specific branch that resolved to `%LOCALAPPDATA%` did not
18
+ * match OpenCode's own resolution and caused `doctor --force` to target a
19
+ * non-existent directory, leaving the real cache at `C:\Users\<user>\.cache`
20
+ * untouched.
21
+ */
22
+ export function getCacheDir(): string {
23
+ return process.env.XDG_CACHE_HOME ?? path.join(os.homedir(), ".cache");
24
+ }
25
+
26
+ export function getOpenCodeCacheDir(): string {
27
+ return path.join(getCacheDir(), "opencode");
28
+ }
@@ -24,6 +24,7 @@ import { createHash } from "node:crypto";
24
24
  import { existsSync, readFileSync } from "node:fs";
25
25
  import { homedir, platform } from "node:os";
26
26
  import { join } from "node:path";
27
+ import { getCacheDir } from "./data-path";
27
28
  import { sessionLog } from "./logger";
28
29
 
29
30
  interface OpencodeClientLike {
@@ -59,16 +60,10 @@ function getModelsJsonPath(): string {
59
60
  const explicit = process.env.OPENCODE_MODELS_PATH?.trim();
60
61
  if (explicit) return explicit;
61
62
 
62
- const xdgCache = process.env.XDG_CACHE_HOME;
63
- const os = platform();
64
- let cacheBase: string;
65
- if (xdgCache) {
66
- cacheBase = xdgCache;
67
- } else if (os === "win32") {
68
- cacheBase = process.env.LOCALAPPDATA ?? join(homedir(), "AppData", "Local");
69
- } else {
70
- cacheBase = join(homedir(), ".cache");
71
- }
63
+ // OpenCode uses `xdg-basedir`, which falls back to `<homedir>/.cache` on
64
+ // every platform (including Windows) when XDG_CACHE_HOME is unset. See
65
+ // shared/data-path.ts#getCacheDir for the shared helper.
66
+ const cacheBase = getCacheDir();
72
67
 
73
68
  // 2. Custom models source → hashed filename (matches OpenCode).
74
69
  // source === "https://models.dev" ? "models.json" : `models-${Hash.fast(source)}.json`
@@ -36,13 +36,23 @@ export interface SidebarSnapshot {
36
36
  */
37
37
  toolCallTokens: number;
38
38
  /**
39
- * Token estimate of tool schemas OpenCode sends alongside in the request
40
- * `tools` parameter (bash, edit, grep, MCP servers, ctx_* tools, etc.).
41
- * Computed as inputTokens systemPromptTokens messagesBlock −
42
- * toolCallTokens and clamped to 0. Display layer shows this as
43
- * "Tool Definitions". Includes tokenizer imprecision residual.
39
+ * Measured token cost of tool schemas (description + JSON-schema
40
+ * parameters) OpenCode sends in the request `tools` parameter. Populated
41
+ * by the `tool.definition` plugin hook, keyed by
42
+ * `{providerID, modelID, agentName}`. Zero until the first turn after
43
+ * plugin startup measures the current agent's tool set. Display layer
44
+ * shows this as "Tool Definitions".
44
45
  */
45
46
  toolDefinitionTokens: number;
47
+ /**
48
+ * Residual catch-all: provider-side wrapping not captured elsewhere —
49
+ * the JSON envelope around the `tools` array, tool-choice fields,
50
+ * provider-specific cache-control markers, tokenizer imprecision, etc.
51
+ * Computed as `inputTokens − systemPromptTokens − messagesBlock −
52
+ * toolCallTokens − toolDefinitionTokens` and clamped to ≥ 0. Display
53
+ * layer shows this as "Overhead".
54
+ */
55
+ overheadTokens: number;
46
56
  }
47
57
 
48
58
  export interface StatusDetail extends SidebarSnapshot {
@@ -51,6 +51,7 @@ const EMPTY_SNAPSHOT: SidebarSnapshot = {
51
51
  conversationTokens: 0,
52
52
  toolCallTokens: 0,
53
53
  toolDefinitionTokens: 0,
54
+ overheadTokens: 0,
54
55
  };
55
56
 
56
57
  /** Fetch sidebar snapshot from the server via RPC. */
package/src/tui/index.tsx CHANGED
@@ -207,12 +207,19 @@ const StatusDialog = (props: { api: TuiPluginApi; s: StatusDetail }) => {
207
207
 
208
208
  const elapsed = () => (s().lastResponseTime > 0 ? Date.now() - s().lastResponseTime : 0)
209
209
 
210
- // Token breakdown segments — same colors as sidebar
210
+ // Token breakdown segments — same colors as sidebar. Kept in sync with
211
+ // slots/sidebar-content.tsx so the status dialog and sidebar read identically.
211
212
  const COLORS = {
213
+ // Cool / structured — injected by the plugin into message[0]
212
214
  system: "#c084fc",
213
215
  compartments: "#60a5fa",
214
216
  facts: "#fbbf24",
215
217
  memories: "#34d399",
218
+ // Warm / user-facing — chat and tool traffic
219
+ conversation: "#f87171",
220
+ toolCalls: "#fb923c",
221
+ toolDefs: "#f472b6",
222
+ overhead: "#9ca3af",
216
223
  }
217
224
 
218
225
  const breakdownSegments = () => {
@@ -245,11 +252,13 @@ const StatusDialog = (props: { api: TuiPluginApi; s: StatusDetail }) => {
245
252
  })
246
253
 
247
254
  if (d.conversationTokens > 0)
248
- segs.push({ label: "Conversation", tokens: d.conversationTokens, color: t().textMuted })
255
+ segs.push({ label: "Conversation", tokens: d.conversationTokens, color: COLORS.conversation })
249
256
  if (d.toolCallTokens > 0)
250
- segs.push({ label: "Tool Calls", tokens: d.toolCallTokens, color: "#6b7280" })
257
+ segs.push({ label: "Tool Calls", tokens: d.toolCallTokens, color: COLORS.toolCalls })
251
258
  if (d.toolDefinitionTokens > 0)
252
- segs.push({ label: "Tool Defs + Overhead", tokens: d.toolDefinitionTokens, color: "#9ca3af" })
259
+ segs.push({ label: "Tool Defs", tokens: d.toolDefinitionTokens, color: COLORS.toolDefs })
260
+ if (d.overheadTokens > 0)
261
+ segs.push({ label: "Overhead", tokens: d.overheadTokens, color: COLORS.overhead })
253
262
 
254
263
  return { segs, total }
255
264
  }
@@ -23,11 +23,17 @@ function relativeTime(ms: number): string {
23
23
 
24
24
  // Token breakdown segment colors (hardcoded hex values)
25
25
  const COLORS = {
26
- system: "#c084fc", // Purple-ish
27
- compartments: "#60a5fa", // Blue-ish
28
- facts: "#fbbf24", // Yellow/orange
29
- memories: "#34d399", // Green
30
- conversation: "#9ca3af", // Gray (will use theme.textMuted)
26
+ // Cool / structured — injected by the plugin into message[0]
27
+ system: "#c084fc", // Purple
28
+ compartments: "#60a5fa", // Blue
29
+ facts: "#fbbf24", // Yellow/orange
30
+ memories: "#34d399", // Green
31
+ // Warm / user-facing — regular chat and tool traffic. Grouped visually
32
+ // by hue family so the user reads them as a related block.
33
+ conversation: "#f87171", // Red
34
+ toolCalls: "#fb923c", // Orange
35
+ toolDefs: "#f472b6", // Pink
36
+ overhead: "#9ca3af", // Gray — catch-all residual
31
37
  }
32
38
 
33
39
  interface TokenSegment {
@@ -95,7 +101,7 @@ const TokenBreakdown = (props: {
95
101
  result.push({
96
102
  key: "conv",
97
103
  tokens: s.conversationTokens,
98
- color: props.theme.textMuted,
104
+ color: COLORS.conversation,
99
105
  label: "Conversation",
100
106
  })
101
107
  }
@@ -106,19 +112,35 @@ const TokenBreakdown = (props: {
106
112
  result.push({
107
113
  key: "tool-calls",
108
114
  tokens: s.toolCallTokens,
109
- color: "#6b7280",
115
+ color: COLORS.toolCalls,
110
116
  label: "Tool Calls",
111
117
  })
112
118
  }
113
119
 
114
- // Tool Definitions = tool schemas sent separately by OpenCode
115
- // (residual: inputTokens - system - messagesBlock - toolCalls)
120
+ // Tool Definitions = measured description + JSON-schema parameters for
121
+ // each tool OpenCode sends in the `tools` request parameter, populated
122
+ // by the `tool.definition` plugin hook keyed by {provider, model, agent}.
123
+ // Zero until the first turn measures the active agent's tool set.
116
124
  if (s.toolDefinitionTokens > 0) {
117
125
  result.push({
118
126
  key: "tool-defs",
119
127
  tokens: s.toolDefinitionTokens,
120
- color: COLORS.conversation,
121
- label: "Tool Defs + Overhead",
128
+ color: COLORS.toolDefs,
129
+ label: "Tool Defs",
130
+ })
131
+ }
132
+
133
+ // Overhead = residual between input tokens and everything measured above.
134
+ // Captures provider-side JSON wrapping around the tools array,
135
+ // tool_choice/cache-control markers, and tokenizer imprecision. Before
136
+ // the first turn's tool.definition measurement lands, the real tool
137
+ // schema cost also shows up here.
138
+ if (s.overheadTokens > 0) {
139
+ result.push({
140
+ key: "overhead",
141
+ tokens: s.overheadTokens,
142
+ color: COLORS.overhead,
143
+ label: "Overhead",
122
144
  })
123
145
  }
124
146