mirror of
https://github.com/harivansh-afk/sandbox-agent.git
synced 2026-04-15 08:03:46 +00:00
chore: fix bad merge
This commit is contained in:
parent
1dd45908a3
commit
94353f7696
205 changed files with 19244 additions and 14866 deletions
481
scripts/agent-configs/dump.ts
Normal file
481
scripts/agent-configs/dump.ts
Normal file
|
|
@ -0,0 +1,481 @@
|
|||
/**
|
||||
* Fetches model/mode lists from agent backends and writes them to resources/.
|
||||
*
|
||||
* Usage:
|
||||
* npx tsx dump.ts # Dump all agents
|
||||
* npx tsx dump.ts --agent claude # Dump only Claude
|
||||
* npx tsx dump.ts --agent opencode --opencode-url http://127.0.0.1:4096
|
||||
*
|
||||
* Sources:
|
||||
* Claude — Anthropic API (GET /v1/models?beta=true). Extracts API key from
|
||||
* ANTHROPIC_API_KEY env. Falls back to aliases (default, sonnet, opus, haiku)
|
||||
* on 401/403 or missing credentials.
|
||||
* Codex — Codex app-server JSON-RPC (model/list over stdio, paginated).
|
||||
* OpenCode — OpenCode HTTP server (GET {base_url}/config/providers, fallback /provider).
|
||||
* Model IDs formatted as {provider_id}/{model_id}.
|
||||
* Cursor — `cursor-agent models` CLI command. Parses the text output.
|
||||
*
|
||||
* Output goes to resources/ alongside this script. These JSON files are committed
|
||||
* to the repo and included in the sandbox-agent binary at compile time via include_str!.
|
||||
*/
|
||||
|
||||
import { execSync, spawn } from "node:child_process";
|
||||
import * as fs from "node:fs";
|
||||
import * as path from "node:path";
|
||||
import * as readline from "node:readline";
|
||||
|
||||
// ─── Types ────────────────────────────────────────────────────────────────────
|
||||
|
||||
interface ModelEntry {
|
||||
id: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
interface ModeEntry {
|
||||
id: string;
|
||||
name: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
interface AgentModelList {
|
||||
defaultModel: string;
|
||||
models: ModelEntry[];
|
||||
defaultMode?: string;
|
||||
modes?: ModeEntry[];
|
||||
}
|
||||
|
||||
// ─── CLI ──────────────────────────────────────────────────────────────────────
|
||||
|
||||
const args = process.argv.slice(2);
|
||||
const agentFilter: string[] = [];
|
||||
let opencodeUrl: string | undefined;
|
||||
let codexPath: string | undefined;
|
||||
let cursorPath: string | undefined;
|
||||
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
if (args[i] === "--agent" && args[i + 1]) {
|
||||
agentFilter.push(args[++i]);
|
||||
} else if (args[i] === "--opencode-url" && args[i + 1]) {
|
||||
opencodeUrl = args[++i];
|
||||
} else if (args[i] === "--codex-path" && args[i + 1]) {
|
||||
codexPath = args[++i];
|
||||
} else if (args[i] === "--cursor-path" && args[i + 1]) {
|
||||
cursorPath = args[++i];
|
||||
}
|
||||
}
|
||||
|
||||
const RESOURCES_DIR = path.join(__dirname, "resources");
|
||||
const agents = agentFilter.length
|
||||
? agentFilter
|
||||
: ["claude", "codex", "opencode", "cursor"];
|
||||
|
||||
async function main() {
|
||||
fs.mkdirSync(RESOURCES_DIR, { recursive: true });
|
||||
|
||||
for (const agent of agents) {
|
||||
try {
|
||||
switch (agent) {
|
||||
case "claude":
|
||||
await dumpClaude();
|
||||
break;
|
||||
case "codex":
|
||||
await dumpCodex();
|
||||
break;
|
||||
case "opencode":
|
||||
await dumpOpencode();
|
||||
break;
|
||||
case "cursor":
|
||||
await dumpCursor();
|
||||
break;
|
||||
default:
|
||||
console.error(`Unknown agent: ${agent}`);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(` Error for ${agent}: ${err}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function writeList(agent: string, list: AgentModelList) {
|
||||
const filePath = path.join(RESOURCES_DIR, `${agent}.json`);
|
||||
fs.writeFileSync(filePath, JSON.stringify(list, null, 2) + "\n");
|
||||
const modeCount = list.modes?.length ?? 0;
|
||||
console.log(
|
||||
` Wrote ${list.models.length} models${modeCount ? `, ${modeCount} modes` : ""} to ${filePath} (default: ${list.defaultModel})`
|
||||
);
|
||||
}
|
||||
|
||||
// ─── Claude ───────────────────────────────────────────────────────────────────
|
||||
|
||||
const ANTHROPIC_API_URL = "https://api.anthropic.com/v1/models?beta=true";
|
||||
const ANTHROPIC_VERSION = "2023-06-01";
|
||||
|
||||
const CLAUDE_FALLBACK: AgentModelList = {
|
||||
defaultModel: "default",
|
||||
models: [
|
||||
{ id: "default", name: "Default (recommended)" },
|
||||
{ id: "opus", name: "Opus" },
|
||||
{ id: "sonnet", name: "Sonnet" },
|
||||
{ id: "haiku", name: "Haiku" },
|
||||
],
|
||||
};
|
||||
|
||||
async function dumpClaude() {
|
||||
console.log("Fetching Claude models...");
|
||||
const apiKey = process.env.ANTHROPIC_API_KEY || process.env.CLAUDE_API_KEY;
|
||||
if (!apiKey) {
|
||||
console.log(" No ANTHROPIC_API_KEY set, using fallback aliases");
|
||||
writeList("claude", CLAUDE_FALLBACK);
|
||||
return;
|
||||
}
|
||||
|
||||
const headers: Record<string, string> = {
|
||||
"anthropic-version": ANTHROPIC_VERSION,
|
||||
"x-api-key": apiKey,
|
||||
};
|
||||
|
||||
const response = await fetch(ANTHROPIC_API_URL, { headers });
|
||||
if (response.status === 401 || response.status === 403) {
|
||||
console.log(
|
||||
` API returned ${response.status}, using fallback aliases`
|
||||
);
|
||||
writeList("claude", CLAUDE_FALLBACK);
|
||||
return;
|
||||
}
|
||||
if (!response.ok) {
|
||||
throw new Error(
|
||||
`Anthropic API returned ${response.status}: ${await response.text()}`
|
||||
);
|
||||
}
|
||||
|
||||
const body = (await response.json()) as {
|
||||
data?: Array<{
|
||||
id: string;
|
||||
display_name?: string;
|
||||
created_at?: string;
|
||||
}>;
|
||||
};
|
||||
const data = body.data ?? [];
|
||||
|
||||
let defaultModel: string | undefined;
|
||||
let defaultCreated: string | undefined;
|
||||
const models: ModelEntry[] = [];
|
||||
|
||||
for (const item of data) {
|
||||
models.push({
|
||||
id: item.id,
|
||||
name: item.display_name ?? item.id,
|
||||
});
|
||||
if (item.created_at) {
|
||||
if (!defaultCreated || item.created_at > defaultCreated) {
|
||||
defaultCreated = item.created_at;
|
||||
defaultModel = item.id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
models.sort((a, b) => a.id.localeCompare(b.id));
|
||||
|
||||
if (models.length === 0) {
|
||||
console.log(" API returned empty model list, using fallback aliases");
|
||||
writeList("claude", CLAUDE_FALLBACK);
|
||||
return;
|
||||
}
|
||||
|
||||
writeList("claude", {
|
||||
defaultModel: defaultModel ?? models[0]?.id ?? "default",
|
||||
models,
|
||||
});
|
||||
}
|
||||
|
||||
// ─── Codex ────────────────────────────────────────────────────────────────────
|
||||
|
||||
async function dumpCodex() {
|
||||
console.log("Fetching Codex models...");
|
||||
const binary = codexPath ?? findBinary("codex");
|
||||
if (!binary) {
|
||||
throw new Error("codex binary not found (set --codex-path or add to PATH)");
|
||||
}
|
||||
console.log(` Using binary: ${binary}`);
|
||||
|
||||
const child = spawn(binary, ["app-server"], {
|
||||
stdio: ["pipe", "pipe", "ignore"],
|
||||
});
|
||||
|
||||
const rl = readline.createInterface({ input: child.stdout! });
|
||||
|
||||
const models: ModelEntry[] = [];
|
||||
let defaultModel: string | undefined;
|
||||
const seen = new Set<string>();
|
||||
let cursor: string | null = null;
|
||||
let requestId = 1;
|
||||
|
||||
try {
|
||||
// Initialize handshake (required before model/list)
|
||||
const initRequest = JSON.stringify({
|
||||
jsonrpc: "2.0",
|
||||
id: requestId++,
|
||||
method: "initialize",
|
||||
params: {
|
||||
clientInfo: {
|
||||
name: "agent-configs-dump",
|
||||
title: "agent-configs-dump",
|
||||
version: "1.0.0",
|
||||
},
|
||||
},
|
||||
});
|
||||
child.stdin!.write(initRequest + "\n");
|
||||
const initLine = await readLineWithTimeout(rl, 10_000);
|
||||
const initValue = JSON.parse(initLine);
|
||||
if (initValue.error) {
|
||||
throw new Error(`Codex initialize error: ${JSON.stringify(initValue.error)}`);
|
||||
}
|
||||
// Send initialized notification
|
||||
child.stdin!.write(JSON.stringify({ jsonrpc: "2.0", method: "initialized" }) + "\n");
|
||||
|
||||
while (true) {
|
||||
const request = JSON.stringify({
|
||||
jsonrpc: "2.0",
|
||||
id: requestId++,
|
||||
method: "model/list",
|
||||
params: { cursor, limit: null },
|
||||
});
|
||||
child.stdin!.write(request + "\n");
|
||||
|
||||
const line = await readLineWithTimeout(rl, 10_000);
|
||||
const value = JSON.parse(line);
|
||||
|
||||
if (value.error) {
|
||||
throw new Error(`Codex error: ${JSON.stringify(value.error)}`);
|
||||
}
|
||||
|
||||
const result = value.result ?? value;
|
||||
const data = result.data ?? [];
|
||||
|
||||
for (const item of data) {
|
||||
const modelId = item.model ?? item.id;
|
||||
if (!modelId || seen.has(modelId)) continue;
|
||||
seen.add(modelId);
|
||||
|
||||
models.push({
|
||||
id: modelId,
|
||||
name: item.displayName ?? modelId,
|
||||
});
|
||||
|
||||
if (!defaultModel && item.isDefault) {
|
||||
defaultModel = modelId;
|
||||
}
|
||||
}
|
||||
|
||||
const nextCursor = result.nextCursor;
|
||||
if (!nextCursor) break;
|
||||
cursor = nextCursor;
|
||||
}
|
||||
} finally {
|
||||
child.kill();
|
||||
}
|
||||
|
||||
models.sort((a, b) => a.id.localeCompare(b.id));
|
||||
|
||||
writeList("codex", {
|
||||
defaultModel: defaultModel ?? models[0]?.id ?? "",
|
||||
models,
|
||||
});
|
||||
}
|
||||
|
||||
function readLineWithTimeout(
|
||||
rl: readline.Interface,
|
||||
timeoutMs: number
|
||||
): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const timer = setTimeout(() => {
|
||||
reject(new Error("readline timeout"));
|
||||
}, timeoutMs);
|
||||
rl.once("line", (line) => {
|
||||
clearTimeout(timer);
|
||||
resolve(line);
|
||||
});
|
||||
rl.once("close", () => {
|
||||
clearTimeout(timer);
|
||||
reject(new Error("readline closed"));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// ─── OpenCode ─────────────────────────────────────────────────────────────────
|
||||
|
||||
async function dumpOpencode() {
|
||||
const baseUrl = opencodeUrl ?? process.env.OPENCODE_URL;
|
||||
if (!baseUrl) {
|
||||
console.log(
|
||||
" Skipped: --opencode-url not provided (set OPENCODE_URL or pass --opencode-url)"
|
||||
);
|
||||
return;
|
||||
}
|
||||
console.log(`Fetching OpenCode models from ${baseUrl}...`);
|
||||
|
||||
const endpoints = [
|
||||
`${baseUrl}/config/providers`,
|
||||
`${baseUrl}/provider`,
|
||||
];
|
||||
|
||||
for (const url of endpoints) {
|
||||
try {
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) {
|
||||
console.log(` ${url} returned ${response.status}`);
|
||||
continue;
|
||||
}
|
||||
const value = await response.json();
|
||||
const list = parseOpencodeProviders(value as Record<string, unknown>);
|
||||
if (list) {
|
||||
writeList("opencode", list);
|
||||
return;
|
||||
}
|
||||
console.log(` ${url} returned no parseable models`);
|
||||
} catch (err) {
|
||||
console.log(` ${url} failed: ${err}`);
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error("OpenCode model endpoints unavailable");
|
||||
}
|
||||
|
||||
function parseOpencodeProviders(
|
||||
value: Record<string, unknown>
|
||||
): AgentModelList | null {
|
||||
const providers = (
|
||||
(value.providers as unknown[]) ?? (value.all as unknown[])
|
||||
) as Array<{
|
||||
id: string;
|
||||
name?: string;
|
||||
models?: Record<string, { id?: string; name?: string }>;
|
||||
}> | undefined;
|
||||
if (!providers) return null;
|
||||
|
||||
const defaultMap = (value.default as Record<string, string>) ?? {};
|
||||
const models: ModelEntry[] = [];
|
||||
const providerOrder: string[] = [];
|
||||
|
||||
for (const provider of providers) {
|
||||
if (!provider.id) continue;
|
||||
providerOrder.push(provider.id);
|
||||
if (!provider.models) continue;
|
||||
const providerName = provider.name ?? provider.id;
|
||||
for (const [key, model] of Object.entries(provider.models)) {
|
||||
const modelId = model.id ?? key;
|
||||
const modelName = model.name ?? modelId;
|
||||
models.push({
|
||||
id: `${provider.id}/${modelId}`,
|
||||
name: `${providerName}/${modelName}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
models.sort((a, b) => a.id.localeCompare(b.id));
|
||||
|
||||
let defaultModel: string | undefined;
|
||||
for (const providerId of providerOrder) {
|
||||
if (defaultMap[providerId]) {
|
||||
defaultModel = `${providerId}/${defaultMap[providerId]}`;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!defaultModel) {
|
||||
defaultModel = models[0]?.id;
|
||||
}
|
||||
|
||||
return {
|
||||
defaultModel: defaultModel ?? "",
|
||||
models,
|
||||
// OpenCode modes are not available via /config/providers — hardcode known ones
|
||||
defaultMode: "build",
|
||||
modes: [
|
||||
{
|
||||
id: "build",
|
||||
name: "Build",
|
||||
description:
|
||||
"The default agent. Executes tools based on configured permissions.",
|
||||
},
|
||||
{
|
||||
id: "plan",
|
||||
name: "Plan",
|
||||
description: "Plan mode. Disallows all edit tools.",
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
// ─── Cursor ───────────────────────────────────────────────────────────────────
|
||||
|
||||
async function dumpCursor() {
|
||||
console.log("Fetching Cursor models...");
|
||||
const binary = cursorPath ?? findBinary("cursor-agent");
|
||||
if (!binary) {
|
||||
throw new Error(
|
||||
"cursor-agent binary not found (set --cursor-path or add to PATH)"
|
||||
);
|
||||
}
|
||||
console.log(` Using binary: ${binary}`);
|
||||
|
||||
const output = execSync(`${binary} models`, {
|
||||
encoding: "utf-8",
|
||||
timeout: 15_000,
|
||||
});
|
||||
|
||||
const models: ModelEntry[] = [];
|
||||
let defaultModel: string | undefined;
|
||||
|
||||
// Parse lines like: "model-id - Display Name (current)" or "(default)"
|
||||
for (const rawLine of output.split("\n")) {
|
||||
// Strip ANSI escape codes
|
||||
const line = rawLine.replace(/\x1b\[[0-9;]*[A-Za-z]|\x1b\[?[0-9;]*[A-Za-z]/g, "").trim();
|
||||
const match = line.match(
|
||||
/^(\S+)\s+-\s+(.+?)(?:\s+\((current|default)\))?$/
|
||||
);
|
||||
if (!match) continue;
|
||||
const [, id, name, tag] = match;
|
||||
models.push({ id, name: name.trim() });
|
||||
if (tag === "current" || tag === "default") {
|
||||
defaultModel = id;
|
||||
}
|
||||
}
|
||||
|
||||
if (models.length === 0) {
|
||||
throw new Error(
|
||||
"cursor-agent models returned no parseable models"
|
||||
);
|
||||
}
|
||||
|
||||
writeList("cursor", {
|
||||
defaultModel: defaultModel ?? models[0]?.id ?? "auto",
|
||||
models,
|
||||
});
|
||||
}
|
||||
|
||||
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
||||
|
||||
function findBinary(name: string): string | null {
|
||||
// Check sandbox-agent install dir
|
||||
const installDir = path.join(
|
||||
process.env.HOME ?? "",
|
||||
".local",
|
||||
"share",
|
||||
"sandbox-agent",
|
||||
"bin"
|
||||
);
|
||||
const installed = path.join(installDir, name);
|
||||
if (fs.existsSync(installed)) return installed;
|
||||
|
||||
// Search PATH
|
||||
try {
|
||||
return execSync(`which ${name}`, { encoding: "utf-8" }).trim() || null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
19
scripts/agent-configs/package.json
Normal file
19
scripts/agent-configs/package.json
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"name": "agent-configs",
|
||||
"version": "1.0.0",
|
||||
"description": "Fetches model/mode lists from agent backends and dumps them to JSON",
|
||||
"scripts": {
|
||||
"dump": "npx tsx dump.ts",
|
||||
"dump:claude": "npx tsx dump.ts --agent claude",
|
||||
"dump:codex": "npx tsx dump.ts --agent codex",
|
||||
"dump:opencode": "npx tsx dump.ts --agent opencode",
|
||||
"dump:cursor": "npx tsx dump.ts --agent cursor",
|
||||
"check-types": "tsc --noEmit"
|
||||
},
|
||||
"packageManager": "pnpm@10.13.1",
|
||||
"devDependencies": {
|
||||
"@types/node": "^24.3.0",
|
||||
"tsx": "^4.19.0",
|
||||
"typescript": "^5.8.0"
|
||||
}
|
||||
}
|
||||
21
scripts/agent-configs/resources/claude.json
Normal file
21
scripts/agent-configs/resources/claude.json
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"defaultModel": "default",
|
||||
"models": [
|
||||
{
|
||||
"id": "default",
|
||||
"name": "Default (recommended)"
|
||||
},
|
||||
{
|
||||
"id": "opus",
|
||||
"name": "Opus"
|
||||
},
|
||||
{
|
||||
"id": "sonnet",
|
||||
"name": "Sonnet"
|
||||
},
|
||||
{
|
||||
"id": "haiku",
|
||||
"name": "Haiku"
|
||||
}
|
||||
]
|
||||
}
|
||||
25
scripts/agent-configs/resources/codex.json
Normal file
25
scripts/agent-configs/resources/codex.json
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"defaultModel": "gpt-5.3-codex",
|
||||
"models": [
|
||||
{
|
||||
"id": "gpt-5.1-codex-max",
|
||||
"name": "gpt-5.1-codex-max"
|
||||
},
|
||||
{
|
||||
"id": "gpt-5.1-codex-mini",
|
||||
"name": "gpt-5.1-codex-mini"
|
||||
},
|
||||
{
|
||||
"id": "gpt-5.2",
|
||||
"name": "gpt-5.2"
|
||||
},
|
||||
{
|
||||
"id": "gpt-5.2-codex",
|
||||
"name": "gpt-5.2-codex"
|
||||
},
|
||||
{
|
||||
"id": "gpt-5.3-codex",
|
||||
"name": "gpt-5.3-codex"
|
||||
}
|
||||
]
|
||||
}
|
||||
137
scripts/agent-configs/resources/cursor.json
Normal file
137
scripts/agent-configs/resources/cursor.json
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
{
|
||||
"defaultModel": "opus-4.6-thinking",
|
||||
"models": [
|
||||
{
|
||||
"id": "auto",
|
||||
"name": "Auto"
|
||||
},
|
||||
{
|
||||
"id": "composer-1.5",
|
||||
"name": "Composer 1.5"
|
||||
},
|
||||
{
|
||||
"id": "composer-1",
|
||||
"name": "Composer 1"
|
||||
},
|
||||
{
|
||||
"id": "gpt-5.3-codex",
|
||||
"name": "GPT-5.3 Codex"
|
||||
},
|
||||
{
|
||||
"id": "gpt-5.3-codex-low",
|
||||
"name": "GPT-5.3 Codex Low"
|
||||
},
|
||||
{
|
||||
"id": "gpt-5.3-codex-high",
|
||||
"name": "GPT-5.3 Codex High"
|
||||
},
|
||||
{
|
||||
"id": "gpt-5.3-codex-xhigh",
|
||||
"name": "GPT-5.3 Codex Extra High"
|
||||
},
|
||||
{
|
||||
"id": "gpt-5.3-codex-fast",
|
||||
"name": "GPT-5.3 Codex Fast"
|
||||
},
|
||||
{
|
||||
"id": "gpt-5.3-codex-low-fast",
|
||||
"name": "GPT-5.3 Codex Low Fast"
|
||||
},
|
||||
{
|
||||
"id": "gpt-5.3-codex-high-fast",
|
||||
"name": "GPT-5.3 Codex High Fast"
|
||||
},
|
||||
{
|
||||
"id": "gpt-5.3-codex-xhigh-fast",
|
||||
"name": "GPT-5.3 Codex Extra High Fast"
|
||||
},
|
||||
{
|
||||
"id": "gpt-5.2",
|
||||
"name": "GPT-5.2"
|
||||
},
|
||||
{
|
||||
"id": "gpt-5.2-codex",
|
||||
"name": "GPT-5.2 Codex"
|
||||
},
|
||||
{
|
||||
"id": "gpt-5.2-codex-high",
|
||||
"name": "GPT-5.2 Codex High"
|
||||
},
|
||||
{
|
||||
"id": "gpt-5.2-codex-low",
|
||||
"name": "GPT-5.2 Codex Low"
|
||||
},
|
||||
{
|
||||
"id": "gpt-5.2-codex-xhigh",
|
||||
"name": "GPT-5.2 Codex Extra High"
|
||||
},
|
||||
{
|
||||
"id": "gpt-5.2-codex-fast",
|
||||
"name": "GPT-5.2 Codex Fast"
|
||||
},
|
||||
{
|
||||
"id": "gpt-5.2-codex-high-fast",
|
||||
"name": "GPT-5.2 Codex High Fast"
|
||||
},
|
||||
{
|
||||
"id": "gpt-5.2-codex-low-fast",
|
||||
"name": "GPT-5.2 Codex Low Fast"
|
||||
},
|
||||
{
|
||||
"id": "gpt-5.2-codex-xhigh-fast",
|
||||
"name": "GPT-5.2 Codex Extra High Fast"
|
||||
},
|
||||
{
|
||||
"id": "gpt-5.1-codex-max",
|
||||
"name": "GPT-5.1 Codex Max"
|
||||
},
|
||||
{
|
||||
"id": "gpt-5.1-codex-max-high",
|
||||
"name": "GPT-5.1 Codex Max High"
|
||||
},
|
||||
{
|
||||
"id": "opus-4.6-thinking",
|
||||
"name": "Claude 4.6 Opus (Thinking)"
|
||||
},
|
||||
{
|
||||
"id": "gpt-5.2-high",
|
||||
"name": "GPT-5.2 High"
|
||||
},
|
||||
{
|
||||
"id": "opus-4.6",
|
||||
"name": "Claude 4.6 Opus"
|
||||
},
|
||||
{
|
||||
"id": "opus-4.5",
|
||||
"name": "Claude 4.5 Opus"
|
||||
},
|
||||
{
|
||||
"id": "opus-4.5-thinking",
|
||||
"name": "Claude 4.5 Opus (Thinking)"
|
||||
},
|
||||
{
|
||||
"id": "sonnet-4.5",
|
||||
"name": "Claude 4.5 Sonnet"
|
||||
},
|
||||
{
|
||||
"id": "sonnet-4.5-thinking",
|
||||
"name": "Claude 4.5 Sonnet (Thinking)"
|
||||
},
|
||||
{
|
||||
"id": "gpt-5.1-high",
|
||||
"name": "GPT-5.1 High"
|
||||
},
|
||||
{
|
||||
"id": "gemini-3-pro",
|
||||
"name": "Gemini 3 Pro"
|
||||
},
|
||||
{
|
||||
"id": "gemini-3-flash",
|
||||
"name": "Gemini 3 Flash"
|
||||
},
|
||||
{
|
||||
"id": "grok",
|
||||
"name": "Grok"
|
||||
}
|
||||
]
|
||||
}
|
||||
254
scripts/agent-configs/resources/opencode.json
Normal file
254
scripts/agent-configs/resources/opencode.json
Normal file
|
|
@ -0,0 +1,254 @@
|
|||
{
|
||||
"defaultModel": "opencode/gemini-3-pro",
|
||||
"models": [
|
||||
{
|
||||
"id": "anthropic/claude-3-5-haiku-20241022",
|
||||
"name": "Anthropic/Claude Haiku 3.5"
|
||||
},
|
||||
{
|
||||
"id": "anthropic/claude-3-5-haiku-latest",
|
||||
"name": "Anthropic/Claude Haiku 3.5 (latest)"
|
||||
},
|
||||
{
|
||||
"id": "anthropic/claude-3-5-sonnet-20240620",
|
||||
"name": "Anthropic/Claude Sonnet 3.5"
|
||||
},
|
||||
{
|
||||
"id": "anthropic/claude-3-5-sonnet-20241022",
|
||||
"name": "Anthropic/Claude Sonnet 3.5 v2"
|
||||
},
|
||||
{
|
||||
"id": "anthropic/claude-3-7-sonnet-20250219",
|
||||
"name": "Anthropic/Claude Sonnet 3.7"
|
||||
},
|
||||
{
|
||||
"id": "anthropic/claude-3-7-sonnet-latest",
|
||||
"name": "Anthropic/Claude Sonnet 3.7 (latest)"
|
||||
},
|
||||
{
|
||||
"id": "anthropic/claude-3-haiku-20240307",
|
||||
"name": "Anthropic/Claude Haiku 3"
|
||||
},
|
||||
{
|
||||
"id": "anthropic/claude-3-opus-20240229",
|
||||
"name": "Anthropic/Claude Opus 3"
|
||||
},
|
||||
{
|
||||
"id": "anthropic/claude-3-sonnet-20240229",
|
||||
"name": "Anthropic/Claude Sonnet 3"
|
||||
},
|
||||
{
|
||||
"id": "anthropic/claude-haiku-4-5",
|
||||
"name": "Anthropic/Claude Haiku 4.5 (latest)"
|
||||
},
|
||||
{
|
||||
"id": "anthropic/claude-haiku-4-5-20251001",
|
||||
"name": "Anthropic/Claude Haiku 4.5"
|
||||
},
|
||||
{
|
||||
"id": "anthropic/claude-opus-4-0",
|
||||
"name": "Anthropic/Claude Opus 4 (latest)"
|
||||
},
|
||||
{
|
||||
"id": "anthropic/claude-opus-4-1",
|
||||
"name": "Anthropic/Claude Opus 4.1 (latest)"
|
||||
},
|
||||
{
|
||||
"id": "anthropic/claude-opus-4-1-20250805",
|
||||
"name": "Anthropic/Claude Opus 4.1"
|
||||
},
|
||||
{
|
||||
"id": "anthropic/claude-opus-4-20250514",
|
||||
"name": "Anthropic/Claude Opus 4"
|
||||
},
|
||||
{
|
||||
"id": "anthropic/claude-opus-4-5",
|
||||
"name": "Anthropic/Claude Opus 4.5 (latest)"
|
||||
},
|
||||
{
|
||||
"id": "anthropic/claude-opus-4-5-20251101",
|
||||
"name": "Anthropic/Claude Opus 4.5"
|
||||
},
|
||||
{
|
||||
"id": "anthropic/claude-opus-4-6",
|
||||
"name": "Anthropic/Claude Opus 4.6"
|
||||
},
|
||||
{
|
||||
"id": "anthropic/claude-sonnet-4-0",
|
||||
"name": "Anthropic/Claude Sonnet 4 (latest)"
|
||||
},
|
||||
{
|
||||
"id": "anthropic/claude-sonnet-4-20250514",
|
||||
"name": "Anthropic/Claude Sonnet 4"
|
||||
},
|
||||
{
|
||||
"id": "anthropic/claude-sonnet-4-5",
|
||||
"name": "Anthropic/Claude Sonnet 4.5 (latest)"
|
||||
},
|
||||
{
|
||||
"id": "anthropic/claude-sonnet-4-5-20250929",
|
||||
"name": "Anthropic/Claude Sonnet 4.5"
|
||||
},
|
||||
{
|
||||
"id": "cerebras/gpt-oss-120b",
|
||||
"name": "Cerebras/GPT OSS 120B"
|
||||
},
|
||||
{
|
||||
"id": "cerebras/qwen-3-235b-a22b-instruct-2507",
|
||||
"name": "Cerebras/Qwen 3 235B Instruct"
|
||||
},
|
||||
{
|
||||
"id": "cerebras/zai-glm-4.7",
|
||||
"name": "Cerebras/Z.AI GLM-4.7"
|
||||
},
|
||||
{
|
||||
"id": "openai/gpt-5.1-codex",
|
||||
"name": "OpenAI/GPT-5.1 Codex"
|
||||
},
|
||||
{
|
||||
"id": "openai/gpt-5.1-codex-max",
|
||||
"name": "OpenAI/GPT-5.1 Codex Max"
|
||||
},
|
||||
{
|
||||
"id": "openai/gpt-5.1-codex-mini",
|
||||
"name": "OpenAI/GPT-5.1 Codex mini"
|
||||
},
|
||||
{
|
||||
"id": "openai/gpt-5.2",
|
||||
"name": "OpenAI/GPT-5.2"
|
||||
},
|
||||
{
|
||||
"id": "openai/gpt-5.2-codex",
|
||||
"name": "OpenAI/GPT-5.2 Codex"
|
||||
},
|
||||
{
|
||||
"id": "openai/gpt-5.3-codex",
|
||||
"name": "OpenAI/GPT-5.3 Codex"
|
||||
},
|
||||
{
|
||||
"id": "opencode/big-pickle",
|
||||
"name": "OpenCode Zen/Big Pickle"
|
||||
},
|
||||
{
|
||||
"id": "opencode/claude-3-5-haiku",
|
||||
"name": "OpenCode Zen/Claude Haiku 3.5"
|
||||
},
|
||||
{
|
||||
"id": "opencode/claude-haiku-4-5",
|
||||
"name": "OpenCode Zen/Claude Haiku 4.5"
|
||||
},
|
||||
{
|
||||
"id": "opencode/claude-opus-4-1",
|
||||
"name": "OpenCode Zen/Claude Opus 4.1"
|
||||
},
|
||||
{
|
||||
"id": "opencode/claude-opus-4-5",
|
||||
"name": "OpenCode Zen/Claude Opus 4.5"
|
||||
},
|
||||
{
|
||||
"id": "opencode/claude-opus-4-6",
|
||||
"name": "OpenCode Zen/Claude Opus 4.6"
|
||||
},
|
||||
{
|
||||
"id": "opencode/claude-sonnet-4",
|
||||
"name": "OpenCode Zen/Claude Sonnet 4"
|
||||
},
|
||||
{
|
||||
"id": "opencode/claude-sonnet-4-5",
|
||||
"name": "OpenCode Zen/Claude Sonnet 4.5"
|
||||
},
|
||||
{
|
||||
"id": "opencode/gemini-3-flash",
|
||||
"name": "OpenCode Zen/Gemini 3 Flash"
|
||||
},
|
||||
{
|
||||
"id": "opencode/gemini-3-pro",
|
||||
"name": "OpenCode Zen/Gemini 3 Pro"
|
||||
},
|
||||
{
|
||||
"id": "opencode/glm-4.6",
|
||||
"name": "OpenCode Zen/GLM-4.6"
|
||||
},
|
||||
{
|
||||
"id": "opencode/glm-4.7",
|
||||
"name": "OpenCode Zen/GLM-4.7"
|
||||
},
|
||||
{
|
||||
"id": "opencode/gpt-5",
|
||||
"name": "OpenCode Zen/GPT-5"
|
||||
},
|
||||
{
|
||||
"id": "opencode/gpt-5-codex",
|
||||
"name": "OpenCode Zen/GPT-5 Codex"
|
||||
},
|
||||
{
|
||||
"id": "opencode/gpt-5-nano",
|
||||
"name": "OpenCode Zen/GPT-5 Nano"
|
||||
},
|
||||
{
|
||||
"id": "opencode/gpt-5.1",
|
||||
"name": "OpenCode Zen/GPT-5.1"
|
||||
},
|
||||
{
|
||||
"id": "opencode/gpt-5.1-codex",
|
||||
"name": "OpenCode Zen/GPT-5.1 Codex"
|
||||
},
|
||||
{
|
||||
"id": "opencode/gpt-5.1-codex-max",
|
||||
"name": "OpenCode Zen/GPT-5.1 Codex Max"
|
||||
},
|
||||
{
|
||||
"id": "opencode/gpt-5.1-codex-mini",
|
||||
"name": "OpenCode Zen/GPT-5.1 Codex Mini"
|
||||
},
|
||||
{
|
||||
"id": "opencode/gpt-5.2",
|
||||
"name": "OpenCode Zen/GPT-5.2"
|
||||
},
|
||||
{
|
||||
"id": "opencode/gpt-5.2-codex",
|
||||
"name": "OpenCode Zen/GPT-5.2 Codex"
|
||||
},
|
||||
{
|
||||
"id": "opencode/kimi-k2",
|
||||
"name": "OpenCode Zen/Kimi K2"
|
||||
},
|
||||
{
|
||||
"id": "opencode/kimi-k2-thinking",
|
||||
"name": "OpenCode Zen/Kimi K2 Thinking"
|
||||
},
|
||||
{
|
||||
"id": "opencode/kimi-k2.5",
|
||||
"name": "OpenCode Zen/Kimi K2.5"
|
||||
},
|
||||
{
|
||||
"id": "opencode/kimi-k2.5-free",
|
||||
"name": "OpenCode Zen/Kimi K2.5 Free"
|
||||
},
|
||||
{
|
||||
"id": "opencode/minimax-m2.1",
|
||||
"name": "OpenCode Zen/MiniMax M2.1"
|
||||
},
|
||||
{
|
||||
"id": "opencode/minimax-m2.1-free",
|
||||
"name": "OpenCode Zen/MiniMax M2.1 Free"
|
||||
},
|
||||
{
|
||||
"id": "opencode/trinity-large-preview-free",
|
||||
"name": "OpenCode Zen/Trinity Large Preview"
|
||||
}
|
||||
],
|
||||
"defaultMode": "build",
|
||||
"modes": [
|
||||
{
|
||||
"id": "build",
|
||||
"name": "Build",
|
||||
"description": "The default agent. Executes tools based on configured permissions."
|
||||
},
|
||||
{
|
||||
"id": "plan",
|
||||
"name": "Plan",
|
||||
"description": "Plan mode. Disallows all edit tools."
|
||||
}
|
||||
]
|
||||
}
|
||||
8
scripts/agent-configs/tsconfig.json
Normal file
8
scripts/agent-configs/tsconfig.json
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"types": ["node"]
|
||||
},
|
||||
"include": ["**/*.ts"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
|
|
@ -36,6 +36,7 @@ export async function tagDocker(opts: ReleaseOpts) {
|
|||
// Create and push manifest with latest
|
||||
if (opts.latest) {
|
||||
await createManifest(sourceCommit, "latest");
|
||||
await createManifest(sourceCommit, opts.minorVersionChannel);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ export interface ReleaseOpts {
|
|||
root: string;
|
||||
version: string;
|
||||
latest: boolean;
|
||||
minorVersionChannel: string;
|
||||
/** Commit to publish release for. */
|
||||
commit: string;
|
||||
/** Optional version to reuse artifacts and Docker images from instead of building. */
|
||||
|
|
@ -434,6 +435,10 @@ async function main() {
|
|||
console.log(`Auto-determined latest flag: ${isLatest} (version: ${version})`);
|
||||
}
|
||||
|
||||
const parsedVersion = semver.parse(version);
|
||||
assert(parsedVersion !== null, "version must be parseable");
|
||||
const minorVersionChannel = `${parsedVersion.major}.${parsedVersion.minor}.x`;
|
||||
|
||||
// Setup opts
|
||||
let commit: string;
|
||||
if (opts.overrideCommit) {
|
||||
|
|
@ -449,6 +454,7 @@ async function main() {
|
|||
root: ROOT_DIR,
|
||||
version: version,
|
||||
latest: isLatest,
|
||||
minorVersionChannel,
|
||||
commit,
|
||||
reuseEngineVersion: opts.reuseEngineVersion,
|
||||
};
|
||||
|
|
@ -469,6 +475,7 @@ async function main() {
|
|||
console.log(`\nRelease Details:`);
|
||||
console.log(` Version: ${releaseOpts.version}`);
|
||||
console.log(` Latest: ${releaseOpts.latest}`);
|
||||
console.log(` Minor channel: ${releaseOpts.minorVersionChannel}`);
|
||||
console.log(` Commit: ${releaseOpts.commit}`);
|
||||
if (releaseOpts.reuseEngineVersion) {
|
||||
console.log(` Reusing engine version: ${releaseOpts.reuseEngineVersion}`);
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ export async function promoteArtifacts(opts: ReleaseOpts) {
|
|||
await uploadInstallScripts(opts, opts.version);
|
||||
if (opts.latest) {
|
||||
await uploadInstallScripts(opts, "latest");
|
||||
await uploadInstallScripts(opts, opts.minorVersionChannel);
|
||||
}
|
||||
|
||||
// Upload gigacode install scripts
|
||||
|
|
@ -97,5 +98,23 @@ async function promotePath(opts: ReleaseOpts, sourceCommit: string, name: string
|
|||
await copyPath(sourcePrefix, `${PREFIX}/${opts.version}/${name}/`);
|
||||
if (opts.latest) {
|
||||
await copyPath(sourcePrefix, `${PREFIX}/latest/${name}/`);
|
||||
if (name === "binaries") {
|
||||
const binariesSourcePrefix = `${PREFIX}/${sourceCommit}/binaries/sandbox-agent-`;
|
||||
const sandboxAgentBinaries = await listReleasesObjects(binariesSourcePrefix);
|
||||
if (
|
||||
!Array.isArray(sandboxAgentBinaries?.Contents) ||
|
||||
sandboxAgentBinaries.Contents.length === 0
|
||||
) {
|
||||
throw new Error(`No sandbox-agent binaries found under ${binariesSourcePrefix}`);
|
||||
}
|
||||
|
||||
await copyPath(
|
||||
binariesSourcePrefix,
|
||||
`${PREFIX}/${opts.minorVersionChannel}/binaries/sandbox-agent-`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
await copyPath(sourcePrefix, `${PREFIX}/${opts.minorVersionChannel}/${name}/`);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -228,13 +228,17 @@ export async function publishNpmCliShared(opts: ReleaseOpts) {
|
|||
|
||||
// Add --tag flag for release candidates
|
||||
const isReleaseCandidate = opts.version.includes("-rc.");
|
||||
const tag = isReleaseCandidate ? "rc" : "latest";
|
||||
const tag = isReleaseCandidate ? "rc" : (opts.latest ? "latest" : opts.minorVersionChannel);
|
||||
|
||||
await $({
|
||||
stdio: "inherit",
|
||||
cwd: cliSharedPath,
|
||||
})`pnpm publish --access public --tag ${tag} --no-git-checks`;
|
||||
|
||||
if (opts.latest && tag === "latest") {
|
||||
await addNpmDistTag(name, opts.version, opts.minorVersionChannel);
|
||||
}
|
||||
|
||||
console.log(`✅ Published ${name}@${opts.version}`);
|
||||
}
|
||||
|
||||
|
|
@ -265,13 +269,17 @@ export async function publishNpmSdk(opts: ReleaseOpts) {
|
|||
|
||||
// Add --tag flag for release candidates
|
||||
const isReleaseCandidate = opts.version.includes("-rc.");
|
||||
const tag = isReleaseCandidate ? "rc" : "latest";
|
||||
const tag = isReleaseCandidate ? "rc" : (opts.latest ? "latest" : opts.minorVersionChannel);
|
||||
|
||||
await $({
|
||||
stdio: "inherit",
|
||||
cwd: sdkPath,
|
||||
})`pnpm publish --access public --tag ${tag} --no-git-checks`;
|
||||
|
||||
if (opts.latest && tag === "latest") {
|
||||
await addNpmDistTag(name, opts.version, opts.minorVersionChannel);
|
||||
}
|
||||
|
||||
console.log(`✅ Published ${name}@${opts.version}`);
|
||||
}
|
||||
|
||||
|
|
@ -346,7 +354,12 @@ export async function publishNpmCli(opts: ReleaseOpts) {
|
|||
|
||||
// Add --tag flag for release candidates
|
||||
const isReleaseCandidate = opts.version.includes("-rc.");
|
||||
const tag = isReleaseCandidate ? "rc" : "latest";
|
||||
const tag = getCliPackageNpmTag({
|
||||
packageName,
|
||||
isReleaseCandidate,
|
||||
latest: opts.latest,
|
||||
minorVersionChannel: opts.minorVersionChannel,
|
||||
});
|
||||
|
||||
try {
|
||||
await $({
|
||||
|
|
@ -354,6 +367,14 @@ export async function publishNpmCli(opts: ReleaseOpts) {
|
|||
cwd: packagePath,
|
||||
})`pnpm publish --access public --tag ${tag} --no-git-checks`;
|
||||
console.log(`✅ Published ${packageName}@${opts.version}`);
|
||||
|
||||
if (
|
||||
opts.latest &&
|
||||
tag === "latest" &&
|
||||
isSandboxAgentCliPackage(packageName)
|
||||
) {
|
||||
await addNpmDistTag(packageName, opts.version, opts.minorVersionChannel);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(`❌ Failed to publish ${packageName}`);
|
||||
throw err;
|
||||
|
|
@ -362,3 +383,35 @@ export async function publishNpmCli(opts: ReleaseOpts) {
|
|||
|
||||
console.log("✅ All CLI packages published");
|
||||
}
|
||||
|
||||
function getCliPackageNpmTag(opts: {
|
||||
packageName: string;
|
||||
isReleaseCandidate: boolean;
|
||||
latest: boolean;
|
||||
minorVersionChannel: string;
|
||||
}): string {
|
||||
if (opts.isReleaseCandidate) {
|
||||
return "rc";
|
||||
}
|
||||
|
||||
if (opts.latest) {
|
||||
return "latest";
|
||||
}
|
||||
|
||||
return opts.minorVersionChannel;
|
||||
}
|
||||
|
||||
function isSandboxAgentCliPackage(packageName: string): boolean {
|
||||
return packageName === "@sandbox-agent/cli" || packageName.startsWith("@sandbox-agent/cli-");
|
||||
}
|
||||
|
||||
async function addNpmDistTag(
|
||||
packageName: string,
|
||||
version: string,
|
||||
tag: string,
|
||||
): Promise<void> {
|
||||
console.log(`==> Adding npm dist-tag: ${packageName}@${version} as ${tag}`);
|
||||
await $({
|
||||
stdio: "inherit",
|
||||
})`npm dist-tag add ${packageName}@${version} ${tag}`;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -322,7 +322,7 @@ async function installSandboxAgent(sandbox: Sandbox, binaryPath: string): Promis
|
|||
if (binaryPath === "RELEASE") {
|
||||
log.info("Installing from releases.rivet.dev...");
|
||||
const result = await sandbox.exec(
|
||||
"curl -fsSL https://releases.rivet.dev/sandbox-agent/latest/install.sh | sh",
|
||||
"curl -fsSL https://releases.rivet.dev/sandbox-agent/0.2.x/install.sh | sh",
|
||||
);
|
||||
log.debug(`Install output: ${result.stdout}`);
|
||||
if (result.exitCode !== 0) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue