pleumrouter 0.5.35 → 0.5.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -17,25 +17,28 @@ bun install -g pleumrouter # bun
17
17
  ## 빠른 시작
18
18
 
19
19
  ```bash
20
- npx pleumrouter login # 브라우저 OAuth 로그인 (API 키 없음)
21
- npx pleumrouter launch claude --model claude-sonnet-5
22
- npx pleumrouter launch codex --model gpt-5.3-codex
23
- npx pleumrouter run gpt-5.4-mini # 터미널 채팅
20
+ pleum # 에이전트 실행 → Claude Code · Codex · Antigravity · OpenCode
21
+ pleum claude # Claude Code 바로 실행
22
+ pleum codex # Codex 바로 실행
23
+ pleum agy # Antigravity CLI 바로 실행
24
+ pleum opencode # opencode 바로 실행
25
+ pleum run gpt-5.4-mini # 터미널 채팅
24
26
  npx pleumrouter run gpt-5.4-mini "한 줄 요약: ..." # 1회 실행(스크립트용)
25
27
  cat error.log | npx pleumrouter run gpt-5.4-mini "원인은?" # 파이프
26
28
  ```
27
29
 
28
- 로그인 후 `~/.pleum/config.json`에 access/refresh 토큰이 저장됩니다. `plm_` API 키는 발급되지 않습니다.
30
+ 최초 실행 때 브라우저 로그인을 안내하고, 코딩 에이전트용 `plm_` 키를 한 번 발급해 재사용합니다. 로그인 세션은 `~/.pleum/config.json`, 에이전트 키는 `~/.pleum/wire.json`에 저장됩니다. 두 파일은 사용자만 읽을 수 있습니다. 에이전트 실행은 만료되는 로그인 토큰을 직접 전달하지 않습니다.
29
31
  SSH/CI에서는 `pleum login --device`를 쓰세요.
30
32
  ## 명령
31
33
 
32
34
  | 명령 | 설명 |
33
35
  |------|------|
34
- | `pleum` | (인자 없음, TTY) 인터랙티브 런처 메뉴 — 키보드 전용. ↑/↓ 이동 · enter 실행 · → 모델 설정 · esc 종료(서브메뉴에선 뒤로) · ctrl+c 즉시 종료. "에이전트 실행" 진입 시 Claude Code·Codex·opencode·omp·Hermes Agent·Qwen Code·GitHub Copilot CLI 등 지원 에이전트 전체를 설치 여부와 함께 볼 수 있고, 미설치는 확인 후 자동 설치(또는 설정 파일 안내). "설정" 진입 시 언어·에이전트별 기본 모델·계정(로그인/로그아웃)·CLI 업데이트·셸 자동완성을 한곳에서 관리. 실행 종료 후 메뉴 복귀. 파이프에선 도움말 출력 |
36
+ | `pleum` | (인자 없음, TTY) 에이전트 실행 → Claude Code·Codex·Antigravity·OpenCode. 앞의 세 도구는 공식/기본 모델 또는 custom(beta)을 선택. 파이프에선 도움말 출력 |
37
+ | `pleum claude\|codex\|agy\|opencode [--model id]` | 네 우선 지원 도구를 한 명령으로 실행. Claude·Codex·agy는 모델 미지정 시 공식/기본 모드, `--model` 지정 시 custom 모드. 최초 실행은 브라우저 로그인 후 에이전트 키 발급 |
35
38
  | `pleum login [--device]` | 브라우저 OAuth 로그인 → access/refresh 토큰을 `~/.pleum/config.json`에 저장(API 키 미발급). `--device`는 SSH·CI |
36
39
  | `pleum logout` | 서버 세션 revoke + 로컬 토큰 삭제(언어·기본 모델 등 나머지 설정은 유지) |
37
40
  | `pleum launch [tool] [--model id] [-- args]` | 에이전트 실행. `--` 뒤 인자는 도구로 그대로 전달. 도구 생략 시 지원 목록·설치 여부 표시 |
38
- | `pleum wire [claude\|codex]` | Desktop용으로 `~/.claude/settings.json`·`~/.codex/config.toml`에 전용 `plm_` 키를 병합. 생략 시 둘 다. `pleum launch`의 격리 홈과는 별개 |
41
+ | `pleum wire [claude\|codex]` | Desktop용으로 `~/.claude/settings.json`·`~/.codex/config.toml`에 같은 `plm_` 키를 병합. 생략 시 둘 다 |
39
42
  | `pleum unwire [claude\|codex] [--revoke-key]` | wire가 넣은 설정만 제거. `--revoke-key`는 서버 키도 폐기 |
