@cortexkit/opencode-magic-context 0.15.7 → 0.16.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 (204) hide show
  1. package/README.md +42 -16
  2. package/dist/agents/magic-context-prompt.d.ts +2 -13
  3. package/dist/agents/magic-context-prompt.d.ts.map +1 -1
  4. package/dist/config/schema/magic-context.d.ts +67 -4
  5. package/dist/config/schema/magic-context.d.ts.map +1 -1
  6. package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
  7. package/dist/features/magic-context/compaction.d.ts +1 -1
  8. package/dist/features/magic-context/compaction.d.ts.map +1 -1
  9. package/dist/features/magic-context/compartment-storage.d.ts +1 -1
  10. package/dist/features/magic-context/compartment-storage.d.ts.map +1 -1
  11. package/dist/features/magic-context/compression-depth-storage.d.ts +1 -1
  12. package/dist/features/magic-context/compression-depth-storage.d.ts.map +1 -1
  13. package/dist/features/magic-context/dreamer/lease.d.ts +1 -1
  14. package/dist/features/magic-context/dreamer/lease.d.ts.map +1 -1
  15. package/dist/features/magic-context/dreamer/queue.d.ts +8 -3
  16. package/dist/features/magic-context/dreamer/queue.d.ts.map +1 -1
  17. package/dist/features/magic-context/dreamer/runner.d.ts +1 -1
  18. package/dist/features/magic-context/dreamer/runner.d.ts.map +1 -1
  19. package/dist/features/magic-context/dreamer/scheduler.d.ts +1 -1
  20. package/dist/features/magic-context/dreamer/scheduler.d.ts.map +1 -1
  21. package/dist/features/magic-context/dreamer/storage-dream-runs.d.ts +1 -1
  22. package/dist/features/magic-context/dreamer/storage-dream-runs.d.ts.map +1 -1
  23. package/dist/features/magic-context/dreamer/storage-dream-state.d.ts +1 -1
  24. package/dist/features/magic-context/dreamer/storage-dream-state.d.ts.map +1 -1
  25. package/dist/features/magic-context/git-commits/indexer.d.ts +1 -1
  26. package/dist/features/magic-context/git-commits/indexer.d.ts.map +1 -1
  27. package/dist/features/magic-context/git-commits/search-git-commits.d.ts +1 -1
  28. package/dist/features/magic-context/git-commits/search-git-commits.d.ts.map +1 -1
  29. package/dist/features/magic-context/git-commits/storage-git-commit-embeddings.d.ts +1 -1
  30. package/dist/features/magic-context/git-commits/storage-git-commit-embeddings.d.ts.map +1 -1
  31. package/dist/features/magic-context/git-commits/storage-git-commits.d.ts +1 -1
  32. package/dist/features/magic-context/git-commits/storage-git-commits.d.ts.map +1 -1
  33. package/dist/features/magic-context/key-files/identify-key-files.d.ts +1 -1
  34. package/dist/features/magic-context/key-files/identify-key-files.d.ts.map +1 -1
  35. package/dist/features/magic-context/key-files/read-stats.d.ts +1 -1
  36. package/dist/features/magic-context/key-files/read-stats.d.ts.map +1 -1
  37. package/dist/features/magic-context/key-files/storage-key-files.d.ts +1 -1
  38. package/dist/features/magic-context/key-files/storage-key-files.d.ts.map +1 -1
  39. package/dist/features/magic-context/memory/embedding-backfill.d.ts +1 -1
  40. package/dist/features/magic-context/memory/embedding-backfill.d.ts.map +1 -1
  41. package/dist/features/magic-context/memory/embedding-cache.d.ts +1 -1
  42. package/dist/features/magic-context/memory/embedding-cache.d.ts.map +1 -1
  43. package/dist/features/magic-context/memory/embedding-local.d.ts.map +1 -1
  44. package/dist/features/magic-context/memory/embedding.d.ts +1 -1
  45. package/dist/features/magic-context/memory/embedding.d.ts.map +1 -1
  46. package/dist/features/magic-context/memory/normalize-hash.d.ts.map +1 -1
  47. package/dist/features/magic-context/memory/project-identity.d.ts.map +1 -1
  48. package/dist/features/magic-context/memory/promotion.d.ts +1 -1
  49. package/dist/features/magic-context/memory/promotion.d.ts.map +1 -1
  50. package/dist/features/magic-context/memory/storage-memory-embeddings.d.ts +1 -1
  51. package/dist/features/magic-context/memory/storage-memory-embeddings.d.ts.map +1 -1
  52. package/dist/features/magic-context/memory/storage-memory-fts.d.ts +1 -1
  53. package/dist/features/magic-context/memory/storage-memory-fts.d.ts.map +1 -1
  54. package/dist/features/magic-context/memory/storage-memory.d.ts +1 -1
  55. package/dist/features/magic-context/memory/storage-memory.d.ts.map +1 -1
  56. package/dist/features/magic-context/message-index.d.ts +1 -1
  57. package/dist/features/magic-context/message-index.d.ts.map +1 -1
  58. package/dist/features/magic-context/migrations.d.ts +1 -1
  59. package/dist/features/magic-context/migrations.d.ts.map +1 -1
  60. package/dist/features/magic-context/mock-database.d.ts +1 -1
  61. package/dist/features/magic-context/mock-database.d.ts.map +1 -1
  62. package/dist/features/magic-context/plugin-messages.d.ts +1 -1
  63. package/dist/features/magic-context/plugin-messages.d.ts.map +1 -1
  64. package/dist/features/magic-context/search.d.ts +1 -1
  65. package/dist/features/magic-context/search.d.ts.map +1 -1
  66. package/dist/features/magic-context/sidekick/agent.d.ts +2 -1
  67. package/dist/features/magic-context/sidekick/agent.d.ts.map +1 -1
  68. package/dist/features/magic-context/sidekick/core.d.ts +38 -0
  69. package/dist/features/magic-context/sidekick/core.d.ts.map +1 -0
  70. package/dist/features/magic-context/storage-db.d.ts +20 -1
  71. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  72. package/dist/features/magic-context/storage-meta-persisted.d.ts +1 -1
  73. package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
  74. package/dist/features/magic-context/storage-meta-session.d.ts +1 -1
  75. package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
  76. package/dist/features/magic-context/storage-meta-shared.d.ts +1 -1
  77. package/dist/features/magic-context/storage-meta-shared.d.ts.map +1 -1
  78. package/dist/features/magic-context/storage-notes.d.ts +1 -1
  79. package/dist/features/magic-context/storage-notes.d.ts.map +1 -1
  80. package/dist/features/magic-context/storage-ops.d.ts +1 -1
  81. package/dist/features/magic-context/storage-ops.d.ts.map +1 -1
  82. package/dist/features/magic-context/storage-source.d.ts +1 -1
  83. package/dist/features/magic-context/storage-source.d.ts.map +1 -1
  84. package/dist/features/magic-context/storage-tags.d.ts +17 -1
  85. package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
  86. package/dist/features/magic-context/tagger.d.ts +1 -1
  87. package/dist/features/magic-context/tagger.d.ts.map +1 -1
  88. package/dist/features/magic-context/user-memory/review-user-memories.d.ts +1 -1
  89. package/dist/features/magic-context/user-memory/review-user-memories.d.ts.map +1 -1
  90. package/dist/features/magic-context/user-memory/storage-user-memory.d.ts +1 -1
  91. package/dist/features/magic-context/user-memory/storage-user-memory.d.ts.map +1 -1
  92. package/dist/hooks/magic-context/auto-search-hint.d.ts.map +1 -1
  93. package/dist/hooks/magic-context/auto-search-runner.d.ts +1 -1
  94. package/dist/hooks/magic-context/auto-search-runner.d.ts.map +1 -1
  95. package/dist/hooks/magic-context/command-handler.d.ts +1 -1
  96. package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
  97. package/dist/hooks/magic-context/compaction-marker-manager.d.ts +1 -1
  98. package/dist/hooks/magic-context/compaction-marker-manager.d.ts.map +1 -1
  99. package/dist/hooks/magic-context/compartment-prompt.d.ts +1 -0
  100. package/dist/hooks/magic-context/compartment-prompt.d.ts.map +1 -1
  101. package/dist/hooks/magic-context/compartment-runner-compressor.d.ts +1 -1
  102. package/dist/hooks/magic-context/compartment-runner-compressor.d.ts.map +1 -1
  103. package/dist/hooks/magic-context/compartment-runner-drop-queue.d.ts +1 -1
  104. package/dist/hooks/magic-context/compartment-runner-drop-queue.d.ts.map +1 -1
  105. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts +1 -0
  106. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
  107. package/dist/hooks/magic-context/compartment-runner-recomp.d.ts.map +1 -1
  108. package/dist/hooks/magic-context/compartment-runner-types.d.ts +1 -1
  109. package/dist/hooks/magic-context/compartment-runner-types.d.ts.map +1 -1
  110. package/dist/hooks/magic-context/compartment-trigger.d.ts +1 -1
  111. package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -1
  112. package/dist/hooks/magic-context/execute-flush.d.ts +1 -1
  113. package/dist/hooks/magic-context/execute-flush.d.ts.map +1 -1
  114. package/dist/hooks/magic-context/execute-status.d.ts +1 -1
  115. package/dist/hooks/magic-context/execute-status.d.ts.map +1 -1
  116. package/dist/hooks/magic-context/historian-state-file.d.ts +29 -0
  117. package/dist/hooks/magic-context/historian-state-file.d.ts.map +1 -0
  118. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  119. package/dist/hooks/magic-context/inject-compartments.d.ts +1 -1
  120. package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
  121. package/dist/hooks/magic-context/note-nudger.d.ts +1 -1
  122. package/dist/hooks/magic-context/note-nudger.d.ts.map +1 -1
  123. package/dist/hooks/magic-context/nudge-placement-store.d.ts +1 -1
  124. package/dist/hooks/magic-context/nudge-placement-store.d.ts.map +1 -1
  125. package/dist/hooks/magic-context/read-session-chunk.d.ts +39 -0
  126. package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
  127. package/dist/hooks/magic-context/read-session-db.d.ts +1 -1
  128. package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
  129. package/dist/hooks/magic-context/read-session-raw.d.ts +1 -1
  130. package/dist/hooks/magic-context/read-session-raw.d.ts.map +1 -1
  131. package/dist/hooks/magic-context/send-session-notification.d.ts.map +1 -1
  132. package/dist/hooks/magic-context/system-prompt-hash.d.ts +6 -5
  133. package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
  134. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  135. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  136. package/dist/index.js +8284 -8166
  137. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  138. package/dist/plugin/messages-transform.d.ts +1 -1
  139. package/dist/plugin/rpc-handlers.d.ts +4 -0
  140. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  141. package/dist/plugin/tool-registry.d.ts.map +1 -1
  142. package/dist/shared/conflict-detector.d.ts.map +1 -1
  143. package/dist/shared/data-path.d.ts +22 -0
  144. package/dist/shared/data-path.d.ts.map +1 -1
  145. package/dist/shared/harness.d.ts +43 -0
  146. package/dist/shared/harness.d.ts.map +1 -0
  147. package/dist/shared/rpc-notifications.d.ts +4 -2
  148. package/dist/shared/rpc-notifications.d.ts.map +1 -1
  149. package/dist/shared/sqlite-helpers.d.ts +16 -0
  150. package/dist/shared/sqlite-helpers.d.ts.map +1 -0
  151. package/dist/shared/sqlite.d.ts +55 -0
  152. package/dist/shared/sqlite.d.ts.map +1 -0
  153. package/dist/shared/subagent-runner.d.ts +202 -0
  154. package/dist/shared/subagent-runner.d.ts.map +1 -0
  155. package/dist/shared/tag-transcript.d.ts +66 -0
  156. package/dist/shared/tag-transcript.d.ts.map +1 -0
  157. package/dist/shared/transcript-opencode.d.ts +71 -0
  158. package/dist/shared/transcript-opencode.d.ts.map +1 -0
  159. package/dist/shared/transcript.d.ts +212 -0
  160. package/dist/shared/transcript.d.ts.map +1 -0
  161. package/dist/shared/tui-config.d.ts.map +1 -1
  162. package/dist/tools/ctx-memory/tools.d.ts.map +1 -1
  163. package/dist/tools/ctx-memory/types.d.ts +13 -2
  164. package/dist/tools/ctx-memory/types.d.ts.map +1 -1
  165. package/dist/tools/ctx-note/tools.d.ts +8 -2
  166. package/dist/tools/ctx-note/tools.d.ts.map +1 -1
  167. package/dist/tools/ctx-reduce/tools.d.ts +1 -1
  168. package/dist/tools/ctx-reduce/tools.d.ts.map +1 -1
  169. package/dist/tools/ctx-search/tools.d.ts.map +1 -1
  170. package/dist/tools/ctx-search/types.d.ts +8 -2
  171. package/dist/tools/ctx-search/types.d.ts.map +1 -1
  172. package/dist/tui/data/context-db.d.ts.map +1 -1
  173. package/package.json +73 -75
  174. package/src/shared/conflict-detector.test.ts +44 -1
  175. package/src/shared/conflict-detector.ts +24 -8
  176. package/src/shared/data-path.test.ts +53 -1
  177. package/src/shared/data-path.ts +28 -0
  178. package/src/shared/harness.ts +61 -0
  179. package/src/shared/rpc-notifications.ts +11 -5
  180. package/src/shared/sqlite-helpers.ts +27 -0
  181. package/src/shared/sqlite.ts +91 -0
  182. package/src/shared/subagent-runner.ts +206 -0
  183. package/src/shared/tag-transcript.ts +541 -0
  184. package/src/shared/transcript-opencode.ts +259 -0
  185. package/src/shared/transcript.ts +226 -0
  186. package/src/shared/tui-config.ts +34 -8
  187. package/src/tui/data/context-db.ts +5 -1
  188. package/dist/cli/config-paths.d.ts +0 -11
  189. package/dist/cli/config-paths.d.ts.map +0 -1
  190. package/dist/cli/diagnostics.d.ts +0 -82
  191. package/dist/cli/diagnostics.d.ts.map +0 -1
  192. package/dist/cli/doctor.d.ts +0 -5
  193. package/dist/cli/doctor.d.ts.map +0 -1
  194. package/dist/cli/index.d.ts +0 -3
  195. package/dist/cli/index.d.ts.map +0 -1
  196. package/dist/cli/logs.d.ts +0 -22
  197. package/dist/cli/logs.d.ts.map +0 -1
  198. package/dist/cli/opencode-helpers.d.ts +0 -19
  199. package/dist/cli/opencode-helpers.d.ts.map +0 -1
  200. package/dist/cli/prompts.d.ts +0 -14
  201. package/dist/cli/prompts.d.ts.map +0 -1
  202. package/dist/cli/setup.d.ts +0 -2
  203. package/dist/cli/setup.d.ts.map +0 -1
  204. package/dist/cli.js +0 -11287
