@velum-labs/routekit-daemon 1.3.2 → 1.5.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.
Files changed (172) hide show
  1. package/dist/account-enroll-service.d.ts +1 -3
  2. package/dist/account-enroll-service.js +262 -262
  3. package/dist/account-mutation-service.d.ts +1 -3
  4. package/dist/account-mutation-service.js +302 -283
  5. package/dist/account-query-service.d.ts +1 -3
  6. package/dist/account-query-service.js +88 -86
  7. package/dist/call-attribution-store.js +544 -1
  8. package/dist/control-dispatch.js +9 -15
  9. package/dist/daemon-bootstrap-preflight.js +1 -1
  10. package/dist/daemon-control-handlers.d.ts +1 -1
  11. package/dist/daemon-control-handlers.js +24 -27
  12. package/dist/daemon-generations.d.ts +14 -28
  13. package/dist/daemon-generations.js +114 -53
  14. package/dist/daemon-lifecycle-service.d.ts +1 -3
  15. package/dist/daemon-lifecycle-service.js +88 -94
  16. package/dist/daemon-maintenance.d.ts +27 -49
  17. package/dist/daemon-maintenance.js +5 -1
  18. package/dist/daemon-options.d.ts +3 -2
  19. package/dist/daemon-policy-context.d.ts +1 -0
  20. package/dist/daemon-policy-context.js +1 -0
  21. package/dist/daemon-runtime-state.d.ts +1 -1
  22. package/dist/daemon-runtime-state.js +2 -3
  23. package/dist/daemon-state-context.d.ts +1 -1
  24. package/dist/daemon-state-context.js +1 -38
  25. package/dist/doctor-service.d.ts +1 -3
  26. package/dist/doctor-service.js +87 -91
  27. package/dist/effect/daemon-live.d.ts +7 -6
  28. package/dist/effect/daemon-live.js +57 -135
  29. package/dist/eval-routing-service.d.ts +1 -3
  30. package/dist/eval-routing-service.js +45 -69
  31. package/dist/eval-session-execution-store.d.ts +24 -0
  32. package/dist/eval-session-execution-store.js +253 -0
  33. package/dist/host-protocol.d.ts +1 -0
  34. package/dist/host.js +3 -0
  35. package/dist/internal-providers/provider-anthropic/index.d.ts +23 -0
  36. package/dist/internal-providers/provider-anthropic/index.js +42 -0
  37. package/dist/internal-providers/provider-anthropic/test/provider.test.js +33 -0
  38. package/dist/internal-providers/provider-azure/index.d.ts +25 -0
  39. package/dist/internal-providers/provider-azure/index.js +101 -0
  40. package/dist/internal-providers/provider-azure/test/provider.test.js +83 -0
  41. package/dist/internal-providers/provider-bedrock/codec.d.ts +11 -0
  42. package/dist/internal-providers/provider-bedrock/codec.js +484 -0
  43. package/dist/internal-providers/provider-bedrock/connection-settings.d.ts +6 -0
  44. package/dist/internal-providers/provider-bedrock/connection-settings.js +41 -0
  45. package/dist/internal-providers/provider-bedrock/connection.d.ts +17 -0
  46. package/dist/internal-providers/provider-bedrock/connection.js +143 -0
  47. package/dist/internal-providers/provider-bedrock/index.d.ts +27 -0
  48. package/dist/internal-providers/provider-bedrock/index.js +47 -0
  49. package/dist/internal-providers/provider-bedrock/source.d.ts +39 -0
  50. package/dist/internal-providers/provider-bedrock/source.js +454 -0
  51. package/dist/internal-providers/provider-bedrock/test/bedrock-source.test.d.ts +1 -0
  52. package/dist/internal-providers/provider-bedrock/test/bedrock-source.test.js +786 -0
  53. package/dist/internal-providers/provider-bedrock/test/connection.test.d.ts +1 -0
  54. package/dist/internal-providers/provider-bedrock/test/connection.test.js +249 -0
  55. package/dist/internal-providers/provider-bedrock/test/workload-credentials.test.d.ts +1 -0
  56. package/dist/internal-providers/provider-bedrock/test/workload-credentials.test.js +29 -0
  57. package/dist/internal-providers/provider-bedrock/workload-credentials.d.ts +5 -0
  58. package/dist/internal-providers/provider-bedrock/workload-credentials.js +14 -0
  59. package/dist/internal-providers/provider-claude-code/index.d.ts +6 -0
  60. package/dist/internal-providers/provider-claude-code/index.js +4 -0
  61. package/dist/internal-providers/provider-claude-code/module-api.d.ts +25 -0
  62. package/dist/internal-providers/provider-claude-code/module-api.js +31 -0
  63. package/dist/internal-providers/provider-claude-code/relay.d.ts +20 -0
  64. package/dist/internal-providers/provider-claude-code/relay.js +115 -0
  65. package/dist/internal-providers/provider-claude-code/subscription.d.ts +2 -0
  66. package/dist/internal-providers/provider-claude-code/subscription.js +194 -0
  67. package/dist/internal-providers/provider-claude-code/test/http-submission.test.d.ts +1 -0
  68. package/dist/internal-providers/provider-claude-code/test/http-submission.test.js +140 -0
  69. package/dist/internal-providers/provider-claude-code/test/relay.test.d.ts +1 -0
  70. package/dist/internal-providers/provider-claude-code/test/relay.test.js +379 -0
  71. package/dist/internal-providers/provider-claude-code/test/subscription.test.d.ts +1 -0
  72. package/dist/internal-providers/provider-claude-code/test/subscription.test.js +256 -0
  73. package/dist/internal-providers/provider-cliproxy/index.d.ts +9 -0
  74. package/dist/internal-providers/provider-cliproxy/index.js +15 -0
  75. package/dist/internal-providers/provider-codex/index.d.ts +6 -0
  76. package/dist/internal-providers/provider-codex/index.js +7 -0
  77. package/dist/internal-providers/provider-codex/module-api.d.ts +25 -0
  78. package/dist/internal-providers/provider-codex/module-api.js +31 -0
  79. package/dist/internal-providers/provider-codex/relay.d.ts +123 -0
  80. package/dist/internal-providers/provider-codex/relay.js +261 -0
  81. package/dist/internal-providers/provider-codex/subscription.d.ts +2 -0
  82. package/dist/internal-providers/provider-codex/subscription.js +555 -0
  83. package/dist/internal-providers/provider-codex/test/http-submission.test.d.ts +1 -0
  84. package/dist/internal-providers/provider-codex/test/http-submission.test.js +142 -0
  85. package/dist/internal-providers/provider-codex/test/relay.test.d.ts +1 -0
  86. package/dist/internal-providers/provider-codex/test/relay.test.js +600 -0
  87. package/dist/internal-providers/provider-codex/test/subscription.test.d.ts +1 -0
  88. package/dist/internal-providers/provider-codex/test/subscription.test.js +70 -0
  89. package/dist/internal-providers/provider-codex/test/translated-content.test.d.ts +1 -0
  90. package/dist/internal-providers/provider-codex/test/translated-content.test.js +91 -0
  91. package/dist/internal-providers/provider-custom/index.d.ts +9 -0
  92. package/dist/internal-providers/provider-custom/index.js +15 -0
  93. package/dist/internal-providers/provider-google/index.d.ts +23 -0
  94. package/dist/internal-providers/provider-google/index.js +43 -0
  95. package/dist/internal-providers/provider-google/test/provider.test.d.ts +1 -0
  96. package/dist/internal-providers/provider-google/test/provider.test.js +34 -0
  97. package/dist/internal-providers/provider-google-vertex/index.d.ts +28 -0
  98. package/dist/internal-providers/provider-google-vertex/index.js +137 -0
  99. package/dist/internal-providers/provider-google-vertex/test/provider.test.d.ts +1 -0
  100. package/dist/internal-providers/provider-google-vertex/test/provider.test.js +85 -0
  101. package/dist/internal-providers/provider-openai/documented-reasoning.d.ts +9 -0
  102. package/dist/internal-providers/provider-openai/documented-reasoning.js +26 -0
  103. package/dist/internal-providers/provider-openai/index.d.ts +23 -0
  104. package/dist/internal-providers/provider-openai/index.js +74 -0
  105. package/dist/internal-providers/provider-openai/test/provider.test.d.ts +1 -0
  106. package/dist/internal-providers/provider-openai/test/provider.test.js +268 -0
  107. package/dist/internal-providers/provider-openai-compatible/index.d.ts +9 -0
  108. package/dist/internal-providers/provider-openai-compatible/index.js +15 -0
  109. package/dist/internal-providers/provider-openai-compatible/test/provider.test.d.ts +1 -0
  110. package/dist/internal-providers/provider-openai-compatible/test/provider.test.js +40 -0
  111. package/dist/internal-providers/provider-openrouter/connection.d.ts +5 -0
  112. package/dist/internal-providers/provider-openrouter/connection.js +143 -0
  113. package/dist/internal-providers/provider-openrouter/index.d.ts +28 -0
  114. package/dist/internal-providers/provider-openrouter/index.js +42 -0
  115. package/dist/internal-providers/provider-openrouter/pricing.d.ts +4 -0
  116. package/dist/internal-providers/provider-openrouter/pricing.js +108 -0
  117. package/dist/internal-providers/provider-openrouter/test/connection.test.d.ts +1 -0
  118. package/dist/internal-providers/provider-openrouter/test/connection.test.js +71 -0
  119. package/dist/internal-providers/provider-openrouter/test/pricing.test.d.ts +1 -0
  120. package/dist/internal-providers/provider-openrouter/test/pricing.test.js +45 -0
  121. package/dist/internal-providers/provider-openrouter/test/provider.test.d.ts +1 -0
  122. package/dist/internal-providers/provider-openrouter/test/provider.test.js +141 -0
  123. package/dist/internal-providers/provider-openrouter/test/validation.test.d.ts +1 -0
  124. package/dist/internal-providers/provider-openrouter/test/validation.test.js +225 -0
  125. package/dist/launcher-service.d.ts +3 -7
  126. package/dist/launcher-service.js +144 -133
  127. package/dist/provider-modules.d.ts +6 -0
  128. package/dist/provider-modules.js +55 -0
  129. package/dist/provider-query-service.d.ts +1 -3
  130. package/dist/provider-query-service.js +140 -143
  131. package/dist/router-generation-service.d.ts +1 -3
  132. package/dist/router-generation-service.js +83 -78
  133. package/dist/services/eval-session/service.d.ts +20 -8
  134. package/dist/services/eval-session/service.js +410 -40
  135. package/dist/services/gateway-generation/service.d.ts +7 -3
  136. package/dist/services/gateway-generation/service.js +126 -63
  137. package/dist/services/generations/service.d.ts +3 -3
  138. package/dist/services/generations/service.js +5 -1
  139. package/dist/telemetry-application-service.d.ts +1 -3
  140. package/dist/telemetry-application-service.js +41 -45
  141. package/dist/test/call-attribution-store.test.js +186 -0
  142. package/dist/test/daemon-accounts.test.js +2 -2
  143. package/dist/test/daemon-data-plane.test.js +24 -45
  144. package/dist/test/daemon-fixtures.js +1 -1
  145. package/dist/test/daemon-generation-transaction.test.js +66 -2
  146. package/dist/test/daemon-runtime-state.test.js +28 -1
  147. package/dist/test/effect-daemon.test.js +38 -0
  148. package/dist/test/eval-routing-application-service.test.js +6 -6
  149. package/dist/test/eval-session-execution.test.d.ts +1 -0
  150. package/dist/test/eval-session-execution.test.js +356 -0
  151. package/dist/test/eval-session-service.test.js +70 -1
  152. package/dist/test/host-worker-session.test.js +1 -0
  153. package/dist/test/launcher-session.test.d.ts +1 -0
  154. package/dist/test/launcher-session.test.js +87 -0
  155. package/dist/test/leaderboard.test.js +25 -1
  156. package/dist/test/provider-modules.test.d.ts +1 -0
  157. package/dist/test/provider-modules.test.js +65 -0
  158. package/dist/test/routekit-upstream-sources.test.d.ts +1 -0
  159. package/dist/test/routekit-upstream-sources.test.js +40 -0
  160. package/dist/test/runtime-composition-types.test.js +11 -0
  161. package/dist/token-application-service.d.ts +1 -3
  162. package/dist/token-application-service.js +38 -44
  163. package/dist/worker.js +5 -3
  164. package/package.json +35 -11
  165. package/dist/application-services.d.ts +0 -10
  166. package/dist/application-services.js +0 -22
  167. package/dist/daemon-lifecycle.d.ts +0 -54
  168. package/dist/daemon-lifecycle.js +0 -177
  169. package/dist/test/application-services.test.js +0 -135
  170. package/dist/test/daemon-lifecycle.test.js +0 -182
  171. /package/dist/{test/application-services.test.d.ts → internal-providers/provider-anthropic/test/provider.test.d.ts} +0 -0
  172. /package/dist/{test/daemon-lifecycle.test.d.ts → internal-providers/provider-azure/test/provider.test.d.ts} +0 -0
