@cortexkit/opencode-magic-context 0.21.2 → 0.21.5

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 (50) hide show
  1. package/README.md +1 -1
  2. package/dist/config/index.d.ts.map +1 -1
  3. package/dist/config/schema/magic-context.d.ts +0 -3
  4. package/dist/config/schema/magic-context.d.ts.map +1 -1
  5. package/dist/config/variable.d.ts +9 -7
  6. package/dist/config/variable.d.ts.map +1 -1
  7. package/dist/features/magic-context/compaction-marker.d.ts +3 -1
  8. package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
  9. package/dist/features/magic-context/dreamer/runner.d.ts.map +1 -1
  10. package/dist/features/magic-context/key-files/identify-key-files.d.ts.map +1 -1
  11. package/dist/features/magic-context/key-files/project-key-files.d.ts.map +1 -1
  12. package/dist/features/magic-context/key-files/read-history.d.ts.map +1 -1
  13. package/dist/features/magic-context/migrations.d.ts +18 -0
  14. package/dist/features/magic-context/migrations.d.ts.map +1 -1
  15. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  16. package/dist/features/magic-context/storage-meta-persisted.d.ts +17 -0
  17. package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
  18. package/dist/features/magic-context/storage-meta.d.ts +1 -1
  19. package/dist/features/magic-context/storage-meta.d.ts.map +1 -1
  20. package/dist/features/magic-context/storage-notes.d.ts +6 -2
  21. package/dist/features/magic-context/storage-notes.d.ts.map +1 -1
  22. package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
  23. package/dist/features/magic-context/storage.d.ts +1 -1
  24. package/dist/features/magic-context/storage.d.ts.map +1 -1
  25. package/dist/hooks/magic-context/auto-search-runner.d.ts.map +1 -1
  26. package/dist/hooks/magic-context/compaction-marker-manager.d.ts +4 -4
  27. package/dist/hooks/magic-context/compaction-marker-manager.d.ts.map +1 -1
  28. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
  29. package/dist/hooks/magic-context/compartment-runner-types.d.ts +0 -2
  30. package/dist/hooks/magic-context/compartment-runner-types.d.ts.map +1 -1
  31. package/dist/hooks/magic-context/compartment-trigger.d.ts +2 -2
  32. package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -1
  33. package/dist/hooks/magic-context/hook.d.ts +0 -1
  34. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  35. package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
  36. package/dist/hooks/magic-context/transform-compartment-phase.d.ts +0 -2
  37. package/dist/hooks/magic-context/transform-compartment-phase.d.ts.map +1 -1
  38. package/dist/hooks/magic-context/transform.d.ts +0 -1
  39. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  40. package/dist/index.js +214 -75
  41. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  42. package/dist/plugin/sidebar-snapshot-cache.d.ts.map +1 -1
  43. package/dist/shared/jsonc-parser.d.ts +1 -0
  44. package/dist/shared/jsonc-parser.d.ts.map +1 -1
  45. package/dist/tools/ctx-note/constants.d.ts +1 -1
  46. package/dist/tools/ctx-note/constants.d.ts.map +1 -1
  47. package/dist/tools/ctx-note/tools.d.ts.map +1 -1
  48. package/package.json +1 -1
  49. package/src/shared/jsonc-parser.ts +1 -1
  50. package/src/tui/slots/sidebar-content.tsx +27 -14