@@ -0,0 +1,212 @@
1
+ /**
2
+ * Harness-agnostic transcript interface.
3
+ *
4
+ * Magic Context's transform pipeline operates on messages in a specific
5
+ * shape: ordered messages with role-tagged parts (text, tool, reasoning,
6
+ * tool_result, image), where tagging, sentinel stripping, and queued-drop
7
+ * application MUTATE part content in-place. OpenCode's plugin transform
8
+ * receives a `{ info, parts: unknown[] }[]` array and the AI SDK reads
9
+ * those mutations directly. Pi's `pi.on("context", ...)` event delivers a
10
+ * `AgentMessage[]` and accepts a fully-replaced array as the result.
11
+ *
12
+ * Rather than building a bidirectional `MessageLike[] ↔ AgentMessage[]`
13
+ * adapter (Oracle's rejected Q1 alternative — too much round-trip
14
+ * complexity, double-conversion bugs), this module defines a small
15
+ * adapter contract that:
16
+ *
17
+ * 1. Exposes ordered messages with a *uniform* part-level mutation
18
+ * surface, regardless of underlying shape.
19
+ * 2. Is owned by the harness — OpenCode's adapter mutates `parts[]`
20
+ * directly (zero copies), Pi's adapter rebuilds an `AgentMessage[]`
21
+ * from the mutated transcript only at commit time.
22
+ * 3. Lets the shared transform code (tagging, stripping, drops)
23
+ * operate on `TranscriptPart` interface instances without caring
24
+ * whether they're wrapping `Part` from `@opencode-ai/sdk` or
25
+ * `TextContent | ToolCall | ThinkingContent` from `@mariozechner/pi-ai`.
26
+ *
27
+ * What this interface deliberately does NOT do:
28
+ *
29
+ * - **No data round-trip.** The transcript is a *view* over harness data;
30
+ * it doesn't define a third canonical message shape. There's no JSON
31
+ * serialization, no normalization to a common DTO. Round-trip-free
32
+ * adapters are 10x simpler and faster.
33
+ *
34
+ * - **No mutation semantics divergence.** Both adapters expose the same
35
+ * in-place mutation API (`setText`, `setOutput`, `replaceWithSentinel`).
36
+ * Whether mutation flushes to the source array immediately (OpenCode)
37
+ * or accumulates until `commit()` (Pi) is the adapter's concern.
38
+ *
39
+ * - **No session-storage abstraction.** Compartment storage, ordinals,
40
+ * raw-history reads — those live in feature modules, not here. The
41
+ * transcript only models the *current turn's* live message buffer.
42
+ *
43
+ * Step 4b.1 ships ONLY the interface and OpenCode adapter migration.
44
+ * Pi adapter implementation lands in 4b.2 alongside the Pi context-event
45
+ * wire-up, since the two are co-designed (the Pi adapter has to satisfy
46
+ * the same operations the tagging code calls). 4b.3 wires the Pi
47
+ * compartment trigger and historian invocation. 4b.4 nudges + auto-search.
48
+ */
49
+ /** Categorical kind of a transcript part, useful for filter predicates. */
50
+ export type TranscriptPartKind = "text" | "thinking" | "tool_use" | "tool_result" | "image" | "file" | "structural" | "unknown";
51
+ /**
52
+ * A single content fragment within a transcript message.
53
+ *
54
+ * The interface is intentionally narrow: it exposes the operations Magic
55
+ * Context's transform code performs (read kind, read text, mutate text,
56
+ * mutate tool output, drop, replace with sentinel) and nothing more. Each
57
+ * harness adapter implements these against its native part type.
58
+ *
59
+ * IMPORTANT: implementations are stateful proxies over the live source
60
+ * data. Calling `setText("...")` on an OpenCode part mutates the
61
+ * underlying `Part.text`; calling it on a Pi part flips a dirty flag and
62
+ * the adapter's `commit()` rebuilds the affected `AgentMessage`. Either
63
+ * way, the transcript code reads back consistent values via `getText()`.
64
+ */
65
+ export interface TranscriptPart {
66
+ /** Discriminator for filter logic. Stable across mutations. */
67
+ readonly kind: TranscriptPartKind;
68
+ /**
69
+ * Best-effort identifier for cross-pass tracking. May be:
70
+ * - OpenCode part ID (e.g. "prt_..."), stable across passes.
71
+ * - Pi tool-call ID for tool_use/tool_result parts.
72
+ * - undefined for synthetic/structural parts.
73
+ *
74
+ * Pure parts without a stable ID return undefined and are tracked
75
+ * positionally within their containing message instead.
76
+ */
77
+ readonly id: string | undefined;
78
+ /**
79
+ * The user-/agent-visible text payload, if this part has one. Returns
80
+ * undefined for parts that have no text representation (image, file,
81
+ * structural-only). For thinking parts returns the thinking text. For
82
+ * tool_use returns the JSON-stringified arguments (so size accounting
83
+ * reflects what the model sees). For tool_result returns the
84
+ * concatenated text content of the result.
85
+ */
86
+ getText(): string | undefined;
87
+ /**
88
+ * Replace the visible text payload. Applies only to text and thinking
89
+ * parts; throws for kinds where mutation isn't meaningful (the caller
90
+ * should check `kind` first).
91
+ *
92
+ * Returns true if the underlying source data actually changed (so
93
+ * deduplication helpers can short-circuit). Returns false when the
94
+ * new text equals the existing text byte-for-byte.
95
+ */
96
+ setText(newText: string): boolean;
97
+ /**
98
+ * For tool_result parts: replace the text content of the result.
99
+ * For tool_use parts: replace JSON-serialized arguments.
100
+ * For everything else: throws — caller should check `kind` first.
101
+ */
102
+ setToolOutput(newText: string): boolean;
103
+ /**
104
+ * Tool-specific metadata exposed for tagging/drop accounting:
105
+ * - toolName: tool identifier (e.g. "bash", "ctx_search"). undefined
106
+ * for non-tool parts.
107
+ * - inputByteSize: serialized argument size; used by historian
108
+ * pressure projection to estimate post-drop savings.
109
+ *
110
+ * For non-tool parts both fields are undefined.
111
+ */
112
+ getToolMetadata(): {
113
+ toolName: string | undefined;
114
+ inputByteSize: number;
115
+ };
116
+ /**
117
+ * Replace this part with a sentinel placeholder. Sentinels look like
118
+ * `[dropped §N§]` or `[truncated §N§]` and survive cache-busting
119
+ * cycles by carrying their original tag number. Used by the
120
+ * apply-operations flow when a queued drop fires.
121
+ *
122
+ * Implementations replace the part *in place* in the parent message's
123
+ * part array. The replaced part's `kind` shifts to "structural" so
124
+ * subsequent transform passes don't double-process it.
125
+ *
126
+ * Returns true on success; returns false if the part can't be
127
+ * replaced (e.g. it's already a sentinel, or it's an image part).
128
+ */
129
+ replaceWithSentinel(sentinelText: string): boolean;
130
+ }
131
+ /**
132
+ * A single message in the transcript, exposing role + ordered parts.
133
+ *
134
+ * Lifetime: a TranscriptMessage is valid only within a single transform
135
+ * pass. Adapters do not guarantee identity across passes — callers must
136
+ * use `info.id` for cross-pass correlation, never the message reference.
137
+ */
138
+ export interface TranscriptMessage {
139
+ /**
140
+ * Lightweight metadata exposed for tagging, sentinel persistence, and
141
+ * cross-pass correlation. Adapters fill these from harness-native
142
+ * fields:
143
+ *
144
+ * - id: provider-stable message ID (OpenCode `msg_...`, Pi entryId).
145
+ * - role: "user" | "assistant" | "system" | "tool" | other custom roles.
146
+ * - sessionId: session identifier, used to scope DB writes.
147
+ *
148
+ * IMPORTANT for Pi: Pi's `ToolResultMessage` has role "toolResult"
149
+ * which the OpenCode-derived transform code expects to NOT be present
150
+ * (OpenCode folds tool results into the next user message's parts).
151
+ * The Pi adapter therefore exposes tool-result messages as parts of a
152
+ * synthetic "user" message in the transcript view, even though the
153
+ * underlying Pi storage has them as separate top-level entries. This
154
+ * is the *only* shape normalization the adapter performs.
155
+ */
156
+ readonly info: {
157
+ id?: string;
158
+ role: string;
159
+ sessionId?: string;
160
+ };
161
+ /** Ordered parts. Same ordering invariants as the underlying source. */
162
+ readonly parts: TranscriptPart[];
163
+ }
164
+ /**
165
+ * Adapter contract: everything the transform pipeline calls on a
166
+ * harness-specific transcript implementation.
167
+ *
168
+ * Adapters are owned by the harness adapter layer (OpenCode's
169
+ * messages-transform.ts, Pi's context-event handler). The shared
170
+ * transform code receives a Transcript and operates only through this
171
+ * interface — it never imports from `@opencode-ai/sdk` or
172
+ * `@mariozechner/pi-ai`.
173
+ */
174
+ export interface Transcript {
175
+ /** Ordered messages in the current pass. */
176
+ readonly messages: TranscriptMessage[];
177
+ /**
178
+ * Adapter identification. Useful for:
179
+ * - Logging (`magic-context[opencode]` vs `magic-context[pi]`).
180
+ * - Per-harness behaviors gated at adapter level (e.g. opencode-only
181
+ * compaction marker injection).
182
+ * - Test assertions confirming the right adapter ran.
183
+ */
184
+ readonly harness: "opencode" | "pi";
185
+ /**
186
+ * Commit accumulated mutations to the underlying source array.
187
+ *
188
+ * For OpenCode: no-op — parts are mutated directly in `Part.text`/
189
+ * `Part.state.output` and OpenCode reads them back from the same
190
+ * array, so changes are already visible.
191
+ *
192
+ * For Pi: rebuilds a new `AgentMessage[]` from the dirty messages
193
+ * and stores it on the adapter so `pi.on("context", ...)` can return
194
+ * `{ messages }` to Pi. Idempotent: calling twice is safe.
195
+ *
196
+ * Always called exactly once per pass, after the transform pipeline
197
+ * finishes. Adapters that don't need it implement it as a no-op.
198
+ */
199
+ commit(): void;
200
+ }
201
+ /**
202
+ * Sentinel marker for transcript parts that should be ignored by all
203
+ * downstream transform stages (tagging, drops, indexing). Adapters set
204
+ * this on parts that exist only as structural artifacts (e.g. OpenCode's
205
+ * `step-start`/`step-finish`).
206
+ *
207
+ * Exported so harness adapters can stamp it on synthetic parts they
208
+ * create internally and so test fixtures can construct synthetic
209
+ * transcripts without needing real OpenCode/Pi structures.
210
+ */
211
+ export declare const STRUCTURAL_SENTINEL_KIND: TranscriptPartKind;
212
+ //# sourceMappingURL=transcript.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transcript.d.ts","sourceRoot":"","sources":["../../src/shared/transcript.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AAEH,2EAA2E;AAC3E,MAAM,MAAM,kBAAkB,GACxB,MAAM,GACN,UAAU,GACV,UAAU,GACV,aAAa,GACb,OAAO,GACP,MAAM,GACN,YAAY,GACZ,SAAS,CAAC;AAEhB;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,cAAc;IAC3B,+DAA+D;IAC/D,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAElC;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,CAAC;IAEhC;;;;;;;OAOG;IACH,OAAO,IAAI,MAAM,GAAG,SAAS,CAAC;IAE9B;;;;;;;;OAQG;IACH,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;IAElC;;;;OAIG;IACH,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;IAExC;;;;;;;;OAQG;IACH,eAAe,IAAI;QAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC;IAE3E;;;;;;;;;;;;OAYG;IACH,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC;CACtD;AAED;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAC9B;;;;;;;;;;;;;;;;OAgBG;IACH,QAAQ,CAAC,IAAI,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAEjE,wEAAwE;IACxE,QAAQ,CAAC,KAAK,EAAE,cAAc,EAAE,CAAC;CACpC;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,UAAU;IACvB,4CAA4C;IAC5C,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAEvC;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI,CAAC;IAEpC;;;;;;;;;;;;;OAaG;IACH,MAAM,IAAI,IAAI,CAAC;CAClB;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,wBAAwB,EAAE,kBAAiC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"tui-config.d.ts","sourceRoot":"","sources":["../../src/shared/tui-config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAqBH;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CA4C9C"}
1
+ {"version":3,"file":"tui-config.d.ts","sourceRoot":"","sources":["../../src/shared/tui-config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA4CH;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CA+C9C"}
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../../src/tools/ctx-memory/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAQ,MAAM,qBAAqB,CAAC;AAsBhE,OAAO,EAIH,KAAK,iBAAiB,EACzB,MAAM,SAAS,CAAC;AA+cjB,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAI5F"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../../src/tools/ctx-memory/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAQ,MAAM,qBAAqB,CAAC;AAsBhE,OAAO,EAIH,KAAK,iBAAiB,EACzB,MAAM,SAAS,CAAC;AAgdjB,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAI5F"}
@@ -1,5 +1,5 @@
1
- import type { Database } from "bun:sqlite";
2
1
  import type { MemorySourceType } from "../../features/magic-context/memory";
