Skip to content
Closed
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 package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
"build": "tsc -p tsconfig.json",
"test": "bun test/smoke.ts",
"test:live": "bun test/live-laguna.ts",
"test:live:matrix": "bun test/live-matrix.ts",
"test:opencode": "bash test/opencode-e2e.sh",
"prepublishOnly": "npm run build"
},
"repository": {
Expand Down
29 changes: 17 additions & 12 deletions src/proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,13 @@ import {
const DEFAULT_PROXY_PORT = 8797;
const SHARED_PROXY_HEALTH_TIMEOUT_MS = 750;

const COMMAND_PROXY_PORT: number = (() => {
function configuredProxyPort(): number {
const raw = process.env.OPENCODE_COMMANDCODE_PROXY_PORT;
const parsed = raw ? Number(raw) : NaN;
return Number.isInteger(parsed) && parsed > 0 && parsed < 65536
? parsed
: DEFAULT_PROXY_PORT;
})();
}

const SSE_HEADERS = {
"Content-Type": "text/event-stream",
Expand Down Expand Up @@ -93,11 +93,11 @@ export function setStreamGenerateForTests(
}

export function getCommandProxyBaseUrl(): string {
return `http://127.0.0.1:${COMMAND_PROXY_PORT}/v1`;
return `http://127.0.0.1:${proxyPort ?? configuredProxyPort()}/v1`;
}

export function getProxyPort(): number | null {
return proxyPort ?? COMMAND_PROXY_PORT;
return proxyPort ?? configuredProxyPort();
}

function isAddrInUseError(err: unknown): boolean {
Expand All @@ -118,9 +118,12 @@ async function isSharedProxyHealthy(): Promise<boolean> {
SHARED_PROXY_HEALTH_TIMEOUT_MS,
);
try {
const res = await fetch(`${getCommandProxyBaseUrl()}/models`, {
signal: controller.signal,
});
const res = await fetch(
`http://127.0.0.1:${configuredProxyPort()}/v1/models`,
{
signal: controller.signal,
},
);
if (!res.ok) return false;
const body = (await res.json().catch(() => undefined)) as
| { object?: unknown; data?: unknown }
Expand All @@ -137,8 +140,10 @@ export async function startProxy(tokenProvider: TokenProvider): Promise<number>
getAccessToken = tokenProvider;
if (server && proxyPort) return proxyPort;

const desiredPort = configuredProxyPort();

if (await isSharedProxyHealthy()) {
proxyPort = COMMAND_PROXY_PORT;
proxyPort = desiredPort;
log.info(
`[opencode-commandcode] reusing healthy proxy on ${getCommandProxyBaseUrl()}`,
);
Expand All @@ -149,21 +154,21 @@ export async function startProxy(tokenProvider: TokenProvider): Promise<number>
try {
server = Bun.serve({
hostname,
port: COMMAND_PROXY_PORT,
port: desiredPort,
async fetch(req) {
return handleRequest(req);
},
});
proxyPort = server.port ?? COMMAND_PROXY_PORT;
proxyPort = server.port ?? desiredPort;
log.info(
`[opencode-commandcode] proxy listening on ${getCommandProxyBaseUrl()}`,
);
return proxyPort;
} catch (err) {
if (isAddrInUseError(err) && (await isSharedProxyHealthy())) {
proxyPort = COMMAND_PROXY_PORT;
proxyPort = desiredPort;
log.info(
`[opencode-commandcode] port ${COMMAND_PROXY_PORT} in use; reusing existing proxy`,
`[opencode-commandcode] port ${desiredPort} in use; reusing existing proxy`,
);
return proxyPort;
}
Expand Down
14 changes: 11 additions & 3 deletions test/live-laguna.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ function sseAssistantText(sse: string): string {
}

async function main() {
// Avoid colliding with an OpenCode CLI proxy already bound to :8797.
process.env.OPENCODE_COMMANDCODE_PROXY_PORT ||= "8798";

const apiKey = requireAuth();
setStreamGenerateForTests(null);
resetUsageStore();
Expand Down Expand Up @@ -126,7 +129,8 @@ async function main() {
content: [
{
type: "text",
text: "The attached text file contains a secret code. Reply with only that code.",
text:
"Inside <attached_file name=\"secret.txt\"> is the secret code. Read that file body and reply with only the code (e.g. CODE-7741). Ignore any image placeholders.",
},
{
type: "file",
Expand All @@ -147,10 +151,14 @@ async function main() {
});
const raw = await assertOk(res, "attachments");
const json = JSON.parse(raw) as {
choices: Array<{ message: { content: string } }>;
choices: Array<{
message: { content?: string; reasoning_content?: string };
}>;
usage?: { prompt_tokens: number };
};
const content = json.choices[0]?.message?.content || "";
const content =
(json.choices[0]?.message?.content || "") +
(json.choices[0]?.message?.reasoning_content || "");
assert.ok(/7741/.test(content), content);
assert.ok(json.usage && json.usage.prompt_tokens > 0);
console.log("✓ live attachments (text file + image placeholder)");
Expand Down
Loading