40
43
  | `pleum run [model] ["프롬프트"] [--attach image]` | 채팅 — 대화형 REPL, 1회 실행, stdin 파이프. 모델 생략 시 화살표로 선택. 이미지 업로드는 명시적으로 `--attach ./shot.png`(1회 실행) 또는 REPL의 `@./shot.png`를 사용한다. `--skip-cache`(이번 요청 응답 캐시 스킵), `--tag a,b`(리포팅 태그, ≤10) |
41
44
  | `pleum models [query] [--json]` | 모델 목록(공개) — provider·컨텍스트·가격(₩/1M) 컬럼, `--json`은 스크립트용 |
@@ -75,10 +78,12 @@ SSH/CI에서는 `pleum login --device`를 쓰세요.
75
78
  ## 자동 실행 지원 도구
76
79
 
77
80
  `claude` · `codex` · `aider` · `goose` · `openhands` · `opencode` · `omp` · `hermes` · `qwen` · `copilot` · `gemini` · `agy` · `pi` · `crush` · `minimax` · `mimo` · `openclaw` · `plandex` · `interpreter` —
78
- env 또는 격리 홈(`CODEX_HOME` / `PI_CODING_AGENT_DIR` / `CRUSH_GLOBAL_CONFIG`)만 세팅하고 바로 실행한다.
81
+ env·실행 인자 또는 일부 도구의 격리 홈(`PI_CODING_AGENT_DIR` / `CRUSH_GLOBAL_CONFIG`)으로 연결한다. Codex는 `-c` 임시 설정을 써서 기존 `~/.codex`의 세션과 설정을 유지한다.
79
82
  별칭: `antigravity`→`agy`, `picode`→`pi`, `ohmypi`/`oh-my-pi`→`omp`, `qwencode`/`qwen-code`→`qwen`, `minimax-code`/`mcode`→`minimax`, `mimocode`/`mimo-code`→`mimo`, `open-interpreter`→`interpreter`.
80
83
 
81
- `agy`만 사용자 `~/.gemini/antigravity-cli/settings.json`에 `modelProvider=gemini`를 병합한다(제품이 이 파일 없이 키를 무시함). Kiro는 공식 BYOK가 없어 지원하지 않는다.
84
+ 공식/기본 모드에서도 요청은 PleumRouter를 거쳐 Pleum API 크레딧으로 정산된다. Claude custom은 주 대화 모델만 바꾸며 일반 서브에이전트는 Pleum의 Sonnet으로 실행한다(Claude의 fork·`model: inherit` skill은 주 대화 모델을 상속할 수 있다). OpenCode 실행 세션의 `/models`에는 활성 Pleum 텍스트 대화 모델만 표시하며 추천 10개를 즐겨찾기 상단에 둔다. 기존 즐겨찾기와 최근 기록은 보존한다.
85
+
86
+ `agy`만 사용자 `~/.gemini/antigravity-cli/settings.json`에 `modelProvider=gemini`를 임시 병합하고 종료 시 복구한다(제품이 이 파일 없이 키를 무시함). agy custom은 설치 버전의 모델 목록과 실제 요청 ID가 확인된 Gemini 모델만 실행한다. Kiro는 공식 BYOK가 없어 지원하지 않는다.
82
87
 
83
88
  ## 환경변수
84
89
 
