@codemem/opencode-plugin 0.45.0 → 0.46.0-alpha.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/.opencode/lib/compat.js +4 -1
- package/.opencode/lib/opencode-v2-adapter.js +1 -1
- package/.opencode/lib/raw-event-delivery.js +451 -0
- package/.opencode/lib/raw-event-spool.js +42 -7
- package/.opencode/lib/recall-lifecycle.js +324 -0
- package/.opencode/lib/runtime.js +115 -699
- package/package.json +1 -1
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
export const MAX_MESSAGE_INJECTION_CACHE_SESSIONS = 20;
|
|
2
|
+
export const MAX_MESSAGE_INJECTION_CACHE_ENTRIES = 100;
|
|
3
|
+
|
|
4
|
+
const MAX_ATTEMPT_ENTRIES = 2000;
|
|
5
|
+
|
|
6
|
+
const trimOldest = (entries, maximum) => {
|
|
7
|
+
while (entries.size > maximum) {
|
|
8
|
+
const oldest = entries.keys().next().value;
|
|
9
|
+
if (!oldest) break;
|
|
10
|
+
entries.delete(oldest);
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const getSessionMessageInjectionCache = (messageInjectionCache, sessionID) => {
|
|
15
|
+
if (!sessionID) return null;
|
|
16
|
+
const cacheKey = sessionID;
|
|
17
|
+
let sessionCache = messageInjectionCache.get(cacheKey);
|
|
18
|
+
if (sessionCache) messageInjectionCache.delete(cacheKey);
|
|
19
|
+
else sessionCache = new Map();
|
|
20
|
+
messageInjectionCache.set(cacheKey, sessionCache);
|
|
21
|
+
trimOldest(messageInjectionCache, MAX_MESSAGE_INJECTION_CACHE_SESSIONS);
|
|
22
|
+
return sessionCache;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const setSessionMessageInjectionCacheEntry = (
|
|
26
|
+
sessionCache,
|
|
27
|
+
messageID,
|
|
28
|
+
value,
|
|
29
|
+
{ preserveMessageIDs = new Set(), evictionSnapshot = null } = {},
|
|
30
|
+
) => {
|
|
31
|
+
sessionCache.delete(messageID);
|
|
32
|
+
sessionCache.set(messageID, value);
|
|
33
|
+
while (sessionCache.size > MAX_MESSAGE_INJECTION_CACHE_ENTRIES) {
|
|
34
|
+
const oldestMessageID = [...sessionCache.keys()].find((id) =>
|
|
35
|
+
!preserveMessageIDs.has(id)
|
|
36
|
+
&& (!evictionSnapshot || (evictionSnapshot.has(id) && evictionSnapshot.get(id) === sessionCache.get(id))),
|
|
37
|
+
);
|
|
38
|
+
if (!oldestMessageID) break;
|
|
39
|
+
sessionCache.delete(oldestMessageID);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const createSessionFinalizationMutex = () => {
|
|
44
|
+
const tails = new Map();
|
|
45
|
+
return async (sessionID) => {
|
|
46
|
+
if (!sessionID) return () => {};
|
|
47
|
+
const key = String(sessionID);
|
|
48
|
+
const previous = tails.get(key) || Promise.resolve();
|
|
49
|
+
let releaseOwner = () => {};
|
|
50
|
+
const owner = new Promise((resolve) => { releaseOwner = resolve; });
|
|
51
|
+
tails.set(key, owner);
|
|
52
|
+
await previous;
|
|
53
|
+
let released = false;
|
|
54
|
+
return () => {
|
|
55
|
+
if (released) return;
|
|
56
|
+
released = true;
|
|
57
|
+
releaseOwner();
|
|
58
|
+
if (tails.get(key) === owner) tails.delete(key);
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const createAttemptMetadata = (getPromptCounter) => {
|
|
64
|
+
const attemptStartedAt = new Map();
|
|
65
|
+
return (identity, sessionID = null, promptNumber = getPromptCounter()) => ({
|
|
66
|
+
attempt_id: identity.attemptId,
|
|
67
|
+
started_at: (() => {
|
|
68
|
+
const existing = attemptStartedAt.get(identity.attemptId);
|
|
69
|
+
if (existing) return existing;
|
|
70
|
+
const created = new Date().toISOString();
|
|
71
|
+
attemptStartedAt.set(identity.attemptId, created);
|
|
72
|
+
trimOldest(attemptStartedAt, MAX_ATTEMPT_ENTRIES);
|
|
73
|
+
return created;
|
|
74
|
+
})(),
|
|
75
|
+
source: "opencode",
|
|
76
|
+
...(sessionID ? { stream_id: String(sessionID), source_session_id: String(sessionID) } : {}),
|
|
77
|
+
...(promptNumber > 0 ? { prompt_number: promptNumber } : {}),
|
|
78
|
+
request_id: identity.requestId,
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const createSkipRecorder = ({
|
|
83
|
+
createIdentity,
|
|
84
|
+
emptyQueryHash,
|
|
85
|
+
runPromptPackLedger,
|
|
86
|
+
attemptMetadata,
|
|
87
|
+
getPromptCounter,
|
|
88
|
+
defaultSurface,
|
|
89
|
+
}) => {
|
|
90
|
+
const disabledInjectionRecorded = new Set();
|
|
91
|
+
const latestPolicySkips = new Map();
|
|
92
|
+
let skippedAttemptCounter = 0;
|
|
93
|
+
const record = (failureCode, sessionID = null, surface = defaultSurface, requestKey = null) => {
|
|
94
|
+
const memoKey = `${surface}:${String(sessionID || "unknown")}`;
|
|
95
|
+
if (requestKey) {
|
|
96
|
+
const signature = `${requestKey}:${failureCode}`;
|
|
97
|
+
if (latestPolicySkips.get(memoKey) === signature) return null;
|
|
98
|
+
latestPolicySkips.delete(memoKey);
|
|
99
|
+
latestPolicySkips.set(memoKey, signature);
|
|
100
|
+
trimOldest(latestPolicySkips, MAX_MESSAGE_INJECTION_CACHE_SESSIONS);
|
|
101
|
+
}
|
|
102
|
+
if (failureCode === "injection_disabled" && disabledInjectionRecorded.has(memoKey)) return null;
|
|
103
|
+
if (failureCode === "injection_disabled") disabledInjectionRecorded.add(memoKey);
|
|
104
|
+
const eventKey = requestKey
|
|
105
|
+
|| (failureCode === "injection_disabled" ? "once" : `event-${++skippedAttemptCounter}`);
|
|
106
|
+
const identity = createIdentity({
|
|
107
|
+
sessionID: sessionID || "unknown",
|
|
108
|
+
requestKey: `${failureCode}:${eventKey}`,
|
|
109
|
+
surface,
|
|
110
|
+
promptNumber: getPromptCounter(),
|
|
111
|
+
queryHash: emptyQueryHash,
|
|
112
|
+
});
|
|
113
|
+
void runPromptPackLedger({
|
|
114
|
+
action: "record",
|
|
115
|
+
...attemptMetadata(identity, sessionID),
|
|
116
|
+
retrieval_status: "skipped",
|
|
117
|
+
failure_code: failureCode,
|
|
118
|
+
failure_stage: "policy",
|
|
119
|
+
});
|
|
120
|
+
return identity.attemptId;
|
|
121
|
+
};
|
|
122
|
+
return {
|
|
123
|
+
record,
|
|
124
|
+
startSession: () => {
|
|
125
|
+
disabledInjectionRecorded.delete("message:unknown");
|
|
126
|
+
disabledInjectionRecorded.delete("system:unknown");
|
|
127
|
+
skippedAttemptCounter = 0;
|
|
128
|
+
},
|
|
129
|
+
clearSession: (sessionID) => {
|
|
130
|
+
disabledInjectionRecorded.delete(`message:${sessionID}`);
|
|
131
|
+
disabledInjectionRecorded.delete(`system:${sessionID}`);
|
|
132
|
+
latestPolicySkips.delete(`message:${sessionID}`);
|
|
133
|
+
latestPolicySkips.delete(`system:${sessionID}`);
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const createCacheReuseRecorder = ({
|
|
139
|
+
createIdentity,
|
|
140
|
+
emptyQueryHash,
|
|
141
|
+
runPromptPackLedger,
|
|
142
|
+
attemptMetadata,
|
|
143
|
+
getPromptCounter,
|
|
144
|
+
}) => (cached, { messageId, sessionID, surface = "message" } = {}) => {
|
|
145
|
+
cached.reuseCount = (cached.reuseCount || 0) + 1;
|
|
146
|
+
const promptNumber = cached.promptNumber || getPromptCounter();
|
|
147
|
+
const identity = createIdentity({
|
|
148
|
+
sessionID: sessionID || "unknown",
|
|
149
|
+
requestKey: `${messageId || "unknown"}:cache:${cached.reuseCount}`,
|
|
150
|
+
surface,
|
|
151
|
+
promptNumber,
|
|
152
|
+
queryHash: cached.queryHash || emptyQueryHash,
|
|
153
|
+
});
|
|
154
|
+
const ready = runPromptPackLedger({
|
|
155
|
+
action: "cache_reuse",
|
|
156
|
+
...attemptMetadata(identity, sessionID, promptNumber),
|
|
157
|
+
original_attempt_id: cached.attemptId,
|
|
158
|
+
});
|
|
159
|
+
return { attemptId: identity.attemptId, ready };
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
const createDeliveryConfirmer = (runPromptPackLedger) =>
|
|
163
|
+
(attemptId, deliveryStatus = "handed_off", evaluation) => {
|
|
164
|
+
const delivery = { action: "delivery", attempt_id: attemptId, delivery_status: deliveryStatus };
|
|
165
|
+
void runPromptPackLedger({ ...delivery, ...evaluation }).then((result) => {
|
|
166
|
+
if (
|
|
167
|
+
evaluation
|
|
168
|
+
&& result?.transport === "viewer"
|
|
169
|
+
&& result.failureKind === "viewer_contract_unsupported"
|
|
170
|
+
) {
|
|
171
|
+
return runPromptPackLedger(delivery, { viewerOnly: true });
|
|
172
|
+
}
|
|
173
|
+
if (evaluation && result?.transport === "cli" && result.exitCode !== 0) {
|
|
174
|
+
return runPromptPackLedger(delivery);
|
|
175
|
+
}
|
|
176
|
+
}).catch(() => {});
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
const completeDeferredDelivery = async ({
|
|
180
|
+
status,
|
|
181
|
+
commits,
|
|
182
|
+
pending,
|
|
183
|
+
measurements,
|
|
184
|
+
dispatch,
|
|
185
|
+
recordMeasurement,
|
|
186
|
+
}) => {
|
|
187
|
+
const tasks = [];
|
|
188
|
+
for (const commit of commits.splice(0)) {
|
|
189
|
+
if (status === "handed_off") tasks.push(commit());
|
|
190
|
+
}
|
|
191
|
+
for (const confirmation of pending.splice(0)) dispatch(confirmation);
|
|
192
|
+
for (const measurement of measurements.splice(0)) {
|
|
193
|
+
const finalized = status === "handed_off" ? measurement : {
|
|
194
|
+
...measurement, reason: "delivery_failed", new_tokens: 0, retained_tokens: 0,
|
|
195
|
+
};
|
|
196
|
+
tasks.push(recordMeasurement(finalized));
|
|
197
|
+
}
|
|
198
|
+
await Promise.all(tasks);
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
const createDeferredTransformDelivery = ({
|
|
202
|
+
confirmPromptPackDelivery,
|
|
203
|
+
recordMeasurement,
|
|
204
|
+
acquireSessionFinalization,
|
|
205
|
+
}) => {
|
|
206
|
+
let completion = null;
|
|
207
|
+
let finalizationReady = null;
|
|
208
|
+
let releaseFinalization = null;
|
|
209
|
+
const pending = [];
|
|
210
|
+
const commits = [];
|
|
211
|
+
const measurements = [];
|
|
212
|
+
const dispatch = ([attemptId, status, evaluation]) => {
|
|
213
|
+
const deliveryStatus = completion === "failed" && (!status || status === "handed_off")
|
|
214
|
+
? "failed"
|
|
215
|
+
: status;
|
|
216
|
+
confirmPromptPackDelivery(attemptId, deliveryStatus, evaluation);
|
|
217
|
+
};
|
|
218
|
+
const beginFinalization = async (sessionID) => {
|
|
219
|
+
if (!finalizationReady) {
|
|
220
|
+
finalizationReady = acquireSessionFinalization(sessionID).then((release) => {
|
|
221
|
+
releaseFinalization = release;
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
await finalizationReady;
|
|
225
|
+
};
|
|
226
|
+
const finish = async (status = "handed_off") => {
|
|
227
|
+
if (completion) return;
|
|
228
|
+
completion = status;
|
|
229
|
+
try {
|
|
230
|
+
await completeDeferredDelivery({
|
|
231
|
+
status, commits, pending, measurements, dispatch, recordMeasurement,
|
|
232
|
+
});
|
|
233
|
+
} finally {
|
|
234
|
+
releaseFinalization?.();
|
|
235
|
+
releaseFinalization = null;
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
return {
|
|
239
|
+
commit: (commit) => { commits.push(commit); },
|
|
240
|
+
recordMeasurement: (measurement) => { measurements.push(measurement); },
|
|
241
|
+
beginFinalization,
|
|
242
|
+
finish,
|
|
243
|
+
complete: finish,
|
|
244
|
+
confirm: (...confirmation) => {
|
|
245
|
+
if (completion) dispatch(confirmation);
|
|
246
|
+
else pending.push(confirmation);
|
|
247
|
+
},
|
|
248
|
+
};
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
const createTransformDeliveryFactory = ({ confirmPromptPackDelivery, logLine }) => {
|
|
252
|
+
const acquireSessionFinalization = createSessionFinalizationMutex();
|
|
253
|
+
const recordMeasurement = (measurement) => logLine(`inject.recall ${JSON.stringify(measurement)}`);
|
|
254
|
+
return (deferred) => {
|
|
255
|
+
if (!deferred) {
|
|
256
|
+
return {
|
|
257
|
+
complete: undefined,
|
|
258
|
+
finish: async () => {},
|
|
259
|
+
beginFinalization: async () => {},
|
|
260
|
+
confirm: confirmPromptPackDelivery,
|
|
261
|
+
recordMeasurement,
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
return createDeferredTransformDelivery({
|
|
265
|
+
confirmPromptPackDelivery, recordMeasurement, acquireSessionFinalization,
|
|
266
|
+
});
|
|
267
|
+
};
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
const createRetryArtifactState = () => {
|
|
271
|
+
const promptPackRetryCounts = new Map();
|
|
272
|
+
const successfulPromptPackArtifacts = new Map();
|
|
273
|
+
return {
|
|
274
|
+
advancePromptPackRetryIdentity: (attemptKey) => {
|
|
275
|
+
promptPackRetryCounts.set(attemptKey, (promptPackRetryCounts.get(attemptKey) || 0) + 1);
|
|
276
|
+
trimOldest(promptPackRetryCounts, MAX_ATTEMPT_ENTRIES);
|
|
277
|
+
},
|
|
278
|
+
getPromptPackRetryCount: (attemptKey) => promptPackRetryCounts.get(attemptKey) || 0,
|
|
279
|
+
getSuccessfulPromptPackArtifact: (attemptKey) => successfulPromptPackArtifacts.get(attemptKey),
|
|
280
|
+
rememberSuccessfulPromptPackArtifact: (attemptKey, retryCount, fingerprint) => {
|
|
281
|
+
successfulPromptPackArtifacts.delete(attemptKey);
|
|
282
|
+
successfulPromptPackArtifacts.set(attemptKey, { retryCount, fingerprint });
|
|
283
|
+
trimOldest(successfulPromptPackArtifacts, MAX_ATTEMPT_ENTRIES);
|
|
284
|
+
},
|
|
285
|
+
};
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
export const createRecallLifecycle = ({
|
|
289
|
+
createIdentity,
|
|
290
|
+
emptyQueryHash,
|
|
291
|
+
runPromptPackLedger,
|
|
292
|
+
logLine,
|
|
293
|
+
getPromptCounter,
|
|
294
|
+
defaultSurface,
|
|
295
|
+
}) => {
|
|
296
|
+
const injectionToastShown = new Set();
|
|
297
|
+
const messageInjectionCache = new Map();
|
|
298
|
+
const emptyRecallCache = new Map();
|
|
299
|
+
const attemptMetadata = createAttemptMetadata(getPromptCounter);
|
|
300
|
+
const shared = {
|
|
301
|
+
createIdentity, emptyQueryHash, runPromptPackLedger, attemptMetadata, getPromptCounter,
|
|
302
|
+
};
|
|
303
|
+
const skipRecorder = createSkipRecorder({ ...shared, defaultSurface });
|
|
304
|
+
const confirmPromptPackDelivery = createDeliveryConfirmer(runPromptPackLedger);
|
|
305
|
+
const retryArtifacts = createRetryArtifactState();
|
|
306
|
+
return {
|
|
307
|
+
injectionToastShown,
|
|
308
|
+
messageInjectionCache,
|
|
309
|
+
emptyRecallCache,
|
|
310
|
+
attemptMetadata,
|
|
311
|
+
recordSkippedPromptPack: skipRecorder.record,
|
|
312
|
+
recordCachedPromptPack: createCacheReuseRecorder(shared),
|
|
313
|
+
confirmPromptPackDelivery,
|
|
314
|
+
createTransformDelivery: createTransformDeliveryFactory({ confirmPromptPackDelivery, logLine }),
|
|
315
|
+
...retryArtifacts,
|
|
316
|
+
startSession: skipRecorder.startSession,
|
|
317
|
+
clearSession: (sessionID) => {
|
|
318
|
+
injectionToastShown.delete(sessionID);
|
|
319
|
+
messageInjectionCache.delete(sessionID);
|
|
320
|
+
emptyRecallCache.delete(sessionID);
|
|
321
|
+
skipRecorder.clearSession(sessionID);
|
|
322
|
+
},
|
|
323
|
+
};
|
|
324
|
+
};
|