offrouter-core 0.2.1 → 0.2.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.
Files changed (139) hide show
  1. package/dist/audit.d.ts +137 -0
  2. package/dist/audit.d.ts.map +1 -0
  3. package/dist/audit.js +320 -0
  4. package/dist/audit.js.map +1 -0
  5. package/dist/auth/credential-chain.d.ts +84 -0
  6. package/dist/auth/credential-chain.d.ts.map +1 -0
  7. package/dist/auth/credential-chain.js +150 -0
  8. package/dist/auth/credential-chain.js.map +1 -0
  9. package/dist/auth/index.d.ts +10 -0
  10. package/dist/auth/index.d.ts.map +1 -0
  11. package/dist/auth/index.js +7 -0
  12. package/dist/auth/index.js.map +1 -0
  13. package/dist/auth/keychain.d.ts +60 -0
  14. package/dist/auth/keychain.d.ts.map +1 -0
  15. package/dist/auth/keychain.js +104 -0
  16. package/dist/auth/keychain.js.map +1 -0
  17. package/dist/auth/oauth-pkce.d.ts +138 -0
  18. package/dist/auth/oauth-pkce.d.ts.map +1 -0
  19. package/dist/auth/oauth-pkce.js +375 -0
  20. package/dist/auth/oauth-pkce.js.map +1 -0
  21. package/dist/auth/oauth-server.d.ts +36 -0
  22. package/dist/auth/oauth-server.d.ts.map +1 -0
  23. package/dist/auth/oauth-server.js +210 -0
  24. package/dist/auth/oauth-server.js.map +1 -0
  25. package/dist/config.d.ts +76 -0
  26. package/dist/config.d.ts.map +1 -0
  27. package/dist/config.js +355 -0
  28. package/dist/config.js.map +1 -0
  29. package/dist/delegation.d.ts +123 -0
  30. package/dist/delegation.d.ts.map +1 -0
  31. package/dist/delegation.js +455 -0
  32. package/dist/delegation.js.map +1 -0
  33. package/dist/index.d.ts +41 -0
  34. package/dist/index.d.ts.map +1 -0
  35. package/dist/index.js +26 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/policy.d.ts +45 -0
  38. package/dist/policy.d.ts.map +1 -0
  39. package/dist/policy.js +318 -0
  40. package/dist/policy.js.map +1 -0
  41. package/{src/protocol.ts → dist/protocol.d.ts} +2 -2
  42. package/dist/protocol.d.ts.map +1 -0
  43. package/dist/protocol.js +6 -0
  44. package/dist/protocol.js.map +1 -0
  45. package/dist/providers/adapter.d.ts +137 -0
  46. package/dist/providers/adapter.d.ts.map +1 -0
  47. package/dist/providers/adapter.js +163 -0
  48. package/dist/providers/adapter.js.map +1 -0
  49. package/dist/providers/catalog-data.d.ts +128 -0
  50. package/dist/providers/catalog-data.d.ts.map +1 -0
  51. package/dist/providers/catalog-data.js +397 -0
  52. package/dist/providers/catalog-data.js.map +1 -0
  53. package/dist/providers/catalog.d.ts +63 -0
  54. package/dist/providers/catalog.d.ts.map +1 -0
  55. package/dist/providers/catalog.js +394 -0
  56. package/dist/providers/catalog.js.map +1 -0
  57. package/dist/providers/fake.d.ts +46 -0
  58. package/dist/providers/fake.d.ts.map +1 -0
  59. package/dist/providers/fake.js +234 -0
  60. package/dist/providers/fake.js.map +1 -0
  61. package/dist/providers/openai-compatible.d.ts +65 -0
  62. package/dist/providers/openai-compatible.d.ts.map +1 -0
  63. package/dist/providers/openai-compatible.js +434 -0
  64. package/dist/providers/openai-compatible.js.map +1 -0
  65. package/dist/proxy/responses-mapper.d.ts +366 -0
  66. package/dist/proxy/responses-mapper.d.ts.map +1 -0
  67. package/dist/proxy/responses-mapper.js +517 -0
  68. package/dist/proxy/responses-mapper.js.map +1 -0
  69. package/dist/proxy/responses-server.d.ts +29 -0
  70. package/dist/proxy/responses-server.d.ts.map +1 -0
  71. package/dist/proxy/responses-server.js +360 -0
  72. package/dist/proxy/responses-server.js.map +1 -0
  73. package/dist/router.d.ts +18 -0
  74. package/dist/router.d.ts.map +1 -0
  75. package/dist/router.js +296 -0
  76. package/dist/router.js.map +1 -0
  77. package/dist/schemas.d.ts +560 -0
  78. package/dist/schemas.d.ts.map +1 -0
  79. package/{src/schemas.ts → dist/schemas.js} +83 -103
  80. package/dist/schemas.js.map +1 -0
  81. package/dist/secrets.d.ts +112 -0
  82. package/dist/secrets.d.ts.map +1 -0
  83. package/dist/secrets.js +326 -0
  84. package/dist/secrets.js.map +1 -0
  85. package/dist/types.d.ts +117 -0
  86. package/dist/types.d.ts.map +1 -0
  87. package/dist/types.js +6 -0
  88. package/dist/types.js.map +1 -0
  89. package/dist/usage-file.d.ts +59 -0
  90. package/dist/usage-file.d.ts.map +1 -0
  91. package/dist/usage-file.js +316 -0
  92. package/dist/usage-file.js.map +1 -0
  93. package/dist/usage.d.ts +235 -0
  94. package/dist/usage.d.ts.map +1 -0
  95. package/dist/usage.js +517 -0
  96. package/dist/usage.js.map +1 -0
  97. package/package.json +7 -2
  98. package/src/audit.test.ts +0 -302
  99. package/src/audit.ts +0 -553
  100. package/src/auth/credential-chain.test.ts +0 -326
  101. package/src/auth/credential-chain.ts +0 -235
  102. package/src/auth/index.ts +0 -45
  103. package/src/auth/keychain.test.ts +0 -265
  104. package/src/auth/keychain.ts +0 -168
  105. package/src/auth/oauth-pkce.test.ts +0 -329
  106. package/src/auth/oauth-pkce.ts +0 -571
  107. package/src/auth/oauth-server.test.ts +0 -83
  108. package/src/auth/oauth-server.ts +0 -296
  109. package/src/config.test.ts +0 -479
  110. package/src/config.ts +0 -505
  111. package/src/delegation.test.ts +0 -368
  112. package/src/delegation.ts +0 -605
  113. package/src/index.ts +0 -280
  114. package/src/policy.test.ts +0 -634
  115. package/src/policy.ts +0 -420
  116. package/src/providers/adapter.test.ts +0 -293
  117. package/src/providers/adapter.ts +0 -328
  118. package/src/providers/catalog-data.test.ts +0 -258
  119. package/src/providers/catalog-data.ts +0 -498
  120. package/src/providers/catalog.test.ts +0 -84
  121. package/src/providers/catalog.ts +0 -483
  122. package/src/providers/fake.ts +0 -312
  123. package/src/providers/openai-compatible.test.ts +0 -366
  124. package/src/providers/openai-compatible.ts +0 -554
  125. package/src/proxy/responses-mapper.test.ts +0 -290
  126. package/src/proxy/responses-mapper.ts +0 -736
  127. package/src/proxy/responses-server.test.ts +0 -322
  128. package/src/proxy/responses-server.ts +0 -469
  129. package/src/router.test.ts +0 -699
  130. package/src/router.ts +0 -352
  131. package/src/schemas.test.ts +0 -291
  132. package/src/secrets.test.ts +0 -271
  133. package/src/secrets.ts +0 -461
  134. package/src/types.ts +0 -173
  135. package/src/usage-file.test.ts +0 -243
  136. package/src/usage-file.ts +0 -435
  137. package/src/usage.test.ts +0 -335
  138. package/src/usage.ts +0 -859
  139. package/tsconfig.json +0 -9
