@code-yeongyu/senpi 2026.7.22-2 → 2026.7.23
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/CHANGELOG.md +20 -0
- package/dist/core/extensions/builtin/compaction/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/index.js +14 -6
- package/dist/core/extensions/builtin/compaction/index.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/openai-remote-convert.d.ts +26 -0
- package/dist/core/extensions/builtin/compaction/openai-remote-convert.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/openai-remote-convert.js +194 -0
- package/dist/core/extensions/builtin/compaction/openai-remote-convert.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/openai-remote-model.d.ts +22 -0
- package/dist/core/extensions/builtin/compaction/openai-remote-model.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/openai-remote-model.js +92 -0
- package/dist/core/extensions/builtin/compaction/openai-remote-model.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/openai-remote-schema.d.ts +92 -0
- package/dist/core/extensions/builtin/compaction/openai-remote-schema.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/openai-remote-schema.js +56 -0
- package/dist/core/extensions/builtin/compaction/openai-remote-schema.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/openai-remote.d.ts +7 -84
- package/dist/core/extensions/builtin/compaction/openai-remote.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/openai-remote.js +55 -271
- package/dist/core/extensions/builtin/compaction/openai-remote.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.2.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.2.js +3 -0
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.2.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.3-codex.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.3-codex.js +3 -0
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.3-codex.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.4.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.4.js +3 -0
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.4.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.5.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.5.js +3 -0
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.5.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js +3 -0
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.js +3 -0
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/gpt-eval-routing.d.ts +3 -0
- package/dist/core/extensions/builtin/prompt-preset/gpt-eval-routing.d.ts.map +1 -0
- package/dist/core/extensions/builtin/prompt-preset/gpt-eval-routing.js +6 -0
- package/dist/core/extensions/builtin/prompt-preset/gpt-eval-routing.js.map +1 -0
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +34 -4
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/tool-progress.js +1 -1
- package/dist/modes/interactive/tool-progress.js.map +1 -1
- package/dist/utils/duration.d.ts +2 -0
- package/dist/utils/duration.d.ts.map +1 -0
- package/dist/utils/duration.js +16 -0
- package/dist/utils/duration.js.map +1 -0
- package/docs/session-format.md +4 -0
- package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +14 -0
- package/node_modules/@code-yeongyu/senpi-codemode/README.md +15 -6
- package/node_modules/@code-yeongyu/senpi-codemode/package.json +3 -3
- package/node_modules/@code-yeongyu/senpi-codemode/src/codemode/runtime.ts +258 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/codemode/tools.ts +106 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/extension/runtime-factory.ts +114 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/extension/session-manager-proxy.ts +116 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/index.ts +73 -204
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-runtime.js +1 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js +34 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/package.json +2 -2
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts +20 -0
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/google-vertex.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/huggingface.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode-go.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.models.d.ts +8 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.models.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/huggingface.models.d.ts +4 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/huggingface.models.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/huggingface.models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/opencode-go.models.d.ts +4 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/opencode-go.models.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/opencode-go.models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.d.ts +4 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/types.d.ts +4 -0
- package/node_modules/@earendil-works/pi-ai/dist/types.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/types.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/package.json +1 -1
- package/node_modules/@earendil-works/pi-pty/package.json +1 -1
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/package.json +6 -6
|
@@ -1,38 +1,13 @@
|
|
|
1
1
|
import { streamSimple } from "@earendil-works/pi-ai/compat";
|
|
2
|
-
|
|
2
|
+
import { convertBranchEntries, convertPendingMessages, getOpenAiRemoteCompactionDetails, isOpenAiContextCompactionItem, isOpenAiRemoteCompactionOutputItem, isRecord, isRetainedRemoteOutputItem, isRetainedResponsesStreamInputItem, OPENAI_REMOTE_COMPACTION_SCHEMA, providerNativeItem, } from "./openai-remote-convert.js";
|
|
3
|
+
import { createOpenAiRemoteCompactionHeaders, isOpenAiRemoteCompactionModel, matchesOpenAiRemoteCompactionIdentity, openAiRemoteCompactionEndpointPath, openAiRemoteCompactionEndpointUrl, openAiRemoteCompactionIdentity, } from "./openai-remote-model.js";
|
|
4
|
+
export { getOpenAiRemoteCompactionDetails, OPENAI_REMOTE_COMPACTION_SCHEMA } from "./openai-remote-convert.js";
|
|
3
5
|
export const SENPI_COMPACTION_EVENT = "senpi:compaction";
|
|
4
6
|
const OPENAI_REMOTE_COMPACTION_TIMEOUT_MS = 15_000;
|
|
5
7
|
const REMOTE_COMPACTION_TIMEOUT_REASON = "remote-compaction-timeout";
|
|
6
|
-
function isRecord(value) {
|
|
7
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8
|
-
}
|
|
9
|
-
function parseJsonRecord(value) {
|
|
10
|
-
if (!value?.startsWith("{"))
|
|
11
|
-
return undefined;
|
|
12
|
-
try {
|
|
13
|
-
const parsed = JSON.parse(value);
|
|
14
|
-
return isRecord(parsed) ? parsed : undefined;
|
|
15
|
-
}
|
|
16
|
-
catch {
|
|
17
|
-
return undefined;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
function parseTextSignature(signature) {
|
|
21
|
-
if (!signature)
|
|
22
|
-
return undefined;
|
|
23
|
-
const parsed = parseJsonRecord(signature);
|
|
24
|
-
if (parsed?.v === 1 && typeof parsed.id === "string") {
|
|
25
|
-
if (parsed.phase === "commentary" || parsed.phase === "final_answer") {
|
|
26
|
-
return { id: parsed.id, phase: parsed.phase };
|
|
27
|
-
}
|
|
28
|
-
return { id: parsed.id };
|
|
29
|
-
}
|
|
30
|
-
return { id: signature };
|
|
31
|
-
}
|
|
32
|
-
function isOpenAiResponsesModel(model) {
|
|
33
|
-
return model?.provider === "openai" && model.api === "openai-responses";
|
|
34
|
-
}
|
|
35
8
|
function supportsOpenAiResponsesWebSocket(model) {
|
|
9
|
+
if (model.provider !== "openai" || model.api !== "openai-responses")
|
|
10
|
+
return false;
|
|
36
11
|
if (model.compat?.supportsWebSocket !== undefined)
|
|
37
12
|
return model.compat.supportsWebSocket;
|
|
38
13
|
try {
|
|
@@ -42,196 +17,11 @@ function supportsOpenAiResponsesWebSocket(model) {
|
|
|
42
17
|
return false;
|
|
43
18
|
}
|
|
44
19
|
}
|
|
45
|
-
function toolResultText(content) {
|
|
46
|
-
if (typeof content === "string")
|
|
47
|
-
return content;
|
|
48
|
-
const parts = [];
|
|
49
|
-
for (const block of content) {
|
|
50
|
-
if (block.type !== "text")
|
|
51
|
-
return undefined;
|
|
52
|
-
parts.push(block.text);
|
|
53
|
-
}
|
|
54
|
-
return parts.join("\n");
|
|
55
|
-
}
|
|
56
|
-
function convertUserContent(content) {
|
|
57
|
-
if (typeof content === "string")
|
|
58
|
-
return [{ type: "input_text", text: content }];
|
|
59
|
-
return content.map((block) => {
|
|
60
|
-
if (block.type === "text")
|
|
61
|
-
return { type: "input_text", text: block.text };
|
|
62
|
-
return {
|
|
63
|
-
type: "input_image",
|
|
64
|
-
detail: "auto",
|
|
65
|
-
image_url: `data:${block.mimeType};base64,${block.data}`,
|
|
66
|
-
};
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
function providerNativeItem(raw) {
|
|
70
|
-
if (!isRecord(raw) || typeof raw.type !== "string")
|
|
71
|
-
return undefined;
|
|
72
|
-
return { ...raw, type: raw.type };
|
|
73
|
-
}
|
|
74
|
-
function convertThinking(block) {
|
|
75
|
-
const parsed = parseJsonRecord(block.thinkingSignature);
|
|
76
|
-
if (parsed?.type !== "reasoning")
|
|
77
|
-
return undefined;
|
|
78
|
-
return { ...parsed, type: "reasoning" };
|
|
79
|
-
}
|
|
80
|
-
function convertTextBlock(block, messageIndex) {
|
|
81
|
-
const signature = parseTextSignature(block.textSignature);
|
|
82
|
-
const item = {
|
|
83
|
-
type: "message",
|
|
84
|
-
role: "assistant",
|
|
85
|
-
status: "completed",
|
|
86
|
-
id: signature?.id ?? `msg_${messageIndex}`,
|
|
87
|
-
content: [{ type: "output_text", text: block.text, annotations: [] }],
|
|
88
|
-
...(signature?.phase ? { phase: signature.phase } : {}),
|
|
89
|
-
};
|
|
90
|
-
return item;
|
|
91
|
-
}
|
|
92
|
-
function convertToolCall(block) {
|
|
93
|
-
const [callId = block.id, itemId] = block.id.split("|");
|
|
94
|
-
return {
|
|
95
|
-
type: "function_call",
|
|
96
|
-
// The Responses API rejects item ids not beginning with "fc"; custom tool
|
|
97
|
-
// calls carry the "<call_id>|custom" sentinel, not a server-issued id.
|
|
98
|
-
...(itemId?.startsWith("fc") ? { id: itemId } : {}),
|
|
99
|
-
call_id: callId,
|
|
100
|
-
name: block.name,
|
|
101
|
-
arguments: JSON.stringify(block.arguments ?? {}),
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
function isSameOpenAiResponsesAssistant(message) {
|
|
105
|
-
return message.provider === "openai" && message.api === "openai-responses";
|
|
106
|
-
}
|
|
107
|
-
function convertAssistantMessage(message, messageIndex) {
|
|
108
|
-
if (!isSameOpenAiResponsesAssistant(message))
|
|
109
|
-
return undefined;
|
|
110
|
-
const items = [];
|
|
111
|
-
for (const block of message.content) {
|
|
112
|
-
switch (block.type) {
|
|
113
|
-
case "text":
|
|
114
|
-
items.push(convertTextBlock(block, messageIndex));
|
|
115
|
-
break;
|
|
116
|
-
case "thinking": {
|
|
117
|
-
const reasoning = convertThinking(block);
|
|
118
|
-
if (!reasoning)
|
|
119
|
-
return undefined;
|
|
120
|
-
items.push(reasoning);
|
|
121
|
-
break;
|
|
122
|
-
}
|
|
123
|
-
case "toolCall":
|
|
124
|
-
items.push(convertToolCall(block));
|
|
125
|
-
break;
|
|
126
|
-
case "providerNative": {
|
|
127
|
-
const item = providerNativeItem(block.raw);
|
|
128
|
-
if (!item)
|
|
129
|
-
return undefined;
|
|
130
|
-
items.push(item);
|
|
131
|
-
break;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
return items.length > 0 ? items : undefined;
|
|
136
|
-
}
|
|
137
|
-
function convertAgentMessage(message, messageIndex) {
|
|
138
|
-
switch (message.role) {
|
|
139
|
-
case "user":
|
|
140
|
-
return [{ role: "user", content: convertUserContent(message.content) }];
|
|
141
|
-
case "assistant":
|
|
142
|
-
return convertAssistantMessage(message, messageIndex);
|
|
143
|
-
case "toolResult": {
|
|
144
|
-
const [callId = message.toolCallId] = message.toolCallId.split("|");
|
|
145
|
-
const output = toolResultText(message.content);
|
|
146
|
-
if (output === undefined)
|
|
147
|
-
return undefined;
|
|
148
|
-
return [{ type: "function_call_output", call_id: callId, output }];
|
|
149
|
-
}
|
|
150
|
-
case "bashExecution":
|
|
151
|
-
case "branchSummary":
|
|
152
|
-
case "compactionSummary":
|
|
153
|
-
case "custom":
|
|
154
|
-
return undefined;
|
|
155
|
-
default: {
|
|
156
|
-
const exhaustive = message;
|
|
157
|
-
return exhaustive;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
function detailsFromEntry(entry) {
|
|
162
|
-
if (entry.type !== "compaction")
|
|
163
|
-
return undefined;
|
|
164
|
-
return getOpenAiRemoteCompactionDetails(entry.details);
|
|
165
|
-
}
|
|
166
|
-
export function getOpenAiRemoteCompactionDetails(value) {
|
|
167
|
-
if (!isRecord(value))
|
|
168
|
-
return undefined;
|
|
169
|
-
if (value.schema !== OPENAI_REMOTE_COMPACTION_SCHEMA || value.mode !== "openai-remote")
|
|
170
|
-
return undefined;
|
|
171
|
-
if (value.provider !== "openai" || value.api !== "openai-responses")
|
|
172
|
-
return undefined;
|
|
173
|
-
if (typeof value.modelId !== "string" || typeof value.responseId !== "string")
|
|
174
|
-
return undefined;
|
|
175
|
-
if (typeof value.createdAt !== "number")
|
|
176
|
-
return undefined;
|
|
177
|
-
if (typeof value.requestInputItemCount !== "number" || typeof value.retainedInputItemCount !== "number") {
|
|
178
|
-
return undefined;
|
|
179
|
-
}
|
|
180
|
-
if (!Array.isArray(value.replacementInput))
|
|
181
|
-
return undefined;
|
|
182
|
-
return {
|
|
183
|
-
schema: OPENAI_REMOTE_COMPACTION_SCHEMA,
|
|
184
|
-
mode: "openai-remote",
|
|
185
|
-
provider: "openai",
|
|
186
|
-
api: "openai-responses",
|
|
187
|
-
transport: value.transport === "websocket" ? "websocket" : "compact-endpoint",
|
|
188
|
-
modelId: value.modelId,
|
|
189
|
-
responseId: value.responseId,
|
|
190
|
-
createdAt: value.createdAt,
|
|
191
|
-
requestInputItemCount: value.requestInputItemCount,
|
|
192
|
-
retainedInputItemCount: value.retainedInputItemCount,
|
|
193
|
-
replacementInput: value.replacementInput.filter((item) => isRecord(item)),
|
|
194
|
-
...(isRecord(value.usage) ? { usage: value.usage } : {}),
|
|
195
|
-
};
|
|
196
|
-
}
|
|
197
|
-
function convertBranchEntries(entries) {
|
|
198
|
-
const items = [];
|
|
199
|
-
let messageIndex = 0;
|
|
200
|
-
for (const entry of entries) {
|
|
201
|
-
switch (entry.type) {
|
|
202
|
-
case "message": {
|
|
203
|
-
const converted = convertAgentMessage(entry.message, messageIndex);
|
|
204
|
-
if (!converted)
|
|
205
|
-
return undefined;
|
|
206
|
-
items.push(...converted);
|
|
207
|
-
messageIndex++;
|
|
208
|
-
break;
|
|
209
|
-
}
|
|
210
|
-
case "compaction": {
|
|
211
|
-
const details = detailsFromEntry(entry);
|
|
212
|
-
if (!details)
|
|
213
|
-
return undefined;
|
|
214
|
-
items.push(...details.replacementInput);
|
|
215
|
-
break;
|
|
216
|
-
}
|
|
217
|
-
case "branch_summary":
|
|
218
|
-
case "custom_message":
|
|
219
|
-
return undefined;
|
|
220
|
-
case "thinking_level_change":
|
|
221
|
-
case "model_change":
|
|
222
|
-
case "custom":
|
|
223
|
-
case "label":
|
|
224
|
-
case "session_info":
|
|
225
|
-
break;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
return items;
|
|
229
|
-
}
|
|
230
20
|
export function createOpenAiRemoteCompactionRequest(options) {
|
|
231
|
-
if (!
|
|
21
|
+
if (!isOpenAiRemoteCompactionModel(options.model))
|
|
232
22
|
return undefined;
|
|
233
|
-
const input = convertBranchEntries(options.branchEntries);
|
|
234
|
-
if (
|
|
23
|
+
const input = convertBranchEntries(options.branchEntries, options.model);
|
|
24
|
+
if (input.length === 0)
|
|
235
25
|
return undefined;
|
|
236
26
|
return {
|
|
237
27
|
body: {
|
|
@@ -245,32 +35,23 @@ export function createOpenAiRemoteCompactionRequest(options) {
|
|
|
245
35
|
tokensBefore: options.tokensBefore,
|
|
246
36
|
};
|
|
247
37
|
}
|
|
248
|
-
function
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
}
|
|
257
|
-
function isRetainedRemoteOutputItem(item) {
|
|
258
|
-
if (isOpenAiRemoteCompactionOutputItem(item))
|
|
259
|
-
return true;
|
|
260
|
-
return item.type === "message" && (item.role === "user" || item.role === "system" || item.role === "developer");
|
|
261
|
-
}
|
|
262
|
-
function isRetainedResponsesStreamInputItem(item) {
|
|
263
|
-
if (item.type === "message")
|
|
264
|
-
return item.role === "user";
|
|
265
|
-
return "role" in item && item.role === "user";
|
|
266
|
-
}
|
|
267
|
-
function isOpenAiCompactedResponse(value) {
|
|
268
|
-
if (!isRecord(value))
|
|
269
|
-
return false;
|
|
270
|
-
if (value.object !== "response.compaction" || typeof value.id !== "string" || typeof value.created_at !== "number") {
|
|
271
|
-
return false;
|
|
38
|
+
function parseOpenAiCompactedResponse(options) {
|
|
39
|
+
if (!isRecord(options.value) || !Array.isArray(options.value.output))
|
|
40
|
+
return undefined;
|
|
41
|
+
if (options.model.api === "openai-responses") {
|
|
42
|
+
if (options.value.object !== "response.compaction" ||
|
|
43
|
+
typeof options.value.id !== "string" ||
|
|
44
|
+
typeof options.value.created_at !== "number") {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
272
47
|
}
|
|
273
|
-
return
|
|
48
|
+
return {
|
|
49
|
+
id: typeof options.value.id === "string" ? options.value.id : `codex-compact:${options.requestId}`,
|
|
50
|
+
created_at: typeof options.value.created_at === "number" ? options.value.created_at : Math.floor(options.now() / 1000),
|
|
51
|
+
object: "response.compaction",
|
|
52
|
+
output: options.value.output.filter((item) => isRecord(item)),
|
|
53
|
+
...(isRecord(options.value.usage) ? { usage: options.value.usage } : {}),
|
|
54
|
+
};
|
|
274
55
|
}
|
|
275
56
|
export function buildOpenAiRemoteCompactionResult(options) {
|
|
276
57
|
const replacementInput = options.response.output.filter(isRetainedRemoteOutputItem);
|
|
@@ -281,8 +62,7 @@ export function buildOpenAiRemoteCompactionResult(options) {
|
|
|
281
62
|
const details = {
|
|
282
63
|
schema: OPENAI_REMOTE_COMPACTION_SCHEMA,
|
|
283
64
|
mode: "openai-remote",
|
|
284
|
-
|
|
285
|
-
api: "openai-responses",
|
|
65
|
+
...openAiRemoteCompactionIdentity(options.model),
|
|
286
66
|
transport: "compact-endpoint",
|
|
287
67
|
modelId: options.model.id,
|
|
288
68
|
responseId: options.response.id,
|
|
@@ -292,10 +72,13 @@ export function buildOpenAiRemoteCompactionResult(options) {
|
|
|
292
72
|
replacementInput,
|
|
293
73
|
...(options.response.usage ? { usage: options.response.usage } : {}),
|
|
294
74
|
};
|
|
75
|
+
const endpointPath = options.model.api === "openai-codex-responses"
|
|
76
|
+
? `/${openAiRemoteCompactionEndpointPath(options.model)}`
|
|
77
|
+
: "/v1/responses/compact";
|
|
295
78
|
return {
|
|
296
79
|
summary: [
|
|
297
80
|
"OpenAI remote compaction checkpoint.",
|
|
298
|
-
`Native
|
|
81
|
+
`Native ${endpointPath} replay is active for ${replacementInput.length.toLocaleString()} retained item(s).`,
|
|
299
82
|
`Original OpenAI input items compacted: ${options.requestInputItemCount.toLocaleString()}.`,
|
|
300
83
|
].join("\n"),
|
|
301
84
|
firstKeptEntryId: options.firstKeptEntryId,
|
|
@@ -303,18 +86,6 @@ export function buildOpenAiRemoteCompactionResult(options) {
|
|
|
303
86
|
details,
|
|
304
87
|
};
|
|
305
88
|
}
|
|
306
|
-
function compactEndpointUrl(model) {
|
|
307
|
-
const baseUrl = model.baseUrl || "https://api.openai.com/v1";
|
|
308
|
-
return new URL("responses/compact", baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`).toString();
|
|
309
|
-
}
|
|
310
|
-
function createHeaders(auth) {
|
|
311
|
-
const headers = new Headers(auth.headers);
|
|
312
|
-
headers.set("content-type", "application/json");
|
|
313
|
-
if (!headers.has("authorization") && auth.apiKey) {
|
|
314
|
-
headers.set("authorization", `Bearer ${auth.apiKey}`);
|
|
315
|
-
}
|
|
316
|
-
return headers.has("authorization") ? headers : undefined;
|
|
317
|
-
}
|
|
318
89
|
async function runWithRemoteTimeout(options) {
|
|
319
90
|
if (options.signal.aborted) {
|
|
320
91
|
throw new Error("Request was aborted");
|
|
@@ -464,7 +235,7 @@ async function runOpenAiCompactEndpointCompaction(options) {
|
|
|
464
235
|
});
|
|
465
236
|
let response;
|
|
466
237
|
try {
|
|
467
|
-
response = await options.fetchImpl(
|
|
238
|
+
response = await options.fetchImpl(openAiRemoteCompactionEndpointUrl(options.model), {
|
|
468
239
|
method: "POST",
|
|
469
240
|
headers: options.headers,
|
|
470
241
|
body: JSON.stringify(options.request.body),
|
|
@@ -513,7 +284,13 @@ async function runOpenAiCompactEndpointCompaction(options) {
|
|
|
513
284
|
});
|
|
514
285
|
return undefined;
|
|
515
286
|
}
|
|
516
|
-
|
|
287
|
+
const compactedResponse = parseOpenAiCompactedResponse({
|
|
288
|
+
value: payload,
|
|
289
|
+
model: options.model,
|
|
290
|
+
requestId: options.requestId,
|
|
291
|
+
now: options.now,
|
|
292
|
+
});
|
|
293
|
+
if (!compactedResponse) {
|
|
517
294
|
options.emit?.({
|
|
518
295
|
version: 1,
|
|
519
296
|
action: "remote_fallback",
|
|
@@ -532,7 +309,7 @@ async function runOpenAiCompactEndpointCompaction(options) {
|
|
|
532
309
|
firstKeptEntryId: options.firstKeptEntryId,
|
|
533
310
|
tokensBefore: options.request.tokensBefore,
|
|
534
311
|
requestInputItemCount: options.request.inputItemCount,
|
|
535
|
-
response:
|
|
312
|
+
response: compactedResponse,
|
|
536
313
|
});
|
|
537
314
|
}
|
|
538
315
|
catch (error) {
|
|
@@ -553,7 +330,7 @@ async function runOpenAiCompactEndpointCompaction(options) {
|
|
|
553
330
|
route: "builtin.compaction.openai_remote",
|
|
554
331
|
requestId: options.requestId,
|
|
555
332
|
modelId: options.model.id,
|
|
556
|
-
responseId:
|
|
333
|
+
responseId: compactedResponse.id,
|
|
557
334
|
retainedInputItemCount: result.details.retainedInputItemCount,
|
|
558
335
|
transport: "compact-endpoint",
|
|
559
336
|
});
|
|
@@ -561,7 +338,7 @@ async function runOpenAiCompactEndpointCompaction(options) {
|
|
|
561
338
|
}
|
|
562
339
|
export async function runOpenAiRemoteCompaction(ctx, event, emit, dependencies = {}) {
|
|
563
340
|
const model = ctx.model;
|
|
564
|
-
if (!
|
|
341
|
+
if (!isOpenAiRemoteCompactionModel(model) || event.reason === "branch") {
|
|
565
342
|
emit?.({
|
|
566
343
|
version: 1,
|
|
567
344
|
action: "remote_fallback",
|
|
@@ -601,7 +378,7 @@ export async function runOpenAiRemoteCompaction(ctx, event, emit, dependencies =
|
|
|
601
378
|
route: "builtin.compaction.openai_remote",
|
|
602
379
|
requestId: event.requestId,
|
|
603
380
|
modelId: model.id,
|
|
604
|
-
reason: "
|
|
381
|
+
reason: "empty-compaction-input",
|
|
605
382
|
});
|
|
606
383
|
return undefined;
|
|
607
384
|
}
|
|
@@ -678,7 +455,7 @@ export async function runOpenAiRemoteCompaction(ctx, event, emit, dependencies =
|
|
|
678
455
|
});
|
|
679
456
|
}
|
|
680
457
|
}
|
|
681
|
-
const headers =
|
|
458
|
+
const headers = createOpenAiRemoteCompactionHeaders(requestModel, auth, request.body.prompt_cache_key);
|
|
682
459
|
if (!headers) {
|
|
683
460
|
emit?.({
|
|
684
461
|
version: 1,
|
|
@@ -710,6 +487,7 @@ export async function runOpenAiRemoteCompaction(ctx, event, emit, dependencies =
|
|
|
710
487
|
requestId: event.requestId,
|
|
711
488
|
signal,
|
|
712
489
|
firstKeptEntryId: event.preparation.firstKeptEntryId,
|
|
490
|
+
now: dependencies.now ?? Date.now,
|
|
713
491
|
emit,
|
|
714
492
|
}),
|
|
715
493
|
});
|
|
@@ -741,15 +519,21 @@ function leadingPromptMessages(input) {
|
|
|
741
519
|
return result;
|
|
742
520
|
}
|
|
743
521
|
export function rewriteOpenAiPayloadWithRemoteCompaction(payload, options, emit) {
|
|
744
|
-
if (!
|
|
522
|
+
if (!isOpenAiRemoteCompactionModel(options.model) || !isRecord(payload))
|
|
745
523
|
return undefined;
|
|
746
524
|
const remote = latestRemoteCompaction(options.branchEntries);
|
|
747
|
-
if (!remote)
|
|
748
|
-
return undefined;
|
|
749
|
-
const postCompactionItems = convertBranchEntries(options.branchEntries.slice(remote.index + 1));
|
|
750
|
-
if (!postCompactionItems)
|
|
525
|
+
if (!remote || !matchesOpenAiRemoteCompactionIdentity(options.model, remote.details))
|
|
751
526
|
return undefined;
|
|
752
|
-
const
|
|
527
|
+
const postCompactionItems = convertBranchEntries(options.branchEntries.slice(remote.index + 1), options.model);
|
|
528
|
+
// The in-flight prompt is not yet persisted in the branch at provider-request
|
|
529
|
+
// time; append it so the replayed payload still carries the user's message.
|
|
530
|
+
const pendingItems = convertPendingMessages(options.pendingMessages ?? [], options.model);
|
|
531
|
+
const input = [
|
|
532
|
+
...leadingPromptMessages(payload.input),
|
|
533
|
+
...remote.details.replacementInput,
|
|
534
|
+
...postCompactionItems,
|
|
535
|
+
...pendingItems,
|
|
536
|
+
];
|
|
753
537
|
emit?.({
|
|
754
538
|
version: 1,
|
|
755
539
|
action: "remote_payload_rewritten",
|