mirror of
https://github.com/stack-auth/stack.git
synced 2026-06-30 21:01:54 +08:00
chore: align config agent proxy defaults
This commit is contained in:
parent
212502a00b
commit
57188ed78b
@ -1,4 +1,5 @@
|
||||
import { ALLOWED_MODEL_IDS } from "@/lib/ai/models";
|
||||
import { PRODUCTION_AI_PROXY_BASE_URL } from "@/lib/ai/proxy-url";
|
||||
import { preprocessProxyBody } from "@/private";
|
||||
import { handleApiRequest } from "@/route-handlers/smart-route-handler";
|
||||
import { getEnvVariable } from "@hexclave/shared/dist/utils/env";
|
||||
@ -6,7 +7,6 @@ import { StatusError } from "@hexclave/shared/dist/utils/errors";
|
||||
import { NextRequest } from "next/server";
|
||||
|
||||
const OPENROUTER_BASE_URL = "https://openrouter.ai/api";
|
||||
const PRODUCTION_PROXY_BASE_URL = "https://api.hexclave.com/api/latest/integrations/ai-proxy";
|
||||
const OPENROUTER_DEFAULT_MODEL = "anthropic/claude-sonnet-4.6";
|
||||
|
||||
function sanitizeBody(raw: ArrayBuffer): Uint8Array {
|
||||
@ -49,7 +49,7 @@ async function proxyToOpenRouter(req: NextRequest, options: { params: Promise<{
|
||||
: undefined;
|
||||
|
||||
if (apiKey === "FORWARD_TO_PRODUCTION") {
|
||||
const targetUrl = `${PRODUCTION_PROXY_BASE_URL}/${subpath}${req.nextUrl.search}`;
|
||||
const targetUrl = `${PRODUCTION_AI_PROXY_BASE_URL}/${subpath}${req.nextUrl.search}`;
|
||||
const headers: Record<string, string> = {};
|
||||
if (contentType) {
|
||||
headers["Content-Type"] = contentType;
|
||||
|
||||
@ -2,6 +2,7 @@ import { isLocalEmulatorEnabled } from "@/lib/local-emulator";
|
||||
import { getNodeEnvironment } from "@hexclave/shared/dist/utils/env";
|
||||
import { HexclaveAssertionError } from "@hexclave/shared/dist/utils/errors";
|
||||
import { createOpenRouter } from "@openrouter/ai-sdk-provider";
|
||||
import { PRODUCTION_AI_PROXY_BASE_URL } from "./proxy-url";
|
||||
|
||||
export const MODEL_QUALITIES = ["dumb", "smart", "smartest"] as const;
|
||||
export const MODEL_SPEEDS = ["slow", "fast"] as const;
|
||||
@ -62,7 +63,7 @@ export const ALLOWED_MODEL_IDS: ReadonlySet<string> = new Set([
|
||||
export function createOpenRouterProvider() {
|
||||
const baseURL = (getNodeEnvironment() === "development" || isLocalEmulatorEnabled())
|
||||
? "http://localhost:8102/api/latest/integrations/ai-proxy/v1"
|
||||
: "https://api.hexclave.com/api/latest/integrations/ai-proxy/v1";
|
||||
: `${PRODUCTION_AI_PROXY_BASE_URL}/v1`;
|
||||
return createOpenRouter({
|
||||
apiKey: "forwarded",
|
||||
baseURL,
|
||||
|
||||
1
apps/backend/src/lib/ai/proxy-url.ts
Normal file
1
apps/backend/src/lib/ai/proxy-url.ts
Normal file
@ -0,0 +1 @@
|
||||
export const PRODUCTION_AI_PROXY_BASE_URL = "https://api.hexclave.com/api/latest/integrations/ai-proxy";
|
||||
@ -42,13 +42,13 @@
|
||||
import { getEnvVariable } from "@hexclave/shared/dist/utils/env";
|
||||
import { captureError } from "@hexclave/shared/dist/utils/errors";
|
||||
import { Sandbox } from "@vercel/sandbox";
|
||||
import { PRODUCTION_AI_PROXY_BASE_URL } from "../ai/proxy-url";
|
||||
|
||||
const AGENT_SDK_VERSION = "0.2.73";
|
||||
const BASE = "/vercel/sandbox";
|
||||
const REPO_DIR = `${BASE}/repo`;
|
||||
const TOOLS_DIR = BASE; // agent SDK + runner live here, separate from the repo
|
||||
const DEFAULT_AGENT_MODEL = "anthropic/claude-haiku-4.5";
|
||||
const DEFAULT_PROXY_URL = "https://api.hexclave.com/api/latest/integrations/ai-proxy";
|
||||
const SANDBOX_TIMEOUT_MS = 900_000;
|
||||
const REVIEW_SANDBOX_KEEPALIVE_MS = 5 * 60_000;
|
||||
const GIT_BOT_NAME = "Hexclave Config Bot";
|
||||
@ -330,7 +330,7 @@ async function runAgent(sandbox: Sandbox, prompt: string, onProgress?: AgentProg
|
||||
const agentInput = {
|
||||
prompt,
|
||||
model: getEnvVariable("STACK_CONFIG_AGENT_MODEL", DEFAULT_AGENT_MODEL),
|
||||
baseUrl: getEnvVariable("STACK_CLAUDE_PROXY_URL", DEFAULT_PROXY_URL),
|
||||
baseUrl: getEnvVariable("STACK_CLAUDE_PROXY_URL", PRODUCTION_AI_PROXY_BASE_URL),
|
||||
apiKey: "stack-auth-proxy",
|
||||
};
|
||||
// Write runner.mjs fresh each run (not baked into the base snapshot) so changes
|
||||
|
||||
66
packages/shared-backend/src/config-agent.test.ts
Normal file
66
packages/shared-backend/src/config-agent.test.ts
Normal file
@ -0,0 +1,66 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const queryMock = vi.hoisted(() => vi.fn(async function* (_input: unknown) {
|
||||
yield { type: "result", result: "done" };
|
||||
}));
|
||||
|
||||
vi.mock("@anthropic-ai/claude-agent-sdk", () => ({
|
||||
query: queryMock,
|
||||
}));
|
||||
|
||||
let originalProxyUrl: string | undefined;
|
||||
|
||||
beforeEach(() => {
|
||||
originalProxyUrl = process.env.STACK_CLAUDE_PROXY_URL;
|
||||
delete process.env.STACK_CLAUDE_PROXY_URL;
|
||||
vi.resetModules();
|
||||
queryMock.mockClear();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
if (originalProxyUrl === undefined) {
|
||||
delete process.env.STACK_CLAUDE_PROXY_URL;
|
||||
} else {
|
||||
process.env.STACK_CLAUDE_PROXY_URL = originalProxyUrl;
|
||||
}
|
||||
});
|
||||
|
||||
describe("runHeadlessClaudeAgent", () => {
|
||||
it("defaults to the latest AI proxy endpoint", async () => {
|
||||
const { runHeadlessClaudeAgent } = await import("./config-agent");
|
||||
|
||||
await runHeadlessClaudeAgent({
|
||||
prompt: "update the config",
|
||||
cwd: process.cwd(),
|
||||
allowedTools: [],
|
||||
});
|
||||
|
||||
expect(queryMock).toHaveBeenCalledWith(expect.objectContaining({
|
||||
options: expect.objectContaining({
|
||||
env: expect.objectContaining({
|
||||
ANTHROPIC_BASE_URL: "https://api.hexclave.com/api/latest/integrations/ai-proxy",
|
||||
}),
|
||||
}),
|
||||
}));
|
||||
});
|
||||
|
||||
it("allows the agent proxy endpoint to be overridden", async () => {
|
||||
process.env.STACK_CLAUDE_PROXY_URL = "https://example.com/agent-proxy";
|
||||
const { runHeadlessClaudeAgent } = await import("./config-agent");
|
||||
|
||||
await runHeadlessClaudeAgent({
|
||||
prompt: "update the config",
|
||||
cwd: process.cwd(),
|
||||
allowedTools: [],
|
||||
});
|
||||
|
||||
expect(queryMock).toHaveBeenCalledWith(expect.objectContaining({
|
||||
options: expect.objectContaining({
|
||||
env: expect.objectContaining({
|
||||
ANTHROPIC_BASE_URL: "https://example.com/agent-proxy",
|
||||
}),
|
||||
}),
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { query } from "@anthropic-ai/claude-agent-sdk";
|
||||
import path from "path";
|
||||
|
||||
const DEFAULT_PROXY_URL = "https://api.hexclave.com/api/v1/integrations/ai-proxy";
|
||||
const DEFAULT_PROXY_URL = "https://api.hexclave.com/api/latest/integrations/ai-proxy";
|
||||
const ANTHROPIC_PROXY_BASE_URL: string = process.env.STACK_CLAUDE_PROXY_URL ?? DEFAULT_PROXY_URL;
|
||||
|
||||
export type ClaudeAgentToolName = "Read" | "Write" | "Edit" | "MultiEdit" | "NotebookEdit" | "Bash" | "Glob" | "Grep";
|
||||
|
||||
Loading…
Reference in New Issue
Block a user