70 lines
2.2 KiB
TypeScript
70 lines
2.2 KiB
TypeScript
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
import { readFileSync, existsSync } from "node:fs";
|
|
import { join } from "node:path";
|
|
|
|
const BASE_URL = "http://exacode-chat.lge.com/v1";
|
|
|
|
// The EXACODE gateway routes requests by the `X-Title` header.
|
|
// - "EXACODE Agent Roo" -> the official VS Code extension route; gated by a
|
|
// client-version check (blocks curl/SDKs/outdated builds).
|
|
// - "EXACODE SWE(API)" -> the API-client route; the intended tier for
|
|
// programmatic access. Requires an SWE(API)-scoped bearer token, which
|
|
// lives in `.env` as EXACODE_API_KEY (different from the Roo Code JWT).
|
|
//
|
|
// `X-Model` echoes the requested model id (redundant -- it also travels in the
|
|
// request body -- but the official example sets it as a default header).
|
|
const X_TITLE = "EXACODE SWE(API)";
|
|
|
|
// pi does not auto-load `.env`, so populate process.env ourselves at startup.
|
|
// Real environment variables take precedence over the file.
|
|
function loadDotEnv(file: string) {
|
|
if (!existsSync(file)) return;
|
|
const text = readFileSync(file, "utf8");
|
|
for (const rawLine of text.split(/\r?\n/)) {
|
|
const line = rawLine.trim();
|
|
if (!line || line.startsWith("#")) continue;
|
|
const eq = line.indexOf("=");
|
|
if (eq < 0) continue;
|
|
const key = line.slice(0, eq).trim();
|
|
let value = line.slice(eq + 1).trim();
|
|
if (
|
|
(value.startsWith('"') && value.endsWith('"')) ||
|
|
(value.startsWith("'") && value.endsWith("'"))
|
|
) {
|
|
value = value.slice(1, -1);
|
|
}
|
|
if (key && process.env[key] === undefined) {
|
|
process.env[key] = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
loadDotEnv(join(process.cwd(), ".env"));
|
|
|
|
const MODELS = [
|
|
{
|
|
id: "Chat-EXACODE-A",
|
|
name: "Chat-EXACODE-A (EXACODE 3.5)",
|
|
reasoning: true,
|
|
input: ["text"] as const,
|
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
contextWindow: 131072,
|
|
maxTokens: 8192,
|
|
headers: { "X-Model": "Chat-EXACODE-A" },
|
|
},
|
|
];
|
|
|
|
export default function (pi: ExtensionAPI) {
|
|
pi.registerProvider("exacode", {
|
|
name: "exacode",
|
|
baseUrl: BASE_URL,
|
|
apiKey: "$EXACODE_API_KEY",
|
|
authHeader: true,
|
|
api: "openai-completions",
|
|
headers: {
|
|
"X-Title": X_TITLE,
|
|
},
|
|
models: MODELS,
|
|
});
|
|
}
|