Skip to content

Commit aecc1d0

Browse files
committed
feat: dual endpoint header, Sigquit guard, Ctrl+C -> quit panel
Feat: TUI header - Two-row endpoint display (OpenAI + Anthropic URLs) - [o] copies OpenAI URL, [a] copies Anthropic base URL - Footer, help page, Proxy Config (page 6) synced with dual endpoints - All URLs follow user-configured port dynamically Feat: Ctrl+C guard - TUI mode: Ctrl+C opens quit confirmation panel instead of force exit - Status bar shows red hint: press q or Ctrl+C again to confirm - Quit panel: Ctrl+C also confirms (same as Y/Enter) Docs: naming convention - OpenCode: Command Code - Model /Op and /An suffixes - Zed: Model - CommandCode display_name format - API-REFERENCE, AGENTS.md updated with conventions
1 parent a38c51f commit aecc1d0

4 files changed

Lines changed: 87 additions & 27 deletions

File tree

AGENTS.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ npm v11 has a bug installing global git deps: the install appears to succeed (`a
178178
},
179179
"models": {
180180
"deepseek/deepseek-v4-pro": {
181-
"name": "DeepSeek V4 Pro",
181+
"name": "Command Code - DeepSeek V4 Pro /Op",
182182
"tool_call": true,
183183
"reasoning": true,
184184
"limit": { "context": 1048576, "input": 1048576, "output": 8192 }
@@ -199,7 +199,7 @@ npm v11 has a bug installing global git deps: the install appears to succeed (`a
199199
},
200200
"models": {
201201
"deepseek/deepseek-v4-pro": {
202-
"name": "DeepSeek V4 Pro",
202+
"name": "Command Code - DeepSeek V4 Pro /Op",
203203
"tool_call": true,
204204
"reasoning": true,
205205
"limit": { "context": 1048576, "input": 1048576, "output": 8192 }
@@ -271,7 +271,8 @@ Visualization uses `ProgressBar` from nocterm with color-coded fill:
271271
|-----|---------|--------|
272272
| `1-6` | Always | Switch info page |
273273
| `r` | Always | Refresh all API data |
274-
| `c` | Always | Copy endpoint URL to clipboard |
274+
| `o` | Always | Copy OpenAI endpoint URL to clipboard |
275+
| `a` | Always | Copy Anthropic endpoint URL to clipboard |
275276
| `p` | Always | Open port configuration panel |
276277
| `h` | Always | Open help panel |
277278
| `q` | Always | Open quit confirmation |

docs/API-REFERENCE.md

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ All endpoints at `http://127.0.0.1:17077`.
44

55
## OpenAI Compatible
66

7+
Base URL: `http://127.0.0.1:17077/v1`
8+
79
| Path | Method | Description |
810
|------|--------|-------------|
911
| `/v1/chat/completions` | POST | Chat completions (stream + non-stream) |
@@ -14,6 +16,8 @@ All endpoints at `http://127.0.0.1:17077`.
1416

1517
## Anthropic Compatible
1618

19+
Base URL: `http://127.0.0.1:17077`
20+
1721
| Path | Method | Description |
1822
|------|--------|-------------|
1923
| `/v1/messages` | POST | Messages API (stream + non-stream) |
@@ -36,7 +40,7 @@ Any value works. The bridge uses your saved Command Code auth from `~/.commandco
3640
},
3741
"models": {
3842
"deepseek/deepseek-v4-pro": {
39-
"name": "DeepSeek V4 Pro",
43+
"name": "Command Code - DeepSeek V4 Pro /Op",
4044
"tool_call": true,
4145
"reasoning": true,
4246
"limit": { "context": 1048576, "input": 1048576, "output": 8192 }
@@ -57,7 +61,7 @@ Any value works. The bridge uses your saved Command Code auth from `~/.commandco
5761
},
5862
"models": {
5963
"deepseek/deepseek-v4-pro": {
60-
"name": "DeepSeek V4 Pro",
64+
"name": "Command Code - DeepSeek V4 Pro /An",
6165
"tool_call": true,
6266
"reasoning": true,
6367
"limit": { "context": 1048576, "input": 1048576, "output": 8192 }
@@ -69,16 +73,17 @@ Any value works. The bridge uses your saved Command Code auth from `~/.commandco
6973
### Zed (Anthropic Compatible)
7074

7175
Zed reads providers from `settings.json` under `language_models.anthropic_compatible`.
72-
The API key must be entered through **Agent Settings** (`agent: open settings` -> LLM Providers),
73-
not in `settings.json`.
76+
The API key must be entered through **Agent Settings** (`agent: open settings` -> LLM Providers).
77+
78+
`api_url` must be the base URL **without** `/v1` — Zed auto-appends `/v1/messages`.
7479

7580
```jsonc
7681
"Anthropic Command Code (Go Plan) - Khip01 Local": {
7782
"api_url": "http://127.0.0.1:17077",
7883
"available_models": [
7984
{
8085
"name": "deepseek/deepseek-v4-pro",
81-
"display_name": "DeepSeek V4 Pro (CC)",
86+
"display_name": "DeepSeek V4 Pro - CommandCode",
8287
"max_tokens": 1000000,
8388
"max_output_tokens": 64000,
8489
"extra_beta_headers": [],

docs/TUI.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
|-----|---------|--------|
1818
| `1-6` | Always | Switch info page |
1919
| `r` | Always | Refresh all API data |
20-
| `c` | Always | Copy endpoint URL to clipboard |
20+
| `o` | Always | Copy OpenAI endpoint URL to clipboard |
21+
| `a` | Always | Copy Anthropic URL to clipboard |
2122
| `p` | Always | Configure proxy port (with availability scan) |
2223
| `h` | Always | Open help |
2324
| `q` | Always | Quit (with confirmation) |

lib/src/tui/app.dart

Lines changed: 71 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,8 @@ class AppState extends State<CmdBridgeApp> {
203203

204204
if (_panel == _Panel.quit) {
205205
if (e.logicalKey == LogicalKey.keyY ||
206-
e.logicalKey == LogicalKey.enter) {
206+
e.logicalKey == LogicalKey.enter ||
207+
(e.logicalKey == LogicalKey.keyC && e.isControlPressed)) {
207208
_doQuit();
208209
return true;
209210
}
@@ -247,6 +248,13 @@ class AppState extends State<CmdBridgeApp> {
247248
}
248249

249250
if (_panel == _Panel.main) {
251+
if (e.logicalKey == LogicalKey.keyC && e.isControlPressed) {
252+
_panel = _Panel.quit;
253+
_setStatus('Press q or Ctrl+C to quit', duration: 10);
254+
setState(() {});
255+
return true;
256+
}
257+
250258
if (e.logicalKey == LogicalKey.keyL && e.isControlPressed) {
251259
_showLog = !_showLog;
252260
if (_showLog) _logFullscreen = false;
@@ -320,10 +328,14 @@ class AppState extends State<CmdBridgeApp> {
320328
_refreshData(foreground: true);
321329
return true;
322330

323-
case LogicalKey.keyC:
331+
case LogicalKey.keyO:
324332
_copyEndpointUrl();
325333
return true;
326334

335+
case LogicalKey.keyA:
336+
_copyAnthropicUrl();
337+
return true;
338+
327339
case LogicalKey.keyP:
328340
_showPortConfig();
329341
return true;
@@ -463,12 +475,27 @@ class AppState extends State<CmdBridgeApp> {
463475
}
464476

465477
void _copyEndpointUrl() {
466-
final url = 'http://127.0.0.1:${_config.config.serverPort}/v1';
467-
_setStatus('Copying endpoint URL...');
478+
final port = _config.config.serverPort;
479+
final url = 'http://127.0.0.1:$port/v1';
480+
_setStatus('Copying OpenAI endpoint...');
481+
_copyNative(url).then((ok) {
482+
if (ok) {
483+
_setStatus('Copied OpenAI: $url', duration: 4);
484+
LogStore.info('Copied OpenAI endpoint URL');
485+
} else {
486+
_setStatus('Clipboard copy failed', duration: 4);
487+
}
488+
});
489+
}
490+
491+
void _copyAnthropicUrl() {
492+
final port = _config.config.serverPort;
493+
final url = 'http://127.0.0.1:$port';
494+
_setStatus('Copying Anthropic endpoint...');
468495
_copyNative(url).then((ok) {
469496
if (ok) {
470-
_setStatus('Copied endpoint: $url', duration: 4);
471-
LogStore.info('Copied endpoint URL');
497+
_setStatus('Copied Anthropic: $url', duration: 4);
498+
LogStore.info('Copied Anthropic endpoint URL');
472499
} else {
473500
_setStatus('Clipboard copy failed', duration: 4);
474501
}
@@ -631,6 +658,7 @@ class AppState extends State<CmdBridgeApp> {
631658
final email = whoami?.email ?? '';
632659
final planName = sub != null ? _planDisplayName(sub.planId) : '';
633660
final isRunning = _proxy.isRunning;
661+
final port = _config.config.serverPort;
634662

635663
return Container(
636664
padding: const EdgeInsets.all(1),
@@ -644,7 +672,7 @@ class AppState extends State<CmdBridgeApp> {
644672
children: [
645673
Text('CommandCode Bridge',
646674
style: const TextStyle(fontWeight: FontWeight.bold)),
647-
Text(' OpenAI Compatible',
675+
Text(' OpenAI + Anthropic',
648676
style: TextStyle(color: Colors.green)),
649677
Text(' | ', style: TextStyle(color: Colors.grey)),
650678
Text(displayName, style: const TextStyle(color: Colors.cyan)),
@@ -665,10 +693,20 @@ class AppState extends State<CmdBridgeApp> {
665693
),
666694
Row(
667695
children: [
668-
Text('\u25b8 http://127.0.0.1:${_config.config.serverPort}/v1',
696+
Text('\u25b8 OpenAI: ',
697+
style: TextStyle(color: Colors.grey)),
698+
Text('http://127.0.0.1:$port/v1',
669699
style: const TextStyle(color: Colors.green)),
670-
Text(' [c]', style: TextStyle(color: Colors.green, fontWeight: FontWeight.bold)),
671-
Text('opy endpoint url', style: TextStyle(color: Colors.grey)),
700+
Text(' [o] copy', style: TextStyle(color: Colors.green, fontWeight: FontWeight.bold)),
701+
],
702+
),
703+
Row(
704+
children: [
705+
Text('\u25b8 Anthropic: ',
706+
style: TextStyle(color: Colors.grey)),
707+
Text('http://127.0.0.1:$port',
708+
style: const TextStyle(color: Colors.cyan)),
709+
Text(' [a] copy', style: TextStyle(color: Colors.cyan, fontWeight: FontWeight.bold)),
672710
const Spacer(),
673711
Text('Last used: ${_proxy.currentModel}',
674712
style: TextStyle(color: Colors.grey)),
@@ -1078,11 +1116,18 @@ class AppState extends State<CmdBridgeApp> {
10781116
add('');
10791117
add('Endpoints', Colors.cyan);
10801118
add('');
1081-
add('POST /v1/chat/completions OpenAI-compatible chat');
1082-
add('GET /v1/models List available models');
1083-
add('GET /v1/health Health check');
1084-
add('GET /v1/token Get access token');
1085-
add('GET /v1/info Bridge info');
1119+
add('OpenAI:');
1120+
add(' http://127.0.0.1:${_config.config.serverPort}/v1');
1121+
add(' POST /v1/chat/completions Chat completions');
1122+
add(' GET /v1/models List models');
1123+
add(' GET /v1/health Health check');
1124+
add(' GET /v1/token Access token');
1125+
add(' GET /v1/info Bridge info');
1126+
add('');
1127+
add('Anthropic:');
1128+
add(' http://127.0.0.1:${_config.config.serverPort}');
1129+
add(' POST /v1/messages Messages API');
1130+
add(' POST /messages Messages API (alt)');
10861131
add('');
10871132
add('API Key: any value works (bridge uses your saved auth)');
10881133
break;
@@ -1265,12 +1310,18 @@ class AppState extends State<CmdBridgeApp> {
12651310
add('');
12661311
add('Other:', Colors.cyan);
12671312
add('');
1268-
add(' [c] Copy endpoint URL (http://.../v1) to clipboard');
1313+
add(' [o] Copy OpenAI endpoint URL (http://.../v1) to clipboard');
1314+
add(' [a] Copy Anthropic endpoint URL (http://... base) to clipboard');
12691315
add(' [p] Configure proxy port');
12701316
add(' [l] Login panel (if not authenticated)');
12711317
add(' [h] Show this help');
12721318
add(' [q] Quit');
12731319
add('');
1320+
add('Endpoints:', Colors.cyan);
1321+
add('');
1322+
add(' OpenAI: http://127.0.0.1:${_config.config.serverPort}/v1');
1323+
add(' Anthropic: http://127.0.0.1:${_config.config.serverPort}');
1324+
add('');
12741325
add('Links:', Colors.cyan);
12751326
add('');
12761327
add(' Docs: https://commandcode.ai/docs');
@@ -1514,8 +1565,10 @@ class AppState extends State<CmdBridgeApp> {
15141565
children: [
15151566
Text('Actions:', style: TextStyle(color: Colors.cyan, fontWeight: FontWeight.bold)),
15161567
if (_account.isLoaded) ...[
1517-
Text(' [c]', style: TextStyle(color: Colors.green, fontWeight: FontWeight.bold)),
1518-
Text('opy endpoint url ', style: TextStyle(color: Colors.grey)),
1568+
Text(' [o]', style: TextStyle(color: Colors.green, fontWeight: FontWeight.bold)),
1569+
Text('penai url ', style: TextStyle(color: Colors.grey)),
1570+
Text('[a]', style: TextStyle(color: Colors.cyan, fontWeight: FontWeight.bold)),
1571+
Text('nthropic url ', style: TextStyle(color: Colors.grey)),
15191572
Text('[r]', style: TextStyle(color: Colors.cyan, fontWeight: FontWeight.bold)),
15201573
Text('efresh ', style: TextStyle(color: Colors.grey)),
15211574
Text('[p]', style: TextStyle(color: Colors.yellow, fontWeight: FontWeight.bold)),

0 commit comments

Comments
 (0)