Skip to content

Commit 4503f71

Browse files
committed
fix: stop continuous API polling, refresh on page open or [r] only
Fix: polling - Removed per-page interval auto-refresh that hit Command Code endpoints every 8-30s while staying on a page (e.g. Models/Cost) - Data now refreshes only on manual [r] or once in the background when a page is opened, throttled to once per 10s - Fixes spamming the Command Code API just by viewing a page Chore: release - Bump to 1.3.1 (package.json, pubspec.yaml, version.dart) - Sync CHANGELOG + docs
1 parent 05a2844 commit 4503f71

7 files changed

Lines changed: 48 additions & 40 deletions

File tree

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,17 @@
22

33
All notable changes to this project will be documented in this file.
44

5+
## v1.3.1 (2026-08-02)
6+
7+
### Fixes
8+
9+
- Removed continuous API polling: staying on a TUI page (e.g. Models or Cost)
10+
no longer re-fetches Command Code data every few seconds. Data is refreshed
11+
once in the background when a page is opened (throttled to once per 10s to
12+
avoid spamming the API during rapid page switching) and on manual `[r]`
13+
refresh. This avoids hammering the Command Code endpoints just by viewing a
14+
page.
15+
516
## v1.3.0 (2026-08-02)
617

718
### Features

docs/ARCHITECTURE.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,12 @@ sync with Command Code pricing.
8181
## Dynamic Model List
8282

8383
The bridge does not rely solely on its bundled registry. On every TUI refresh
84-
(`[r]` or auto-refresh) it calls the official Command Code endpoint
85-
`GET /provider/v1/models`, caches the result in memory, and merges it with the
86-
52 bundled `ModelsDb` models. This means newly released models (for example
87-
`inclusionai/ling-3.0-flash-free`, `poolside/laguna-s-2.1-free`) are served by
88-
`/v1/models` and shown in the TUI without needing a bridge release.
84+
(`[r]`, or once in the background when a page is opened) it calls the official
85+
Command Code endpoint `GET /provider/v1/models`, caches the result in memory,
86+
and merges it with the 52 bundled `ModelsDb` models. This means newly released
87+
models (for example `inclusionai/ling-3.0-flash-free`,
88+
`poolside/laguna-s-2.1-free`) are served by `/v1/models` and shown in the TUI
89+
without needing a bridge release.
8990

9091
- `api_client.fetchModels()` returns the live model list from the API
9192
- `ServerController.setLiveModelIds()` updates the in-memory cache used by `/v1/models`

docs/TUI.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,20 @@
1212
| `6` | Proxy Config | Bridge state | Port, API URL, endpoints, uptime |
1313
| `7` | Cost Sync | Local CLI agent configs | Detected agents, provider list, model pricing, sync status |
1414

15+
## Refresh Behavior
16+
17+
Data is fetched from Command Code only when you press `[r]` (manual foreground
18+
refresh) or once in the background when you open a page (throttled to once per
19+
10 seconds). The bridge does not poll the API continuously while you stay on a
20+
page, so viewing the Models or Cost page does not spam the Command Code
21+
endpoints.
22+
1523
## Key Bindings
1624

1725
| Key | Context | Action |
1826
|-----|---------|--------|
1927
| `1-7` | Always | Switch info page |
20-
| `r` | Always | Refresh all API data |
28+
| `r` | Always | Refresh all API data (manual) |
2129
| `o` | Always | Copy OpenAI endpoint URL to clipboard |
2230
| `a` | Always | Copy Anthropic URL to clipboard |
2331
| `p` | Always | Configure proxy port (with availability scan) |

lib/src/models/version.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
const bridgeVersion = '1.3.0';
1+
const bridgeVersion = '1.3.1';

lib/src/tui/app.dart

