@wacry/codeks-bridge 0.0.0-stage → 0.0.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 (104) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +13 -0
  3. package/README.md +40 -2
  4. package/catalog/README.md +63 -0
  5. package/catalog/claude-opus-5-5.json +194 -0
  6. package/catalog/claude-sonnet-5-5.json +194 -0
  7. package/catalog/deepseek-flash.json +203 -0
  8. package/catalog/gpt-5.6-sol.json +152 -0
  9. package/catalog/gpt-6-astra.json +184 -0
  10. package/catalog/gpt-6-luna.json +178 -0
  11. package/catalog/gpt-6-sol.json +182 -0
  12. package/catalog/gpt-6.1-sol.json +187 -0
  13. package/dist/adapter-options.d.ts +5 -0
  14. package/dist/adapter-options.js +41 -0
  15. package/dist/auth.d.ts +2 -0
  16. package/dist/auth.js +42 -0
  17. package/dist/backends/anthropic-tools.d.ts +13 -0
  18. package/dist/backends/anthropic-tools.js +41 -0
  19. package/dist/backends/anthropic.d.ts +9 -0
  20. package/dist/backends/anthropic.js +356 -0
  21. package/dist/backends/chat.d.ts +16 -0
  22. package/dist/backends/chat.js +284 -0
  23. package/dist/backends/deepseek.d.ts +6 -0
  24. package/dist/backends/deepseek.js +37 -0
  25. package/dist/backends/responses.d.ts +5 -0
  26. package/dist/backends/responses.js +227 -0
  27. package/dist/carrier.d.ts +22 -0
  28. package/dist/carrier.js +61 -0
  29. package/dist/catalog.d.ts +8 -0
  30. package/dist/catalog.js +40 -0
  31. package/dist/cli.d.ts +2 -0
  32. package/dist/cli.js +64 -0
  33. package/dist/compaction-handoff.d.ts +13 -0
  34. package/dist/compaction-handoff.js +126 -0
  35. package/dist/compaction-history.d.ts +7 -0
  36. package/dist/compaction-history.js +20 -0
  37. package/dist/compaction.d.ts +20 -0
  38. package/dist/compaction.js +134 -0
  39. package/dist/config.d.ts +6 -0
  40. package/dist/config.js +170 -0
  41. package/dist/errors.d.ts +43 -0
  42. package/dist/errors.js +141 -0
  43. package/dist/headers.d.ts +6 -0
  44. package/dist/headers.js +39 -0
  45. package/dist/history.d.ts +7 -0
  46. package/dist/history.js +85 -0
  47. package/dist/ids.d.ts +1 -0
  48. package/dist/ids.js +4 -0
  49. package/dist/index.d.ts +5 -0
  50. package/dist/index.js +4 -0
  51. package/dist/inspect/capture.d.ts +119 -0
  52. package/dist/inspect/capture.js +370 -0
  53. package/dist/inspect/http.d.ts +7 -0
  54. package/dist/inspect/http.js +149 -0
  55. package/dist/inspect/view.d.ts +239 -0
  56. package/dist/inspect/view.js +388 -0
  57. package/dist/model-catalog.d.ts +18 -0
  58. package/dist/model-catalog.js +16 -0
  59. package/dist/profiles.d.ts +6 -0
  60. package/dist/profiles.js +63 -0
  61. package/dist/prompts.d.ts +5 -0
  62. package/dist/prompts.js +118 -0
  63. package/dist/server.d.ts +4 -0
  64. package/dist/server.js +232 -0
  65. package/dist/sse.d.ts +12 -0
  66. package/dist/sse.js +93 -0
  67. package/dist/tool-history.d.ts +4 -0
  68. package/dist/tool-history.js +73 -0
  69. package/dist/tools.d.ts +35 -0
  70. package/dist/tools.js +193 -0
  71. package/dist/types.d.ts +125 -0
  72. package/dist/types.js +1 -0
  73. package/dist/upstream.d.ts +3 -0
  74. package/dist/upstream.js +89 -0
  75. package/dist/writer.d.ts +95 -0
  76. package/dist/writer.js +430 -0
  77. package/docs/backends-anthropic.md +88 -0
  78. package/docs/backends-deepseek-chat.md +75 -0
  79. package/docs/backends-responses.md +33 -0
  80. package/docs/compaction.md +180 -0
  81. package/docs/config.md +271 -0
  82. package/docs/design.md +97 -0
  83. package/docs/inspect.md +148 -0
  84. package/docs/reasoning.md +72 -0
  85. package/docs/releasing.md +50 -0
  86. package/docs/responses-stream.md +90 -0
  87. package/docs/testing.md +177 -0
  88. package/docs/tools.md +68 -0
  89. package/examples/config.json +35 -0
  90. package/examples/gpt-claude.json +27 -0
  91. package/package.json +46 -4
  92. package/ui/api.js +64 -0
  93. package/ui/app.css +379 -0
  94. package/ui/app.js +489 -0
  95. package/ui/detail.js +713 -0
  96. package/ui/diff.js +281 -0
  97. package/ui/dom.js +258 -0
  98. package/ui/events.js +376 -0
  99. package/ui/favicon.svg +1 -0
  100. package/ui/index.html +58 -0
  101. package/ui/labels.js +106 -0
  102. package/ui/list.js +180 -0
  103. package/ui/structure.js +285 -0
  104. package/ui/tree.js +158 -0
