@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
@@ -1,41 +1,39 @@
1
1
  import { join } from "node:path";
2
- import { CLIPROXY_API_KEY_ENV, CLIPROXY_BASE_URL_ENV, cliproxyApiKey, cliproxyBaseUrl, subscriptionAccountIdentity, subscriptionCredentialFingerprint } from "@velum-labs/routekit-accounts";
3
2
  import { AccountActivity, AccountAuth } from "@velum-labs/routekit-accounts/effect";
4
3
  import { resolveLeaderboardConfig } from "@velum-labs/routekit-config";
5
4
  import { ROUTEKIT_CONTROL_CAPABILITY, ROUTEKIT_DAEMON_ROLL_CAPABILITY } from "@velum-labs/routekit-control";
5
+ import { toPromiseControlHandlers } from "@velum-labs/routekit-control/effect";
6
6
  import { createWorkloadJwtVerifier } from "@velum-labs/routekit-gateway";
7
7
  import { startSwitchingGatewayProxyEffect } from "@velum-labs/routekit-gateway/effect";
8
8
  import { CONTROL_PROTOCOL_VERSION, ControlError, generateControlToken } from "@velum-labs/routekit-runtime/control";
9
- import { RouteKitLive, startControlServerEffect, toRouteKitFailure, withAbortSignal } from "@velum-labs/routekit-runtime/effect";
9
+ import { RouteKitLive, startControlServerEffect, toRouteKitFailure } from "@velum-labs/routekit-runtime/effect";
10
10
  import { createPortlessSession } from "@velum-labs/routekit-runtime/network";
11
11
  import { nextServiceGeneration, processIdentity, supervisorFromEnv } from "@velum-labs/routekit-runtime/service";
12
12
  import { Context, Effect, Layer, Ref } from "effect";
13
- import { callInspection } from "../call-attribution-store.js";
13
+ import { AccountRecovery } from "../account-recovery-context.js";
14
14
  import { createCliproxySidecar, createHostedCliproxySidecar } from "../cliproxy-sidecar.js";
15
15
  import { createDaemonControlDispatch } from "../control-dispatch.js";
16
16
  import { prepareDaemonBootstrap } from "../daemon-bootstrap-preflight.js";
17
17
  import { createDaemonControlHandlers } from "../daemon-control-handlers.js";
18
- import { createDaemonGenerationManager } from "../daemon-generations.js";
19
- import { accountEntriesWithPaths, canonicalConfigDocument, redactedProcessArgs } from "../daemon-maintenance.js";
18
+ import { DaemonEnv } from "../daemon-env-context.js";
19
+ import { DaemonHost } from "../daemon-host-context.js";
20
+ import { canonicalConfigDocument, redactedProcessArgs } from "../daemon-maintenance.js";
21
+ import { DaemonPolicy, wantsCliproxySidecar } from "../daemon-policy-context.js";
20
22
  import { healthyControl, removeDaemonPublicRecord, workloadJwtOptions, writeDaemonPublicRecord, writeDaemonRevisions } from "../daemon-state.js";
21
- import { makeCompositionalRoutingPolicyReader } from "../eval-routing-policy.js";
23
+ import { DaemonState } from "../daemon-state-context.js";
24
+ import { DataPlane } from "../data-plane-context.js";
25
+ import { makeEvalSessionExecutionStore } from "../eval-session-execution-store.js";
22
26
  import { LeaderboardRollupStore } from "../leaderboard.js";
23
- import { AccountRecovery } from "../account-recovery-context.js";
27
+ import { Leaderboard } from "../leaderboard-context.js";
24
28
  import { ActiveGateway } from "../services/active-gateway/service.js";
25
29
  import { CallAttributions } from "../services/call-attributions/service.js";
26
- import { DaemonEnv } from "../daemon-env-context.js";
27
- import { DaemonHost } from "../daemon-host-context.js";
28
- import { DaemonPolicy } from "../daemon-policy-context.js";
29
30
  import { DaemonRuntime } from "../services/daemon-runtime/service.js";
