Skip to content

Commit f059763

Browse files
committed
fix: handle commandcode install states
1 parent babb68d commit f059763

4 files changed

Lines changed: 107 additions & 5 deletions

File tree

install.sh

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,90 @@ generate_key() {
182182
fi
183183
}
184184

185+
commandcode_bin() {
186+
if command -v cmd >/dev/null 2>&1; then
187+
command -v cmd
188+
return 0
189+
fi
190+
if command -v command-code >/dev/null 2>&1; then
191+
command -v command-code
192+
return 0
193+
fi
194+
return 1
195+
}
196+
197+
confirm_default_yes() {
198+
local prompt="$1"
199+
[ "$ASSUME_YES" -eq 0 ] || return 0
200+
[ -t 0 ] || return 0
201+
printf '%s [Y/n]: ' "$prompt"
202+
read -r answer || true
203+
case "${answer:-}" in
204+
""|y|Y|yes|YES) return 0 ;;
205+
*) return 1 ;;
206+
esac
207+
}
208+
209+
ensure_commandcode_cli() {
210+
if commandcode_bin >/dev/null 2>&1; then
211+
log "Command Code CLI found: $(commandcode_bin)"
212+
return 0
213+
fi
214+
215+
if confirm_default_yes "Command Code CLI가 없습니다. npm i -g command-code 후 계속 진행할까요?"; then
216+
log "Installing Command Code CLI with npm."
217+
npm install -g command-code
218+
else
219+
fail "Command Code CLI가 필요합니다. 'npm i -g command-code' 후 'cmd login'을 완료하고 다시 설치를 실행하세요."
220+
fi
221+
222+
commandcode_bin >/dev/null 2>&1 || fail "Command Code CLI install finished but 'cmd' was not found on PATH. Add npm global bin to PATH and retry."
223+
}
224+
225+
extract_commandcode_api_key() {
226+
local auth_file="$HOME/.commandcode/auth.json"
227+
[ -f "$auth_file" ] || return 1
228+
node -e '
229+
const fs = require("fs");
230+
const file = process.argv[1];
231+
const data = JSON.parse(fs.readFileSync(file, "utf8"));
232+
function stringValue(value) {
233+
if (typeof value !== "string") return undefined;
234+
const trimmed = value.trim();
235+
return trimmed.length > 0 ? trimmed : undefined;
236+
}
237+
function walk(value) {
238+
const scalar = stringValue(value);
239+
if (scalar) return scalar;
240+
if (!value || typeof value !== "object") return undefined;
241+
for (const key of ["apiKey", "api_key", "access", "accessToken", "token", "key", "commandcode", "commandCode", "command_code", "auth", "credentials", "oauth", "account"]) {
242+
const found = walk(value[key]);
243+
if (found) return found;
244+
}
245+
return undefined;
246+
}
247+
const key = walk(data);
248+
if (!key) process.exit(1);
249+
process.stdout.write(key);
250+
' "$auth_file"
251+
}
252+
253+
DETECTED_COMMANDCODE_API_KEY=""
254+
ensure_commandcode_auth() {
255+
ensure_commandcode_cli
256+
DETECTED_COMMANDCODE_API_KEY="$(extract_commandcode_api_key 2>/dev/null || true)"
257+
if [ -n "$DETECTED_COMMANDCODE_API_KEY" ]; then
258+
if [ -z "$COMMANDCODE_API_KEY" ]; then
259+
COMMANDCODE_API_KEY="$DETECTED_COMMANDCODE_API_KEY"
260+
log "기존 Command Code 인증 키를 브릿지 key1로 가져왔습니다."
261+
else
262+
log "Command Code 인증은 확인됐고, 입력한 COMMANDCODE_API_KEY를 우선 사용합니다."
263+
fi
264+
else
265+
log "Command Code CLI는 설치되어 있지만 인증 키가 없습니다. 설치 후 'cmd login'을 실행하고 브릿지를 재시작하세요."
266+
fi
267+
}
268+
185269
require_command() {
186270
command -v "$1" >/dev/null 2>&1 || fail "required command not found: $1"
187271
}
@@ -216,6 +300,7 @@ validate_env_value COMMANDCODE_API_KEY "$COMMANDCODE_API_KEY"
216300
require_command node
217301
require_command npm
218302
require_command systemctl
303+
ensure_commandcode_auth
219304

220305
NODE_MAJOR="$(node -p "Number(process.versions.node.split('.')[0])")"
221306
if [ "$NODE_MAJOR" -lt 20 ]; then

