@velum-labs/routekit-daemon 0.16.0 → 0.16.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -8,20 +8,19 @@
8
8
  */
9
9
  import { chmodSync, existsSync, lstatSync, mkdirSync, readFileSync, rmSync } from "node:fs";
10
10
  import { basename, dirname, join } from "node:path";
11
- import { AccountActivityCoordinator, CLIPROXY_API_KEY_ENV, CLIPROXY_BASE_URL_ENV, accountStoreEntries, cliproxyAuthDirectory, cliproxyAccountEntries, cliproxyAccountMatchesKind, cliproxyApiKey, cliproxyBaseUrl, cliproxyCredentialValid, defaultSubscriptionAccountDirectory, RateLimitTracker, removeCliproxyAccount, removeSubscriptionAccount, renameSubscriptionAccount, sanitizeSubscriptionLabel, subscriptionAccountIdentity } from "@velum-labs/routekit-accounts";
11
+ import { AccountActivityCoordinator, accountStoreEntries, CLIPROXY_API_KEY_ENV, CLIPROXY_BASE_URL_ENV, cliproxyAccountEntries, cliproxyAccountMatchesKind, cliproxyApiKey, cliproxyAuthDirectory, cliproxyBaseUrl, cliproxyCredentialValid, defaultSubscriptionAccountDirectory, RateLimitTracker, removeCliproxyAccount, removeSubscriptionAccount, renameSubscriptionAccount, sanitizeSubscriptionLabel, subscriptionAccountIdentity } from "@velum-labs/routekit-accounts";
12
12
  import { configuredProviderIds, globalRouterConfigPath, parseRouterConfigDocument, routekitHome, writeRouterConfig } from "@velum-labs/routekit-config";
13
13
  import { createRouteKitControlHandler, ROUTEKIT_CONTROL_CAPABILITY } from "@velum-labs/routekit-control";
14
- import { startSwitchingGatewayProxy } from "@velum-labs/routekit-gateway";
15
- import { resolveLeaderboardConfig } from "@velum-labs/routekit-gateway";
16
- import { PROVIDERS, accountKindForCliproxyAuthType, resolveAccountConnector } from "@velum-labs/routekit-registry";
14
+ import { resolveLeaderboardConfig, startSwitchingGatewayProxy } from "@velum-labs/routekit-gateway";
15
+ import { accountKindForCliproxyAuthType, PROVIDERS, resolveAccountConnector } from "@velum-labs/routekit-registry";
17
16
  import { startRouter } from "@velum-labs/routekit-router";
18
17
  import { acquireLifecycleLock, CONTROL_PROTOCOL_VERSION, ControlClient, ControlError, createPortlessSession, createServiceRecordStore, createTokenStore, encodeJoinCredential, extendCleanupGrace, generateControlToken, nextServiceGeneration, processIdentity, registerCleanup, SERVICE_HOME_MODE, startControlServer, supervisorFromEnv, writeFileAtomic } from "@velum-labs/routekit-runtime";
19
18
  import { createConsentManager } from "@velum-labs/routekit-telemetry-core";
20
19
  import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
21
- import { createCliproxySidecar } from "./cliproxy-sidecar.js";
22
20
  import { cleanupAccountTransaction, markAccountTransactionCommitted, prepareAccountTransaction, recoverAccountTransactions, rollbackAccountTransaction } from "./account-transaction.js";
23
21
  import { CallAttributionStore, callInspection } from "./call-attribution-store.js";
24
- import { aggregateInspections, buildLeaderboardResult, LeaderboardRollupStore } from "./leaderboard.js";
22
+ import { createCliproxySidecar } from "./cliproxy-sidecar.js";
23
+ import { aggregateInspections, buildLeaderboardResult, defaultLeaderboardWindow, LeaderboardRollupStore } from "./leaderboard.js";
25
24
  export const ROUTEKIT_DAEMON_KIND = "daemon";
