@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.
- package/README.md +42 -16
- package/dist/agents/magic-context-prompt.d.ts +2 -13
- package/dist/agents/magic-context-prompt.d.ts.map +1 -1
- package/dist/config/schema/magic-context.d.ts +67 -4
- package/dist/config/schema/magic-context.d.ts.map +1 -1
- package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
- package/dist/features/magic-context/compaction.d.ts +1 -1
- package/dist/features/magic-context/compaction.d.ts.map +1 -1
- package/dist/features/magic-context/compartment-storage.d.ts +1 -1
- package/dist/features/magic-context/compartment-storage.d.ts.map +1 -1
- package/dist/features/magic-context/compression-depth-storage.d.ts +1 -1
- package/dist/features/magic-context/compression-depth-storage.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/lease.d.ts +1 -1
- package/dist/features/magic-context/dreamer/lease.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/queue.d.ts +8 -3
- package/dist/features/magic-context/dreamer/queue.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/runner.d.ts +1 -1
- package/dist/features/magic-context/dreamer/runner.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/scheduler.d.ts +1 -1
- package/dist/features/magic-context/dreamer/scheduler.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/storage-dream-runs.d.ts +1 -1
- package/dist/features/magic-context/dreamer/storage-dream-runs.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/storage-dream-state.d.ts +1 -1
- package/dist/features/magic-context/dreamer/storage-dream-state.d.ts.map +1 -1
- package/dist/features/magic-context/git-commits/indexer.d.ts +1 -1
- package/dist/features/magic-context/git-commits/indexer.d.ts.map +1 -1
- package/dist/features/magic-context/git-commits/search-git-commits.d.ts +1 -1
- package/dist/features/magic-context/git-commits/search-git-commits.d.ts.map +1 -1
- package/dist/features/magic-context/git-commits/storage-git-commit-embeddings.d.ts +1 -1
- package/dist/features/magic-context/git-commits/storage-git-commit-embeddings.d.ts.map +1 -1
- package/dist/features/magic-context/git-commits/storage-git-commits.d.ts +1 -1
- package/dist/features/magic-context/git-commits/storage-git-commits.d.ts.map +1 -1
- package/dist/features/magic-context/key-files/identify-key-files.d.ts +1 -1
- package/dist/features/magic-context/key-files/identify-key-files.d.ts.map +1 -1
- package/dist/features/magic-context/key-files/read-stats.d.ts +1 -1
- package/dist/features/magic-context/key-files/read-stats.d.ts.map +1 -1
- package/dist/features/magic-context/key-files/storage-key-files.d.ts +1 -1
- package/dist/features/magic-context/key-files/storage-key-files.d.ts.map +1 -1
- package/dist/features/magic-context/memory/embedding-backfill.d.ts +1 -1
- package/dist/features/magic-context/memory/embedding-backfill.d.ts.map +1 -1
- package/dist/features/magic-context/memory/embedding-cache.d.ts +1 -1
- package/dist/features/magic-context/memory/embedding-cache.d.ts.map +1 -1
- package/dist/features/magic-context/memory/embedding-local.d.ts.map +1 -1
- package/dist/features/magic-context/memory/embedding.d.ts +1 -1
- package/dist/features/magic-context/memory/embedding.d.ts.map +1 -1
- package/dist/features/magic-context/memory/normalize-hash.d.ts.map +1 -1
- package/dist/features/magic-context/memory/project-identity.d.ts.map +1 -1
- package/dist/features/magic-context/memory/promotion.d.ts +1 -1
- package/dist/features/magic-context/memory/promotion.d.ts.map +1 -1
- package/dist/features/magic-context/memory/storage-memory-embeddings.d.ts +1 -1
- package/dist/features/magic-context/memory/storage-memory-embeddings.d.ts.map +1 -1
- package/dist/features/magic-context/memory/storage-memory-fts.d.ts +1 -1
- package/dist/features/magic-context/memory/storage-memory-fts.d.ts.map +1 -1
- package/dist/features/magic-context/memory/storage-memory.d.ts +1 -1
- package/dist/features/magic-context/memory/storage-memory.d.ts.map +1 -1
- package/dist/features/magic-context/message-index.d.ts +1 -1
- package/dist/features/magic-context/message-index.d.ts.map +1 -1
- package/dist/features/magic-context/migrations.d.ts +1 -1
- package/dist/features/magic-context/migrations.d.ts.map +1 -1
- package/dist/features/magic-context/mock-database.d.ts +1 -1
- package/dist/features/magic-context/mock-database.d.ts.map +1 -1
- package/dist/features/magic-context/plugin-messages.d.ts +1 -1
- package/dist/features/magic-context/plugin-messages.d.ts.map +1 -1
- package/dist/features/magic-context/search.d.ts +1 -1
- package/dist/features/magic-context/search.d.ts.map +1 -1
- package/dist/features/magic-context/sidekick/agent.d.ts +2 -1
- package/dist/features/magic-context/sidekick/agent.d.ts.map +1 -1
- package/dist/features/magic-context/sidekick/core.d.ts +38 -0
- package/dist/features/magic-context/sidekick/core.d.ts.map +1 -0
- package/dist/features/magic-context/storage-db.d.ts +20 -1
- package/dist/features/magic-context/storage-db.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-persisted.d.ts +1 -1
- package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-session.d.ts +1 -1
- package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-shared.d.ts +1 -1
- package/dist/features/magic-context/storage-meta-shared.d.ts.map +1 -1
- package/dist/features/magic-context/storage-notes.d.ts +1 -1
- package/dist/features/magic-context/storage-notes.d.ts.map +1 -1
- package/dist/features/magic-context/storage-ops.d.ts +1 -1
- package/dist/features/magic-context/storage-ops.d.ts.map +1 -1
- package/dist/features/magic-context/storage-source.d.ts +1 -1
- package/dist/features/magic-context/storage-source.d.ts.map +1 -1
- package/dist/features/magic-context/storage-tags.d.ts +17 -1
- package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
- package/dist/features/magic-context/tagger.d.ts +1 -1
- package/dist/features/magic-context/tagger.d.ts.map +1 -1
- package/dist/features/magic-context/user-memory/review-user-memories.d.ts +1 -1
- package/dist/features/magic-context/user-memory/review-user-memories.d.ts.map +1 -1
- package/dist/features/magic-context/user-memory/storage-user-memory.d.ts +1 -1
- package/dist/features/magic-context/user-memory/storage-user-memory.d.ts.map +1 -1
- package/dist/hooks/magic-context/auto-search-hint.d.ts.map +1 -1
- package/dist/hooks/magic-context/auto-search-runner.d.ts +1 -1
- package/dist/hooks/magic-context/auto-search-runner.d.ts.map +1 -1
- package/dist/hooks/magic-context/command-handler.d.ts +1 -1
- package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/compaction-marker-manager.d.ts +1 -1
- package/dist/hooks/magic-context/compaction-marker-manager.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-prompt.d.ts +1 -0
- package/dist/hooks/magic-context/compartment-prompt.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-compressor.d.ts +1 -1
- package/dist/hooks/magic-context/compartment-runner-compressor.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-drop-queue.d.ts +1 -1
- package/dist/hooks/magic-context/compartment-runner-drop-queue.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-incremental.d.ts +1 -0
- package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-recomp.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-types.d.ts +1 -1
- package/dist/hooks/magic-context/compartment-runner-types.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-trigger.d.ts +1 -1
- package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -1
- package/dist/hooks/magic-context/execute-flush.d.ts +1 -1
- package/dist/hooks/magic-context/execute-flush.d.ts.map +1 -1
- package/dist/hooks/magic-context/execute-status.d.ts +1 -1
- package/dist/hooks/magic-context/execute-status.d.ts.map +1 -1
- package/dist/hooks/magic-context/historian-state-file.d.ts +29 -0
- package/dist/hooks/magic-context/historian-state-file.d.ts.map +1 -0
- package/dist/hooks/magic-context/hook.d.ts.map +1 -1
- package/dist/hooks/magic-context/inject-compartments.d.ts +1 -1
- package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
- package/dist/hooks/magic-context/note-nudger.d.ts +1 -1
- package/dist/hooks/magic-context/note-nudger.d.ts.map +1 -1
- package/dist/hooks/magic-context/nudge-placement-store.d.ts +1 -1
- package/dist/hooks/magic-context/nudge-placement-store.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-chunk.d.ts +39 -0
- package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-db.d.ts +1 -1
- package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-raw.d.ts +1 -1
- package/dist/hooks/magic-context/read-session-raw.d.ts.map +1 -1
- package/dist/hooks/magic-context/send-session-notification.d.ts.map +1 -1
- package/dist/hooks/magic-context/system-prompt-hash.d.ts +6 -5
- package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform.d.ts.map +1 -1
- package/dist/index.js +8284 -8166
- package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
- package/dist/plugin/messages-transform.d.ts +1 -1
- package/dist/plugin/rpc-handlers.d.ts +4 -0
- package/dist/plugin/rpc-handlers.d.ts.map +1 -1
- package/dist/plugin/tool-registry.d.ts.map +1 -1
- package/dist/shared/conflict-detector.d.ts.map +1 -1
- package/dist/shared/data-path.d.ts +22 -0
- package/dist/shared/data-path.d.ts.map +1 -1
- package/dist/shared/harness.d.ts +43 -0
- package/dist/shared/harness.d.ts.map +1 -0
- package/dist/shared/rpc-notifications.d.ts +4 -2
- package/dist/shared/rpc-notifications.d.ts.map +1 -1
- package/dist/shared/sqlite-helpers.d.ts +16 -0
- package/dist/shared/sqlite-helpers.d.ts.map +1 -0
- package/dist/shared/sqlite.d.ts +55 -0
- package/dist/shared/sqlite.d.ts.map +1 -0
- package/dist/shared/subagent-runner.d.ts +202 -0
- package/dist/shared/subagent-runner.d.ts.map +1 -0
- package/dist/shared/tag-transcript.d.ts +66 -0
- package/dist/shared/tag-transcript.d.ts.map +1 -0
- package/dist/shared/transcript-opencode.d.ts +71 -0
- package/dist/shared/transcript-opencode.d.ts.map +1 -0
- package/dist/shared/transcript.d.ts +212 -0
- package/dist/shared/transcript.d.ts.map +1 -0
- package/dist/shared/tui-config.d.ts.map +1 -1
- package/dist/tools/ctx-memory/tools.d.ts.map +1 -1
- package/dist/tools/ctx-memory/types.d.ts +13 -2
- package/dist/tools/ctx-memory/types.d.ts.map +1 -1
- package/dist/tools/ctx-note/tools.d.ts +8 -2
- package/dist/tools/ctx-note/tools.d.ts.map +1 -1
- package/dist/tools/ctx-reduce/tools.d.ts +1 -1
- package/dist/tools/ctx-reduce/tools.d.ts.map +1 -1
- package/dist/tools/ctx-search/tools.d.ts.map +1 -1
- package/dist/tools/ctx-search/types.d.ts +8 -2
- package/dist/tools/ctx-search/types.d.ts.map +1 -1
- package/dist/tui/data/context-db.d.ts.map +1 -1
- package/package.json +73 -75
- package/src/shared/conflict-detector.test.ts +44 -1
- package/src/shared/conflict-detector.ts +24 -8
- package/src/shared/data-path.test.ts +53 -1
- package/src/shared/data-path.ts +28 -0
- package/src/shared/harness.ts +61 -0
- package/src/shared/rpc-notifications.ts +11 -5
- package/src/shared/sqlite-helpers.ts +27 -0
- package/src/shared/sqlite.ts +91 -0
- package/src/shared/subagent-runner.ts +206 -0
- package/src/shared/tag-transcript.ts +541 -0
- package/src/shared/transcript-opencode.ts +259 -0
- package/src/shared/transcript.ts +226 -0
- package/src/shared/tui-config.ts +34 -8
- package/src/tui/data/context-db.ts +5 -1
- package/dist/cli/config-paths.d.ts +0 -11
- package/dist/cli/config-paths.d.ts.map +0 -1
- package/dist/cli/diagnostics.d.ts +0 -82
- package/dist/cli/diagnostics.d.ts.map +0 -1
- package/dist/cli/doctor.d.ts +0 -5
- package/dist/cli/doctor.d.ts.map +0 -1
- package/dist/cli/index.d.ts +0 -3
- package/dist/cli/index.d.ts.map +0 -1
- package/dist/cli/logs.d.ts +0 -22
- package/dist/cli/logs.d.ts.map +0 -1
- package/dist/cli/opencode-helpers.d.ts +0 -19
- package/dist/cli/opencode-helpers.d.ts.map +0 -1
- package/dist/cli/prompts.d.ts +0 -14
- package/dist/cli/prompts.d.ts.map +0 -1
- package/dist/cli/setup.d.ts +0 -2
- package/dist/cli/setup.d.ts.map +0 -1
- 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;
|
|
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;
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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,
|
|
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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../../src/tools/ctx-reduce/tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
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;
|
|
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 "
|
|
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
|
-
|
|
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,
|
|
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;
|
|
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
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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/
|
|
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.
|