@nick3/copilot-api 1.6.0 → 1.6.3

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 (29) hide show
  1. package/dist/{account-B2tSWtVS.js → account-Db80RUHX.js} +2 -2
  2. package/dist/{account-B2tSWtVS.js.map → account-Db80RUHX.js.map} +1 -1
  3. package/dist/{accounts-manager-CAyZJSn8.js → accounts-manager-B4eOuKSK.js} +225 -293
  4. package/dist/accounts-manager-B4eOuKSK.js.map +1 -0
  5. package/dist/admin/assets/index-B2qj1asn.css +1 -0
  6. package/dist/admin/assets/index-CH72K8cb.js +107 -0
  7. package/dist/admin/assets/sse-BHNhW__Y.js +9 -0
  8. package/dist/admin/index.html +2 -2
  9. package/dist/{auth-BXCeDjRG.js → auth-Ba8K-1aX.js} +3 -3
  10. package/dist/{auth-BXCeDjRG.js.map → auth-Ba8K-1aX.js.map} +1 -1
  11. package/dist/{check-usage-CQxXYfUx.js → check-usage-ChbkyMqB.js} +3 -3
  12. package/dist/{check-usage-CQxXYfUx.js.map → check-usage-ChbkyMqB.js.map} +1 -1
  13. package/dist/{get-copilot-token-p17sJyPU.js → get-copilot-token-Buo3CA1x.js} +2 -2
  14. package/dist/{get-copilot-token-p17sJyPU.js.map → get-copilot-token-Buo3CA1x.js.map} +1 -1
  15. package/dist/main.js +3 -3
  16. package/dist/{poll-access-token-Bc6VwWab.js → poll-access-token-tKPQmH_6.js} +2 -2
  17. package/dist/{poll-access-token-Bc6VwWab.js.map → poll-access-token-tKPQmH_6.js.map} +1 -1
  18. package/dist/request-outbound-C0g49Ab6.js +505 -0
  19. package/dist/request-outbound-C0g49Ab6.js.map +1 -0
  20. package/dist/request-outbound-IimJTlvY.js +4 -0
  21. package/dist/{server-CFijvv3C.js → server-Dw9SIlHL.js} +3835 -3350
  22. package/dist/server-Dw9SIlHL.js.map +1 -0
  23. package/dist/{start-DQlnH71A.js → start-BI0sDz7p.js} +7 -6
  24. package/dist/{start-DQlnH71A.js.map → start-BI0sDz7p.js.map} +1 -1
  25. package/package.json +1 -1
  26. package/dist/accounts-manager-CAyZJSn8.js.map +0 -1
  27. package/dist/admin/assets/index-BESw8Vvd.css +0 -1
  28. package/dist/admin/assets/index-Ddo9RHg-.js +0 -101
  29. package/dist/server-CFijvv3C.js.map +0 -1
@@ -1,12 +1,11 @@
1
- import { O as accountFromState, _ as HTTPError, g as getCopilotUsage, j as consumeOutboundHeadersSnapshot, m as getGitHubUser, x as copilotModelsHeaders, y as copilotBaseUrl } from "./poll-access-token-Bc6VwWab.js";
2
- import { b as getCurrentIdentityEnvironment, c as isAccountEnabled, f as readLegacyToken, h as saveAccountToken, i as ensureAccountClientIdentity, l as listAccountsFromRegistry, o as hasLegacyToken, r as addAccountToRegistry, s as hasRegistry, u as loadAccountToken, v as buildIdentityKey, y as createAccountSessionId } from "./account-B2tSWtVS.js";
1
+ import { O as accountFromState, _ as HTTPError, g as getCopilotUsage, j as consumeOutboundHeadersSnapshot, m as getGitHubUser, x as copilotModelsHeaders, y as copilotBaseUrl } from "./poll-access-token-tKPQmH_6.js";
2
+ import { b as getCurrentIdentityEnvironment, c as isAccountEnabled, f as readLegacyToken, h as saveAccountToken, i as ensureAccountClientIdentity, l as listAccountsFromRegistry, o as hasLegacyToken, r as addAccountToRegistry, s as hasRegistry, u as loadAccountToken, v as buildIdentityKey, y as createAccountSessionId } from "./account-Db80RUHX.js";
3
3
  import { t as PATHS } from "./paths-DGlr310R.js";