Lines changed: 19 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class AppState extends State<CmdBridgeApp> {
4949
bool _loadingData = false;
5050
bool _foregroundRefresh = true;
5151
DateTime? _lastAutoRefreshAt;
52+
DateTime? _lastPageOpenRefreshAt;
5253
int _lastLogVersion = -1;
5354
int _lastModelVersion = 0;
5455

@@ -87,25 +88,6 @@ class AppState extends State<CmdBridgeApp> {
8788
super.dispose();
8889
}
8990

90-
Duration _refreshIntervalForPage(_InfoPage page) {
91-
switch (page) {
92-
case _InfoPage.account:
93-
return const Duration(seconds: 20);
94-
case _InfoPage.plan:
95-
return const Duration(seconds: 15);
96-
case _InfoPage.usage:
97-
return const Duration(seconds: 8);
98-
case _InfoPage.limits:
99-
return const Duration(seconds: 8);
100-
case _InfoPage.models:
101-
return const Duration(seconds: 30);
102-
case _InfoPage.proxy:
103-
return const Duration(seconds: 1);
104-
case _InfoPage.cost:
105-
return const Duration(seconds: 30);
106-
}
107-
}
108-
10991
void _startActivePageRefresh() {
11092
_pageRefreshTimer?.cancel();
11193
_pageRefreshTimer = Timer.periodic(const Duration(seconds: 1), (_) {
@@ -123,9 +105,6 @@ class AppState extends State<CmdBridgeApp> {
123105
void _refreshVisiblePage() {
124106
if (!mounted || _panel != _Panel.main) return;
125107

126-
final now = DateTime.now();
127-
final interval = _refreshIntervalForPage(_infoPage);
128-
129108
if (_showLog && _lastLogVersion != LogStore.version) {
130109
_lastLogVersion = LogStore.version;
131110
setState(() {});
@@ -142,25 +121,30 @@ class AppState extends State<CmdBridgeApp> {
142121
setState(() {});
143122
return;
144123
}
145-
146-
if (_loadingData) return;
147-
if (_lastAutoRefreshAt != null && now.difference(_lastAutoRefreshAt!) < interval) {
148-
return;
149-
}
150-
151-
_lastAutoRefreshAt = now;
152-
_refreshData(silent: true, foreground: false);
153124
}
154125

155126
void _setInfoPage(_InfoPage page) {
156127
_infoPage = page;
157128
_selectedModelIndex = 0;
158129
_infoScrollCtrl.jumpTo(0);
159-
_lastAutoRefreshAt = null;
160130
_refreshVisiblePage();
131+
_refreshDataOnPageOpen();
161132
setState(() {});
162133
}
163134

135+
/// Refresh data once in the background when a page is opened, throttled so
136+
/// rapid page switching does not spam the Command Code API. Continuous
137+
/// per-page polling was removed; use `[r]` for a manual foreground refresh.
138+
void _refreshDataOnPageOpen() {
139+
final now = DateTime.now();
140+
if (_lastPageOpenRefreshAt != null &&
141+
now.difference(_lastPageOpenRefreshAt!).inSeconds < 10) {
142+
return;
143+
}
144+
_lastPageOpenRefreshAt = now;
145+
_refreshData(silent: true, foreground: false);
146+
}
147+
164148
Color _notifColor() {
165149
final msg = _status;
166150
if (msg.startsWith('Data refreshed') || msg.contains('Copied')) return Colors.green;
@@ -457,6 +441,10 @@ class AppState extends State<CmdBridgeApp> {
457441
}
458442
_loadingData = true;
459443
_foregroundRefresh = foreground;
444+
_lastAutoRefreshAt = DateTime.now();
445+
if (foreground) {
446+
_lastPageOpenRefreshAt = _lastAutoRefreshAt;
447+
}
460448
if (!silent) {
461449
_setStatus('Fetching data...');
462450
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "commandcode-bridge",
3-
"version": "1.3.0",
3+
"version": "1.3.1",
44
"description": "Command Code single-account proxy bridge with TUI dashboard. OpenAI-compatible endpoint for OpenCode, Cursor, etc.",
55
"type": "module",
66
"bin": {

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: commandcode_bridge
22
description: Command Code single-account proxy bridge with OpenAI-compatible endpoint
3-
version: 1.3.0
3+
version: 1.3.1
44

55
environment:
66
sdk: ^3.10.8

0 commit comments

Comments
 (0)