2
+ import type { Database } from "../../shared/sqlite";
3
3
  export declare const CTX_MEMORY_ACTIONS: readonly ["write", "delete"];
4
4
  export declare const CTX_MEMORY_DREAMER_ACTIONS: readonly ["write", "delete", "list", "update", "merge", "archive"];
5
5
  export type CtxMemoryAction = (typeof CTX_MEMORY_DREAMER_ACTIONS)[number];
@@ -14,7 +14,18 @@ export interface CtxMemoryArgs {
14
14
  }
15
15
  export interface CtxMemoryToolDeps {
16
16
  db: Database;
17
- projectPath: string;
17
+ /**
18
+ * Resolve the project identity for the active session's directory.
19
+ *
20
+ * Why a function instead of a baked string: OpenCode's top-level
21
+ * `ctx.directory` is the directory the OpenCode process was started
22
+ * in (often `$HOME` when launched via `opencode -s <id>` from outside
23
+ * the project). The session's actual working directory is exposed
24
+ * per-call via `toolContext.directory`. Resolving here ensures
25
+ * `ctx_memory` operates on the session's project, not the launch
26
+ * directory's project.
27
+ */
28
+ resolveProjectPath: (directory: string) => string;
18
29
  memoryEnabled: boolean;
19
30
  embeddingEnabled: boolean;
20
31
  allowedActions?: CtxMemoryAction[];
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/tools/ctx-memory/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AAE5E,eAAO,MAAM,kBAAkB,8BAA+B,CAAC;AAE/D,eAAO,MAAM,0BAA0B,oEAM7B,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,0BAA0B,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1E,MAAM,WAAW,aAAa;IAC1B,MAAM,EAAE,eAAe,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAC9B,EAAE,EAAE,QAAQ,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,OAAO,CAAC;IACvB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,eAAe,EAAE,CAAC;IACnC,UAAU,CAAC,EAAE,gBAAgB,CAAC;CACjC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/tools/ctx-memory/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AAC5E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEpD,eAAO,MAAM,kBAAkB,8BAA+B,CAAC;AAE/D,eAAO,MAAM,0BAA0B,oEAM7B,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,0BAA0B,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1E,MAAM,WAAW,aAAa;IAC1B,MAAM,EAAE,eAAe,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAC9B,EAAE,EAAE,QAAQ,CAAC;IACb;;;;;;;;;;OAUG;IACH,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC;IAClD,aAAa,EAAE,OAAO,CAAC;IACvB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,eAAe,EAAE,CAAC;IACnC,UAAU,CAAC,EAAE,gBAAgB,CAAC;CACjC"}
@@ -1,9 +1,15 @@
1
- import type { Database } from "bun:sqlite";
2
1
  import { type ToolDefinition } from "@opencode-ai/plugin";
2
+ import type { Database } from "../../shared/sqlite";
3
3
  export interface CtxNoteToolDeps {
4
4
  db: Database;
5
5
  dreamerEnabled?: boolean;
6
- projectIdentity?: string;
6
+ /**
7
+ * Resolve the project identity for the session's directory at call time.
8
+ * See CtxMemoryToolDeps.resolveProjectPath for why this is a function.
9
+ * Optional — when undefined, smart-note creation is rejected with an
10
+ * explanatory error.
11
+ */
12
+ resolveProjectPath?: (directory: string) => string;
7
13
  }
8
14
  export declare function createCtxNoteTools(deps: CtxNoteToolDeps): Record<string, ToolDefinition>;
9
15
  //# sourceMappingURL=tools.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../../src/tools/ctx-note/tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,KAAK,cAAc,EAAQ,MAAM,qBAAqB,CAAC;AAehE,MAAM,WAAW,eAAe;IAC5B,EAAE,EAAE,QAAQ,CAAC;IACb,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC5B;AAyND,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;AA+ND,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAIxF"}
@@ -1,5 +1,5 @@
1
- import type { Database } from "bun:sqlite";
2
1
  import { type ToolDefinition } from "@opencode-ai/plugin";
2
+ import type { Database } from "../../shared/sqlite";
3
3
  export interface CtxReduceToolDeps {
4
4
  db: Database;
5
5
  protectedTags: number;
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../../src/tools/ctx-reduce/tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,KAAK,cAAc,EAAQ,MAAM,qBAAqB,CAAC;AAahE,MAAM,WAAW,iBAAiB;IAC9B,EAAE,EAAE,QAAQ,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC;CACpD;AAuGD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAI5F"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../../src/tools/ctx-reduce/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAQ,MAAM,qBAAqB,CAAC;AAUhE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAIpD,MAAM,WAAW,iBAAiB;IAC9B,EAAE,EAAE,QAAQ,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC;CACpD;AAuGD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAI5F"}
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../../src/tools/ctx-search/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAQ,MAAM,qBAAqB,CAAC;AAShE,OAAO,KAAK,EAAkC,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAyIjF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAI5F"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../../src/tools/ctx-search/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAQ,MAAM,qBAAqB,CAAC;AAShE,OAAO,KAAK,EAAkC,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAoJjF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAI5F"}
@@ -1,4 +1,4 @@
1
- import type { Database } from "bun:sqlite";
1
+ import type { Database } from "../../shared/sqlite";
2
2
  /** Sources the agent can narrow ctx_search to. Facts are intentionally NOT a
3
3
  * source — they're always rendered in <session-history> in message[0], so
4
4
  * searching them returns content already visible in context. */
