@bitkyc08/opencodex 2.65.0 → 2.66.0-preview.20260925
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 +14 -0
- package/gui/dist/assets/App-BVjA0T6O.js +51 -0
- package/gui/dist/assets/App-gkoJIEOV.css +1 -0
- package/gui/dist/assets/{Tray-D4bA1vff.js → Tray-BCFtiWwD.js} +1 -1
- package/gui/dist/assets/index-ComVsdSk.css +1 -0
- package/gui/dist/assets/index-vO4dgfiU.js +86 -0
- package/gui/dist/assets/{tray-data-BZXhB3qz.js → tray-data-C4FiNaxk.js} +1 -1
- package/gui/dist/index.html +2 -2
- package/package.json +1 -2
- package/src/adapters/anthropic/beta-allowlist.ts +80 -0
- package/src/adapters/anthropic/passthrough.ts +221 -0
- package/src/adapters/anthropic-image-codec.ts +56 -19
- package/src/adapters/anthropic-image-normalize.ts +20 -10
- package/src/adapters/anthropic.ts +55 -24
- package/src/adapters/coding-agent/protocol.ts +29 -19
- package/src/adapters/cursor/live-transport.ts +18 -3
- package/src/adapters/cursor/native-exec-shell.ts +18 -63
- package/src/adapters/cursor/native-exec.ts +5 -2
- package/src/adapters/cursor/native-foreground-shell.ts +44 -0
- package/src/adapters/devin/cloud-direct/chat.ts +7 -1
- package/src/adapters/exec-tool-result-normalize.ts +4 -1
- package/src/adapters/google.ts +12 -0
- package/src/adapters/ollama-native.ts +32 -1
- package/src/adapters/openai-chat/serialized-tool-call-content.ts +131 -34
- package/src/adapters/openai-chat.ts +6 -4
- package/src/adapters/openai-responses/passthrough.ts +1 -0
- package/src/adapters/openai-responses/reasoning.ts +45 -1
- package/src/bridge/response-json.ts +10 -2
- package/src/chat/outbound.ts +104 -52
- package/src/claude/claude-code-block.ts +16 -0
- package/src/claude/context-windows.ts +52 -4
- package/src/claude/desktop-first-party.ts +25 -8
- package/src/claude/inbound.ts +22 -0
- package/src/claude/intercept/connect-proxy.ts +37 -4
- package/src/claude/intercept/proxy-auth.ts +166 -0
- package/src/claude/intercept/runtime.ts +21 -0
- package/src/claude/intercept/settings.ts +33 -12
- package/src/claude/outbound.ts +45 -27
- package/src/cli/account-extended.ts +47 -15
- package/src/cli/account-target.ts +115 -0
- package/src/cli/account.ts +20 -28
- package/src/cli/agent.ts +10 -1
- package/src/cli/api-protocols.ts +206 -0
- package/src/cli/capabilities.ts +86 -0
- package/src/cli/combo.ts +2 -2
- package/src/cli/connect.ts +127 -3
- package/src/cli/dispatch.ts +8 -0
- package/src/cli/doctor.ts +33 -0
- package/src/cli/help.ts +2 -0
- package/src/cli/link.ts +288 -0
- package/src/cli/registry.ts +23 -0
- package/src/cli/runtime-api.ts +79 -0
- package/src/cli/system-command.ts +21 -2
- package/src/client/connect.ts +125 -23
- package/src/client/hub-relay.ts +12 -8
- package/src/client/link-join.ts +323 -0
- package/src/client/link-relay.ts +241 -0
- package/src/client/link-state.ts +110 -0
- package/src/client/link-teardown.ts +63 -0
- package/src/client/link-tunnel.ts +465 -0
- package/src/client/machine-listener.ts +14 -5
- package/src/client/runtime.ts +91 -42
- package/src/client/state.ts +4 -0
- package/src/codex/catalog/build-entries.ts +4 -0
- package/src/codex/catalog/derive-entry.ts +5 -0
- package/src/codex/catalog/parsing.ts +4 -0
- package/src/codex/catalog/retained-sync.ts +4 -1
- package/src/codex/desktop-switches.ts +88 -8
- package/src/codex/inject/plan.ts +16 -3
- package/src/codex/inject.ts +3 -0
- package/src/codex/internal/catalog-writer.ts +13 -2
- package/src/combos/failover.ts +3 -2
- package/src/combos/index.ts +12 -0
- package/src/combos/jev.ts +646 -0
- package/src/combos/request.ts +5 -0
- package/src/combos/resolve.ts +17 -15
- package/src/combos/types.ts +47 -3
- package/src/config/atomic-write.ts +3 -0
- package/src/config/live-reconcile.ts +20 -4
- package/src/config/persist-unlocked.ts +20 -7
- package/src/config/schema/config-schema.ts +16 -0
- package/src/config/schema/leaf-validators.ts +38 -1
- package/src/generated/compatibility-version.json +416 -128
- package/src/integrations/omp-yaml-source.ts +109 -4
- package/src/lab/automation/orchestrator.ts +60 -4
- package/src/lab/events/limits.ts +1 -1
- package/src/lib/bounded-body.ts +55 -38
- package/src/lib/config-ownership.ts +11 -22
- package/src/lib/local-desktop-snapshot-capability.ts +56 -0
- package/src/lib/local-management-capability.ts +25 -3
- package/src/lib/optional-shutdown-hooks.ts +17 -0
- package/src/lib/state-store-registrations.ts +2 -2
- package/src/lib/windows-elevation.ts +62 -25
- package/src/lib/windows-secret-acl.ts +114 -23
- package/src/link/admission-wait.ts +73 -0
- package/src/link/compensation.ts +100 -0
- package/src/link/fingerprint.ts +21 -0
- package/src/link/paths.ts +19 -0
- package/src/link/ports.ts +12 -0
- package/src/link/routes.ts +32 -0
- package/src/link/ssh-argv.ts +170 -0
- package/src/link/ssh-config.ts +152 -0
- package/src/link/ssh-runner.ts +161 -0
- package/src/link/status-projection.ts +96 -0
- package/src/link/store.ts +139 -0
- package/src/link/supervisor.ts +404 -0
- package/src/link/tunnel-state.ts +91 -0
- package/src/protocols/baseline.ts +88 -0
- package/src/protocols/codecs/chat.ts +17 -0
- package/src/protocols/codecs/messages.ts +18 -0
- package/src/protocols/codecs/responses.ts +17 -0
- package/src/protocols/contract.ts +185 -0
- package/src/protocols/dto.ts +267 -0
- package/src/protocols/encoders/adapter-events.ts +876 -0
- package/src/protocols/encoders/chat.ts +243 -0
- package/src/protocols/encoders/messages.ts +462 -0
- package/src/protocols/envelope.ts +43 -0
- package/src/protocols/features.ts +295 -0
- package/src/protocols/guard.ts +33 -0
- package/src/protocols/opaque-state.ts +132 -0
- package/src/protocols/path.ts +39 -0
- package/src/protocols/plan-snapshot.ts +226 -0
- package/src/protocols/plan.ts +192 -0
- package/src/protocols/provider-summary.ts +101 -0
- package/src/protocols/settings.ts +118 -0
- package/src/protocols/shadow-plan.ts +36 -0
- package/src/protocols/shadow.ts +62 -0
- package/src/protocols/trace.ts +335 -0
- package/src/providers/model-rename-migration.ts +3 -3
- package/src/providers/registry/entries-core.ts +6 -1
- package/src/providers/registry/entries-extended.ts +15 -0
- package/src/providers/registry/model-ids.ts +1 -0
- package/src/providers/registry/types.ts +6 -0
- package/src/providers/registry.ts +1 -1
- package/src/remote-control/workspace-hub.ts +5 -4
- package/src/responses/apply-patch-envelope.ts +6 -1
- package/src/responses/code-mode-shell-input.ts +4 -2
- package/src/responses/freeform-wrapper-scan.ts +51 -24
- package/src/responses/progressive-freeform-input.ts +14 -20
- package/src/responses/spill-store.ts +187 -33
- package/src/responses/state/snapshot-select.ts +49 -0
- package/src/responses/state/spill-inspect.ts +46 -0
- package/src/responses/state/spill-queue.ts +16 -0
- package/src/responses/state.ts +51 -27
- package/src/server/audio-client.ts +8 -3
- package/src/server/audio-upstream.ts +9 -4
- package/src/server/auth-cors.ts +25 -8
- package/src/server/chat-completions.ts +71 -11
- package/src/server/chat-native-eligibility.ts +74 -0
- package/src/server/chat-native.ts +139 -74
- package/src/server/claude-messages.ts +140 -22
- package/src/server/hub-usage.ts +4 -3
- package/src/server/index/link-listener.ts +195 -0
- package/src/server/index/optional-listeners.ts +115 -0
- package/src/server/index/serve-options.ts +44 -10
- package/src/server/index.ts +10 -9
- package/src/server/inference/attempt.ts +51 -0
- package/src/server/inference/client-encoder-delivery.ts +235 -0
- package/src/server/inference/client-wire-log.ts +49 -0
- package/src/server/inference/client-wire.ts +69 -0
- package/src/server/inference/context.ts +15 -0
- package/src/server/inference/final-log.ts +37 -0
- package/src/server/local-desktop-snapshot-auth.ts +57 -0
- package/src/server/management/agent-settings-routes.ts +15 -13
- package/src/server/management/api-access.ts +11 -1
- package/src/server/management/config-routes.ts +3 -6
- package/src/server/management/context.ts +25 -0
- package/src/server/management/link-routes.ts +535 -0
- package/src/server/management/logs-usage-routes.ts +31 -1
- package/src/server/management/native-integration-routes.ts +6 -11
- package/src/server/management/oauth-account-routes.ts +42 -16
- package/src/server/management/protocol-routes.ts +159 -0
- package/src/server/management/protocol-settings-patch.ts +145 -0
- package/src/server/management/provider-patch-transaction.ts +61 -0
- package/src/server/management/provider-routes.ts +39 -18
- package/src/server/management/route-registry.ts +12 -0
- package/src/server/management/sidebar-routes.ts +8 -3
- package/src/server/management/system-routes.ts +18 -1
- package/src/server/management/usage-aggregate-cache.ts +206 -6
- package/src/server/management-api.ts +26 -1
- package/src/server/management-auth.ts +19 -5
- package/src/server/messages-native-eligibility.ts +161 -0
- package/src/server/messages-native-oauth.ts +149 -0
- package/src/server/messages-native.ts +790 -0
- package/src/server/relay.ts +9 -0
- package/src/server/request-log-filter.ts +92 -0
- package/src/server/request-log.ts +31 -70
- package/src/server/responses/adapter-delivery.ts +43 -16
- package/src/server/responses/agent-task-recovery.ts +90 -22
- package/src/server/responses/codex-ws-exchange.ts +4 -0
- package/src/server/responses/codex-ws-wire.ts +10 -1
- package/src/server/responses/core-combo-native.ts +323 -0
- package/src/server/responses/core-combo.ts +224 -13
- package/src/server/responses/core-options.ts +22 -0
- package/src/server/responses/core.ts +14 -26
- package/src/server/responses/request-sidecar-auth.ts +8 -3
- package/src/server/responses/run-turn-execution.ts +257 -63
- package/src/server/responses/sidecar-execution.ts +7 -4
- package/src/server/system-env.ts +7 -0
- package/src/service/diagnostics.ts +7 -1
- package/src/service/launchd.ts +26 -37
- package/src/service/windows-ops.ts +24 -20
- package/src/types/config.ts +58 -1
- package/src/types.ts +2 -0
- package/src/update/transactional-install.d.mts +0 -1
- package/src/update/transactional-install.mjs +17 -17
- package/src/usage/jev-stats.ts +495 -0
- package/src/usage/log.ts +24 -3
- package/src/web-search/run-turn-loop.ts +568 -0
- package/gui/dist/assets/App-8NMiZxT0.css +0 -1
- package/gui/dist/assets/App-DGLte6IR.js +0 -50
- package/gui/dist/assets/index--EWgGQvZ.css +0 -1
- package/gui/dist/assets/index-Bi1K37Wl.js +0 -86
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AdapterEvent -> OpenAI Chat Completions, without the internal Responses SSE (PF-09).
|
|
3
|
+
*
|
|
4
|
+
* The writer reproduces `responsesSseToChatCompletionsSse` (src/chat/outbound.ts) for the frames
|
|
5
|
+
* the bridge produced: one role frame first, content and `reasoning_content` deltas, each
|
|
6
|
+
* function call as ONE complete tool_call chunk at its completion (Chat tool-call fields are
|
|
7
|
+
* append-only, so the converter never streamed partial arguments), a finish chunk carrying the
|
|
8
|
+
* usage, then `[DONE]`; failures end with one `{error}` frame and no `[DONE]`. Wire-silence
|
|
9
|
+
* heartbeats become `: opencodex heartbeat` SSE comments, as the converter relays them. Ids, the finish
|
|
10
|
+
* and error mapping and the usage shape are the converter's own exported helpers.
|
|
11
|
+
*/
|
|
12
|
+
import type { AdapterEvent } from "../../types";
|
|
13
|
+
import type { TranslatorBudget } from "../../lib/translator-budget";
|
|
14
|
+
import { responsesUsage } from "../../bridge/internal";
|
|
15
|
+
import {
|
|
16
|
+
chatCompletionsErrorResponse,
|
|
17
|
+
chatCompletionsFailedResponse,
|
|
18
|
+
chatCompletionsIncompleteOutcome,
|
|
19
|
+
chatCompletionsStreamErrorPayload,
|
|
20
|
+
chatCompletionsUsage,
|
|
21
|
+
chunkBase,
|
|
22
|
+
collectChatCompletion,
|
|
23
|
+
completionId,
|
|
24
|
+
dataFrame,
|
|
25
|
+
isChatCompletionsStreamError,
|
|
26
|
+
type ChatCompletionsStreamFailure,
|
|
27
|
+
} from "../../chat/outbound";
|
|
28
|
+
import {
|
|
29
|
+
encodeAdapterEventStream,
|
|
30
|
+
type AdapterEventEncodeOptions,
|
|
31
|
+
type ClientFrameSink,
|
|
32
|
+
type ClientWireWriter,
|
|
33
|
+
} from "./adapter-events";
|
|
34
|
+
import type { RelayedEventObservation } from "../../usage/attempt-delivery";
|
|
35
|
+
|
|
36
|
+
type Rec = Record<string, unknown>;
|
|
37
|
+
|
|
38
|
+
export interface ChatCompletionEncodeOptions extends AdapterEventEncodeOptions {
|
|
39
|
+
/** The model string the client asked for; every chunk carries it. */
|
|
40
|
+
model: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function createChatCompletionWriter(sink: ClientFrameSink, model: string): ClientWireWriter {
|
|
44
|
+
const id = completionId();
|
|
45
|
+
const created = Math.floor(Date.now() / 1000);
|
|
46
|
+
let started = false;
|
|
47
|
+
let sawToolUse = false;
|
|
48
|
+
let terminated = false;
|
|
49
|
+
let failed = false;
|
|
50
|
+
// call_id -> streaming index: OpenAI requires a stable index per tool call.
|
|
51
|
+
const toolIndexByCallId = new Map<string, number>();
|
|
52
|
+
const toolIndexByItemId = new Map<string, number>();
|
|
53
|
+
const toolNameByIndex = new Map<number, string>();
|
|
54
|
+
const emittedToolIndexes = new Set<number>();
|
|
55
|
+
let nextToolIndex = 0;
|
|
56
|
+
let staged: { text: string; observation?: RelayedEventObservation }[] | undefined;
|
|
57
|
+
|
|
58
|
+
const emit = (payload: Rec | "[DONE]", observation?: RelayedEventObservation) => {
|
|
59
|
+
if (failed) return;
|
|
60
|
+
const text = dataFrame(payload);
|
|
61
|
+
if (staged) staged.push({ text, ...(observation ? { observation } : {}) });
|
|
62
|
+
else sink.emit(text, observation);
|
|
63
|
+
};
|
|
64
|
+
const ensureRole = () => {
|
|
65
|
+
if (started) return;
|
|
66
|
+
started = true;
|
|
67
|
+
const frame = chunkBase(id, model, created);
|
|
68
|
+
frame.choices = [{ index: 0, delta: { role: "assistant", content: "" }, finish_reason: null }];
|
|
69
|
+
emit(frame);
|
|
70
|
+
};
|
|
71
|
+
const emitToolCall = (toolIndex: number, callId: string, name: string, args: string) => {
|
|
72
|
+
if (!callId || emittedToolIndexes.has(toolIndex)) return;
|
|
73
|
+
emittedToolIndexes.add(toolIndex);
|
|
74
|
+
ensureRole();
|
|
75
|
+
const frame = chunkBase(id, model, created);
|
|
76
|
+
frame.choices = [{
|
|
77
|
+
index: 0,
|
|
78
|
+
delta: {
|
|
79
|
+
tool_calls: [{
|
|
80
|
+
index: toolIndex,
|
|
81
|
+
id: callId,
|
|
82
|
+
type: "function",
|
|
83
|
+
function: { name, arguments: args },
|
|
84
|
+
}],
|
|
85
|
+
},
|
|
86
|
+
finish_reason: null,
|
|
87
|
+
}];
|
|
88
|
+
emit(frame, { sideEffect: true, semanticBytes: Buffer.byteLength(args) });
|
|
89
|
+
};
|
|
90
|
+
// Every started call reaches toolDone before a finishing terminal (the driver closes or fails
|
|
91
|
+
// it first), so the converter's pending-call flush has nothing left to flush here.
|
|
92
|
+
const finish = (finishReason: string, usage: Rec | null) => {
|
|
93
|
+
if (terminated) return;
|
|
94
|
+
// Admit every terminal frame before exposing any of them.
|
|
95
|
+
const batch: NonNullable<typeof staged> = [];
|
|
96
|
+
staged = batch;
|
|
97
|
+
try {
|
|
98
|
+
ensureRole();
|
|
99
|
+
const frame = chunkBase(id, model, created);
|
|
100
|
+
frame.choices = [{ index: 0, delta: {}, finish_reason: finishReason }];
|
|
101
|
+
if (usage) frame.usage = chatCompletionsUsage(usage);
|
|
102
|
+
emit(frame, { terminal: true });
|
|
103
|
+
emit("[DONE]");
|
|
104
|
+
} finally {
|
|
105
|
+
staged = undefined;
|
|
106
|
+
}
|
|
107
|
+
sink.emitBatch(batch);
|
|
108
|
+
terminated = true;
|
|
109
|
+
};
|
|
110
|
+
const fail = (message: string, details?: ChatCompletionsStreamFailure) => {
|
|
111
|
+
if (terminated) return;
|
|
112
|
+
terminated = true;
|
|
113
|
+
failed = true;
|
|
114
|
+
// A real error event, then an abnormal close without [DONE].
|
|
115
|
+
const { payload, bounded } = chatCompletionsStreamErrorPayload(message, details);
|
|
116
|
+
try {
|
|
117
|
+
if (bounded) sink.emitBounded(dataFrame(payload));
|
|
118
|
+
else sink.emit(dataFrame(payload), { terminal: true });
|
|
119
|
+
} catch {
|
|
120
|
+
/* the converter drops an unadmittable error frame the same way */
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
return {
|
|
125
|
+
start: ensureRole,
|
|
126
|
+
heartbeat() {
|
|
127
|
+
// The converter answers each typed heartbeat with the role frame (once) and then an SSE
|
|
128
|
+
// comment (#5805): transport liveness without a chunk a parser could count as output.
|
|
129
|
+
if (terminated) return;
|
|
130
|
+
ensureRole();
|
|
131
|
+
sink.emitKeepalive(": opencodex heartbeat\n\n");
|
|
132
|
+
},
|
|
133
|
+
text(delta) {
|
|
134
|
+
if (!delta) return;
|
|
135
|
+
ensureRole();
|
|
136
|
+
const frame = chunkBase(id, model, created);
|
|
137
|
+
frame.choices = [{ index: 0, delta: { content: delta }, finish_reason: null }];
|
|
138
|
+
emit(frame, { semanticBytes: Buffer.byteLength(delta) });
|
|
139
|
+
},
|
|
140
|
+
messageDone() { /* the converter reads nothing from a finished message */ },
|
|
141
|
+
reasoning(delta) {
|
|
142
|
+
if (!delta) return;
|
|
143
|
+
ensureRole();
|
|
144
|
+
// Many OpenAI-compatible clients accept reasoning_content; harmless if ignored.
|
|
145
|
+
const frame = chunkBase(id, model, created);
|
|
146
|
+
frame.choices = [{ index: 0, delta: { reasoning_content: delta }, finish_reason: null }];
|
|
147
|
+
emit(frame, { semanticBytes: Buffer.byteLength(delta) });
|
|
148
|
+
},
|
|
149
|
+
reasoningDone() { /* reasoning items carry nothing a Chat client reads */ },
|
|
150
|
+
toolStart(call) {
|
|
151
|
+
// Custom and tool-search calls have no Chat representation; the converter skips them.
|
|
152
|
+
if (call.kind !== "function") return;
|
|
153
|
+
ensureRole();
|
|
154
|
+
sawToolUse = true;
|
|
155
|
+
let toolIndex = toolIndexByCallId.get(call.callId);
|
|
156
|
+
if (toolIndex === undefined) {
|
|
157
|
+
toolIndex = nextToolIndex++;
|
|
158
|
+
toolIndexByCallId.set(call.callId, toolIndex);
|
|
159
|
+
}
|
|
160
|
+
toolIndexByItemId.set(call.itemId, toolIndex);
|
|
161
|
+
if (call.name) toolNameByIndex.set(toolIndex, call.name);
|
|
162
|
+
},
|
|
163
|
+
toolArgsDelta() { /* arguments are delivered once, complete, at toolDone */ },
|
|
164
|
+
toolArgsDone() { /* likewise */ },
|
|
165
|
+
toolDone(call) {
|
|
166
|
+
if (call.kind !== "function") return;
|
|
167
|
+
sawToolUse = true;
|
|
168
|
+
if (!call.callId) return;
|
|
169
|
+
const toolIndex = toolIndexByCallId.get(call.callId) ?? toolIndexByItemId.get(call.itemId) ?? nextToolIndex++;
|
|
170
|
+
toolIndexByCallId.set(call.callId, toolIndex);
|
|
171
|
+
toolIndexByItemId.set(call.itemId, toolIndex);
|
|
172
|
+
if (call.name) toolNameByIndex.set(toolIndex, call.name);
|
|
173
|
+
// The completed arguments are never empty ("{}" at least), so they win over the stream.
|
|
174
|
+
emitToolCall(toolIndex, call.callId, call.name || toolNameByIndex.get(toolIndex) || "", call.arguments);
|
|
175
|
+
},
|
|
176
|
+
webSearchDone() { /* server-side search has no Chat representation */ },
|
|
177
|
+
terminal(terminal) {
|
|
178
|
+
if (terminal.status === "completed") {
|
|
179
|
+
finish(sawToolUse ? "tool_calls" : "stop", responsesUsage(terminal.usage));
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
if (terminal.status === "incomplete") {
|
|
183
|
+
const outcome = chatCompletionsIncompleteOutcome(terminal.incomplete?.reason, terminal.incomplete?.message);
|
|
184
|
+
if ("finishReason" in outcome) {
|
|
185
|
+
finish(outcome.finishReason, terminal.usageOnWire ? responsesUsage(terminal.usage) : null);
|
|
186
|
+
} else {
|
|
187
|
+
fail(outcome.failMessage);
|
|
188
|
+
}
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
const failure = chatCompletionsFailedResponse((terminal.error ?? {}) as unknown as Rec);
|
|
192
|
+
fail(failure.message, failure.details);
|
|
193
|
+
},
|
|
194
|
+
overflow() {
|
|
195
|
+
fail("upstream translation buffer exceeded the safe limit", {
|
|
196
|
+
code: "translation_buffer_limit",
|
|
197
|
+
status: 502,
|
|
198
|
+
type: "upstream_error",
|
|
199
|
+
});
|
|
200
|
+
},
|
|
201
|
+
dispose() { /* nothing retained beyond the driver's frames */ },
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/** Stream adapter events as Chat Completions SSE bytes. */
|
|
206
|
+
export function encodeChatCompletionSse(
|
|
207
|
+
events: AsyncIterable<AdapterEvent>,
|
|
208
|
+
options: ChatCompletionEncodeOptions,
|
|
209
|
+
): ReadableStream<Uint8Array> {
|
|
210
|
+
return encodeAdapterEventStream(events, sink => createChatCompletionWriter(sink, options.model), options);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Fold an encoded Chat stream into the non-streaming client response, with the status mapping
|
|
215
|
+
* the Chat ingress applied to its collected completion: a stream failure becomes the matching
|
|
216
|
+
* Chat error response, anything else unexpected a 502.
|
|
217
|
+
*/
|
|
218
|
+
export async function collectChatCompletionResponse(
|
|
219
|
+
stream: ReadableStream<Uint8Array>,
|
|
220
|
+
model: string,
|
|
221
|
+
translatorBudget: TranslatorBudget,
|
|
222
|
+
): Promise<Response> {
|
|
223
|
+
try {
|
|
224
|
+
const completion = await collectChatCompletion(stream, model, translatorBudget);
|
|
225
|
+
return new Response(JSON.stringify(completion), {
|
|
226
|
+
status: 200,
|
|
227
|
+
headers: { "Content-Type": "application/json" },
|
|
228
|
+
});
|
|
229
|
+
} catch (err) {
|
|
230
|
+
if (isChatCompletionsStreamError(err)) {
|
|
231
|
+
return chatCompletionsErrorResponse(err.status, err.message, err.type, err.code);
|
|
232
|
+
}
|
|
233
|
+
return chatCompletionsErrorResponse(502, err instanceof Error ? err.message : String(err), "server_error");
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/** Non-streaming client: the encoded stream folded exactly as the Chat collector folds it. */
|
|
238
|
+
export function foldChatCompletion(
|
|
239
|
+
events: AsyncIterable<AdapterEvent>,
|
|
240
|
+
options: ChatCompletionEncodeOptions,
|
|
241
|
+
): Promise<Response> {
|
|
242
|
+
return collectChatCompletionResponse(encodeChatCompletionSse(events, options), options.model, options.translatorBudget);
|
|
243
|
+
}
|