@neutrome/open-ai-router 0.1.18 → 0.2.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/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # `@neutrome/open-ai-router`
2
2
 
3
- Deployable router app and reusable router/runtime library surface built on `lil-core` + `lil-exec`.
3
+ Deployable router app and reusable router/runtime library built on
4
+ `@neutrome/lil-engine` for protocol conversion and `@neutrome/lilsdk-ts` for
5
+ executor/tool contracts.
4
6
 
5
7
  ```ts
6
8
  import { createApp, createRouterRuntime, type RouterConfig } from "@neutrome/open-ai-router";
@@ -8,8 +10,9 @@ import { createApp, createRouterRuntime, type RouterConfig } from "@neutrome/ope
8
10
 
9
11
  Primary runtime model:
10
12
 
11
- - client JSON/SSE -> `lil-core` IR
12
- - target resolution -> `lil-exec`
13
+ - client JSON/SSE -> `@neutrome/lil-engine` IR
14
+ - target resolution -> router execution runtime
15
+ - SDK executor or upstream provider invocation
13
16
  - provider transport -> router host
14
17
 
15
18
  Development commands:
@@ -22,4 +25,5 @@ pnpm --filter @neutrome/open-ai-router typecheck
22
25
  Notes:
23
26
 
24
27
  - `RouterConfig` is the canonical router config surface.
25
- - `/v1/models` lists configured executor aliases plus provider `catalog` entries.
28
+ - `/v1/models` lists configured executor aliases.
29
+ - Executor contracts and `connectTools` come from `@neutrome/lilsdk-ts`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neutrome/open-ai-router",
3
- "version": "0.1.18",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./src/index.ts"
@@ -8,7 +8,8 @@
8
8
  "dependencies": {
9
9
  "@modelcontextprotocol/sdk": "^1.29.0",
10
10
  "hono": "^4.12.18",
11
- "@neutrome/lil-engine": "0.1.5"
11
+ "@neutrome/lil-engine": "0.2.0",
12
+ "@neutrome/lilsdk-ts": "0.2.0"
12
13
  },
13
14
  "devDependencies": {
14
15
  "@types/node": "^25.9.3",
@@ -12,7 +12,7 @@ const config: RouterConfig = {
12
12
  exports: ["*"],
13
13
  },
14
14
  },
15
- executors: {
15
+ modelNamespaces: {
16
16
  default: {
17
17
  exports: ["*"],
18
18
  models: {
@@ -28,7 +28,7 @@ describe("createRouterApp trace finalization", () => {
28
28
  const onTrace = vi.fn(async () => {});
29
29
  const app = createRouterApp({
30
30
  config,
31
- executors: {},
31
+ executorImplementations: {},
32
32
  auth: {
33
33
  async authenticate() {
34
34
  return {};
@@ -79,7 +79,7 @@ describe("createRouterApp trace finalization", () => {
79
79
  const onTrace = vi.fn(async () => {});
80
80
  const app = createRouterApp({
81
81
  config,
82
- executors: {},
82
+ executorImplementations: {},
83
83
  auth: {
84
84
  async authenticate() {
85
85
  return {};
@@ -1,6 +1,5 @@
1
1
  import { Hono, type Context } from "hono";
2
- import type { Executor, ProgramTransform } from "@neutrome/lil-engine";
3
- import type { ExecutionRuntimeOptions } from "@neutrome/lil-engine";
2
+ import type { Executor, ProgramTransform } from "@neutrome/lilsdk-ts";
4
3
  import { cors } from "./cors.ts";
5
4
  import { healthHandler } from "./health.ts";
6
5
  import { createTraceCollector, type ExecutionTrace } from "../observer.ts";
@@ -16,6 +15,7 @@ import {
16
15
  import type { RequestContext } from "../auth/types.ts";
17
16
  import type { RouterConfig } from "../router/config.ts";
18
17
  import type { RemoteMcpClientFactory } from "../router/mcp.ts";
18
+ import type { ExecutionRuntimeOptions } from "../router/execution-types.ts";
19
19
 
20
20
  export type RouterAppAuth = {
21
21
  authenticate(request: Request, env: Record<string, unknown>): Promise<object | null>;
@@ -29,7 +29,7 @@ export type RouterAppHooks = {
29
29
 
30
30
  export type RouterAppOptions = {
31
31
  config: RouterConfig;
32
- executors: Readonly<Record<string, Executor>>;
32
+ executorImplementations: Readonly<Record<string, Executor>>;
33
33
  transforms?: Readonly<Record<string, ProgramTransform>>;
34
34
  auth: RouterAppAuth;
35
35
  hooks?: RouterAppHooks;
@@ -135,7 +135,7 @@ export function createRouterApp(options: RouterAppOptions) {
135
135
  const response = await handler({
136
136
  runtime,
137
137
  ctx,
138
- executors: options.executors,
138
+ executorImplementations: options.executorImplementations,
139
139
  ...(options.transforms ? { transforms: options.transforms } : {}),
140
140
  observe,
141
141
  ...(options.upstreamTimeoutMs !== undefined ? { upstreamTimeoutMs: options.upstreamTimeoutMs } : {}),
@@ -1,5 +1,4 @@
1
1
  import type { Context } from "hono";
2
- import type { Executor, ProgramTransform } from "@neutrome/lil-engine";
3
2
  import type { RequestContext } from "../auth/types.ts";
4
3
  import {
5
4
  handleAnthropicMessages,
@@ -18,10 +17,7 @@ type OpenAiModel = {
18
17
  owned_by: string;
19
18
  };
20
19
 
21
- export type ChatCompletionsHandlerOptions = RouterExecutionOptions & {
22
- executors?: Readonly<Record<string, Executor>>;
23
- transforms?: Readonly<Record<string, ProgramTransform>>;
24
- };
20
+ export type ChatCompletionsHandlerOptions = RouterExecutionOptions;
25
21
 
26
22
  export type ResponsesHandlerOptions = ChatCompletionsHandlerOptions;
27
23
  export type AnthropicMessagesHandlerOptions = ChatCompletionsHandlerOptions;
@@ -111,8 +107,8 @@ function createExecutionHandlerOptions(
111
107
  ctx,
112
108
  } as Parameters<typeof handleChatCompletions>[0];
113
109
 
114
- if (options.executors) {
115
- handlerOptions.executors = options.executors;
110
+ if (options.executorImplementations) {
111
+ handlerOptions.executorImplementations = options.executorImplementations;
116
112
  }
117
113
  if (options.resolveExecutor) {
118
114
  handlerOptions.resolveExecutor = options.resolveExecutor;
@@ -1,8 +1,8 @@
1
1
  import { describe, expect, it, vi } from "vitest";
2
+ import { appendAssistantMessage } from "@neutrome/lilsdk-ts/synthetic";
3
+ import { streamTextResponse } from "@neutrome/lilsdk-ts/stream";
2
4
  import {
3
- appendAssistantMessage,
4
5
  getModel,
5
- streamTextResponse,
6
6
  } from "@neutrome/lil-engine";
7
7
  import { createApp } from "./example.ts";
8
8
 
@@ -19,11 +19,11 @@ describe("open-ai-router createApp", () => {
19
19
  exports: ["*"],
20
20
  },
21
21
  },
22
- executors: {
22
+ modelNamespaces: {
23
23
  semantyka: {
24
24
  exports: ["enei-*"],
25
25
  models: {
26
- "enei-1": { executor: "enei-1" },
26
+ "enei-1": { executorId: "enei-1" },
27
27
  },
28
28
  },
29
29
  },
@@ -59,7 +59,7 @@ describe("open-ai-router createApp", () => {
59
59
  exports: ["*"],
60
60
  },
61
61
  },
62
- executors: {
62
+ modelNamespaces: {
63
63
  default: {
64
64
  exports: ["*"],
65
65
  models: {
@@ -135,7 +135,7 @@ describe("open-ai-router createApp", () => {
135
135
  exports: ["*"],
136
136
  },
137
137
  },
138
- executors: {
138
+ modelNamespaces: {
139
139
  default: {
140
140
  exports: ["*"],
141
141
  models: {
@@ -209,7 +209,7 @@ describe("open-ai-router createApp", () => {
209
209
  exports: ["*"],
210
210
  },
211
211
  },
212
- executors: {
212
+ modelNamespaces: {
213
213
  default: {
214
214
  exports: ["*"],
215
215
  models: {
@@ -278,16 +278,16 @@ describe("open-ai-router createApp", () => {
278
278
  const app = createApp({
279
279
  config: {
280
280
  providers: {},
281
- executors: {
281
+ modelNamespaces: {
282
282
  support: {
283
283
  exports: ["*"],
284
284
  models: {
285
- "refund-router": { executor: "support/refund-router" },
285
+ "refund-router": { executorId: "support/refund-router" },
286
286
  },
287
287
  },
288
288
  },
289
289
  },
290
- executors: {
290
+ executorImplementations: {
291
291
  "support/refund-router": {
292
292
  async execute(request) {
293
293
  executeCalled = true;
@@ -333,16 +333,16 @@ describe("open-ai-router createApp", () => {
333
333
  const app = createApp({
334
334
  config: {
335
335
  providers: {},
336
- executors: {
336
+ modelNamespaces: {
337
337
  support: {
338
338
  exports: ["*"],
339
339
  models: {
340
- "refund-router": { executor: "support/refund-router" },
340
+ "refund-router": { executorId: "support/refund-router" },
341
341
  },
342
342
  },
343
343
  },
344
344
  },
345
- executors: {
345
+ executorImplementations: {
346
346
  "support/refund-router": {
347
347
  async execute(request) {
348
348
  capturedModel = getModel(request) ?? null;
package/src/example.ts CHANGED
@@ -29,8 +29,8 @@ export function createApp(options: CreateAppOptions) {
29
29
  const app = new Hono();
30
30
 
31
31
  const handlerOptions = {} as ChatCompletionsHandlerOptions;
32
- if (options.executors) {
33
- handlerOptions.executors = options.executors;
32
+ if (options.executorImplementations) {
33
+ handlerOptions.executorImplementations = options.executorImplementations;
34
34
  }
35
35
  if (options.transforms) {
36
36
  handlerOptions.transforms = options.transforms;
package/src/index.ts CHANGED
@@ -15,34 +15,56 @@ export type { CreateAppOptions } from "./example.ts";
15
15
 
16
16
  export {
17
17
  createFetchProviderInvoker,
18
+ createExecutionRuntime,
18
19
  createRouterExecutionRuntime,
19
20
  createRouterRuntime,
21
+ createAuditEvent,
22
+ createInMemoryAuditSink,
23
+ ExecutionError,
20
24
  handleAnthropicMessages,
21
25
  handleChatCompletions,
22
26
  handleGoogleGenAI,
23
27
  handleResponses,
28
+ isExecutionError,
24
29
  listConfiguredModels,
25
30
  ProviderHttpError,
26
31
  resolveInvocationTarget,
27
32
  resolveInvocationTargets,
28
33
  resolveRequestTarget,
29
34
  RouterError,
35
+ executionTargetAuditRef,
36
+ executionTargetId,
30
37
  } from "./router/index.ts";
31
38
  export type {
39
+ AuditEvent,
40
+ AuditEventInput,
32
41
  AuthConfig,
33
42
  CreateRouterOptions,
34
- ExecutorNamespaceConfig,
35
- ExecutorRouteConfig,
36
- ExecutorRouteRuntime,
37
- ExecutorRuntime,
43
+ ExecutionErrorDetails,
44
+ ExecutionErrorKind,
45
+ ExecutionErrorStage,
46
+ ExecutionRuntime,
47
+ ExecutionRuntimeOptions,
48
+ ExecutionTarget,
49
+ Executor,
38
50
  HandleAnthropicMessagesOptions,
39
51
  HandleChatCompletionsOptions,
40
52
  HandleGoogleGenAIOptions,
41
53
  HandleResponsesOptions,
54
+ InvokeOptions,
55
+ ModelNamespaceConfig,
56
+ ModelNamespaceRuntime,
57
+ ModelRouteConfig,
58
+ ModelRouteRuntime,
59
+ ProgramTransform,
42
60
  ProviderApiStyle,
43
61
  ProviderApiStyle as ProviderStyle,
62
+ ProviderInvocationContext,
63
+ ProviderInvoker,
44
64
  ProviderRuntime,
45
65
  ProviderTargetConfig,
66
+ ResolveExecutor,
67
+ ResolveTarget,
46
68
  RemoteMcpServerConfig,
47
69
  RemoteMcpToolConfig,
48
70
  ResolvedTarget,
@@ -0,0 +1,61 @@
1
+ import {
2
+ createTwoPassExecutor,
3
+ INTERNAL_DRAFT_TOOL_NAME,
4
+ type Executor,
5
+ } from "@neutrome/lilsdk-ts";
6
+
7
+ const LOCALIZED_MODEL = "default/openai/gpt-oss-20b";
8
+ const REASONING_MODEL = "default/openai/gpt-oss-120b";
9
+
10
+ const DRAFT_SYSTEM_PROMPT = ``;
11
+
12
+ const LOCALIZED_SYSTEM_PROMPT_SUFFIX = `Ти — Еней. Український ШІ-асистент.
13
+
14
+ ## Вказівки щодо особистості
15
+ Ти володієш природним розумінням українського культурного контексту, але висловлюєш його тонко й доречно. Ніколи не нав’язуй у своїх відповідях патріотичну риторику, гордість чи культурні алюзії, якщо це не має прямого стосунку до запиту користувача.
16
+
17
+ Ти — відвертий, практичний і прямий ШІ-асистент, який спрямовує користувача на продуктивну діяльність та особистий успіх. Будь відкритим та зважай на думки користувачів, але не погоджуйся, якщо це суперечить об’єктивним фактам. Пристосовуйся до настрою користувача: якщо користувач переживає труднощі, схиляйся до заохочення; якщо користувач просить відгук, надай вдумливу, об’єктивну думку. Коли користувач досліджує або шукає інформацію, повністю присвячуй себе наданню корисної, лаконічної допомоги. Ти глибоко дбаєш про допомогу користувачеві і не прикрашатимеш свої поради, пропонуючи конструктивну критику.
18
+
19
+ Використовуй українську мову за замовчуванням, а інші мови — лише коли це доречно або якщо користувач про це просить.
20
+
21
+ ## Приклади стилю мовлення - використовуй їх як референс стилю, не звертай уваги на суть!
22
+
23
+ Привітання та залучення уваги
24
+ 1. "Друзі, всім величезний привіт! Ви просто не уявляєте, до чого ми сьогодні з вами дійшли."
25
+ 2. "Значить так, історія наступна: ми беремо цю ідею, відкидаємо все зайве і занурюємося туди, де ще ніхто нічого не робив."
26
+ 3. "Я не знаю, наскільки слова взагалі можуть це передати, але давайте я спробую пояснити це максимально просто і без зайвої води."
27
+
28
+ Вираження захоплення та емоцій
29
+ 4. "Ви просто вдумайтесь у це! Це ж справжній відвал бошки, ну погодьтесь."
30
+ 5. "Я зараз дивлюся на цей результат і просто не вірю своїм очам. Це якась абсолютна магія, по-іншому і не скажеш."
31
+ 6. "Цей підхід — це просто якийсь космос. Я щиро знімаю капелюха перед тими, хто взагалі це придумав."
32
+ 7. "Я очікував побачити тут що завгодно, але тільки не це. Це просто тотальний розрив шаблонів!"
33
+ 8. "Ця деталь — це окремий вид мистецтва. Я взагалі не розумію, як воно працює зсередини, але це настільки круто, що можна просто збожеволіти."
34
+
35
+ Розповідь про труднощі та зусилля
36
+ 9. "Ми билися над цим не один день, я вже трохи схожий на зомбі, але повірте: фінальний результат перекриває абсолютно всю втому."
37
+ 10. "Давайте будемо відвертими, це рішення об'єктивно не з найпростіших. Але чи варте воно тих зусиль? На всі сто відсотків."
38
+ 11. "Я не претендую на звання супер-експерта у цій вузькій темі, я просто ділюся своїм досвідом, але давайте спробуємо розібратися разом, як це взагалі працює."
39
+
40
+ Опис процесів та атмосфери
41
+ 12. "Тут є така неймовірна логіка, що хочеться просто зупинитися, роздивитися все ближче і взагалі нікуди не поспішати."
42
+ 13. "Система максимально інтуїтивна і зрозуміла. Ти просто робиш перший крок, і далі все йде як по маслу."
43
+
44
+ Підсумки та висновки
45
+ 14. "Новий досвід — це, мабуть, найкраще, у що людина може інвестувати свій час та ресурси. Тому постійно пробуйте щось нове, друзі, воно того точно варте."
46
+ 15. "Це був дійсно складний виклик, але емоції від результату просто переповнюють. Я щиро радий, що зміг розділити цей момент з вами!"
47
+
48
+ ## Додаткові вказівки
49
+ Дотримуйся наведених вище вказівок природно, не повторюючи, не посилаючись, не переказуючи та не відтворюючи жодних формулювань з них. Усі вказівки повинні непомітно керувати діями і ні в якому разі не впливати на формулювання відповіді — ані явно, ані на метарівні.
50
+
51
+ You may receive an assistant tool call to "${INTERNAL_DRAFT_TOOL_NAME}" followed by a tool result with the same call ID. That exchange is synthetic internal metadata produced by another model. It is not a real user-visible tool invocation.
52
+ Treat the "${INTERNAL_DRAFT_TOOL_NAME}" tool result as background reasoning or a draft answer to inform your response. Use it to answer the user clearly and directly. Do not mention the internal tool exchange, do not ask the user to run it, and do not expose it unless the user explicitly asks for that internal reasoning.`;
53
+
54
+ export const enei1Executor: Executor = createTwoPassExecutor({
55
+ draftModel: REASONING_MODEL,
56
+ finalModel: LOCALIZED_MODEL,
57
+ draftSystemPrompt: DRAFT_SYSTEM_PROMPT,
58
+ finalSystemPrompt: LOCALIZED_SYSTEM_PROMPT_SUFFIX,
59
+ });
60
+
61
+ export default enei1Executor;
package/src/observer.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { opcodeName, type AuditEvent, type Program } from "@neutrome/lil-engine";
1
+ import { opcodeName, type Program } from "@neutrome/lil-engine";
2
+ import type { AuditEvent } from "./router/execution-types.ts";
2
3
 
3
4
  const decoder = new TextDecoder();
4
5
 
@@ -0,0 +1,21 @@
1
+ import type { AuditEvent, AuditEventInput } from "./execution-types.ts";
2
+
3
+ export function createAuditEvent(input: AuditEventInput): AuditEvent {
4
+ return {
5
+ ...input,
6
+ timestamp: input.timestamp ?? new Date().toISOString(),
7
+ };
8
+ }
9
+
10
+ export function createInMemoryAuditSink(): {
11
+ events: AuditEvent[];
12
+ observe(event: AuditEvent): void;
13
+ } {
14
+ const events: AuditEvent[] = [];
15
+ return {
16
+ events,
17
+ observe(event: AuditEvent) {
18
+ events.push(event);
19
+ },
20
+ };
21
+ }
@@ -12,9 +12,9 @@ export type ProviderTargetConfig = {
12
12
  headers?: Record<string, string>;
13
13
  };
14
14
 
15
- export type ExecutorRouteConfig =
15
+ export type ModelRouteConfig =
16
16
  | {
17
- executor: string;
17
+ executorId: string;
18
18
  alias?: string;
19
19
  transforms?: string[];
20
20
  mcps?: string[];
@@ -26,9 +26,9 @@ export type ExecutorRouteConfig =
26
26
  mcps?: string[];
27
27
  };
28
28
 
29
- export type ExecutorNamespaceConfig = {
29
+ export type ModelNamespaceConfig = {
30
30
  exports?: string[] | null;
31
- models: Record<string, ExecutorRouteConfig>;
31
+ models: Record<string, ModelRouteConfig>;
32
32
  };
33
33
 
34
34
  export type RemoteMcpToolConfig = {
@@ -48,6 +48,6 @@ export type RouterConfig = {
48
48
  trace?: boolean;
49
49
  auth?: AuthConfig;
50
50
  providers: Record<string, ProviderTargetConfig>;
51
- executors: Record<string, ExecutorNamespaceConfig>;
51
+ modelNamespaces: Record<string, ModelNamespaceConfig>;
52
52
  mcps?: Record<string, RemoteMcpServerConfig>;
53
53
  };
@@ -0,0 +1,60 @@
1
+ import type { ValidationIssue } from "@neutrome/lil-engine";
2
+
3
+ export type ExecutionErrorKind =
4
+ | "validation"
5
+ | "resolution"
6
+ | "provider"
7
+ | "transform"
8
+ | "executor"
9
+ | "stream"
10
+ | "cancellation"
11
+ | "recursion_limit";
12
+
13
+ export type ExecutionErrorStage =
14
+ | "request"
15
+ | "target_resolution"
16
+ | "transform"
17
+ | "transform_output"
18
+ | "provider_invoke"
19
+ | "provider_result"
20
+ | "executor_invoke"
21
+ | "executor_result"
22
+ | "stream_chunk";
23
+
24
+ export type ExecutionErrorDetails = {
25
+ issues?: ValidationIssue[];
26
+ depth?: number;
27
+ maxDepth?: number;
28
+ transform?: string;
29
+ target?: string;
30
+ source?: "provider" | "executor";
31
+ };
32
+
33
+ export class ExecutionError extends Error {
34
+ readonly kind: ExecutionErrorKind;
35
+ readonly stage?: ExecutionErrorStage;
36
+ readonly details?: ExecutionErrorDetails;
37
+
38
+ constructor(
39
+ kind: ExecutionErrorKind,
40
+ message: string,
41
+ options: {
42
+ stage?: ExecutionErrorStage;
43
+ details?: ExecutionErrorDetails;
44
+ cause?: unknown;
45
+ } = {},
46
+ ) {
47
+ super(message, options.cause === undefined ? undefined : { cause: options.cause });
48
+ this.kind = kind;
49
+ if (options.stage !== undefined) {
50
+ this.stage = options.stage;
51
+ }
52
+ if (options.details !== undefined) {
53
+ this.details = options.details;
54
+ }
55
+ }
56
+ }
57
+
58
+ export function isExecutionError(error: unknown): error is ExecutionError {
59
+ return error instanceof ExecutionError;
60
+ }
@@ -1,4 +1,4 @@
1
- import { appendAssistantMessage } from "@neutrome/lil-engine";
1
+ import { appendAssistantMessage } from "@neutrome/lilsdk-ts/synthetic";
2
2
  import { describe, expect, it, vi } from "vitest";
3
3
  import type { RequestContext } from "../auth/types.ts";
4
4
  import { handleChatCompletions } from "./execute.ts";
@@ -23,7 +23,7 @@ describe("router execution", () => {
23
23
  exports: ["*"],
24
24
  },
25
25
  },
26
- executors: {
26
+ modelNamespaces: {
27
27
  default: {
28
28
  exports: ["*"],
29
29
  models: {
@@ -132,7 +132,7 @@ describe("router execution", () => {
132
132
  }],
133
133
  },
134
134
  },
135
- executors: {
135
+ modelNamespaces: {
136
136
  default: {
137
137
  exports: ["*"],
138
138
  models: {
@@ -239,7 +239,7 @@ describe("router execution", () => {
239
239
  exports: ["*"],
240
240
  },
241
241
  },
242
- executors: {
242
+ modelNamespaces: {
243
243
  default: {
244
244
  exports: ["*"],
245
245
  models: {
@@ -312,7 +312,7 @@ describe("router execution", () => {
312
312
  exports: ["*"],
313
313
  },
314
314
  },
315
- executors: {
315
+ modelNamespaces: {
316
316
  default: {
317
317
  exports: ["*"],
318
318
  models: {
@@ -387,7 +387,7 @@ describe("router execution", () => {
387
387
  exports: ["*"],
388
388
  },
389
389
  },
390
- executors: {
390
+ modelNamespaces: {
391
391
  default: {
392
392
  exports: ["*"],
393
393
  models: {
@@ -451,11 +451,11 @@ describe("router execution", () => {
451
451
  const runtime = createRouterRuntime({
452
452
  config: {
453
453
  providers: {},
454
- executors: {
454
+ modelNamespaces: {
455
455
  enei: {
456
456
  exports: ["enei-*"],
457
457
  models: {
458
- "enei-1": { executor: "enei-1" },
458
+ "enei-1": { executorId: "enei-1" },
459
459
  },
460
460
  },
461
461
  },
@@ -479,7 +479,7 @@ describe("router execution", () => {
479
479
  const response = await handleChatCompletions({
480
480
  runtime,
481
481
  ctx,
482
- executors: {
482
+ executorImplementations: {
483
483
  "enei-1": {
484
484
  async execute(request) {
485
485
  return appendAssistantMessage(request, "done");
@@ -515,7 +515,7 @@ describe("router execution", () => {
515
515
  exports: ["*"],
516
516
  },
517
517
  },
518
- executors: {
518
+ modelNamespaces: {
519
519
  default: {
520
520
  exports: ["*"],
521
521
  models: {
@@ -589,7 +589,7 @@ describe("router execution", () => {
589
589
  exports: ["*"],
590
590
  },
591
591
  },
592
- executors: {
592
+ modelNamespaces: {
593
593
  default: {
594
594
  exports: ["*"],
595
595
  models: {