@@ -11,7 +11,13 @@ export interface CtxSearchArgs {
11
11
  }
12
12
  export interface CtxSearchToolDeps {
13
13
  db: Database;
14
- projectPath: string;
14
+ /**
15
+ * Resolve the project identity for the session's directory at call time.
16
+ * See CtxMemoryToolDeps.resolveProjectPath for why this is a function:
17
+ * OpenCode's top-level `ctx.directory` reflects the launch dir, not the
18
+ * session's working directory.
19
+ */
20
+ resolveProjectPath: (directory: string) => string;
15
21
  memoryEnabled: boolean;
16
22
  embeddingEnabled: boolean;
17
23
  /** When true, ctx_search surfaces indexed git commits as a 3rd source. */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/tools/ctx-search/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C;;iEAEiE;AACjE,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,SAAS,GAAG,YAAY,CAAC;AAElE,MAAM,WAAW,aAAa;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,OAAO,CAAC,EAAE,eAAe,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,iBAAiB;IAC9B,EAAE,EAAE,QAAQ,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,OAAO,CAAC;IACvB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,0EAA0E;IAC1E,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,8EAA8E;IAC9E,YAAY,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,KAAK,CAAC;QACxC,OAAO,EAAE,MAAM,CAAC;QAChB,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,OAAO,EAAE,CAAC;KACpB,CAAC,CAAC;CACN"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/tools/ctx-search/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEpD;;iEAEiE;AACjE,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,SAAS,GAAG,YAAY,CAAC;AAElE,MAAM,WAAW,aAAa;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,OAAO,CAAC,EAAE,eAAe,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,iBAAiB;IAC9B,EAAE,EAAE,QAAQ,CAAC;IACb;;;;;OAKG;IACH,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC;IAClD,aAAa,EAAE,OAAO,CAAC;IACvB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,0EAA0E;IAC1E,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,8EAA8E;IAC9E,YAAY,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,KAAK,CAAC;QACxC,OAAO,EAAE,MAAM,CAAC;QAChB,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,OAAO,EAAE,CAAC;KACpB,CAAC,CAAC;CACN"}
