@cortexkit/opencode-magic-context 0.16.3 → 0.17.0
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/dist/features/magic-context/message-index-async.d.ts +12 -0
- package/dist/features/magic-context/message-index-async.d.ts.map +1 -0
- package/dist/features/magic-context/message-index.d.ts +4 -0
- package/dist/features/magic-context/message-index.d.ts.map +1 -1
- package/dist/features/magic-context/migrations.d.ts +7 -0
- package/dist/features/magic-context/migrations.d.ts.map +1 -1
- package/dist/features/magic-context/search.d.ts +2 -2
- package/dist/features/magic-context/search.d.ts.map +1 -1
- package/dist/features/magic-context/storage-db.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-persisted.d.ts +3 -6
- package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
- package/dist/features/magic-context/storage-tags.d.ts +163 -1
- package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
- package/dist/features/magic-context/storage.d.ts +1 -1
- package/dist/features/magic-context/storage.d.ts.map +1 -1
- package/dist/features/magic-context/tagger.d.ts +52 -2
- package/dist/features/magic-context/tagger.d.ts.map +1 -1
- package/dist/features/magic-context/tool-definition-tokens.d.ts +26 -3
- package/dist/features/magic-context/tool-definition-tokens.d.ts.map +1 -1
- package/dist/features/magic-context/tool-owner-backfill.d.ts +90 -0
- package/dist/features/magic-context/tool-owner-backfill.d.ts.map +1 -0
- package/dist/features/magic-context/types.d.ts +17 -0
- package/dist/features/magic-context/types.d.ts.map +1 -1
- package/dist/hooks/magic-context/auto-search-runner.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-drop-queue.d.ts +23 -0
- package/dist/hooks/magic-context/compartment-runner-drop-queue.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-payloads.d.ts +8 -0
- package/dist/hooks/magic-context/event-payloads.d.ts.map +1 -1
- package/dist/hooks/magic-context/heuristic-cleanup.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook.d.ts.map +1 -1
- package/dist/hooks/magic-context/inject-compartments.d.ts +16 -0
- package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
- package/dist/hooks/magic-context/nudger.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-chunk.d.ts +24 -1
- package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-db.d.ts +1 -0
- package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-raw.d.ts +1 -0
- package/dist/hooks/magic-context/read-session-raw.d.ts.map +1 -1
- package/dist/hooks/magic-context/strip-content.d.ts +9 -6
- package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
- package/dist/hooks/magic-context/tag-messages.d.ts +1 -1
- package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
- package/dist/hooks/magic-context/tool-drop-target.d.ts +16 -1
- package/dist/hooks/magic-context/tool-drop-target.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +0 -11
- 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.d.ts.map +1 -1
- package/dist/index.js +1731 -758
- package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
- package/dist/plugin/rpc-handlers.d.ts +3 -0
- package/dist/plugin/rpc-handlers.d.ts.map +1 -1
- package/dist/shared/models-dev-cache.d.ts +3 -10
- package/dist/shared/models-dev-cache.d.ts.map +1 -1
- package/dist/shared/tag-transcript.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/shared/models-dev-cache.test.ts +64 -57
- package/src/shared/models-dev-cache.ts +49 -68
- package/src/shared/tag-transcript.ts +137 -126
- package/dist/hooks/magic-context/reasoning-capability.d.ts +0 -23
- package/dist/hooks/magic-context/reasoning-capability.d.ts.map +0 -1
|
@@ -146,151 +146,156 @@ export function tagTranscript(
|
|
|
146
146
|
// across both invocation and result.
|
|
147
147
|
const toolAggregates = new Map<string, ToolAggregate & { tagId: number }>();
|
|
148
148
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
149
|
+
// v3.3.1 Layer C (plan v3.3.1 Finding #16): the previous outer
|
|
150
|
+
// db.transaction() wrapper rolled back EVERY tag insert + savedSource
|
|
151
|
+
// when a single UNIQUE collision fired late in the walk. Per-tag
|
|
152
|
+
// SAVEPOINTs inside `assignToolTag` / `assignTag` already give us the
|
|
153
|
+
// atomicity we need. Removing the wrapper matches OpenCode's
|
|
154
|
+
// tag-messages.ts design — see the long comment there for the
|
|
155
|
+
// rationale (cache-bust amplifier story).
|
|
156
|
+
for (let msgIndex = 0; msgIndex < transcript.messages.length; msgIndex += 1) {
|
|
157
|
+
const message = transcript.messages[msgIndex];
|
|
158
|
+
if (message === undefined) continue;
|
|
159
|
+
const messageId = message.info.id;
|
|
154
160
|
|
|
155
|
-
|
|
161
|
+
let textOrdinal = 0;
|
|
156
162
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
163
|
+
for (let partIndex = 0; partIndex < message.parts.length; partIndex += 1) {
|
|
164
|
+
const part = message.parts[partIndex];
|
|
165
|
+
if (part === undefined) continue;
|
|
160
166
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
167
|
+
if (part.kind === "text") {
|
|
168
|
+
// Synthetic message ids (Pi tail synthetic user with
|
|
169
|
+
// no id) cannot be tagged — there's no stable handle
|
|
170
|
+
// to bind a tag to across passes. Pass through
|
|
171
|
+
// untagged; this is rare (only happens for the
|
|
172
|
+
// dangling tool-result tail case in Pi).
|
|
173
|
+
if (messageId === undefined) {
|
|
174
|
+
textOrdinal += 1;
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
tagTextPart({
|
|
178
|
+
sessionId,
|
|
179
|
+
message,
|
|
180
|
+
messageId,
|
|
181
|
+
msgIndex,
|
|
182
|
+
textOrdinal,
|
|
183
|
+
part,
|
|
184
|
+
tagger,
|
|
185
|
+
db,
|
|
186
|
+
targets,
|
|
187
|
+
skipPrefixInjection,
|
|
188
|
+
});
|
|
189
|
+
textOrdinal += 1;
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (part.kind === "tool_use" || part.kind === "tool_result") {
|
|
194
|
+
if (messageId === undefined) continue;
|
|
195
|
+
|
|
196
|
+
const callId = part.id;
|
|
197
|
+
const text = part.getText() ?? "";
|
|
198
|
+
const meta = part.getToolMetadata();
|
|
199
|
+
|
|
200
|
+
if (typeof callId !== "string" || callId.length === 0) {
|
|
201
|
+
// No stable callId to aggregate on. Tag independently.
|
|
202
|
+
tagToolPart({
|
|
172
203
|
sessionId,
|
|
173
204
|
message,
|
|
174
205
|
messageId,
|
|
175
206
|
msgIndex,
|
|
176
|
-
|
|
207
|
+
partIndex,
|
|
177
208
|
part,
|
|
178
209
|
tagger,
|
|
179
210
|
db,
|
|
180
211
|
targets,
|
|
181
212
|
skipPrefixInjection,
|
|
182
213
|
});
|
|
183
|
-
textOrdinal += 1;
|
|
184
214
|
continue;
|
|
185
215
|
}
|
|
186
216
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
part,
|
|
203
|
-
tagger,
|
|
204
|
-
db,
|
|
205
|
-
targets,
|
|
206
|
-
skipPrefixInjection,
|
|
207
|
-
});
|
|
208
|
-
continue;
|
|
217
|
+
const existing = toolAggregates.get(callId);
|
|
218
|
+
if (existing) {
|
|
219
|
+
// Second (or later) occurrence for this call_id.
|
|
220
|
+
// Merge into the existing aggregate, update byte_size
|
|
221
|
+
// in DB if larger, and rebuild the TagTarget so the
|
|
222
|
+
// closures over `occurrences` see all parts.
|
|
223
|
+
existing.occurrences.push({
|
|
224
|
+
message,
|
|
225
|
+
part,
|
|
226
|
+
kind: part.kind,
|
|
227
|
+
});
|
|
228
|
+
const newByteSize = byteSize(text);
|
|
229
|
+
if (newByteSize > existing.maxByteSize) {
|
|
230
|
+
existing.maxByteSize = newByteSize;
|
|
231
|
+
updateTagByteSize(db, sessionId, existing.tagId, newByteSize);
|
|
209
232
|
}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
occurrences: [
|
|
270
|
-
{
|
|
271
|
-
message,
|
|
272
|
-
part,
|
|
273
|
-
kind: part.kind,
|
|
274
|
-
},
|
|
275
|
-
],
|
|
276
|
-
maxByteSize: byteSize(text),
|
|
277
|
-
toolName: meta.toolName ?? null,
|
|
278
|
-
inputByteSize: part.kind === "tool_use" ? meta.inputByteSize : 0,
|
|
279
|
-
};
|
|
280
|
-
toolAggregates.set(callId, aggregate);
|
|
281
|
-
// Inject §N§ prefix into this occurrence's visible text
|
|
282
|
-
// when it's a tool_result. (OpenCode parity: prefix
|
|
283
|
-
// only goes on the result, not the invocation.)
|
|
284
|
-
if (!skipPrefixInjection && part.kind === "tool_result") {
|
|
285
|
-
part.setText(prependTag(tagId, text));
|
|
286
|
-
}
|
|
287
|
-
targets.set(tagId, buildAggregateTarget(tagId, aggregate.occurrences));
|
|
233
|
+
if (existing.toolName === null && meta.toolName) {
|
|
234
|
+
existing.toolName = meta.toolName;
|
|
235
|
+
}
|
|
236
|
+
if (
|
|
237
|
+
existing.inputByteSize === 0 &&
|
|
238
|
+
part.kind === "tool_use" &&
|
|
239
|
+
meta.inputByteSize > 0
|
|
240
|
+
) {
|
|
241
|
+
existing.inputByteSize = meta.inputByteSize;
|
|
242
|
+
updateTagInputByteSize(db, sessionId, existing.tagId, meta.inputByteSize);
|
|
243
|
+
}
|
|
244
|
+
// Inject §N§ prefix into this tool_result occurrence
|
|
245
|
+
// (matches OpenCode behavior — only result gets the prefix).
|
|
246
|
+
if (!skipPrefixInjection && part.kind === "tool_result") {
|
|
247
|
+
part.setText(prependTag(existing.tagId, text));
|
|
248
|
+
}
|
|
249
|
+
// Rebuild the aggregate target so it walks the now-
|
|
250
|
+
// longer occurrences list.
|
|
251
|
+
targets.set(
|
|
252
|
+
existing.tagId,
|
|
253
|
+
buildAggregateTarget(existing.tagId, existing.occurrences),
|
|
254
|
+
);
|
|
255
|
+
} else {
|
|
256
|
+
// First occurrence — reserve the tag number.
|
|
257
|
+
// v3.3.1 Layer C: Pi main aggregation path. Owner
|
|
258
|
+
// is the Pi message hosting the tool aggregate.
|
|
259
|
+
// Owner stays stable across passes because Pi
|
|
260
|
+
// re-emits the full transcript each time and
|
|
261
|
+
// message ids are durable.
|
|
262
|
+
const tagId = tagger.assignToolTag(
|
|
263
|
+
sessionId,
|
|
264
|
+
callId,
|
|
265
|
+
messageId,
|
|
266
|
+
byteSize(text),
|
|
267
|
+
db,
|
|
268
|
+
0,
|
|
269
|
+
meta.toolName ?? null,
|
|
270
|
+
meta.inputByteSize,
|
|
271
|
+
);
|
|
272
|
+
const aggregate = {
|
|
273
|
+
callId,
|
|
274
|
+
tagId,
|
|
275
|
+
occurrences: [
|
|
276
|
+
{
|
|
277
|
+
message,
|
|
278
|
+
part,
|
|
279
|
+
kind: part.kind,
|
|
280
|
+
},
|
|
281
|
+
],
|
|
282
|
+
maxByteSize: byteSize(text),
|
|
283
|
+
toolName: meta.toolName ?? null,
|
|
284
|
+
inputByteSize: part.kind === "tool_use" ? meta.inputByteSize : 0,
|
|
285
|
+
};
|
|
286
|
+
toolAggregates.set(callId, aggregate);
|
|
287
|
+
// Inject §N§ prefix into this occurrence's visible text
|
|
288
|
+
// when it's a tool_result. (OpenCode parity: prefix
|
|
289
|
+
// only goes on the result, not the invocation.)
|
|
290
|
+
if (!skipPrefixInjection && part.kind === "tool_result") {
|
|
291
|
+
part.setText(prependTag(tagId, text));
|
|
288
292
|
}
|
|
293
|
+
targets.set(tagId, buildAggregateTarget(tagId, aggregate.occurrences));
|
|
289
294
|
}
|
|
290
|
-
// thinking, image, file, structural, unknown → skip.
|
|
291
295
|
}
|
|
296
|
+
// thinking, image, file, structural, unknown → skip.
|
|
292
297
|
}
|
|
293
|
-
}
|
|
298
|
+
}
|
|
294
299
|
|
|
295
300
|
return { targets };
|
|
296
301
|
}
|
|
@@ -366,10 +371,16 @@ function tagToolPart(args: TagToolPartArgs): void {
|
|
|
366
371
|
const contentId = stableId ?? `${args.messageId}:t${args.partIndex}`;
|
|
367
372
|
const text = args.part.getText() ?? "";
|
|
368
373
|
const meta = args.part.getToolMetadata();
|
|
369
|
-
|
|
374
|
+
// v3.3.1 Layer C: synthetic ownership for the no-callId Pi
|
|
375
|
+
// fallback. Owner == callId == contentId. The composite key
|
|
376
|
+
// collapses to a unique synthetic identifier per part, preserving
|
|
377
|
+
// the legacy "each part gets its own tag" behavior while
|
|
378
|
+
// satisfying the composite-identity contract (TagEntry.tool_owner_message_id
|
|
379
|
+
// is non-null, lazy-adoption path is correctly bypassed).
|
|
380
|
+
const tagId = args.tagger.assignToolTag(
|
|
370
381
|
args.sessionId,
|
|
371
382
|
contentId,
|
|
372
|
-
|
|
383
|
+
contentId,
|
|
373
384
|
byteSize(text),
|
|
374
385
|
args.db,
|
|
375
386
|
0,
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
export interface LiveSessionModel {
|
|
2
|
-
providerID: string;
|
|
3
|
-
modelID: string;
|
|
4
|
-
}
|
|
5
|
-
/**
|
|
6
|
-
* Return true when the session's current model exposes an interleaved
|
|
7
|
-
* reasoning field (for example `reasoning_content`). In that mode OpenCode's
|
|
8
|
-
* provider transform concatenates typed `reasoning` parts into a top-level
|
|
9
|
-
* wire field and strips those parts from `content` afterwards.
|
|
10
|
-
*
|
|
11
|
-
* Magic-context's older reasoning cleanup rewrites aged reasoning to the
|
|
12
|
-
* literal string `[cleared]` and then removes those reasoning parts entirely.
|
|
13
|
-
* That is safe for providers that treat reasoning as optional local context,
|
|
14
|
-
* but it breaks providers like Moonshot/Kimi: once we remove all reasoning
|
|
15
|
-
* parts from an assistant tool-call message, OpenCode emits no
|
|
16
|
-
* `reasoning_content` field and the provider rejects the request.
|
|
17
|
-
*
|
|
18
|
-
* Unknown models return false on purpose. We only disable stripping when the
|
|
19
|
-
* cache explicitly says the provider requires interleaved reasoning; guessing
|
|
20
|
-
* true would preserve extra context for models that do not need it.
|
|
21
|
-
*/
|
|
22
|
-
export declare function modelRequiresInterleavedReasoning(model: LiveSessionModel | undefined): boolean;
|
|
23
|
-
//# sourceMappingURL=reasoning-capability.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"reasoning-capability.d.ts","sourceRoot":"","sources":["../../../src/hooks/magic-context/reasoning-capability.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,gBAAgB;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iCAAiC,CAAC,KAAK,EAAE,gBAAgB,GAAG,SAAS,GAAG,OAAO,CAO9F"}
|