@juspay/neurolink 9.65.2 → 9.66.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/CHANGELOG.md +6 -0
- package/dist/browser/neurolink.min.js +362 -354
- package/dist/cli/commands/proxy.js +154 -5
- package/dist/lib/proxy/modelRouter.d.ts +5 -1
- package/dist/lib/proxy/modelRouter.js +8 -0
- package/dist/lib/proxy/openaiFormat.d.ts +137 -0
- package/dist/lib/proxy/openaiFormat.js +801 -0
- package/dist/lib/proxy/proxyTranslationEngine.d.ts +124 -0
- package/dist/lib/proxy/proxyTranslationEngine.js +679 -0
- package/dist/lib/server/routes/claudeProxyRoutes.d.ts +6 -5
- package/dist/lib/server/routes/claudeProxyRoutes.js +22 -355
- package/dist/lib/server/routes/index.d.ts +1 -0
- package/dist/lib/server/routes/index.js +10 -2
- package/dist/lib/server/routes/openaiProxyRoutes.d.ts +30 -0
- package/dist/lib/server/routes/openaiProxyRoutes.js +337 -0
- package/dist/lib/types/proxy.d.ts +179 -0
- package/dist/lib/types/server.d.ts +3 -0
- package/dist/proxy/modelRouter.d.ts +5 -1
- package/dist/proxy/modelRouter.js +8 -0
- package/dist/proxy/openaiFormat.d.ts +137 -0
- package/dist/proxy/openaiFormat.js +800 -0
- package/dist/proxy/proxyTranslationEngine.d.ts +124 -0
- package/dist/proxy/proxyTranslationEngine.js +678 -0
- package/dist/server/routes/claudeProxyRoutes.d.ts +6 -5
- package/dist/server/routes/claudeProxyRoutes.js +22 -355
- package/dist/server/routes/index.d.ts +1 -0
- package/dist/server/routes/index.js +10 -2
- package/dist/server/routes/openaiProxyRoutes.d.ts +30 -0
- package/dist/server/routes/openaiProxyRoutes.js +336 -0
- package/dist/types/proxy.d.ts +179 -0
- package/dist/types/server.d.ts +3 -0
- package/package.json +1 -1
|
@@ -234,6 +234,122 @@ async function clearClaudeProxySettings(expectedBaseUrl) {
|
|
|
234
234
|
fs.writeFileSync(CLAUDE_SETTINGS_PATH, JSON.stringify(settings, null, 2));
|
|
235
235
|
return hadBaseUrl || hadToolSearch;
|
|
236
236
|
}
|
|
237
|
+
// =============================================================================
|
|
238
|
+
// OPENCODE AUTO-CONFIGURATION
|
|
239
|
+
// =============================================================================
|
|
240
|
+
function getOpenCodeConfigDir() {
|
|
241
|
+
if (process.platform === "darwin") {
|
|
242
|
+
return join(homedir(), "Library", "Application Support", "opencode");
|
|
243
|
+
}
|
|
244
|
+
// Linux/other: XDG_CONFIG_HOME or ~/.config
|
|
245
|
+
return join(process.env.XDG_CONFIG_HOME || join(homedir(), ".config"), "opencode");
|
|
246
|
+
}
|
|
247
|
+
const OPENCODE_CONFIG_PATH = join(getOpenCodeConfigDir(), "opencode.json");
|
|
248
|
+
/**
|
|
249
|
+
* Key under which we persist the snapshot of the user's pre-existing
|
|
250
|
+
* `provider.neurolink` config inside `opencode.json` itself. Persisting (rather
|
|
251
|
+
* than relying on in-process state) means restoration still works even if the
|
|
252
|
+
* proxy crashes or shutdown handlers run in a different process.
|
|
253
|
+
*
|
|
254
|
+
* Mirrors the Claude pattern (`__proxy_original_env` inside Claude's settings).
|
|
255
|
+
*/
|
|
256
|
+
const OPENCODE_ORIGINAL_KEY = "__proxy_original_neurolink";
|
|
257
|
+
async function setOpenCodeProxySettings(baseUrl, proxyKey) {
|
|
258
|
+
const fs = await import("fs");
|
|
259
|
+
const configDir = getOpenCodeConfigDir();
|
|
260
|
+
try {
|
|
261
|
+
fs.accessSync(configDir);
|
|
262
|
+
}
|
|
263
|
+
catch {
|
|
264
|
+
// OpenCode not installed — config directory does not exist, skip silently
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
let config;
|
|
268
|
+
try {
|
|
269
|
+
config = JSON.parse(fs.readFileSync(OPENCODE_CONFIG_PATH, "utf8"));
|
|
270
|
+
}
|
|
271
|
+
catch {
|
|
272
|
+
// file missing/invalid — create fresh config object
|
|
273
|
+
config = { provider: {} };
|
|
274
|
+
}
|
|
275
|
+
const provider = (config.provider ?? {});
|
|
276
|
+
// Persist a snapshot of the user's pre-existing provider.neurolink — but
|
|
277
|
+
// only the first time we touch the file. Subsequent set() calls must NOT
|
|
278
|
+
// overwrite the snapshot (otherwise after the proxy writes its own block,
|
|
279
|
+
// the next set() would store the proxy's block as the "original" and
|
|
280
|
+
// permanently lose the user's real config on the next clear()).
|
|
281
|
+
if (!(OPENCODE_ORIGINAL_KEY in config)) {
|
|
282
|
+
config[OPENCODE_ORIGINAL_KEY] =
|
|
283
|
+
"neurolink" in provider
|
|
284
|
+
? JSON.parse(JSON.stringify(provider.neurolink))
|
|
285
|
+
: null;
|
|
286
|
+
}
|
|
287
|
+
provider.neurolink = {
|
|
288
|
+
id: "neurolink",
|
|
289
|
+
name: "NeuroLink Proxy",
|
|
290
|
+
npm: "@ai-sdk/openai-compatible",
|
|
291
|
+
env: [],
|
|
292
|
+
models: {},
|
|
293
|
+
options: {
|
|
294
|
+
baseURL: baseUrl,
|
|
295
|
+
apiKey: proxyKey || "neurolink-proxy",
|
|
296
|
+
},
|
|
297
|
+
};
|
|
298
|
+
config.provider = provider;
|
|
299
|
+
fs.writeFileSync(OPENCODE_CONFIG_PATH, JSON.stringify(config, null, 2));
|
|
300
|
+
}
|
|
301
|
+
async function clearOpenCodeProxySettings(expectedBaseUrl) {
|
|
302
|
+
const fs = await import("fs");
|
|
303
|
+
let config;
|
|
304
|
+
try {
|
|
305
|
+
config = JSON.parse(fs.readFileSync(OPENCODE_CONFIG_PATH, "utf8"));
|
|
306
|
+
}
|
|
307
|
+
catch {
|
|
308
|
+
return false;
|
|
309
|
+
}
|
|
310
|
+
const provider = config.provider;
|
|
311
|
+
if (!provider || !("neurolink" in provider)) {
|
|
312
|
+
return false;
|
|
313
|
+
}
|
|
314
|
+
// Check if our proxy URL matches before removing
|
|
315
|
+
const existing = provider.neurolink;
|
|
316
|
+
if (expectedBaseUrl && existing) {
|
|
317
|
+
const options = existing.options;
|
|
318
|
+
if (options && typeof options.baseURL === "string") {
|
|
319
|
+
if (options.baseURL !== expectedBaseUrl) {
|
|
320
|
+
// User configured a different URL; do not clobber
|
|
321
|
+
return false;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
const hadNeurolink = "neurolink" in provider;
|
|
326
|
+
// Restore from the snapshot persisted at first set(), regardless of process
|
|
327
|
+
// identity. Only delete provider.neurolink when the snapshot says the user
|
|
328
|
+
// explicitly had no entry before — never on an "undefined" snapshot, since
|
|
329
|
+
// that would mean the snapshot was lost and we cannot prove the entry is ours.
|
|
330
|
+
if (OPENCODE_ORIGINAL_KEY in config) {
|
|
331
|
+
const snapshot = config[OPENCODE_ORIGINAL_KEY];
|
|
332
|
+
if (snapshot === null) {
|
|
333
|
+
// User had no provider.neurolink before the proxy started — safe to remove.
|
|
334
|
+
delete provider.neurolink;
|
|
335
|
+
}
|
|
336
|
+
else {
|
|
337
|
+
provider.neurolink = snapshot;
|
|
338
|
+
}
|
|
339
|
+
delete config[OPENCODE_ORIGINAL_KEY];
|
|
340
|
+
}
|
|
341
|
+
else {
|
|
342
|
+
// No snapshot present — refuse to delete to avoid destroying a config
|
|
343
|
+
// the proxy may not own (e.g. a user wrote their own `neurolink` block
|
|
344
|
+
// before the snapshot key was introduced, or this is being cleared from
|
|
345
|
+
// a process that never ran set()).
|
|
346
|
+
logger.debug("[proxy] OpenCode clear: no original-provider snapshot found, leaving provider.neurolink intact");
|
|
347
|
+
return false;
|
|
348
|
+
}
|
|
349
|
+
config.provider = provider;
|
|
350
|
+
fs.writeFileSync(OPENCODE_CONFIG_PATH, JSON.stringify(config, null, 2));
|
|
351
|
+
return hadNeurolink;
|
|
352
|
+
}
|
|
237
353
|
async function isProxyHealthy(host, port, timeoutMs) {
|
|
238
354
|
try {
|
|
239
355
|
const response = await fetch(`http://${host}:${port}/health`, {
|
|
@@ -533,9 +649,10 @@ function printProxyBanner(url, strategy) {
|
|
|
533
649
|
logger.always(` ${chalk.bold("PID:")} ${chalk.cyan(process.pid)}`);
|
|
534
650
|
logger.always("");
|
|
535
651
|
logger.always(chalk.bold("Endpoints:"));
|
|
536
|
-
logger.always(` ${chalk.blue("POST")} /v1/messages
|
|
537
|
-
logger.always(` ${chalk.
|
|
538
|
-
logger.always(` ${chalk.green("GET")} /
|
|
652
|
+
logger.always(` ${chalk.blue("POST")} /v1/messages — Claude proxy (Anthropic format)`);
|
|
653
|
+
logger.always(` ${chalk.blue("POST")} /v1/chat/completions — OpenAI-compatible proxy`);
|
|
654
|
+
logger.always(` ${chalk.green("GET")} /health — Health check`);
|
|
655
|
+
logger.always(` ${chalk.green("GET")} /status — Detailed status`);
|
|
539
656
|
logger.always("");
|
|
540
657
|
logger.always(chalk.bold("Set in Claude Code:"));
|
|
541
658
|
logger.always(` ${chalk.cyan(`ANTHROPIC_BASE_URL=${url}`)}`);
|
|
@@ -706,6 +823,7 @@ async function resolveBootPrimaryAccountKey(primaryEmail) {
|
|
|
706
823
|
}
|
|
707
824
|
async function createProxyStartApp(params) {
|
|
708
825
|
const { createClaudeProxyRoutes } = await import("../../lib/server/routes/claudeProxyRoutes.js");
|
|
826
|
+
const { createOpenAIProxyRoutes } = await import("../../lib/server/routes/openaiProxyRoutes.js");
|
|
709
827
|
const { Hono } = await import("hono");
|
|
710
828
|
const app = new Hono();
|
|
711
829
|
const readiness = createProxyReadinessState();
|
|
@@ -724,7 +842,9 @@ async function createProxyStartApp(params) {
|
|
|
724
842
|
}, 502);
|
|
725
843
|
});
|
|
726
844
|
const routeGroup = createClaudeProxyRoutes(params.modelRouter, "", params.strategy, params.passthrough, params.primaryAccountKey);
|
|
727
|
-
|
|
845
|
+
const openaiRouteGroup = createOpenAIProxyRoutes(params.modelRouter, "", params.port);
|
|
846
|
+
const allProxyRoutes = [...routeGroup.routes, ...openaiRouteGroup.routes];
|
|
847
|
+
for (const route of allProxyRoutes) {
|
|
728
848
|
const method = route.method.toLowerCase();
|
|
729
849
|
app[method](route.path, async (c) => {
|
|
730
850
|
const emptyBody = {};
|
|
@@ -1025,6 +1145,13 @@ function registerProxyShutdownHandlers(params) {
|
|
|
1025
1145
|
catch {
|
|
1026
1146
|
// non-fatal
|
|
1027
1147
|
}
|
|
1148
|
+
try {
|
|
1149
|
+
const shutdownHost = params.host === "0.0.0.0" ? "localhost" : params.host;
|
|
1150
|
+
await clearOpenCodeProxySettings(`http://${shutdownHost}:${params.port}/v1`);
|
|
1151
|
+
}
|
|
1152
|
+
catch {
|
|
1153
|
+
// non-fatal
|
|
1154
|
+
}
|
|
1028
1155
|
}
|
|
1029
1156
|
try {
|
|
1030
1157
|
params.server.close?.();
|
|
@@ -1114,6 +1241,15 @@ async function startProxyRuntime(params) {
|
|
|
1114
1241
|
logger.debug("[proxy] Failed to auto-configure Claude Code: " +
|
|
1115
1242
|
(error instanceof Error ? error.message : String(error)));
|
|
1116
1243
|
}
|
|
1244
|
+
try {
|
|
1245
|
+
await setOpenCodeProxySettings(`${url}/v1`);
|
|
1246
|
+
logger.always(chalk.green(" ✓ Auto-configured OpenCode settings"));
|
|
1247
|
+
logger.always(chalk.dim(" Restart OpenCode to connect through proxy"));
|
|
1248
|
+
}
|
|
1249
|
+
catch (error) {
|
|
1250
|
+
logger.debug("[proxy] Failed to auto-configure OpenCode: " +
|
|
1251
|
+
(error instanceof Error ? error.message : String(error)));
|
|
1252
|
+
}
|
|
1117
1253
|
}
|
|
1118
1254
|
else {
|
|
1119
1255
|
logger.always(chalk.dim(" ⊘ Dev mode: skipping client auto-configuration"));
|
|
@@ -1808,6 +1944,12 @@ export const proxyGuardCommand = {
|
|
|
1808
1944
|
}
|
|
1809
1945
|
// Restart failed or launchd not installed — clean up Claude settings
|
|
1810
1946
|
const cleared = await clearClaudeProxySettings(expectedBaseUrl);
|
|
1947
|
+
try {
|
|
1948
|
+
await clearOpenCodeProxySettings(`${expectedBaseUrl}/v1`);
|
|
1949
|
+
}
|
|
1950
|
+
catch {
|
|
1951
|
+
// non-fatal
|
|
1952
|
+
}
|
|
1811
1953
|
const state = loadProxyState();
|
|
1812
1954
|
if (state &&
|
|
1813
1955
|
state.host === host &&
|
|
@@ -1916,9 +2058,16 @@ export const proxySetupCommand = {
|
|
|
1916
2058
|
console.info(chalk.green(" ✓ Claude Code configured"));
|
|
1917
2059
|
}
|
|
1918
2060
|
catch (e) {
|
|
1919
|
-
console.info(chalk.yellow(` ⚠ Could not auto-configure: ${e instanceof Error ? e.message : String(e)}`));
|
|
2061
|
+
console.info(chalk.yellow(` ⚠ Could not auto-configure Claude Code: ${e instanceof Error ? e.message : String(e)}`));
|
|
1920
2062
|
console.info(chalk.yellow(` Set manually: ANTHROPIC_BASE_URL=${url}`));
|
|
1921
2063
|
}
|
|
2064
|
+
try {
|
|
2065
|
+
await setOpenCodeProxySettings(`${url}/v1`);
|
|
2066
|
+
console.info(chalk.green(" ✓ OpenCode configured"));
|
|
2067
|
+
}
|
|
2068
|
+
catch (e) {
|
|
2069
|
+
console.info(chalk.yellow(` ⚠ Could not auto-configure OpenCode: ${e instanceof Error ? e.message : String(e)}`));
|
|
2070
|
+
}
|
|
1922
2071
|
// Done!
|
|
1923
2072
|
console.info("");
|
|
1924
2073
|
console.info(chalk.bold.green("Setup complete!"));
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { FallbackEntry, ProxyRoutingConfig, RouteResult } from "../types/index.js";
|
|
1
|
+
import type { FallbackEntry, ModelMapping, ProxyRoutingConfig, RouteResult } from "../types/index.js";
|
|
2
2
|
export declare class ModelRouter {
|
|
3
3
|
private readonly mappings;
|
|
4
4
|
private readonly passthrough;
|
|
@@ -7,4 +7,8 @@ export declare class ModelRouter {
|
|
|
7
7
|
resolve(requestedModel: string): RouteResult;
|
|
8
8
|
isClaudeTarget(requestedModel: string): boolean;
|
|
9
9
|
getFallbackChain(): FallbackEntry[];
|
|
10
|
+
/** Return the raw model mapping entries (used by /v1/models). */
|
|
11
|
+
getModelMappings(): ModelMapping[];
|
|
12
|
+
/** Return models configured for passthrough (used by /v1/models). */
|
|
13
|
+
getPassthroughModels(): string[];
|
|
10
14
|
}
|
|
@@ -29,5 +29,13 @@ export class ModelRouter {
|
|
|
29
29
|
getFallbackChain() {
|
|
30
30
|
return this.fallback;
|
|
31
31
|
}
|
|
32
|
+
/** Return the raw model mapping entries (used by /v1/models). */
|
|
33
|
+
getModelMappings() {
|
|
34
|
+
return Array.from(this.mappings.values());
|
|
35
|
+
}
|
|
36
|
+
/** Return models configured for passthrough (used by /v1/models). */
|
|
37
|
+
getPassthroughModels() {
|
|
38
|
+
return Array.from(this.passthrough);
|
|
39
|
+
}
|
|
32
40
|
}
|
|
33
41
|
//# sourceMappingURL=modelRouter.js.map
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI Chat Completions API format conversion layer.
|
|
3
|
+
*
|
|
4
|
+
* Provides a request parser (OpenAI -> NeuroLink), a response serializer
|
|
5
|
+
* (NeuroLink -> OpenAI), a streaming SSE state machine, and an error
|
|
6
|
+
* envelope helper. Together they allow NeuroLink to act as a
|
|
7
|
+
* drop-in OpenAI API proxy.
|
|
8
|
+
*
|
|
9
|
+
* Reference: https://platform.openai.com/docs/api-reference/chat/create
|
|
10
|
+
*/
|
|
11
|
+
import type { ClaudeRequest, ClaudeResponse, InternalResult, OpenAICompletionRequest, OpenAICompletionResponse, OpenAIErrorResponse, ParsedOpenAIRequest, StreamLifecycleState } from "../types/index.js";
|
|
12
|
+
/** Generate a unique chat completion ID in the OpenAI format. */
|
|
13
|
+
export declare function generateChatCompletionId(): string;
|
|
14
|
+
/** Generate an OpenAI-format tool call ID (`call_` + random chars). */
|
|
15
|
+
export declare function generateOpenAIToolCallId(): string;
|
|
16
|
+
/**
|
|
17
|
+
* Parse an incoming OpenAI Chat Completions request into an intermediate
|
|
18
|
+
* representation consumable by NeuroLink's generate/stream pipeline.
|
|
19
|
+
*
|
|
20
|
+
* Handles:
|
|
21
|
+
* - System prompt extraction from system messages
|
|
22
|
+
* - Message flattening (text + image parts)
|
|
23
|
+
* - Tool definition conversion
|
|
24
|
+
* - tool_choice mapping
|
|
25
|
+
* - top_p, temperature, max_tokens pass-through
|
|
26
|
+
*/
|
|
27
|
+
export declare function parseOpenAIRequest(body: OpenAICompletionRequest): ParsedOpenAIRequest;
|
|
28
|
+
/**
|
|
29
|
+
* Serialize a NeuroLink GenerateResult into an OpenAI Chat Completions response.
|
|
30
|
+
*/
|
|
31
|
+
export declare function serializeOpenAIResponse(result: InternalResult, requestModel: string): OpenAICompletionResponse;
|
|
32
|
+
/**
|
|
33
|
+
* Build an OpenAI-compatible error envelope.
|
|
34
|
+
*/
|
|
35
|
+
export declare function buildOpenAIError(status: number, message: string): OpenAIErrorResponse;
|
|
36
|
+
/**
|
|
37
|
+
* Format a single OpenAI SSE frame.
|
|
38
|
+
* OpenAI uses only `data:` lines (no `event:` prefix unlike Claude).
|
|
39
|
+
*/
|
|
40
|
+
export declare function formatOpenAISSE(data: unknown): string;
|
|
41
|
+
/**
|
|
42
|
+
* Stateful SSE serializer that emits a well-formed OpenAI streaming response.
|
|
43
|
+
*
|
|
44
|
+
* Tracks lifecycle state (`idle` -> `streaming` -> `done`) and the current
|
|
45
|
+
* tool call index for multi-tool streaming.
|
|
46
|
+
*
|
|
47
|
+
* Usage:
|
|
48
|
+
* ```ts
|
|
49
|
+
* const sse = new OpenAIStreamSerializer(requestModel);
|
|
50
|
+
*
|
|
51
|
+
* // Start the stream
|
|
52
|
+
* yield* sse.start();
|
|
53
|
+
*
|
|
54
|
+
* // Text deltas
|
|
55
|
+
* for await (const chunk of textStream) {
|
|
56
|
+
* yield* sse.pushDelta(chunk);
|
|
57
|
+
* }
|
|
58
|
+
*
|
|
59
|
+
* // Tool use
|
|
60
|
+
* yield* sse.pushToolUse(toolId, toolName, toolInput);
|
|
61
|
+
*
|
|
62
|
+
* // Finalize
|
|
63
|
+
* yield* sse.finish("stop", usage);
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export declare class OpenAIStreamSerializer {
|
|
67
|
+
private state;
|
|
68
|
+
private readonly id;
|
|
69
|
+
private readonly model;
|
|
70
|
+
private started;
|
|
71
|
+
private toolCallIndex;
|
|
72
|
+
constructor(model: string);
|
|
73
|
+
/** Current lifecycle state (exposed for testing). */
|
|
74
|
+
getState(): StreamLifecycleState;
|
|
75
|
+
private makeChunk;
|
|
76
|
+
/**
|
|
77
|
+
* Emit the opening frame with `role: "assistant"`.
|
|
78
|
+
*/
|
|
79
|
+
start(): Generator<string>;
|
|
80
|
+
/**
|
|
81
|
+
* Push a text content delta.
|
|
82
|
+
*/
|
|
83
|
+
pushDelta(text: string): Generator<string>;
|
|
84
|
+
/**
|
|
85
|
+
* Push the start of a tool call (id, name, empty arguments).
|
|
86
|
+
*/
|
|
87
|
+
pushToolCallStart(id: string, name: string): Generator<string>;
|
|
88
|
+
/**
|
|
89
|
+
* Push an arguments delta for the current tool call.
|
|
90
|
+
*/
|
|
91
|
+
pushToolCallArgDelta(index: number, argsChunk: string): Generator<string>;
|
|
92
|
+
/**
|
|
93
|
+
* Push a complete tool use: emits tool call start followed by chunked
|
|
94
|
+
* argument deltas (~100 chars per chunk).
|
|
95
|
+
*/
|
|
96
|
+
pushToolUse(id: string, name: string, input: unknown): Generator<string>;
|
|
97
|
+
/**
|
|
98
|
+
* Finalize the stream: emit finish_reason chunk, then `data: [DONE]`.
|
|
99
|
+
*/
|
|
100
|
+
finish(finishReason?: string, usage?: {
|
|
101
|
+
input: number;
|
|
102
|
+
output: number;
|
|
103
|
+
total: number;
|
|
104
|
+
}): Generator<string>;
|
|
105
|
+
/**
|
|
106
|
+
* Emit an error event. Transitions to terminal ERROR state.
|
|
107
|
+
*/
|
|
108
|
+
emitError(message: string): Generator<string>;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Convert an OpenAI Chat Completions request to a Claude Messages API request.
|
|
112
|
+
*
|
|
113
|
+
* Used by the OpenAI proxy endpoint to internally loopback requests targeting
|
|
114
|
+
* Claude models through the proxy's native /v1/messages passthrough path,
|
|
115
|
+
* so they benefit from OAuth account rotation, retry, SSE interception, etc.
|
|
116
|
+
*/
|
|
117
|
+
export declare function convertOpenAIToClaudeRequest(openai: OpenAICompletionRequest): ClaudeRequest;
|
|
118
|
+
/**
|
|
119
|
+
* Convert a non-streaming Claude Messages response to an OpenAI Chat
|
|
120
|
+
* Completions response by bridging through {@link InternalResult}.
|
|
121
|
+
*/
|
|
122
|
+
export declare function convertClaudeToOpenAIResponse(claude: ClaudeResponse, requestModel: string): OpenAICompletionResponse;
|
|
123
|
+
/**
|
|
124
|
+
* Create a TransformStream that parses Claude Messages API SSE events from
|
|
125
|
+
* the upstream response and re-emits them as OpenAI Chat Completions SSE
|
|
126
|
+
* frames.
|
|
127
|
+
*
|
|
128
|
+
* Handles the canonical Claude SSE event types:
|
|
129
|
+
* - message_start -> emits the opening `role: "assistant"` chunk
|
|
130
|
+
* - content_block_start -> text block: no-op; tool_use block: emit tool call start
|
|
131
|
+
* - content_block_delta -> text_delta: emit content delta;
|
|
132
|
+
* input_json_delta: emit tool call argument delta
|
|
133
|
+
* - content_block_stop -> no-op
|
|
134
|
+
* - message_delta -> captures stop_reason and output token usage
|
|
135
|
+
* - message_stop -> emits the final `finish_reason` chunk + `[DONE]`
|
|
136
|
+
*/
|
|
137
|
+
export declare function createClaudeToOpenAIStreamTransform(requestModel: string): TransformStream<Uint8Array, Uint8Array>;
|