@velum-labs/routekit-gateway 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +28 -0
  3. package/dist/acp-agent.d.ts +38 -0
  4. package/dist/acp-agent.js +142 -0
  5. package/dist/acp-registry.d.ts +36 -0
  6. package/dist/acp-registry.js +85 -0
  7. package/dist/adapters/anthropic.d.ts +131 -0
  8. package/dist/adapters/anthropic.js +1195 -0
  9. package/dist/adapters/chat.d.ts +14 -0
  10. package/dist/adapters/chat.js +34 -0
  11. package/dist/adapters/cursor.d.ts +34 -0
  12. package/dist/adapters/cursor.js +305 -0
  13. package/dist/adapters/dropped.d.ts +10 -0
  14. package/dist/adapters/dropped.js +24 -0
  15. package/dist/adapters/openai-chat-wire.d.ts +93 -0
  16. package/dist/adapters/openai-chat-wire.js +143 -0
  17. package/dist/adapters/responses-stream.d.ts +7 -0
  18. package/dist/adapters/responses-stream.js +597 -0
  19. package/dist/adapters/responses.d.ts +174 -0
  20. package/dist/adapters/responses.js +778 -0
  21. package/dist/adapters/server-tool-loop.d.ts +94 -0
  22. package/dist/adapters/server-tool-loop.js +477 -0
  23. package/dist/adapters/upstream-error.d.ts +14 -0
  24. package/dist/adapters/upstream-error.js +25 -0
  25. package/dist/adapters/validate.d.ts +27 -0
  26. package/dist/adapters/validate.js +180 -0
  27. package/dist/adapters/web-search.d.ts +46 -0
  28. package/dist/adapters/web-search.js +151 -0
  29. package/dist/auth.d.ts +10 -0
  30. package/dist/auth.js +28 -0
  31. package/dist/backend.d.ts +151 -0
  32. package/dist/backend.js +143 -0
  33. package/dist/capacity-pool.d.ts +31 -0
  34. package/dist/capacity-pool.js +99 -0
  35. package/dist/cost.d.ts +49 -0
  36. package/dist/cost.js +112 -0
  37. package/dist/endpoint-health.d.ts +54 -0
  38. package/dist/endpoint-health.js +123 -0
  39. package/dist/index.d.ts +40 -0
  40. package/dist/index.js +23 -0
  41. package/dist/provenance.d.ts +31 -0
  42. package/dist/provenance.js +191 -0
  43. package/dist/provider-backends.d.ts +40 -0
  44. package/dist/provider-backends.js +1050 -0
  45. package/dist/provider-source.d.ts +40 -0
  46. package/dist/provider-source.js +293 -0
  47. package/dist/router.d.ts +168 -0
  48. package/dist/router.js +474 -0
  49. package/dist/server.d.ts +67 -0
  50. package/dist/server.js +930 -0
  51. package/dist/sse/chat-assembler.d.ts +45 -0
  52. package/dist/sse/chat-assembler.js +190 -0
  53. package/dist/sse/parse.d.ts +50 -0
  54. package/dist/sse/parse.js +149 -0
  55. package/dist/sse-wire.d.ts +10 -0
  56. package/dist/sse-wire.js +31 -0
  57. package/dist/switching-proxy.d.ts +15 -0
  58. package/dist/switching-proxy.js +232 -0
  59. package/dist/test/acp-agent.test.d.ts +1 -0
  60. package/dist/test/acp-agent.test.js +66 -0
  61. package/dist/test/acp-registry.test.d.ts +1 -0
  62. package/dist/test/acp-registry.test.js +70 -0
  63. package/dist/test/anthropic.test.d.ts +1 -0
  64. package/dist/test/anthropic.test.js +793 -0
  65. package/dist/test/auth.test.d.ts +1 -0
  66. package/dist/test/auth.test.js +25 -0
  67. package/dist/test/boundary.test.d.ts +1 -0
  68. package/dist/test/boundary.test.js +32 -0
  69. package/dist/test/chat.test.d.ts +1 -0
  70. package/dist/test/chat.test.js +418 -0
  71. package/dist/test/cost.test.d.ts +1 -0
  72. package/dist/test/cost.test.js +60 -0
  73. package/dist/test/cursor.test.d.ts +1 -0
  74. package/dist/test/cursor.test.js +100 -0
  75. package/dist/test/drain.test.d.ts +1 -0
  76. package/dist/test/drain.test.js +116 -0
  77. package/dist/test/dropped.test.d.ts +1 -0
  78. package/dist/test/dropped.test.js +80 -0
  79. package/dist/test/endpoint-health.test.d.ts +1 -0
  80. package/dist/test/endpoint-health.test.js +73 -0
  81. package/dist/test/provenance.test.d.ts +1 -0
  82. package/dist/test/provenance.test.js +176 -0
  83. package/dist/test/provider-backends.test.d.ts +1 -0
  84. package/dist/test/provider-backends.test.js +699 -0
  85. package/dist/test/responses.test.d.ts +1 -0
  86. package/dist/test/responses.test.js +813 -0
  87. package/dist/test/routed-backend.test.d.ts +1 -0
  88. package/dist/test/routed-backend.test.js +39 -0
  89. package/dist/test/router.test.d.ts +1 -0
  90. package/dist/test/router.test.js +297 -0
  91. package/dist/test/server-resilience.test.d.ts +1 -0
  92. package/dist/test/server-resilience.test.js +169 -0
  93. package/dist/test/sse-codec.test.d.ts +1 -0
  94. package/dist/test/sse-codec.test.js +186 -0
  95. package/dist/test/web-search-loop.test.d.ts +1 -0
  96. package/dist/test/web-search-loop.test.js +469 -0
  97. package/dist/test/wire-validation.test.d.ts +1 -0
  98. package/dist/test/wire-validation.test.js +140 -0
  99. package/package.json +48 -0
