codex-copilot-dx 0.9.15 → 0.9.16
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/docs/REFERENCE.md +8 -6
- package/package.json +1 -1
- package/src/dashboard/index.html +2 -2
- package/src/dashboard/language.js +215 -182
- package/src/dashboard/ui.css +1 -0
- package/src/dashboard/ui.js +13 -4
package/docs/REFERENCE.md
CHANGED
|
@@ -107,7 +107,7 @@ This performs a fresh, read-only GitHub Copilot model-directory lookup without s
|
|
|
107
107
|
|
|
108
108
|
Interactive terminals use aligned tables for `models`, `auth status`, and `usage`. Redirected or piped output retains the plain-text layout for scripts; use `--format table` or `--format plain` when a command offers an explicit format override.
|
|
109
109
|
|
|
110
|
-
`ccdx usage` and the dashboard Usage table show token cache hit rate for each model and the aggregate: recorded cached input tokens divided by recorded input tokens, weighted by token count rather than averaging request percentages. This describes the upstream prompt cache; the local history and image-transform caches are separate. Incomplete historical records do not hide a computable ratio: `~` marks a rate derived from incomplete counts. A rate is `—` when input tokens are zero, usable totals are missing, or token counts are invalid. Older logs may omit explicit zero cache counts; new Responses usage records retain reported zeros. CLI tables keep existing token columns on narrow terminals and show rates below the table when the extra column does not fit.
|
|
110
|
+
`ccdx usage` and the dashboard Model Usage table show token cache hit rate for each model and the aggregate: recorded cached input tokens divided by recorded input tokens, weighted by token count rather than averaging request percentages. This describes the upstream prompt cache; the local history and image-transform caches are separate. Incomplete historical records do not hide a computable ratio: `~` marks a rate derived from incomplete counts. A rate is `—` when input tokens are zero, usable totals are missing, or token counts are invalid. Older logs may omit explicit zero cache counts; new Responses usage records retain reported zeros. CLI tables keep existing token columns on narrow terminals and show rates below the table when the extra column does not fit.
|
|
111
111
|
|
|
112
112
|
### Auto-review model
|
|
113
113
|
|
|
@@ -250,19 +250,21 @@ JSON reply to a streaming request is still not silently converted to SSE.
|
|
|
250
250
|
|
|
251
251
|
After starting `ccdx`, open [http://127.0.0.1:2026/](http://127.0.0.1:2026/) in a browser. If `ADAPTER_PORT` is customized, use that port instead. The dashboard shares the existing adapter listener; CCDX does not open a browser automatically or start another service. The page and its assets require both a loopback connection and a loopback Host header, even when LAN binding is enabled.
|
|
252
252
|
|
|
253
|
-
The dashboard loads local status, a live GitHub Copilot model directory, and a summary of local usage metadata once when opened. Each section has an explicit Refresh control; nothing polls in the background. The appearance button switches between the default dark terminal theme (sun icon) and a light theme (moon icon); the choice is stored only in that browser. The Requests card shows the running adapter's active raw and decoded per-request body limits, not request-body usage; Local History shows its in-memory Responses history use and active limit. Limit changes remain CLI-only (`ccdx limits` and `ccdx cache`). The live model table uses the same fresh account validation and selectable GPT filtering as `ccdx models`, never labels cached fallback data as online, and makes no inference request. A catalog listing does not guarantee inference access. The Usage table combines the current and rotated local usage logs, shows totals and up to 100 model rows, and contains no prompt, response body, or credential fields. The animation selector previews the existing themes and saves through the same settings writer as `ccdx animation`; changes take effect on the next adapter start, and `CCDX_TERMINAL_ANIMATION=off` still disables terminal motion. Dashboard data requests require a custom header that cross-site simple requests cannot send; animation writes also require a matching same-origin `Origin`. The dashboard does not initialize the optional image handler. The overview's known-model count is the adapter's current in-memory catalog, not the live table. A missing image-generation status does not prove the feature is disabled: use `ccdx image-status` to check setup. Recent upstream error prose may contain sensitive details, so review the page before sharing screenshots.
|
|
253
|
+
The dashboard loads local status, a live GitHub Copilot model directory, and a summary of local usage metadata once when opened. Each section has an explicit Refresh control; nothing polls in the background. The appearance button switches between the default dark terminal theme (sun icon) and a light theme (moon icon); the choice is stored only in that browser. The Requests card shows the running adapter's active raw and decoded per-request body limits, not request-body usage; Local History shows its in-memory Responses history use and active limit. Limit changes remain CLI-only (`ccdx limits` and `ccdx cache`). The live model table uses the same fresh account validation and selectable GPT filtering as `ccdx models`, never labels cached fallback data as online, and makes no inference request. A catalog listing does not guarantee inference access. The Model Usage table combines the current and rotated local usage logs, shows totals and up to 100 model rows, and contains no prompt, response body, or credential fields. The animation selector previews the existing themes and saves through the same settings writer as `ccdx animation`; changes take effect on the next adapter start, and `CCDX_TERMINAL_ANIMATION=off` still disables terminal motion. Dashboard data requests require a custom header that cross-site simple requests cannot send; animation writes also require a matching same-origin `Origin`. The dashboard does not initialize the optional image handler. The overview's known-model count is the adapter's current in-memory catalog, not the live table. A missing image-generation status does not prove the feature is disabled: use `ccdx image-status` to check setup. Recent upstream error prose may contain sensitive details, so review the page before sharing screenshots.
|
|
254
|
+
|
|
255
|
+
The dashboard labels the upstream token cache hit metric **Reuse Rate** and cached input **Reused Input**, separate from **Local History**. Chinese uses short functional names such as “对话暂存”, “重用输入” and “重用比例”. English and Chinese preserve model IDs, commands, units, HTTP status codes and raw diagnostic values. Animation display names translate in place; theme IDs and CLI parameters do not change.
|
|
254
256
|
|
|
255
257
|
The transparent, single-color double-peak favicon follows the dashboard's saved light/dark choice without a separate network request.
|
|
256
258
|
|
|
257
|
-
The saved GitHub Copilot account appears immediately to the left of the
|
|
259
|
+
The saved GitHub Copilot account appears immediately to the left of the Status updated time. It uses the same local credentials and fingerprint-bound identity metadata as `ccdx auth status`, with username (or numeric ID fallback) and a `SAVED` label; this is not an online entitlement check. Missing, invalid, unidentified, or unreadable credentials are shown explicitly. The account read runs once on page load and on the top Refresh action, independently of adapter status, with no polling or upstream authentication calls. Its loopback-only, custom-header-protected API exposes no token, fingerprint, credential path, or raw metadata. The general status endpoint retains its existing identity-free contract.
|
|
258
260
|
|
|
259
261
|
Account names containing underscores are supported, including `dingxiao_microsoft`. A numeric ID is a fallback, not a replacement for an available, safely displayable username; the existing length bounds and credential-shaped text suppression still apply.
|
|
260
262
|
|
|
261
263
|
The language button immediately right of the appearance button switches between English and Simplified Chinese. English remains the default; the choice is saved only in the current browser, separately from light/dark mode. Switching translates the existing page in place: it does not fetch API data, rebuild charts, change selected filters, discard unsaved animation choices, or reset expanded failure details. Static labels, live status text, chart tooltips and accessibility labels follow the selected language. Model IDs, account names, dates, numeric values and upstream diagnostic prose stay unchanged; copied diagnostic fields retain their original names and values. The local translation asset adds no dependency, external service, polling or inference-path work.
|
|
262
264
|
|
|
263
|
-
Usage
|
|
265
|
+
Usage Trends is collapsed by default. Opening it adds daily input/output token bars (7/30/90 days) and a 365-day calendar of recorded usage calls or tokens, grouped in the browser's time zone. Cache-read tokens are already part of input and are not added again. Model and range filters use the current snapshot without additional requests; selecting a day shows its filtered model totals in the Model Usage table, and Show all restores the original table. Analytics shares the existing current/rotated-log scan and exposes only bounded metadata (365 days, up to 100 model filters). Days before retained history are hatched, not presented as zero; the oldest retained day may be partial. Counts describe retained usage records, not messages, session time, or all HTTP requests. Refresh explicitly to update the snapshot; there is no background collection or polling.
|
|
264
266
|
|
|
265
|
-
Terminal Animation is collapsed at the bottom of the page, with an Animation shortcut in the header. Preview frames load only when opened; closing it, hiding the page, or requesting reduced motion stops the preview timer. Unsaved choices survive folding and reopening. Recent response failures expand to diagnostic fields (time, model, code, message, response/request IDs, and retry policy) with a Copy
|
|
267
|
+
Terminal Animation is collapsed at the bottom of the page, with an Animation shortcut in the header. Preview frames load only when opened; closing it, hiding the page, or requesting reduced motion stops the preview timer. Unsaved choices survive folding and reopening. Recent response failures expand to diagnostic fields (time, model, code, message, response/request IDs, and retry policy) with a Copy details control. The view combines the last 10 retained `response.failed` events with failures from the 20 most recently finished Responses/compact requests, showing at most 10 entries. Matching local request IDs attach the final outcome and timing metadata, so a recovered event can show `completed`; an uncorrelated retry attempt does not prove recovery. Transport failures and incomplete/cancelled requests can appear without a `response.failed` event. These are bounded runtime observations, not complete session histories. Diagnostic prose is redacted by the existing recorder but can still contain sensitive context: review before copying or sharing.
|
|
266
268
|
|
|
267
269
|
Inspect only the local Codex configuration:
|
|
268
270
|
|
|
@@ -326,7 +328,7 @@ ccdx --show-request-id
|
|
|
326
328
|
|
|
327
329
|
### Authentication recovery
|
|
328
330
|
|
|
329
|
-
The dashboard's collapsed **RECENT
|
|
331
|
+
The dashboard's collapsed **RECENT REQUESTS** section reuses the same
|
|
330
332
|
status snapshot. It shows at most 20 finished request observations: serialized
|
|
331
333
|
upstream payload bytes, image count, reported input tokens, the advertised model
|
|
332
334
|
window and terminal outcome, plus process-local compaction outcome counts. Missing
|
package/package.json
CHANGED
package/src/dashboard/index.html
CHANGED
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
|
|
27
27
|
<section class="overview" aria-label="Overview" data-i18n-label>
|
|
28
28
|
<article class="card"><h2 data-i18n>ADAPTER</h2><strong id="version">—</strong><p id="uptime">—</p></article>
|
|
29
|
-
<article class="card"><h2>
|
|
29
|
+
<article class="card"><h2>Copilot</h2><strong id="copilot">—</strong><p id="token">—</p></article>
|
|
30
30
|
<article class="card"><h2 data-i18n>KNOWN MODELS</h2><strong id="models">—</strong><p id="model-source">—</p></article>
|
|
31
31
|
<article class="card"><h2 data-i18n>REQUESTS</h2><strong id="requests">—</strong><p id="request-errors">—</p><p><span data-i18n>Per-request limits (active)</span><br><span id="body-limits">—</span></p></article>
|
|
32
32
|
</section>
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
<section class="panel dashboard-section" aria-label="Live upstream models" data-i18n-label>
|
|
59
59
|
<div class="panel-heading"><h2 data-i18n>UPSTREAM GPT MODELS</h2><div class="heading-actions"><span id="models-state" data-i18n>CHECKING LIVE</span><button id="refresh-models" type="button" data-i18n>Refresh</button></div></div>
|
|
60
60
|
<p id="models-note" class="table-note" data-i18n>Querying GitHub Copilot…</p>
|
|
61
|
-
<div class="table-wrap"><table><thead><tr><th scope="col" data-i18n>MODEL</th><th scope="col" data-i18n>VENDOR</th><th scope="col">API</th><th scope="col" data-i18n>FLAG</th></tr></thead><tbody id="live-models-body"><tr><td colspan="4" data-i18n>Loading…</td></tr></tbody></table></div>
|
|
61
|
+
<div class="table-wrap"><table><thead><tr><th scope="col" data-i18n>MODEL</th><th scope="col" data-i18n>VENDOR</th><th scope="col" data-i18n>API</th><th scope="col" data-i18n>FLAG</th></tr></thead><tbody id="live-models-body"><tr><td colspan="4" data-i18n>Loading…</td></tr></tbody></table></div>
|
|
62
62
|
<p class="hint" data-i18n>Catalog listing does not guarantee inference access.</p>
|
|
63
63
|
</section>
|
|
64
64
|
|
|
@@ -1,185 +1,218 @@
|
|
|
1
1
|
(() => {
|
|
2
2
|
const translations = {
|
|
3
|
-
"CCDX · Local dashboard": "CCDX ·
|
|
4
|
-
"/ LOCAL STATUS": "/
|
|
5
|
-
"READING": "读取中",
|
|
6
|
-
"LOCAL OK": "本机正常",
|
|
7
|
-
"UNAVAILABLE": "
|
|
8
|
-
"Refresh": "刷新",
|
|
9
|
-
"Animation": "动效",
|
|
10
|
-
"Switch to light mode": "
|
|
11
|
-
"Switch to dark mode": "
|
|
12
|
-
"Overview": "概览",
|
|
13
|
-
"RECENT REQUEST CONTEXT": "
|
|
14
|
-
"WIRE MiB": "
|
|
15
|
-
"IMAGES": "
|
|
16
|
-
"INPUT TOKENS": "
|
|
17
|
-
"MODEL WINDOW": "
|
|
18
|
-
"INPUT / WINDOW": "
|
|
19
|
-
"OUTCOME": "
|
|
20
|
-
"Unknown": "未知",
|
|
21
|
-
"No observed request metadata.": "
|
|
22
|
-
"20 latest finished requests / compactions: {completed} completed, {incomplete} incomplete, {failed} failed": "
|
|
23
|
-
"Recent upstream request metadata, not exact live session occupancy. Missing values are unknown. No prompt or image content is retained.": "
|
|
24
|
-
"Runtime details": "运行详情",
|
|
25
|
-
"ADAPTER": "
|
|
26
|
-
"KNOWN MODELS": "
|
|
27
|
-
"REQUESTS": "
|
|
28
|
-
"Per-request limits (active)": "
|
|
29
|
-
"MODEL OUTCOMES": "
|
|
30
|
-
"Completed": "已完成",
|
|
31
|
-
"Incomplete": "未完成",
|
|
32
|
-
"Failed": "失败",
|
|
33
|
-
"Cancelled": "已取消",
|
|
34
|
-
"HTTP 2xx != model completed.": "HTTP 2xx
|
|
35
|
-
"LOCAL HISTORY": "
|
|
36
|
-
"ACTIVE LIMIT": "
|
|
37
|
-
"History cache usage": "
|
|
38
|
-
"IMAGE GENERATION": "图片生成",
|
|
39
|
-
"OPTIONAL": "
|
|
40
|
-
"Live upstream models": "
|
|
41
|
-
"UPSTREAM GPT MODELS": "
|
|
42
|
-
"CHECKING LIVE": "
|
|
43
|
-
"Querying GitHub Copilot…": "
|
|
44
|
-
"MODEL": "模型",
|
|
45
|
-
"VENDOR": "提供方",
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
-
"
|
|
74
|
-
"
|
|
75
|
-
"
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
"
|
|
79
|
-
"
|
|
80
|
-
"
|
|
81
|
-
"
|
|
82
|
-
"
|
|
83
|
-
"Reading
|
|
84
|
-
"
|
|
85
|
-
"
|
|
86
|
-
"
|
|
87
|
-
"
|
|
88
|
-
"
|
|
89
|
-
"
|
|
90
|
-
"
|
|
91
|
-
"GitHub /
|
|
92
|
-
"GitHub /
|
|
93
|
-
"GitHub /
|
|
94
|
-
"GitHub /
|
|
95
|
-
"GitHub /
|
|
96
|
-
"account
|
|
97
|
-
"
|
|
98
|
-
"
|
|
99
|
-
"
|
|
100
|
-
"
|
|
101
|
-
"service token
|
|
102
|
-
"
|
|
103
|
-
"
|
|
104
|
-
"
|
|
105
|
-
"
|
|
106
|
-
"
|
|
107
|
-
"
|
|
108
|
-
"
|
|
109
|
-
"
|
|
110
|
-
"{
|
|
111
|
-
"
|
|
112
|
-
"
|
|
113
|
-
"
|
|
114
|
-
"
|
|
115
|
-
"
|
|
116
|
-
"
|
|
117
|
-
"
|
|
118
|
-
"
|
|
119
|
-
"
|
|
120
|
-
"retry
|
|
121
|
-
"
|
|
122
|
-
"
|
|
123
|
-
"
|
|
124
|
-
"
|
|
125
|
-
"
|
|
126
|
-
"
|
|
127
|
-
"
|
|
128
|
-
"
|
|
129
|
-
"
|
|
130
|
-
"
|
|
131
|
-
"
|
|
132
|
-
"
|
|
133
|
-
"
|
|
134
|
-
"
|
|
135
|
-
"
|
|
136
|
-
"
|
|
137
|
-
"
|
|
138
|
-
"
|
|
139
|
-
"
|
|
140
|
-
"attempted": "
|
|
141
|
-
"
|
|
142
|
-
"
|
|
143
|
-
"
|
|
144
|
-
"
|
|
145
|
-
"
|
|
146
|
-
"
|
|
147
|
-
"
|
|
148
|
-
"
|
|
149
|
-
"
|
|
150
|
-
"
|
|
151
|
-
"
|
|
152
|
-
"
|
|
153
|
-
"
|
|
154
|
-
"
|
|
155
|
-
"
|
|
156
|
-
"
|
|
157
|
-
"
|
|
158
|
-
"No
|
|
159
|
-
"
|
|
160
|
-
"
|
|
161
|
-
" / {
|
|
162
|
-
"
|
|
163
|
-
"
|
|
164
|
-
" /
|
|
165
|
-
"
|
|
166
|
-
"{
|
|
167
|
-
"
|
|
168
|
-
"
|
|
169
|
-
"
|
|
170
|
-
" {
|
|
171
|
-
"
|
|
172
|
-
"
|
|
173
|
-
"
|
|
174
|
-
"
|
|
175
|
-
"
|
|
176
|
-
"
|
|
177
|
-
"
|
|
178
|
-
"Animation
|
|
179
|
-
"
|
|
180
|
-
"
|
|
181
|
-
"
|
|
182
|
-
"
|
|
3
|
+
"CCDX · Local dashboard": ["CCDX · Dashboard", "CCDX · 运行看板"],
|
|
4
|
+
"/ LOCAL STATUS": ["/ DASHBOARD", "/ 运行看板"],
|
|
5
|
+
"READING": ["READING", "读取中"],
|
|
6
|
+
"LOCAL OK": ["LOCAL OK", "本机正常"],
|
|
7
|
+
"UNAVAILABLE": ["UNAVAILABLE", "无法读取"],
|
|
8
|
+
"Refresh": ["Refresh", "刷新"],
|
|
9
|
+
"Animation": ["Animation", "动效"],
|
|
10
|
+
"Switch to light mode": ["Light mode", "白天模式"],
|
|
11
|
+
"Switch to dark mode": ["Dark mode", "夜间模式"],
|
|
12
|
+
"Overview": ["Overview", "概览"],
|
|
13
|
+
"RECENT REQUEST CONTEXT": ["RECENT REQUESTS", "近期请求"],
|
|
14
|
+
"WIRE MiB": ["DATA SIZE", "数据大小"],
|
|
15
|
+
"IMAGES": ["IMAGES", "图片数量"],
|
|
16
|
+
"INPUT TOKENS": ["INPUT USAGE", "输入用量"],
|
|
17
|
+
"MODEL WINDOW": ["MODEL CAPACITY", "模型容量"],
|
|
18
|
+
"INPUT / WINDOW": ["CAPACITY USED", "占用比例"],
|
|
19
|
+
"OUTCOME": ["RESULT", "结果"],
|
|
20
|
+
"Unknown": ["Unknown", "未知"],
|
|
21
|
+
"No observed request metadata.": ["No request records yet.", "暂未收到请求记录。"],
|
|
22
|
+
"20 latest finished requests / compactions: {completed} completed, {incomplete} incomplete, {failed} failed": ["Last 20 finished requests.\nHistory compaction: {completed} completed · {incomplete} incomplete · {failed} failed", "最近20次已结束请求。\n压缩完成:{completed}次\n压缩未完成:{incomplete}次\n压缩失败:{failed}次"],
|
|
23
|
+
"Recent upstream request metadata, not exact live session occupancy. Missing values are unknown. No prompt or image content is retained.": ["Size: MiB. Usage and capacity: Token.\nRequest records, not exact current thread usage.\nMissing data is unknown. No prompts or images are saved.", "大小单位:MiB。\n用量单位:Token。\n不是会话当前的精确占用。\n缺失数据表示未知。\n不保存提问或图片内容。"],
|
|
24
|
+
"Runtime details": ["Runtime details", "运行详情"],
|
|
25
|
+
"ADAPTER": ["SERVICE", "服务状态"],
|
|
26
|
+
"KNOWN MODELS": ["MODEL COUNT", "模型数量"],
|
|
27
|
+
"REQUESTS": ["REQUESTS", "请求次数"],
|
|
28
|
+
"Per-request limits (active)": ["Per-request limits", "单次上限"],
|
|
29
|
+
"MODEL OUTCOMES": ["REQUEST RESULTS", "处理结果"],
|
|
30
|
+
"Completed": ["Completed", "已完成"],
|
|
31
|
+
"Incomplete": ["Incomplete", "未完成"],
|
|
32
|
+
"Failed": ["Failed", "失败"],
|
|
33
|
+
"Cancelled": ["Cancelled", "已取消"],
|
|
34
|
+
"HTTP 2xx != model completed.": ["HTTP 2xx can still mean an unfinished reply.", "HTTP 2xx也可能没答完整。"],
|
|
35
|
+
"LOCAL HISTORY": ["LOCAL HISTORY", "对话暂存"],
|
|
36
|
+
"ACTIVE LIMIT": ["STORAGE LIMIT", "存储上限"],
|
|
37
|
+
"History cache usage": ["Local history usage", "对话暂存"],
|
|
38
|
+
"IMAGE GENERATION": ["IMAGE GENERATION", "图片生成"],
|
|
39
|
+
"OPTIONAL": ["OPT-IN", "按需开启"],
|
|
40
|
+
"Live upstream models": ["Online models", "在线模型"],
|
|
41
|
+
"UPSTREAM GPT MODELS": ["ONLINE MODELS", "在线模型"],
|
|
42
|
+
"CHECKING LIVE": ["CHECKING", "查询中"],
|
|
43
|
+
"Querying GitHub Copilot…": ["Checking Copilot models…", "正在查询Copilot模型。"],
|
|
44
|
+
"MODEL": ["MODEL", "模型"],
|
|
45
|
+
"VENDOR": ["PROVIDER", "提供方"],
|
|
46
|
+
"API": ["INTERFACE", "连接方式"],
|
|
47
|
+
"FLAG": ["STAGE", "阶段"],
|
|
48
|
+
"Loading…": ["Loading…", "加载中"],
|
|
49
|
+
"Catalog listing does not guarantee inference access.": ["A listed model may still be unavailable to your account.", "模型列出后,仍可能无法使用。"],
|
|
50
|
+
"Usage by model": ["Model usage", "模型用量"],
|
|
51
|
+
"USAGE": ["MODEL USAGE", "模型用量"],
|
|
52
|
+
"READING LOG": ["COUNTING", "统计中"],
|
|
53
|
+
"All history": ["Show all", "查看全部"],
|
|
54
|
+
"Aggregating local usage metadata…": ["Counting local usage…", "正在统计本机用量。"],
|
|
55
|
+
"CALLS": ["REQUESTS", "请求次数"],
|
|
56
|
+
"INPUT": ["INPUT USAGE", "输入用量"],
|
|
57
|
+
"CACHE READ": ["REUSED INPUT", "重用输入"],
|
|
58
|
+
"OUTPUT": ["OUTPUT USAGE", "输出用量"],
|
|
59
|
+
"TOTAL": ["TOTAL", "总用量"],
|
|
60
|
+
"CACHE HIT": ["REUSE RATE", "重用比例"],
|
|
61
|
+
"Cache hit = recorded cached / input tokens. ~ = incomplete history. — = unavailable or invalid counts.": ["Usage unit: Token. Reuse rate = reused input / input usage.\n~ means incomplete records. — means unknown or invalid data.", "用量单位:Token。\n重用输入占输入用量的比例。\n~:记录不完整。\n—:数据未知或无效。"],
|
|
62
|
+
"USAGE ANALYTICS": ["USAGE TRENDS", "用量趋势"],
|
|
63
|
+
"Model": ["Model", "模型"],
|
|
64
|
+
"All models": ["All models", "全部模型"],
|
|
65
|
+
"Daily range": ["Date range", "时间范围"],
|
|
66
|
+
"7 days": ["Last 7 days", "近7天"],
|
|
67
|
+
"30 days": ["Last 30 days", "近30天"],
|
|
68
|
+
"90 days": ["Last 90 days", "近90天"],
|
|
69
|
+
"Activity": ["Measure", "统计内容"],
|
|
70
|
+
"Calls": ["Requests", "请求次数"],
|
|
71
|
+
"Tokens": ["Usage (Token)", "处理用量"],
|
|
72
|
+
"Open to read retained usage history.": ["Open to view usage trends.", "展开查看用量趋势。"],
|
|
73
|
+
"DAILY TOKENS": ["DAILY USAGE", "每日用量"],
|
|
74
|
+
"INPUT + OUTPUT / CACHE INCLUDED IN INPUT": ["INPUT + OUTPUT · REUSED INPUT INCLUDED", "输入与输出合计。\n重用部分已计入输入用量。"],
|
|
75
|
+
"Daily token usage": ["Daily usage in Token", "每日用量"],
|
|
76
|
+
"Input": ["Input usage", "输入用量"],
|
|
77
|
+
"Output": ["Output usage", "输出用量"],
|
|
78
|
+
"REQUEST ACTIVITY · 365 DAYS": ["ACTIVITY · LAST 365 DAYS", "活跃日历"],
|
|
79
|
+
"Daily recorded request activity": ["Daily recorded activity over 365 days", "每日活跃"],
|
|
80
|
+
"Select a day to inspect its model totals. No history is distinct from zero recorded calls.": ["Select a day to view its usage.\nNo records is different from zero requests.", "点击日期,查看当天用量。\n没有记录,不等于零次请求。"],
|
|
81
|
+
"Recent failures": ["Recent issues", "异常记录"],
|
|
82
|
+
"RECENT RESPONSE FAILURES": ["RECENT ISSUES", "异常记录"],
|
|
83
|
+
"Reading…": ["Reading…", "读取中"],
|
|
84
|
+
"Reading status…": ["Reading status…", "读取中"],
|
|
85
|
+
"Upstream messages may contain sensitive text.": ["Error details may contain private information.", "错误内容可能含私人信息。"],
|
|
86
|
+
"TERMINAL ANIMATION": ["TERMINAL ANIMATION", "终端动效"],
|
|
87
|
+
"Animation theme": ["Animation style", "动效样式"],
|
|
88
|
+
"Save selection": ["Save animation", "保存动效"],
|
|
89
|
+
"Applies on next ccdx start.": ["Save, then restart ccdx to apply.", "保存后,下次启动生效。"],
|
|
90
|
+
"LOCAL ONLY / NO BACKGROUND POLLING": ["LOCAL ONLY · NO TIMED REFRESH", "仅在本机查看。不会定时读取。"],
|
|
91
|
+
"Saved GitHub Copilot account / local credentials only; not an online entitlement check.": ["Saved local sign-in details only.\nOnline access has not been checked.", "仅查看本机保存的登录信息。\n尚未核实在线使用权限。"],
|
|
92
|
+
"GitHub / READING": ["GitHub / READING", "GitHub / 读取中"],
|
|
93
|
+
"GitHub / UNAVAILABLE": ["GitHub / UNAVAILABLE", "GitHub / 无法读取"],
|
|
94
|
+
"GitHub / NOT CONFIGURED": ["GitHub / NOT SET UP", "GitHub / 未设置"],
|
|
95
|
+
"GitHub / INVALID": ["GitHub / INVALID DETAILS", "GitHub / 信息无效"],
|
|
96
|
+
"GitHub / {account} / SAVED": ["GitHub / {account} / SAVED", "GitHub / {account} / 已保存"],
|
|
97
|
+
"account unknown": ["account unknown", "账号未知"],
|
|
98
|
+
"pid {pid} / uptime {duration}": ["PID {pid} · running {duration}", "进程编号:{pid} · 已运行:{duration}"],
|
|
99
|
+
"BOUND": ["IDENTIFIED", "已识别"],
|
|
100
|
+
"UNCONFIRMED": ["UNCONFIRMED", "待确认"],
|
|
101
|
+
"service token / TTL {duration}": ["Access details expire in {duration}", "有效期:{duration}"],
|
|
102
|
+
"service token not cached": ["No saved access details yet.", "还没有暂存授权信息。"],
|
|
103
|
+
"source {source} / live: ccdx models": ["Source: {source}\nOnline list: ccdx models", "来源:{source}\n在线目录:ccdx models"],
|
|
104
|
+
"built-in": ["built-in list", "内置目录"],
|
|
105
|
+
"cache": ["existing list", "已有目录"],
|
|
106
|
+
"live": ["online list", "在线目录"],
|
|
107
|
+
"unknown": ["unknown", "未知"],
|
|
108
|
+
"4xx {client} / 5xx {server} / active {active}": ["4xx {client} · 5xx {server} · active {active}", "4xx {client} · 5xx {server} · 进行中 {active}"],
|
|
109
|
+
"raw {raw} / decoded {decoded}": ["Received: {raw}\nUnpacked: {decoded}", "接收上限:{raw}\n展开上限:{decoded}"],
|
|
110
|
+
"entries {entries} / trees {trees} / misses {misses} (evicted {evicted})": ["Records: {entries} · groups: {trees}\nNot found: {misses} · after removal: {evicted}", "记录:{entries}条 · 历史分组:{trees}组\n未找到:{misses}次\n清出后未找到:{evicted}次"],
|
|
111
|
+
"{count} succeeded": ["{count} succeeded", "成功:{count}次"],
|
|
112
|
+
"NOT INITIALIZED": ["UNCONFIRMED", "尚未确认"],
|
|
113
|
+
"active {active} / failed {failed} / delivery failures {delivery}": ["Active: {active} · failed: {failed}\nDelivery failures: {delivery}", "进行中:{active} · 生成失败:{failed}\n交付失败:{delivery}"],
|
|
114
|
+
"Setup state unknown / ccdx image-status": ["Check setup:\nccdx image-status", "查看设置:\nccdx image-status"],
|
|
115
|
+
"Snapshot {time}": ["Status updated {time}", "状态更新:{time}"],
|
|
116
|
+
"Status unavailable / check ccdx, then refresh": ["Cannot read status. Check ccdx, then refresh.", "状态读取失败,请检查后刷新。"],
|
|
117
|
+
"{count} retained / requests + events": ["{count} records retained", "保留:{count}条"],
|
|
118
|
+
"No recent request failures recorded.": ["No recent issues recorded.", "暂未记录异常。"],
|
|
119
|
+
"Request ended without successful completion.": ["This request did not finish successfully.", "该请求未能完整完成。"],
|
|
120
|
+
"{detail} / {retry}": ["{detail} / {retry}", "{detail} / {retry}"],
|
|
121
|
+
"retry attempted": ["retried", "已重试"],
|
|
122
|
+
"no retry": ["not retried", "未重试"],
|
|
123
|
+
"time": ["Time", "时间"],
|
|
124
|
+
"model": ["Model", "模型"],
|
|
125
|
+
"event": ["Event type", "事件类型"],
|
|
126
|
+
"code": ["Error code", "错误代码"],
|
|
127
|
+
"message": ["Error details", "错误详情"],
|
|
128
|
+
"response_id": ["Response ID", "回答编号"],
|
|
129
|
+
"upstream_request_id": ["Provider request ID", "服务编号"],
|
|
130
|
+
"request_id": ["Local request ID", "本机编号"],
|
|
131
|
+
"outcome": ["Result", "处理结果"],
|
|
132
|
+
"origin": ["Reported by", "结果来源"],
|
|
133
|
+
"phase": ["Last step", "最后步骤"],
|
|
134
|
+
"http_status": ["HTTP status", "返回状态"],
|
|
135
|
+
"upstream_attempts": ["Send attempts", "发送次数"],
|
|
136
|
+
"timings_ms": ["Timeline (ms)", "时间记录(毫秒)"],
|
|
137
|
+
"retry": ["Retry status", "重试情况"],
|
|
138
|
+
"retry_policy": ["Retry rule", "重试规则"],
|
|
139
|
+
"retry_skipped": ["Skip reason", "跳过原因"],
|
|
140
|
+
"attempted (outcome not recorded here)": ["Retried; result not recorded here.", "已重试;这里未记录结果。"],
|
|
141
|
+
"attempted": ["retried", "已重试"],
|
|
142
|
+
"not attempted": ["not retried", "未重试"],
|
|
143
|
+
"Copy diagnostic": ["Copy details", "复制详情"],
|
|
144
|
+
"Copied": ["Copied", "已复制"],
|
|
145
|
+
"Copy unavailable": ["Copy failed", "复制失败"],
|
|
146
|
+
"DEFAULT": ["DEFAULT", "默认"],
|
|
147
|
+
"Disabled by CCDX_TERMINAL_ANIMATION; saved choice applies after override removal and next start.": ["Disabled by CCDX_TERMINAL_ANIMATION.\nRemove this setting, then restart to apply your saved choice.", "启动设置已关闭动效。\nCCDX_TERMINAL_ANIMATION\n移除此设置后,重启生效。"],
|
|
148
|
+
"Saved choice applies on next ccdx start.": ["Saved choice applies after restarting ccdx.", "保存后,下次启动生效。"],
|
|
149
|
+
"CURRENT {theme}{unsaved}": ["SAVED {theme}{unsaved}", "已保存:{theme}{unsaved}"],
|
|
150
|
+
" / UNSAVED": [" / UNSAVED", " / 待保存"],
|
|
151
|
+
"Saving…": ["Saving…", "保存中"],
|
|
152
|
+
"Not saved / {error}": ["Not saved: {error}", "保存失败:{error}"],
|
|
153
|
+
"preview": ["preview", "测试版"],
|
|
154
|
+
"No selectable GPT models advertised.": ["No selectable GPT models found.", "暂未发现可选GPT模型。"],
|
|
155
|
+
"LIVE SNAPSHOT": ["FETCHED", "已获取"],
|
|
156
|
+
"{selectable} selectable / {advertised} advertised / {host} / {time}": ["Selectable: {selectable} · listed: {advertised}\nSource: {host} · checked {time}", "可选:{selectable}个 · 服务列出:{advertised}个\n来源:{host} · 获取时间:{time}"],
|
|
157
|
+
"LIVE LOOKUP FAILED": ["CHECK FAILED", "查询失败"],
|
|
158
|
+
"No live catalog available.": ["Cannot get the model list.", "无法获取模型列表。"],
|
|
159
|
+
"No usage records.": ["No usage records yet.", "暂未记录用量。"],
|
|
160
|
+
"LOCAL LOG": ["LOCAL RECORDS", "本机记录"],
|
|
161
|
+
"{records} records / {shown} of {models} models shown{day}": ["Records: {records} · models: {shown} of {models}{day}", "记录:{records}条\n模型:展示{shown}个,共{models}个{day}"],
|
|
162
|
+
" / {zone} / {model}": [" / {zone} / {model}", " / {zone} / {model}"],
|
|
163
|
+
"no retained history": ["no records", "没有记录"],
|
|
164
|
+
"{calls} recorded calls / input {input} / output {output} / cached {cached} (included in input){partial}": ["{calls} recorded requests\nInput: {input} · output: {output} · reused: {cached} Token\nReused input is included in input usage.{partial}", "请求:{calls}次\n输入用量:{input} Token\n输出用量:{output} Token\n重用输入:{cached} Token\n重用部分已计入输入用量。{partial}"],
|
|
165
|
+
" / partial token counts": ["\nIncomplete usage records.", "\n用量记录不完整。"],
|
|
166
|
+
"{date} / {description}": ["{date} / {description}", "{date} / {description}"],
|
|
167
|
+
"{metric} / PEAK {peak}": ["365 DAYS · {metric} · PEAK {peak}", "近365天 · {metric} · 峰值{peak}"],
|
|
168
|
+
"INPUT + OUTPUT": ["TOTAL USAGE (Token)", "总用量"],
|
|
169
|
+
"RECORDED CALLS": ["RECORDED REQUESTS", "请求次数"],
|
|
170
|
+
"{zone} / {from} — {to} / retained history starts {first}; oldest day may be partial.{excluded}{limit}": ["{zone} · {from} — {to}\nEarliest record: {first}. That day may be incomplete.{excluded}{limit}", "时区:{zone}\n记录范围:{from}—{to}\n最早记录:{first}\n最早一天的记录可能不全。{excluded}{limit}"],
|
|
171
|
+
" {count} records with invalid/future timestamps excluded.": ["\nSkipped {count} records with invalid or future dates.", "\n已跳过{count}条时间异常记录。"],
|
|
172
|
+
" Model filters limited to 100; all-model totals include the remainder.": ["\nFilters show up to 100 models. Totals include the rest.", "\n只列出前100个模型。\n总计包含其余模型。"],
|
|
173
|
+
"Selected {date} / {model}: totals in the Usage table above / All history resets the table.": ["Selected: {date} / {model}. See the usage table above.\nChoose Show all to reset the date.", "已选:{date}/{model}\n当天用量见上方表格。\n点击“查看全部”恢复总表。"],
|
|
174
|
+
"Select a day for model totals. Calls are usage records, not messages or time. Hatched cells: no retained history; empty cells: zero recorded calls.": ["Select a day to view its usage.\nCounts are recorded requests, not messages or time.\nHatched: no records. Blank: zero recorded requests.", "点击日期,查看当天用量。\n按已记录的请求统计。\n不代表消息数或使用时长。\n斜线格表示没有记录。\n空白格表示已记录零次请求。"],
|
|
175
|
+
"LOG UNAVAILABLE": ["READ FAILED", "读取失败"],
|
|
176
|
+
"No usage summary available.": ["Cannot read usage records.", "无法读取用量记录。"],
|
|
177
|
+
"Analytics unavailable / refresh Usage to retry.": ["Trends unavailable. Refresh Model usage to retry.", "统计失败,请刷新用量。"],
|
|
178
|
+
"Animation settings are invalid; inspect them with ccdx animation": ["Invalid animation settings.\nRun ccdx animation.", "设置无效,请检查动效。\n运行ccdx animation。"],
|
|
179
|
+
"Animation setting was not saved; check ccdx animation": ["Animation was not saved.\nRun ccdx animation.", "保存失败,请检查动效。\n运行ccdx animation。"],
|
|
180
|
+
"Could not read local usage summary": ["Cannot read usage. Refresh to retry.", "无法读取用量,请刷新。"],
|
|
181
|
+
"Live model lookup timed out. Retry or run ccdx models.": ["Model check timed out. Try again.\nRun ccdx models for details.", "模型查询超时,请重试。\n运行ccdx models。"],
|
|
182
|
+
"GitHub token not found. Start ccdx to sign in.": ["No GitHub sign-in details found.\nRun ccdx to sign in.", "未找到登录信息。\n运行ccdx登录。"],
|
|
183
|
+
"Live model lookup failed. Run ccdx models for details.": ["Model check failed.\nRun ccdx models for details.", "模型查询失败,请查看详情。\n运行ccdx models。"],
|
|
184
|
+
"Live model lookup failed (HTTP {status}). Run ccdx models for details.": ["Model check failed: HTTP {status}.\nRun ccdx models for details.", "模型查询失败:HTTP {status}\n运行ccdx models。"],
|
|
185
|
+
"Select a listed animation theme": ["Choose an animation from the list.", "请选择列表中的动效。"],
|
|
186
|
+
"Animation changes require the same-origin dashboard": ["Save from this computer's dashboard.", "请从本机看板保存动效。"],
|
|
187
|
+
"Animation changes require application/json": ["The save format is invalid.", "保存内容格式不正确。"],
|
|
188
|
+
"Invalid animation request body": ["The animation selection is invalid.", "动效选择格式不正确。"],
|
|
189
|
+
"Select a valid usage time zone": ["Choose a valid time zone.", "所选时区无效。"],
|
|
190
|
+
"Method not allowed": ["This action is not supported.", "此操作不受支持。"],
|
|
191
|
+
"Dashboard API is available only at a loopback address": ["Open the dashboard on this computer.", "请在本机打开看板。"],
|
|
192
|
+
"Dashboard API requires a same-origin page request": ["Use this computer's dashboard to continue.", "请从本机看板操作。"],
|
|
193
|
+
"{time} / {model} / {code}": ["{time} / {model} / {code}", "{time} / {model} / {code}"],
|
|
194
|
+
"unknown time": ["unknown time", "时间未知"],
|
|
195
|
+
"unknown_model": ["unknown model", "模型未知"],
|
|
196
|
+
"unknown_error": ["unknown error", "错误未知"],
|
|
197
|
+
"{index} {theme}": ["{index} {theme}", "{index} {theme}"],
|
|
198
|
+
"Comet": ["Comet", "彗星"],
|
|
199
|
+
"Twin": ["Twin", "双星"],
|
|
200
|
+
"Shuttle": ["Shuttle", "往返"],
|
|
201
|
+
"Chase": ["Chase", "追逐"],
|
|
202
|
+
"Mirror": ["Mirror", "对称"],
|
|
203
|
+
"Pulse": ["Pulse", "呼吸"],
|
|
204
|
+
"Stack": ["Stack", "堆叠"],
|
|
205
|
+
"Relay": ["Relay", "接力"],
|
|
206
|
+
"Split": ["Split", "分岔"],
|
|
207
|
+
"COMET": ["COMET", "彗星"],
|
|
208
|
+
"TWIN": ["TWIN", "双星"],
|
|
209
|
+
"SHUTTLE": ["SHUTTLE", "往返"],
|
|
210
|
+
"CHASE": ["CHASE", "追逐"],
|
|
211
|
+
"MIRROR": ["MIRROR", "对称"],
|
|
212
|
+
"PULSE": ["PULSE", "呼吸"],
|
|
213
|
+
"STACK": ["STACK", "堆叠"],
|
|
214
|
+
"RELAY": ["RELAY", "接力"],
|
|
215
|
+
"SPLIT": ["SPLIT", "分岔"],
|
|
183
216
|
};
|
|
184
217
|
const storageKey = "ccdx.dashboard.language";
|
|
185
218
|
let language = "en";
|
|
@@ -189,7 +222,7 @@
|
|
|
189
222
|
const attributes = { textContent: "data-i18n", title: "data-i18n-title", "aria-label": "data-i18n-label" };
|
|
190
223
|
|
|
191
224
|
function format(key, values = {}) {
|
|
192
|
-
const template = language === "zh" ?
|
|
225
|
+
const template = Object.hasOwn(translations, key) ? translations[key][language === "zh" ? 1 : 0] : key;
|
|
193
226
|
return String(template).replace(/\{(\w+)\}/g, (match, name) => {
|
|
194
227
|
if (!Object.hasOwn(values, name)) return match;
|
|
195
228
|
const value = values[name];
|
|
@@ -219,7 +252,7 @@
|
|
|
219
252
|
}
|
|
220
253
|
const button = document.getElementById("language-toggle");
|
|
221
254
|
button.textContent = language === "en" ? "中文" : "EN";
|
|
222
|
-
const label = language === "en" ? "Switch to Chinese" : "
|
|
255
|
+
const label = language === "en" ? "Switch to Chinese" : "切换英文";
|
|
223
256
|
button.setAttribute("aria-label", label);
|
|
224
257
|
button.title = label;
|
|
225
258
|
}
|
package/src/dashboard/ui.css
CHANGED
|
@@ -72,6 +72,7 @@ h1 span { color: var(--accent-soft); }
|
|
|
72
72
|
.section-actions { display: flex; align-items: center; gap: 15px; margin-top: 16px; }
|
|
73
73
|
.section-actions span { color: var(--muted); font-size: 11px; }
|
|
74
74
|
.table-note { margin: 15px 0 8px; color: var(--muted); font-size: 11px; }
|
|
75
|
+
.card p, .hint, .table-note, .section-actions span, .chart-heading span { white-space: pre-line; }
|
|
75
76
|
.table-wrap { width: 100%; overflow-x: auto; }
|
|
76
77
|
table { width: 100%; border-collapse: collapse; font-size: 11px; }
|
|
77
78
|
th { color: var(--heading); text-align: left; font-weight: 700; letter-spacing: .05em; }
|
package/src/dashboard/ui.js
CHANGED
|
@@ -81,7 +81,11 @@ function renderFailures(recent, recentRequests = []) {
|
|
|
81
81
|
details.open = expanded.has(details.dataset.key);
|
|
82
82
|
const title = document.createElement("summary");
|
|
83
83
|
localize(title, "{detail} / {retry}", {
|
|
84
|
-
detail:
|
|
84
|
+
detail: phrase("{time} / {model} / {code}", {
|
|
85
|
+
time: failure.at ? String(failure.at) : phrase("unknown time"),
|
|
86
|
+
model: failure.model ? String(failure.model).slice(0, 80) : phrase("unknown_model"),
|
|
87
|
+
code: failure.code ? String(failure.code).slice(0, 80) : phrase("unknown_error"),
|
|
88
|
+
}),
|
|
85
89
|
retry: phrase(failure.retried ? "retry attempted" : "no retry"),
|
|
86
90
|
});
|
|
87
91
|
const timeline = failure.timeline;
|
|
@@ -311,7 +315,9 @@ function buildAnimationOptions(data) {
|
|
|
311
315
|
});
|
|
312
316
|
const name = document.createElement("span");
|
|
313
317
|
name.className = "theme-name";
|
|
314
|
-
|
|
318
|
+
const label = document.createElement("span");
|
|
319
|
+
localize(label, "{index} {theme}", { index: String(index + 1).padStart(2, "0"), theme: phrase(theme.label) });
|
|
320
|
+
name.append(label);
|
|
315
321
|
if (theme.default) {
|
|
316
322
|
const marker = document.createElement("small");
|
|
317
323
|
localize(marker, "DEFAULT");
|
|
@@ -365,7 +371,7 @@ async function loadAnimation() {
|
|
|
365
371
|
}
|
|
366
372
|
|
|
367
373
|
function updateAnimationState() {
|
|
368
|
-
text("animation-state", "CURRENT {theme}{unsaved}", { theme: savedAnimation.toUpperCase(), unsaved: selectedAnimation !== savedAnimation ? phrase(" / UNSAVED") : "" });
|
|
374
|
+
text("animation-state", "CURRENT {theme}{unsaved}", { theme: phrase(savedAnimation.toUpperCase()), unsaved: selectedAnimation !== savedAnimation ? phrase(" / UNSAVED") : "" });
|
|
369
375
|
}
|
|
370
376
|
|
|
371
377
|
async function saveAnimation() {
|
|
@@ -435,7 +441,10 @@ async function loadModels() {
|
|
|
435
441
|
text("models-note", "{selectable} selectable / {advertised} advertised / {host} / {time}", { selectable: number(data.selectable), advertised: number(data.advertised), host: data.upstream_host, time: new Date(data.checked_at).toLocaleTimeString() });
|
|
436
442
|
} catch (error) {
|
|
437
443
|
text("models-state", "LIVE LOOKUP FAILED");
|
|
438
|
-
|
|
444
|
+
const message = String(error.message || error).slice(0, 240);
|
|
445
|
+
const httpError = /^Live model lookup failed \(HTTP (\d{3})\)\. Run ccdx models for details\.$/.exec(message);
|
|
446
|
+
if (httpError) text("models-note", "Live model lookup failed (HTTP {status}). Run ccdx models for details.", { status: httpError[1] });
|
|
447
|
+
else text("models-note", message);
|
|
439
448
|
emptyTable("live-models-body", 4, "No live catalog available.");
|
|
440
449
|
} finally {
|
|
441
450
|
button.disabled = false;
|