4
- import { t as getCopilotToken } from "./get-copilot-token-p17sJyPU.js";
4
+ import { t as getCopilotToken } from "./get-copilot-token-Buo3CA1x.js";
5
+ import { c as getAdminDbUserVersion, i as getRequestOutboundStore, o as getAdminDb, s as getAdminDbPath } from "./request-outbound-C0g49Ab6.js";
5
6
  import consola, { consola as consola$1 } from "consola";
6
7
  import fs from "node:fs/promises";
7
- import path from "node:path";
8
8
  import fs$1 from "node:fs";
9
- import { Database } from "bun:sqlite";
10
9
 
11
10
  //#region src/lib/config.ts
12
11
  const PROVIDER_TYPE_ANTHROPIC = "anthropic";
@@ -62,7 +61,13 @@ const defaultConfig = {
62
61
  sessionAffinityRetentionDays: 7,
63
62
  useMessagesApi: true,
64
63
  useResponsesApiWebSearch: true,
65
- logLevel: "info"
64
+ logLevel: "info",
65
+ devMode: {
66
+ enabled: false,
67
+ capture4xx: false,
68
+ capture5xx: false,
69
+ captureOther: false
70
+ }
66
71
  };
67
72
  let cachedConfig = null;
68
73
  function isPlainObject(value) {
@@ -225,6 +230,25 @@ function mergeDefaultLogLevel(config) {
225
230
  changed: true
226
231
  };
227
232
  }