@@ -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;AA4ED,sDAAsD;AACtD,wBAAsB,mBAAmB,CACrC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAClB,OAAO,CAAC,eAAe,CAAC,CA4B1B;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;AAa9C,2DAA2D;AAC3D,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAGrD;AAED,+BAA+B;AAC/B,wBAAgB,QAAQ,IAAI,IAAI,CAG/B;AA4ED,sDAAsD;AACtD,wBAAsB,mBAAmB,CACrC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAClB,OAAO,CAAC,eAAe,CAAC,CA4B1B;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,77 +1,75 @@
1
1
  {
2
- "name": "@cortexkit/opencode-magic-context",
3
- "version": "0.15.7",
4
- "type": "module",
5
- "description": "OpenCode plugin for Magic Context — cross-session memory and context management",
6
- "main": "dist/index.js",
7
- "types": "dist/index.d.ts",
8
- "bin": {
9
- "opencode-magic-context": "dist/cli.js"
10
- },
11
- "author": "ualtinok",
12
- "license": "MIT",
13
- "keywords": [
14
- "opencode",
15
- "plugin",
16
- "context",
17
- "memory",
18
- "ai",
19
- "llm",
20
- "prompt-caching",
21
- "session-history"
22
- ],
23
- "repository": {
24
- "type": "git",
25
- "url": "https://github.com/cortexkit/opencode-magic-context",
26
- "directory": "packages/plugin"
27
- },
28
- "files": [
29
- "dist",
30
- "src/tui",
31
- "src/shared",
32
- "README.md"
33
- ],
34
- "scripts": {
35
- "build": "bun build src/index.ts --outdir dist --target bun --format esm --external @opencode-ai/plugin --external @huggingface/transformers && bun build src/cli/index.ts --outfile dist/cli.js --target node --format esm && tsc --emitDeclarationOnly",
36
- "typecheck": "tsc --noEmit && tsc -p tsconfig.scripts.json",
37
- "test": "bun test",
38
- "lint": "biome check .",
39
- "lint:fix": "biome check --write .",
40
- "format": "biome format --write .",
41
- "format:check": "biome format .",
42
- "clean": "rm -rf dist",
43
- "prepublishOnly": "bun run build"
44
- },
45
- "dependencies": {
46
- "@clack/prompts": "^1.1.0",
47
- "@huggingface/transformers": "^4.1.0",
48
- "@opencode-ai/plugin": "^1.2.26",
49
- "@opencode-ai/sdk": "^1.2.26",
50
- "ai-tokenizer": "^1.0.6",
51
- "comment-json": "^4.6.2",
52
- "zod": "^4.1.8"
53
- },
54
- "devDependencies": {
55
- "@types/node": "^22.0.0",
56
- "bun-types": "^1.3.10",
57
- "typescript": "^5.8.0",
58
- "@biomejs/biome": "^2.4.7"
59
- },
60
- "exports": {
61
- ".": {
62
- "types": "./dist/index.d.ts",
63
- "import": "./dist/index.js"
64
- },
65
- "./tui": {
66
- "types": "./src/tui/index.tsx",
67
- "import": "./src/tui/index.tsx"
68
- }
69
- },
70
- "oc-plugin": [
71
- "server",
72
- "tui"
73
- ],
74
- "peerDependencies": {
75
- "@opencode-ai/plugin": ">=1.2.0"
76
- }
2
+ "name": "@cortexkit/opencode-magic-context",
3
+ "version": "0.16.1",
4
+ "type": "module",
5
+ "description": "OpenCode plugin for Magic Context — cross-session memory and context management",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "author": "ualtinok",
9
+ "license": "MIT",
10
+ "keywords": [
11
+ "opencode",
12
+ "plugin",
13
+ "context",
14
+ "memory",
15
+ "ai",
16
+ "llm",
17
+ "prompt-caching",
18
+ "session-history"
19
+ ],
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "https://github.com/cortexkit/magic-context",
23
+ "directory": "packages/plugin"
24
+ },
25
+ "files": [
26
+ "dist",
27
+ "src/tui",
28
+ "src/shared",
29
+ "README.md"
30
+ ],
31
+ "scripts": {
32
+ "build": "bun build src/index.ts --outdir dist --target node --format esm --external @opencode-ai/plugin --external @huggingface/transformers --external better-sqlite3 --external bun:sqlite && tsc --emitDeclarationOnly",
33
+ "typecheck": "tsc --noEmit && tsc -p tsconfig.scripts.json",
34
+ "test": "bun test",
35
+ "lint": "biome check .",
36
+ "lint:fix": "biome check --write .",
37
+ "format": "biome format --write .",
38
+ "format:check": "biome format .",
39
+ "clean": "rm -rf dist",
40
+ "prepublishOnly": "bun run build"
41
+ },
42
+ "dependencies": {
43
+ "@huggingface/transformers": "^4.1.0",
44
+ "@opencode-ai/plugin": "^1.2.26",
45
+ "@opencode-ai/sdk": "^1.2.26",
46
+ "ai-tokenizer": "^1.0.6",
47
+ "better-sqlite3": "^12.9.0",
48
+ "comment-json": "^4.2.5",
49
+ "zod": "^4.1.8"
50
+ },
51
+ "devDependencies": {
52
+ "@biomejs/biome": "^2.4.7",
53
+ "@types/better-sqlite3": "^7.6.13",
54
+ "@types/node": "^22.0.0",
55
+ "bun-types": "^1.3.10",
56
+ "typescript": "^5.8.0"
57
+ },
58
+ "exports": {
59
+ ".": {
60
+ "types": "./dist/index.d.ts",
61
+ "import": "./dist/index.js"
62
+ },
63
+ "./tui": {
64
+ "types": "./src/tui/index.tsx",
65
+ "import": "./src/tui/index.tsx"
66
+ }
67
+ },
68
+ "oc-plugin": [
69
+ "server",
70
+ "tui"
71
+ ],
72
+ "peerDependencies": {
73
+ "@opencode-ai/plugin": ">=1.2.0"
74
+ }
77
75
  }
