@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.
- package/LICENSE +202 -0
- package/NOTICE +13 -0
- package/README.md +40 -2
- package/catalog/README.md +63 -0
- package/catalog/claude-opus-5-5.json +194 -0
- package/catalog/claude-sonnet-5-5.json +194 -0
- package/catalog/deepseek-flash.json +203 -0
- package/catalog/gpt-5.6-sol.json +152 -0
- package/catalog/gpt-6-astra.json +184 -0
- package/catalog/gpt-6-luna.json +178 -0
- package/catalog/gpt-6-sol.json +182 -0
- package/catalog/gpt-6.1-sol.json +187 -0
- package/dist/adapter-options.d.ts +5 -0
- package/dist/adapter-options.js +41 -0
- package/dist/auth.d.ts +2 -0
- package/dist/auth.js +42 -0
- package/dist/backends/anthropic-tools.d.ts +13 -0
- package/dist/backends/anthropic-tools.js +41 -0
- package/dist/backends/anthropic.d.ts +9 -0
- package/dist/backends/anthropic.js +356 -0
- package/dist/backends/chat.d.ts +16 -0
- package/dist/backends/chat.js +284 -0
- package/dist/backends/deepseek.d.ts +6 -0
- package/dist/backends/deepseek.js +37 -0
- package/dist/backends/responses.d.ts +5 -0
- package/dist/backends/responses.js +227 -0
- package/dist/carrier.d.ts +22 -0
- package/dist/carrier.js +61 -0
- package/dist/catalog.d.ts +8 -0
- package/dist/catalog.js +40 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +64 -0
- package/dist/compaction-handoff.d.ts +13 -0
- package/dist/compaction-handoff.js +126 -0
- package/dist/compaction-history.d.ts +7 -0
- package/dist/compaction-history.js +20 -0
- package/dist/compaction.d.ts +20 -0
- package/dist/compaction.js +134 -0
- package/dist/config.d.ts +6 -0
- package/dist/config.js +170 -0
- package/dist/errors.d.ts +43 -0
- package/dist/errors.js +141 -0
- package/dist/headers.d.ts +6 -0
- package/dist/headers.js +39 -0
- package/dist/history.d.ts +7 -0
- package/dist/history.js +85 -0
- package/dist/ids.d.ts +1 -0
- package/dist/ids.js +4 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +4 -0
- package/dist/inspect/capture.d.ts +119 -0
- package/dist/inspect/capture.js +370 -0
- package/dist/inspect/http.d.ts +7 -0
- package/dist/inspect/http.js +149 -0
- package/dist/inspect/view.d.ts +239 -0
- package/dist/inspect/view.js +388 -0
- package/dist/model-catalog.d.ts +18 -0
- package/dist/model-catalog.js +16 -0
- package/dist/profiles.d.ts +6 -0
- package/dist/profiles.js +63 -0
- package/dist/prompts.d.ts +5 -0
- package/dist/prompts.js +118 -0
- package/dist/server.d.ts +4 -0
- package/dist/server.js +232 -0
- package/dist/sse.d.ts +12 -0
- package/dist/sse.js +93 -0
- package/dist/tool-history.d.ts +4 -0
- package/dist/tool-history.js +73 -0
- package/dist/tools.d.ts +35 -0
- package/dist/tools.js +193 -0
- package/dist/types.d.ts +125 -0
- package/dist/types.js +1 -0
- package/dist/upstream.d.ts +3 -0
- package/dist/upstream.js +89 -0
- package/dist/writer.d.ts +95 -0
- package/dist/writer.js +430 -0
- package/docs/backends-anthropic.md +88 -0
- package/docs/backends-deepseek-chat.md +75 -0
- package/docs/backends-responses.md +33 -0
- package/docs/compaction.md +180 -0
- package/docs/config.md +271 -0
- package/docs/design.md +97 -0
- package/docs/inspect.md +148 -0
- package/docs/reasoning.md +72 -0
- package/docs/releasing.md +50 -0
- package/docs/responses-stream.md +90 -0
- package/docs/testing.md +177 -0
- package/docs/tools.md +68 -0
- package/examples/config.json +35 -0
- package/examples/gpt-claude.json +27 -0
- package/package.json +46 -4
- package/ui/api.js +64 -0
- package/ui/app.css +379 -0
- package/ui/app.js +489 -0
- package/ui/detail.js +713 -0
- package/ui/diff.js +281 -0
- package/ui/dom.js +258 -0
- package/ui/events.js +376 -0
- package/ui/favicon.svg +1 -0
- package/ui/index.html +58 -0
- package/ui/labels.js +106 -0
- package/ui/list.js +180 -0
- package/ui/structure.js +285 -0
- package/ui/tree.js +158 -0
package/dist/errors.js
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { forwardResponseHeaders } from "./headers.js";
|
|
2
|
+
/** Native Responses HTTP failures retain their transport-level meaning. */
|
|
3
|
+
export class UpstreamHttpError extends Error {
|
|
4
|
+
status;
|
|
5
|
+
body;
|
|
6
|
+
headers;
|
|
7
|
+
constructor(status, body, headers) {
|
|
8
|
+
super(`Upstream returned HTTP ${status}`);
|
|
9
|
+
this.name = "UpstreamHttpError";
|
|
10
|
+
this.status = status;
|
|
11
|
+
this.body = body;
|
|
12
|
+
this.headers = headers;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/** A Responses failure belongs to the SSE protocol, not HTTP classification. */
|
|
16
|
+
export class ResponsesStreamError extends Error {
|
|
17
|
+
error;
|
|
18
|
+
response;
|
|
19
|
+
event;
|
|
20
|
+
headers;
|
|
21
|
+
constructor(error, response, event, headers) {
|
|
22
|
+
super(typeof error.message === "string" ? error.message : "The upstream response failed");
|
|
23
|
+
this.name = "ResponsesStreamError";
|
|
24
|
+
this.error = error;
|
|
25
|
+
this.response = response;
|
|
26
|
+
this.event = event;
|
|
27
|
+
this.headers = headers;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/** An incomplete response has its own client termination and usage semantics. */
|
|
31
|
+
export class ResponsesIncompleteError extends Error {
|
|
32
|
+
response;
|
|
33
|
+
event;
|
|
34
|
+
constructor(response, event) {
|
|
35
|
+
super(`The upstream response is incomplete: ${String(response.incomplete_details?.reason ?? "unknown")}`);
|
|
36
|
+
this.name = "ResponsesIncompleteError";
|
|
37
|
+
this.response = response;
|
|
38
|
+
this.event = event;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/** Client retry classification is separate from the unmodified upstream failure. */
|
|
42
|
+
export class BridgeError extends Error {
|
|
43
|
+
code;
|
|
44
|
+
status;
|
|
45
|
+
headers;
|
|
46
|
+
upstream;
|
|
47
|
+
constructor(message, code = "invalid_prompt", status = 400, headers, options) {
|
|
48
|
+
super(message, options);
|
|
49
|
+
this.name = "BridgeError";
|
|
50
|
+
this.code = code;
|
|
51
|
+
this.status = status;
|
|
52
|
+
this.headers = headers;
|
|
53
|
+
this.upstream = options?.upstream;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function record(value) {
|
|
57
|
+
return value !== null && typeof value === "object" ? value : undefined;
|
|
58
|
+
}
|
|
59
|
+
function retryAfter(value) {
|
|
60
|
+
if (value instanceof Headers)
|
|
61
|
+
return value.get("retry-after") ?? undefined;
|
|
62
|
+
for (const [name, content] of Object.entries(record(value) ?? {})) {
|
|
63
|
+
if (name.toLowerCase() === "retry-after" && (typeof content === "string" || typeof content === "number"))
|
|
64
|
+
return String(content);
|
|
65
|
+
}
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
/** Keep native fields; only supplement missing retry advice from HTTP headers. */
|
|
69
|
+
export function responsesStreamError(payload, headers, event) {
|
|
70
|
+
const envelope = record(payload);
|
|
71
|
+
const response = envelope?.error !== undefined && (envelope.object === "response" || typeof envelope.status === "string" ||
|
|
72
|
+
(event?.type === "response.failed" && event.response !== undefined)) ? envelope : undefined;
|
|
73
|
+
let error = record(envelope?.error ?? payload) ?? {};
|
|
74
|
+
const delay = retryAfter(headers);
|
|
75
|
+
if (delay !== undefined && retryAfter(error.headers) === undefined) {
|
|
76
|
+
error = { ...error, headers: { ...record(error.headers), "retry-after": delay } };
|
|
77
|
+
}
|
|
78
|
+
return new ResponsesStreamError(error, response ? { ...response, error } : undefined, event, headers);
|
|
79
|
+
}
|
|
80
|
+
/** Translate non-Responses protocols into errors understood by the client. */
|
|
81
|
+
export function upstreamError(status, payload, headers) {
|
|
82
|
+
const envelope = record(payload);
|
|
83
|
+
const raw = envelope?.error ?? payload;
|
|
84
|
+
const error = record(raw);
|
|
85
|
+
const message = typeof error?.message === "string" ? error.message
|
|
86
|
+
: typeof raw === "string" && raw.length ? raw
|
|
87
|
+
: status !== undefined ? `Upstream returned HTTP ${status}` : "The upstream response failed";
|
|
88
|
+
const kind = [error?.code, error?.type].filter((value) => typeof value === "string").join(" ");
|
|
89
|
+
let code;
|
|
90
|
+
if (/context_length|too_many_tokens/.test(kind) || /prompt is too long|maximum context length|too many tokens/i.test(message))
|
|
91
|
+
code = "context_length_exceeded";
|
|
92
|
+
else if (/quota|billing|credit|balance/.test(kind) || /insufficient (quota|credit|balance)/i.test(message))
|
|
93
|
+
code = "insufficient_quota";
|
|
94
|
+
else if (status === 429 || /rate_limit|slow_down/.test(kind))
|
|
95
|
+
code = "rate_limit_exceeded";
|
|
96
|
+
else if (status === 503 || status === 529 || /overload/.test(kind))
|
|
97
|
+
code = "server_is_overloaded";
|
|
98
|
+
else if (/stream_error/.test(kind))
|
|
99
|
+
code = "stream_error";
|
|
100
|
+
else if (/invalid|authentication|permission|not_found/.test(kind))
|
|
101
|
+
code = "invalid_prompt";
|
|
102
|
+
else
|
|
103
|
+
code = status !== undefined && status < 500 ? "invalid_prompt" : "upstream_error";
|
|
104
|
+
const mappedStatus = code === "rate_limit_exceeded" || code === "insufficient_quota" ? 429
|
|
105
|
+
: code === "server_is_overloaded" ? 503
|
|
106
|
+
: code === "invalid_prompt" || code === "context_length_exceeded" ? 400 : 502;
|
|
107
|
+
const delay = retryAfter(headers) ?? retryAfter(error?.headers) ?? retryAfter(envelope?.headers);
|
|
108
|
+
const forwarded = headers ? forwardResponseHeaders(headers) : {};
|
|
109
|
+
if (delay !== undefined)
|
|
110
|
+
forwarded["retry-after"] = delay;
|
|
111
|
+
return new BridgeError(message, code, status ?? mappedStatus, Object.keys(forwarded).length ? forwarded : undefined, {
|
|
112
|
+
upstream: { ...(status !== undefined ? { status } : {}), body: payload },
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
function transportFailure(value, seen = new Set()) {
|
|
116
|
+
const error = record(value);
|
|
117
|
+
const result = { message: typeof error?.message === "string" ? error.message : typeof value === "string" ? value : "Upstream request failed" };
|
|
118
|
+
if (seen.has(value))
|
|
119
|
+
return result;
|
|
120
|
+
seen.add(value);
|
|
121
|
+
if (typeof error?.name === "string")
|
|
122
|
+
result.name = error.name;
|
|
123
|
+
if (typeof error?.code === "string")
|
|
124
|
+
result.code = error.code;
|
|
125
|
+
if (error?.cause !== undefined)
|
|
126
|
+
result.cause = transportFailure(error.cause, seen);
|
|
127
|
+
if (Array.isArray(error?.errors))
|
|
128
|
+
result.errors = error.errors.map((cause) => transportFailure(cause, seen));
|
|
129
|
+
return result;
|
|
130
|
+
}
|
|
131
|
+
function transportMessage(error) {
|
|
132
|
+
const own = error.code ? `${error.message} (${error.code})` : error.message;
|
|
133
|
+
return [own, ...(error.cause ? [transportMessage(error.cause)] : []), ...(error.errors?.map(transportMessage) ?? [])].filter(Boolean).join(": ");
|
|
134
|
+
}
|
|
135
|
+
/** Pick only diagnostics; fetch options and credential-command output must not escape. */
|
|
136
|
+
export function transportError(cause) {
|
|
137
|
+
if (cause instanceof BridgeError)
|
|
138
|
+
return cause;
|
|
139
|
+
const failure = transportFailure(cause);
|
|
140
|
+
return new BridgeError(transportMessage(failure), "upstream_error", 502, undefined, { cause: failure });
|
|
141
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { IncomingHttpHeaders } from "node:http";
|
|
2
|
+
export type HeaderRecord = Record<string, string | string[]>;
|
|
3
|
+
export declare function incomingHeaders(input: IncomingHttpHeaders): Headers;
|
|
4
|
+
/** Credentials belong to the selected upstream, never to the bridge client. */
|
|
5
|
+
export declare function forwardRequestHeaders(input?: Headers, authHeader?: string): Headers;
|
|
6
|
+
export declare function forwardResponseHeaders(input: Headers, rewritten?: boolean): HeaderRecord;
|
package/dist/headers.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const HOP_BY_HOP = ["connection", "keep-alive", "proxy-authenticate", "proxy-authorization", "proxy-connection", "te", "trailer", "transfer-encoding", "upgrade"];
|
|
2
|
+
/** Each HTTP leg owns its framing; metadata is forwarded unless it conflicts. */
|
|
3
|
+
function withoutTransportHeaders(input) {
|
|
4
|
+
const headers = new Headers(input);
|
|
5
|
+
const connection = (headers.get("connection") ?? "").split(",").map(name => name.trim()).filter(Boolean);
|
|
6
|
+
for (const name of [...connection, ...HOP_BY_HOP, "content-length", "content-encoding", "content-md5", "digest", "content-digest", "repr-digest"])
|
|
7
|
+
headers.delete(name);
|
|
8
|
+
return headers;
|
|
9
|
+
}
|
|
10
|
+
export function incomingHeaders(input) {
|
|
11
|
+
const headers = new Headers();
|
|
12
|
+
for (const [name, value] of Object.entries(input)) {
|
|
13
|
+
for (const item of Array.isArray(value) ? value : value === undefined ? [] : [value])
|
|
14
|
+
headers.append(name, item);
|
|
15
|
+
}
|
|
16
|
+
return headers;
|
|
17
|
+
}
|
|
18
|
+
/** Credentials belong to the selected upstream, never to the bridge client. */
|
|
19
|
+
export function forwardRequestHeaders(input, authHeader) {
|
|
20
|
+
const headers = withoutTransportHeaders(input);
|
|
21
|
+
for (const name of ["host", "accept-encoding", "authorization", "x-api-key", "api-key", "cookie", ...(authHeader ? [authHeader] : [])])
|
|
22
|
+
headers.delete(name);
|
|
23
|
+
return headers;
|
|
24
|
+
}
|
|
25
|
+
export function forwardResponseHeaders(input, rewritten = true) {
|
|
26
|
+
const headers = withoutTransportHeaders(input);
|
|
27
|
+
// The catalog belongs to the bridge even when the selected upstream also
|
|
28
|
+
// serves Codex. Rewritten bodies need their own content type.
|
|
29
|
+
headers.delete("x-models-etag");
|
|
30
|
+
if (rewritten) {
|
|
31
|
+
headers.delete("content-type");
|
|
32
|
+
headers.delete("etag");
|
|
33
|
+
}
|
|
34
|
+
const result = Object.fromEntries(headers);
|
|
35
|
+
const cookies = headers.getSetCookie();
|
|
36
|
+
if (cookies.length)
|
|
37
|
+
result["set-cookie"] = cookies;
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type CompactionCarrier, type StatePayload } from "./carrier.ts";
|
|
2
|
+
import type { ResolvedModel, ResponsesRequest } from "./types.ts";
|
|
3
|
+
/** Replay policy for decoded state. The inspector reports the same decisions. */
|
|
4
|
+
export declare function replaysReasoning(carrier: StatePayload, route: ResolvedModel): boolean;
|
|
5
|
+
export declare function restoresNativeCompaction(carrier: CompactionCarrier, route: ResolvedModel): boolean;
|
|
6
|
+
/** Selects model-specific opaque state without changing the stored history. */
|
|
7
|
+
export declare function prepareHistory(input: ResponsesRequest["input"], route: ResolvedModel): Record<string, any>[];
|
package/dist/history.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { decodeCompaction, decodeReasoning } from "./carrier.js";
|
|
2
|
+
import { BridgeError } from "./errors.js";
|
|
3
|
+
import { SUMMARY_PREFIX } from "./prompts.js";
|
|
4
|
+
import { translateToolHistory } from "./tool-history.js";
|
|
5
|
+
/** Replay policy for decoded state. The inspector reports the same decisions. */
|
|
6
|
+
export function replaysReasoning(carrier, route) {
|
|
7
|
+
return route.replay.reasoning.has(carrier.source.id) && carrier.format === route.profile.reasoning_format;
|
|
8
|
+
}
|
|
9
|
+
export function restoresNativeCompaction(carrier, route) {
|
|
10
|
+
return !!carrier.native && route.compaction.native_replay &&
|
|
11
|
+
route.replay.native_compaction.has(carrier.native.source.id) &&
|
|
12
|
+
carrier.native.format === route.profile.native_compaction_format;
|
|
13
|
+
}
|
|
14
|
+
/** Selects model-specific opaque state without changing the stored history. */
|
|
15
|
+
export function prepareHistory(input, route) {
|
|
16
|
+
if (typeof input === "string") {
|
|
17
|
+
return [{ type: "message", role: "user", content: [{ type: "input_text", text: input }] }];
|
|
18
|
+
}
|
|
19
|
+
if (input === undefined)
|
|
20
|
+
return [];
|
|
21
|
+
if (!Array.isArray(input))
|
|
22
|
+
throw new BridgeError("input must be a string or an array of items");
|
|
23
|
+
const result = [];
|
|
24
|
+
for (const original of input) {
|
|
25
|
+
if (!original || typeof original !== "object" || Array.isArray(original)) {
|
|
26
|
+
throw new BridgeError("Each input item must be an object");
|
|
27
|
+
}
|
|
28
|
+
const item = structuredClone(original);
|
|
29
|
+
if (item.type === "bridge_reasoning") {
|
|
30
|
+
throw new BridgeError("Internal reasoning items cannot be supplied as request history");
|
|
31
|
+
}
|
|
32
|
+
if (item.type === "item_reference") {
|
|
33
|
+
throw new BridgeError("Stored item references are unsupported; send the complete conversation items");
|
|
34
|
+
}
|
|
35
|
+
if (item.type === "reasoning") {
|
|
36
|
+
const carrier = decodeReasoning(item.encrypted_content);
|
|
37
|
+
if (carrier && replaysReasoning(carrier, route)) {
|
|
38
|
+
result.push({ type: "bridge_reasoning", state: carrier, summary: item.summary ?? [] });
|
|
39
|
+
}
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
if (item.type === "agent_message" && route.profile.api !== "responses") {
|
|
43
|
+
if (typeof item.author !== "string" || typeof item.recipient !== "string" || !Array.isArray(item.content)) {
|
|
44
|
+
throw new BridgeError("An agent message requires author, recipient, and content");
|
|
45
|
+
}
|
|
46
|
+
if (item.encrypted_content || item.content.some((part) => part?.type === "encrypted_content")) {
|
|
47
|
+
throw new BridgeError("Encrypted agent messages are unsupported on this backend; use plaintext agent messages");
|
|
48
|
+
}
|
|
49
|
+
for (const part of item.content) {
|
|
50
|
+
if (!["input_text", "input_image"].includes(part?.type)) {
|
|
51
|
+
throw new BridgeError(`Unsupported agent message content: ${String(part?.type)}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
result.push({
|
|
55
|
+
type: "message", role: "user",
|
|
56
|
+
content: [
|
|
57
|
+
{ type: "input_text", text: `Agent message from ${JSON.stringify(item.author)} to ${JSON.stringify(item.recipient)}:\n` },
|
|
58
|
+
...item.content,
|
|
59
|
+
],
|
|
60
|
+
});
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (item.type === "compaction" || item.type === "compaction_summary") {
|
|
64
|
+
const carrier = decodeCompaction(item.encrypted_content);
|
|
65
|
+
if (!carrier) {
|
|
66
|
+
throw new BridgeError("This compaction item has no portable summary or handoff recipe; use history created through this bridge");
|
|
67
|
+
}
|
|
68
|
+
if (restoresNativeCompaction(carrier, route)) {
|
|
69
|
+
result.push(carrier.native.data);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
if (!carrier.summary)
|
|
73
|
+
throw new BridgeError("Deferred compaction summary has not been materialized");
|
|
74
|
+
result.push({
|
|
75
|
+
type: "message",
|
|
76
|
+
role: "user",
|
|
77
|
+
content: [{ type: "input_text", text: `${SUMMARY_PREFIX}\n\n${carrier.summary}` }],
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
result.push(item);
|
|
83
|
+
}
|
|
84
|
+
return route.profile.api === "responses" ? result : translateToolHistory(result);
|
|
85
|
+
}
|
package/dist/ids.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function newId(prefix: string): string;
|
package/dist/ids.js
ADDED
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { createBridgeServer } from "./server.ts";
|
|
2
|
+
export { loadConfig, validateConfig, resolveModel } from "./config.ts";
|
|
3
|
+
export { buildCatalog, configSnippet } from "./catalog.ts";
|
|
4
|
+
export { BridgeError } from "./errors.ts";
|
|
5
|
+
export type { BridgeConfig, UpstreamConfig, ModelConfig } from "./types.ts";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import type { IncomingHttpHeaders, IncomingMessage, OutgoingHttpHeaders, ServerResponse } from "node:http";
|
|
2
|
+
import type { BridgeConfig, ResolvedModel, ResponsesRequest } from "../types.ts";
|
|
3
|
+
export declare const DEFAULT_CAPTURE_MIB = 256;
|
|
4
|
+
export type EndKind = "active" | "complete" | "cancelled" | "error" | "unread";
|
|
5
|
+
export type HeaderMap = Record<string, string>;
|
|
6
|
+
export interface Part {
|
|
7
|
+
t: number;
|
|
8
|
+
text: string;
|
|
9
|
+
}
|
|
10
|
+
/** Lowercase names, join repeated values, and redact credentials. */
|
|
11
|
+
export declare function headerMap(headers: Headers | IncomingHttpHeaders | OutgoingHttpHeaders | undefined, extra?: ReadonlySet<string>): HeaderMap;
|
|
12
|
+
/** One HTTP message after its start line: status, headers, and timed body parts. */
|
|
13
|
+
export declare class Message {
|
|
14
|
+
status?: number;
|
|
15
|
+
statusText?: string;
|
|
16
|
+
headers?: HeaderMap;
|
|
17
|
+
headersMs?: number;
|
|
18
|
+
endedMs?: number;
|
|
19
|
+
end: EndKind;
|
|
20
|
+
error?: string;
|
|
21
|
+
readonly parts: Part[];
|
|
22
|
+
bytes: number;
|
|
23
|
+
private readonly decoder;
|
|
24
|
+
private readonly exchange;
|
|
25
|
+
constructor(exchange: Exchange);
|
|
26
|
+
head(status: number, statusText: string | undefined, headers: HeaderMap): void;
|
|
27
|
+
push(chunk: Uint8Array | string): void;
|
|
28
|
+
finish(end: Exclude<EndKind, "active">, error?: unknown): void;
|
|
29
|
+
text(): string;
|
|
30
|
+
discard(): void;
|
|
31
|
+
}
|
|
32
|
+
/** One request from the bridge to an upstream. */
|
|
33
|
+
export declare class Call {
|
|
34
|
+
readonly index: number;
|
|
35
|
+
readonly label: string;
|
|
36
|
+
readonly startedMs: number;
|
|
37
|
+
readonly method = "POST";
|
|
38
|
+
readonly url: string;
|
|
39
|
+
readonly headers: HeaderMap;
|
|
40
|
+
text: string;
|
|
41
|
+
bytes: number;
|
|
42
|
+
error?: string;
|
|
43
|
+
response?: Message;
|
|
44
|
+
private readonly exchange;
|
|
45
|
+
constructor(exchange: Exchange, label: string, url: string, headers: HeaderMap, text: string);
|
|
46
|
+
received(response: Response): void;
|
|
47
|
+
chunk(value: Uint8Array): void;
|
|
48
|
+
done(end: Exclude<EndKind, "active">, error?: unknown): void;
|
|
49
|
+
failed(error: unknown): void;
|
|
50
|
+
discard(): void;
|
|
51
|
+
}
|
|
52
|
+
export interface RequestMeta {
|
|
53
|
+
model: string | null;
|
|
54
|
+
kind: "turn" | "compaction" | "invalid";
|
|
55
|
+
stream: boolean | null;
|
|
56
|
+
input_items: number | null;
|
|
57
|
+
preview: string | null;
|
|
58
|
+
}
|
|
59
|
+
/** One client request and everything it caused. */
|
|
60
|
+
export declare class Exchange {
|
|
61
|
+
readonly id: string;
|
|
62
|
+
readonly seq: number;
|
|
63
|
+
rev: number;
|
|
64
|
+
readonly startedAt: number;
|
|
65
|
+
durationMs?: number;
|
|
66
|
+
closed: boolean;
|
|
67
|
+
readonly method: string;
|
|
68
|
+
readonly path: string;
|
|
69
|
+
readonly headers: HeaderMap;
|
|
70
|
+
requestText?: string;
|
|
71
|
+
requestBytes: number;
|
|
72
|
+
meta: RequestMeta;
|
|
73
|
+
route?: ResolvedModel;
|
|
74
|
+
responsesLite?: boolean;
|
|
75
|
+
readonly calls: Call[];
|
|
76
|
+
readonly response: Message;
|
|
77
|
+
bytes: number;
|
|
78
|
+
readonly inspector: Inspector;
|
|
79
|
+
private readonly t0;
|
|
80
|
+
constructor(inspector: Inspector, seq: number, req: IncomingMessage, res: ServerResponse);
|
|
81
|
+
now(): number;
|
|
82
|
+
touch(): void;
|
|
83
|
+
account(bytes: number): void;
|
|
84
|
+
received(text: string): void;
|
|
85
|
+
parsed(request: ResponsesRequest): void;
|
|
86
|
+
routed(route: ResolvedModel, responsesLite: boolean): void;
|
|
87
|
+
/** Records what the bridge writes, at the same calls that write it. */
|
|
88
|
+
private tap;
|
|
89
|
+
private close;
|
|
90
|
+
/** Releases captured data without stopping the underlying HTTP exchange. */
|
|
91
|
+
discard(): void;
|
|
92
|
+
}
|
|
93
|
+
/** Process-wide capture store. Nothing is kept unless capture is on. */
|
|
94
|
+
export declare class Inspector {
|
|
95
|
+
capturing: boolean;
|
|
96
|
+
readonly maxBytes: number;
|
|
97
|
+
bytes: number;
|
|
98
|
+
evicted: number;
|
|
99
|
+
rev: number;
|
|
100
|
+
private seq;
|
|
101
|
+
readonly startedAt: number;
|
|
102
|
+
readonly exchanges: Map<string, Exchange>;
|
|
103
|
+
readonly config: BridgeConfig;
|
|
104
|
+
private readonly redactions;
|
|
105
|
+
constructor(config: BridgeConfig);
|
|
106
|
+
/** Runs one server request with a slot for its exchange. */
|
|
107
|
+
scope<T>(fn: () => T): T;
|
|
108
|
+
begin(req: IncomingMessage, res: ServerResponse): Exchange | undefined;
|
|
109
|
+
/** Records one upstream request made inside the current exchange. */
|
|
110
|
+
upstream(url: string, headers: Headers, text: string): Call | undefined;
|
|
111
|
+
account(exchange: Exchange, bytes: number): void;
|
|
112
|
+
/** Rechecks the soft cap when bytes arrive or an active exchange closes. */
|
|
113
|
+
evict(): void;
|
|
114
|
+
clear(): void;
|
|
115
|
+
}
|
|
116
|
+
/** Labels upstream calls made inside fn, such as native compaction or a handoff. */
|
|
117
|
+
export declare function withCaptureLabel<T>(label: string, fn: () => T): T;
|
|
118
|
+
/** Records an upstream request when the current server request is being captured. */
|
|
119
|
+
export declare function captureUpstream(url: string, headers: Headers, text: string): Call | undefined;
|