offrouter-core 0.2.0 → 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 +9 -4
  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,360 @@
1
+ /**
2
+ * Local OpenAI Responses-compatible proxy server.
3
+ *
4
+ * Exposes POST /v1/responses (and an optional /v1/chat/completions alias) so
5
+ * harnesses or apps that support custom model base URLs can route through
6
+ * OffRouter. Each request is policy-checked, routed to the best allowed
7
+ * provider (subscription-first), invoked via the provider adapter, and streamed
8
+ * back in OpenAI Responses (or Chat Completions) SSE format.
9
+ *
10
+ * Local-first: binds to 127.0.0.1 by default. An optional bearer token gates
11
+ * access; when unset the proxy runs in loopback-only dev mode and warns.
12
+ *
13
+ * Built on node:http with no external framework.
14
+ */
15
+ import { createHash, timingSafeEqual } from "node:crypto";
16
+ import { createServer } from "node:http";
17
+ import { routeRequest } from "../router.js";
18
+ import { buildDelegationRequest, buildRouteRequest, ChatCompletionsSseBuilder, CHAT_COMPLETIONS_DONE, extractPromptFromChatCompletions, extractPromptFromResponsesInput, openAiErrorPayload, policyDecisionToHttpStatus, providerErrorCodeToHttpStatus, responsesSseData, ResponsesSseBuilder, } from "./responses-mapper.js";
19
+ const DEFAULT_PORT = 8787;
20
+ const DEFAULT_HOST = "127.0.0.1";
21
+ const DEFAULT_HARNESS = { kind: "other", profile: "proxy" };
22
+ const SSE_HEADERS = {
23
+ "content-type": "text/event-stream; charset=utf-8",
24
+ "cache-control": "no-cache",
25
+ connection: "keep-alive",
26
+ "x-accel-buffering": "no",
27
+ };
28
+ /**
29
+ * Start the local proxy and resolve once it is listening.
30
+ * Returns a handle whose `close()` stops the server.
31
+ */
32
+ export function startResponsesProxy(context, options = {}) {
33
+ const host = options.host ?? DEFAULT_HOST;
34
+ const port = options.port ?? DEFAULT_PORT;
35
+ const token = options.token;
36
+ const harness = options.harness ?? DEFAULT_HARNESS;
37
+ const workspace = options.workspace ?? {
38
+ cwd: process.cwd(),
39
+ trusted: true,
40
+ };
41
+ const now = options.now ?? (() => new Date());
42
+ const warn = options.warn ?? ((message) => console.warn(message));
43
+ if (token === undefined) {
44
+ warn("OffRouter proxy: OFFROUTER_PROXY_TOKEN unset; running in dev mode on loopback only.");
45
+ }
46
+ const server = createServer((req, res) => {
47
+ void handleRequest(req, res, context, {
48
+ token,
49
+ harness,
50
+ workspace,
51
+ now,
52
+ }).catch((err) => {
53
+ sendError(res, 500, errorMessage(err), "internal_error");
54
+ });
55
+ });
56
+ return new Promise((resolve, reject) => {
57
+ const onError = (err) => {
58
+ server.removeListener("error", onError);
59
+ reject(err);
60
+ };
61
+ server.once("error", onError);
62
+ server.listen(port, host, () => {
63
+ server.removeListener("error", onError);
64
+ const address = server.address();
65
+ const actualPort = typeof address === "object" && address ? address.port : port;
66
+ resolve({
67
+ port: actualPort,
68
+ host,
69
+ close: () => new Promise((closeResolve, closeReject) => {
70
+ server.close((err) => (err ? closeReject(err) : closeResolve()));
71
+ }),
72
+ });
73
+ });
74
+ });
75
+ }
76
+ async function handleRequest(req, res, context, deps) {
77
+ if (req.method !== "POST") {
78
+ sendError(res, 404, "Not found", "not_found");
79
+ return;
80
+ }
81
+ const format = formatForPath(req.url ?? "");
82
+ if (!format) {
83
+ sendError(res, 404, "Not found", "not_found");
84
+ return;
85
+ }
86
+ if (!authorize(req, deps.token)) {
87
+ sendError(res, 401, "Missing or invalid bearer token.", "authentication_error");
88
+ return;
89
+ }
90
+ const body = await readBody(req);
91
+ let parsed;
92
+ try {
93
+ parsed =
94
+ format === "responses"
95
+ ? extractPromptFromResponsesInput(body)
96
+ : extractPromptFromChatCompletions(body);
97
+ }
98
+ catch {
99
+ sendError(res, 400, "Invalid request body.", "invalid_request_error");
100
+ return;
101
+ }
102
+ await streamResponse(req, res, context, deps, parsed, format);
103
+ }
104
+ function formatForPath(url) {
105
+ const path = url.split("?")[0];
106
+ if (path === "/v1/responses")
107
+ return "responses";
108
+ if (path === "/v1/chat/completions")
109
+ return "chat";
110
+ return null;
111
+ }
112
+ function authorize(req, token) {
113
+ if (token === undefined)
114
+ return true; // dev loopback mode
115
+ const header = req.headers["authorization"];
116
+ if (typeof header !== "string")
117
+ return false;
118
+ const expected = `Bearer ${token}`;
119
+ // Constant-time compare: hash both inputs to fixed-length digests so
120
+ // crypto.timingSafeEqual always receives equal-length buffers.
121
+ return safeEqual(header, expected);
122
+ }
123
+ function safeEqual(a, b) {
124
+ const da = createHash("sha256").update(a, "utf8").digest();
125
+ const db = createHash("sha256").update(b, "utf8").digest();
126
+ return timingSafeEqual(da, db);
127
+ }
128
+ async function readBody(req) {
129
+ const chunks = [];
130
+ for await (const chunk of req) {
131
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
132
+ }
133
+ const text = Buffer.concat(chunks).toString("utf8").trim();
134
+ if (text.length === 0)
135
+ return {};
136
+ try {
137
+ return JSON.parse(text);
138
+ }
139
+ catch {
140
+ throw new Error("request body is not valid JSON");
141
+ }
142
+ }
143
+ async function streamResponse(req, res, context, deps, parsed, format) {
144
+ const route = buildRouteRequest({
145
+ prompt: parsed.prompt,
146
+ harness: deps.harness,
147
+ workspace: deps.workspace,
148
+ });
149
+ // Policy gate with digest/preview only (raw prompt never reaches routing).
150
+ const decision = routeRequest(route, context.candidates, context.policy);
151
+ if (decision.blocked || !decision.route) {
152
+ const status = policyDecisionToHttpStatus(decision);
153
+ const message = decision.explanation || decision.reason || "routing blocked by policy";
154
+ sendError(res, status, message, decision.needsConfiguration ? "needs_configuration" : "policy_blocked");
155
+ return;
156
+ }
157
+ const delegation = buildDelegationRequest({
158
+ prompt: parsed.prompt,
159
+ route,
160
+ maxOutputTokens: parsed.maxOutputTokens,
161
+ temperature: parsed.temperature,
162
+ });
163
+ const taskId = delegation.taskId;
164
+ let settled = false;
165
+ const onClose = () => {
166
+ if (!settled && !res.writableEnded) {
167
+ void context.runtime.cancel(taskId).catch(() => undefined);
168
+ }
169
+ };
170
+ // res 'close' is the canonical client-disconnect signal: it fires when the
171
+ // underlying connection terminates before the response completes.
172
+ res.on("close", onClose);
173
+ req.on("close", onClose);
174
+ try {
175
+ await pump(context, res, delegation, parsed, format, deps, () => {
176
+ settled = true;
177
+ });
178
+ }
179
+ catch (err) {
180
+ if (!res.headersSent) {
181
+ const status = 500;
182
+ sendError(res, status, errorMessage(err), "internal_error");
183
+ return;
184
+ }
185
+ safeEnd(res);
186
+ }
187
+ finally {
188
+ settled = true;
189
+ res.off("close", onClose);
190
+ req.off("close", onClose);
191
+ }
192
+ }
193
+ async function pump(context, res, delegation, parsed, format, deps, markSettled) {
194
+ // Only an explicit stream:false opts out of SSE; omitting stream (or true)
195
+ // keeps the streaming path identical to prior behavior.
196
+ const wantStream = parsed.stream !== false;
197
+ const responsesBuilder = new ResponsesSseBuilder("", deps.now);
198
+ const chatBuilder = new ChatCompletionsSseBuilder("", deps.now);
199
+ let headersSent = false;
200
+ const sendHeaders = () => {
201
+ if (headersSent)
202
+ return;
203
+ headersSent = true;
204
+ res.writeHead(200, SSE_HEADERS);
205
+ if (format === "responses") {
206
+ safeWrite(res, responsesSseData(responsesBuilder.createdEvent()));
207
+ }
208
+ else {
209
+ safeWrite(res, responsesSseData(chatBuilder.firstEvent()));
210
+ }
211
+ };
212
+ const eventStream = context.runtime.stream(delegation);
213
+ try {
214
+ for await (const event of eventStream) {
215
+ switch (event.type) {
216
+ case "start": {
217
+ if (event.model) {
218
+ responsesBuilder.setModel(event.model);
219
+ chatBuilder.setModel(event.model);
220
+ }
221
+ break;
222
+ }
223
+ case "text-delta": {
224
+ responsesBuilder.addText(event.text);
225
+ chatBuilder.addText(event.text);
226
+ if (wantStream) {
227
+ sendHeaders();
228
+ if (format === "responses") {
229
+ safeWrite(res, responsesSseData(responsesBuilder.deltaEvent(event.text)));
230
+ }
231
+ else {
232
+ safeWrite(res, responsesSseData(chatBuilder.deltaEvent(event.text)));
233
+ }
234
+ }
235
+ break;
236
+ }
237
+ case "usage": {
238
+ responsesBuilder.setUsage({
239
+ inputTokens: event.inputTokens,
240
+ outputTokens: event.outputTokens,
241
+ totalTokens: event.totalTokens,
242
+ });
243
+ chatBuilder.setUsage({
244
+ promptTokens: event.inputTokens,
245
+ completionTokens: event.outputTokens,
246
+ totalTokens: event.totalTokens,
247
+ });
248
+ break;
249
+ }
250
+ case "done": {
251
+ if (wantStream) {
252
+ sendHeaders();
253
+ finalize(res, format, responsesBuilder, chatBuilder);
254
+ }
255
+ else {
256
+ sendNonStreamJson(res, format, responsesBuilder, chatBuilder);
257
+ }
258
+ markSettled();
259
+ return;
260
+ }
261
+ case "error": {
262
+ if (!res.headersSent) {
263
+ // Provider failed before any content was flushed.
264
+ const status = event.code !== undefined
265
+ ? providerErrorCodeToHttpStatus(event.code)
266
+ : 500;
267
+ sendError(res, status, event.message, event.code ?? "internal_error");
268
+ }
269
+ else {
270
+ // Mid-stream error: emit an SSE error frame and close.
271
+ safeWrite(res, responsesSseData({
272
+ type: "error",
273
+ error: {
274
+ message: event.message,
275
+ code: event.code ?? "internal_error",
276
+ },
277
+ }));
278
+ finalize(res, format, responsesBuilder, chatBuilder, true);
279
+ }
280
+ markSettled();
281
+ return;
282
+ }
283
+ case "cancelled": {
284
+ if (!res.headersSent) {
285
+ res.writeHead(499, { "content-type": "application/json" });
286
+ }
287
+ finalize(res, format, responsesBuilder, chatBuilder, true);
288
+ markSettled();
289
+ return;
290
+ }
291
+ default:
292
+ break;
293
+ }
294
+ }
295
+ // Stream ended without an explicit done: finalize gracefully.
296
+ if (wantStream) {
297
+ if (!headersSent)
298
+ sendHeaders();
299
+ finalize(res, format, responsesBuilder, chatBuilder);
300
+ }
301
+ else {
302
+ sendNonStreamJson(res, format, responsesBuilder, chatBuilder);
303
+ }
304
+ }
305
+ finally {
306
+ markSettled();
307
+ }
308
+ }
309
+ /** Emit a single JSON response object for non-streaming requests. */
310
+ function sendNonStreamJson(res, format, responsesBuilder, chatBuilder) {
311
+ if (res.writableEnded || res.destroyed)
312
+ return;
313
+ const body = format === "responses"
314
+ ? JSON.stringify(responsesBuilder.responseObject())
315
+ : JSON.stringify(chatBuilder.completionObject());
316
+ res.writeHead(200, {
317
+ "content-type": "application/json; charset=utf-8",
318
+ "content-length": Buffer.byteLength(body).toString(),
319
+ });
320
+ res.end(body);
321
+ }
322
+ function finalize(res, format, responsesBuilder, chatBuilder, aborted = false) {
323
+ if (res.writableEnded || res.destroyed)
324
+ return;
325
+ if (format === "responses" && !aborted) {
326
+ safeWrite(res, responsesSseData(responsesBuilder.completedEvent()));
327
+ }
328
+ else if (format === "chat" && !aborted) {
329
+ safeWrite(res, responsesSseData(chatBuilder.doneEvent()));
330
+ safeWrite(res, CHAT_COMPLETIONS_DONE);
331
+ }
332
+ safeEnd(res);
333
+ }
334
+ function safeWrite(res, chunk) {
335
+ if (res.writableEnded || res.destroyed)
336
+ return;
337
+ res.write(chunk);
338
+ }
339
+ function safeEnd(res) {
340
+ if (res.writableEnded || res.destroyed)
341
+ return;
342
+ res.end();
343
+ }
344
+ function sendError(res, status, message, code) {
345
+ if (res.headersSent) {
346
+ safeEnd(res);
347
+ return;
348
+ }
349
+ const payload = openAiErrorPayload(status, message, code);
350
+ const body = JSON.stringify(payload);
351
+ res.writeHead(status, {
352
+ "content-type": "application/json; charset=utf-8",
353
+ "content-length": Buffer.byteLength(body).toString(),
354
+ });
355
+ res.end(body);
356
+ }
357
+ function errorMessage(err) {
358
+ return err instanceof Error ? err.message : String(err);
359
+ }
360
+ //# sourceMappingURL=responses-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"responses-server.js","sourceRoot":"","sources":["../../src/proxy/responses-server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Deterministic model scoring and route explain for OffRouter V1.
3
+ */
4
+ import { type PolicyConfig } from "./policy.js";
5
+ import type { ProviderCandidate, RouteDecision, RouteRequest } from "./types.js";
6
+ export interface RouteOptions {
7
+ /** Optional decision id factory for tests; defaults to deterministic hash-ish id. */
8
+ decisionId?: string;
9
+ }
10
+ declare function sortCandidates(candidates: ProviderCandidate[]): ProviderCandidate[];
11
+ /**
12
+ * Route a request against candidates under policy.
13
+ * Pure and deterministic: same inputs -> same decision (except optional decisionId).
14
+ */
15
+ export declare function routeRequest(request: RouteRequest, candidates: ProviderCandidate[], config: PolicyConfig, options?: RouteOptions): RouteDecision;
16
+ /** @internal exported for focused testing */
17
+ export { sortCandidates };
18
+ //# sourceMappingURL=router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhE,OAAO,KAAK,EAGV,iBAAiB,EACjB,aAAa,EACb,YAAY,EACb,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,YAAY;IAC3B,qFAAqF;IACrF,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAwCD,iBAAS,cAAc,CAAC,UAAU,EAAE,iBAAiB,EAAE,GAAG,iBAAiB,EAAE,CAgB5E;AAsFD;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,YAAY,EACrB,UAAU,EAAE,iBAAiB,EAAE,EAC/B,MAAM,EAAE,YAAY,EACpB,OAAO,GAAE,YAAiB,GACzB,aAAa,CAqLf;AAED,6CAA6C;AAC7C,OAAO,EAAE,cAAc,EAAE,CAAC"}