@@ -50,7 +50,7 @@ describe("detectConflicts", () => {
50
50
  rmSync(userConfigDir, { recursive: true, force: true });
51
51
  });
52
52
 
53
- function writeProjectConfig(plugins: string[]): void {
53
+ function writeProjectConfig(plugins: Array<string | [string, unknown]>): void {
54
54
  writeFileSync(join(projectDir, "opencode.json"), JSON.stringify({ plugin: plugins }));
55
55
  }
56
56
 
@@ -186,4 +186,47 @@ describe("detectConflicts", () => {
186
186
  const result = detectConflicts(projectDir);
187
187
  expect(result.hasConflict).toBe(false);
188
188
  });
189
+
190
+ // --- Tuple plugin entries (issue #49) ---
191
+ // OpenCode supports ["pkg@version", { ...options }] tuple form.
192
+ // The old code spread the raw array into the plugin list, causing
193
+ // matchesPackageName to receive an array instead of a string → crash.
194
+
195
+ describe("tuple plugin entries (issue #49)", () => {
196
+ it("does not crash when a plugin is defined as a [name, options] tuple", () => {
197
+ writeProjectConfig([
198
+ "@cortexkit/opencode-magic-context@latest",
199
+ ["@plannotator/opencode@latest", { workflow: "plan-agent" }],
200
+ ]);
201
+ expect(() => detectConflicts(projectDir)).not.toThrow();
202
+ });
203
+
204
+ it("detects DCP conflict when DCP is expressed as a tuple", () => {
205
+ writeProjectConfig([
206
+ "@cortexkit/opencode-magic-context@latest",
207
+ ["@tarquinen/opencode-dcp@latest", {}],
208
+ ]);
209
+ const result = detectConflicts(projectDir);
210
+ expect(result.conflicts.dcpPlugin).toBe(true);
211
+ });
212
+
213
+ it("detects OMO conflict when OMO is expressed as a tuple", () => {
214
+ writeProjectConfig([["oh-my-opencode@latest", {}]]);
215
+ const result = detectConflicts(projectDir);
216
+ expect(result.conflicts.omoPreemptiveCompaction).toBe(true);
217
+ });
218
+
219
+ it("does not crash on mixed string and tuple entries with unrelated packages", () => {
220
+ writeProjectConfig([
221
+ "oh-my-opencode-slim",
222
+ [
223
+ "@plannotator/opencode@latest",
224
+ { workflow: "plan-agent", planningAgents: ["plan"] },
225
+ ],
226
+ "@cortexkit/opencode-magic-context@latest",
227
+ ]);
228
+ const result = detectConflicts(projectDir);
229
+ expect(result.hasConflict).toBe(false);
230
+ });
231
+ });
189
232
  });