package/dist/tools.js ADDED
@@ -0,0 +1,193 @@
1
+ // Tool definitions for upstreams that only know plain functions.
2
+ //
3
+ // codeks sends three kinds of client tools: `function`, `custom` (freeform
4
+ // input, optionally constrained by a Lark or regex grammar) and `namespace`
5
+ // (a group of functions). The shared Messages/Chat mapping uses names matching
6
+ // [a-zA-Z0-9_-]{1,64}, the smaller Chat limit. See docs/tools.md.
7
+ import { createHash } from "node:crypto";
8
+ import { BridgeError } from "./errors.js";
9
+ export const MAX_TOOL_NAME = 64;
10
+ function sanitize(name) {
11
+ const cleaned = name.replace(/[^a-zA-Z0-9_-]/g, "_");
12
+ return cleaned === "" ? "tool" : cleaned;
13
+ }
14
+ function shorten(name, limit) {
15
+ if (name.length <= limit)
16
+ return name;
17
+ // Same idea as codeks for long MCP tool names: keep a readable prefix and
18
+ // add a short hash so that different long names stay different.
19
+ const hash = createHash("sha1").update(name).digest("hex").slice(0, 8);
20
+ return `${name.slice(0, limit - 9)}_${hash}`;
21
+ }
22
+ /** Joins a namespace and a tool name the way codeks names MCP tools. */
23
+ export function baseFlatName(namespace, name) {
24
+ let joined = name;
25
+ if (namespace)
26
+ joined = namespace.endsWith("_") ? `${namespace}${name}` : `${namespace}__${name}`;
27
+ return shorten(sanitize(joined), MAX_TOOL_NAME);
28
+ }
29
+ function identity(namespace, name) {
30
+ return `${namespace === "functions" ? "" : namespace ?? ""}\u0000${name}`;
31
+ }
32
+ /** Extracts Lite declarations for APIs whose tools live outside the conversation. */
33
+ export function normalizeToolDeclarations(request) {
34
+ if (!Array.isArray(request.input))
35
+ return request;
36
+ const tools = [...(request.tools ?? [])];
37
+ const input = request.input.filter((item) => {
38
+ if (item?.type !== "additional_tools")
39
+ return true;
40
+ if (!Array.isArray(item.tools))
41
+ throw new BridgeError("additional_tools requires a tools array.");
42
+ tools.push(...item.tools);
43
+ return false;
44
+ });
45
+ return { ...request, input, tools };
46
+ }
47
+ const SCHEMA_CHILD_MAPS = ["properties", "patternProperties", "$defs", "definitions", "dependentSchemas"];
48
+ const SCHEMA_CHILD_LISTS = ["anyOf", "oneOf", "allOf", "prefixItems"];
49
+ const SCHEMA_CHILD_ONE = ["items", "additionalProperties", "not", "if", "then", "else", "contains", "propertyNames"];
50
+ /** Removes keywords that only the OpenAI Responses API understands. */
51
+ export function cleanSchema(schema) {
52
+ if (Array.isArray(schema))
53
+ return schema.map(cleanSchema);
54
+ if (!schema || typeof schema !== "object")
55
+ return schema;
56
+ const out = {};
57
+ for (const [key, value] of Object.entries(schema)) {
58
+ if (key === "encrypted" && typeof value === "boolean")
59
+ continue;
60
+ if (SCHEMA_CHILD_MAPS.includes(key) && value && typeof value === "object" && !Array.isArray(value)) {
61
+ const mapped = {};
62
+ for (const [k, v] of Object.entries(value))
63
+ mapped[k] = cleanSchema(v);
64
+ out[key] = mapped;
65
+ }
66
+ else if (SCHEMA_CHILD_LISTS.includes(key) && Array.isArray(value)) {
67
+ out[key] = value.map(cleanSchema);
68
+ }
69
+ else if (SCHEMA_CHILD_ONE.includes(key)) {
70
+ out[key] = cleanSchema(value);
71
+ }
72
+ else {
73
+ out[key] = value;
74
+ }
75
+ }
76
+ return out;
77
+ }
78
+ function objectSchema(parameters) {
79
+ if (parameters == null)
80
+ return { type: "object", properties: {} };
81
+ const cleaned = cleanSchema(parameters);
82
+ if (cleaned && typeof cleaned === "object" && !Array.isArray(cleaned)) {
83
+ return { type: "object", ...cleaned };
84
+ }
85
+ throw new BridgeError("Function tool parameters must be a JSON Schema object.");
86
+ }
87
+ /** Describes a custom tool's input format in words, for function-only upstreams. */
88
+ export function customToolDescription(description, format) {
89
+ const parts = [description.trim()];
90
+ parts.push("Pass the whole tool input as the string field `input`.");
91
+ if (format && format.type === "grammar" && typeof format.definition === "string") {
92
+ const syntax = String(format.syntax ?? "lark");
93
+ if (syntax === "regex") {
94
+ parts.push(`The \`input\` string must match this regular expression:\n\n\`\`\`\n${format.definition}\n\`\`\``);
95
+ }
96
+ else {
97
+ parts.push(`The \`input\` string must match this ${syntax === "lark" ? "Lark" : syntax} grammar:\n\n\`\`\`${syntax}\n${format.definition}\n\`\`\``);
98
+ }
99
+ }
100
+ return parts.filter((p) => p !== "").join("\n\n");
101
+ }
102
+ const CUSTOM_PARAMETERS = {
103
+ type: "object",
104
+ properties: { input: { type: "string", description: "The raw tool input." } },
105
+ required: ["input"],
106
+ additionalProperties: false,
107
+ };
108
+ export function buildToolSet(tools) {
109
+ const entries = [];
110
+ const byFlat = new Map();
111
+ const byIdentity = new Map();
112
+ const add = (entry) => {
113
+ const id = identity(entry.namespace, entry.name);
114
+ const previous = byIdentity.get(id);
115
+ if (previous) {
116
+ // Lite updates contain only changed members. Replace that definition
117
+ // without losing siblings or changing its established upstream name.
118
+ Object.assign(previous, entry);
119
+ return previous;
120
+ }
121
+ let flatName = baseFlatName(entry.namespace, entry.name);
122
+ // Add a suffix only when two different tools would get the same name.
123
+ for (let n = 2; byFlat.has(flatName); n++) {
124
+ const suffix = `_${n}`;
125
+ flatName = baseFlatName(entry.namespace, entry.name).slice(0, MAX_TOOL_NAME - suffix.length) + suffix;
126
+ }
127
+ const full = { ...entry, flatName };
128
+ entries.push(full);
129
+ byFlat.set(flatName, full);
130
+ byIdentity.set(id, full);
131
+ return full;
132
+ };
133
+ const visit = (tool, namespace) => {
134
+ if (!tool || typeof tool !== "object")
135
+ return [];
136
+ if (tool.type === "function") {
137
+ return [add({
138
+ kind: "function",
139
+ name: String(tool.name),
140
+ namespace,
141
+ description: String(tool.description ?? ""),
142
+ parameters: objectSchema(tool.parameters),
143
+ })];
144
+ }
145
+ else if (tool.type === "custom") {
146
+ return [add({
147
+ kind: "custom",
148
+ name: String(tool.name),
149
+ namespace,
150
+ description: customToolDescription(String(tool.description ?? ""), tool.format),
151
+ parameters: CUSTOM_PARAMETERS,
152
+ })];
153
+ }
154
+ else if (tool.type === "namespace" && Array.isArray(tool.tools)) {
155
+ return tool.tools.flatMap((inner) => visit(inner, String(tool.name)));
156
+ }
157
+ // Hosted tools (web_search, image_generation, tool_search, ...) have no
158
+ // equivalent on these upstreams and are left out.
159
+ return [];
160
+ };
161
+ const addTools = (declarations) => {
162
+ const changed = new Map();
163
+ for (const declaration of declarations) {
164
+ for (const entry of visit(declaration, undefined))
165
+ changed.set(entry.flatName, entry);
166
+ }
167
+ // Later updates may mutate the registry's current definition. Earlier
168
+ // inline definitions must retain the exact payload used at that point.
169
+ return structuredClone([...changed.values()]);
170
+ };
171
+ addTools(tools ?? []);
172
+ return {
173
+ entries,
174
+ add: addTools,
175
+ byFlat,
176
+ flatFor(namespace, name) {
177
+ return byIdentity.get(identity(namespace, name))?.flatName ?? baseFlatName(namespace, name);
178
+ },
179
+ get(namespace, name) {
180
+ return byIdentity.get(identity(namespace, name));
181
+ },
182
+ resolve(flatName) {
183
+ return byFlat.get(flatName);
184
+ },
185
+ };
186
+ }
187
+ /** Upstream tool call ids must match [a-zA-Z0-9_-]{1,64} on some APIs. */
188
+ export function safeCallId(id) {
189
+ if (/^[a-zA-Z0-9_-]{1,64}$/.test(id))
190
+ return id;
191
+ const hash = createHash("sha1").update(id).digest("hex").slice(0, 8);
192
+ return `${sanitize(id).slice(0, 55)}_${hash}`;
193
+ }
@@ -0,0 +1,125 @@
1
+ import type { ResponseWriter, Usage } from "./writer.ts";
2
+ export type Api = "responses" | "anthropic" | "chat";
3
+ export type AdapterId = "gpt-responses" | "claude-messages" | "deepseek-chat";
4
+ export interface ClaudeMessagesOptions {
5
+ tool_updates: "inline" | "top_level";
6
+ thinking_mismatch: "drop_block" | "error" | "upstream_default";
7
+ }
8
+ /** Bridge behavior, distinct from native request-body options. */
9
+ export interface AdapterConfig {
10
+ "claude-messages"?: Partial<ClaudeMessagesOptions>;
11
+ }
12
+ export interface UpstreamConfig {
13
+ base_url: string;
14
+ api_key_env?: string;
15
+ /** An argv array. The command writes a short-lived credential to stdout. */
16
+ api_key_command?: string[];
17
+ auth_header?: string;
18
+ stream_idle_timeout_ms?: number;
19
+ headers?: Record<string, string>;
20
+ options?: Record<string, unknown>;
21
+ adapters?: AdapterConfig;
22
+ }
23
+ export interface ModelConfig {
24
+ upstream: string;
25
+ model: string;
26
+ catalog: string;
27
+ /** Include this alias in the client catalog. Defaults to true. */
28
+ expose?: boolean;
29
+ context_window?: number;
30
+ max_output_tokens?: number;
31
+ input_modalities?: ("text" | "image")[];
32
+ reasoning?: {
33
+ default_effort?: string;
34
+ effort_map?: Record<string, string>;
35
+ };
36
+ replay?: {
37
+ reasoning_from?: string[];
38
+ native_compaction_from?: string[];
39
+ };
40
+ compaction?: {
41
+ mode?: "summary" | "native";
42
+ model?: string;
43
+ native_replay?: boolean;
44
+ };
45
+ options?: Record<string, unknown>;
46
+ adapters?: AdapterConfig;
47
+ }
48
+ export interface BridgeConfig {
49
+ host?: string;
50
+ port?: number;
51
+ token_env?: string;
52
+ compaction_cache_dir?: string;
53
+ /** Debug capture for the /inspect/ page. */
54
+ inspect?: {
55
+ capture?: boolean;
56
+ max_mib?: number;
57
+ };
58
+ upstreams: Record<string, UpstreamConfig>;
59
+ models: Record<string, ModelConfig>;
60
+ }
61
+ export interface ModelProfile {
62
+ model_info: Record<string, any>;
63
+ max_output_tokens?: number;
64
+ id: AdapterId;
65
+ api: Api;
66
+ reasoning_format: string;
67
+ native_compaction_format?: string;
68
+ default_effort: string;
69
+ multi_agent_effort?: string;
70
+ effort_map: Record<string, string>;
71
+ input_modalities: ("text" | "image")[];
72
+ }
73
+ export interface StateOrigin {
74
+ /** Stable source fingerprint, independent of aliases and replay policy. */
75
+ id: string;
76
+ connection: string;
77
+ model: string;
78
+ adapter: AdapterId;
79
+ }
80
+ export interface ResolvedModel {
81
+ slug: string;
82
+ config: ModelConfig;
83
+ upstream: UpstreamConfig;
84
+ profile: ModelProfile;
85
+ origin: StateOrigin;
86
+ replay: {
87
+ reasoning: ReadonlySet<string>;
88
+ native_compaction: ReadonlySet<string>;
89
+ };
90
+ compaction: {
91
+ mode: "summary" | "native";
92
+ native_replay: boolean;
93
+ };
94
+ }
95
+ export interface ResponsesRequest {
96
+ model: string;
97
+ input?: string | Record<string, any>[];
98
+ instructions?: string;
99
+ tools?: any[];
100
+ tool_choice?: any;
101
+ reasoning?: {
102
+ effort?: string;
103
+ summary?: string;
104
+ [key: string]: unknown;
105
+ };
106
+ stream?: boolean;
107
+ [key: string]: any;
108
+ }
109
+ export interface BackendContext {
110
+ request: ResponsesRequest;
111
+ route: ResolvedModel;
112
+ signal: AbortSignal;
113
+ /** Client metadata; transport framing and credentials are replaced upstream. */
114
+ requestHeaders?: Headers;
115
+ compacting?: boolean;
116
+ /** Transport mode received from the client, including tool-free Lite requests. */
117
+ responsesLite?: boolean;
118
+ /** Called after the upstream accepts the HTTP request, before consuming its body. */
119
+ onAccepted?: (headers?: Headers) => void;
120
+ }
121
+ export interface BackendResult {
122
+ usage: Usage;
123
+ endTurn?: boolean;
124
+ }
125
+ export type Backend = (context: BackendContext, writer: ResponseWriter) => Promise<BackendResult>;
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ import type { ResolvedModel } from "./types.ts";
2
+ /** base_url includes any API version prefix; path is appended, never resolved from /. */
3
+ export declare function upstreamFetch(route: ResolvedModel, path: string, body: unknown, signal: AbortSignal, requestHeaders?: Headers, protocolHeaders?: Record<string, string | string[]>): Promise<Response>;
@@ -0,0 +1,89 @@
1
+ import { upstreamHeaders } from "./auth.js";
2
+ import { BridgeError, transportError, upstreamError, UpstreamHttpError } from "./errors.js";
3
+ import { captureUpstream } from "./inspect/capture.js";
4
+ /** base_url includes any API version prefix; path is appended, never resolved from /. */
5
+ export async function upstreamFetch(route, path, body, signal, requestHeaders, protocolHeaders) {
6
+ const url = route.upstream.base_url.replace(/\/+$/, "") + "/" + path.replace(/^\/+/, "");
7
+ const headers = await upstreamHeaders(route.upstream, route.profile.api, signal, requestHeaders);
8
+ for (const [name, value] of Object.entries(protocolHeaders ?? {})) {
9
+ // A protocol may require additional comma-separated feature flags without
10
+ // replacing the endpoint's configured flags. Scalar headers still replace.
11
+ headers.set(name, Array.isArray(value)
12
+ ? [...new Set([...(headers.get(name)?.split(",") ?? []), ...value].map(v => v.trim()).filter(Boolean))].join(",")
13
+ : value);
14
+ }
15
+ const payload = JSON.stringify(body);
16
+ const call = captureUpstream(url, headers, payload);
17
+ const idle = new AbortController();
18
+ const combined = AbortSignal.any([signal, idle.signal]);
19
+ const timeoutMs = route.upstream.stream_idle_timeout_ms ?? 300_000;
20
+ let timer;
21
+ const reset = () => {
22
+ clearTimeout(timer);
23
+ timer = setTimeout(() => idle.abort(new BridgeError("Upstream stream timed out", "stream_error", 504)), timeoutMs).unref();
24
+ };
25
+ reset();
26
+ let response;
27
+ try {
28
+ response = await fetch(url, { method: "POST", headers, body: payload, signal: combined, redirect: "error" });
29
+ }
30
+ catch (error) {
31
+ clearTimeout(timer);
32
+ call?.failed(combined.aborted ? combined.reason : error);
33
+ if (combined.aborted)
34
+ throw combined.reason;
35
+ throw transportError(error);
36
+ }
37
+ // Downstream keepalives do not count as upstream progress. Time out both the
38
+ // wait for headers and an idle response body, including a stalled error body.
39
+ call?.received(response);
40
+ if (response.body) {
41
+ const reader = response.body.getReader();
42
+ response = new Response(new ReadableStream({
43
+ async pull(controller) {
44
+ try {
45
+ const chunk = await reader.read();
46
+ if (chunk.done) {
47
+ clearTimeout(timer);
48
+ call?.done("complete");
49
+ controller.close();
50
+ }
51
+ else {
52
+ reset();
53
+ call?.chunk(chunk.value);
54
+ controller.enqueue(chunk.value);
55
+ }
56
+ }
57
+ catch (error) {
58
+ clearTimeout(timer);
59
+ const cause = combined.aborted ? combined.reason : transportError(error);
60
+ call?.done("error", cause);
61
+ controller.error(cause);
62
+ }
63
+ },
64
+ async cancel(reason) {
65
+ clearTimeout(timer);
66
+ call?.done("unread");
67
+ await reader.cancel(reason);
68
+ },
69
+ }), { status: response.status, statusText: response.statusText, headers: response.headers });
70
+ }
71
+ else {
72
+ clearTimeout(timer);
73
+ call?.done("complete");
74
+ }
75
+ if (!response.ok) {
76
+ const text = await response.text();
77
+ if (combined.aborted)
78
+ throw combined.reason;
79
+ if (route.profile.api === "responses")
80
+ throw new UpstreamHttpError(response.status, text, response.headers);
81
+ let payload = text;
82
+ try {
83
+ payload = JSON.parse(text);
84
+ }
85
+ catch { /* Non-JSON error bodies are still useful diagnostics. */ }
86
+ throw upstreamError(response.status, payload, response.headers);
87
+ }
88
+ return response;
89
+ }
@@ -0,0 +1,95 @@
1
+ export interface Usage {
2
+ input_tokens: number;
3
+ cached_tokens?: number;
4
+ cache_write_tokens?: number;
5
+ output_tokens: number;
6
+ reasoning_tokens?: number;
7
+ }
8
+ export interface Sink {
9
+ write(chunk: string): void;
10
+ }
11
+ export interface FunctionCallItem {
12
+ call_id: string;
13
+ name: string;
14
+ namespace?: string;
15
+ arguments: string;
16
+ }
17
+ export interface CustomToolCallItem {
18
+ call_id: string;
19
+ name: string;
20
+ input: string;
21
+ namespace?: string;
22
+ }
23
+ type Phase = "commentary" | "partial_answer" | "final_answer";
24
+ export declare function usageJson(usage: Usage): Record<string, unknown>;
25
+ export declare class ResponseWriter {
26
+ private id;
27
+ private readonly sink;
28
+ private readonly model;
29
+ private readonly showSummary;
30
+ private seq;
31
+ private nextOutputIndex;
32
+ private readonly output;
33
+ private message;
34
+ private reasoning;
35
+ private pendingMessage;
36
+ private calls;
37
+ private suffix;
38
+ private suffixOutputStart;
39
+ private native;
40
+ private nativeEnd;
41
+ private started;
42
+ private finished;
43
+ constructor(sink: Sink, opts: {
44
+ model: string;
45
+ showSummary?: boolean;
46
+ responseId?: string;
47
+ });
48
+ get responseId(): string;
49
+ get nativeResponse(): Record<string, any> | undefined;
50
+ get outputItems(): readonly Record<string, any>[];
51
+ get isFinished(): boolean;
52
+ get hasOutput(): boolean;
53
+ private write;
54
+ private send;
55
+ private emit;
56
+ private holdSuffix;
57
+ private releaseSuffix;
58
+ private discardSuffix;
59
+ private responseObject;
60
+ start(): void;
61
+ /** An event that codeks ignores but that resets its stream idle timer. */
62
+ keepalive(): void;
63
+ /** Native Responses events retain their own ids, envelopes and metadata. */
64
+ useNativeResponses(): void;
65
+ nativeEvent(event: Record<string, any>): void;
66
+ nativeFailed(response: Record<string, any>, event?: Record<string, any>): void;
67
+ nativeIncomplete(response: Record<string, any>, event?: Record<string, any>): void;
68
+ private nativeFailure;
69
+ private openReasoning;
70
+ startReasoningSummary(summaryIndex?: number): void;
71
+ reasoningDelta(text: string, summaryIndex?: number): void;
72
+ endReasoningSummary(summaryIndex?: number, text?: string): void;
73
+ /** Closes the open reasoning item (opening one if needed) with its carrier. */
74
+ endReasoning(encryptedContent: string | undefined, summary?: Array<{
75
+ type: "summary_text";
76
+ text: string;
77
+ }>): void;
78
+ get reasoningOpen(): boolean;
79
+ textDelta(text: string, phase?: Phase): void;
80
+ /** Ends the current text block. Its done event waits until the phase is known. */
81
+ closeMessage(phase?: Phase): void;
82
+ private flushPendingMessage;
83
+ addFunctionCall(call: FunctionCallItem): void;
84
+ addCustomToolCall(call: CustomToolCallItem): void;
85
+ private addTool;
86
+ get toolCallCount(): number;
87
+ /** Emits a complete item as-is (added and done together). */
88
+ addItem(item: Record<string, unknown>): void;
89
+ private flushAll;
90
+ complete(usage: Usage | undefined, endTurn?: boolean): void;
91
+ /** Fails the response. Tool calls that were not emitted yet are dropped. */
92
+ fail(error: Record<string, unknown>): void;
93
+ incomplete(reason: string, usage: Usage | undefined): void;
94
+ }
95
+ export {};