233
+ function mergeDefaultDevMode(config) {
234
+ const current = config.devMode;
235
+ if (current && typeof current.enabled === "boolean" && typeof current.capture4xx === "boolean" && typeof current.capture5xx === "boolean" && typeof current.captureOther === "boolean") return {
236
+ mergedConfig: config,
237
+ changed: false
238
+ };
239
+ return {
240
+ mergedConfig: {
241
+ ...config,
242
+ devMode: {
243
+ enabled: current?.enabled === true,
244
+ capture4xx: current?.capture4xx === true,
245
+ capture5xx: current?.capture5xx === true,
246
+ captureOther: current?.captureOther === true
247
+ }
248
+ },
249
+ changed: true
250
+ };
251
+ }
228
252
  function applyConfigMerges(config, mergeFns) {
229
253
  return mergeFns.reduce((acc, mergeFn) => {
230
254
  const result = mergeFn(acc.mergedConfig);
@@ -244,7 +268,8 @@ function mergeConfigWithDefaults() {
244
268
  mergeDefaultAccountAffinity,
245
269
  mergeDefaultModelRefreshInterval,
246
270
  mergeDefaultSessionAffinityRetention,
247
- mergeDefaultLogLevel
271
+ mergeDefaultLogLevel,
272
+ mergeDefaultDevMode
248
273
  ]);
249
274
  if (changed) try {
250
275
  fs$1.writeFileSync(PATHS.CONFIG_PATH, `${JSON.stringify(mergedConfig, null, 2)}\n`, "utf8");
@@ -601,11 +626,189 @@ function isAffinityAccountUsable(accountId, accounts) {
601
626
  return account;
602
627
  }
603
628
 
629
+ //#endregion
630
+ //#region src/lib/dev-mode.ts
631
+ function isDevModeEnabled() {
632
+ return getConfig().devMode?.enabled === true;
633
+ }
634
+ function isCapture4xxEnabled() {
635
+ return getConfig().devMode?.capture4xx === true;
636
+ }
637
+ function isCapture5xxEnabled() {
638
+ return getConfig().devMode?.capture5xx === true;
639
+ }
640
+ function isCaptureOtherEnabled() {
641
+ return getConfig().devMode?.captureOther === true;
642
+ }
643
+
644
+ //#endregion
645
+ //#region src/services/copilot/copilot-fetch.ts
646
+ const pendingCaptures = /* @__PURE__ */ new Map();
647
+ const pendingCapturePromises = /* @__PURE__ */ new Map();
648
+ async function flushPendingCapture(requestId) {
649
+ const pending = pendingCaptures.get(requestId);
650
+ if (pending) {
651
+ pendingCaptures.delete(requestId);
652
+ pendingCapturePromises.delete(requestId);
653
+ persistNow(pending);
654
+ return;
655
+ }
656
+ const promise = pendingCapturePromises.get(requestId);
657
+ if (promise) {
658
+ await promise;
659
+ const deferred = pendingCaptures.get(requestId);
660
+ if (deferred) {
661
+ pendingCaptures.delete(requestId);
662
+ persistNow(deferred);
663
+ }
664
+ pendingCapturePromises.delete(requestId);
665
+ }
666
+ }
667
+ function snapshotHeaders(init) {
668
+ const headers = init.headers;
669
+ if (headers instanceof Headers) {
670
+ const out$1 = {};
671
+ for (const [key, value] of headers.entries()) out$1[key] = value;
672
+ return out$1;
673
+ }
674
+ if (Array.isArray(headers)) {
675
+ const out$1 = {};
676
+ for (const [key, value] of headers) out$1[key] = value;
677
+ return out$1;
678
+ }
679
+ const out = {};
680
+ for (const [key, value] of Object.entries(headers ?? {})) out[key] = value;
681
+ return out;
682
+ }
683
+ function snapshotBody(init) {
684
+ const body = init.body;
685
+ if (body === null || body === void 0) return {
686
+ body: null,
687
+ bodyKind: "text"
688
+ };
689
+ if (typeof body === "string") try {
690
+ JSON.parse(body);
691
+ return {
692
+ body,
693
+ bodyKind: "json"
694
+ };
695
+ } catch {
696
+ return {
697
+ body,
698
+ bodyKind: "text"
699
+ };
700
+ }
701
+ if (body instanceof Uint8Array) return {
702
+ body: Buffer.from(body).toString("base64"),
703
+ bodyKind: "binary"
704
+ };
705
+ if (body instanceof ArrayBuffer) return {
706
+ body: Buffer.from(new Uint8Array(body)).toString("base64"),
707
+ bodyKind: "binary"
708
+ };
709
+ return {
710
+ body: null,
711
+ bodyKind: "text"
712
+ };
713
+ }
714
+ function shouldCaptureStatus(status) {
715
+ if (status >= 400 && status < 500) return isCapture4xxEnabled();
716
+ if (status >= 500) return isCapture5xxEnabled();
717
+ return isCaptureOtherEnabled();
718
+ }
719
+ async function copilotFetch(input, init, ctx) {
720
+ const requestSnapshot = {
721
+ url: typeof input === "string" ? input : input.toString(),
722
+ method: (init.method ?? "GET").toUpperCase(),
723
+ headers: snapshotHeaders(init),
724
+ ...snapshotBody(init)
725
+ };
726
+ const response = await fetch(input, init);
727
+ if (!(ctx.requestId !== void 0 && ctx.capturable !== false && shouldCaptureStatus(response.status))) return response;
728
+ const contentType = response.headers.get("content-type") ?? "";
729
+ const isSSE = contentType.includes("text/event-stream");
730
+ const responseHeaders = {};
731
+ for (const [key, value] of response.headers.entries()) responseHeaders[key] = value;
732
+ if (!response.body) {
733
+ storePending({
734
+ requestSnapshot,
735
+ status: response.status,
736
+ responseBody: "",
737
+ responseBodyKind: isSSE ? "sse" : "json",
738
+ responseHeaders,
739
+ ctx
740
+ });
741
+ return response;
742
+ }
743
+ const [forClient, forCapture] = response.body.tee();
744
+ const capturePromise = (async () => {
745
+ const chunks = [];
746
+ const reader = forCapture.getReader();
747
+ try {
748
+ for (;;) {
749
+ const result = await reader.read();
750
+ if (result.done) break;
751
+ const value = result.value;
752
+ if (value instanceof Uint8Array) chunks.push(value);
753
+ }
754
+ const text = Buffer.concat(chunks.map((chunk) => Buffer.from(chunk))).toString("utf8");
755
+ let responseBodyKind = "text";
756
+ if (isSSE) responseBodyKind = "sse";
757
+ else if (contentType.includes("application/json")) responseBodyKind = "json";
758
+ storePending({
759
+ requestSnapshot,
760
+ status: response.status,
761
+ responseBody: text,
762
+ responseBodyKind,
763
+ responseHeaders,
764
+ ctx
765
+ });
766
+ } catch (error) {
767
+ consola.debug("copilotFetch capture stream failed", error);
768
+ }
769
+ })();
770
+ if (ctx.requestId) pendingCapturePromises.set(ctx.requestId, capturePromise);
771
+ return new Response(forClient, {
772
+ status: response.status,
773
+ statusText: response.statusText,
774
+ headers: response.headers
775
+ });
776
+ }
777
+ function storePending(input) {
778
+ const id = input.ctx.requestId;
779
+ if (!id) return;
780
+ pendingCaptures.set(id, input);
781
+ }
782
+ function persistNow({ requestSnapshot, status, responseBody, responseBodyKind, responseHeaders, ctx }) {
783
+ if (!ctx.requestId) return;
784
+ try {
785
+ getRequestOutboundStore().insert({
786
+ requestId: ctx.requestId,
787
+ httpStatus: status,
788
+ upstreamUrl: requestSnapshot.url,
789
+ upstreamMethod: requestSnapshot.method,
790
+ requestHeaders: requestSnapshot.headers,
791
+ requestBody: requestSnapshot.body,
792
+ requestBodyKind: requestSnapshot.bodyKind,
793
+ responseStatus: status,
794
+ responseHeaders,
795
+ responseBody,
796
+ responseBodyKind
797
+ });
798
+ } catch (error) {
799
+ consola.debug("copilotFetch persist failed", error);
800
+ }
801
+ }
802
+
604
803
  //#endregion
605
804
  //#region src/services/copilot/get-models.ts
606
- const getModels = async (account) => {
805
+ const getModels = async (account, options) => {
607
806
  const ctx = account ?? accountFromState();
608
- const response = await fetch(`${copilotBaseUrl(ctx)}/models`, { headers: copilotModelsHeaders(ctx) });
807
+ const response = await copilotFetch(`${copilotBaseUrl(ctx)}/models`, { headers: copilotModelsHeaders(ctx) }, {
808
+ requestId: options?.requestId,
809
+ callSite: "models",
810
+ capturable: false
811
+ });
609
812
  if (!response.ok) {
610
813
  const errorText = await response.clone().text();
611
814
  consola.error("Failed to get models response body", errorText);
@@ -726,288 +929,6 @@ const releasePremiumReservation = (account, reservation) => {
726
929
  if (reservations.size === 0) account.premiumReservations = void 0;
727
930
  };
728
931
 
729
- //#endregion
730
- //#region src/lib/admin-db.ts
731
- const DEFAULT_DB_PATH = path.join(PATHS.APP_DIR, "admin.sqlite");
732
- let sharedDb = null;
733
- let initialized = false;
734
- const INIT_WARN_THROTTLE_MS = 3e4;
735
- let lastInitWarnAtMs = 0;
736
- let suppressedInitWarnCount = 0;
737
- function warnAdminDbInitFailure(error) {
738
- const now = Date.now();
739
- if (now - lastInitWarnAtMs < INIT_WARN_THROTTLE_MS) {
740
- suppressedInitWarnCount++;
741
- return;
742
- }
743
- const suppressed = suppressedInitWarnCount;
744
- suppressedInitWarnCount = 0;
745
- lastInitWarnAtMs = now;
746
- const suffix = suppressed > 0 ? ` (suppressed ${suppressed} similar errors)` : "";
747
- consola.warn(`Failed to initialize admin DB; admin features disabled${suffix}`, error);
748
- }
749
- function getAdminDbPath() {
750
- return DEFAULT_DB_PATH;
751
- }
752
- function openAdminDb(filePath = DEFAULT_DB_PATH) {
753
- return new Database(filePath);
754
- }
755
- function initAdminDb(db) {
756
- db.run("PRAGMA journal_mode = WAL;");
757
- db.run("PRAGMA synchronous = NORMAL;");
758
- db.run("PRAGMA busy_timeout = 3000;");
759
- db.run("PRAGMA foreign_keys = ON;");
760
- migrateAdminDb(db);
761
- }
762
- function getAdminDb() {
763
- if (!sharedDb) sharedDb = openAdminDb();
764
- if (!initialized) try {
765
- initAdminDb(sharedDb);
766
- initialized = true;
767
- } catch (error) {
768
- warnAdminDbInitFailure(error);
769
- }
770
- return sharedDb;
771
- }
772
- function getAdminDbUserVersion(db = getAdminDb()) {
773
- try {
774
- return db.query("PRAGMA user_version;").get()?.user_version ?? 0;
775
- } catch {
776
- return 0;
777
- }
778
- }
779
- function hasRequestLogColumn(db, columnName) {
780
- return db.query("PRAGMA table_info(request_log);").all().some((row) => row.name === columnName);
781
- }
782
- function migrateV1(db) {
783
- db.run(`
784
- CREATE TABLE IF NOT EXISTS request_log (
785
- id INTEGER PRIMARY KEY AUTOINCREMENT,
786
- request_id TEXT NOT NULL UNIQUE,
787
-
788
- started_at_ms INTEGER NOT NULL,
789
- finished_at_ms INTEGER,
790
- duration_ms INTEGER,
791
- ttfb_ms INTEGER,
792
-
793
- method TEXT NOT NULL,
794
- path TEXT NOT NULL,
795
- upstream_endpoint TEXT,
796
- stream INTEGER NOT NULL DEFAULT 0,
797
-
798
- account_id TEXT,
799
- account_type TEXT,
800
- cost_units REAL,
801
- client_model TEXT,
802
- upstream_model TEXT,
803
-
804
- client_ip TEXT,
805
- client_ip_source TEXT,
806
- user_agent TEXT,
807
-
808
- tokens_input INTEGER,
809
- tokens_output INTEGER,
810
- tokens_total INTEGER,
811
- tokens_cached_input INTEGER,
812
- usage_json TEXT,
813
-
814
- premium_remaining_before REAL,
815
- premium_remaining_after REAL,
816
- premium_remaining_diff REAL,
817
- premium_unlimited_before INTEGER,
818
- premium_unlimited_after INTEGER,
819
-
820
- http_status INTEGER,
821
- error_name TEXT,
822
- error_status INTEGER,
823
- error_message TEXT,
824
- selection_failure_reason TEXT
825
- );
826
-
827
- CREATE INDEX IF NOT EXISTS idx_request_log_started_at
828
- ON request_log(started_at_ms DESC);
829
- CREATE INDEX IF NOT EXISTS idx_request_log_account_started_at
830
- ON request_log(account_id, started_at_ms DESC);
831
- CREATE INDEX IF NOT EXISTS idx_request_log_model_started_at
832
- ON request_log(upstream_model, started_at_ms DESC);
833
- CREATE INDEX IF NOT EXISTS idx_request_log_endpoint_started_at
834
- ON request_log(upstream_endpoint, started_at_ms DESC);
835
- CREATE INDEX IF NOT EXISTS idx_request_log_status_started_at
836
- ON request_log(http_status, started_at_ms DESC);
837
-
838
- PRAGMA user_version = 1;
839
- `);
840
- }
841
- function migrateV9(db) {
842
- db.run(`
843
- CREATE TABLE IF NOT EXISTS daily_premium_stats (
844
- date TEXT NOT NULL,
845
- account_id TEXT NOT NULL,
846
- request_count INTEGER NOT NULL DEFAULT 0,
847
- cost_units_sum REAL NOT NULL DEFAULT 0,
848
- tokens_total INTEGER NOT NULL DEFAULT 0,
849
- error_count INTEGER NOT NULL DEFAULT 0,
850
- updated_at_ms INTEGER NOT NULL,
851
- PRIMARY KEY (date, account_id)
852
- );
853
-
854
- CREATE INDEX IF NOT EXISTS idx_daily_premium_stats_date
855
- ON daily_premium_stats(date);
856
- `);
857
- if (db.query("SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'request_log' LIMIT 1;").get()) {
858
- const nowMs = Date.now();
859
- db.run(`INSERT INTO daily_premium_stats
860
- (date, account_id, request_count, cost_units_sum, tokens_total, error_count, updated_at_ms)
861
- SELECT
862
- date(started_at_ms / 1000, 'unixepoch', 'localtime') AS date,
863
- account_id,
864
- COUNT(*) AS request_count,
865
- SUM(cost_units) AS cost_units_sum,
866
- COALESCE(SUM(tokens_total), 0) AS tokens_total,
867
- SUM(CASE WHEN error_name IS NOT NULL THEN 1 ELSE 0 END) AS error_count,
868
- ? AS updated_at_ms
869
- FROM request_log
870
- WHERE cost_units > 0
871
- AND account_id IS NOT NULL
872
- GROUP BY 1, 2
873
- ON CONFLICT(date, account_id) DO UPDATE SET
874
- request_count = excluded.request_count,
875
- cost_units_sum = excluded.cost_units_sum,
876
- tokens_total = excluded.tokens_total,
877
- error_count = excluded.error_count,
878
- updated_at_ms = excluded.updated_at_ms;`, [nowMs]);
879
- }
880
- db.run("PRAGMA user_version = 9;");
881
- }
882
- function migrateV8(db) {
883
- db.run(`
884
- CREATE TABLE IF NOT EXISTS session_affinity (
885
- cache_key TEXT PRIMARY KEY,
886
- account_id TEXT NOT NULL,
887
- created_at_ms INTEGER NOT NULL,
888
- last_confirmed_at_ms INTEGER NOT NULL,
889
- last_used_at_ms INTEGER NOT NULL
890
- );
891
-
892
- CREATE INDEX IF NOT EXISTS idx_session_affinity_last_used
893
- ON session_affinity(last_used_at_ms);
894
-
895
- CREATE INDEX IF NOT EXISTS idx_session_affinity_account
896
- ON session_affinity(account_id);
897
-
898
- PRAGMA user_version = 8;
899
- `);
900
- }
901
- function migrateV10(db) {
902
- db.run(`
903
- CREATE TABLE IF NOT EXISTS quota_snapshots (
904
- id INTEGER PRIMARY KEY AUTOINCREMENT,
905
- account_id TEXT NOT NULL,
906
- snapshot_at_ms INTEGER NOT NULL,
907
- remaining INTEGER NOT NULL,
908
- entitlement INTEGER NOT NULL,
909
- unlimited INTEGER NOT NULL DEFAULT 0,
910
- source TEXT NOT NULL DEFAULT 'refresh'
911
- );
912
-
913
- CREATE INDEX IF NOT EXISTS idx_quota_snapshots_account_time
914
- ON quota_snapshots(account_id, snapshot_at_ms);
915
-
916
- CREATE INDEX IF NOT EXISTS idx_quota_snapshots_time
917
- ON quota_snapshots(snapshot_at_ms);
918
- `);
919
- if (db.query("SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'request_log' LIMIT 1;").get()) db.run(`
920
- INSERT INTO quota_snapshots
921
- (account_id, snapshot_at_ms, remaining, entitlement, unlimited, source)
922
- SELECT
923
- account_id,
924
- finished_at_ms,
925
- CAST(premium_remaining_after AS INTEGER),
926
- 0,
927
- COALESCE(premium_unlimited_after, 0),
928
- 'backfill'
929
- FROM request_log
930
- WHERE premium_remaining_after IS NOT NULL
931
- AND account_id IS NOT NULL
932
- AND finished_at_ms IS NOT NULL
933
- ORDER BY finished_at_ms;
934
- `);
935
- db.run("PRAGMA user_version = 10;");
936
- }
937
- function migrateV11(db) {
938
- for (const columnName of [
939
- "outbound_x_request_id",
940
- "outbound_x_agent_task_id",
941
- "outbound_x_interaction_type",
942
- "outbound_openai_intent",
943
- "outbound_user_agent"
944
- ]) if (!hasRequestLogColumn(db, columnName)) db.run(`ALTER TABLE request_log ADD COLUMN ${columnName} TEXT;`);
945
- db.run("PRAGMA user_version = 11;");
946
- }
947
- function migrateV8ToV11(db, current) {
948
- if (current < 8) migrateV8(db);
949
- if (current < 9) migrateV9(db);
950
- if (current < 10) migrateV10(db);
951
- if (current < 11) migrateV11(db);
952
- }
953
- function migrateAdminDb(db) {
954
- const current = db.query("PRAGMA user_version;").get()?.user_version ?? 0;
955
- if (current >= 11) return;
956
- if (current < 1) migrateV1(db);
957
- if (current < 2) db.run(`
958
- ALTER TABLE request_log ADD COLUMN user_id TEXT;
959
- ALTER TABLE request_log ADD COLUMN safety_identifier TEXT;
960
- ALTER TABLE request_log ADD COLUMN prompt_cache_key TEXT;
961
- ALTER TABLE request_log ADD COLUMN initiator TEXT;
962
- ALTER TABLE request_log ADD COLUMN upstream_request_id TEXT;
963
-
964
- PRAGMA user_version = 2;
965
- `);
966
- if (current < 3) db.run(`
967
- CREATE INDEX IF NOT EXISTS idx_request_log_session_finished
968
- ON request_log(
969
- prompt_cache_key,
970
- safety_identifier,
971
- finished_at_ms DESC
972
- )
973
- WHERE finished_at_ms IS NOT NULL
974
- AND tokens_input IS NOT NULL;
975
-
976
- PRAGMA user_version = 3;
977
- `);
978
- if (current < 4) db.run(`
979
- CREATE INDEX IF NOT EXISTS idx_request_log_session_finished_by_client_model
980
- ON request_log(
981
- prompt_cache_key,
982
- safety_identifier,
983
- client_model,
984
- finished_at_ms DESC
985
- )
986
- WHERE finished_at_ms IS NOT NULL
987
- AND tokens_input IS NOT NULL;
988
-
989
- PRAGMA user_version = 4;
990
- `);
991
- if (current < 5) db.run(`
992
- ALTER TABLE request_log ADD COLUMN affinity_hit INTEGER;
993
- ALTER TABLE request_log ADD COLUMN affinity_cache_key TEXT;
994
-
995
- PRAGMA user_version = 5;
996
- `);
997
- if (current < 6) {
998
- if (!hasRequestLogColumn(db, "is_subagent")) db.run("ALTER TABLE request_log ADD COLUMN is_subagent INTEGER;");
999
- db.run("PRAGMA user_version = 6;");
1000
- }
1001
- if (current < 7) {
1002
- if (!hasRequestLogColumn(db, "affinity_key_used")) db.run("ALTER TABLE request_log ADD COLUMN affinity_key_used TEXT;");
1003
- if (!hasRequestLogColumn(db, "affinity_key_source")) db.run("ALTER TABLE request_log ADD COLUMN affinity_key_source TEXT;");
1004
- if (!hasRequestLogColumn(db, "selection_reason")) db.run("ALTER TABLE request_log ADD COLUMN selection_reason TEXT;");
1005
- if (!hasRequestLogColumn(db, "upstream_error_message_raw")) db.run("ALTER TABLE request_log ADD COLUMN upstream_error_message_raw TEXT;");
1006
- db.run("PRAGMA user_version = 7;");
1007
- }
1008
- migrateV8ToV11(db, current);
1009
- }
1010
-
1011
932
  //#endregion
1012
933
  //#region src/lib/stats-store.ts
1013
934
  const DEFAULT_STATS_RETENTION_DAYS = 180;
@@ -1609,6 +1530,7 @@ var RequestHistoryStore = class {
1609
1530
  } catch (error) {
1610
1531
  consola.debug("Failed to cleanup request_log retention", error);
1611
1532
  }
1533
+ import("./request-outbound-IimJTlvY.js").then((m) => m.getRequestOutboundStore().cleanupOrphans()).catch(() => {});
1612
1534
  }
1613
1535
  meta() {
1614
1536
  return {
@@ -2693,6 +2615,16 @@ var AccountsManager = class {
2693
2615
  }
2694
2616
  }
2695
2617
  /**
2618
+ * Get account context by account ID.
2619
+ * Returns null if no account with the given ID exists.
2620
+ */
2621
+ getAccountContextById(id) {
2622
+ if (this.temporaryAccount && this.temporaryAccount.id === id) return this.toAccountContext(this.temporaryAccount);
2623
+ const account = this.accounts.get(id);
2624
+ if (account) return this.toAccountContext(account);
2625
+ return null;
2626
+ }
2627
+ /**
2696
2628
  * Get account context by index.
2697
2629
  * Index 0 is the temporary account (if exists), otherwise the first registered account.
2698
2630
  * Returns null if index is out of bounds.
@@ -2928,5 +2860,5 @@ var AccountsManager = class {
2928
2860
  const accountsManager = new AccountsManager({ persistentAffinityStore: getSharedSessionAffinityStore });
2929
2861
 
2930
2862
  //#endregion
2931
- export { isResponsesApiWebSearchEnabled as A, getReasoningEffortForModel as C, isMessageStartInputTokensFallbackEnabled as D, isForceAgentEnabled as E, resolveModelAlias as M, shouldCompactUseSmallModel as N, isMessagesApiEnabled as O, getProviderConfig as S, isAccountAffinityEnabled as T, getExtraPromptForModel as _, getClientIpInfo as a, getModelAliasesInfo as b, normalizeChatCompletionsUsage as c, toLocalDateString as d, PROVIDER_TYPE_ANTHROPIC as f, getConfig as g, getClaudeTokenMultiplier as h, extractResponsesUsageFromStreamEvent as i, mergeConfigWithDefaults as j, isResponsesApiContextManagementModel as k, normalizeEmbeddingsUsage as l, getAnthropicApiKey as m, applySharedSessionAffinityRetention as n, getRequestHistoryStore as o, getAliasTargetSet as p, extractResponsesUsageFromResult as r, getStatsStore as s, accountsManager as t, normalizeMessagesUsage as u, getLogLevel as v, getSmallModel as w, getModelRefreshIntervalMs as x, getModelAliases as y };
2932
- //# sourceMappingURL=accounts-manager-CAyZJSn8.js.map
2863
+ export { isMessageStartInputTokensFallbackEnabled as A, getModelAliasesInfo as C, getSmallModel as D, getReasoningEffortForModel as E, resolveModelAlias as F, shouldCompactUseSmallModel as I, isResponsesApiContextManagementModel as M, isResponsesApiWebSearchEnabled as N, isAccountAffinityEnabled as O, mergeConfigWithDefaults as P, getModelAliases as S, getProviderConfig as T, getAnthropicApiKey as _, getClientIpInfo as a, getExtraPromptForModel as b, normalizeChatCompletionsUsage as c, toLocalDateString as d, copilotFetch as f, getAliasTargetSet as g, PROVIDER_TYPE_ANTHROPIC as h, extractResponsesUsageFromStreamEvent as i, isMessagesApiEnabled as j, isForceAgentEnabled as k, normalizeEmbeddingsUsage as l, isDevModeEnabled as m, applySharedSessionAffinityRetention as n, getRequestHistoryStore as o, flushPendingCapture as p, extractResponsesUsageFromResult as r, getStatsStore as s, accountsManager as t, normalizeMessagesUsage as u, getClaudeTokenMultiplier as v, getModelRefreshIntervalMs as w, getLogLevel as x, getConfig as y };
2864
+ //# sourceMappingURL=accounts-manager-B4eOuKSK.js.map