@@ -0,0 +1,40 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+ import { parseRouterConfig } from "@velum-labs/routekit-config";
4
+ import { routeKitUpstreamSources } from "../services/gateway-generation/service.js";
5
+ test("RouteKit upstream wraps only the explicitly delegated snapshot providers", () => {
6
+ const config = parseRouterConfig({
7
+ providers: { openai: {}, anthropic: {} },
8
+ defaultModel: "openai/test-model"
9
+ });
10
+ const sources = routeKitUpstreamSources(config, {
11
+ ROUTEKIT_UPSTREAM_GATEWAY_URL: "https://gateway.example",
12
+ ROUTEKIT_UPSTREAM_GATEWAY_TOKEN: "gateway-token",
13
+ ROUTEKIT_UPSTREAM_PROVIDER_IDS: "openai"
14
+ });
15
+ assert.deepEqual(Object.keys(sources), ["openai"]);
16
+ assert.equal(sources.openai?.sourceId, "openai");
17
+ assert.equal(sources.anthropic, undefined);
18
+ });
19
+ test("RouteKit upstream ignores delegated providers absent from the current local config", () => {
20
+ const config = parseRouterConfig({
21
+ providers: { anthropic: {} },
22
+ defaultModel: "anthropic/test-model"
23
+ });
24
+ const sources = routeKitUpstreamSources(config, {
25
+ ROUTEKIT_UPSTREAM_GATEWAY_URL: "https://gateway.example",
26
+ ROUTEKIT_UPSTREAM_GATEWAY_TOKEN: "gateway-token",
27
+ ROUTEKIT_UPSTREAM_PROVIDER_IDS: "openai"
28
+ });
29
+ assert.deepEqual(sources, {});
30
+ });
31
+ test("RouteKit upstream fails closed without an explicit delegated provider set", () => {
32
+ const config = parseRouterConfig({
33
+ providers: { openai: {} },
34
+ defaultModel: "openai/test-model"
35
+ });
36
+ assert.throws(() => routeKitUpstreamSources(config, {
37
+ ROUTEKIT_UPSTREAM_GATEWAY_URL: "https://gateway.example",
38
+ ROUTEKIT_UPSTREAM_GATEWAY_TOKEN: "gateway-token"
39
+ }), /ROUTEKIT_UPSTREAM_PROVIDER_IDS is required/u);
40
+ });
@@ -2,6 +2,17 @@ import test from "node:test";
2
2
  import { daemonLive } from "../effect/daemon-live.js";