src/model-catalog.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export const COMMANDCODE_MODEL_DEFINITIONS: CommandCodeModelDefinition[] = [
1818
family: "deepseek",
1919
aliases: ["deepseek-v4-pro", "commandcode/deepseek-v4-pro"],
2020
enabledByDefault: true,
21-
notes: "Stable baseline model.",
21+
notes: "CommandCode OSS credits · exact model rate from CommandCode billing",
2222
},
2323
{
2424
id: "deepseek/deepseek-v4-flash",
@@ -27,7 +27,7 @@ export const COMMANDCODE_MODEL_DEFINITIONS: CommandCodeModelDefinition[] = [
2727
family: "deepseek",
2828
aliases: ["deepseek-v4-flash", "commandcode/deepseek-v4-flash"],
2929
enabledByDefault: true,
30-
notes: "Cheap load-test model; 8-way parallel smoke was healthy, so 4 per key is recommended.",
30+
notes: "CommandCode OSS credits · exact model rate from CommandCode billing",
3131
},
3232
{
3333
id: "MiniMaxAI/MiniMax-M2.7",
@@ -36,6 +36,7 @@ export const COMMANDCODE_MODEL_DEFINITIONS: CommandCodeModelDefinition[] = [
3636
family: "minimax",
3737
aliases: ["minimax-m2.7", "MiniMax-M2.7"],
3838
enabledByDefault: true,
39+
notes: "CommandCode OSS credits · exact model rate from CommandCode billing",
3940
},
4041
{
4142
id: "Qwen/Qwen3.6-Plus",
@@ -44,6 +45,7 @@ export const COMMANDCODE_MODEL_DEFINITIONS: CommandCodeModelDefinition[] = [
4445
family: "qwen",
4546
aliases: ["qwen3.6-plus", "Qwen3.6-Plus"],
4647
enabledByDefault: true,
48+
notes: "CommandCode OSS credits · exact model rate from CommandCode billing",
4749
},
4850
{
4951
id: "zai-org/GLM-5.1",
@@ -52,6 +54,7 @@ export const COMMANDCODE_MODEL_DEFINITIONS: CommandCodeModelDefinition[] = [
5254
family: "glm",
5355
aliases: ["glm-5.1", "GLM-5.1"],
5456
enabledByDefault: true,
57+
notes: "CommandCode OSS credits · exact model rate from CommandCode billing",
5558
},
5659
{
5760
id: "moonshotai/Kimi-K2.6",
@@ -60,6 +63,7 @@ export const COMMANDCODE_MODEL_DEFINITIONS: CommandCodeModelDefinition[] = [
6063
family: "kimi",
6164
aliases: ["kimi-k2.6", "Kimi-K2.6"],
6265
enabledByDefault: true,
66+
notes: "CommandCode OSS credits · exact model rate from CommandCode billing",
6367
},
6468
{
6569
id: "openai/gpt-5.5",
@@ -68,7 +72,7 @@ export const COMMANDCODE_MODEL_DEFINITIONS: CommandCodeModelDefinition[] = [
6872
family: "gpt",
6973
aliases: ["gpt-5.5", "GPT-5.5"],
7074
enabledByDefault: false,
71-
notes: "Prepared in the bridge catalog; disabled until explicitly enabled.",
75+
notes: "CommandCode: $5/M in · $30/M out",
7276
},
7377
{
7478
id: "anthropic/claude-opus-4.7",
@@ -77,7 +81,7 @@ export const COMMANDCODE_MODEL_DEFINITIONS: CommandCodeModelDefinition[] = [
7781
family: "claude",
7882
aliases: ["claude-opus-4.7", "opus-4.7"],
7983
enabledByDefault: false,
80-
notes: "Prepared in the bridge catalog; disabled until explicitly enabled.",
84+
notes: "CommandCode: $5/M in · $25/M out · cache hit $0.5/M",
8185
},
8286
{
8387
id: "anthropic/claude-sonnet-4.6",
@@ -86,7 +90,7 @@ export const COMMANDCODE_MODEL_DEFINITIONS: CommandCodeModelDefinition[] = [
8690
family: "claude",
8791
aliases: ["claude-sonnet-4.6", "sonnet-4.6"],
8892
enabledByDefault: false,
89-
notes: "Prepared in the bridge catalog; disabled until explicitly enabled.",
93+
notes: "CommandCode: $3/M in · $15/M out · cache hit $0.3/M",
9094
},
9195
];
9296

tests/config.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,16 @@ describe("configuration and model aliases", () => {
88
expect(config.defaultModel).toBe("deepseek/deepseek-v4-pro");
99
});
1010

11+
it("shows CommandCode pricing instead of descriptive model notes", () => {
12+
const config = loadBridgeConfig({ env: {} });
13+
expect(config.modelCatalog?.find((model) => model.id === "openai/gpt-5.5")?.notes).toBe(
14+
"CommandCode: $5/M in · $30/M out",
15+
);
16+
expect(
17+
config.modelCatalog?.find((model) => model.id === "deepseek/deepseek-v4-pro")?.notes,
18+
).toContain("CommandCode OSS credits");
19+
});
20+
1121
it("keeps balance alerts off by default while failing closed on empty length responses", () => {
1222
const config = loadBridgeConfig({ env: {} });
1323
expect(config.balanceAlerts.enabled).toBe(false);

tests/install-scripts.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ describe("installer scripts", () => {
3939
expect(script).toContain("sk-cmdbridge-");
4040
expect(script).toContain("randomBytes(3)");
4141
expect(script).toContain("read -rs key_input");
42+
expect(script).toContain("ensure_commandcode_cli");
43+
expect(script).toContain("extract_commandcode_api_key");
44+
expect(script).toContain('COMMANDCODE_API_KEY="$DETECTED_COMMANDCODE_API_KEY"');
4245
expect(script).toContain("refusing unexpected INSTALL_DIR");
4346
});
4447

0 commit comments

Comments
 (0)