@uncensoredcode/openbridge 0.1.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.
- package/README.md +117 -0
- package/bin/openbridge.js +10 -0
- package/package.json +85 -0
- package/packages/cli/dist/args.d.ts +30 -0
- package/packages/cli/dist/args.js +160 -0
- package/packages/cli/dist/cli.d.ts +2 -0
- package/packages/cli/dist/cli.js +9 -0
- package/packages/cli/dist/index.d.ts +26 -0
- package/packages/cli/dist/index.js +76 -0
- package/packages/runtime/dist/assistant-protocol.d.ts +34 -0
- package/packages/runtime/dist/assistant-protocol.js +121 -0
- package/packages/runtime/dist/execution/in-process.d.ts +14 -0
- package/packages/runtime/dist/execution/in-process.js +45 -0
- package/packages/runtime/dist/execution/types.d.ts +49 -0
- package/packages/runtime/dist/execution/types.js +20 -0
- package/packages/runtime/dist/index.d.ts +86 -0
- package/packages/runtime/dist/index.js +60 -0
- package/packages/runtime/dist/normalizers/index.d.ts +6 -0
- package/packages/runtime/dist/normalizers/index.js +12 -0
- package/packages/runtime/dist/normalizers/legacy-packet.d.ts +6 -0
- package/packages/runtime/dist/normalizers/legacy-packet.js +131 -0
- package/packages/runtime/dist/output-sanitizer.d.ts +23 -0
- package/packages/runtime/dist/output-sanitizer.js +78 -0
- package/packages/runtime/dist/packet-extractor.d.ts +17 -0
- package/packages/runtime/dist/packet-extractor.js +43 -0
- package/packages/runtime/dist/packet-normalizer.d.ts +21 -0
- package/packages/runtime/dist/packet-normalizer.js +47 -0
- package/packages/runtime/dist/prompt-compiler.d.ts +28 -0
- package/packages/runtime/dist/prompt-compiler.js +301 -0
- package/packages/runtime/dist/protocol.d.ts +44 -0
- package/packages/runtime/dist/protocol.js +165 -0
- package/packages/runtime/dist/provider-failure.d.ts +52 -0
- package/packages/runtime/dist/provider-failure.js +236 -0
- package/packages/runtime/dist/provider.d.ts +40 -0
- package/packages/runtime/dist/provider.js +1 -0
- package/packages/runtime/dist/runtime.d.ts +86 -0
- package/packages/runtime/dist/runtime.js +462 -0
- package/packages/runtime/dist/session-bound-provider.d.ts +52 -0
- package/packages/runtime/dist/session-bound-provider.js +366 -0
- package/packages/runtime/dist/tool-name-aliases.d.ts +5 -0
- package/packages/runtime/dist/tool-name-aliases.js +13 -0
- package/packages/runtime/dist/tools/bash.d.ts +9 -0
- package/packages/runtime/dist/tools/bash.js +157 -0
- package/packages/runtime/dist/tools/edit.d.ts +9 -0
- package/packages/runtime/dist/tools/edit.js +94 -0
- package/packages/runtime/dist/tools/index.d.ts +39 -0
- package/packages/runtime/dist/tools/index.js +27 -0
- package/packages/runtime/dist/tools/list-dir.d.ts +9 -0
- package/packages/runtime/dist/tools/list-dir.js +127 -0
- package/packages/runtime/dist/tools/read.d.ts +9 -0
- package/packages/runtime/dist/tools/read.js +56 -0
- package/packages/runtime/dist/tools/registry.d.ts +15 -0
- package/packages/runtime/dist/tools/registry.js +38 -0
- package/packages/runtime/dist/tools/runtime-path.d.ts +7 -0
- package/packages/runtime/dist/tools/runtime-path.js +22 -0
- package/packages/runtime/dist/tools/search-files.d.ts +9 -0
- package/packages/runtime/dist/tools/search-files.js +149 -0
- package/packages/runtime/dist/tools/text-file.d.ts +32 -0
- package/packages/runtime/dist/tools/text-file.js +101 -0
- package/packages/runtime/dist/tools/workspace-path.d.ts +17 -0
- package/packages/runtime/dist/tools/workspace-path.js +70 -0
- package/packages/runtime/dist/tools/write.d.ts +9 -0
- package/packages/runtime/dist/tools/write.js +59 -0
- package/packages/server/dist/bridge/bridge-model-catalog.d.ts +56 -0
- package/packages/server/dist/bridge/bridge-model-catalog.js +100 -0
- package/packages/server/dist/bridge/bridge-runtime-service.d.ts +61 -0
- package/packages/server/dist/bridge/bridge-runtime-service.js +1386 -0
- package/packages/server/dist/bridge/chat-completions/chat-completion-service.d.ts +127 -0
- package/packages/server/dist/bridge/chat-completions/chat-completion-service.js +1026 -0
- package/packages/server/dist/bridge/index.d.ts +335 -0
- package/packages/server/dist/bridge/index.js +45 -0
- package/packages/server/dist/bridge/live-provider-extraction-canary.d.ts +69 -0
- package/packages/server/dist/bridge/live-provider-extraction-canary.js +186 -0
- package/packages/server/dist/bridge/providers/generic-provider-transport.d.ts +53 -0
- package/packages/server/dist/bridge/providers/generic-provider-transport.js +973 -0
- package/packages/server/dist/bridge/providers/provider-session-resolver.d.ts +17 -0
- package/packages/server/dist/bridge/providers/provider-session-resolver.js +95 -0
- package/packages/server/dist/bridge/providers/provider-streams.d.ts +80 -0
- package/packages/server/dist/bridge/providers/provider-streams.js +844 -0
- package/packages/server/dist/bridge/providers/provider-transport-profile.d.ts +194 -0
- package/packages/server/dist/bridge/providers/provider-transport-profile.js +198 -0
- package/packages/server/dist/bridge/providers/web-provider-transport.d.ts +30 -0
- package/packages/server/dist/bridge/providers/web-provider-transport.js +151 -0
- package/packages/server/dist/bridge/state/file-bridge-state-store.d.ts +36 -0
- package/packages/server/dist/bridge/state/file-bridge-state-store.js +164 -0
- package/packages/server/dist/bridge/stores/local-session-package-store.d.ts +23 -0
- package/packages/server/dist/bridge/stores/local-session-package-store.js +548 -0
- package/packages/server/dist/bridge/stores/provider-store.d.ts +94 -0
- package/packages/server/dist/bridge/stores/provider-store.js +143 -0
- package/packages/server/dist/bridge/stores/session-backed-provider-store.d.ts +7 -0
- package/packages/server/dist/bridge/stores/session-backed-provider-store.js +26 -0
- package/packages/server/dist/bridge/stores/session-package-store.d.ts +286 -0
- package/packages/server/dist/bridge/stores/session-package-store.js +1527 -0
- package/packages/server/dist/bridge/stores/session-store.d.ts +120 -0
- package/packages/server/dist/bridge/stores/session-store.js +139 -0
- package/packages/server/dist/cli/index.d.ts +9 -0
- package/packages/server/dist/cli/index.js +6 -0
- package/packages/server/dist/cli/main.d.ts +2 -0
- package/packages/server/dist/cli/main.js +9 -0
- package/packages/server/dist/cli/run-bridge-server-cli.d.ts +54 -0
- package/packages/server/dist/cli/run-bridge-server-cli.js +371 -0
- package/packages/server/dist/client/bridge-api-client.d.ts +61 -0
- package/packages/server/dist/client/bridge-api-client.js +267 -0
- package/packages/server/dist/client/index.d.ts +11 -0
- package/packages/server/dist/client/index.js +11 -0
- package/packages/server/dist/config/bridge-server-config.d.ts +52 -0
- package/packages/server/dist/config/bridge-server-config.js +118 -0
- package/packages/server/dist/config/index.d.ts +20 -0
- package/packages/server/dist/config/index.js +8 -0
- package/packages/server/dist/http/bridge-api-route-context.d.ts +14 -0
- package/packages/server/dist/http/bridge-api-route-context.js +1 -0
- package/packages/server/dist/http/create-bridge-api-server.d.ts +72 -0
- package/packages/server/dist/http/create-bridge-api-server.js +225 -0
- package/packages/server/dist/http/index.d.ts +5 -0
- package/packages/server/dist/http/index.js +5 -0
- package/packages/server/dist/http/parse-request.d.ts +6 -0
- package/packages/server/dist/http/parse-request.js +27 -0
- package/packages/server/dist/http/register-bridge-api-routes.d.ts +7 -0
- package/packages/server/dist/http/register-bridge-api-routes.js +17 -0
- package/packages/server/dist/http/routes/admin-routes.d.ts +7 -0
- package/packages/server/dist/http/routes/admin-routes.js +135 -0
- package/packages/server/dist/http/routes/chat-completions-route.d.ts +7 -0
- package/packages/server/dist/http/routes/chat-completions-route.js +49 -0
- package/packages/server/dist/http/routes/health-routes.d.ts +6 -0
- package/packages/server/dist/http/routes/health-routes.js +7 -0
- package/packages/server/dist/http/routes/message-routes.d.ts +7 -0
- package/packages/server/dist/http/routes/message-routes.js +7 -0
- package/packages/server/dist/index.d.ts +85 -0
- package/packages/server/dist/index.js +28 -0
- package/packages/server/dist/security/bridge-auth.d.ts +9 -0
- package/packages/server/dist/security/bridge-auth.js +41 -0
- package/packages/server/dist/security/cors-policy.d.ts +5 -0
- package/packages/server/dist/security/cors-policy.js +34 -0
- package/packages/server/dist/security/index.d.ts +16 -0
- package/packages/server/dist/security/index.js +12 -0
- package/packages/server/dist/security/redact-sensitive-values.d.ts +19 -0
- package/packages/server/dist/security/redact-sensitive-values.js +67 -0
- package/packages/server/dist/shared/api-schema.d.ts +133 -0
- package/packages/server/dist/shared/api-schema.js +1 -0
- package/packages/server/dist/shared/bridge-api-error.d.ts +17 -0
- package/packages/server/dist/shared/bridge-api-error.js +19 -0
- package/packages/server/dist/shared/index.d.ts +7 -0
- package/packages/server/dist/shared/index.js +7 -0
- package/packages/server/dist/shared/output.d.ts +5 -0
- package/packages/server/dist/shared/output.js +14 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { bridgeModule } from "../../bridge/index.js";
|
|
2
|
+
import { bridgeApiErrorModule } from "../../shared/bridge-api-error.js";
|
|
3
|
+
import { parseRequestModule } from "../parse-request.js";
|
|
4
|
+
const { buildModelListResponse, createModelRequestSchema, buildSessionPackageStatus, createProviderRequestSchema, modelMutationResponseSchema, createSessionRequestSchema, providerDeleteResponseSchema, providerIdParamsSchema, providerListResponseSchema, providerResponseSchema, sessionDeleteResponseSchema, sessionIdParamsSchema, sessionListResponseSchema, sessionPackageDeleteResponseSchema, sessionPackageSchema, sessionPackageStatusResponseSchema, sessionResponseSchema, updateProviderRequestSchema, updateSessionRequestSchema } = bridgeModule;
|
|
5
|
+
const { BridgeApiError } = bridgeApiErrorModule;
|
|
6
|
+
const { parseRequest } = parseRequestModule;
|
|
7
|
+
function registerAdminRoutes(app, context) {
|
|
8
|
+
app.get("/v1/models", async () => buildModelListResponse(context.providerStore.list()));
|
|
9
|
+
app.post("/v1/models", async (request, reply) => {
|
|
10
|
+
const body = parseRequest(createModelRequestSchema, request.body);
|
|
11
|
+
const provider = requireProvider(context, body.provider);
|
|
12
|
+
const modelId = body.model.trim();
|
|
13
|
+
const currentModels = Array.isArray(provider.config.models)
|
|
14
|
+
? provider.config.models.filter((value) => typeof value === "string")
|
|
15
|
+
: [];
|
|
16
|
+
const nextModels = [...new Set([...currentModels.map((value) => value.trim()), modelId])]
|
|
17
|
+
.filter(Boolean)
|
|
18
|
+
.sort((left, right) => left.localeCompare(right));
|
|
19
|
+
context.providerStore.update(provider.id, {
|
|
20
|
+
config: {
|
|
21
|
+
...provider.config,
|
|
22
|
+
models: nextModels
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
reply.code(201);
|
|
26
|
+
return modelMutationResponseSchema.parse({
|
|
27
|
+
ok: true,
|
|
28
|
+
providerId: provider.id,
|
|
29
|
+
modelId
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
app.get("/v1/providers", async () => providerListResponseSchema.parse({
|
|
33
|
+
providers: context.providerStore.list()
|
|
34
|
+
}));
|
|
35
|
+
app.post("/v1/providers", async (request, reply) => {
|
|
36
|
+
const body = parseRequest(createProviderRequestSchema, request.body);
|
|
37
|
+
const provider = context.providerStore.create(body);
|
|
38
|
+
reply.code(201);
|
|
39
|
+
return providerResponseSchema.parse({ provider });
|
|
40
|
+
});
|
|
41
|
+
app.get("/v1/providers/:id", async (request) => {
|
|
42
|
+
const params = parseRequest(providerIdParamsSchema, request.params);
|
|
43
|
+
const provider = context.providerStore.get(params.id);
|
|
44
|
+
if (!provider) {
|
|
45
|
+
throw providerNotFoundError(params.id);
|
|
46
|
+
}
|
|
47
|
+
return providerResponseSchema.parse({ provider });
|
|
48
|
+
});
|
|
49
|
+
app.patch("/v1/providers/:id", async (request) => {
|
|
50
|
+
const params = parseRequest(providerIdParamsSchema, request.params);
|
|
51
|
+
const body = parseRequest(updateProviderRequestSchema, request.body);
|
|
52
|
+
const provider = context.providerStore.update(params.id, body);
|
|
53
|
+
return providerResponseSchema.parse({ provider });
|
|
54
|
+
});
|
|
55
|
+
app.delete("/v1/providers/:id", async (request) => {
|
|
56
|
+
const params = parseRequest(providerIdParamsSchema, request.params);
|
|
57
|
+
const deleted = context.providerStore.delete(params.id);
|
|
58
|
+
return providerDeleteResponseSchema.parse(deleted);
|
|
59
|
+
});
|
|
60
|
+
app.put("/v1/providers/:id/session-package", async (request) => {
|
|
61
|
+
const params = parseRequest(providerIdParamsSchema, request.params);
|
|
62
|
+
const body = parseRequest(sessionPackageSchema, request.body);
|
|
63
|
+
const stored = context.sessionPackageStore.put(params.id, body);
|
|
64
|
+
return sessionPackageStatusResponseSchema.parse(buildSessionPackageStatus(params.id, stored));
|
|
65
|
+
});
|
|
66
|
+
app.get("/v1/providers/:id/session-package", async (request) => {
|
|
67
|
+
const params = parseRequest(providerIdParamsSchema, request.params);
|
|
68
|
+
requireProvider(context, params.id);
|
|
69
|
+
const stored = context.sessionPackageStore.getStatus(params.id);
|
|
70
|
+
if (!stored || !stored.hasSessionPackage) {
|
|
71
|
+
throw new BridgeApiError({
|
|
72
|
+
statusCode: 404,
|
|
73
|
+
code: "session_package_not_found",
|
|
74
|
+
message: `Provider '${params.id}' does not have a session package.`
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
return sessionPackageStatusResponseSchema.parse(buildSessionPackageStatus(params.id, stored));
|
|
78
|
+
});
|
|
79
|
+
app.delete("/v1/providers/:id/session-package", async (request) => {
|
|
80
|
+
const params = parseRequest(providerIdParamsSchema, request.params);
|
|
81
|
+
requireProvider(context, params.id);
|
|
82
|
+
return sessionPackageDeleteResponseSchema.parse(context.sessionPackageStore.deleteSession(params.id));
|
|
83
|
+
});
|
|
84
|
+
app.get("/v1/sessions", async () => sessionListResponseSchema.parse({
|
|
85
|
+
sessions: context.sessionStore.list()
|
|
86
|
+
}));
|
|
87
|
+
app.post("/v1/sessions", async (request, reply) => {
|
|
88
|
+
const body = parseRequest(createSessionRequestSchema, request.body);
|
|
89
|
+
const session = context.sessionStore.create(body);
|
|
90
|
+
reply.code(201);
|
|
91
|
+
return sessionResponseSchema.parse({ session });
|
|
92
|
+
});
|
|
93
|
+
app.get("/v1/sessions/:id", async (request) => {
|
|
94
|
+
const params = parseRequest(sessionIdParamsSchema, request.params);
|
|
95
|
+
const session = context.sessionStore.get(params.id);
|
|
96
|
+
if (!session) {
|
|
97
|
+
throw sessionNotFoundError(params.id);
|
|
98
|
+
}
|
|
99
|
+
return sessionResponseSchema.parse({ session });
|
|
100
|
+
});
|
|
101
|
+
app.patch("/v1/sessions/:id", async (request) => {
|
|
102
|
+
const params = parseRequest(sessionIdParamsSchema, request.params);
|
|
103
|
+
const body = parseRequest(updateSessionRequestSchema, request.body);
|
|
104
|
+
const session = context.sessionStore.update(params.id, body);
|
|
105
|
+
return sessionResponseSchema.parse({ session });
|
|
106
|
+
});
|
|
107
|
+
app.delete("/v1/sessions/:id", async (request) => {
|
|
108
|
+
const params = parseRequest(sessionIdParamsSchema, request.params);
|
|
109
|
+
return sessionDeleteResponseSchema.parse(context.sessionStore.delete(params.id));
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
function requireProvider(context, providerId) {
|
|
113
|
+
const provider = context.providerStore.get(providerId);
|
|
114
|
+
if (provider) {
|
|
115
|
+
return provider;
|
|
116
|
+
}
|
|
117
|
+
throw providerNotFoundError(providerId);
|
|
118
|
+
}
|
|
119
|
+
function providerNotFoundError(providerId) {
|
|
120
|
+
return new BridgeApiError({
|
|
121
|
+
statusCode: 404,
|
|
122
|
+
code: "provider_not_found",
|
|
123
|
+
message: `Provider '${providerId}' was not found.`
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
function sessionNotFoundError(sessionId) {
|
|
127
|
+
return new BridgeApiError({
|
|
128
|
+
statusCode: 404,
|
|
129
|
+
code: "session_not_found",
|
|
130
|
+
message: `Session '${sessionId}' was not found.`
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
export const adminRoutesModule = {
|
|
134
|
+
registerAdminRoutes
|
|
135
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { FastifyInstance } from "fastify";
|
|
2
|
+
import type { BridgeApiRouteContext } from "../bridge-api-route-context.ts";
|
|
3
|
+
declare function registerChatCompletionRoute(app: FastifyInstance, context: BridgeApiRouteContext): void;
|
|
4
|
+
export declare const chatCompletionsRouteModule: {
|
|
5
|
+
registerChatCompletionRoute: typeof registerChatCompletionRoute;
|
|
6
|
+
};
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { chatCompletionServiceModule } from "../../bridge/chat-completions/chat-completion-service.js";
|
|
2
|
+
import { fileBridgeStateStoreModule } from "../../bridge/state/file-bridge-state-store.js";
|
|
3
|
+
import { parseRequestModule } from "../parse-request.js";
|
|
4
|
+
const { chatCompletionsRequestSchema, handleBridgeChatCompletionRequest } = chatCompletionServiceModule;
|
|
5
|
+
const { FileBridgeStateStore } = fileBridgeStateStoreModule;
|
|
6
|
+
const { parseRequest } = parseRequestModule;
|
|
7
|
+
function registerChatCompletionRoute(app, context) {
|
|
8
|
+
const stateStore = new FileBridgeStateStore(context.config.stateRoot);
|
|
9
|
+
app.post("/v1/chat/completions", async (request, reply) => {
|
|
10
|
+
const body = parseRequest(chatCompletionsRequestSchema, request.body);
|
|
11
|
+
const execution = await handleBridgeChatCompletionRequest({
|
|
12
|
+
body,
|
|
13
|
+
headers: request.headers,
|
|
14
|
+
providerStore: context.providerStore,
|
|
15
|
+
service: context.service,
|
|
16
|
+
stateStore,
|
|
17
|
+
request: {
|
|
18
|
+
method: request.method,
|
|
19
|
+
url: request.url
|
|
20
|
+
},
|
|
21
|
+
onInternalError: context.onInternalError
|
|
22
|
+
});
|
|
23
|
+
if (execution.kind === "json") {
|
|
24
|
+
return execution.response;
|
|
25
|
+
}
|
|
26
|
+
reply.hijack();
|
|
27
|
+
reply.raw.writeHead(200, {
|
|
28
|
+
"Content-Type": "text/event-stream; charset=utf-8",
|
|
29
|
+
"Cache-Control": "no-store",
|
|
30
|
+
Connection: "keep-alive"
|
|
31
|
+
});
|
|
32
|
+
reply.raw.flushHeaders?.();
|
|
33
|
+
try {
|
|
34
|
+
for await (const event of execution.events) {
|
|
35
|
+
reply.raw.write(event === "[DONE]" ? "data: [DONE]\n\n" : formatSseData(event));
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
finally {
|
|
39
|
+
reply.raw.end();
|
|
40
|
+
}
|
|
41
|
+
return reply;
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function formatSseData(value) {
|
|
45
|
+
return `data: ${JSON.stringify(value)}\n\n`;
|
|
46
|
+
}
|
|
47
|
+
export const chatCompletionsRouteModule = {
|
|
48
|
+
registerChatCompletionRoute
|
|
49
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { FastifyInstance } from "fastify";
|
|
2
|
+
import type { BridgeApiRouteContext } from "../bridge-api-route-context.ts";
|
|
3
|
+
declare function registerMessageRoutes(app: FastifyInstance, context: BridgeApiRouteContext): void;
|
|
4
|
+
export declare const messageRoutesModule: {
|
|
5
|
+
registerMessageRoutes: typeof registerMessageRoutes;
|
|
6
|
+
};
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
function registerMessageRoutes(app, context) {
|
|
2
|
+
app.post("/v1/respond", async (request) => context.service.respond(request.body));
|
|
3
|
+
app.post("/v1/sessions/:sessionId/messages", async (request) => context.service.respond(request.body, request.params.sessionId));
|
|
4
|
+
}
|
|
5
|
+
export const messageRoutesModule = {
|
|
6
|
+
registerMessageRoutes
|
|
7
|
+
};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
export declare const bridgeServer: {
|
|
2
|
+
BridgeApiHttpError: typeof import("./client/bridge-api-client.ts").BridgeApiHttpError;
|
|
3
|
+
buildHealthUrl: (baseUrl: string) => string;
|
|
4
|
+
buildSessionMessageUrl: (baseUrl: string, sessionId: string) => string;
|
|
5
|
+
checkBridgeHealth: (input: import("./client/bridge-api-client.ts").CheckBridgeHealthInput) => Promise<import("./shared/api-schema.ts").BridgeHealthResponse>;
|
|
6
|
+
sendBridgeMessage: (input: import("./client/bridge-api-client.ts").SendBridgeMessageInput) => Promise<import("./shared/api-schema.ts").BridgeMessageResponse>;
|
|
7
|
+
loadBridgeServerConfig: (env?: NodeJS.ProcessEnv, overrides?: import("./config/bridge-server-config.ts").BridgeServerConfigOverrides) => import("./config/bridge-server-config.ts").BridgeServerConfig;
|
|
8
|
+
BridgeApiError: typeof import("./shared/bridge-api-error.ts").BridgeApiError;
|
|
9
|
+
isBridgeApiError: (error: unknown) => error is import("./shared/bridge-api-error.ts").BridgeApiError;
|
|
10
|
+
DEFAULT_LIVE_CANARY_EXPECTED_SUBSTRING: string;
|
|
11
|
+
DEFAULT_LIVE_CANARY_PROMPT: string;
|
|
12
|
+
formatLiveProviderExtractionCanaryResult: (result: import("./bridge/live-provider-extraction-canary.ts").LiveProviderExtractionCanaryResult) => string;
|
|
13
|
+
runLiveProviderExtractionCanary: (input: import("./bridge/live-provider-extraction-canary.ts").LiveProviderExtractionCanaryInput) => Promise<import("./bridge/live-provider-extraction-canary.ts").LiveProviderExtractionCanaryResult>;
|
|
14
|
+
sanitizeBridgeApiOutput: (content: string) => import("@uncensoredcode/openbridge/runtime").VisibleModelOutputSanitizationResult;
|
|
15
|
+
createBridgeRuntimeService: (dependencies: import("./bridge/bridge-runtime-service.ts").BridgeRuntimeServiceDependencies) => {
|
|
16
|
+
respond(request: import("./shared/api-schema.ts").BridgeMessageRequest, pathSessionId?: string): Promise<import("./shared/api-schema.ts").BridgeMessageResponse>;
|
|
17
|
+
execute(request: {
|
|
18
|
+
sessionId: string;
|
|
19
|
+
input: string;
|
|
20
|
+
providerId: string;
|
|
21
|
+
modelId: string;
|
|
22
|
+
metadata?: Record<string, unknown>;
|
|
23
|
+
toolProfile?: import("./shared/api-schema.ts").BridgeApiToolProfile;
|
|
24
|
+
sessionHistory?: import("@uncensoredcode/openbridge/runtime").BridgeSessionTurn[];
|
|
25
|
+
persistSession?: boolean;
|
|
26
|
+
}): Promise<import("./shared/api-schema.ts").BridgeMessageResponse>;
|
|
27
|
+
completeChatCompletionPacket(request: {
|
|
28
|
+
sessionId: string;
|
|
29
|
+
providerId: string;
|
|
30
|
+
modelId: string;
|
|
31
|
+
messages: import("@uncensoredcode/openbridge/runtime").CompiledProviderMessage[];
|
|
32
|
+
tools: import("./shared/api-schema.ts").BridgeChatCompletionTool[];
|
|
33
|
+
toolChoice?: import("./shared/api-schema.ts").BridgeChatCompletionRequest["tool_choice"];
|
|
34
|
+
continuation: boolean;
|
|
35
|
+
toolFollowUp: boolean;
|
|
36
|
+
metadata?: Record<string, unknown>;
|
|
37
|
+
persistSession?: boolean;
|
|
38
|
+
}): Promise<{
|
|
39
|
+
packet: import("@uncensoredcode/openbridge/runtime").AssistantResponse;
|
|
40
|
+
providerBindingReused: boolean;
|
|
41
|
+
}>;
|
|
42
|
+
streamChatCompletionPacket(request: {
|
|
43
|
+
sessionId: string;
|
|
44
|
+
providerId: string;
|
|
45
|
+
modelId: string;
|
|
46
|
+
messages: import("@uncensoredcode/openbridge/runtime").CompiledProviderMessage[];
|
|
47
|
+
tools: import("./shared/api-schema.ts").BridgeChatCompletionTool[];
|
|
48
|
+
toolChoice?: import("./shared/api-schema.ts").BridgeChatCompletionRequest["tool_choice"];
|
|
49
|
+
continuation: boolean;
|
|
50
|
+
toolFollowUp: boolean;
|
|
51
|
+
metadata?: Record<string, unknown>;
|
|
52
|
+
persistSession?: boolean;
|
|
53
|
+
}): Promise<{
|
|
54
|
+
content: AsyncIterable<import("./bridge/providers/provider-streams.ts").ProviderStreamFragment>;
|
|
55
|
+
packet: Promise<import("@uncensoredcode/openbridge/runtime").AssistantResponse>;
|
|
56
|
+
providerBindingReused: boolean;
|
|
57
|
+
}>;
|
|
58
|
+
streamChatCompletion(request: {
|
|
59
|
+
sessionId: string;
|
|
60
|
+
input: string;
|
|
61
|
+
providerId: string;
|
|
62
|
+
modelId: string;
|
|
63
|
+
metadata?: Record<string, unknown>;
|
|
64
|
+
toolProfile?: import("./shared/api-schema.ts").BridgeApiToolProfile;
|
|
65
|
+
sessionHistory?: import("@uncensoredcode/openbridge/runtime").BridgeSessionTurn[];
|
|
66
|
+
persistSession?: boolean;
|
|
67
|
+
}): Promise<AsyncIterable<string>>;
|
|
68
|
+
};
|
|
69
|
+
createBridgeApiServer: (options?: import("./http/create-bridge-api-server.ts").BridgeApiServerOptions) => import("node:http").Server<typeof import("node:http").IncomingMessage, typeof import("node:http").ServerResponse>;
|
|
70
|
+
startBridgeApiServer: (options?: import("./http/create-bridge-api-server.ts").BridgeApiServerOptions) => Promise<import("node:http").Server<typeof import("node:http").IncomingMessage, typeof import("node:http").ServerResponse>>;
|
|
71
|
+
getBridgeServerCliHelpText: () => string;
|
|
72
|
+
parseBridgeServerCliArgs: (input: {
|
|
73
|
+
argv: string[];
|
|
74
|
+
env?: NodeJS.ProcessEnv;
|
|
75
|
+
}) => import("./cli/run-bridge-server-cli.ts").BridgeServerCliCommand;
|
|
76
|
+
runBridgeServerCli: (input: import("./cli/run-bridge-server-cli.ts").RunBridgeServerCliInput) => Promise<number>;
|
|
77
|
+
};
|
|
78
|
+
export type { LiveProviderExtractionCanaryInput, LiveProviderExtractionCanaryResult } from "./bridge/index.ts";
|
|
79
|
+
export type { BridgeRuntimeServiceDependencies } from "./bridge/index.ts";
|
|
80
|
+
export type { BridgeServerCliCommand, RunBridgeServerCliInput } from "./cli/index.ts";
|
|
81
|
+
export type { BridgeApiClientFetch, CheckBridgeHealthInput, SendBridgeMessageInput } from "./client/index.ts";
|
|
82
|
+
export type { BridgeServerConfig } from "./config/index.ts";
|
|
83
|
+
export type { BridgeApiServerOptions } from "./http/index.ts";
|
|
84
|
+
export type { BridgeApiErrorResponse, BridgeApiToolProfile, BridgeChatCompletionMessage, BridgeChatCompletionRequest, BridgeChatCompletionResponse, BridgeHealthResponse, BridgeMessageRequest, BridgeMessageResponse, BridgeReadyResponse } from "./shared/api-schema.ts";
|
|
85
|
+
export type { BridgeApiError } from "./shared/bridge-api-error.ts";
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { bridgeModule } from "./bridge/index.js";
|
|
2
|
+
import { cliModule } from "./cli/index.js";
|
|
3
|
+
import { clientModule } from "./client/index.js";
|
|
4
|
+
import { configModule } from "./config/index.js";
|
|
5
|
+
import { httpModule } from "./http/index.js";
|
|
6
|
+
import { bridgeApiErrorModule } from "./shared/bridge-api-error.js";
|
|
7
|
+
import { outputModule } from "./shared/output.js";
|
|
8
|
+
export const bridgeServer = {
|
|
9
|
+
BridgeApiHttpError: clientModule.BridgeApiHttpError,
|
|
10
|
+
buildHealthUrl: clientModule.buildHealthUrl,
|
|
11
|
+
buildSessionMessageUrl: clientModule.buildSessionMessageUrl,
|
|
12
|
+
checkBridgeHealth: clientModule.checkBridgeHealth,
|
|
13
|
+
sendBridgeMessage: clientModule.sendBridgeMessage,
|
|
14
|
+
loadBridgeServerConfig: configModule.loadBridgeServerConfig,
|
|
15
|
+
BridgeApiError: bridgeApiErrorModule.BridgeApiError,
|
|
16
|
+
isBridgeApiError: bridgeApiErrorModule.isBridgeApiError,
|
|
17
|
+
DEFAULT_LIVE_CANARY_EXPECTED_SUBSTRING: bridgeModule.DEFAULT_LIVE_CANARY_EXPECTED_SUBSTRING,
|
|
18
|
+
DEFAULT_LIVE_CANARY_PROMPT: bridgeModule.DEFAULT_LIVE_CANARY_PROMPT,
|
|
19
|
+
formatLiveProviderExtractionCanaryResult: bridgeModule.formatLiveProviderExtractionCanaryResult,
|
|
20
|
+
runLiveProviderExtractionCanary: bridgeModule.runLiveProviderExtractionCanary,
|
|
21
|
+
sanitizeBridgeApiOutput: outputModule.sanitizeBridgeApiOutput,
|
|
22
|
+
createBridgeRuntimeService: bridgeModule.createBridgeRuntimeService,
|
|
23
|
+
createBridgeApiServer: httpModule.createBridgeApiServer,
|
|
24
|
+
startBridgeApiServer: httpModule.startBridgeApiServer,
|
|
25
|
+
getBridgeServerCliHelpText: cliModule.getBridgeServerCliHelpText,
|
|
26
|
+
parseBridgeServerCliArgs: cliModule.parseBridgeServerCliArgs,
|
|
27
|
+
runBridgeServerCli: cliModule.runBridgeServerCli
|
|
28
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { IncomingHttpHeaders } from "node:http";
|
|
2
|
+
import type { FastifyRequest } from "fastify";
|
|
3
|
+
declare function isAuthorizedBridgeRequest(headers: IncomingHttpHeaders, configuredToken: string | null | undefined): boolean;
|
|
4
|
+
declare function requiresBridgeAuth(request: FastifyRequest, configuredToken: string | null | undefined): boolean;
|
|
5
|
+
export declare const bridgeAuthModule: {
|
|
6
|
+
isAuthorizedBridgeRequest: typeof isAuthorizedBridgeRequest;
|
|
7
|
+
requiresBridgeAuth: typeof requiresBridgeAuth;
|
|
8
|
+
};
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { timingSafeEqual } from "node:crypto";
|
|
2
|
+
function isAuthorizedBridgeRequest(headers, configuredToken) {
|
|
3
|
+
if (!configuredToken) {
|
|
4
|
+
return true;
|
|
5
|
+
}
|
|
6
|
+
const providedToken = readBearerToken(headers.authorization) ?? readHeaderString(headers["x-bridge-token"]);
|
|
7
|
+
if (!providedToken) {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
const expected = Buffer.from(configuredToken, "utf8");
|
|
11
|
+
const actual = Buffer.from(providedToken, "utf8");
|
|
12
|
+
if (expected.length !== actual.length) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
return timingSafeEqual(expected, actual);
|
|
16
|
+
}
|
|
17
|
+
function requiresBridgeAuth(request, configuredToken) {
|
|
18
|
+
if (!configuredToken) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
const pathname = request.raw.url?.split("?")[0] ?? request.url;
|
|
22
|
+
return pathname !== "/health" && pathname !== "/ready";
|
|
23
|
+
}
|
|
24
|
+
function readBearerToken(value) {
|
|
25
|
+
const normalized = readHeaderString(value);
|
|
26
|
+
if (!normalized || !/^Bearer\s+/i.test(normalized)) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
const token = normalized.replace(/^Bearer\s+/i, "").trim();
|
|
30
|
+
return token || null;
|
|
31
|
+
}
|
|
32
|
+
function readHeaderString(value) {
|
|
33
|
+
if (Array.isArray(value)) {
|
|
34
|
+
return value[0]?.trim() || null;
|
|
35
|
+
}
|
|
36
|
+
return value?.trim() || null;
|
|
37
|
+
}
|
|
38
|
+
export const bridgeAuthModule = {
|
|
39
|
+
isAuthorizedBridgeRequest,
|
|
40
|
+
requiresBridgeAuth
|
|
41
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { configModule } from "../config/index.js";
|
|
2
|
+
const { isLocalBridgeHost, isWildcardCorsOrigins } = configModule;
|
|
3
|
+
function resolveCorsOrigin(origin, configuredOrigins) {
|
|
4
|
+
const normalizedOrigin = origin?.trim();
|
|
5
|
+
if (!normalizedOrigin) {
|
|
6
|
+
return null;
|
|
7
|
+
}
|
|
8
|
+
if (isWildcardCorsOrigins(configuredOrigins)) {
|
|
9
|
+
return "*";
|
|
10
|
+
}
|
|
11
|
+
if (configuredOrigins && configuredOrigins.length > 0) {
|
|
12
|
+
return configuredOrigins.includes(normalizedOrigin) ? normalizedOrigin : null;
|
|
13
|
+
}
|
|
14
|
+
return isDefaultAllowedCorsOrigin(normalizedOrigin) ? normalizedOrigin : null;
|
|
15
|
+
}
|
|
16
|
+
function isDefaultAllowedCorsOrigin(origin) {
|
|
17
|
+
let parsed;
|
|
18
|
+
try {
|
|
19
|
+
parsed = new URL(origin);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
if (parsed.protocol === "chrome-extension:" || parsed.protocol === "moz-extension:") {
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
return isLocalBridgeHost(parsed.hostname);
|
|
31
|
+
}
|
|
32
|
+
export const corsPolicyModule = {
|
|
33
|
+
resolveCorsOrigin
|
|
34
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare const securityModule: {
|
|
2
|
+
isAuthorizedBridgeRequest: (headers: import("node:http").IncomingHttpHeaders, configuredToken: string | null | undefined) => boolean;
|
|
3
|
+
requiresBridgeAuth: (request: import("fastify").FastifyRequest, configuredToken: string | null | undefined) => boolean;
|
|
4
|
+
resolveCorsOrigin: (origin: string | undefined, configuredOrigins: string[] | undefined) => string | null;
|
|
5
|
+
formatBridgeServerErrorLog: (error: unknown, context?: {
|
|
6
|
+
method?: string;
|
|
7
|
+
url?: string;
|
|
8
|
+
}) => string;
|
|
9
|
+
redactSensitiveValue: (value: unknown, path?: string[]) => unknown;
|
|
10
|
+
sanitizeBridgeApiErrorPayload: (error: import("../index.ts").BridgeApiError) => {
|
|
11
|
+
code: string;
|
|
12
|
+
message: string;
|
|
13
|
+
details: unknown;
|
|
14
|
+
};
|
|
15
|
+
sanitizeSensitiveText: (value: string) => string;
|
|
16
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { bridgeAuthModule } from "./bridge-auth.js";
|
|
2
|
+
import { corsPolicyModule } from "./cors-policy.js";
|
|
3
|
+
import { redactSensitiveValuesModule } from "./redact-sensitive-values.js";
|
|
4
|
+
export const securityModule = {
|
|
5
|
+
isAuthorizedBridgeRequest: bridgeAuthModule.isAuthorizedBridgeRequest,
|
|
6
|
+
requiresBridgeAuth: bridgeAuthModule.requiresBridgeAuth,
|
|
7
|
+
resolveCorsOrigin: corsPolicyModule.resolveCorsOrigin,
|
|
8
|
+
formatBridgeServerErrorLog: redactSensitiveValuesModule.formatBridgeServerErrorLog,
|
|
9
|
+
redactSensitiveValue: redactSensitiveValuesModule.redactSensitiveValue,
|
|
10
|
+
sanitizeBridgeApiErrorPayload: redactSensitiveValuesModule.sanitizeBridgeApiErrorPayload,
|
|
11
|
+
sanitizeSensitiveText: redactSensitiveValuesModule.sanitizeSensitiveText
|
|
12
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { BridgeApiError } from "../shared/bridge-api-error.ts";
|
|
2
|
+
declare function sanitizeBridgeApiErrorPayload(error: BridgeApiError): {
|
|
3
|
+
code: string;
|
|
4
|
+
message: string;
|
|
5
|
+
details: unknown;
|
|
6
|
+
};
|
|
7
|
+
declare function formatBridgeServerErrorLog(error: unknown, context?: {
|
|
8
|
+
method?: string;
|
|
9
|
+
url?: string;
|
|
10
|
+
}): string;
|
|
11
|
+
declare function redactSensitiveValue(value: unknown, path?: string[]): unknown;
|
|
12
|
+
declare function sanitizeSensitiveText(value: string): string;
|
|
13
|
+
export declare const redactSensitiveValuesModule: {
|
|
14
|
+
sanitizeBridgeApiErrorPayload: typeof sanitizeBridgeApiErrorPayload;
|
|
15
|
+
formatBridgeServerErrorLog: typeof formatBridgeServerErrorLog;
|
|
16
|
+
redactSensitiveValue: typeof redactSensitiveValue;
|
|
17
|
+
sanitizeSensitiveText: typeof sanitizeSensitiveText;
|
|
18
|
+
};
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
const REDACTED = "[REDACTED]";
|
|
2
|
+
const SENSITIVE_KEY_PATTERN = /(authorization|headers?|cookie|cookies|set-cookie|localstorage|token|secret|bearer|session[-_]?package|extraheaders?|ciphertext|authtag|vaultkey|sessionvaultkey)/i;
|
|
3
|
+
function sanitizeBridgeApiErrorPayload(error) {
|
|
4
|
+
return {
|
|
5
|
+
code: error.code,
|
|
6
|
+
message: sanitizeSensitiveText(error.message),
|
|
7
|
+
details: error.details === undefined ? undefined : redactSensitiveValue(error.details)
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
function formatBridgeServerErrorLog(error, context = {}) {
|
|
11
|
+
const prefix = [
|
|
12
|
+
context.method && context.url ? `${context.method} ${context.url}` : (context.url ?? null),
|
|
13
|
+
"bridge-server error"
|
|
14
|
+
]
|
|
15
|
+
.filter((segment) => Boolean(segment))
|
|
16
|
+
.join(": ");
|
|
17
|
+
if (typeof error === "object" && error !== null) {
|
|
18
|
+
const name = "name" in error && typeof error.name === "string" ? error.name : "Error";
|
|
19
|
+
const code = "code" in error && typeof error.code === "string" ? error.code : "";
|
|
20
|
+
const message = "message" in error && typeof error.message === "string" ? error.message : "";
|
|
21
|
+
const details = "details" in error && error.details !== undefined
|
|
22
|
+
? ` details=${JSON.stringify(redactSensitiveValue(error.details))}`
|
|
23
|
+
: "";
|
|
24
|
+
return `${prefix}: ${sanitizeSensitiveText([name, code, message].filter(Boolean).join(" "))}${details}`;
|
|
25
|
+
}
|
|
26
|
+
return `${prefix}: ${sanitizeSensitiveText(String(error))}`;
|
|
27
|
+
}
|
|
28
|
+
function redactSensitiveValue(value, path = []) {
|
|
29
|
+
const currentKey = path.at(-1) ?? "";
|
|
30
|
+
if (isSensitiveKey(currentKey)) {
|
|
31
|
+
return REDACTED;
|
|
32
|
+
}
|
|
33
|
+
if (typeof value === "string") {
|
|
34
|
+
return sanitizeSensitiveText(value);
|
|
35
|
+
}
|
|
36
|
+
if (Array.isArray(value)) {
|
|
37
|
+
return value.map((entry) => redactSensitiveValue(entry, path));
|
|
38
|
+
}
|
|
39
|
+
if (value && typeof value === "object") {
|
|
40
|
+
const result = {};
|
|
41
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
42
|
+
result[key] = redactSensitiveValue(entry, [...path, key]);
|
|
43
|
+
}
|
|
44
|
+
return result;
|
|
45
|
+
}
|
|
46
|
+
return value;
|
|
47
|
+
}
|
|
48
|
+
function sanitizeSensitiveText(value) {
|
|
49
|
+
return value
|
|
50
|
+
.replace(/(Authorization\s*:\s*)Bearer\s+[^\s",]+/gi, "$1Bearer [REDACTED]")
|
|
51
|
+
.replace(/(["']authorization["']\s*:\s*["'])Bearer\s+[^"']+(["'])/gi, `$1Bearer ${REDACTED}$2`)
|
|
52
|
+
.replace(/Bearer\s+[^\s",]+/gi, "Bearer [REDACTED]")
|
|
53
|
+
.replace(/((?:cookie|set-cookie)\s*[:=]\s*)([^"'\n}]+)/gi, (_match, prefix, cookieHeader) => {
|
|
54
|
+
return `${prefix}${cookieHeader.replace(/([A-Za-z0-9._-]+\s*=)[^;,\s]+/g, `$1${REDACTED}`)}`;
|
|
55
|
+
})
|
|
56
|
+
.replace(/(["']?(?:token|access_token|refresh_token|bearerToken)["']?\s*[:=]\s*["']?)[^"',\s}]+/gi, `$1${REDACTED}`)
|
|
57
|
+
.replace(/((?:session|cookie)\s*=\s*)[^;\s",]+/gi, `$1${REDACTED}`);
|
|
58
|
+
}
|
|
59
|
+
function isSensitiveKey(value) {
|
|
60
|
+
return SENSITIVE_KEY_PATTERN.test(value);
|
|
61
|
+
}
|
|
62
|
+
export const redactSensitiveValuesModule = {
|
|
63
|
+
sanitizeBridgeApiErrorPayload,
|
|
64
|
+
formatBridgeServerErrorLog,
|
|
65
|
+
redactSensitiveValue,
|
|
66
|
+
sanitizeSensitiveText
|
|
67
|
+
};
|