3
3
  test("daemon runtime composition rejects prebuilt coordinator bags at compile time", () => {
4
4
  if (false) {
5
+ const layer = daemonLive({
6
+ packageVersion: "0.0.0"
7
+ });
8
+ void layer;
9
+ const dataPlane = undefined;
10
+ const policy = undefined;
11
+ void dataPlane;
12
+ void policy;
13
+ // @ts-expect-error launcher credentials are private, not part of the published DaemonLive API.
14
+ const launcher = undefined;
15
+ void launcher;
5
16
  // @ts-expect-error daemonLive constructs TokenStore; callers cannot inject one.
6
17
  daemonLive({ packageVersion: "0.0.0", tokenStore: {} });
7
18
  // @ts-expect-error daemonLive constructs/acquires the sidecar adapter.
@@ -1,7 +1,5 @@
1
1
  import type { EffectRouteKitControlHandlers } from "@velum-labs/routekit-control/effect";
2
2
  type TokenHandlers = Pick<EffectRouteKitControlHandlers, "tokens.issue" | "tokens.list" | "tokens.revoke">;
3
3
  /** Binds token use cases to the control protocol. */
4
- export declare class TokenApplicationService {
5
- handlers(): TokenHandlers;
6
- }
4
+ export declare const tokenHandlers: TokenHandlers;
7
5
  export {};
@@ -7,53 +7,47 @@ import { Tokens } from "./services/tokens/service.js";
7
7
  const tokenFailure = (error, operation) => {
8
8
  const message = error instanceof Error ? error.message : String(error);
9
9
  return new ControlError({
10
- code: operation === "revoke" && message.startsWith("unknown token")
11
- ? "not_found"
12
- : "bad_request",
10
+ code: operation === "revoke" && message.startsWith("unknown token") ? "not_found" : "bad_request",
13
11
  message
14
12
  });
15
13
  };
16
14
  /** Binds token use cases to the control protocol. */
17
- export class TokenApplicationService {
18
- handlers() {
15
+ export const tokenHandlers = {
16
+ "tokens.issue": (params, context) => Effect.gen(function* () {
17
+ const env = yield* DaemonEnv;
18
+ const tokens = yield* Tokens;
19
+ const issued = yield* tokens
20
+ .issue({
21
+ label: params.label,
22
+ plane: params.plane,
23
+ role: "admin",
24
+ createdBy: params.createdBy ?? context.principal?.label ?? "control"
25
+ })
26
+ .pipe(Effect.mapError((error) => tokenFailure(error, "issue")));
19
27
  return {
20
- "tokens.issue": (params, context) => Effect.gen(function* () {
21
- const env = yield* DaemonEnv;
22
- const tokens = yield* Tokens;
23
- const issued = yield* tokens
24
- .issue({
25
- label: params.label,
26
- plane: params.plane,
27
- role: "admin",
28
- createdBy: params.createdBy ?? context.principal?.label ?? "control"
29
- })
30
- .pipe(Effect.mapError((error) => tokenFailure(error, "issue")));
31
- return {
32
- id: issued.id,
33
- label: issued.label,
34
- plane: issued.plane,
35
- role: issued.role,
36
- token: issued.token,
37
- ...(issued.plane === "control"
38
- ? {
39
- joinCredential: encodeJoinCredential({
40
- publicRecordPath: daemonPublicRecordPath(env.home),
41
- token: issued.token
42
- })
43
- }
44
- : {})
45
- };
46
- }),
47
- "tokens.list": (params) => Effect.gen(function* () {
48
- const tokens = yield* Tokens;
49
- return { tokens: yield* tokens.list(params.plane) };
50
- }),
51
- "tokens.revoke": (params) => Effect.gen(function* () {
52
- const tokens = yield* Tokens;
53
- return yield* tokens
54
- .revoke(params.id)
55
- .pipe(Effect.mapError((error) => tokenFailure(error, "revoke")));
56
- })
28
+ id: issued.id,
29
+ label: issued.label,
30
+ plane: issued.plane,
31
+ role: issued.role,
32
+ token: issued.token,
33
+ ...(issued.plane === "control"
34
+ ? {
35
+ joinCredential: encodeJoinCredential({
36
+ publicRecordPath: daemonPublicRecordPath(env.home),
37
+ token: issued.token
38
+ })
39
+ }
40
+ : {})
57
41
  };
58
- }
59
- }
42
+ }),
43
+ "tokens.list": (params) => Effect.gen(function* () {
44
+ const tokens = yield* Tokens;
45
+ return { tokens: yield* tokens.list(params.plane) };
46
+ }),
47
+ "tokens.revoke": (params) => Effect.gen(function* () {
48
+ const tokens = yield* Tokens;
49
+ return yield* tokens
50
+ .revoke(params.id)
51
+ .pipe(Effect.mapError((error) => tokenFailure(error, "revoke")));
52
+ })
53
+ };
package/dist/worker.js CHANGED
@@ -107,7 +107,9 @@ export async function runRouteKitDaemonWorker(options) {
107
107
  const ipc = WorkerIpc.layer((message) => hostRequests.accept(message));
108
108
  const application = Layer.unwrap(Effect.map(WorkerIpc, () => daemonLive(daemonOptions))).pipe(Layer.provideMerge(ipc));
109
109
  const runtime = ManagedRuntime.make(application);
110
- const runWorker = (daemon, workerIpc) => Effect.scoped(Effect.gen(function* () {
110
+ const runWorker = Effect.scoped(Effect.gen(function* () {
111
+ const daemon = yield* DaemonRuntime;
112
+ const workerIpc = yield* WorkerIpc;
111
113
  const snapshot = yield* daemon.snapshot;
112
114
  send({
113
115
  type: "worker.ready",
@@ -118,6 +120,7 @@ export async function runRouteKitDaemonWorker(options) {
118
120
  : { workerProcessIdentity: daemon.record.processIdentity }),
119
121
  workerStartedAt: daemon.record.startedAt,
120
122
  packageVersion: options.packageVersion,
123
+ ...(options.sourceBuildId === undefined ? {} : { sourceBuildId: options.sourceBuildId }),
121
124
  generation,
122
125
  configRevision: snapshot.configRevision,
123
126
  accountRevision: snapshot.accountRevision,
@@ -181,8 +184,7 @@ export async function runRouteKitDaemonWorker(options) {
181
184
  }));
182
185
  let exitCode = 0;
183
186
  try {
184
- const [daemon, workerIpc] = await runtime.runPromise(Effect.all([DaemonRuntime, WorkerIpc]));
185
- await runtime.runPromise(runWorker(daemon, workerIpc));
187
+ await runtime.runPromise(runWorker);
186
188
  }
187
189
  catch (error) {
188
190
  exitCode = 1;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@velum-labs/routekit-daemon",
3
3
  "private": false,
4
- "version": "1.3.2",
4
+ "version": "1.5.0",
5
5
  "description": "Singleton RouteKit control daemon and stable model gateway.",
6
6
  "repository": {
7
7
  "type": "git",
@@ -41,21 +41,45 @@
41
41
  "service"
42
42
  ],
43
43
  "dependencies": {
44
+ "@aws-sdk/credential-providers": "3.1095.0",
45
+ "@openrouter/sdk": "1.2.106",
46
+ "oauth4webapi": "3.8.7",
44
47
  "effect": "4.0.0-rc.108",
45
48
  "posthog-node": "5.46.1",
46
49
  "yaml": "2.9.0",
47
- "@velum-labs/routekit-accounts": "1.3.2",
48
- "@velum-labs/routekit-config": "1.3.2",
49
- "@velum-labs/routekit-control": "1.3.2",
50
- "@velum-labs/routekit-eval-contracts": "1.3.2",
51
- "@velum-labs/routekit-eval-store": "1.3.2",
52
- "@velum-labs/routekit-gateway": "1.3.2",
53
- "@velum-labs/routekit-registry": "1.3.2",
54
- "@velum-labs/routekit-runtime": "1.3.2",
55
- "@velum-labs/routekit-telemetry-core": "1.3.2"
50
+ "@aws-sdk/client-bedrock": "3.1095.0",
51
+ "@aws-sdk/client-bedrock-runtime": "3.1095.0",
52
+ "google-auth-library": "11.0.2",
53
+ "zod": "4.4.3",
54
+ "@velum-labs/routekit-accounts": "1.5.0",
55
+ "@velum-labs/routekit-config": "1.5.0",
56
+ "@velum-labs/routekit-control": "1.5.0",
57
+ "@velum-labs/routekit-contracts": "1.5.0",
58
+ "@velum-labs/routekit-eval-contracts": "1.5.0",
59
+ "@velum-labs/routekit-eval-store": "1.5.0",
60
+ "@velum-labs/routekit-gateway": "1.5.0",
61
+ "@velum-labs/routekit-provider-core": "1.5.0",
62
+ "@velum-labs/routekit-registry": "1.5.0",
63
+ "@velum-labs/routekit-runtime": "1.5.0",
64
+ "@velum-labs/routekit-telemetry-core": "1.5.0"
65
+ },
66
+ "devDependencies": {
67
+ "@velum-labs/routekit-provider-anthropic": "1.5.0",
68
+ "@velum-labs/routekit-provider-azure": "1.5.0",
69
+ "@velum-labs/routekit-provider-bedrock": "1.5.0",
70
+ "@velum-labs/routekit-provider-claude-code": "1.5.0",
71
+ "@velum-labs/routekit-provider-cliproxy": "1.5.0",
72
+ "@velum-labs/routekit-provider-codex": "1.5.0",
73
+ "@velum-labs/routekit-provider-custom": "1.5.0",
74
+ "@velum-labs/routekit-provider-fake-openai": "1.5.0",
75
+ "@velum-labs/routekit-provider-google": "1.5.0",
76
+ "@velum-labs/routekit-provider-google-vertex": "1.5.0",
77
+ "@velum-labs/routekit-provider-openai": "1.5.0",
78
+ "@velum-labs/routekit-provider-openai-compatible": "1.5.0",
79
+ "@velum-labs/routekit-provider-openrouter": "1.5.0"
56
80
  },
57
81
  "scripts": {
58
- "build": "tsc -b",
82
+ "build": "node --input-type=module -e \"import { rmSync } from 'node:fs'; for (const path of ['dist', 'tsconfig.tsbuildinfo']) rmSync(path, { recursive: true, force: true })\" && tsc -b && node ../../scripts/embed-private-provider-packages.mjs daemon provider-anthropic provider-azure provider-bedrock provider-claude-code provider-cliproxy provider-codex provider-custom provider-google provider-google-vertex provider-openai provider-openai-compatible provider-openrouter",
59
83
  "test": "node --test \"dist/test/*.test.js\""
60
84
  }
61
85
  }
@@ -1,10 +0,0 @@
1
- import type { RouteKitControlHandlers } from "@velum-labs/routekit-control";
2
- import { ControlMethodRegistry } from "@velum-labs/routekit-control";
3
- /**
4
- * Builds the daemon's control registry straight from the protocol method table.
5
- *
6
- * Authorization, mutation classification, and idempotency policy are protocol
7
- * facts, not daemon opinions, so the daemon binds handlers and inherits the
8
- * rest. A method added to the table is registered here with no edit.
9
- */
10
- export declare function createDaemonControlMethodRegistry(handlers: RouteKitControlHandlers): ControlMethodRegistry;
@@ -1,22 +0,0 @@
1
- import { ControlMethodRegistry, controlAuthorization, controlIdempotency, controlMutation, ROUTEKIT_CONTROL_METHODS, routeKitControlSchemas } from "@velum-labs/routekit-control";
2
- /**
3
- * Builds the daemon's control registry straight from the protocol method table.
4
- *
5
- * Authorization, mutation classification, and idempotency policy are protocol
6
- * facts, not daemon opinions, so the daemon binds handlers and inherits the
7
- * rest. A method added to the table is registered here with no edit.
8
- */
9
- export function createDaemonControlMethodRegistry(handlers) {
10
- const registry = new ControlMethodRegistry();
11
- for (const method of ROUTEKIT_CONTROL_METHODS) {
12
- registry.register({
13
- method,
14
- ...routeKitControlSchemas(method),
15
- authorization: controlAuthorization(method),
16
- mutation: controlMutation(method),
17
- idempotency: controlIdempotency(method),
18
- handler: handlers[method]
19
- });
20
- }
21
- return registry;
22
- }
@@ -1,54 +0,0 @@
1
- import type { AccountActivityService, AccountAuthService } from "@velum-labs/routekit-accounts/effect";
2
- import type { RouteKitControlHandlers } from "@velum-labs/routekit-control";
3
- import type { SwitchingGatewayProxy } from "@velum-labs/routekit-gateway";
4
- import type { RunningControlServer } from "@velum-labs/routekit-runtime/control";
5
- import { type RouteKitPlatform } from "@velum-labs/routekit-runtime/effect";
6
- import { Effect, type ManagedRuntime } from "effect";
7
- import type { DaemonRuntimeState } from "./daemon-runtime-state.js";
8
- import type { RunningGatewayGeneration } from "./services/gateway-generation/service.js";
9
- import type { DaemonTelemetry, GatewayTelemetryAggregator } from "./telemetry.js";
10
- type Supervisor = "systemd" | "launchd" | "detached" | "unknown";
11
- export type DaemonLifecycleOptions = {
12
- runtimeState: DaemonRuntimeState;
13
- handlers: RouteKitControlHandlers;
14
- drainGraceMs: number;
15
- packageVersion: string;
16
- supervisor: Supervisor;
17
- getProxy(): SwitchingGatewayProxy | undefined;
18
- getActiveRouter(): RunningGatewayGeneration | undefined;
19
- getControl(): RunningControlServer | undefined;
20
- accountActivity?: AccountActivityService;
21
- accountAuth?: AccountAuthService;
22
- daemonTelemetry?: DaemonTelemetry;
23
- gatewayTelemetry?: GatewayTelemetryAggregator;
24
- closeSidecar(): Effect.Effect<void, Error>;
25
- cleanupRegistration(): void;
26
- /** Disposed last so in-flight Effect work can finish during teardown. */
27
- effectRuntime?: ManagedRuntime.ManagedRuntime<any, never>;
28
- };
29
- export declare function captureDaemonStarted(input: {
30
- daemonTelemetry?: DaemonTelemetry;
31
- packageVersion: string;
32
- supervisor: Supervisor;
33
- }): void;
34
- export declare function createDaemonLifecycle(options: DaemonLifecycleOptions): {
35
- close(): Effect.Effect<void, Error, RouteKitPlatform>;
36
- retire(graceMs?: number): Effect.Effect<void, Error, RouteKitPlatform>;
37
- pauseMutations(): Effect.Effect<ReturnType<DaemonRuntimeState["snapshot"]>, Error>;
38
- resumeMutations(): void;
39
- snapshot(): ReturnType<DaemonRuntimeState["snapshot"]>;
40
- reload(): Effect.Effect<void, Error>;
41
- };
42
- export declare function cleanupFailedDaemon(input: {
43
- gatewayTelemetry?: GatewayTelemetryAggregator;
44
- daemonTelemetry?: DaemonTelemetry;
45
- proxy?: SwitchingGatewayProxy;
46
- activeRouter?: RunningGatewayGeneration;
47
- accountActivity?: AccountActivityService;
48
- accountAuth?: AccountAuthService;
49
- closeSidecar(): Effect.Effect<void, Error>;
50
- control?: RunningControlServer;
51
- cleanupRegistration(): void;
52
- effectRuntime?: ManagedRuntime.ManagedRuntime<any, never>;
53
- }): Effect.Effect<void, Error, RouteKitPlatform>;
54
- export {};
@@ -1,177 +0,0 @@
1
- import { extendCleanupGrace, registerCleanup } from "@velum-labs/routekit-runtime/lifecycle";
2
- import { ResourceDisposalTimeoutError } from "@velum-labs/routekit-runtime/lifecycle";
3
- import { routeKitError, runRouteKitEffect, toRouteKitFailure } from "@velum-labs/routekit-runtime/effect";
4
- import { Cause, Deferred, Effect, Exit, Scope } from "effect";
5
- export function captureDaemonStarted(input) {
6
- input.daemonTelemetry?.capture("routekit.daemon_lifecycle", {
7
- action: "started",
8
- outcome: "success",
9
- supervisor: input.supervisor,
10
- version: input.packageVersion
11
- });
12
- }
13
- function callbackFinalizer(run) {
14
- return Effect.tryPromise({
15
- try: async () => {
16
- await run();
17
- },
18
- catch: toRouteKitFailure
19
- });
20
- }
21
- function closeDaemonResources(finalizers, shutdownBudgetMs) {
22
- return Effect.gen(function* () {
23
- const platform = yield* Effect.context();
24
- const scope = yield* Scope.make("sequential");
25
- const errors = [];
26
- const deadline = shutdownBudgetMs === undefined ? undefined : Date.now() + shutdownBudgetMs;
27
- for (const finalizer of finalizers) {
28
- yield* Scope.addFinalizer(scope, Effect.suspend(() => {
29
- const remaining = deadline === undefined ? undefined : Math.max(0, deadline - Date.now());
30
- const bounded = remaining === undefined
31
- ? finalizer
32
- : finalizer.pipe(Effect.timeoutOrElse({
33
- duration: remaining,
34
- orElse: () => Effect.fail(new ResourceDisposalTimeoutError(shutdownBudgetMs))
35
- }));
36
- return Effect.exit(bounded.pipe(Effect.provide(platform))).pipe(Effect.flatMap((closed) => Exit.isFailure(closed)
37
- ? Effect.sync(() => {
38
- errors.push(Cause.squash(closed.cause));
39
- })
40
- : Effect.void));
41
- }));
42
- }
43
- yield* Scope.close(scope, Exit.void);
44
- if (errors.length > 0) {
45
- return yield* Effect.fail(new AggregateError(errors, "one or more daemon resource finalizers failed"));
46
- }
47
- });
48
- }
49
- export function createDaemonLifecycle(options) {
50
- const shutdownResources = (mode, graceMs) => {
51
- const finalizers = [
52
- // Native Scope finalizers run in LIFO order. Register the Effect runtime
53
- // first so it disposes last, after every Effect-owned resource.
54
- callbackFinalizer(async () => await options.effectRuntime?.dispose()),
55
- callbackFinalizer(() => options.cleanupRegistration()),
56
- callbackFinalizer(() => options.gatewayTelemetry?.close()),
57
- callbackFinalizer(async () => await options.daemonTelemetry?.shutdown()),
58
- options.closeSidecar()
59
- ];
60
- if (options.accountAuth !== undefined) {
61
- finalizers.push(options.accountAuth.close);
62
- }
63
- if (options.accountActivity !== undefined) {
64
- finalizers.push(options.accountActivity.close);
65
- }
66
- const activeRouter = options.getActiveRouter();
67
- if (activeRouter !== undefined)
68
- finalizers.push(activeRouter.close);
69
- const proxy = options.getProxy();
70
- if (proxy !== undefined) {
71
- finalizers.push(mode === "retire" ? proxy.retire(graceMs) : proxy.drain(graceMs));
72
- }
73
- const control = options.getControl();
74
- if (control !== undefined) {
75
- finalizers.push(mode === "retire" ? control.retire(Math.min(graceMs, 2_000)) : control.close);
76
- }
77
- return closeDaemonResources(finalizers, graceMs + 10_000);
78
- };
79
- let removeSighupListener = () => { };
80
- let shutdownLatch;
81
- let shutdownOwner;
82
- const shutdown = (mode, graceMs) => {
83
- if (shutdownOwner !== undefined)
84
- return Deferred.await(shutdownLatch);
85
- shutdownLatch = Deferred.makeUnsafe();
86
- shutdownOwner = Effect.gen(function* () {
87
- if (mode === "close")
88
- options.runtimeState.beginShutdown();
89
- else
90
- options.runtimeState.beginRetire();
91
- yield* options.runtimeState.awaitMutations();
92
- if (mode === "close") {
93
- yield* Effect.sync(() => {
94
- try {
95
- options.daemonTelemetry?.capture("routekit.daemon_lifecycle", {
96
- action: "stopped",
97
- outcome: "success",
98
- supervisor: options.supervisor,
99
- version: options.packageVersion
100
- });
101
- }
102
- catch (error) {
103
- process.stderr.write(`routekit daemon stop telemetry failed: ${error instanceof Error ? error.message : String(error)}\n`);
104
- }
105
- });
106
- }
107
- options.runtimeState.markDraining();
108
- yield* shutdownResources(mode, graceMs).pipe(Effect.mapError((cause) => routeKitError(cause)));
109
- }).pipe(Effect.ensuring(Effect.sync(() => {
110
- removeSighupListener();
111
- options.runtimeState.markClosed();
112
- })), Effect.matchEffect({
113
- onFailure: (error) => Deferred.fail(shutdownLatch, error).pipe(Effect.andThen(Effect.fail(error))),
114
- onSuccess: () => Deferred.succeed(shutdownLatch, undefined)
115
- }));
116
- return shutdownOwner;
117
- };
118
- const close = () => shutdown("close", options.drainGraceMs);
119
- extendCleanupGrace(options.drainGraceMs + 10_000);
120
- registerCleanup(() => runRouteKitEffect(close()).catch(() => undefined));
121
- const onSighup = () => {
122
- void runRouteKitEffect(reload(options.handlers, "sighup")).catch((error) => {
123
- process.stderr.write(`routekit daemon reload failed: ${error instanceof Error ? error.message : String(error)}\n`);
124
- });
125
- };
126
- process.on("SIGHUP", onSighup);
127
- removeSighupListener = () => process.off("SIGHUP", onSighup);
128
- return {
129
- close,
130
- retire: (graceMs = options.drainGraceMs) => shutdown("retire", graceMs),
131
- pauseMutations: () => Effect.gen(function* () {
132
- yield* Effect.try({
133
- try: () => {
134
- options.runtimeState.pause();
135
- },
136
- catch: toRouteKitFailure
137
- });
138
- yield* options.runtimeState.awaitMutations();
139
- return options.runtimeState.snapshot();
140
- }),
141
- resumeMutations: () => {
142
- options.runtimeState.resume();
143
- },
144
- snapshot: () => options.runtimeState.snapshot(),
145
- reload: () => reload(options.handlers, "direct")
146
- };
147
- }
148
- export function cleanupFailedDaemon(input) {
149
- const finalizers = [
150
- callbackFinalizer(async () => await input.effectRuntime?.dispose()),
151
- callbackFinalizer(() => input.cleanupRegistration())
152
- ];
153
- if (input.control !== undefined)
154
- finalizers.push(input.control.close);
155
- finalizers.push(input.closeSidecar());
156
- if (input.accountAuth !== undefined) {
157
- finalizers.push(input.accountAuth.close);
158
- }
159
- if (input.accountActivity !== undefined) {
160
- finalizers.push(input.accountActivity.close);
161
- }
162
- if (input.activeRouter !== undefined)
163
- finalizers.push(input.activeRouter.close);
164
- if (input.proxy !== undefined)
165
- finalizers.push(input.proxy.close);
166
- finalizers.push(callbackFinalizer(async () => await input.daemonTelemetry?.shutdown()), callbackFinalizer(() => input.gatewayTelemetry?.close()));
167
- return closeDaemonResources(finalizers);
168
- }
169
- function reload(handlers, requestId) {
170
- return Effect.tryPromise({
171
- try: () => Promise.resolve(handlers["daemon.reload"]({}, {
172
- signal: new AbortController().signal,
173
- requestId
174
- })).then(() => undefined),
175
- catch: toRouteKitFailure
176
- });
177
- }
@@ -1,135 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import test from "node:test";
3
- import { ROUTEKIT_CONTROL_METHODS } from "@velum-labs/routekit-control";
4
- import { createDaemonControlMethodRegistry } from "../application-services.js";
5
- import { AccountEnrollService } from "../account-enroll-service.js";
6
- import { AccountMutationService } from "../account-mutation-service.js";
7
- import { AccountQueryService } from "../account-query-service.js";
8
- import { DaemonLifecycleService } from "../daemon-lifecycle-service.js";
9
- import { DoctorApplicationService } from "../doctor-service.js";
10
- import { EvalRoutingApplicationService } from "../eval-routing-service.js";
11
- import { EvalSessionApplicationService } from "../services/eval-session/service.js";
12
- import { LauncherSessionManager } from "../services/launcher-session/service.js";
13
- import { LauncherApplicationService } from "../launcher-service.js";
14
- import { ProviderQueryService } from "../provider-query-service.js";
15
- import { RouterGenerationService } from "../router-generation-service.js";
16
- import { TelemetryApplicationService } from "../telemetry-application-service.js";
17
- import { TokenApplicationService } from "../token-application-service.js";
18
- const handlers = new Proxy({}, {
19
- get: (_target, method) => async () => String(method)
20
- });
21
- test("daemon application services register disjoint owned method groups", () => {
22
- const registry = createDaemonControlMethodRegistry(handlers);
23
- const definitions = registry.list();
24
- const methods = definitions.map(({ method }) => method);
25
- assert.equal(new Set(methods).size, methods.length);
26
- assert.equal(methods.length, ROUTEKIT_CONTROL_METHODS.length);
27
- const enroll = registry.definition("accounts.enroll");
28
- assert.deepEqual({
29
- method: enroll.method,
30
- paramsSchema: enroll.paramsSchema.name,
31
- resultSchema: enroll.resultSchema.name,
32
- authorization: enroll.authorization,
33
- mutation: enroll.mutation,
34
- idempotency: enroll.idempotency
35
- }, {
36
- method: "accounts.enroll",
37
- paramsSchema: "accounts.enroll.params",
38
- resultSchema: "accounts.enroll.result",
39
- authorization: "authenticated",
40
- mutation: "mutation",
41
- idempotency: "optional"
42
- });
43
- assert.equal(registry.definition("models.list").mutation, "query");
44
- assert.equal(registry.definition("daemon.reload").mutation, "mutation");
45
- assert.equal(registry.definition("daemon.roll").authorization, "ephemeral");
46
- });
47
- test("application services expose concrete bounded handler groups", () => {
48
- const accountQuery = new AccountQueryService().handlers();
49
- const accountEnroll = new AccountEnrollService().handlers();
50
- const accountMutation = new AccountMutationService().handlers();
51
- const provider = new ProviderQueryService().handlers();
52
- const router = new RouterGenerationService().handlers();
53
- assert.deepEqual(Object.keys(accountQuery).sort(), [
54
- "accounts.list",
55
- "accounts.status",
56
- "accounts.usage"
57
- ]);
58
- assert.deepEqual(Object.keys(accountEnroll).sort(), [
59
- "accounts.enroll",
60
- "accounts.enrollActivate"
61
- ]);
62
- assert.deepEqual(Object.keys(accountMutation).sort(), [
63
- "accounts.redeemReset",
64
- "accounts.remove",
65
- "accounts.rename",
66
- "accounts.resetCredits",
67
- "accounts.sync"
68
- ]);
69
- assert.deepEqual(Object.keys(provider).sort(), [
70
- "calls.inspect",
71
- "calls.leaderboard",
72
- "models.info",
73
- "models.list",
74
- "providers.status"
75
- ]);
76
- assert.deepEqual(Object.keys(router).sort(), [
77
- "config.get",
78
- "config.import",
79
- "config.update",
80
- "daemon.reload",
81
- "providers.set"
82
- ]);
83
- assert.deepEqual(Object.keys(new DaemonLifecycleService().handlers()).sort(), [
84
- "daemon.prepareShutdown",
85
- "daemon.roll",
86
- "daemon.status"
87
- ]);
88
- assert.deepEqual(Object.keys(new DoctorApplicationService().handlers()), ["doctor.run"]);
89
- assert.deepEqual(Object.keys(new LauncherApplicationService({ listModels: (() => undefined) }).handlers()), ["launcher.prepare"]);
90
- assert.deepEqual(Object.keys(new TokenApplicationService().handlers()).sort(), [
91
- "tokens.issue",
92
- "tokens.list",
93
- "tokens.revoke"
94
- ]);
95
- assert.deepEqual(Object.keys(new EvalSessionApplicationService().handlers()).sort(), [
96
- "evalSession.close",
97
- "evalSession.open"
98
- ]);
99
- assert.deepEqual(Object.keys(new EvalRoutingApplicationService().handlers()).sort(), [
100
- "evalRouting.activate",
101
- "evalRouting.installAuthoritative",
102
- "evalRouting.rollbackAuthoritative",
103
- "evalRouting.status"
104
- ]);
105
- assert.deepEqual(Object.keys(new TelemetryApplicationService().handlers()).sort(), [
106
- "telemetry.captureCommand",
107
- "telemetry.get",
108
- "telemetry.resetIdentity",
109
- "telemetry.schema",
110
- "telemetry.set"
111
- ]);
112
- });
113
- test("launcher sessions bind repository profile context without durable token state", () => {
114
- let byte = 0;
115
- const sessions = new LauncherSessionManager({
116
- random: (length) => Buffer.alloc(length, byte++)
117
- });
118
- const token = sessions.open({
119
- repositoryRoot: "/workspace/repository",
120
- profileName: "quality",
121
- role: "owner"
122
- });
123
- assert.deepEqual(sessions.resolve(token), {
124
- id: `launcher_${Buffer.alloc(16, 1).toString("base64url")}`,
125
- label: "launcher:quality",
126
- role: "owner",
127
- routing: {
128
- repositoryRoot: "/workspace/repository",
129
- profileName: "quality"
130
- }
131
- });
132
- assert.equal(sessions.resolve("wrong"), undefined);
133
- sessions.closeAll();
134
- assert.equal(sessions.resolve(token), undefined);
135
- });