@@ -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;;;;;;qBAqD6pJ,CAAC;;;;;;;;;;;;qBAA9sC,CAAC;mBAAyB,CAAC;iBAAuB,CAAC;iBAAuB,CAAC;0BAAc,CAAC;uBAAiB,CAAC;;;;;;0BAA4utB,CAAC;;;;;;EADzy0B"}
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;;;;;;qBAoDkuJ,CAAC;;;;;;;;;;;;qBAA9sC,CAAC;mBAAyB,CAAC;iBAAuB,CAAC;iBAAuB,CAAC;0BAAc,CAAC;uBAAiB,CAAC;;;;;;0BAAwgtB,CAAC;;;;;;EAD1o0B"}
@@ -1 +1 @@
1
- {"version":3,"file":"sidebar-snapshot-cache.d.ts","sourceRoot":"","sources":["../../src/plugin/sidebar-snapshot-cache.ts"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAY3D;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CACpC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,eAAe,GACvB,eAAe,CA6CjB;AAQD;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAEjE;AAED;;GAEG;AACH,wBAAgB,yBAAyB,IAAI,IAAI,CAEhD"}
1
+ {"version":3,"file":"sidebar-snapshot-cache.d.ts","sourceRoot":"","sources":["../../src/plugin/sidebar-snapshot-cache.ts"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAY3D;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CACpC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,eAAe,GACvB,eAAe,CA+DjB;AAQD;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAEjE;AAED;;GAEG;AACH,wBAAgB,yBAAyB,IAAI,IAAI,CAEhD"}
@@ -1,3 +1,4 @@
1
+ export declare function stripJsonComments(content: string): string;
1
2
  export declare function parseJsonc<T = unknown>(content: string): T;
2
3
  export declare function readJsoncFile<T = unknown>(filePath: string): T | null;
3
4
  export declare function detectConfigFile(basePath: string): {
@@ -1 +1 @@
1
- {"version":3,"file":"jsonc-parser.d.ts","sourceRoot":"","sources":["../../src/shared/jsonc-parser.ts"],"names":[],"mappings":"AA4GA,wBAAgB,UAAU,CAAC,CAAC,GAAG,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,CAAC,CAG1D;AAED,wBAAgB,aAAa,CAAC,CAAC,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,CAMrE;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG;IAChD,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;CAChB,CAaA"}
1
+ {"version":3,"file":"jsonc-parser.d.ts","sourceRoot":"","sources":["../../src/shared/jsonc-parser.ts"],"names":[],"mappings":"AAEA,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CA6DzD;AA6CD,wBAAgB,UAAU,CAAC,CAAC,GAAG,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,CAAC,CAG1D;AAED,wBAAgB,aAAa,CAAC,CAAC,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,CAMrE;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG;IAChD,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;CAChB,CAaA"}
@@ -1,2 +1,2 @@
1
- export declare const CTX_NOTE_DESCRIPTION = "Save or inspect durable session notes that persist for this session.\nUse this for short goals, constraints, decisions, or reminders worth carrying forward.\n\nActions:\n- `write`: Append one note. Optionally provide `surface_condition` to create a smart note.\n- `read`: Show current notes. Defaults to active session notes + ready smart notes; use `filter` to inspect all, pending, ready, active, or dismissed notes.\n- `dismiss`: Dismiss a note by `note_id`.\n- `update`: Update a note by `note_id`.\n\n**Smart Notes**: When `surface_condition` is provided with `write`, the note becomes a project-scoped smart note.\nThe dreamer evaluates smart note conditions during nightly runs and surfaces them when conditions are met.\nExample: `ctx_note(action=\"write\", content=\"Implement X because Y\", surface_condition=\"When PR #42 is merged in this repo\")`\n\nHistorian reads these notes, deduplicates them, and rewrites the remaining useful notes over time.";
1
+ export declare const CTX_NOTE_DESCRIPTION = "Save or inspect durable session notes that persist for this session.\nUse this for short goals, constraints, decisions, or reminders worth carrying forward.\n\nActions:\n- `write`: Append one note. Optionally provide `surface_condition` to create a smart note.\n- `read`: Show current notes. Defaults to active session notes + ready smart notes; use `filter` to inspect all, pending, ready, active, or dismissed notes.\n- `dismiss`: Dismiss a note by `note_id`.\n- `update`: Update a note by `note_id`.\n\n**Smart Notes**: When `surface_condition` is provided with `write`, the note becomes a project-scoped smart note. A separate background process (the dreamer) periodically checks the condition using ONLY external, verifiable signals: GitHub state via `gh` CLI, web pages, files on disk, git history, etc. The dreamer cannot read your current conversation, cannot detect when the user says something, and has no memory of context that lives only in this session.\n\nWrite a smart note ONLY when the surface_condition is something an external agent with read-only tools can definitively check:\n\n\u2713 GOOD conditions (externally verifiable):\n- \"When PR #42 in cortexkit/magic-context is merged\"\n- \"When the file packages/plugin/src/foo.ts contains a function named bar\"\n- \"When the latest release tag is >= v0.22.0\"\n- \"When the GitHub Actions workflow runs/123 succeeds\"\n\n\u2717 BAD conditions (require knowing this session's context):\n- \"When the user mentions the worktree system has landed\" \u2192 dreamer cannot see user messages\n- \"When they ask to re-run the audit fixes\" \u2192 dreamer cannot see future requests\n- \"When we revisit this code path\" \u2192 no observable signal\n- \"When relevant to the current discussion\" \u2192 no observable signal\n- \"After we finish the current refactor\" \u2192 no externally checkable boundary\n\nIf you want context that surfaces based on what's happening in your session, use a regular note (omit surface_condition) \u2014 those show up on natural work boundaries within this session. If you want a reminder tied to your future work without a clean external trigger, just write a regular note describing what to do; you'll see it when you read notes later.\n\nExample: `ctx_note(action=\"write\", content=\"Implement X because Y\", surface_condition=\"When PR #42 in cortexkit/magic-context is merged\")`\n\nHistorian reads these notes, deduplicates them, and rewrites the remaining useful notes over time.";
2
2
  //# sourceMappingURL=constants.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/tools/ctx-note/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,s8BAakE,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/tools/ctx-note/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,mgFA8BkE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../../src/tools/ctx-note/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAQ,MAAM,qBAAqB,CAAC;AAWhE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAIpD,MAAM,WAAW,eAAe;IAC5B,EAAE,EAAE,QAAQ,CAAC;IACb,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC;CACtD;AA+ND,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAIxF"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../../src/tools/ctx-note/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAQ,MAAM,qBAAqB,CAAC;AAWhE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAIpD,MAAM,WAAW,eAAe;IAC5B,EAAE,EAAE,QAAQ,CAAC;IACb,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC;CACtD;AA2OD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAIxF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/opencode-magic-context",
3
- "version": "0.21.2",
3
+ "version": "0.21.5",
4
4
  "type": "module",
5
5
  "description": "OpenCode plugin for Magic Context — cross-session memory and context management",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  import { existsSync, readFileSync } from "node:fs";
2
2
 
3
- function stripJsonComments(content: string): string {
3
+ export function stripJsonComments(content: string): string {
4
4
  let result = "";
5
5
  let inString = false;
6
6
  let escaped = false;
@@ -95,15 +95,23 @@ const TokenBreakdown = (props: {
95
95
  }
96
96
 
97
97
  // Conversation = real user/assistant text/reasoning/images
98
- // (excludes injected session-history and excludes tool call I/O)
99
- if (s.conversationTokens > 0) {
100
- result.push({
101
- key: "conv",
102
- tokens: s.conversationTokens,
103
- color: COLORS.conversation,
104
- label: "Conversation",
105
- })
106
- }
98
+ // (excludes injected session-history and excludes tool call I/O).
99
+ //
100
+ // Always show this row even when conversationTokens === 0. The
101
+ // calibrator's residual-distribution math (tokenizer-calibration.ts)
102
+ // can round it down to zero when toolCallsLocal massively dominates
103
+ // conversationLocal — that's a calibration artifact, not a real
104
+ // "zero conversation". Suppressing the row leaves the legend looking
105
+ // truncated, which is more confusing than showing a 0% line. The
106
+ // segment is also skipped in the bar at 0 width because the segment
107
+ // builder uses `Math.max(1, ...)` only when tokens > 0 (see
108
+ // segmentWidths), so the visual bar stays correct either way.
109
+ result.push({
110
+ key: "conv",
111
+ tokens: s.conversationTokens,
112
+ color: COLORS.conversation,
113
+ label: "Conversation",
114
+ })
107
115
 
108
116
  // Tool Calls = tool_use/tool_result/tool/tool-invocation parts in messages
109
117
  // (actionable — users can reduce via ctx_reduce)
@@ -143,8 +151,14 @@ const TokenBreakdown = (props: {
143
151
  // Calculate raw proportions
144
152
  const proportions = segs.map((seg) => seg.tokens / total)
145
153
 
146
- // Convert to character widths (minimum 1 char if tokens > 0)
147
- let widths = proportions.map((p) => Math.max(1, Math.round(p * barWidth)))
154
+ // Convert to character widths. Minimum 1 char ONLY when the segment
155
+ // has tokens > 0 — zero-token segments (e.g. Conversation when the
156
+ // calibrator rounded it to zero) must get width 0 so the bar stays
157
+ // proportional. The legend row still renders for zero-token segments
158
+ // to keep the row stable.
159
+ let widths = segs.map((seg, i) =>
160
+ seg.tokens > 0 ? Math.max(1, Math.round(proportions[i] * barWidth)) : 0,
161
+ )
148
162
 
149
163
  // Adjust to exactly barWidth
150
164
  const sum = widths.reduce((a, b) => a + b, 0)
@@ -349,10 +363,9 @@ const SidebarContent = (props: {
349
363
  {s() && s()!.inputTokens > 0 && (
350
364
  <box marginTop={1} flexDirection="column">
351
365
  {(s()?.contextLimit ?? 0) > 0 && (
352
- <box width="100%" flexDirection="row" justifyContent="space-between">
353
- <text fg={props.theme.textMuted}>Context</text>
366
+ <box width="100%" flexDirection="row" justifyContent="flex-end">
354
367
  <text fg={contextSummaryColor()}>
355
- <b>{s()!.usagePercentage.toFixed(1)}%</b> · {compactTokens(s()!.inputTokens)} / {compactTokens(s()!.contextLimit)} tokens
368
+ <b>{s()!.usagePercentage.toFixed(1)}%</b> · {compactTokens(s()!.inputTokens)} / {compactTokens(s()!.contextLimit)}
356
369
  </text>
357
370
  </box>
358
371
  )}