Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions @omniroute/opencode-plugin-v2/src/catalog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ export interface ResolvedOptions extends FreeOptions {
baseURL: string;
apiKey: string;
managementReadToken?: string;
headers?: Record<string, string>;
timeoutMs: number;
timeouts?: EndpointTimeouts;
logger?: Logger;
Expand Down Expand Up @@ -1124,6 +1125,7 @@ export function buildProviderPayload(
activation: "enabled",
package: NPM_OPENAI_COMPAT,
settings: { baseURL: ensureV1Suffix(opts.baseURL), apiKey: opts.apiKey },
headers: opts.headers,
integrationID: X,
} as unknown as StableProviderInfo;
const models: StableModelInfo[] = [];
Expand Down
12 changes: 8 additions & 4 deletions @omniroute/opencode-plugin-v2/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,8 @@ export default Plugin.define({
return await defaultOmniRouteModelsFetcher(
resolved.baseURL,
resolved.apiKey,
timeouts.models
timeouts.models,
resolved.headers
);
} catch (err) {
log.warn(
Expand All @@ -203,7 +204,8 @@ export default Plugin.define({
value: await defaultOmniRouteCombosFetcher(
resolved.baseURL,
resolved.managementReadToken ?? resolved.apiKey,
timeouts.combos
timeouts.combos,
resolved.headers
),
};
} catch (err) {
Expand All @@ -225,7 +227,8 @@ export default Plugin.define({
resolved.baseURL,
resolved.managementReadToken ?? resolved.apiKey,
timeouts.models,
reportSourceError
reportSourceError,
resolved.headers
),
};
} catch (err) {
Expand All @@ -247,7 +250,8 @@ export default Plugin.define({
resolved.baseURL,
resolved.managementReadToken ?? resolved.apiKey,
timeouts.enrichment,
reportSourceError
reportSourceError,
resolved.headers
),
};
} catch (err) {
Expand Down
8 changes: 8 additions & 0 deletions @omniroute/opencode-plugin-v2/src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ const pluginOptionsSchema = z
.trim()
.refine(isHttpUrl, "baseURL must be an http(s) URL, for example http://localhost:20128"),
apiKey: z.string().optional(),
/**
* Extra HTTP headers sent with every gateway fetch (models, combos,
* providers, enrichment). Useful for gateways behind Cloudflare Access
* or other header-based auth proxies. Merged into the Authorization
* header; never overrides the bearer token.
*/
headers: z.record(z.string(), z.string()).optional(),
displayName: z.string().optional(),
managementReadToken: z.string().optional(),
timeoutMs: z.number().positive().default(10000),
Expand Down Expand Up @@ -159,6 +166,7 @@ export function toResolvedOptions(parsed: PluginOptions): ResolvedOptions {
providerId: parsed.providerId,
baseURL: parsed.baseURL,
apiKey: parsed.apiKey ?? process.env.OMNIROUTE_API_KEY ?? "",
headers: parsed.headers as Record<string, string> | undefined,
managementReadToken: resolveManagementReadToken(parsed.managementReadToken),
timeoutMs: parsed.timeoutMs,
timeouts: parsed.timeouts,
Expand Down
9 changes: 6 additions & 3 deletions @omniroute/opencode-plugin-v2/src/shared/combos-map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ export interface OmniRouteRawCombo {
export type OmniRouteCombosFetcher = (
baseURL: string,
apiKey: string,
timeoutMs?: number
timeoutMs?: number,
headers?: Record<string, string>
) => Promise<OmniRouteRawCombo[]>;

function trimTrailingSlashes(value: string): string {
Expand Down Expand Up @@ -73,7 +74,8 @@ function trimTrailingSlashes(value: string): string {
export const defaultOmniRouteCombosFetcher: OmniRouteCombosFetcher = async (
baseURL,
apiKey,
timeoutMs = 10_000
timeoutMs = 10_000,
headers
) => {
if (!apiKey) throw new Error("[omniroute-v2] apiKey required to fetch /api/combos");
if (!baseURL) throw new Error("[omniroute-v2] baseURL required to fetch /api/combos");
Expand All @@ -91,8 +93,9 @@ export const defaultOmniRouteCombosFetcher: OmniRouteCombosFetcher = async (
const res = await fetch(url, {
method: "GET",
headers: {
Authorization: `Bearer ${apiKey}`,
Accept: "application/json",
...(headers ?? {}),
Authorization: `Bearer ${apiKey}`,
},
signal: controller.signal,
});
Expand Down
9 changes: 6 additions & 3 deletions @omniroute/opencode-plugin-v2/src/shared/enrich.ts
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,8 @@ export type OmniRouteEnrichmentFetcher = (
baseURL: string,
apiKey: string,
timeoutMs?: number,
onSourceError?: OmniRouteEnrichmentSourceError
onSourceError?: OmniRouteEnrichmentSourceError,
extraHeaders?: Record<string, string>
) => Promise<OmniRouteEnrichmentMap>;

function trimTrailingSlashes(value: string): string {
Expand Down Expand Up @@ -355,7 +356,8 @@ export const defaultOmniRouteEnrichmentFetcher: OmniRouteEnrichmentFetcher = asy
baseURL,
apiKey,
timeoutMs = 10_000,
onSourceError
onSourceError,
extraHeaders
) => {
const report = (endpoint: string, reason: unknown): void => {
onSourceError?.(endpoint, reason instanceof Error ? reason.message : String(reason));
Expand All @@ -364,8 +366,9 @@ export const defaultOmniRouteEnrichmentFetcher: OmniRouteEnrichmentFetcher = asy
if (!baseURL || !apiKey) return out;
const root = trimTrailingSlashes(baseURL.replace(/\/v1\/?$/, ""));
const headers = {
Authorization: `Bearer ${apiKey}`,
Accept: "application/json",
...(extraHeaders ?? {}),
Authorization: `Bearer ${apiKey}`,
};

// 1. Catalog with nice display names.
Expand Down
12 changes: 9 additions & 3 deletions @omniroute/opencode-plugin-v2/src/shared/models-map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ export interface OmniRouteRawModelEntry {
export type OmniRouteModelsFetcher = (
baseURL: string,
apiKey: string,
timeoutMs?: number
timeoutMs?: number,
headers?: Record<string, string>
) => Promise<OmniRouteRawModelEntry[]>;

/**
Expand All @@ -50,11 +51,15 @@ export type OmniRouteModelsFetcher = (
* emits today and a bare-array envelope (defensive — keeps the plugin
* working if a future OmniRoute build trims the wrapper). Anything that
* isn't an object with a string `id` is filtered out silently.
*
* `headers` are merged into the request (e.g. Cloudflare Access client
* id/secret). User-supplied values never override the bearer token.
*/
export const defaultOmniRouteModelsFetcher: OmniRouteModelsFetcher = async (
baseURL,
apiKey,
timeoutMs = 10_000
timeoutMs = 10_000,
headers
) => {
if (!apiKey) throw new Error("[omniroute-v2] apiKey required to fetch /v1/models");
if (!baseURL) throw new Error("[omniroute-v2] baseURL required to fetch /v1/models");
Expand All @@ -70,8 +75,9 @@ export const defaultOmniRouteModelsFetcher: OmniRouteModelsFetcher = async (
const res = await fetch(url, {
method: "GET",
headers: {
Authorization: `Bearer ${apiKey}`,
Accept: "application/json",
...(headers ?? {}),
Authorization: `Bearer ${apiKey}`,
},
signal: controller.signal,
});
Expand Down
9 changes: 6 additions & 3 deletions @omniroute/opencode-plugin-v2/src/shared/usable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ export type OmniRouteProvidersFetcher = (
baseURL: string,
apiKey: string,
timeoutMs?: number,
onSourceError?: (endpoint: string, reason: string) => void
onSourceError?: (endpoint: string, reason: string) => void,
headers?: Record<string, string>
) => Promise<OmniRouteProviderConnection[]>;

export interface UsableProviderSet {
Expand All @@ -40,7 +41,8 @@ export const defaultOmniRouteProvidersFetcher: OmniRouteProvidersFetcher = async
baseURL,
apiKey,
timeoutMs = 10_000,
onSourceError
onSourceError,
headers
) => {
const empty: OmniRouteProviderConnection[] = [];
if (!baseURL || !apiKey) return empty;
Expand All @@ -52,8 +54,9 @@ export const defaultOmniRouteProvidersFetcher: OmniRouteProvidersFetcher = async
const res = await fetch(url, {
method: "GET",
headers: {
Authorization: `Bearer ${apiKey}`,
Accept: "application/json",
...(headers ?? {}),
Authorization: `Bearer ${apiKey}`,
},
signal: ac.signal,
});
Expand Down
Loading