30
- import { DaemonState } from "../daemon-state-context.js";
31
- import { DataPlane } from "../data-plane-context.js";
32
31
  import { EvalSessions } from "../services/eval-session/service.js";
33
32
  import { Generations } from "../services/generations/service.js";
34
33
  import { LauncherSessions } from "../services/launcher-session/service.js";
35
- import { Leaderboard } from "../leaderboard-context.js";
36
- import { Sidecar } from "../sidecar-context.js";
37
34
  import { Telemetry } from "../services/telemetry/service.js";
38
35
  import { Tokens } from "../services/tokens/service.js";
36
+ import { Sidecar } from "../sidecar-context.js";
39
37
  const ROUTEKIT_DAEMON_KIND = "daemon";
40
38
  const ROUTEKIT_PRODUCT = "routekit";
41
39
  class DaemonFoundation extends Context.Service()("@velum-labs/routekit-daemon/DaemonFoundation") {
@@ -73,37 +71,6 @@ const prepareFoundation = (options) => Effect.acquireRelease(Effect.tryPromise({
73
71
  }), (foundation) => Effect.sync(() => {
74
72
  foundation.authority?.release();
75
73
  }));
76
- const wantsSidecar = (config) => config.providers.cliproxy !== undefined;
77
- const activeCredentialFingerprints = (env) => new Map(accountEntriesWithPaths(env).flatMap((entry) => entry.connector === "native"
78
- ? [
79
- [
80
- subscriptionAccountIdentity(entry.subscriptionKind, entry.label),
81
- subscriptionCredentialFingerprint(entry.path)
82
- ]
83
- ]
84
- : []));
85
- const routerEnv = (env) => {
86
- const injected = { ...env };
87
- if ((env[CLIPROXY_API_KEY_ENV] ?? "").length === 0) {
88
- const key = cliproxyApiKey(env);
89
- if (key !== undefined)
90
- injected[CLIPROXY_API_KEY_ENV] = key;
91
- }
92
- if ((env[CLIPROXY_BASE_URL_ENV] ?? "").length === 0) {
93
- injected[CLIPROXY_BASE_URL_ENV] = cliproxyBaseUrl(env);
94
- }
95
- return injected;
96
- };
97
- function promiseHandlers(handlers, context) {
98
- return new Proxy(handlers, {
99
- get(target, method, receiver) {
100
- const handler = Reflect.get(target, method, receiver);
101
- if (typeof handler !== "function")
102
- return handler;
103
- return (params, handlerContext) => Effect.runPromiseWith(context)(withAbortSignal(handler(params, handlerContext), handlerContext.signal));
104
- }
105
- });
106
- }
107
74
  const acquireRunningDaemon = Effect.fn("Daemon.acquireRunning")(function* (options) {
108
75
  const foundation = yield* DaemonFoundation;
109
76
  const state = yield* DaemonState;
@@ -116,16 +83,15 @@ const acquireRunningDaemon = Effect.fn("Daemon.acquireRunning")(function* (optio
116
83
  const telemetry = yield* Telemetry;
117
84
  const auth = yield* AccountAuth;
118
85
  const context = yield* Effect.context();
119
- const provideRuntime = (effect) => effect.pipe(Effect.provide(context));
120
86
  yield* Effect.addFinalizer(() => Effect.sync(() => foundation.runtimeState.markClosed()));
121
- yield* sidecar.reconcile(wantsSidecar(state.config));
87
+ yield* sidecar.reconcile(wantsCliproxySidecar(state.config));
122
88
  const router = yield* generations.start(state.config);
123
89
  yield* Ref.update(gateway.state, (current) => ({ ...current, router }));
124
90
  yield* Effect.addFinalizer(() => {
125
91
  const active = gateway.router();
126
92
  return active === undefined ? Effect.void : active.close.pipe(Effect.ignore);
127
93
  });
128
- yield* auth.reconcileActiveCredentials(activeCredentialFingerprints(foundation.env));
94
+ yield* auth.reconcileActiveCredentials(router.activeCredentialFingerprints());
129
95
  const workloadJwt = workloadJwtOptions(options.workloadJwt, foundation.env);
130
96
  const verifyWorkloadJwt = workloadJwt === undefined ? undefined : createWorkloadJwtVerifier(workloadJwt);
131
97
  const proxy = yield* startSwitchingGatewayProxyEffect({
@@ -134,6 +100,7 @@ const acquireRunningDaemon = Effect.fn("Daemon.acquireRunning")(function* (optio
134
100
  host: options.host ?? "127.0.0.1",
135
101
  port: options.port ?? 8080,
136
102
  authToken: tokens.dataAuth.token,
103
+ bindEvalSubmission: (sessionId, request) => evalSessions.bindIngress(sessionId, request),
137
104
  resolveDataPrincipal: (presented) => {
138
105
  const launcherPrincipal = launcherSessions.resolve(presented);
139
106
  if (launcherPrincipal !== undefined)
@@ -164,7 +131,7 @@ const acquireRunningDaemon = Effect.fn("Daemon.acquireRunning")(function* (optio
164
131
  const dataUrl = foundation.hosted?.dataUrl() ??
165
132
  (portless?.enabled === true ? portless.register("gateway", proxy.port()) : proxy.url());
166
133
  yield* Ref.update(gateway.state, (current) => ({ ...current, proxy, dataUrl }));
167
- const handlers = promiseHandlers(createDaemonControlHandlers(), context);
134
+ const handlers = toPromiseControlHandlers(createDaemonControlHandlers(), context);
168
135
  const dispatch = createDaemonControlDispatch({
169
136
  handlers,
170
137
  runtimeState: foundation.runtimeState,
@@ -197,16 +164,17 @@ const acquireRunningDaemon = Effect.fn("Daemon.acquireRunning")(function* (optio
197
164
  });
198
165
  yield* Effect.addFinalizer(() => control.close.pipe(Effect.ignore));
199
166
  yield* Ref.update(gateway.state, (current) => ({ ...current, control }));
167
+ const identity = processIdentity(process.pid);
168
+ const supervisor = supervisorFromEnv(foundation.env);
200
169
  const recordInput = {
201
170
  kind: ROUTEKIT_DAEMON_KIND,
202
171
  pid: process.pid,
203
- ...(processIdentity(process.pid) === undefined
204
- ? {}
205
- : { processIdentity: processIdentity(process.pid) }),
172
+ ...(identity === undefined ? {} : { processIdentity: identity }),
206
173
  url: control.url,
207
174
  port: control.port,
208
175
  startedAt: foundation.startedAt,
209
176
  version: options.packageVersion,
177
+ ...(options.sourceBuildId === undefined ? {} : { sourceBuildId: options.sourceBuildId }),
210
178
  protocolVersion: CONTROL_PROTOCOL_VERSION,
211
179
  controlToken: control.token,
212
180
  dataUrl,
@@ -216,7 +184,7 @@ const acquireRunningDaemon = Effect.fn("Daemon.acquireRunning")(function* (optio
216
184
  drainGraceMs: foundation.drainGraceMs,
217
185
  authTokenFile: tokens.dataAuth.path,
218
186
  generation: foundation.generation,
219
- supervisor: supervisorFromEnv(foundation.env),
187
+ supervisor,
220
188
  ...(process.argv[1] === undefined ? {} : { binPath: process.argv[1] }),
221
189
  args: redactedProcessArgs(process.argv.slice(2)),
222
190
  cwd: process.cwd()
@@ -241,31 +209,28 @@ const acquireRunningDaemon = Effect.fn("Daemon.acquireRunning")(function* (optio
241
209
  removeDaemonPublicRecord(foundation.home);
242
210
  }));
243
211
  }
244
- telemetry.daemon.capture("routekit.daemon_lifecycle", {
245
- action: "started",
212
+ const lifecycleProperties = {
246
213
  outcome: "success",
247
- supervisor: ["systemd", "launchd", "detached"].includes(supervisorFromEnv(foundation.env))
248
- ? supervisorFromEnv(foundation.env)
249
- : "unknown",
214
+ supervisor,
250
215
  version: options.packageVersion
216
+ };
217
+ telemetry.daemon.capture("routekit.daemon_lifecycle", {
218
+ ...lifecycleProperties,
219
+ action: "started"
251
220
  });
252
221
  const prepareClose = Effect.gen(function* () {
253
222
  foundation.runtimeState.beginShutdown();
254
- yield* foundation.runtimeState.awaitMutations();
223
+ yield* foundation.runtimeState.awaitMutations;
255
224
  telemetry.daemon.capture("routekit.daemon_lifecycle", {
256
- action: "stopped",
257
- outcome: "success",
258
- supervisor: ["systemd", "launchd", "detached"].includes(supervisorFromEnv(foundation.env))
259
- ? supervisorFromEnv(foundation.env)
260
- : "unknown",
261
- version: options.packageVersion
225
+ ...lifecycleProperties,
226
+ action: "stopped"
262
227
  });
263
228
  foundation.runtimeState.markDraining();
264
229
  yield* proxy.drain(foundation.drainGraceMs);
265
230
  });
266
231
  const prepareRetire = (graceMs = foundation.drainGraceMs) => Effect.gen(function* () {
267
232
  foundation.runtimeState.beginRetire();
268
- yield* foundation.runtimeState.awaitMutations();
233
+ yield* foundation.runtimeState.awaitMutations;
269
234
  foundation.runtimeState.markDraining();
270
235
  yield* Effect.all([proxy.retire(graceMs), control.retire(Math.min(graceMs, 2_000))], {
271
236
  concurrency: "unbounded"
@@ -282,20 +247,19 @@ const acquireRunningDaemon = Effect.fn("Daemon.acquireRunning")(function* (optio
282
247
  record,
283
248
  dataUrl,
284
249
  controlUrl: control.url,
285
- prepareClose: provideRuntime(prepareClose),
286
- prepareRetire: (graceMs) => provideRuntime(prepareRetire(graceMs)),
287
- pauseMutations: provideRuntime(Effect.gen(function* () {
250
+ prepareClose,
251
+ prepareRetire,
252
+ pauseMutations: Effect.gen(function* () {
288
253
  foundation.runtimeState.pause();
289
- yield* foundation.runtimeState.awaitMutations();
254
+ yield* foundation.runtimeState.awaitMutations;
290
255
  return foundation.runtimeState.snapshot();
291
- })),
292
- resumeMutations: provideRuntime(Effect.sync(() => foundation.runtimeState.resume())),
293
- snapshot: provideRuntime(Effect.sync(() => foundation.runtimeState.snapshot())),
294
- reload: provideRuntime(reload)
256
+ }),
257
+ resumeMutations: Effect.sync(() => foundation.runtimeState.resume()),
258
+ snapshot: Effect.sync(() => foundation.runtimeState.snapshot()),
259
+ reload: Effect.provide(reload, context)
295
260
  });
296
261
  });
297
- /** Construct and own the complete daemon worker lifetime. */
298
- export function daemonLive(options) {
262
+ function daemonLayers(options) {
299
263
  const foundation = Layer.effect(DaemonFoundation, prepareFoundation(options));
300
264
  const platform = RouteKitLive.pipe(Layer.provideMerge(foundation));
301
265
  const owned = Layer.mergeAll(Layer.effect(Sidecar, Effect.flatMap(DaemonFoundation, (value) => Effect.acquireRelease(Effect.sync(() => value.hosted === undefined
@@ -328,7 +292,11 @@ export function daemonLive(options) {
328
292
  });
329
293
  }
330
294
  });
331
- }), (leaderboard) => Effect.sync(() => leaderboard.rollups.flush())))), EvalSessions.layer(), LauncherSessions.layer()).pipe(Layer.provideMerge(platform));
295
+ }), (leaderboard) => Effect.sync(() => leaderboard.rollups.flush())))), Layer.unwrap(Effect.gen(function* () {
296
+ const foundation = yield* DaemonFoundation;
297
+ const store = yield* makeEvalSessionExecutionStore(join(foundation.home, "eval-sessions", "execution-v1"));
298
+ return EvalSessions.layer({ store });
299
+ })), LauncherSessions.layer()).pipe(Layer.provideMerge(platform));
332
300
  const staticServices = Layer.mergeAll(Layer.effect(DaemonEnv, Effect.map(DaemonFoundation, (value) => DaemonEnv.of({
333
301
  home: value.home,
334
302
  configPath: value.configPath,
@@ -340,7 +308,7 @@ export function daemonLive(options) {
340
308
  }))), Layer.unwrap(Effect.map(DaemonFoundation, (value) => DaemonState.layer(value.runtimeState))), Layer.effect(DataPlane, Effect.map(Tokens, (tokens) => ({
341
309
  token: tokens.dataAuth.token,
342
310
  path: tokens.dataAuth.path
343
- }))), Layer.effect(AccountRecovery, Effect.map(DaemonFoundation, (value) => value.accountRecovery)), Layer.unwrap(Effect.map(DaemonFoundation, (value) => CallAttributions.layer(resolveLeaderboardConfig(value.runtimeState.config)))), Layer.effect(DaemonPolicy, Effect.succeed({ wantsCliproxySidecar: wantsSidecar })), Layer.effect(DaemonHost, Effect.map(DaemonFoundation, (value) => ({
311
+ }))), Layer.effect(AccountRecovery, Effect.map(DaemonFoundation, (value) => value.accountRecovery)), Layer.unwrap(Effect.map(DaemonFoundation, (value) => CallAttributions.layer(resolveLeaderboardConfig(value.runtimeState.config)))), Layer.succeed(DaemonPolicy, { wantsCliproxySidecar }), Layer.effect(DaemonHost, Effect.map(DaemonFoundation, (value) => ({
344
312
  ...(options.onShutdownRequested === undefined
345
313
  ? {}
346
314
  : {
@@ -358,61 +326,15 @@ export function daemonLive(options) {
358
326
  ? {}
359
327
  : { onAccountTransactionPhase: options.onAccountTransactionPhase })
360
328
  }))), ActiveGateway.layer, Layer.unwrap(Effect.map(DaemonFoundation, (value) => AccountActivity.layer({ statePath: join(value.home, "usage", "account-activity.v1.json") }))), Layer.unwrap(Effect.map(DaemonFoundation, (value) => AccountAuth.layer({ statePath: join(value.home, "subscriptions", "account-auth.v1.json") })))).pipe(Layer.provideMerge(owned));
361
- const generations = Layer.effect(Generations, Effect.gen(function* () {
362
- const foundation = yield* DaemonFoundation;
363
- const state = yield* DaemonState;
364
- const sidecar = yield* Sidecar;
365
- const activity = yield* AccountActivity;
366
- const auth = yield* AccountAuth;
367
- const gateway = yield* ActiveGateway;
368
- const callAttributions = yield* CallAttributions;
369
- const leaderboard = yield* Leaderboard;
370
- const telemetry = yield* Telemetry;
371
- return createDaemonGenerationManager({
372
- configPath: foundation.configPath,
373
- home: foundation.home,
374
- drainGraceMs: foundation.drainGraceMs,
375
- sidecar,
376
- routerEnv: () => routerEnv(foundation.env),
377
- provenance: {
378
- onModelCall(record) {
379
- callAttributions.onModelCall(record);
380
- const inspection = callInspection(record);
381
- if (inspection !== undefined)
382
- leaderboard.rollups.record(inspection);
383
- telemetry.gateway.record(record);
384
- }
385
- },
386
- compositionalPolicyReader: makeCompositionalRoutingPolicyReader(foundation.home),
387
- activity,
388
- authHealth: auth,
389
- wantsSidecar,
390
- getCurrentConfig: () => state.config,
391
- setCurrentConfig: (config) => {
392
- state.config = config;
393
- },
394
- getCurrentDocument: () => state.document,
395
- setCurrentDocument: (document) => {
396
- state.document = document;
397
- },
398
- getRevisions: () => state.revisions,
399
- setRevisions: (revisions) => {
400
- state.revisions = revisions;
401
- },
402
- getActiveRouter: () => gateway.router(),
403
- setActiveRouter: (router) => Ref.update(gateway.state, (current) => ({ ...current, router })),
404
- getProxy: () => gateway.proxy(),
405
- activeCredentialFingerprints: () => activeCredentialFingerprints(foundation.env),
406
- applyConfig: (config) => {
407
- leaderboard.applyConfig(config);
408
- const current = leaderboard.config();
409
- callAttributions.configureBudget({
410
- limit: current.liveLimit,
411
- ttlMs: current.liveTtlHours * 60 * 60 * 1_000
412
- });
413
- },
414
- ...(options.onGenerationStage === undefined ? {} : { onStage: options.onGenerationStage })
415
- });
416
- })).pipe(Layer.provideMerge(staticServices));
417
- return Layer.effect(DaemonRuntime, acquireRunningDaemon(options)).pipe(Layer.provideMerge(generations));
329
+ const generations = Layer.unwrap(Effect.map(DaemonFoundation, (foundation) => Generations.layer({
330
+ drainGraceMs: foundation.drainGraceMs,
331
+ ...(options.onGenerationStage === undefined ? {} : { onStage: options.onGenerationStage })
332
+ }))).pipe(Layer.provideMerge(staticServices));
333
+ return generations;
334
+ }
335
+ /** Construct and own the complete daemon worker lifetime. */
336
+ export function daemonLive(options) {
337
+ // The published service union deliberately excludes platform/foundation and
338
+ // private launcher credentials. Runtime composition still owns all of them.
339
+ return Layer.effect(DaemonRuntime, acquireRunningDaemon(options)).pipe(Layer.provideMerge(daemonLayers(options)));
418
340
  }
@@ -1,7 +1,5 @@
1
1
  import type { EffectRouteKitControlHandlers } from "@velum-labs/routekit-control/effect";
2
2
  type EvalRoutingHandlers = Pick<EffectRouteKitControlHandlers, "evalRouting.status" | "evalRouting.activate" | "evalRouting.installAuthoritative" | "evalRouting.rollbackAuthoritative">;
3
3
  /** Owns target-local compositional routing status and atomic activation. */
4
- export declare class EvalRoutingApplicationService {
5
- handlers(): EvalRoutingHandlers;
6
- }
4
+ export declare const evalRoutingHandlers: EvalRoutingHandlers;
7
5
  export {};
@@ -1,8 +1,7 @@
1
1
  import { DEFAULT_CLASSIFIER_MODEL } from "@velum-labs/routekit-config";
2
- import { AnyPublishedRoutingActivation, assertPublishedRoutingActivation, assertPublishedRoutingActivationV3 } from "@velum-labs/routekit-eval-contracts";
3
2
  import { makeRoutingActivationStore, RoutingActivationConflictError, RoutingDeploymentConflictError } from "@velum-labs/routekit-eval-store/effect";
4
3
  import { ControlError } from "@velum-labs/routekit-runtime/control";
5
- import { Effect, Schema } from "effect";
4
+ import { Effect } from "effect";
6
5
  import { DaemonEnv } from "./daemon-env-context.js";
7
6
  import { DaemonState } from "./daemon-state-context.js";
8
7
  import { evalRoutingSnapshotDirectory } from "./eval-routing-policy.js";
@@ -20,26 +19,6 @@ function identity(revision) {
20
19
  evidenceDigest: revision.activation.evidenceDigest
21
20
  };
22
21
  }
23
- function decodeAnyActivation(value) {
24
- return Schema.decodeUnknownEffect(AnyPublishedRoutingActivation)(value).pipe(Effect.flatMap((activation) => Effect.try({
25
- try: () => {
26
- if (activation.version === 2)
27
- assertPublishedRoutingActivation(activation);
28
- else
29
- assertPublishedRoutingActivationV3(activation);
30
- return activation;
31
- },
32
- catch: (cause) => new ControlError({
33
- code: "bad_request",
34
- message: `routing activation is invalid: ${detailOf(cause)}`
35
- })
36
- })), Effect.mapError((cause) => cause instanceof ControlError
37
- ? cause
38
- : new ControlError({
39
- code: "bad_request",
40
- message: `routing activation is invalid: ${detailOf(cause)}`
41
- })));
42
- }
43
22
  const mapStoreError = (operation) => (cause) => cause instanceof RoutingActivationConflictError ||
44
23
  cause instanceof RoutingDeploymentConflictError
45
24
  ? new ControlError({ code: "conflict", message: cause.message })
@@ -47,6 +26,7 @@ const mapStoreError = (operation) => (cause) => cause instanceof RoutingActivati
47
26
  code: "internal",
48
27
  message: `failed to ${operation}: ${detailOf(cause)}`
49
28
  });
29
+ const routingStore = Effect.map(DaemonEnv, ({ home }) => makeRoutingActivationStore(evalRoutingSnapshotDirectory(home)));
50
30
  function validateRuntimeCompatibility(activation) {
51
31
  return Effect.gen(function* () {
52
32
  const state = yield* DaemonState;
@@ -89,52 +69,48 @@ function validateRuntimeCompatibility(activation) {
89
69
  });
90
70
  }
91
71
  /** Owns target-local compositional routing status and atomic activation. */
92
- export class EvalRoutingApplicationService {
93
- handlers() {
72
+ export const evalRoutingHandlers = {
73
+ "evalRouting.status": () => Effect.gen(function* () {
74
+ const store = yield* routingStore;
75
+ const deployment = yield* store
76
+ .readDeployment()
77
+ .pipe(Effect.mapError(mapStoreError("read routing deployment")));
94
78
  return {
95
- "evalRouting.status": () => Effect.gen(function* () {
96
- const env = yield* DaemonEnv;
97
- const deployment = yield* makeRoutingActivationStore(evalRoutingSnapshotDirectory(env.home))
98
- .readDeployment()
99
- .pipe(Effect.mapError(mapStoreError("read routing deployment")));
100
- return {
101
- stateRevision: deployment.stateRevision,
102
- authoritative: identity(deployment.authoritative),
103
- previousAuthoritative: identity(deployment.previousAuthoritative)
104
- };
105
- }),
106
- "evalRouting.activate": (params) => Effect.fail(new ControlError({
107
- code: "bad_request",
108
- message: "Classification V2 activation is rollback-only; install a qualified Classification V3 activation or restore the retained V2 revision with evalRouting.rollbackAuthoritative"
109
- })),
110
- "evalRouting.installAuthoritative": (params) => Effect.gen(function* () {
111
- const env = yield* DaemonEnv;
112
- const activation = yield* makeRoutingActivationStore(evalRoutingSnapshotDirectory(env.home))
113
- .readActivation(params.activationPath)
114
- .pipe(Effect.mapError(mapStoreError("read authoritative routing policy")));
115
- yield* validateRuntimeCompatibility(activation);
116
- const deployment = yield* makeRoutingActivationStore(evalRoutingSnapshotDirectory(env.home))
117
- .installAuthoritative(activation, params.activationPath, params.expectedAuthoritativeRevisionDigest, params.expectedPreviousAuthoritativeRevisionDigest)
118
- .pipe(Effect.mapError(mapStoreError("install authoritative routing policy")));
119
- return {
120
- installed: true,
121
- stateRevision: deployment.stateRevision,
122
- authoritative: identity(deployment.authoritative),
123
- previousAuthoritative: identity(deployment.previousAuthoritative)
124
- };
125
- }),
126
- "evalRouting.rollbackAuthoritative": (params) => Effect.gen(function* () {
127
- const env = yield* DaemonEnv;
128
- const deployment = yield* makeRoutingActivationStore(evalRoutingSnapshotDirectory(env.home))
129
- .rollbackAuthoritative(params.expectedAuthoritativeRevisionDigest, params.expectedPreviousAuthoritativeRevisionDigest)
130
- .pipe(Effect.mapError(mapStoreError("roll back authoritative routing policy")));
131
- return {
132
- rolledBack: true,
133
- stateRevision: deployment.stateRevision,
134
- authoritative: identity(deployment.authoritative),
135
- previousAuthoritative: identity(deployment.previousAuthoritative)
136
- };
137
- })
79
+ stateRevision: deployment.stateRevision,
80
+ authoritative: identity(deployment.authoritative),
81
+ previousAuthoritative: identity(deployment.previousAuthoritative)
138
82
  };
139
- }
140
- }
83
+ }),
84
+ "evalRouting.activate": () => Effect.fail(new ControlError({
85
+ code: "bad_request",
86
+ message: "Classification V2 activation is rollback-only; install a qualified Classification V3 activation or restore the retained V2 revision with evalRouting.rollbackAuthoritative"
87
+ })),
88
+ "evalRouting.installAuthoritative": (params) => Effect.gen(function* () {
89
+ const store = yield* routingStore;
90
+ const activation = yield* store
91
+ .readActivation(params.activationPath)
92
+ .pipe(Effect.mapError(mapStoreError("read authoritative routing policy")));
93
+ yield* validateRuntimeCompatibility(activation);
94
+ const deployment = yield* store
95
+ .installAuthoritative(activation, params.activationPath, params.expectedAuthoritativeRevisionDigest, params.expectedPreviousAuthoritativeRevisionDigest)
96
+ .pipe(Effect.mapError(mapStoreError("install authoritative routing policy")));
97
+ return {
98
+ installed: true,
99
+ stateRevision: deployment.stateRevision,
100
+ authoritative: identity(deployment.authoritative),
101
+ previousAuthoritative: identity(deployment.previousAuthoritative)
102
+ };
103
+ }),
104
+ "evalRouting.rollbackAuthoritative": (params) => Effect.gen(function* () {
105
+ const store = yield* routingStore;
106
+ const deployment = yield* store
107
+ .rollbackAuthoritative(params.expectedAuthoritativeRevisionDigest, params.expectedPreviousAuthoritativeRevisionDigest)
108
+ .pipe(Effect.mapError(mapStoreError("roll back authoritative routing policy")));
109
+ return {
110
+ rolledBack: true,
111
+ stateRevision: deployment.stateRevision,
112
+ authoritative: identity(deployment.authoritative),
113
+ previousAuthoritative: identity(deployment.previousAuthoritative)
114
+ };
115
+ })
116
+ };
@@ -0,0 +1,24 @@
1
+ import type { EvalSessionExecutionEvidence } from "@velum-labs/routekit-control";
2
+ import { HttpSubmissionError } from "@velum-labs/routekit-runtime/effect";
3
+ import { Effect, FileSystem, Path } from "effect";
4
+ export type EvalSessionExecutionStore = {
5
+ readonly directory: string;
6
+ readonly create: (evidence: EvalSessionExecutionEvidence) => Effect.Effect<EvalSessionExecutionEvidence, HttpSubmissionError>;
7
+ readonly read: (executionDigest: string, sessionId?: string) => Effect.Effect<EvalSessionExecutionEvidence | undefined, HttpSubmissionError>;
8
+ readonly update: (executionDigest: string, update: (current: EvalSessionExecutionEvidence) => EvalSessionExecutionEvidence, options?: {
9
+ readonly allowReadinessReopen?: boolean;
10
+ }) => Effect.Effect<EvalSessionExecutionEvidence, HttpSubmissionError>;
11
+ readonly recover: (now: string) => Effect.Effect<readonly EvalSessionExecutionEvidence[], HttpSubmissionError>;
12
+ };
13
+ /** Derive closure without ever converting a pending or unknown receipt to success. */
14
+ export declare function normalizeExecutionEvidence(evidence: EvalSessionExecutionEvidence): EvalSessionExecutionEvidence;
15
+ /**
16
+ * Private payload-free authority store. Each operation reads current durable
17
+ * state under the existing process-identity lifecycle lock before an atomic
18
+ * replacement. A retiring worker therefore cannot overwrite a successor's
19
+ * revocation, recovered unknown receipt, or consumed execution identity.
20
+ *
21
+ * The lock is transaction-scoped, not another gateway/request resource owner.
22
+ * Atomic rename covers interruption and reported I/O faults, not power loss.
23
+ */
24
+ export declare const makeEvalSessionExecutionStore: (inputDirectory: string) => Effect.Effect<EvalSessionExecutionStore, HttpSubmissionError, FileSystem.FileSystem | Path.Path>;