@neutrome/open-ai-router 0.1.17 → 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.
@@ -1,3 +1,6 @@
1
+ export { createAuditEvent, createInMemoryAuditSink } from "./audit.ts";
2
+ export { ExecutionError, isExecutionError } from "./errors.ts";
3
+ export { createExecutionRuntime } from "./execution-runtime.ts";
1
4
  export { createRouterRuntime } from "./runtime.ts";
2
5
  export {
3
6
  createFetchProviderInvoker,
@@ -6,11 +9,12 @@ export {
6
9
  handleChatCompletions,
7
10
  handleGoogleGenAI,
8
11
  handleResponses,
12
+ ProviderHttpError,
9
13
  resolveRequestTarget,
10
14
  RouterError,
11
- ProviderHttpError,
12
15
  } from "./execute.ts";
13
16
  export { listConfiguredModels, resolveInvocationTarget, resolveInvocationTargets } from "./resolve.ts";
17
+ export { executionTargetAuditRef, executionTargetId } from "./targets.ts";
14
18
  export {
15
19
  createRemoteMcpToolSet,
16
20
  createStreamableHttpMcpClient,
@@ -19,8 +23,8 @@ export {
19
23
  } from "./mcp.ts";
20
24
  export type {
21
25
  AuthConfig,
22
- ExecutorNamespaceConfig,
23
- ExecutorRouteConfig,
26
+ ModelNamespaceConfig,
27
+ ModelRouteConfig,
24
28
  ProviderApiStyle,
25
29
  ProviderTargetConfig,
26
30
  RemoteMcpServerConfig,
@@ -29,12 +33,29 @@ export type {
29
33
  } from "./config.ts";
30
34
  export type {
31
35
  CreateRouterOptions,
32
- ExecutorRouteRuntime,
33
- ExecutorRuntime,
36
+ ModelNamespaceRuntime,
37
+ ModelRouteRuntime,
34
38
  ProviderRuntime,
35
39
  RemoteMcpServerRuntime,
36
40
  RouterRuntime,
37
41
  } from "./runtime.ts";
42
+ export type {
43
+ AuditEvent,
44
+ AuditEventInput,
45
+ ExecutionErrorDetails,
46
+ ExecutionErrorKind,
47
+ ExecutionErrorStage,
48
+ ExecutionRuntime,
49
+ ExecutionRuntimeOptions,
50
+ ExecutionTarget,
51
+ Executor,
52
+ InvokeOptions,
53
+ ProgramTransform,
54
+ ProviderInvocationContext,
55
+ ProviderInvoker,
56
+ ResolveExecutor,
57
+ ResolveTarget,
58
+ } from "./execution-types.ts";
38
59
  export type {
39
60
  HandleAnthropicMessagesOptions,
40
61
  HandleChatCompletionsOptions,
package/src/router/mcp.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
2
  import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
3
3
  import type { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
4
- import type { ExecutionContext, Tool } from "@neutrome/lil-engine";
4
+ import type { ExecutorContext, Tool } from "@neutrome/lilsdk-ts";
5
5
  import type { RemoteMcpServerRuntime, RouterRuntime } from "./runtime.ts";
6
6
 
7
7
  export type RemoteMcpToolCallClient = {
@@ -44,7 +44,7 @@ export function createRemoteMcpToolSet(
44
44
  name,
45
45
  description: snapshot.description || `Remote MCP tool ${server.name}/${snapshot.name}`,
46
46
  schema: normalizeSchema(snapshot.inputSchema),
47
- async execute(args: Record<string, unknown>, ctx: ExecutionContext) {
47
+ async execute(args: Record<string, unknown>, ctx: ExecutorContext) {
48
48
  const client = await pool.get(server, ctx.signal);
49
49
  const result = await client.callTool(snapshot.name, args);
50
50
  return stringifyMcpToolResult(result);
@@ -13,12 +13,12 @@ describe("router resolution", () => {
13
13
  exports: ["*"],
14
14
  },
15
15
  },
16
- executors: {
16
+ modelNamespaces: {
17
17
  enei: {
18
18
  exports: ["enei-*"],
19
19
  models: {
20
- "enei-1": { executor: "enei-1" },
21
- "enei-1-pro": { executor: "enei-1-pro", transforms: ["reasoning:high"] },
20
+ "enei-1": { executorId: "enei-1" },
21
+ "enei-1-pro": { executorId: "enei-1-pro", transforms: ["reasoning:high"] },
22
22
  },
23
23
  },
24
24
  },
@@ -30,7 +30,7 @@ describe("router resolution", () => {
30
30
  expect(resolved.namespace).toBe("enei");
31
31
  expect(resolved.target).toEqual({
32
32
  kind: "executor",
33
- executor: "enei-1",
33
+ executorId: "enei-1",
34
34
  alias: "enei-1",
35
35
  transforms: ["slwin:8"],
36
36
  });
@@ -46,7 +46,7 @@ describe("router resolution", () => {
46
46
  exports: ["google/*"],
47
47
  },
48
48
  },
49
- executors: {},
49
+ modelNamespaces: {},
50
50
  },
51
51
  knownSuffixes: ["slwin", "kvtools"],
52
52
  });
@@ -71,7 +71,7 @@ describe("router resolution", () => {
71
71
  exports: ["openai/gpt-4.1-mini"],
72
72
  },
73
73
  },
74
- executors: {
74
+ modelNamespaces: {
75
75
  semantyka: {
76
76
  exports: ["enei-*"],
77
77
  models: {
@@ -103,12 +103,12 @@ describe("router resolution", () => {
103
103
  exports: ["*"],
104
104
  },
105
105
  },
106
- executors: {
106
+ modelNamespaces: {
107
107
  enei: {
108
108
  exports: ["enei-*"],
109
109
  models: {
110
- "enei-1": { executor: "enei-1" },
111
- "enei-1-pro": { executor: "enei-1-pro" },
110
+ "enei-1": { executorId: "enei-1" },
111
+ "enei-1-pro": { executorId: "enei-1-pro" },
112
112
  },
113
113
  },
114
114
  },
@@ -131,7 +131,7 @@ describe("router resolution", () => {
131
131
  exports: ["*"],
132
132
  },
133
133
  },
134
- executors: {
134
+ modelNamespaces: {
135
135
  default: {
136
136
  exports: ["*"],
137
137
  models: {
@@ -1,4 +1,4 @@
1
- import type { ExecutionTarget } from "@neutrome/lil-engine";
1
+ import type { ExecutionTarget } from "@neutrome/lilsdk-ts";
2
2
  import { parseModelSyntax, type ModelSuffixSpec } from "../util/model-syntax.ts";
3
3
  import type { RouterRuntime } from "./runtime.ts";
4
4
 
@@ -35,10 +35,10 @@ export function resolveInvocationTargets(
35
35
  }
36
36
 
37
37
  const matches: ResolvedTarget[] = [];
38
- for (const namespace of runtime.executorOrder) {
39
- const executor = runtime.executors.get(namespace)!;
40
- const route = executor.routes.get(parsed.baseModel);
41
- if (route && executor.exportsMatcher(parsed.baseModel)) {
38
+ for (const namespace of runtime.modelNamespaceOrder) {
39
+ const modelNamespace = runtime.modelNamespaces.get(namespace)!;
40
+ const route = modelNamespace.routes.get(parsed.baseModel);
41
+ if (route && modelNamespace.exportsMatcher(parsed.baseModel)) {
42
42
  matches.push({
43
43
  requestedModel,
44
44
  namespace,
@@ -56,10 +56,10 @@ export function resolveInvocationTargets(
56
56
  export function listConfiguredModels(runtime: RouterRuntime): string[] {
57
57
  const models: string[] = [];
58
58
 
59
- for (const namespace of runtime.executorOrder) {
60
- const executor = runtime.executors.get(namespace)!;
61
- for (const alias of executor.routes.keys()) {
62
- if (executor.exportsMatcher(alias)) {
59
+ for (const namespace of runtime.modelNamespaceOrder) {
60
+ const modelNamespace = runtime.modelNamespaces.get(namespace)!;
61
+ for (const alias of modelNamespace.routes.keys()) {
62
+ if (modelNamespace.exportsMatcher(alias)) {
63
63
  models.push(`${namespace}/${alias}`);
64
64
  }
65
65
  }
@@ -76,15 +76,15 @@ function resolveQualified(
76
76
  suffixes: ModelSuffixSpec[],
77
77
  ): ResolvedTarget[] {
78
78
  const provider = runtime.providers.get(namespace);
79
- const executor = runtime.executors.get(namespace);
79
+ const modelNamespace = runtime.modelNamespaces.get(namespace);
80
80
 
81
- if (provider && executor) {
82
- throw new Error(`Ambiguous namespace \`${namespace}\`: both provider and executor are registered`);
81
+ if (provider && modelNamespace) {
82
+ throw new Error(`Ambiguous namespace \`${namespace}\`: both provider and model namespace are registered`);
83
83
  }
84
84
 
85
- if (executor) {
86
- const route = executor.routes.get(model);
87
- if (!route || !executor.exportsMatcher(model)) {
85
+ if (modelNamespace) {
86
+ const route = modelNamespace.routes.get(model);
87
+ if (!route || !modelNamespace.exportsMatcher(model)) {
88
88
  return [];
89
89
  }
90
90
  return [{
@@ -1,10 +1,10 @@
1
- import type { ExecutionTarget } from "@neutrome/lil-engine";
1
+ import type { ExecutionTarget } from "@neutrome/lilsdk-ts";
2
2
  import type { AuthDriver } from "../auth/types.ts";
3
3
  import { buildAuthChain } from "../auth/registry.ts";
4
4
  import { createExportsMatcher } from "../util/glob.ts";
5
5
  import type {
6
- ExecutorNamespaceConfig,
7
- ExecutorRouteConfig,
6
+ ModelNamespaceConfig,
7
+ ModelRouteConfig,
8
8
  ProviderTargetConfig,
9
9
  RemoteMcpServerConfig,
10
10
  RouterConfig,
@@ -19,25 +19,25 @@ export type ProviderRuntime = {
19
19
  exportsMatcher: (model: string) => boolean;
20
20
  };
21
21
 
22
- export type ExecutorRouteRuntime = {
22
+ export type ModelRouteRuntime = {
23
23
  requestedAlias: string;
24
24
  target: ExecutionTarget;
25
25
  transforms: readonly string[];
26
26
  mcps: readonly string[];
27
27
  };
28
28
 
29
- export type ExecutorRuntime = {
29
+ export type ModelNamespaceRuntime = {
30
30
  name: string;
31
31
  exportsMatcher: (model: string) => boolean;
32
- routes: ReadonlyMap<string, ExecutorRouteRuntime>;
32
+ routes: ReadonlyMap<string, ModelRouteRuntime>;
33
33
  };
34
34
 
35
35
  export type RouterRuntime = {
36
36
  config: RouterConfig;
37
37
  providers: ReadonlyMap<string, ProviderRuntime>;
38
38
  providerOrder: readonly string[];
39
- executors: ReadonlyMap<string, ExecutorRuntime>;
40
- executorOrder: readonly string[];
39
+ modelNamespaces: ReadonlyMap<string, ModelNamespaceRuntime>;
40
+ modelNamespaceOrder: readonly string[];
41
41
  mcps: ReadonlyMap<string, RemoteMcpServerRuntime>;
42
42
  authChain: readonly AuthDriver[];
43
43
  knownSuffixes: ReadonlySet<string>;
@@ -57,19 +57,19 @@ export type CreateRouterOptions = {
57
57
 
58
58
  export function createRouterRuntime(options: CreateRouterOptions): RouterRuntime {
59
59
  const providers = new Map<string, ProviderRuntime>();
60
- const executors = new Map<string, ExecutorRuntime>();
60
+ const modelNamespaces = new Map<string, ModelNamespaceRuntime>();
61
61
  const mcps = new Map<string, RemoteMcpServerRuntime>();
62
62
  const providerOrder: string[] = [];
63
- const executorOrder: string[] = [];
63
+ const modelNamespaceOrder: string[] = [];
64
64
 
65
65
  for (const [name, config] of Object.entries(options.config.providers)) {
66
66
  providerOrder.push(name);
67
67
  providers.set(name, buildProviderRuntime(name, config));
68
68
  }
69
69
 
70
- for (const [name, config] of Object.entries(options.config.executors)) {
71
- executorOrder.push(name);
72
- executors.set(name, buildExecutorRuntime(name, config));
70
+ for (const [name, config] of Object.entries(options.config.modelNamespaces)) {
71
+ modelNamespaceOrder.push(name);
72
+ modelNamespaces.set(name, buildModelNamespaceRuntime(name, config));
73
73
  }
74
74
  for (const [name, config] of Object.entries(options.config.mcps ?? {})) {
75
75
  mcps.set(name, { name, ...config });
@@ -79,8 +79,8 @@ export function createRouterRuntime(options: CreateRouterOptions): RouterRuntime
79
79
  config: options.config,
80
80
  providers,
81
81
  providerOrder,
82
- executors,
83
- executorOrder,
82
+ modelNamespaces,
83
+ modelNamespaceOrder,
84
84
  mcps,
85
85
  authChain: options.authDrivers ?? buildAuthChain(options.config.auth),
86
86
  knownSuffixes: new Set(options.knownSuffixes ?? ["slwin", "kvtools"]),
@@ -99,10 +99,10 @@ function buildProviderRuntime(name: string, config: ProviderTargetConfig): Provi
99
99
  };
100
100
  }
101
101
 
102
- function buildExecutorRuntime(name: string, config: ExecutorNamespaceConfig): ExecutorRuntime {
103
- const routes = new Map<string, ExecutorRouteRuntime>();
102
+ function buildModelNamespaceRuntime(name: string, config: ModelNamespaceConfig): ModelNamespaceRuntime {
103
+ const routes = new Map<string, ModelRouteRuntime>();
104
104
  for (const [alias, route] of Object.entries(config.models)) {
105
- routes.set(alias, buildExecutorRoute(alias, route));
105
+ routes.set(alias, buildModelRoute(alias, route));
106
106
  }
107
107
 
108
108
  return {
@@ -112,7 +112,7 @@ function buildExecutorRuntime(name: string, config: ExecutorNamespaceConfig): Ex
112
112
  };
113
113
  }
114
114
 
115
- function buildExecutorRoute(alias: string, route: ExecutorRouteConfig): ExecutorRouteRuntime {
115
+ function buildModelRoute(alias: string, route: ModelRouteConfig): ModelRouteRuntime {
116
116
  if ("provider" in route) {
117
117
  return {
118
118
  requestedAlias: alias,
@@ -128,12 +128,12 @@ function buildExecutorRoute(alias: string, route: ExecutorRouteConfig): Executor
128
128
  }
129
129
 
130
130
  return {
131
- requestedAlias: alias,
132
- transforms: route.transforms ?? [],
133
- mcps: route.mcps ?? [],
134
- target: {
131
+ requestedAlias: alias,
132
+ transforms: route.transforms ?? [],
133
+ mcps: route.mcps ?? [],
134
+ target: {
135
135
  kind: "executor",
136
- executor: route.executor,
136
+ executorId: route.executorId,
137
137
  alias: route.alias ?? alias,
138
138
  transforms: route.transforms ?? [],
139
139
  },
@@ -0,0 +1,17 @@
1
+ import type { ExecutionTarget } from "./execution-types.ts";
2
+
3
+ export function executionTargetId(target: ExecutionTarget): string {
4
+ return target.kind === "provider"
5
+ ? target.provider ? `${target.provider}/${target.model}` : target.model
6
+ : `${target.executorId}/${target.alias}`;
7
+ }
8
+
9
+ export function executionTargetAuditRef(target: ExecutionTarget): {
10
+ kind: "provider" | "executor";
11
+ id: string;
12
+ } {
13
+ return {
14
+ kind: target.kind,
15
+ id: executionTargetId(target),
16
+ };
17
+ }
package/src/worker.ts CHANGED
@@ -18,7 +18,7 @@ const config: RouterConfig = {
18
18
  exports: ["*:free"],
19
19
  },
20
20
  },
21
- executors: {},
21
+ modelNamespaces: {},
22
22
  };
23
23
 
24
24
  let appPromise: Promise<ReturnType<typeof createApp>> | undefined;