package/bin/pleum.mjs CHANGED
@@ -30,6 +30,7 @@ function buildHelp() {
30
30
  ["", t("--device: browser-less environments (SSH/CI)")],
31
31
  ["pleum logout", t("Revoke session and clear local tokens")],
32
32
  ["pleum launch [tool] [--model id]", t("Run a coding agent against PleumRouter")],
33
+ ["pleum claude|codex|agy|opencode", t("Run a coding agent against PleumRouter")],
33
34
  ["", `(${Object.keys(RECIPES).join(" · ")})`],
34
35
  ["", t("omit the tool to see the supported list and install status")],
35
36
  ["pleum wire [claude|codex]", t("persist config in ~/.claude or ~/.codex for Desktop apps")],
@@ -55,6 +56,10 @@ function buildHelp() {
55
56
  ["pleum wire", null],
56
57
  ["pleum launch claude --model claude-sonnet-5", null],
57
58
  ["pleum launch codex --model gpt-5.3-codex -- --full-auto", null],
59
+ ["pleum claude", null],
60
+ ["pleum codex", null],
61
+ ["pleum agy", null],
62
+ ["pleum opencode", null],
58
63
  ["pleum run gpt-5.4-mini", t("interactive")],
59
64
  [`pleum run gpt-5.4-mini "${t("Summarize in one line: ...")}"`, t("one-shot")],
60
65
  [`cat error.log | pleum run gpt-5.4-mini "${t("what caused this?")}"`, t("pipe")],
@@ -72,7 +77,10 @@ function buildHelp() {
72
77
  function parseLaunchArgs(args) {
73
78
  const out = { model: undefined, passthrough: [] };
74
79
  for (let i = 0; i < args.length; i++) {
75
- if (args[i] === "--model" || args[i] === "-m") out.model = args[++i];
80
+ if (args[i] === "--model" || args[i] === "-m") {
81
+ if (!args[i + 1] || args[i + 1] === "--") throw new Error("--model requires a model ID");
82
+ out.model = args[++i];
83
+ }
76
84
  else if (args[i] === "--") {
77
85
  out.passthrough.push(...args.slice(i + 1));
78
86
  break;
@@ -101,8 +109,13 @@ try {
101
109
  case "lang":
102
110
  await lang(rest);
103
111
  break;
104
- case "launch": {
105
- const tool = rest[0];
112
+ case "launch":
113
+ case "claude":
114
+ case "codex":
115
+ case "agy":
116
+ case "antigravity":
117
+ case "opencode": {
118
+ const tool = cmd === "launch" ? rest[0] : cmd;
106
119
  if (!tool) {
107
120
  const io = process.stdin;
108
121
  if (io.isTTY && process.stdout.isTTY && typeof io.setRawMode === "function") {
@@ -112,7 +125,7 @@ try {
112
125
  launchHelp();
113
126
  break;
114
127
  }
115
- const { model, passthrough } = parseLaunchArgs(rest.slice(1));
128
+ const { model, passthrough } = parseLaunchArgs(cmd === "launch" ? rest.slice(1) : rest);
116
129
  await launch(tool, model, passthrough);
117
130
  break;
118
131
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pleumrouter",
3
- "version": "0.5.35",
3
+ "version": "0.5.37",
4
4
  "description": "Official PleumRouter terminal CLI — launch any coding agent against PleumRouter.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -3,7 +3,7 @@
3
3
  import { t } from "./i18n.mjs";
4
4
  import { launchToolNames } from "./recipes.mjs";
5
5
 
6
- const COMMANDS = "login logout lang launch wire unwire run models top balance usage health version update upgrade completion help";
6
+ const COMMANDS = "claude codex agy antigravity opencode login logout lang launch wire unwire run models top balance usage health version update upgrade completion help";
7
7
  const TOOLS = launchToolNames().join(" ");
8
8
 
9
9
  function bash() {
package/src/launch.mjs CHANGED
@@ -1,10 +1,13 @@
1
- import { spawn } from "node:child_process";
2
- import { mkdirSync, writeFileSync, existsSync, readFileSync, rmSync } from "node:fs";
3
- import { homedir } from "node:os";
1
+ import { spawn, execFileSync } from "node:child_process";
2
+ import { mkdirSync, writeFileSync, existsSync, readFileSync, rmSync, mkdtempSync, renameSync } from "node:fs";
3
+ import { homedir, tmpdir } from "node:os";
4
4
  import { join, delimiter, dirname, resolve } from "node:path";
5
- import { requireAuth, getActiveContext } from "./config.mjs";
5
+ import { readConfig, isLoggedIn, getActiveContext, ROOT } from "./config.mjs";
6
+ import { login } from "./login.mjs";
7
+ import { ensureWireKey } from "./wire.mjs";
6
8
  import {
7
9
  RECIPES,
10
+ CORE_MODELS,
8
11
  MANUAL,
9
12
  LAUNCH_ALIASES,
10
13
  resolveLaunchTool,
@@ -15,6 +18,7 @@ import {
15
18
  } from "./recipes.mjs";
16
19
  import { t } from "./i18n.mjs";
17
20
  import { sanitizeTerminalText } from "./ansi.mjs";
21
+ import { fetchModels, codingModels } from "./models.mjs";
18
22
 
19
23
  // PATH에서 실행 파일을 찾는다(설치 여부 표시용). menu.mjs도 사용.
20
24
  export function onPath(bin) {
@@ -93,17 +97,125 @@ export function launchHelp() {
93
97
  console.log(`\n${t("Example: pleum launch claude --model claude-sonnet-5")}`);
94
98
  }
95
99
 
100
+ // 메뉴·단축 명령·`launch`가 모두 같은 저장 모델을 사용한다. 명시적 --model이 우선이다.
101
+ export function resolveLaunchModel(tool, explicit, cfg = readConfig()) {
102
+ const recipe = RECIPES[tool];
103
+ if (recipe?.resolveModel) return recipe.resolveModel(explicit, cfg);
104
+ return explicit || cfg?.launch_models?.[tool] || recipe?.defaultModel;
105
+ }
106
+
107
+ // agy의 Google API-key 모드는 계정 모드보다 모델이 적다. 임시 HOME으로 실제
108
+ // 설치 버전의 목록을 읽어, 선택 모델이 다른 Gemini 모델로 조용히 바뀌는 일을 막는다.
109
+ export function listAgyModelIds({ run = execFileSync } = {}) {
110
+ const home = mkdtempSync(join(tmpdir(), "pleum-agy-models-"));
111
+ try {
112
+ const settingsDir = join(home, ".gemini", "antigravity-cli");
113
+ mkdirSync(settingsDir, { recursive: true, mode: 0o700 });
114
+ writeFileSync(join(settingsDir, "settings.json"), '{"modelProvider":"gemini"}', { mode: 0o600 });
115
+ const output = run("agy", ["models"], {
116
+ encoding: "utf8",
117
+ timeout: 15000,
118
+ env: {
119
+ ...process.env,
120
+ HOME: home,
121
+ USERPROFILE: home,
122
+ GEMINI_API_KEY: "pleum-model-list-probe",
123
+ GOOGLE_GEMINI_BASE_URL: ROOT,
124
+ },
125
+ });
126
+ return new Set(String(output).split(/\r?\n/).map((line) => line.split(/\s/)[0]).filter((id) => /^gemini-/.test(id)));
127
+ } finally {
128
+ rmSync(home, { recursive: true, force: true });
129
+ }
130
+ }
131
+
132
+ // 설치된 agy 1.2.12를 모의 Gemini 엔드포인트에 연결해 실제 요청 ID가
133
+ // 선택 ID와 일치함을 확인한 모델만 열어 둔다. 새 모델은 같은 검증 후 추가한다.
134
+ const AGY_VERIFIED_MODELS = new Map([
135
+ ["gemini-3.8-flash", "gemini-3.8-flash"],
136
+ ["gemini-3.7-flash", "gemini-3.7-flash"],
137
+ ["gemini-3.6-flash", "gemini-3.6-flash"],
138
+ ["gemini-3.1-pro-preview", "gemini-3.1-pro"],
139
+ ]);
140
+
141
+ export function agyCliModel(model, ids) {
142
+ const cliBase = AGY_VERIFIED_MODELS.get(model);
143
+ if (!cliBase) return null;
144
+ return [cliBase, `${cliBase}-medium`, `${cliBase}-high`, `${cliBase}-low`, `${cliBase}-max`].find((id) => ids.has(id)) || null;
145
+ }
146
+
147
+ export function supportsAgyModel(model, ids) {
148
+ return Boolean(agyCliModel(model, ids));
149
+ }
150
+
151
+ function opencodeStateDir({ run = execFileSync } = {}) {
152
+ try {
153
+ const paths = run("opencode", ["debug", "paths"], { encoding: "utf8", timeout: 5000 });
154
+ const state = /^state\s+(.+)$/m.exec(String(paths))?.[1]?.trim();
155
+ if (state) return state;
156
+ } catch {}
157
+ return join(process.env.XDG_STATE_HOME || join(homedir(), ".local", "state"), "opencode");
158
+ }
159
+
160
+ export function seedOpenCodeFavorites(models, { stateDir = opencodeStateDir() } = {}) {
161
+ const path = join(stateDir, "model.json");
162
+ const state = existsSync(path) ? JSON.parse(readFileSync(path, "utf8")) : {};
163
+ if (!state || typeof state !== "object" || Array.isArray(state)) throw new Error("Invalid OpenCode model state");
164
+ const current = Array.isArray(state.favorite) ? state.favorite : [];
165
+ const active = new Set(codingModels(models).map((m) => m.id));
166
+ const pins = CORE_MODELS.filter((id) => active.has(id)).map((modelID) => ({ providerID: "openai", modelID }));
167
+ const pinKeys = new Set(pins.map((m) => `${m.providerID}/${m.modelID}`));
168
+ const favorite = [...pins, ...current.filter((m) => !pinKeys.has(`${m.providerID}/${m.modelID}`))];
169
+ if (JSON.stringify(favorite) === JSON.stringify(current)) return;
170
+ mkdirSync(stateDir, { recursive: true, mode: 0o700 });
171
+ const temp = join(stateDir, `model.json.pleum-${process.pid}`);
172
+ try {
173
+ writeFileSync(temp, JSON.stringify({ ...state, favorite }), { mode: 0o600 });
174
+ renameSync(temp, path);
175
+ } finally {
176
+ rmSync(temp, { force: true });
177
+ }
178
+ }
179
+
180
+ // 공통 실행 파이프라인의 설정 어댑터. 신규 에이전트는 env/args만 쓰거나
181
+ // 별도 홈이 필요할 때 타입 핸들러 하나를 등록하면 된다.
182
+ const SETUP = {
183
+ env: () => null,
184
+ "codex-home": (env, model) => { env.CODEX_HOME = writeIsolatedHome("codex-home", "config.toml", codexToml(model)); return null; },
185
+ "pi-home": (env, model) => { env.PI_CODING_AGENT_DIR = writeIsolatedHome("pi-home", "models.json", piModelsJson(model)); return null; },
186
+ "crush-home": (env, model) => { env.CRUSH_GLOBAL_CONFIG = writeIsolatedHome("crush-home", "crush.json", crushJson(model)); return null; },
187
+ "agy-settings": (_env, model) => setupAgySettings(model),
188
+ };
189
+
190
+ async function agentKey() {
191
+ if (!isLoggedIn()) {
192
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
193
+ throw new Error(t("Login required. Run this first:\n pleum login"));
194
+ }
195
+ await login();
196
+ }
197
+ // 로그인 JWT는 에이전트가 살아 있는 동안 갱신할 수 없다. 한 번 발급한 plm_ 키를
198
+ // launch와 wire가 공유하면 장시간 실행도 유지되고 Go 데이터플레인을 직접 사용한다.
199
+ return (await ensureWireKey()).key;
200
+ }
201
+
96
202
  // exit:false면 process.exit 대신 자식 종료 코드를 반환 — 런처 메뉴의 실행 후 복귀용.
97
- export async function launch(tool, model, passthrough, { exit = true } = {}) {
203
+ export async function launch(tool, model, passthrough, {
204
+ exit = true,
205
+ getKey = agentKey,
206
+ pathCheck = onPath,
207
+ spawnChild = spawn,
208
+ getModels = fetchModels,
209
+ getAgyModels = listAgyModelIds,
210
+ seedFavorites = seedOpenCodeFavorites,
211
+ } = {}) {
98
212
  recoverAgySettings();
99
-
100
- const key = await requireAuth();
101
213
  const resolved = resolveLaunchTool(tool);
102
214
  const r = RECIPES[resolved];
103
215
 
104
216
  if (!r) {
105
217
  if (MANUAL[resolved]) {
106
- printManual(resolved, key);
218
+ printManual(resolved, await getKey());
107
219
  return;
108
220
  }
109
221
  const aliases = Object.entries(LAUNCH_ALIASES).map(([from, to]) => `${from} → ${to}`).join(", ");
@@ -116,31 +228,51 @@ export async function launch(tool, model, passthrough, { exit = true } = {}) {
116
228
  process.exit(1);
117
229
  }
118
230
 
119
- const env = { ...process.env, ...r.env(key, model) };
120
- if (resolved === "claude") {
121
- delete env.ANTHROPIC_API_KEY;
231
+ if (!pathCheck(r.bin)) {
232
+ console.error(`✗ ${t("'{bin}' not found. Install:\n {install}", { bin: r.bin, install: r.install })}`);
233
+ if (exit) process.exit(127);
234
+ return 127;
122
235
  }
123
236
 
124
- // Codex는 격리 CODEX_HOME에 config.toml을 써서 사용자 ~/.codex를 보존한다.
125
- if (r.type === "codex-home") {
126
- env.CODEX_HOME = writeIsolatedHome("codex-home", "config.toml", codexToml(model));
127
- }
128
- if (r.type === "pi-home") {
129
- env.PI_CODING_AGENT_DIR = writeIsolatedHome("pi-home", "models.json", piModelsJson(model));
130
- }
131
- if (r.type === "crush-home") {
132
- env.CRUSH_GLOBAL_CONFIG = writeIsolatedHome("crush-home", "crush.json", crushJson(model));
237
+ model = resolveLaunchModel(resolved, model);
238
+ let catalog;
239
+ if (model?.mode === "custom" || resolved === "opencode") {
240
+ catalog = codingModels(await getModels());
241
+ const chosen = model?.mode === "custom" ? model.model : model;
242
+ const [id, provider] = String(chosen || "").split("@");
243
+ const entry = catalog.find((m) => m.id === id);
244
+ if (!entry || (provider && !entry.providers?.some((p) => p.provider === provider))) {
245
+ throw new Error(t("Model is not an active coding model: {model}", { model: sanitizeTerminalText(chosen) }));
246
+ }
247
+ if (resolved === "agy") {
248
+ const cliModel = agyCliModel(chosen, getAgyModels());
249
+ if (!cliModel) {
250
+ throw new Error(t("Antigravity does not support this model through its Gemini API mode: {model}", { model: sanitizeTerminalText(chosen) }));
251
+ }
252
+ model = { ...model, cliModel };
253
+ }
133
254
  }
255
+ const key = await getKey();
134
256
 
135
- let restoreAgy = null;
136
- if (r.type === "agy-settings") {
137
- restoreAgy = setupAgySettings(model);
257
+ const env = { ...process.env };
258
+ for (const name of r.unsetEnv || []) delete env[name];
259
+ Object.assign(env, r.env(key, model, catalog));
260
+ const setup = SETUP[r.type || "env"];
261
+ if (!setup) throw new Error(`Unknown agent setup type: ${r.type}`);
262
+ let restore = setup(env, model);
263
+
264
+ if (resolved === "opencode") {
265
+ try {
266
+ seedFavorites(catalog);
267
+ } catch (e) {
268
+ console.log(`ℹ ${t("Could not add Pleum models to OpenCode favorites: {error}", { error: sanitizeTerminalText(e.message) })}`);
269
+ }
138
270
  }
139
271
 
140
272
  const cleanup = () => {
141
- if (restoreAgy) {
142
- restoreAgy();
143
- restoreAgy = null;
273
+ if (restore) {
274
+ restore();
275
+ restore = null;
144
276
  }
145
277
  };
146
278
 
@@ -195,7 +327,7 @@ export async function launch(tool, model, passthrough, { exit = true } = {}) {
195
327
  }
196
328
 
197
329
  return await new Promise((resolve) => {
198
- const child = spawn(command.command, command.args, {
330
+ const child = spawnChild(command.command, command.args, {
199
331
  env,
200
332
  stdio: "inherit",
201
333
  shell: false,
@@ -380,4 +512,3 @@ function printManual(tool, key) {
380
512
  console.log(m.snippet());
381
513
  console.log(`\n${t("2) Export the key and run:")}\n export PLEUM_API_KEY=${key}\n`);
382
514
  }
383
-
@@ -71,8 +71,6 @@ export const ES = {
71
71
  "Necesita GitHub Copilot CLI 2026-04 o posterior para el enrutamiento de proveedores BYOK.",
72
72
  "Gemini CLI speaks Google's native generateContent format — set the model after launch with `/model google/<id>`.":
73
73
  "Gemini CLI usa el formato nativo generateContent de Google — establece el modelo tras el inicio con `/model google/<id>`.",
74
- "Writes modelProvider=gemini into ~/.gemini/antigravity-cli/settings.json. Routes any coding model via PleumRouter.":
75
- "Escribe modelProvider=gemini en ~/.gemini/antigravity-cli/settings.json. Enruta cualquier modelo de codificación a través de PleumRouter.",
76
74
  "↑ {n} more above": "↑ {n} más arriba",
77
75
  "↓ {n} more below": "↓ {n} más abajo",
78
76
  "Auto (best route)": "Auto (mejor ruta)",
@@ -331,5 +329,19 @@ export const ES = {
331
329
  "Medium (Standard)": "Medio (Estándar)",
332
330
  "Balanced reasoning effort": "Esfuerzo de razonamiento equilibrado",
333
331
  "Low reasoning effort for rapid iteration": "Bajo esfuerzo de razonamiento para iteraciones rápidas",
332
+ // Agent launch modes
333
+ "Antigravity custom supports only verified Gemini models in API-key mode.": "Antigravity custom solo admite modelos Gemini verificados en modo de clave API.",
334
+ "Anthropic official models": "Continuar con modelos oficiales de Anthropic",
335
+ "OpenAI official models": "Continuar con modelos oficiales de OpenAI",
336
+ "Antigravity default models": "Continuar con modelos predeterminados de Antigravity",
337
+ "Choose models inside the agent": "Elegir modelo dentro del agente",
338
+ "Choose my model (beta)": "Elegir mi modelo (beta)",
339
+ "Select a PleumRouter coding model": "Elegir un modelo de código de PleumRouter",
340
+ "No compatible coding models available": "No hay modelos de código compatibles",
341
+ "Antigravity model discovery failed: {error}": "No se pudo consultar los modelos de Antigravity: {error}",
342
+ "Model is not an active coding model: {model}": "No es un modelo de código activo: {model}",
343
+ "Antigravity does not support this model through its Gemini API mode: {model}": "Antigravity no admite este modelo en modo Gemini API: {model}",
344
+ "Could not add Pleum models to OpenCode favorites: {error}": "No se pudieron añadir modelos Pleum a favoritos de OpenCode: {error}",
345
+ "↑/↓ move • enter select • esc quit": "↑/↓ mover • enter seleccionar • esc salir",
346
+ "Writes modelProvider=gemini into ~/.gemini/antigravity-cli/settings.json. Supported Gemini models route via PleumRouter.": "Escribe modelProvider=gemini en ~/.gemini/antigravity-cli/settings.json. Los modelos Gemini compatibles usan PleumRouter.",
334
347
  };
335
-
@@ -72,8 +72,6 @@ export const JA = {
72
72
  "BYOK プロバイダールーティングに対応した 2026-04 以降の GitHub Copilot CLI が必要です。",
73
73
  "Gemini CLI speaks Google's native generateContent format — set the model after launch with `/model google/<id>`.":
74
74
  "Gemini CLI は Google のネイティブ generateContent 形式を使用します — 起動後に `/model google/<id>` でモデルを設定してください。",
75
- "Writes modelProvider=gemini into ~/.gemini/antigravity-cli/settings.json. Routes any coding model via PleumRouter.":
76
- "~/.gemini/antigravity-cli/settings.json に modelProvider=gemini を書き込みます。あらゆるコーディングモデルを PleumRouter でルーティングします。",
77
75
  "↑ {n} more above": "↑ 上にあと {n} 件",
78
76
  "↓ {n} more below": "↓ 下にあと {n} 件",
79
77
  "Auto (best route)": "Auto (最適な自動ルーティング)",
@@ -331,5 +329,19 @@ export const JA = {
331
329
  "Medium (Standard)": "中 (標準)",
332
330
  "Balanced reasoning effort": "バランスの取れた標準的な推論強度",
333
331
  "Low reasoning effort for rapid iteration": "迅速なイテレーション向けの低い推論強度",
332
+ // Agent launch modes
333
+ "Antigravity custom supports only verified Gemini models in API-key mode.": "Antigravity custom は API キーモードで検証済みの Gemini モデルのみ対応します。",
334
+ "Anthropic official models": "Anthropic 公式モデルで続行",
335
+ "OpenAI official models": "OpenAI 公式モデルで続行",
336
+ "Antigravity default models": "Antigravity 標準モデルで続行",
337
+ "Choose models inside the agent": "エージェント内でモデルを選択",
338
+ "Choose my model (beta)": "モデルを自分で選ぶ (beta)",
339
+ "Select a PleumRouter coding model": "PleumRouter のコーディングモデルを選択",
340
+ "No compatible coding models available": "対応するコーディングモデルがありません",
341
+ "Antigravity model discovery failed: {error}": "Antigravity のモデル一覧を取得できません: {error}",
342
+ "Model is not an active coding model: {model}": "有効なコーディングモデルではありません: {model}",
343
+ "Antigravity does not support this model through its Gemini API mode: {model}": "Antigravity の Gemini API モードでは使用できません: {model}",
344
+ "Could not add Pleum models to OpenCode favorites: {error}": "OpenCode のお気に入りに Pleum モデルを追加できません: {error}",
345
+ "↑/↓ move • enter select • esc quit": "↑/↓ 移動 • enter 選択 • esc 終了",
346
+ "Writes modelProvider=gemini into ~/.gemini/antigravity-cli/settings.json. Supported Gemini models route via PleumRouter.": "~/.gemini/antigravity-cli/settings.json に modelProvider=gemini を書き込みます。対応する Gemini モデルを PleumRouter 経由で使用します。",
334
347
  };
335
-
@@ -52,8 +52,6 @@ export const KO = {
52
52
  "BYOK provider 라우팅을 지원하는 2026-04 이후 버전의 GitHub Copilot CLI가 필요합니다.",
53
53
  "Gemini CLI speaks Google's native generateContent format — set the model after launch with `/model google/<id>`.":
54
54
  "Gemini CLI는 Google의 네이티브 generateContent 포맷을 사용합니다 — 실행 후 `/model google/<id>`로 모델을 설정하세요.",
55
- "Writes modelProvider=gemini into ~/.gemini/antigravity-cli/settings.json. Routes any coding model via PleumRouter.":
56
- "~/.gemini/antigravity-cli/settings.json 에 modelProvider=gemini 를 씁니다. 모든 코딩 모델을 PleumRouter로 라우팅합니다.",
57
55
  "↑ {n} more above": "↑ 위에 {n}개 더",
58
56
  "↓ {n} more below": "↓ 아래에 {n}개 더",
59
57
  "Auto (best route)": "Auto (최적 자동 라우팅)",
@@ -394,5 +392,19 @@ export const KO = {
394
392
  "Medium (Standard)": "보통 (표준)",
395
393
  "Balanced reasoning effort": "균형 잡힌 표준 추론 강도",
396
394
  "Low reasoning effort for rapid iteration": "빠른 반복 작업을 위한 낮은 추론 강도",
395
+ // Agent launch modes
396
+ "Antigravity custom supports only verified Gemini models in API-key mode.": "Antigravity custom은 API 키 모드에서 검증된 Gemini 모델만 지원합니다.",
397
+ "Anthropic official models": "Anthropic 공식 모델로 진행",
398
+ "OpenAI official models": "OpenAI 공식 모델로 진행",
399
+ "Antigravity default models": "Antigravity 기본 모델로 진행",
400
+ "Choose models inside the agent": "에이전트 안에서 모델 선택",
401
+ "Choose my model (beta)": "모델 내가 custom하기(beta)",
402
+ "Select a PleumRouter coding model": "PleumRouter 코딩 모델 선택",
403
+ "No compatible coding models available": "호환되는 코딩 모델이 없습니다",
404
+ "Antigravity model discovery failed: {error}": "Antigravity 모델 목록 조회 실패: {error}",
405
+ "Model is not an active coding model: {model}": "활성 코딩 모델이 아닙니다: {model}",
406
+ "Antigravity does not support this model through its Gemini API mode: {model}": "Antigravity Gemini API 모드에서 지원하지 않는 모델입니다: {model}",
407
+ "Could not add Pleum models to OpenCode favorites: {error}": "OpenCode 즐겨찾기에 Pleum 모델을 추가하지 못했습니다: {error}",
408
+ "↑/↓ move • enter select • esc quit": "↑/↓ 이동 • enter 선택 • esc 종료",
409
+ "Writes modelProvider=gemini into ~/.gemini/antigravity-cli/settings.json. Supported Gemini models route via PleumRouter.": "~/.gemini/antigravity-cli/settings.json에 modelProvider=gemini를 씁니다. 지원되는 Gemini 모델을 PleumRouter로 라우팅합니다.",
397
410
  };
398
-
@@ -71,8 +71,6 @@ export const ZH = {
71
71
  "需要 2026-04 或更新版本的 GitHub Copilot CLI 才支持 BYOK provider 路由。",
72
72
  "Gemini CLI speaks Google's native generateContent format — set the model after launch with `/model google/<id>`.":
73
73
  "Gemini CLI 使用 Google 原生 generateContent 格式 — 启动后用 `/model google/<id>` 设置模型。",
74
- "Writes modelProvider=gemini into ~/.gemini/antigravity-cli/settings.json. Routes any coding model via PleumRouter.":
75
- "将 modelProvider=gemini 写入 ~/.gemini/antigravity-cli/settings.json。通过 PleumRouter 路由所有编码模型。",
76
74
  "↑ {n} more above": "↑ 上方还有 {n} 项",
77
75
  "↓ {n} more below": "↓ 下方还有 {n} 项",
78
76
  "Auto (best route)": "Auto (最佳自动路由)",
@@ -331,5 +329,19 @@ export const ZH = {
331
329
  "Medium (Standard)": "中 (标准)",
332
330
  "Balanced reasoning effort": "平衡的标准推理强度",
333
331
  "Low reasoning effort for rapid iteration": "快速迭代的低推理强度",
332
+ // Agent launch modes
333
+ "Antigravity custom supports only verified Gemini models in API-key mode.": "Antigravity 自选模型在 API 密钥模式下仅支持已验证的 Gemini 模型。",
334
+ "Anthropic official models": "使用 Anthropic 官方模型",
335
+ "OpenAI official models": "使用 OpenAI 官方模型",
336
+ "Antigravity default models": "使用 Antigravity 默认模型",
337
+ "Choose models inside the agent": "在代理中选择模型",
338
+ "Choose my model (beta)": "自选模型 (beta)",
339
+ "Select a PleumRouter coding model": "选择 PleumRouter 编程模型",
340
+ "No compatible coding models available": "没有兼容的编程模型",
341
+ "Antigravity model discovery failed: {error}": "获取 Antigravity 模型列表失败:{error}",
342
+ "Model is not an active coding model: {model}": "不是可用的编程模型:{model}",
343
+ "Antigravity does not support this model through its Gemini API mode: {model}": "Antigravity 的 Gemini API 模式不支持此模型:{model}",
344
+ "Could not add Pleum models to OpenCode favorites: {error}": "无法将 Pleum 模型加入 OpenCode 收藏:{error}",
345
+ "↑/↓ move • enter select • esc quit": "↑/↓ 移动 • enter 选择 • esc 退出",
346
+ "Writes modelProvider=gemini into ~/.gemini/antigravity-cli/settings.json. Supported Gemini models route via PleumRouter.": "将 modelProvider=gemini 写入 ~/.gemini/antigravity-cli/settings.json。支持的 Gemini 模型经由 PleumRouter 路由。",
334
347
  };
335
-