@@ -0,0 +1,234 @@
1
+ /**
2
+ * Deterministic fake provider adapter for offline tests and MCP demos.
3
+ * Supports one-shot, streaming, configured errors, and cancellation.
4
+ */
5
+ import { ProviderError, } from "./adapter.js";
6
+ const DEFAULT_MODELS = [
7
+ {
8
+ modelId: "fake-coder",
9
+ displayName: "Fake Coder",
10
+ supportsTools: true,
11
+ supportsStreaming: true,
12
+ supportsJson: true,
13
+ supportsImages: false,
14
+ contextWindowTokens: 32_768,
15
+ maxOutputTokens: 8_192,
16
+ estimatedCostUsd: 0,
17
+ },
18
+ ];
19
+ function sleep(ms, signal) {
20
+ if (ms <= 0)
21
+ return Promise.resolve();
22
+ return new Promise((resolve, reject) => {
23
+ if (signal?.aborted) {
24
+ reject(new ProviderError({
25
+ code: "cancelled",
26
+ message: "aborted",
27
+ retryable: false,
28
+ }));
29
+ return;
30
+ }
31
+ const timer = setTimeout(() => {
32
+ signal?.removeEventListener("abort", onAbort);
33
+ resolve();
34
+ }, ms);
35
+ const onAbort = () => {
36
+ clearTimeout(timer);
37
+ signal?.removeEventListener("abort", onAbort);
38
+ reject(new ProviderError({
39
+ code: "cancelled",
40
+ message: "aborted",
41
+ retryable: false,
42
+ }));
43
+ };
44
+ signal?.addEventListener("abort", onAbort, { once: true });
45
+ });
46
+ }
47
+ export class FakeProviderAdapter {
48
+ id;
49
+ options;
50
+ active = new Map();
51
+ cancelled = new Set();
52
+ constructor(options = {}) {
53
+ this.id = options.id ?? "fake";
54
+ this.options = {
55
+ authTier: options.authTier ?? "api-key",
56
+ hasApiKey: options.hasApiKey ?? true,
57
+ limitsDiscoverable: options.limitsDiscoverable ?? true,
58
+ opaqueLimits: options.opaqueLimits ?? false,
59
+ responseText: options.responseText ?? "fake-ok",
60
+ streamChunks: options.streamChunks ?? ["fake ", "stream ", "ok"],
61
+ streamDelayMs: options.streamDelayMs ?? 0,
62
+ hangUntilCancel: options.hangUntilCancel ?? false,
63
+ estimatedCostUsd: options.estimatedCostUsd ?? 0,
64
+ ...options,
65
+ };
66
+ }
67
+ async listModels() {
68
+ return (this.options.models ?? DEFAULT_MODELS).map((m) => ({ ...m }));
69
+ }
70
+ async checkAuth() {
71
+ const tier = this.options.authTier;
72
+ const hasApiKey = tier === "api-key" ? this.options.hasApiKey : false;
73
+ return {
74
+ authTier: tier,
75
+ authScope: tier === "api-key" ? "third-party" : "first-party",
76
+ configured: tier === "local" || tier === "subscription" ? true : hasApiKey,
77
+ hasApiKey,
78
+ subscriptionStatus: tier === "subscription" ? "active" : undefined,
79
+ limitsDiscoverable: this.options.limitsDiscoverable,
80
+ health: "healthy",
81
+ credentialSource: hasApiKey ? "config" : "none",
82
+ subscriptionEligible: tier === "subscription",
83
+ };
84
+ }
85
+ async queryLimits(authTier) {
86
+ if (this.options.opaqueLimits || !this.options.limitsDiscoverable) {
87
+ return {
88
+ authTier,
89
+ discoverable: false,
90
+ opaque: true,
91
+ metadata: {
92
+ reason: "provider_does_not_expose_quota",
93
+ },
94
+ };
95
+ }
96
+ return {
97
+ authTier,
98
+ discoverable: true,
99
+ opaque: false,
100
+ remaining: this.options.remaining ?? 100,
101
+ limit: this.options.limit ?? 100,
102
+ unit: "requests",
103
+ resetAt: "1970-01-01T01:00:00.000Z",
104
+ metadata: {
105
+ source: "fake",
106
+ },
107
+ };
108
+ }
109
+ async estimate(request, model, authTier) {
110
+ void request;
111
+ return {
112
+ model,
113
+ authTier,
114
+ estimatedCostUsd: authTier === "api-key" ? this.options.estimatedCostUsd : 0,
115
+ currency: "USD",
116
+ note: "fake estimate",
117
+ };
118
+ }
119
+ async *invoke(request) {
120
+ if (this.cancelled.has(request.callId) || request.signal?.aborted) {
121
+ yield {
122
+ type: "error",
123
+ callId: request.callId,
124
+ error: new ProviderError({
125
+ code: "cancelled",
126
+ message: `call ${request.callId} cancelled`,
127
+ retryable: false,
128
+ }),
129
+ };
130
+ return;
131
+ }
132
+ const controller = new AbortController();
133
+ this.active.set(request.callId, controller);
134
+ const onExternalAbort = () => controller.abort();
135
+ request.signal?.addEventListener("abort", onExternalAbort, { once: true });
136
+ try {
137
+ yield {
138
+ type: "start",
139
+ callId: request.callId,
140
+ model: request.model,
141
+ };
142
+ if (this.options.error) {
143
+ yield {
144
+ type: "error",
145
+ callId: request.callId,
146
+ error: this.options.error,
147
+ };
148
+ return;
149
+ }
150
+ if (this.options.hangUntilCancel) {
151
+ await sleep(60_000, controller.signal);
152
+ }
153
+ if (this.cancelled.has(request.callId) || controller.signal.aborted) {
154
+ yield {
155
+ type: "error",
156
+ callId: request.callId,
157
+ error: new ProviderError({
158
+ code: "cancelled",
159
+ message: `call ${request.callId} cancelled`,
160
+ retryable: false,
161
+ }),
162
+ };
163
+ return;
164
+ }
165
+ const stream = request.stream ?? false;
166
+ if (stream) {
167
+ for (const chunk of this.options.streamChunks) {
168
+ if (this.cancelled.has(request.callId) || controller.signal.aborted) {
169
+ yield {
170
+ type: "error",
171
+ callId: request.callId,
172
+ error: new ProviderError({
173
+ code: "cancelled",
174
+ message: `call ${request.callId} cancelled`,
175
+ retryable: false,
176
+ }),
177
+ };
178
+ return;
179
+ }
180
+ if (this.options.streamDelayMs > 0) {
181
+ await sleep(this.options.streamDelayMs, controller.signal);
182
+ }
183
+ yield {
184
+ type: "text-delta",
185
+ callId: request.callId,
186
+ text: chunk,
187
+ };
188
+ }
189
+ }
190
+ else {
191
+ yield {
192
+ type: "text-delta",
193
+ callId: request.callId,
194
+ text: this.options.responseText,
195
+ };
196
+ }
197
+ yield {
198
+ type: "usage",
199
+ callId: request.callId,
200
+ inputTokens: 10,
201
+ outputTokens: 5,
202
+ totalTokens: 15,
203
+ };
204
+ yield {
205
+ type: "done",
206
+ callId: request.callId,
207
+ finishReason: "stop",
208
+ };
209
+ }
210
+ catch (err) {
211
+ if (err instanceof ProviderError && err.code === "cancelled") {
212
+ yield {
213
+ type: "error",
214
+ callId: request.callId,
215
+ error: err,
216
+ };
217
+ return;
218
+ }
219
+ throw err;
220
+ }
221
+ finally {
222
+ request.signal?.removeEventListener("abort", onExternalAbort);
223
+ this.active.delete(request.callId);
224
+ }
225
+ }
226
+ async cancel(callId) {
227
+ this.cancelled.add(callId);
228
+ this.active.get(callId)?.abort();
229
+ }
230
+ }
231
+ export function createFakeProvider(options) {
232
+ return new FakeProviderAdapter(options);
233
+ }
234
+ //# sourceMappingURL=fake.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fake.js","sourceRoot":"","sources":["../../src/providers/fake.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * OpenAI-compatible HTTP adapter (OpenRouter / xAI / Ollama shapes).
3
+ * Tests inject fetch; live network only when caller enables it.
4
+ *
5
+ * Auth is presence-only: we set Authorization when a key is provided.
6
+ * Ollama accepts a dummy key when none is configured.
7
+ */
8
+ import type { AuthTier, RouteRequest } from "../types.js";
9
+ import { type AuthStatus, type CostEstimate, type LimitSnapshot, type ModelCapability, type ProviderAdapter, type ProviderEvent, type ProviderInvokeRequest } from "./adapter.js";
10
+ import type { SecretStore } from "../secrets.js";
11
+ import type { CredentialSource } from "../auth/credential-chain.js";
12
+ export type OpenAiCompatibleFlavor = "openai" | "openrouter" | "xai" | "ollama";
13
+ export interface OpenAiCompatibleOptions {
14
+ id: string;
15
+ baseUrl: string;
16
+ flavor?: OpenAiCompatibleFlavor;
17
+ /** Presence-only: empty string/undefined means unconfigured for api-key flavors. */
18
+ apiKey?: string;
19
+ /**
20
+ * Ollama and some local servers ignore auth; when true (default for ollama),
21
+ * send Bearer ollama or dummy if no key is set.
22
+ */
23
+ allowDummyKey?: boolean;
24
+ authTier?: AuthTier;
25
+ defaultHeaders?: Record<string, string>;
26
+ /** Injected fetch for tests. Defaults to globalThis.fetch. */
27
+ fetch?: typeof globalThis.fetch;
28
+ /** Optional static models for offline listModels. */
29
+ models?: ModelCapability[];
30
+ /** Opaque limits by default for remote SaaS; ollama is discoverable offline. */
31
+ opaqueLimits?: boolean;
32
+ estimatedCostUsdPer1kTokens?: number;
33
+ /**
34
+ * Optional credential chain sources for checkAuth resolution.
35
+ * When set, checkAuth will try these sources in order to find a credential.
36
+ */
37
+ credentialSources?: CredentialSource[];
38
+ /**
39
+ * Optional secret store for keychain-backed credential resolution.
40
+ * Required when credentialSources includes a keychain source.
41
+ */
42
+ secretStore?: SecretStore;
43
+ }
44
+ export declare class OpenAiCompatibleAdapter implements ProviderAdapter {
45
+ readonly id: string;
46
+ private readonly options;
47
+ private readonly active;
48
+ private readonly cancelled;
49
+ constructor(options: OpenAiCompatibleOptions);
50
+ private get fetchImpl();
51
+ private offlineNetworkError;
52
+ private resolvedAuthTier;
53
+ private hasConfiguredKey;
54
+ listModels(): Promise<ModelCapability[]>;
55
+ checkAuth(): Promise<AuthStatus>;
56
+ queryLimits(authTier: AuthTier): Promise<LimitSnapshot>;
57
+ estimate(request: RouteRequest, model: string, authTier: AuthTier): Promise<CostEstimate>;
58
+ invoke(request: ProviderInvokeRequest): AsyncIterable<ProviderEvent>;
59
+ private readSseStream;
60
+ cancel(callId: string): Promise<void>;
61
+ }
62
+ export declare function createOpenAiCompatibleAdapter(options: OpenAiCompatibleOptions): OpenAiCompatibleAdapter;
63
+ /** Exported for tests that assert Ollama dummy key behavior. */
64
+ export declare const OLLAMA_DUMMY_BEARER = "Bearer ollama";
65
+ //# sourceMappingURL=openai-compatible.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-compatible.d.ts","sourceRoot":"","sources":["../../src/providers/openai-compatible.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAGL,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,qBAAqB,EAC3B,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAEpE,MAAM,MAAM,sBAAsB,GAAG,QAAQ,GAAG,YAAY,GAAG,KAAK,GAAG,QAAQ,CAAC;AAEhF,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,sBAAsB,CAAC;IAChC,oFAAoF;IACpF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,8DAA8D;IAC9D,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IAChC,qDAAqD;IACrD,MAAM,CAAC,EAAE,eAAe,EAAE,CAAC;IAC3B,gFAAgF;IAChF,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC;;;OAGG;IACH,iBAAiB,CAAC,EAAE,gBAAgB,EAAE,CAAC;IACvC;;;OAGG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AA4CD,qBAAa,uBAAwB,YAAW,eAAe;IAC7D,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0B;IAClD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsC;IAC7D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqB;gBAEnC,OAAO,EAAE,uBAAuB;IAK5C,OAAO,KAAK,SAAS,GAEpB;IAED,OAAO,CAAC,mBAAmB;IAc3B,OAAO,CAAC,gBAAgB;IAKxB,OAAO,CAAC,gBAAgB;IAKlB,UAAU,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;IAiCxC,SAAS,IAAI,OAAO,CAAC,UAAU,CAAC;IAiDhC,WAAW,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,aAAa,CAAC;IA4BvD,QAAQ,CACZ,OAAO,EAAE,YAAY,EACrB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,YAAY,CAAC;IAgBjB,MAAM,CAAC,OAAO,EAAE,qBAAqB,GAAG,aAAa,CAAC,aAAa,CAAC;YAuJ5D,aAAa;IAyHtB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAI5C;AAED,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,uBAAuB,GAC/B,uBAAuB,CAEzB;AAED,gEAAgE;AAChE,eAAO,MAAM,mBAAmB,kBAA+B,CAAC"}