26
25
  export const ROUTEKIT_PRODUCT = "routekit";
27
26
  function dataTokenPath(home) {
@@ -111,9 +110,7 @@ function readRevisions(home) {
111
110
  accounts: typeof parsed.accounts === "number" && Number.isSafeInteger(parsed.accounts)
112
111
  ? parsed.accounts
113
112
  : 0,
114
- daemon: typeof parsed.daemon === "number" && Number.isSafeInteger(parsed.daemon)
115
- ? parsed.daemon
116
- : 0
113
+ daemon: typeof parsed.daemon === "number" && Number.isSafeInteger(parsed.daemon) ? parsed.daemon : 0
117
114
  };
118
115
  }
119
116
  catch {
@@ -170,7 +167,7 @@ function providerCredentialAvailable(provider, accounts, env) {
170
167
  return accounts.some((entry) => entry.subscriptionKind === provider);
171
168
  }
172
169
  if (provider === "cliproxy") {
173
- return ((env[CLIPROXY_API_KEY_ENV] ?? "").length > 0 || cliproxyApiKey(env) !== undefined);
170
+ return (env[CLIPROXY_API_KEY_ENV] ?? "").length > 0 || cliproxyApiKey(env) !== undefined;
174
171
  }
175
172
  const info = PROVIDERS[provider];
176
173
  if (info?.keyEnv === undefined)
@@ -203,7 +200,7 @@ function safeCliproxyCredentialBlob(kind, value) {
203
200
  const type = typeof record.type === "string" ? record.type : undefined;
204
201
  const classified = type === undefined
205
202
  ? undefined
206
- : accountKindForCliproxyAuthType(type) ?? resolveAccountConnector(type)?.kind;
203
+ : (accountKindForCliproxyAuthType(type) ?? resolveAccountConnector(type)?.kind);
207
204
  if (classified !== kind || !cliproxyCredentialValid(record, type)) {
208
205
  throw new ControlError({
209
206
  code: "bad_request",
@@ -396,10 +393,12 @@ export async function startRouteKitDaemon(options) {
396
393
  };
397
394
  }
398
395
  });
399
- portless = await createPortlessSession(options.portless ?? env.ROUTEKIT_PORTLESS !== "0", { project: "routekit", ownerLabel: "routekit-daemon", bareNames: [] });
400
- const dataUrl = portless.enabled
401
- ? portless.register("gateway", proxy.port())
402
- : proxy.url();
396
+ portless = await createPortlessSession(options.portless ?? env.ROUTEKIT_PORTLESS !== "0", {
397
+ project: "routekit",
398
+ ownerLabel: "routekit-daemon",
399
+ bareNames: []
400
+ });
401
+ const dataUrl = portless.enabled ? portless.register("gateway", proxy.port()) : proxy.url();
403
402
  const replaceRouter = async (nextConfig, nextDocument, input) => {
404
403
  // Sidecar reconcile runs before the generation commits; any failure
405
404
  // below must put the sidecar back to the still-live currentConfig.
@@ -641,7 +640,7 @@ export async function startRouteKitDaemon(options) {
641
640
  const by = params.by ?? "principal";
642
641
  const sort = params.sort ?? "cost";
643
642
  const limit = params.limit ?? 20;
644
- const window = params.window ?? "live";
643
+ const window = params.window ?? defaultLeaderboardWindow(leaderboardConfig);
645
644
  const nowIso = new Date().toISOString();
646
645
  if (window === "live") {
647
646
  const inspections = callAttributions.list();
@@ -708,6 +707,9 @@ export async function startRouteKitDaemon(options) {
708
707
  inFlight: 0,
709
708
  lastSelected: false,
710
709
  active: false,
710
+ ...(entry.credentialValid
711
+ ? {}
712
+ : { readinessReasons: [{ code: "credential_invalid" }] }),
711
713
  models: []
712
714
  };
713
715
  }
@@ -730,6 +732,11 @@ export async function startRouteKitDaemon(options) {
730
732
  : {}),
731
733
  lastSelected: member?.lastSelected ?? false,
732
734
  active: member?.lastSelected ?? false,
735
+ ...(member?.readinessReasons !== undefined
736
+ ? { readinessReasons: member.readinessReasons }
737
+ : member === undefined
738
+ ? { readinessReasons: [{ code: "credential_invalid" }] }
739
+ : {}),
733
740
  models: member?.models ?? [],
734
741
  ...(member?.limits !== undefined ? { limits: member.limits } : {})
735
742
  };
@@ -797,8 +804,7 @@ export async function startRouteKitDaemon(options) {
797
804
  const label = connector === "native"
798
805
  ? sanitizeSubscriptionLabel(account.label)
799
806
  : safeCliproxyLabel(account.label);
800
- if (label !== account.label ||
801
- (connector === "native" && label.startsWith("."))) {
807
+ if (label !== account.label || (connector === "native" && label.startsWith("."))) {
802
808
  throw new ControlError({
803
809
  code: "bad_request",
804
810
  message: "account label must already be normalized"
@@ -887,8 +893,7 @@ export async function startRouteKitDaemon(options) {
887
893
  });
888
894
  }
889
895
  }
890
- const unchanged = prepared.every((entry) => existsSync(entry.path) &&
891
- readFileSync(entry.path, "utf8") === entry.content);
896
+ const unchanged = prepared.every((entry) => existsSync(entry.path) && readFileSync(entry.path, "utf8") === entry.content);
892
897
  if (unchanged &&
893
898
  currentConfig.providers[provider] !== undefined) {
894
899
  return;
@@ -1023,8 +1028,7 @@ export async function startRouteKitDaemon(options) {
1023
1028
  !Array.isArray(raw.providers)
1024
1029
  ? { ...raw.providers }
1025
1030
  : {};
1026
- const disableProvider = !hasRemainingAccount &&
1027
- currentConfig.providers[nativeKind] !== undefined;
1031
+ const disableProvider = !hasRemainingAccount && currentConfig.providers[nativeKind] !== undefined;
1028
1032
  if (disableProvider) {
1029
1033
  for (const providerKey of nativeKind === "claude-code"
1030
1034
  ? ["claude-code", "claudeCode", "claude"]
@@ -1037,12 +1041,8 @@ export async function startRouteKitDaemon(options) {
1037
1041
  delete raw.defaultModel;
1038
1042
  }
1039
1043
  }
1040
- const nextDocument = disableProvider
1041
- ? stringifyYaml(raw)
1042
- : currentDocument;
1043
- const nextConfig = disableProvider
1044
- ? parseConfigDocument(nextDocument)
1045
- : currentConfig;
1044
+ const nextDocument = disableProvider ? stringifyYaml(raw) : currentDocument;
1045
+ const nextConfig = disableProvider ? parseConfigDocument(nextDocument) : currentConfig;
1046
1046
  const activityPath = join(home, "usage", "account-activity.v1.json");
1047
1047
  const transaction = prepareAccountTransaction({
1048
1048
  home,
@@ -1054,7 +1054,9 @@ export async function startRouteKitDaemon(options) {
1054
1054
  labels: [params.label]
1055
1055
  });
1056
1056
  try {
1057
- const result = removeSubscriptionAccount(nativeKind, params.label, { accountsDirectory: activeNativeDirectory });
1057
+ const result = removeSubscriptionAccount(nativeKind, params.label, {
1058
+ accountsDirectory: activeNativeDirectory
1059
+ });
1058
1060
  removed = result.removed;
1059
1061
  if (!result.removed) {
1060
1062
  cleanupAccountTransaction(transaction);
@@ -1252,9 +1254,7 @@ export async function startRouteKitDaemon(options) {
1252
1254
  label: result.label,
1253
1255
  redeemRequestId: result.redeemRequestId,
1254
1256
  ...(result.creditId !== undefined ? { creditId: result.creditId } : {}),
1255
- ...(result.windowsReset !== undefined
1256
- ? { windowsReset: result.windowsReset }
1257
- : {}),
1257
+ ...(result.windowsReset !== undefined ? { windowsReset: result.windowsReset } : {}),
1258
1258
  usage: result.usage
1259
1259
  };
1260
1260
  }
@@ -1289,9 +1289,7 @@ export async function startRouteKitDaemon(options) {
1289
1289
  const missingProviders = [
1290
1290
  ...new Set(accounts
1291
1291
  .filter((entry) => {
1292
- const provider = entry.connector === "cliproxy"
1293
- ? "cliproxy"
1294
- : entry.subscriptionKind;
1292
+ const provider = entry.connector === "cliproxy" ? "cliproxy" : entry.subscriptionKind;
1295
1293
  return currentConfig.providers[provider] === undefined;
1296
1294
  })
1297
1295
  .map((entry) => entry.subscriptionKind))
@@ -1364,7 +1362,9 @@ export async function startRouteKitDaemon(options) {
1364
1362
  if (model === undefined || !listed.models.some((entry) => entry.id === model)) {
1365
1363
  throw new ControlError({
1366
1364
  code: "not_found",
1367
- message: params.model === undefined ? "no model is available" : `unknown model: ${params.model}`
1365
+ message: params.model === undefined
1366
+ ? "no model is available"
1367
+ : `unknown model: ${params.model}`
1368
1368
  });
1369
1369
  }
1370
1370
  return {
@@ -1381,9 +1381,7 @@ export async function startRouteKitDaemon(options) {
1381
1381
  label: params.label,
1382
1382
  plane: params.plane,
1383
1383
  role: "admin",
1384
- createdBy: params.createdBy ??
1385
- context.principal?.label ??
1386
- "control"
1384
+ createdBy: params.createdBy ?? context.principal?.label ?? "control"
1387
1385
  });
1388
1386
  if (issued.plane === "data") {
1389
1387
  dataTokenCache.set(issued.label, issued.token);
@@ -5,6 +5,7 @@ export type LeaderboardSort = RouteKitLeaderboard["sort"];
5
5
  export type LeaderboardWindow = NonNullable<RouteKitControlParams["calls.leaderboard"]["window"]>;
6
6
  export declare const LEADERBOARD_ROLLUP_VERSION: 1;
7
7
  export declare const LEADERBOARD_ROLLUP_RELATIVE_PATH: string;
8
+ export declare function defaultLeaderboardWindow(config: Pick<LeaderboardConfig, "durable" | "durableRetentionDays">): LeaderboardWindow;
8
9
  export declare function aggregateInspections(inspections: readonly RouteKitCallInspection[], options: {
9
10
  by: LeaderboardDimension;
10
11
  sort: LeaderboardSort;
@@ -7,6 +7,11 @@ import { dirname, join } from "node:path";
7
7
  import { writeFileAtomic } from "@velum-labs/routekit-runtime";
8
8
  export const LEADERBOARD_ROLLUP_VERSION = 1;
9
9
  export const LEADERBOARD_ROLLUP_RELATIVE_PATH = join("usage", "leaderboard-rollups.v1.json");
10
+ export function defaultLeaderboardWindow(config) {
11
+ if (!config.durable)
12
+ return "live";
13
+ return config.durableRetentionDays >= 7 ? "7d" : "24h";
14
+ }
10
15
  const WINDOW_MS = {
11
16
  "1h": 60 * 60 * 1_000,
12
17
  "24h": 24 * 60 * 60 * 1_000,
@@ -8,8 +8,8 @@ import { CLIPROXY_PINNED_VERSION } from "@velum-labs/routekit-accounts";
8
8
  import { RouteKitControlClient } from "@velum-labs/routekit-control";
9
9
  import { ControlClient, ControlError, createServiceRecordStore } from "@velum-labs/routekit-runtime";
10
10
  import { parse as parseYaml } from "yaml";
11
- import { startRouteKitDaemon } from "../index.js";
12
11
  import { prepareAccountTransaction } from "../account-transaction.js";
12
+ import { startRouteKitDaemon } from "../index.js";
13
13
  async function mockProvider() {
14
14
  const server = createServer((req, res) => {
15
15
  if (req.url === "/v1/models") {
@@ -58,7 +58,9 @@ async function withMockAnthropicDiscovery(run) {
58
58
  globalThis.fetch = async (input, init) => {
59
59
  const url = new URL(input instanceof Request ? input.url : input.toString());
60
60
  if (url.hostname === "api.anthropic.com" && url.pathname === "/v1/models") {
61
- return new Response(JSON.stringify({ data: [{ id: "claude-test-model", type: "model" }] }), { headers: { "content-type": "application/json" } });
61
+ return new Response(JSON.stringify({ data: [{ id: "claude-test-model", type: "model" }] }), {
62
+ headers: { "content-type": "application/json" }
63
+ });
62
64
  }
63
65
  return await originalFetch(input, init);
64
66
  };
@@ -69,7 +71,7 @@ async function withMockAnthropicDiscovery(run) {
69
71
  globalThis.fetch = originalFetch;
70
72
  }
71
73
  }
72
- async function withMockNativeDiscovery(kind, run) {
74
+ async function withMockNativeDiscovery(kind, run, options = {}) {
73
75
  if (kind === "claude-code")
74
76
  return await withMockAnthropicDiscovery(run);
75
77
  const originalFetch = globalThis.fetch;
@@ -80,6 +82,16 @@ async function withMockNativeDiscovery(kind, run) {
80
82
  url.pathname.endsWith("/models")) {
81
83
  return Response.json({ models: [{ slug: "gpt-test-model" }] });
82
84
  }
85
+ if (options.healthyUsage === true &&
86
+ url.hostname === "chatgpt.com" &&
87
+ url.pathname === "/backend-api/wham/usage") {
88
+ return Response.json({
89
+ plan_type: "plus",
90
+ rate_limit: {
91
+ primary_window: { used_percent: 10, reset_at: Date.now() / 1000 + 3_600 }
92
+ }
93
+ });
94
+ }
83
95
  return await originalFetch(input, init);
84
96
  };
85
97
  try {
@@ -473,6 +485,69 @@ test("daemon account activity persists last selection independently of leaderboa
473
485
  rmSync(root, { recursive: true, force: true });
474
486
  }
475
487
  });
488
+ test("cleared persisted cooldown remains absent and eligible after daemon reload", async () => {
489
+ const root = mkdtempSync(join(tmpdir(), "routekit-daemon-cooldown-reload-"));
490
+ const stateHome = join(root, "state");
491
+ const configPath = join(root, "router.yaml");
492
+ const accountsDirectory = join(stateHome, "subscriptions", "codex");
493
+ const statePath = join(accountsDirectory, ".state.json");
494
+ const coolingUntil = Date.now() / 1000 + 3_600;
495
+ mkdirSync(accountsDirectory, { recursive: true });
496
+ writeFileSync(join(accountsDirectory, "work.json"), `${JSON.stringify(nativeCredential("codex"))}\n`);
497
+ writeFileSync(statePath, JSON.stringify({ members: [{ id: "work", coolingUntil }] }));
498
+ writeFileSync(configPath, "providers:\n codex: {}\ndefaultModel: codex/gpt-test-model\n");
499
+ try {
500
+ await withMockNativeDiscovery("codex", async () => {
501
+ const daemon = await startRouteKitDaemon({
502
+ packageVersion: "1.2.3",
503
+ stateHome,
504
+ configPath,
505
+ port: 0,
506
+ portless: false,
507
+ env: {
508
+ HOME: root,
509
+ ROUTEKIT_HOME: stateHome,
510
+ ROUTEKIT_PORTLESS: "0"
511
+ }
512
+ });
513
+ try {
514
+ const client = new RouteKitControlClient({
515
+ url: daemon.record.url,
516
+ token: daemon.record.controlToken
517
+ });
518
+ const before = await client.call("accounts.status", {});
519
+ assert.equal(before.accounts[0]?.relayOpen, false);
520
+ assert.deepEqual(before.accounts[0]?.readinessReasons, [
521
+ { code: "cooldown_active", until: coolingUntil }
522
+ ]);
523
+ const usage = await client.call("accounts.usage", {});
524
+ const recovered = usage.accountSets[0]?.members[0];
525
+ assert.equal(recovered?.coolingUntil, undefined);
526
+ assert.equal(recovered?.poolEligible, true);
527
+ assert.equal(recovered?.relayReady, true);
528
+ assert.deepEqual(recovered?.readinessReasons, []);
529
+ const persisted = JSON.parse(readFileSync(statePath, "utf8"));
530
+ assert.equal(persisted.members[0]?.coolingUntil, undefined);
531
+ assert.equal(persisted.members[0]?.cooldownRevision, 2);
532
+ const daemonStatus = await client.call("daemon.status", {});
533
+ await client.call("daemon.reload", { expectedRevision: daemonStatus.configRevision });
534
+ const afterReload = await client.call("accounts.status", {});
535
+ assert.equal(afterReload.accounts[0]?.relayOpen, true);
536
+ assert.deepEqual(afterReload.accounts[0]?.readinessReasons, []);
537
+ const afterUsage = await client.call("accounts.usage", {});
538
+ assert.equal(afterUsage.accountSets[0]?.members[0]?.coolingUntil, undefined);
539
+ assert.equal(afterUsage.accountSets[0]?.members[0]?.poolEligible, true);
540
+ assert.equal(JSON.parse(readFileSync(statePath, "utf8")).members[0]?.coolingUntil, undefined);
541
+ }
542
+ finally {
543
+ await daemon.close();
544
+ }
545
+ }, { healthyUsage: true });
546
+ }
547
+ finally {
548
+ rmSync(root, { recursive: true, force: true });
549
+ }
550
+ });
476
551
  for (const kind of ["claude-code", "codex"]) {
477
552
  test(`native ${kind} account rename preserves routing and usage state`, async () => {
478
553
  const root = mkdtempSync(join(tmpdir(), `routekit-daemon-rename-${kind}-`));
@@ -763,12 +838,7 @@ test("native removal failure before deletion cleans its prepared transaction", a
763
838
  mode: 0o600
764
839
  });
765
840
  symlinkSync(externalPath, accountPath);
766
- writeFileSync(configPath, [
767
- "providers:",
768
- " openai: {}",
769
- "defaultModel: openai/mock-model",
770
- ""
771
- ].join("\n"));
841
+ writeFileSync(configPath, ["providers:", " openai: {}", "defaultModel: openai/mock-model", ""].join("\n"));
772
842
  const upstream = await mockProvider();
773
843
  const daemon = await startRouteKitDaemon({
774
844
  packageVersion: "1.2.3",
@@ -1019,11 +1089,10 @@ test("daemon owns the cliproxy sidecar: spawn, restart, account routing, shutdow
1019
1089
  assert.ok(await waitFor(() => readFileSync(markerPath, "utf8").trim().split("\n").length === 3, 10_000), "accounts.sync did not restart the managed sidecar");
1020
1090
  assert.equal(processAlive(respawnedPid), false);
1021
1091
  const refreshedStatus = await client.call("accounts.status", {});
1022
- assert.equal(refreshedStatus.accounts.find((entry) => entry.label === "antigravity-user@example.com")?.credentialValid, true);
1023
- assert.equal(refreshedStatus.accounts.find((entry) => entry.label === "kimi-invalid")
1024
- ?.credentialValid, false);
1025
- assert.equal(refreshedStatus.accounts.find((entry) => entry.label === "broken-account")
1026
- ?.credentialValid, false);
1092
+ assert.equal(refreshedStatus.accounts.find((entry) => entry.label === "antigravity-user@example.com")
1093
+ ?.credentialValid, true);
1094
+ assert.equal(refreshedStatus.accounts.find((entry) => entry.label === "kimi-invalid")?.credentialValid, false);
1095
+ assert.equal(refreshedStatus.accounts.find((entry) => entry.label === "broken-account")?.credentialValid, false);
1027
1096
  const syncedPid = Number(readFileSync(markerPath, "utf8").trim().split("\n")[2]);
1028
1097
  // Unclassified/corrupt auth files remain removable using the kind shown
1029
1098
  // by accounts.list rather than becoming stuck in the store.
@@ -1072,7 +1141,9 @@ test("daemon owns the cliproxy sidecar: spawn, restart, account routing, shutdow
1072
1141
  }
1073
1142
  ]
1074
1143
  };
1075
- const activated = await client.call("accounts.enrollActivate", activationParams, { idempotencyKey: "activate-grok" });
1144
+ const activated = await client.call("accounts.enrollActivate", activationParams, {
1145
+ idempotencyKey: "activate-grok"
1146
+ });
1076
1147
  assert.equal(activated.activated, true);
1077
1148
  assert.equal(activated.configRevision, beforeActivation.configRevision + 1);
1078
1149
  assert.equal(activated.accountRevision, beforeActivation.accountRevision + 1);
@@ -1081,11 +1152,14 @@ test("daemon owns the cliproxy sidecar: spawn, restart, account routing, shutdow
1081
1152
  assert.equal(existsSync(join(stateHome, "account-transactions")), false);
1082
1153
  // A fresh transport retry converges on the committed state without
1083
1154
  // incrementing either revision again.
1084
- const replayed = await client.call("accounts.enrollActivate", activationParams, { idempotencyKey: "activate-grok-retry" });
1155
+ const replayed = await client.call("accounts.enrollActivate", activationParams, {
1156
+ idempotencyKey: "activate-grok-retry"
1157
+ });
1085
1158
  assert.equal(replayed.configRevision, activated.configRevision);
1086
1159
  assert.equal(replayed.accountRevision, activated.accountRevision);
1087
1160
  const activatedStatus = await client.call("accounts.status", {});
1088
- assert.equal(activatedStatus.accounts.find((entry) => entry.label === "xai-transaction@example.com")?.configured, true);
1161
+ assert.equal(activatedStatus.accounts.find((entry) => entry.label === "xai-transaction@example.com")
1162
+ ?.configured, true);
1089
1163
  const beforeClaude = await client.call("daemon.status", {});
1090
1164
  const claudeActivation = {
1091
1165
  kind: "claude-code",
@@ -1113,14 +1187,18 @@ test("daemon owns the cliproxy sidecar: spawn, restart, account routing, shutdow
1113
1187
  assert.equal((await client.call("daemon.status", {})).configRevision, beforeClaude.configRevision);
1114
1188
  assert.equal((await client.call("daemon.status", {})).accountRevision, beforeClaude.accountRevision);
1115
1189
  await withMockAnthropicDiscovery(async () => {
1116
- const claudeActivated = await client.call("accounts.enrollActivate", claudeActivation, { idempotencyKey: "activate-claude" });
1190
+ const claudeActivated = await client.call("accounts.enrollActivate", claudeActivation, {
1191
+ idempotencyKey: "activate-claude"
1192
+ });
1117
1193
  assert.equal(claudeActivated.activated, true);
1118
1194
  assert.equal(claudeActivated.configRevision, beforeClaude.configRevision + 1);
1119
1195
  assert.equal(claudeActivated.accountRevision, beforeClaude.accountRevision + 1);
1120
1196
  assert.equal(existsSync(claudePath), true);
1121
1197
  assert.match(readFileSync(configPath, "utf8"), /claude-code:/);
1122
1198
  assert.doesNotMatch(JSON.stringify(claudeActivated), /claude-transaction-access|claude-transaction-refresh/);
1123
- const claudeReplay = await client.call("accounts.enrollActivate", claudeActivation, { idempotencyKey: "activate-claude-retry" });
1199
+ const claudeReplay = await client.call("accounts.enrollActivate", claudeActivation, {
1200
+ idempotencyKey: "activate-claude-retry"
1201
+ });
1124
1202
  assert.equal(claudeReplay.configRevision, claudeActivated.configRevision);
1125
1203
  assert.equal(claudeReplay.accountRevision, claudeActivated.accountRevision);
1126
1204
  assert.equal((await client.call("accounts.status", {})).accounts.find((entry) => entry.subscriptionKind === "claude-code" && entry.label === "claude-work")?.configured, true);
@@ -4,7 +4,7 @@ import { tmpdir } from "node:os";
4
4
  import { join } from "node:path";
5
5
  import test from "node:test";
6
6
  import { AccountActivityCoordinator } from "@velum-labs/routekit-accounts";
7
- import { aggregateInspections, LeaderboardRollupStore } from "../leaderboard.js";
7
+ import { aggregateInspections, defaultLeaderboardWindow, LeaderboardRollupStore } from "../leaderboard.js";
8
8
  function inspection(input) {
9
9
  return {
10
10
  callId: input.callId,
@@ -31,6 +31,12 @@ function inspection(input) {
31
31
  }
32
32
  };
33
33
  }
34
+ test("defaultLeaderboardWindow uses the longest supported durable window", () => {
35
+ assert.equal(defaultLeaderboardWindow({ durable: false, durableRetentionDays: 14 }), "live");
36
+ assert.equal(defaultLeaderboardWindow({ durable: true, durableRetentionDays: 1 }), "24h");
37
+ assert.equal(defaultLeaderboardWindow({ durable: true, durableRetentionDays: 6 }), "24h");
38
+ assert.equal(defaultLeaderboardWindow({ durable: true, durableRetentionDays: 7 }), "7d");
39
+ });
34
40
  test("aggregateInspections ranks principals by cost and keeps unknown cost visible", () => {
35
41
  const result = aggregateInspections([
36
42
  inspection({
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@velum-labs/routekit-daemon",
3
3
  "private": false,
4
- "version": "0.16.0",
4
+ "version": "0.16.2",
5
5
  "description": "Singleton RouteKit control daemon and stable model gateway.",
6
6
  "repository": {
7
7
  "type": "git",
@@ -34,14 +34,14 @@
34
34
  ],
35
35
  "dependencies": {
36
36
  "yaml": "2.9.0",
37
- "@velum-labs/routekit-accounts": "0.16.0",
38
- "@velum-labs/routekit-config": "0.16.0",
39
- "@velum-labs/routekit-control": "0.16.0",
40
- "@velum-labs/routekit-gateway": "0.16.0",
41
- "@velum-labs/routekit-registry": "0.16.0",
42
- "@velum-labs/routekit-router": "0.16.0",
43
- "@velum-labs/routekit-runtime": "0.16.0",
44
- "@velum-labs/routekit-telemetry-core": "0.16.0"
37
+ "@velum-labs/routekit-accounts": "0.16.2",
38
+ "@velum-labs/routekit-config": "0.16.2",
39
+ "@velum-labs/routekit-control": "0.16.2",
40
+ "@velum-labs/routekit-gateway": "0.16.2",
41
+ "@velum-labs/routekit-registry": "0.16.2",
42
+ "@velum-labs/routekit-router": "0.16.2",
43
+ "@velum-labs/routekit-runtime": "0.16.2",
44
+ "@velum-labs/routekit-telemetry-core": "0.16.2"
45
45
  },
46
46
  "scripts": {
47
47
  "build": "tsc -b",