@neutrome/open-ai-router 0.6.8 → 0.6.10

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 CHANGED
@@ -30,4 +30,4 @@ Notes:
30
30
 
31
31
  - `RouterConfig` is the canonical router config surface.
32
32
  - `/v1/models` lists configured executor aliases.
33
- - Executor contracts and `connectTools` come from `@neutrome/lilsdk`.
33
+ - Executor contracts and `createToolsExecutor` come from `@neutrome/lilsdk`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neutrome/open-ai-router",
3
- "version": "0.6.8",
3
+ "version": "0.6.10",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./src/index.ts"
@@ -11,8 +11,8 @@
11
11
  "hono": "^4.12.18",
12
12
  "posthog-node": "^5.41.0",
13
13
  "zod": "^4.2.1",
14
- "@neutrome/lil-engine": "0.4.5",
15
- "@neutrome/lilsdk": "0.4.5"
14
+ "@neutrome/lil-engine": "0.5.1",
15
+ "@neutrome/lilsdk": "0.5.1"
16
16
  },
17
17
  "devDependencies": {
18
18
  "@types/node": "^25.9.3",
@@ -25,6 +25,7 @@
25
25
  "cf-typegen": "wrangler types",
26
26
  "test": "vitest run",
27
27
  "typecheck": "tsc -p tsconfig.json --noEmit",
28
+ "npm:publish": "pnpm publish --no-git-checks",
28
29
  "dev": "wrangler dev",
29
30
  "preview": "wrangler preview",
30
31
  "deploy": "wrangler deploy"
@@ -1,9 +1,9 @@
1
1
  import { Hono, type Context } from "hono";
2
2
  import {
3
3
  getModel,
4
- setStreaming,
5
4
  type Program,
6
5
  type ProviderStyle,
6
+ setStreaming,
7
7
  } from "@neutrome/lil-engine";
8
8
  import { cors } from "./cors.ts";
9
9
  import { healthHandler } from "./health.ts";
@@ -2,7 +2,7 @@ import {
2
2
  appendErrorBlock,
3
3
  createProgram,
4
4
  emitProviderError,
5
- firstError,
5
+ getFirstErrorBlock,
6
6
  parseProviderError,
7
7
  type Program,
8
8
  type ProviderStyle,
@@ -21,7 +21,7 @@ export async function toProviderError(
21
21
  contentType: response.headers.get("content-type"),
22
22
  });
23
23
  const summary =
24
- firstError(program)?.message ||
24
+ getFirstErrorBlock(program)?.message ||
25
25
  `Provider ${provider.name} returned ${response.status}`;
26
26
  return new ProviderHttpError(
27
27
  summary,
@@ -1,4 +1,4 @@
1
- import { appendAssistantMessage } from "@neutrome/lilsdk/synthetic";
1
+ import { appendAssistantMessage } from "@neutrome/lil-engine";
2
2
  import { describe, expect, it, vi } from "vitest";
3
3
  import type { RequestContext } from "../upstream-auth/types.ts";
4
4
  import { handleChatCompletions } from "./execute.ts";
@@ -1,20 +1,18 @@
1
1
  import {
2
- emitChatCompletionsResponse,
3
2
  emitProviderError,
4
3
  emitProviderRequest,
5
4
  emitProviderResponse,
6
5
  emitProviderStreamChunk,
7
6
  getModel,
7
+ getUsage,
8
8
  isStreaming,
9
- parseChatCompletionsRequest,
10
9
  parseProviderRequest,
11
10
  parseProviderResponse,
12
11
  parseProviderStreamChunk,
13
- setModel,
14
- setStreaming,
15
12
  type Program,
16
13
  type ProviderStyle,
17
- usageObject,
14
+ setModel,
15
+ setStreaming,
18
16
  } from "@neutrome/lil-engine";
19
17
  import { createExecutionRuntime } from "./execution-runtime.ts";
20
18
  import { createFetchProviderInvoker } from "./provider-invoker.ts";
@@ -165,10 +163,8 @@ export function createRouterExecutionRuntime(
165
163
  export async function handleChatCompletions(
166
164
  options: HandleChatCompletionsOptions,
167
165
  ): Promise<Response> {
168
- return handleRequestStyle(
169
- "chat-completions",
170
- options,
171
- emitChatCompletionsResponse,
166
+ return handleRequestStyle("chat-completions", options, (program) =>
167
+ emitProviderResponse("chat-completions", program),
172
168
  );
173
169
  }
174
170
 
@@ -1,4 +1,4 @@
1
- import { firstError, type Program } from "@neutrome/lil-engine";
1
+ import { getFirstErrorBlock, type Program } from "@neutrome/lil-engine";
2
2
  import {
3
3
  ExecutionError,
4
4
  isExecutionError,
@@ -100,7 +100,7 @@ export function normalizeExecutionError(
100
100
  ): ExecutionError {
101
101
  if (isExecutionError(error)) return error;
102
102
  if (error instanceof ProviderHttpError) {
103
- const upstream = firstError(error.program);
103
+ const upstream = getFirstErrorBlock(error.program);
104
104
  return new ExecutionError("provider", error.message, {
105
105
  stage: fallbackStage,
106
106
  details: {
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  emitProviderRequest,
3
+ getUsage,
3
4
  isStreaming,
4
5
  parseProviderStreamChunk,
5
- setModel,
6
6
  type Program,
7
- usageObject,
7
+ setModel,
8
8
  } from "@neutrome/lil-engine";
9
9
  import { RouterError } from "./errors.ts";
10
10
  import { toProviderError } from "./error-codec.ts";
@@ -155,7 +155,7 @@ export async function* streamProvider(
155
155
  encoder.encode(data),
156
156
  );
157
157
  responseChunks.push(chunk);
158
- if (usageObject(chunk) !== undefined) lastChunkWithUsage = chunk;
158
+ if (getUsage(chunk) !== undefined) lastChunkWithUsage = chunk;
159
159
  yield chunk;
160
160
  }
161
161
  }
@@ -181,7 +181,7 @@ export async function* streamProvider(
181
181
  encoder.encode(data),
182
182
  );
183
183
  responseChunks.push(chunk);
184
- if (usageObject(chunk) !== undefined) lastChunkWithUsage = chunk;
184
+ if (getUsage(chunk) !== undefined) lastChunkWithUsage = chunk;
185
185
  yield chunk;
186
186
  }
187
187
  }
@@ -1,4 +1,4 @@
1
- import { usageObject, type Program } from "@neutrome/lil-engine";
1
+ import { getUsage, type Program } from "@neutrome/lil-engine";
2
2
  import { createExecutionEvent } from "@neutrome/lilsdk";
3
3
  import { z } from "zod";
4
4
  import {
@@ -21,7 +21,7 @@ export function emitProviderUsage(
21
21
  responseBytes: number,
22
22
  streamChunks?: readonly Program[],
23
23
  ): void {
24
- const usage = response ? usageObject(response) : undefined;
24
+ const usage = response ? getUsage(response) : undefined;
25
25
  const u = (usage && typeof usage === "object" ? usage : {}) as Record<
26
26
  string,
27
27
  unknown
@@ -1,4 +1,4 @@
1
- import { connectTools } from "@neutrome/lilsdk/tools";
1
+ import { createToolsExecutor } from "@neutrome/lilsdk/tools";
2
2
  import type {
3
3
  ExecutionTarget,
4
4
  Executor,
@@ -49,7 +49,10 @@ export function prepareRemoteMcpExecution(
49
49
  ...options,
50
50
  executorImplementations: {
51
51
  ...(options.executorImplementations ?? {}),
52
- [executorName]: connectTools(remoteMcp.tools, resolved.requestedModel),
52
+ [executorName]: createToolsExecutor(
53
+ resolved.requestedModel,
54
+ remoteMcp.tools,
55
+ ),
53
56
  },
54
57
  },
55
58
  close: remoteMcp.close,
@@ -1,5 +1,4 @@
1
1
  import {
2
- parseChatCompletionsRequest,
3
2
  parseProviderRequest,
4
3
  type Program,
5
4
  type ProviderStyle,
@@ -11,6 +10,6 @@ export async function parseRequestProgram(
11
10
  ): Promise<Program> {
12
11
  const body = new Uint8Array(await request.arrayBuffer());
13
12
  return style === "chat-completions"
14
- ? parseChatCompletionsRequest(body)
13
+ ? parseProviderRequest("chat-completions", body)
15
14
  : parseProviderRequest(style, body);
16
15
  }
@@ -1,7 +1,7 @@
1
1
  import {
2
+ delta,
2
3
  emitProviderError,
3
4
  emitProviderStreamChunk,
4
- repackStream,
5
5
  type Program,
6
6
  type ProviderStyle,
7
7
  } from "@neutrome/lil-engine";
@@ -21,9 +21,9 @@ export async function streamExecutionResponse(
21
21
  input: { requestId: string; executionId: string; startedAtMs: number },
22
22
  cleanup?: () => Promise<void>,
23
23
  ): Promise<Response> {
24
- const iterator = repackStream(chunks, { target: responseStyle })[
25
- Symbol.asyncIterator
26
- ]();
24
+ const iterator = delta
25
+ .repack(chunks, { target: responseStyle })
26
+ [Symbol.asyncIterator]();
27
27
 
28
28
  const first = await iterator.next();
29
29
  observeTimedExecution({
@@ -1,10 +1,10 @@
1
1
  import {
2
- decodeStreamToolDelta,
3
- emitChatCompletionsRequest,
4
- emitChatCompletionsResponse,
5
- type Program,
2
+ delta,
3
+ emitProviderRequest,
4
+ emitProviderResponse,
5
+ getUsage,
6
6
  Opcode,
7
- usageObject,
7
+ type Program,
8
8
  } from "@neutrome/lil-engine";
9
9
 
10
10
  const decoder = new TextDecoder();
@@ -13,7 +13,7 @@ const decoder = new TextDecoder();
13
13
  export function normalizeChatRequest(
14
14
  program: Program,
15
15
  ): Record<string, unknown> {
16
- const request = json(emitChatCompletionsRequest(program));
16
+ const request = json(emitProviderRequest("chat-completions", program));
17
17
  delete request.stream;
18
18
  return request;
19
19
  }
@@ -21,7 +21,7 @@ export function normalizeChatRequest(
21
21
  export function normalizeChatResponse(
22
22
  program: Program,
23
23
  ): Record<string, unknown> {
24
- return json(emitChatCompletionsResponse(program));
24
+ return json(emitProviderResponse("chat-completions", program));
25
25
  }
26
26
 
27
27
  export function normalizeChatStream(
@@ -39,7 +39,7 @@ export function normalizeChatStream(
39
39
  let usage: unknown;
40
40
 
41
41
  for (const chunk of chunks) {
42
- const chunkUsage = usageObject(chunk);
42
+ const chunkUsage = getUsage(chunk);
43
43
  if (chunkUsage !== undefined) usage = chunkUsage;
44
44
  for (const instruction of chunk.code) {
45
45
  if (
@@ -68,13 +68,14 @@ export function normalizeChatStream(
68
68
  )
69
69
  reasoning.push(instruction.value.value);
70
70
  if (instruction.opcode !== Opcode.STREAM_TOOL_DELTA) continue;
71
- const delta = decodeStreamToolDelta(instruction);
72
- if (!delta) continue;
73
- const tool = tools.get(delta.index) ?? { arguments: "" };
74
- if (delta.id !== undefined) tool.id = delta.id;
75
- if (delta.name !== undefined) tool.name = delta.name;
76
- if (delta.arguments !== undefined) tool.arguments += delta.arguments;
77
- tools.set(delta.index, tool);
71
+ const toolCall = delta.decodeToolCall(instruction);
72
+ if (!toolCall) continue;
73
+ const tool = tools.get(toolCall.index) ?? { arguments: "" };
74
+ if (toolCall.id !== undefined) tool.id = toolCall.id;
75
+ if (toolCall.name !== undefined) tool.name = toolCall.name;
76
+ if (toolCall.arguments !== undefined)
77
+ tool.arguments += toolCall.arguments;
78
+ tools.set(toolCall.index, tool);
78
79
  }
79
80
  }
80
81
 
@@ -1,5 +1,5 @@
1
1
  import { createExecutionEvent } from "@neutrome/lilsdk";
2
- import { streamEnd, streamStart, streamTextDelta } from "@neutrome/lil-engine";
2
+ import { delta } from "@neutrome/lil-engine";
3
3
  import { describe, expect, it, vi } from "vitest";
4
4
  import {
5
5
  createRouterTelemetry,
@@ -185,10 +185,10 @@ describe("trace chat normalization", () => {
185
185
  it("concatenates stream chunks into a chat completion response", () => {
186
186
  expect(
187
187
  normalizeChatStream([
188
- streamStart(),
189
- streamTextDelta("hello "),
190
- streamTextDelta("world"),
191
- streamEnd("length"),
188
+ delta.start(),
189
+ delta.text("hello "),
190
+ delta.text("world"),
191
+ delta.end("length"),
192
192
  ]),
193
193
  ).toEqual({
194
194
  object: "chat.completion",