@@ -7,7 +7,8 @@ interface OpenCodeConfig {
7
7
  auto?: boolean;
8
8
  prune?: boolean;
9
9
  };
10
- plugin?: string[];
10
+ // OpenCode allows plugins as plain strings or [name, options] tuples.
11
+ plugin?: Array<string | [string, unknown]>;
11
12
  }
12
13
 
13
14
  interface OmoConfig {
@@ -223,9 +224,28 @@ function matchesPackageName(entry: string, canonicalNames: Set<string>): boolean
223
224
  return canonicalNames.has(nameOnly);
224
225
  }
225
226
 
227
+ /** Extract the package-name string from a plugin entry.
228
+ * OpenCode supports two forms:
229
+ * - plain string: "@scope/pkg@latest"
230
+ * - tuple [name, opts]: ["@scope/pkg@latest", { ... }]
231
+ * Returns null for any other shape (numbers, objects, etc.). */
232
+ function extractPluginName(entry: string | [string, unknown]): string | null {
233
+ if (typeof entry === "string") return entry;
234
+ if (Array.isArray(entry) && typeof entry[0] === "string") return entry[0];
235
+ return null;
236
+ }
237
+
226
238
  function collectPluginEntries(directory: string): string[] {
227
239
  const plugins: string[] = [];
228
240
 
241
+ const pushFrom = (entries: Array<string | [string, unknown]> | undefined) => {
242
+ if (!entries) return;
243
+ for (const entry of entries) {
244
+ const name = extractPluginName(entry);
245
+ if (name) plugins.push(name);
246
+ }
247
+ };
248
+
229
249
  // Project-level configs
230
250
  for (const configPath of [
231
251
  join(directory, ".opencode", "opencode.jsonc"),
@@ -234,9 +254,7 @@ function collectPluginEntries(directory: string): string[] {
234
254
  join(directory, "opencode.json"),
235
255
  ]) {
236
256
  const config = readJsoncFile<OpenCodeConfig>(configPath);
237
- if (config?.plugin) {
238
- plugins.push(...config.plugin);
239
- }
257
+ pushFrom(config?.plugin);
240
258
  }
241
259
 
242
260
  // User-level config
@@ -244,9 +262,7 @@ function collectPluginEntries(directory: string): string[] {
244
262
  const paths = getOpenCodeConfigPaths({ binary: "opencode" });
245
263
  for (const configPath of [paths.configJsonc, paths.configJson]) {
246
264
  const config = readJsoncFile<OpenCodeConfig>(configPath);
247
- if (config?.plugin) {
248
- plugins.push(...config.plugin);
249
- }
265
+ pushFrom(config?.plugin);
250
266
  }
251
267
  } catch {
252
268
  // best-effort
@@ -265,7 +281,7 @@ function collectPluginEntries(directory: string): string[] {
265
281
  * `oh-my-opencode-cli`, etc.) are intentionally NOT matched here — they
266
282
  * don't ship the `preemptive-compaction`, `context-window-monitor`, or
267
283
  * `anthropic-context-window-limit-recovery` hooks that conflict with
268
- * Magic Context. See https://github.com/cortexkit/opencode-magic-context/issues/43.
284
+ * Magic Context. See https://github.com/cortexkit/magic-context/issues/43.
269
285
  *
270
286
  * The legacy `@code-yeongyu/` scope is no longer used — both names are
271
287
  * unscoped on npm.