mirror of
https://bitbucket.org/siakitem/my-pi.git
synced 2026-10-26 10:45:22 +00:00
- support sub-api/openai-responses through the public Responses endpoint - preserve explicit Authorization and support header-only authentication - retain Codex JWT requirements and native compaction failure fallback - restore SubAPI checkpoints and preserve portable model-switching summaries - add provider, authentication and checkpoint lifecycle regression tests - document compatibility requirements and the Sub2API protocol reference
67 lines
2.7 KiB
TypeScript
67 lines
2.7 KiB
TypeScript
import {
|
|
buildCodexHeaders,
|
|
isJsonObject,
|
|
isOpenAICodexModel,
|
|
mergeFeatureHeader,
|
|
resolveCodexResponsesUrl,
|
|
type Model,
|
|
} from "./native-compaction.js";
|
|
|
|
export function isNativeCompactionModel(model: unknown): model is Model<any> {
|
|
return isOpenAICodexModel(model) || (
|
|
isJsonObject(model) && model.provider === "sub-api" && model.api === "openai-responses"
|
|
);
|
|
}
|
|
|
|
export function buildNativeCompactionTransport(params: {
|
|
model: Pick<Model<any>, "provider" | "api" | "baseUrl">;
|
|
apiKey?: string;
|
|
headers?: Record<string, string>;
|
|
sessionId: string;
|
|
}): { url: string; headers: Headers } {
|
|
if (isOpenAICodexModel(params.model)) {
|
|
if (!params.apiKey) throw new Error("Codex native compaction authentication requires an API key.");
|
|
return {
|
|
url: resolveCodexResponsesUrl(params.model.baseUrl),
|
|
headers: buildCodexHeaders({ ...params, apiKey: params.apiKey }),
|
|
};
|
|
}
|
|
if (!isNativeCompactionModel(params.model)) {
|
|
throw new Error("Native compaction is not supported for this provider and API.");
|
|
}
|
|
if (!params.model.baseUrl?.trim()) {
|
|
throw new Error("SubAPI native compaction requires an explicit baseUrl.");
|
|
}
|
|
let url: URL;
|
|
try {
|
|
url = new URL(params.model.baseUrl.trim());
|
|
} catch {
|
|
throw new Error("SubAPI native compaction requires a valid HTTP(S) baseUrl.");
|
|
}
|
|
if (!["https:", "http:"].includes(url.protocol) || url.username || url.password || url.hash) {
|
|
throw new Error("SubAPI native compaction requires an HTTP(S) baseUrl without credentials or a fragment.");
|
|
}
|
|
const path = url.pathname.replace(/\/+$/, "");
|
|
url.pathname = path.endsWith("/responses") ? path : `${path}/responses`;
|
|
|
|
// Sub2API accepts native compaction v2 through its public Responses endpoint.
|
|
// The gateway owns upstream Codex credentials; honor the client's resolved authentication.
|
|
const headers = new Headers(params.headers);
|
|
if (!headers.get("authorization")?.trim()) {
|
|
if (params.apiKey?.trim()) {
|
|
headers.set("authorization", `Bearer ${params.apiKey}`);
|
|
} else if (!headers.get("cf-aig-authorization")?.trim()) {
|
|
throw new Error("SubAPI native compaction authentication requires an API key or a non-empty Authorization or cf-aig-authorization header.");
|
|
}
|
|
}
|
|
headers.set("content-type", "application/json");
|
|
headers.set("accept", "text/event-stream");
|
|
headers.set("OpenAI-Beta", "responses=experimental");
|
|
headers.set("originator", "pi");
|
|
headers.set("user-agent", "pi-compaction");
|
|
headers.set("session-id", params.sessionId);
|
|
headers.set("x-client-request-id", params.sessionId);
|
|
headers.set("x-codex-beta-features", mergeFeatureHeader(headers.get("x-codex-beta-features")));
|
|
return { url: url.toString(), headers };
|
|
}
|