@@ -0,0 +1,174 @@
1
+ /**
2
+ * OpenAI Responses adapter. Codex speaks the Responses API exclusively
3
+ * (`wire_api="responses"`; Chat Completions support was removed), so to back it
4
+ * with a local model we translate `/v1/responses` to and from the gateway's
5
+ * OpenAI Chat Completions core. The pure translation functions are exported for
6
+ * testing; the handler returns a `Response` the server pipes (JSON or SSE).
7
+ *
8
+ * This is the highest-fidelity adapter: it maps Responses `input` items
9
+ * (messages, function calls, function-call outputs) into chat messages, and
10
+ * emits the Responses streaming event sequence (`response.created`,
11
+ * `response.output_item.added`, `response.output_text.delta`,
12
+ * `response.function_call_arguments.delta`, `response.completed`, …) from chat
13
+ * completion chunks.
14
+ */
15
+ import type { Backend, BackendRequestOptions } from "../backend.js";
16
+ import { type OpenAiChoice } from "./openai-chat-wire.js";
17
+ import type { ExecutedSearch } from "./server-tool-loop.js";
18
+ export { openAiSseToResponses } from "./responses-stream.js";
19
+ type ResponsesContentPart = {
20
+ type: string;
21
+ text?: string;
22
+ image_url?: string;
23
+ [key: string]: unknown;
24
+ };
25
+ type ResponsesInputItem = {
26
+ type?: "message";
27
+ role: "user" | "assistant" | "system" | "developer";
28
+ content: string | ResponsesContentPart[];
29
+ } | {
30
+ type: "function_call";
31
+ call_id?: string;
32
+ id?: string;
33
+ name: string;
34
+ arguments: string;
35
+ } | {
36
+ type: "function_call_output";
37
+ call_id: string;
38
+ output: unknown;
39
+ } | {
40
+ type: "custom_tool_call";
41
+ call_id?: string;
42
+ id?: string;
43
+ name: string;
44
+ input?: string;
45
+ } | {
46
+ type: "custom_tool_call_output";
47
+ call_id: string;
48
+ output: unknown;
49
+ } | {
50
+ type: string;
51
+ [key: string]: unknown;
52
+ };
53
+ /** A tool declaration on a Responses request: a function tool (JSON-schema
54
+ * `parameters`), a freeform "custom" tool (a grammar/text `format` and raw
55
+ * string input — e.g. Codex's `apply_patch` for GPT-5-family models), or a
56
+ * *typed* tool identified only by its `type` (e.g. Codex's `tool_search` /
57
+ * `web_search` entries, which carry no `name`). */
58
+ type ResponsesTool = {
59
+ type?: string;
60
+ name?: string;
61
+ description?: string;
62
+ parameters?: unknown;
63
+ strict?: boolean;
64
+ format?: {
65
+ type?: string;
66
+ syntax?: string;
67
+ definition?: string;
68
+ };
69
+ /** Typed tools declare who executes them ("client" for CLI-side tools). */
70
+ execution?: string;
71
+ };
72
+ /**
73
+ * Codex encodes "unset" as an explicit JSON `null` for several optional fields
74
+ * (e.g. `"reasoning": null` whenever the selected model's metadata advertises
75
+ * no reasoning levels — the default for many custom-provider models). Every
76
+ * nullable field below must be read with a null-tolerant guard; reading
77
+ * `.effort` off a null `reasoning` previously failed every such Codex turn.
78
+ */
79
+ export type ResponsesRequest = {
80
+ model?: string;
81
+ instructions?: string;
82
+ input?: string | ResponsesInputItem[];
83
+ tools?: ResponsesTool[];
84
+ tool_choice?: "auto" | "none" | "required" | {
85
+ type: string;
86
+ name?: string;
87
+ } | null;
88
+ max_output_tokens?: number;
89
+ temperature?: number;
90
+ top_p?: number;
91
+ parallel_tool_calls?: boolean;
92
+ /**
93
+ * Codex serializes `reasoning: null` (not an absent key) for models whose
94
+ * catalog metadata carries no reasoning level — every custom provider
95
+ * member slug (e.g. `grok-4`, `deepseek`) resolves to Codex's fallback model
96
+ * info, which has none. Null must translate as "no reasoning", never throw.
97
+ */
98
+ reasoning?: {
99
+ effort?: string | null;
100
+ [key: string]: unknown;
101
+ } | null;
102
+ text?: {
103
+ format?: {
104
+ type?: string;
105
+ name?: string;
106
+ schema?: unknown;
107
+ strict?: boolean;
108
+ [key: string]: unknown;
109
+ };
110
+ } | null;
111
+ previous_response_id?: string | null;
112
+ truncation?: string | unknown;
113
+ metadata?: Record<string, unknown> | null;
114
+ include?: unknown[] | null;
115
+ stream?: boolean;
116
+ };
117
+ type OpenAiUsage = {
118
+ prompt_tokens?: number;
119
+ completion_tokens?: number;
120
+ };
121
+ type OpenAiResponse = {
122
+ id?: string;
123
+ choices?: OpenAiChoice[];
124
+ usage?: OpenAiUsage;
125
+ provider_cost?: unknown;
126
+ };
127
+ /**
128
+ * How a declared tool must be emitted when the model calls it:
129
+ * - `function`: a plain `function_call` item (JSON-schema function tools, and
130
+ * tools discovered mid-conversation via `tool_search_output`).
131
+ * - `custom`: a `custom_tool_call` item carrying raw string input (freeform
132
+ * tools like Codex's `apply_patch`).
133
+ * - `typed`: the tool's own native item type (`<type>_call`, e.g.
134
+ * `tool_search_call`) — Codex dispatches these by payload shape, and a
135
+ * `function_call` under the same name fails with "handler received
136
+ * unsupported payload".
137
+ * - `server`: a server-executed tool (`web_search`) the *gateway* runs via the
138
+ * server-tool loop. Its calls never surface as callable items — the loop
139
+ * intercepts them and the egress renders native `web_search_call` items.
140
+ */
141
+ export type ResponsesToolKind = "function" | "custom" | "typed" | "server";
142
+ export type ResponsesToolEntry = {
143
+ kind: ResponsesToolKind;
144
+ /**
145
+ * The tool's namespace, for tools *discovered* through a `tool_search`
146
+ * execution (e.g. `spawn_agent` under `multi_agent_v1`). Codex routes a
147
+ * discovered tool's `function_call` by name **and** namespace — without the
148
+ * namespace the call fails with "unsupported call".
149
+ */
150
+ namespace?: string;
151
+ };
152
+ export type ResponsesToolRegistry = ReadonlyMap<string, ResponsesToolEntry>;
153
+ /** The name the gateway-executed web search tool is projected under chat-side. */
154
+ export declare const WEB_SEARCH_TOOL_NAME = "web_search";
155
+ /** Options gating server-executed tool projection (on iff an executor exists). */
156
+ export type ResponsesTranslationOptions = {
157
+ serverTools?: boolean;
158
+ };
159
+ /**
160
+ * The per-request tool registry: every callable tool the request declares or
161
+ * has discovered, keyed by the name the chat-side model calls it under, mapped
162
+ * to how its calls must be emitted. Typed tools are keyed by their `type`;
163
+ * discovered tools carry their namespace for egress dispatch.
164
+ */
165
+ export declare function responsesToolRegistry(body: ResponsesRequest, options?: ResponsesTranslationOptions): ResponsesToolRegistry;
166
+ /**
167
+ * Back-compat helper: the names of the freeform ("custom") tools a Responses
168
+ * request declares (see {@link responsesToolRegistry}).
169
+ */
170
+ export declare function customToolNames(body: ResponsesRequest): ReadonlySet<string>;
171
+ /** Translate a Responses request to an OpenAI Chat Completions body. */
172
+ export declare function responsesToChat(body: ResponsesRequest, backendModel: string | undefined, options?: ResponsesTranslationOptions): Record<string, unknown>;
173
+ export declare function chatToResponses(openai: OpenAiResponse, model: string, toolRegistry?: ResponsesToolRegistry, searches?: readonly ExecutedSearch[]): Record<string, unknown>;
174
+ export declare function handleResponses(backend: Backend, body: ResponsesRequest, modelCallId?: string, signal?: AbortSignal, backendOptions?: BackendRequestOptions): Promise<Response>;