dsh-ssh-tui 0.3.7 → 0.3.9
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.en.md +49 -28
- package/README.md +29 -14
- package/lib/i18n/en.js +429 -0
- package/lib/i18n/en.js.map +1 -0
- package/lib/i18n/index.js +94 -0
- package/lib/i18n/index.js.map +1 -0
- package/lib/i18n/zh.js +429 -0
- package/lib/i18n/zh.js.map +1 -0
- package/lib/index.js +71 -8
- package/lib/index.js.map +1 -1
- package/lib/picker.js +5 -4
- package/lib/picker.js.map +1 -1
- package/lib/route-memory.js +23 -4
- package/lib/route-memory.js.map +1 -1
- package/lib/session-list.js +46 -0
- package/lib/session-list.js.map +1 -1
- package/lib/session-lock.js +3 -6
- package/lib/session-lock.js.map +1 -1
- package/lib/subagent-model.js +81 -14
- package/lib/subagent-model.js.map +1 -1
- package/lib/supergrok-token.js +132 -0
- package/lib/supergrok-token.js.map +1 -0
- package/lib/tui.js +950 -346
- package/lib/tui.js.map +1 -1
- package/lib/types/i18n/en.d.ts +2 -0
- package/lib/types/i18n/index.d.ts +28 -0
- package/lib/types/i18n/zh.d.ts +2 -0
- package/lib/types/route-memory.d.ts +10 -0
- package/lib/types/session-list.d.ts +16 -0
- package/lib/types/subagent-model.d.ts +28 -2
- package/lib/types/supergrok-token.d.ts +22 -0
- package/lib/types/tui.d.ts +123 -3
- package/lib/update-check.js +2 -1
- package/lib/update-check.js.map +1 -1
- package/package.json +1 -1
package/lib/i18n/en.js
ADDED
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
/** English UI catalog. Keys match `zh.ts`. */
|
|
2
|
+
export const en = {
|
|
3
|
+
'route.deepseek': 'DeepSeek official',
|
|
4
|
+
'route.supergrokKind': 'SuperGrok / X Premium subscription',
|
|
5
|
+
'route.supergrokShort': 'SuperGrok',
|
|
6
|
+
'route.go': 'OpenCode Go',
|
|
7
|
+
'route.zen': 'OpenCode Zen',
|
|
8
|
+
'route.registered': 'Registered provider',
|
|
9
|
+
'paint.localMs': 'Local paint {ms}ms',
|
|
10
|
+
'paint.sshMs': 'SSH paint {ms}ms',
|
|
11
|
+
'paint.sshMsUnprobed': 'SSH paint {ms}ms (RTT not measured)',
|
|
12
|
+
'paint.localChip': 'Local {pips}',
|
|
13
|
+
'paint.sshChip': 'SSH {pips} {delay}',
|
|
14
|
+
'footer.turnsSteps': '{turns} turns · {steps} steps',
|
|
15
|
+
'footer.tokens': 'in {input} · out {output}',
|
|
16
|
+
'footer.ttft': 'TTFT {duration}',
|
|
17
|
+
'footer.llmMs': 'model {duration}',
|
|
18
|
+
'footer.toolMs': 'tools {duration}',
|
|
19
|
+
'footer.cacheHit': 'cache hit {percent}%',
|
|
20
|
+
'footer.planReview': 'plan review',
|
|
21
|
+
'footer.waiting': 'waiting',
|
|
22
|
+
'footer.compacting': 'compacting',
|
|
23
|
+
'footer.retry': 'retry {retry}/{max}',
|
|
24
|
+
'footer.subagents': 'subagents {count}',
|
|
25
|
+
'footer.tools': 'tools {count}',
|
|
26
|
+
'footer.planOpen': 'turn left open',
|
|
27
|
+
'footer.planSwitching': 'switching plan',
|
|
28
|
+
'footer.planMode': 'plan mode',
|
|
29
|
+
'footer.goalActive': 'goal active',
|
|
30
|
+
'footer.goalPaused': 'goal paused',
|
|
31
|
+
'footer.goalBlocked': 'goal blocked',
|
|
32
|
+
'footer.waitSeconds': 'waiting {seconds}s',
|
|
33
|
+
'footer.running': 'running',
|
|
34
|
+
'footer.idle': 'idle',
|
|
35
|
+
'footer.search': 'search {index}/{total}',
|
|
36
|
+
'footer.inputFolded': 'input folded',
|
|
37
|
+
'footer.multiLine': 'multiline',
|
|
38
|
+
'footer.queued': 'queued {count}',
|
|
39
|
+
'footer.cwdChip': 'dir:{name}',
|
|
40
|
+
'footer.effortDefault': 'follow provider default',
|
|
41
|
+
'status.quotaNone': 'quota: none',
|
|
42
|
+
'status.quotaLine': 'quota: {plan} {parts}',
|
|
43
|
+
'status.questionsWaiting': 'questions: waiting {count}',
|
|
44
|
+
'status.questionsNone': 'questions: none',
|
|
45
|
+
'status.planOff': 'off',
|
|
46
|
+
'status.planPending': 'pending',
|
|
47
|
+
'status.planOn': 'on',
|
|
48
|
+
'sub.followParent': 'follow parent',
|
|
49
|
+
'sub.pinned': 'pinned {provider}',
|
|
50
|
+
'sub.sameFamily': 'same family',
|
|
51
|
+
'sub.crossFamily': 'cross-family',
|
|
52
|
+
'sub.light': 'light',
|
|
53
|
+
'sub.expensiveNoLight': 'expensive (no light model)',
|
|
54
|
+
'sub.expensive': 'expensive',
|
|
55
|
+
'sub.line': 'subagent: {model} · {follow} · {fit}',
|
|
56
|
+
'quota.alert': '⚠ {plan} {period} quota is down to {percent}%{reset}. Plan remaining usage.',
|
|
57
|
+
'quota.periodHourly': '5-hour',
|
|
58
|
+
'quota.periodWeekly': 'weekly',
|
|
59
|
+
'quota.periodMonthly': 'monthly',
|
|
60
|
+
'quota.periodUnknown': 'cycle',
|
|
61
|
+
'quota.resetIn': 'resets in ~{duration}',
|
|
62
|
+
'quota.resetAt': 'reset at {when}',
|
|
63
|
+
'quota.resetInParen': ' (resets in ~{duration})',
|
|
64
|
+
'quota.throttled': 'throttled',
|
|
65
|
+
'quota.ok': 'ok',
|
|
66
|
+
'quota.unknown': 'unknown',
|
|
67
|
+
'quota.windowHourly': 'rolling 5h',
|
|
68
|
+
'quota.windowWeekly': 'this week',
|
|
69
|
+
'quota.windowMonthly': 'this month',
|
|
70
|
+
'quota.snapshotHeader': '{plan} quota ({provider})',
|
|
71
|
+
'quota.snapshotWindow': ' {label} · {bar} remaining {percent}%{reset}',
|
|
72
|
+
'quota.unrecognized': 'quota payload was not recognized',
|
|
73
|
+
'quota.supergrokUnrecognized': 'SuperGrok quota payload was not recognized',
|
|
74
|
+
'quota.deepseekUnrecognized': 'DeepSeek balance payload was not recognized',
|
|
75
|
+
'balance.available': 'available',
|
|
76
|
+
'balance.granted': 'granted',
|
|
77
|
+
'balance.topped': 'topped up',
|
|
78
|
+
'balance.remaining': 'remaining',
|
|
79
|
+
'balance.total': 'total',
|
|
80
|
+
'balance.used': 'used',
|
|
81
|
+
'balance.hard': 'hard limit',
|
|
82
|
+
'balance.soft': 'soft limit',
|
|
83
|
+
'balance.generic': 'balance',
|
|
84
|
+
'balance.header': '{plan} balance ({provider})',
|
|
85
|
+
'balance.unavailable': 'account currently unavailable',
|
|
86
|
+
'balance.source': ' source {path}',
|
|
87
|
+
'toolTitle.edit': 'edit',
|
|
88
|
+
'toolTitle.write': 'write',
|
|
89
|
+
'toolTitle.str_replace_editor': 'replace',
|
|
90
|
+
'toolTitle.fetch': 'fetch',
|
|
91
|
+
'toolTitle.list_files': 'list files',
|
|
92
|
+
'toolTitle.list': 'list files',
|
|
93
|
+
'toolTitle.ls': 'list files',
|
|
94
|
+
'toolTitle.find': 'find files',
|
|
95
|
+
'toolTitle.search': 'web search',
|
|
96
|
+
'toolTitle.delete': 'delete',
|
|
97
|
+
'toolTitle.rm': 'delete',
|
|
98
|
+
'toolTitle.rename': 'rename',
|
|
99
|
+
'toolTitle.mv': 'rename',
|
|
100
|
+
'toolTitle.mkdir': 'mkdir',
|
|
101
|
+
'toolTitle.skills': 'skills',
|
|
102
|
+
'toolTitle.create_goal': 'create goal',
|
|
103
|
+
'toolTitle.update_goal': 'update goal',
|
|
104
|
+
'toolTitle.complete_goal': 'complete goal',
|
|
105
|
+
'toolTitle.clear_goal': 'clear goal',
|
|
106
|
+
'toolTitle.pause_goal': 'pause goal',
|
|
107
|
+
'toolTitle.resume_goal': 'resume goal',
|
|
108
|
+
'toolTitle.todo_write': 'update todos',
|
|
109
|
+
'toolTitle.todo': 'update todos',
|
|
110
|
+
'toolTitle.compact': 'compact',
|
|
111
|
+
'toolTitle.glob': 'glob',
|
|
112
|
+
'toolTitle.grep': 'search',
|
|
113
|
+
'toolTitle.read': 'read',
|
|
114
|
+
'toolTitle.web_search': 'web search',
|
|
115
|
+
'toolTitle.web_fetch': 'fetch',
|
|
116
|
+
'toolTitle.subagent': 'subagent',
|
|
117
|
+
'toolTitle.subagent_fork': 'subagent fork',
|
|
118
|
+
'toolTitle.ask_user_question': 'ask user',
|
|
119
|
+
'toolTitle.exit_plan_mode': 'submit plan',
|
|
120
|
+
'toolTitle.get_goal': 'view goal',
|
|
121
|
+
'card.thinking': 'thinking',
|
|
122
|
+
'card.plan': 'plan',
|
|
123
|
+
'card.subagent': 'subagent',
|
|
124
|
+
'card.reply': 'reply',
|
|
125
|
+
'card.tool': 'tool',
|
|
126
|
+
'card.question': 'question',
|
|
127
|
+
'card.goal': 'goal',
|
|
128
|
+
'card.prompt': 'prompt',
|
|
129
|
+
'card.expand': ' · Enter to expand',
|
|
130
|
+
'prompt.systemPreset': 'system preset',
|
|
131
|
+
'prompt.context': 'context',
|
|
132
|
+
'prompt.inject': 'prompt inject',
|
|
133
|
+
'prompt.injectWith': 'prompt inject:{sources}',
|
|
134
|
+
'plan.nudge': 'The plan strip still has unfinished todos at turn end. Call todo_write once now: mark finished items completed and leave the rest pending. Do not add new tasks.',
|
|
135
|
+
'plan.leftOpen': 'Turn left open: {count} todos remaining (session log unchanged).',
|
|
136
|
+
'plan.pendingNext': 'Mode switch takes effect on the next step.',
|
|
137
|
+
'plan.planningOnly': 'Plan only, no code changes until you confirm.',
|
|
138
|
+
'plan.executing': 'Executing the plan.',
|
|
139
|
+
'plan.allDone': 'All plan tasks completed.',
|
|
140
|
+
'plan.stillOpen': 'Plan still open; not everything is done.',
|
|
141
|
+
'plan.closed': 'Plan mode is off. Use /plan to re-enter.',
|
|
142
|
+
'plan.todoDone': '{count} done',
|
|
143
|
+
'plan.todoActive': '{count} in progress',
|
|
144
|
+
'plan.todoPending': '{count} pending',
|
|
145
|
+
'plan.list': 'todo list',
|
|
146
|
+
'plan.todoSummary': '{done}/{total} done',
|
|
147
|
+
'plan.waitConfirm': 'waiting to confirm the plan',
|
|
148
|
+
'plan.emptyBody': 'plan body is empty',
|
|
149
|
+
'plan.reviewing': 'plan review',
|
|
150
|
+
'plan.switching': 'switching',
|
|
151
|
+
'plan.complete': 'plan done',
|
|
152
|
+
'plan.archived': 'archived',
|
|
153
|
+
'plan.header': 'plan · {summary}',
|
|
154
|
+
'plan.moreLines': ' … {count} more plan lines',
|
|
155
|
+
'plan.noTodos': ' no todo list yet',
|
|
156
|
+
'plan.noTasks': 'no tasks yet',
|
|
157
|
+
'plan.entered': 'Entered plan mode: plan first, wait for confirmation, then change code. /plan off to exit.',
|
|
158
|
+
'plan.exited': 'Left plan mode; you can apply changes.',
|
|
159
|
+
'plan.requestOn': 'Requested plan mode.',
|
|
160
|
+
'plan.requestOff': 'Requested leaving plan mode.',
|
|
161
|
+
'plan.enterMode': 'enter plan mode',
|
|
162
|
+
'plan.exitMode': 'leave plan mode',
|
|
163
|
+
'plan.nudgeQueued': 'Asked the model to close leftover todos (once this turn).',
|
|
164
|
+
'plan.nudgeFailed': 'Failed to nudge todos: {error}',
|
|
165
|
+
'todo.list': 'todos',
|
|
166
|
+
'todo.empty': 'no tasks yet',
|
|
167
|
+
'todo.doneMark': 'done',
|
|
168
|
+
'todo.interrupted': 'interrupted',
|
|
169
|
+
'todo.failed': 'failed',
|
|
170
|
+
'ask.multi': '{text} ({count} questions)',
|
|
171
|
+
'tool.signal': ' [signal {signal}]',
|
|
172
|
+
'tool.exitCode': ' [exit {code}]',
|
|
173
|
+
'tool.noOutput': '(no output)',
|
|
174
|
+
'tool.args': 'args',
|
|
175
|
+
'tool.result': 'result',
|
|
176
|
+
'tool.reading': 'reading…',
|
|
177
|
+
'tool.inspectTitle': 'full tool · {title}',
|
|
178
|
+
'tool.inspectHint': 'PgUp/PgDn/wheel to scroll · Esc back to session',
|
|
179
|
+
'tool.inspectFooter': 'full {pos} · Esc to return',
|
|
180
|
+
'mode.standard': 'standard',
|
|
181
|
+
'boot.help': 'Type /help for keys · /find searches thinking/plan/subagent/reply · empty ↑/↓ selects cards',
|
|
182
|
+
'cwd.entered': 'Entered session working directory {cwd}',
|
|
183
|
+
'cwd.notAbsolute': 'Session working directory is not absolute: {path}',
|
|
184
|
+
'cwd.missing': 'Session working directory does not exist: {path}',
|
|
185
|
+
'cwd.failed': 'Could not enter session working directory {path}: {error}',
|
|
186
|
+
'cwd.full': 'working directory {cwd}',
|
|
187
|
+
'onboard.checkFailed': 'First-run setup check failed: {error}',
|
|
188
|
+
'onboard.syncSubFailed': 'Failed to sync subagent model: {error}',
|
|
189
|
+
'onboard.oauthHint': 'This is {kind} ({provider}) using local SuperGrok / X Premium OAuth — no API key. /model switches Grok model and effort; /provider switches to official or OpenCode. Use /setup only to add an API-key provider.',
|
|
190
|
+
'onboard.envInUse': 'Using {env} (environment / launch env file). /setup anytime to change it.',
|
|
191
|
+
'onboard.envStale': 'System already injected {env} (it may be stale). First-run wizard will overwrite your key; restart the TUI after save.',
|
|
192
|
+
'onboard.needSetup': 'First launch: configure a provider and API key (/setup anytime).',
|
|
193
|
+
'onboard.title': 'First-run wizard — pick a provider (same as the official Models page)',
|
|
194
|
+
'onboard.opt1': ' 1 DeepSeek official (api.deepseek.com)',
|
|
195
|
+
'onboard.opt2': ' 2 OpenCode Go (opencode.ai/zen/go, Responses)',
|
|
196
|
+
'onboard.opt3': ' 3 Custom OpenAI-compatible gateway (Completions)',
|
|
197
|
+
'onboard.opt4': ' 4 Custom OpenAI Responses gateway',
|
|
198
|
+
'onboard.opt5': ' 5 Anthropic Messages-compatible gateway',
|
|
199
|
+
'onboard.pickHint': ' Press 1-5, Esc to cancel',
|
|
200
|
+
'onboard.providerLine': 'Provider: {label}',
|
|
201
|
+
'onboard.idPrompt': 'Provider ID (lowercase letters/digits/hyphens, permanent):',
|
|
202
|
+
'onboard.default': ' default: {value}',
|
|
203
|
+
'onboard.enterEsc': ' Enter to confirm, Esc to cancel',
|
|
204
|
+
'onboard.keyPrompt': 'API Key (shown as •):',
|
|
205
|
+
'onboard.basePrompt': 'Base URL (empty uses {fallback}):',
|
|
206
|
+
'onboard.baseFallback': 'official/template default',
|
|
207
|
+
'onboard.modelsPrompt': 'Model IDs (comma or space separated):',
|
|
208
|
+
'onboard.modelsFetched': ' fetched ({count}): {list}',
|
|
209
|
+
'onboard.ctrlF': ' Ctrl+F = fetch model list from endpoint',
|
|
210
|
+
'onboard.confirmTitle': 'Save this configuration?',
|
|
211
|
+
'onboard.confirmProvider': ' provider: {label}',
|
|
212
|
+
'onboard.confirmBase': ' Base URL: {url}',
|
|
213
|
+
'onboard.confirmApi': ' API: {api}',
|
|
214
|
+
'onboard.confirmModels': ' models: {list}',
|
|
215
|
+
'onboard.confirmKey': ' API Key: {head}…{tail} (length {length})',
|
|
216
|
+
'onboard.confirmHint': ' y = save, n = redo, Esc = cancel',
|
|
217
|
+
'onboard.defaultParen': '(default)',
|
|
218
|
+
'onboard.providerCompletions': 'Custom OpenAI-compatible gateway (Completions)',
|
|
219
|
+
'onboard.providerResponses': 'Custom OpenAI Responses gateway',
|
|
220
|
+
'onboard.providerAnthropic': 'Anthropic Messages-compatible gateway',
|
|
221
|
+
'onboard.providerGo': 'OpenCode Go (opencode.ai/zen/go)',
|
|
222
|
+
'onboard.idInvalid': 'Provider ID may only contain lowercase letters, digits, and hyphens, and must not start with a hyphen.',
|
|
223
|
+
'onboard.keyEmpty': 'API Key cannot be empty.',
|
|
224
|
+
'onboard.needModel': 'At least one model ID is required.',
|
|
225
|
+
'onboard.needBase': 'Fill in the Base URL before fetching models.',
|
|
226
|
+
'onboard.fetchingModels': 'Fetching models from the endpoint…',
|
|
227
|
+
'onboard.llmMissing': 'llm service is unavailable',
|
|
228
|
+
'onboard.noModels': 'Endpoint returned no models; enter IDs manually.',
|
|
229
|
+
'onboard.fetchedModels': 'Fetched {count} models: {list} (Enter to confirm, or keep editing).',
|
|
230
|
+
'onboard.fetchFailed': 'Failed to fetch models: {error}',
|
|
231
|
+
'onboard.baseSaved': 'Base URL saved → {path}',
|
|
232
|
+
'onboard.officialDone': 'Saved deepseek-official / {model}. /provider switches other saved routes without /setup.',
|
|
233
|
+
'onboard.settingsMissing': 'settings service unavailable; custom provider was not saved.',
|
|
234
|
+
'onboard.providerSaved': 'Provider {id} saved → {path}',
|
|
235
|
+
'onboard.customDone': 'Saved {id} / {model}. Other providers keep their models and keys; /provider switches on the next request.',
|
|
236
|
+
'onboard.saveFailed': 'Failed to save config: {error}',
|
|
237
|
+
'onboard.credSaved': '{env} saved → {path}',
|
|
238
|
+
'onboard.envShadowWin': 'Environment variable {env} already wins; overwrote via setx + env.cmd. Open a new terminal.',
|
|
239
|
+
'onboard.envShadowUnix': 'Environment variable {env} already wins; wrote a launch-env override. Open a new terminal.',
|
|
240
|
+
'onboard.credMissing': 'credentials service unavailable; wrote a launch-env override → {path}',
|
|
241
|
+
'dialog.planReview': 'plan review {index}/{total}',
|
|
242
|
+
'dialog.ask': 'ask user {index}/{total}: {question}',
|
|
243
|
+
'dialog.recommended': ' (recommended)',
|
|
244
|
+
'dialog.freeform': ' (freeform: type below and press Enter)',
|
|
245
|
+
'dialog.multiHint': ' digits/letters toggle, Enter submits, Esc cancels',
|
|
246
|
+
'dialog.singleHint': ' digits/letters select, Enter submits, Esc cancels',
|
|
247
|
+
'dialog.scrolled': '↑ scrolled {count} lines · PgUp/PgDn/wheel · Esc to bottom',
|
|
248
|
+
'reason.done': '{marker} thought · {lines} lines',
|
|
249
|
+
'reason.live': '{marker} thinking {spinner} · {chars} chars',
|
|
250
|
+
'reason.elapsed': ' · {seconds}s',
|
|
251
|
+
'sub.cardWait': ' waiting for subagent output…',
|
|
252
|
+
'sub.cardEmpty': ' no visible output',
|
|
253
|
+
'sub.cardSession': ' session {id} · {provider}{external}',
|
|
254
|
+
'sub.external': ' · external process',
|
|
255
|
+
'sub.stopReason': ' stop reason: {reason}',
|
|
256
|
+
'sub.started': 'started',
|
|
257
|
+
'sub.startedDetail': 'started ({provider}{external})',
|
|
258
|
+
'sub.ended': 'ended ({reason})',
|
|
259
|
+
'sub.label': 'subagent {provider}',
|
|
260
|
+
'sub.turnEnd': 'turn ended ({reason})',
|
|
261
|
+
'sub.approval': 'waiting for approval: {tool}',
|
|
262
|
+
'sub.listLine': '▶ {label} {id} ({provider}) running {seconds}s [{run}]{activity}',
|
|
263
|
+
'sub.listHint': '{lines}\nEmpty ↑/↓ selects cards, Enter expands; Alt+3 jumps to the latest subagent.',
|
|
264
|
+
'sub.none': 'No active subagents.',
|
|
265
|
+
'sub.killNeedId': '/subagents kill <session-id> — missing subagent session id',
|
|
266
|
+
'sub.killRequested': 'Requested release of subagents: {ids}',
|
|
267
|
+
'sub.unknownAction': '/subagents unknown action "{action}" (list / kill <id>)',
|
|
268
|
+
'sub.followed': 'Subagent followed provider {provider}; model is now {model}{sessionOnly}',
|
|
269
|
+
'sub.sessionOnly': ' (this session only)',
|
|
270
|
+
'sub.settingsMissing': 'settings service unavailable; subagent choice is this session only.',
|
|
271
|
+
'sub.fetchingModels': 'Fetching subagent models ({provider})…',
|
|
272
|
+
'sub.modelFollow': 'Subagent model: {model} (provider follows parent {provider}).',
|
|
273
|
+
'sub.modelPinned': 'Subagent model: {model} (provider {provider}).',
|
|
274
|
+
'sub.effortUnset': 'Model {provider}/{model} declares no reasoning effort; kept the provider default. Do not set high/max by hand.',
|
|
275
|
+
'sub.pickEffort': 'Subagent reasoning effort ({provider}/{model})',
|
|
276
|
+
'sub.effortFollowHint': 'Clear custom effort; follow provider/model default',
|
|
277
|
+
'sub.effortRestored': 'Subagent effort restored to the provider default.',
|
|
278
|
+
'sub.effortSet': 'Subagent effort: {id}.',
|
|
279
|
+
'goal.active': 'active',
|
|
280
|
+
'goal.paused': 'paused',
|
|
281
|
+
'goal.blocked': 'blocked',
|
|
282
|
+
'goal.complete': 'complete',
|
|
283
|
+
'goal.cleared': 'cleared',
|
|
284
|
+
'goal.header': '● goal{spinner} · {phase} · {objective}',
|
|
285
|
+
'goal.help': ' Use /goal to view, pause, resume, or clear the current goal.',
|
|
286
|
+
'goal.unnamed': '(unnamed goal)',
|
|
287
|
+
'goal.clearedLabel': '(cleared)',
|
|
288
|
+
'goal.clearedNotice': 'Current goal cleared.',
|
|
289
|
+
'goal.set': 'Goal set',
|
|
290
|
+
'goal.pausedNotice': 'Goal paused',
|
|
291
|
+
'goal.blockedNotice': 'Goal blocked',
|
|
292
|
+
'goal.doneNotice': 'Goal complete',
|
|
293
|
+
'question.waiting': 'waiting',
|
|
294
|
+
'question.answered': 'answered',
|
|
295
|
+
'question.cancelled': 'cancelled',
|
|
296
|
+
'question.planTitle': 'plan review',
|
|
297
|
+
'question.askTitle': 'ask user',
|
|
298
|
+
'question.dialogHint': ' Use the dialog below; digits/letters select, Enter submits, Esc cancels.',
|
|
299
|
+
'compact.recoverTokens': 'recovered {tokens} tokens',
|
|
300
|
+
'compact.pruneChunks': 'pruned {count} chunks',
|
|
301
|
+
'compact.prepare': 'preparing summary',
|
|
302
|
+
'compact.running': 'compacting · {detail}',
|
|
303
|
+
'compact.failed': 'compact failed · {error}',
|
|
304
|
+
'compact.done': 'compacted · {detail}',
|
|
305
|
+
'compact.status': 'compacting…',
|
|
306
|
+
'compact.bodyRunning': ' Compacting session context; old tool results will be replaced by a summary.',
|
|
307
|
+
'compact.bodyError': ' {error}',
|
|
308
|
+
'compact.bodyDone': ' Compact wrote to the session log; the next turn sees a shorter history.',
|
|
309
|
+
'compact.finished': 'Context compact finished.',
|
|
310
|
+
'compact.failedNotice': 'Context compact failed: {error}',
|
|
311
|
+
'compact.short': 'compact',
|
|
312
|
+
'jump.planDock': 'Jumped to {category} (plan strip).',
|
|
313
|
+
'jump.missing': 'No {category} card right now.',
|
|
314
|
+
'jump.latest': 'Jumped to the latest {category}.',
|
|
315
|
+
'find.none': 'Nothing to search.',
|
|
316
|
+
'find.noMatch': 'No cards matching “{query}”.',
|
|
317
|
+
'find.hits': 'Found {count}{query} · {count}/{count} ({where}). Ctrl+G / Alt+N next, Alt+P previous.',
|
|
318
|
+
'find.empty': 'No search hits yet. /find thinking padAnsi, or Ctrl+/ to search.',
|
|
319
|
+
'find.step': 'Search “{query}” · {index}/{total} ({where}).',
|
|
320
|
+
'title.done': '\x1b]0;dsh ✓ done{suffix}\x07',
|
|
321
|
+
'title.waitAnswer': 'waiting for answer',
|
|
322
|
+
'title.subagents': 'running · subagents {count}',
|
|
323
|
+
'title.tools': 'running · tools {count}',
|
|
324
|
+
'title.idle': '\x1b]0;dsh idle{suffix}\x07',
|
|
325
|
+
'stall.warning': 'Model/tools silent for a long time. Esc or Ctrl+C cancels the turn.',
|
|
326
|
+
'stream.interrupted': ' ⚠ interrupted',
|
|
327
|
+
'stream.interruptedEmpty': 'Turn interrupted; nothing visible.',
|
|
328
|
+
'retry.generatingTitle': 'Generating a session title…',
|
|
329
|
+
'retry.busy': 'Model request failed, retrying',
|
|
330
|
+
'retry.progress': 'Model request failed, retry {retry}/{max} in {ms}ms: {message}',
|
|
331
|
+
'retry.started': 'Starting retry {retry}.',
|
|
332
|
+
'team.event': '[team] {type}',
|
|
333
|
+
'command.failed': 'Command failed.',
|
|
334
|
+
'command.images': ' (images ok)',
|
|
335
|
+
'approval.prompt': 'Allow tool "{tool}"? ({agent}){reason}',
|
|
336
|
+
'approval.hint': 'y = allow once, n = deny, Esc = cancel',
|
|
337
|
+
'approval.thisSession': 'this session',
|
|
338
|
+
'steer.queued': '⚡ {text} (queued while running; Esc/Ctrl+C cancels)',
|
|
339
|
+
'cancel.esc': 'Requested cancel of the current turn…',
|
|
340
|
+
'cancel.ctrlC': 'Requested cancel of the current turn… (Ctrl+C)',
|
|
341
|
+
'clear.transcript': 'Transcript cleared. Subagent, plan, and question cards reappear when new events arrive.',
|
|
342
|
+
'model.added': 'Model {model} added to provider {provider}.',
|
|
343
|
+
'model.addFailed': 'Could not write model {model} into the provider config: {error}',
|
|
344
|
+
'model.prevPage': '« previous',
|
|
345
|
+
'model.nextPage': '» next',
|
|
346
|
+
'model.current': 'current',
|
|
347
|
+
'model.pick': 'Pick a model (provider {provider} · {source}{pages})',
|
|
348
|
+
'model.configured': 'configured list',
|
|
349
|
+
'model.fetching': 'Fetching {provider} models from the endpoint…',
|
|
350
|
+
'model.live': 'live endpoint list',
|
|
351
|
+
'model.xaiCatalog': 'SuperGrok catalog',
|
|
352
|
+
'model.switched': 'Switched to {kind}: {provider}/{model} (effort {effort}{undeclared}); next request.',
|
|
353
|
+
'model.effortDefault': 'default',
|
|
354
|
+
'model.undeclared': ', this model declares no effort options',
|
|
355
|
+
'model.pickEffort': 'Reasoning effort ({model})',
|
|
356
|
+
'model.persistFailSettings': 'Could not persist the default: agentDefaultModel unavailable and settings write failed ({error}). This session only; restart falls back.',
|
|
357
|
+
'model.persistFailNone': 'Could not persist the default: settings service unavailable. This session only.',
|
|
358
|
+
'provider.none': 'No providers to switch. /setup an API-key route first.',
|
|
359
|
+
'provider.pick': 'Pick a provider',
|
|
360
|
+
'provider.currentKind': '{kind} · current',
|
|
361
|
+
'mode.pick': 'Pick a mode',
|
|
362
|
+
'mode.currentPrefix': 'current · ',
|
|
363
|
+
'mode.switched': 'Mode: {name} (this session).',
|
|
364
|
+
'mode.remembered': 'This session already has work; cannot switch mid-session. Remembered {name} for next launch.',
|
|
365
|
+
'mode.missingService': 'agentPresets service is unavailable.',
|
|
366
|
+
'mode.none': 'No modes (presets) available.',
|
|
367
|
+
'resume.running': 'A turn is running. Wait or Esc/cancel before switching sessions.',
|
|
368
|
+
'resume.same': 'Already on this session.',
|
|
369
|
+
'resume.noCallback': 'Session switch callback unavailable; cannot /resume.',
|
|
370
|
+
'resume.switching': 'Switching to session {id}…',
|
|
371
|
+
'resume.noPersistence': 'sessionPersistence service is unavailable.',
|
|
372
|
+
'resume.none': 'No resumable sessions (or /resume <session-id>).',
|
|
373
|
+
'resume.pick': 'Pick a session to resume',
|
|
374
|
+
'resume.unreadable': '⚠ unreadable · ',
|
|
375
|
+
'resume.cancelled': 'Session picker cancelled.',
|
|
376
|
+
'picker.title': 'DeepSeek Harness — pick a session to resume',
|
|
377
|
+
'picker.new': 'new session',
|
|
378
|
+
'picker.cancel': 'cancel',
|
|
379
|
+
'picker.noPersistence': 'dsh-ssh-tui: sessionPersistence service is unavailable\n',
|
|
380
|
+
'picker.none': 'dsh-ssh-tui: no resumable history sessions; starting a fresh session.\n',
|
|
381
|
+
'usage.querying': 'checking quota…',
|
|
382
|
+
'usage.none': 'Provider {provider} has no balance/quota API. DeepSeek official uses /user/balance; OpenAI-compatible gateways probe credit_grants; OpenCode Go and SuperGrok use subscription quota.',
|
|
383
|
+
'usage.sessionTokens': 'This session billed tokens: in {input} · out {output} (session stats, not invoice).',
|
|
384
|
+
'usage.sessionNone': 'No token usage recorded in this session yet.',
|
|
385
|
+
'usage.zenHeader': 'OpenCode Zen is metered ({provider})',
|
|
386
|
+
'usage.zenBody': 'Zen has no fixed quota. Check balance and invoices at https://opencode.ai/zen.',
|
|
387
|
+
'usage.noDeepseekKey': 'DEEPSEEK_API_KEY not found',
|
|
388
|
+
'usage.noCred': 'credential {env} not found',
|
|
389
|
+
'usage.pathBad': '{path}: unrecognized payload',
|
|
390
|
+
'usage.noGateway': 'OpenAI-compatible gateway had no balance API ({errors})',
|
|
391
|
+
'usage.noGrokToken': 'SuperGrok OAuth token not found (~/.grok-bridge/auth.json)',
|
|
392
|
+
'usage.noGoCred': 'OpenCode Go credential {env} not found',
|
|
393
|
+
'usage.fetchFail': 'Cannot reach {label} quota API: {error}',
|
|
394
|
+
'usage.http': '{label} quota API returned HTTP {status}',
|
|
395
|
+
'usage.goFetchFail': 'Cannot reach OpenCode quota API: {error}',
|
|
396
|
+
'usage.go401': 'OpenCode Go API key invalid or unauthorized (401){detail}',
|
|
397
|
+
'usage.go403': 'This key is not subscribed to OpenCode Go, or quota is unavailable (403){detail}',
|
|
398
|
+
'usage.goHttp': 'OpenCode Go quota API returned HTTP {status}{detail}',
|
|
399
|
+
'help.intro1': 'Enter steers while running; Esc drops selection or the turn; idle Ctrl+C exits.',
|
|
400
|
+
'help.intro2': 'Empty ↑/↓ selects cards (same as Ctrl+N/P); Enter expands (oversized bodies open a full view, Esc returns); Ctrl+R expands/collapses all; Ctrl+T folds input.',
|
|
401
|
+
'help.intro3': 'Alt+1 latest thinking · Alt+2 plan · Alt+3 subagent · Alt+4 latest reply.',
|
|
402
|
+
'help.intro4': '/find [thinking|plan|subagent|reply|prompt] query; Ctrl+/ or Alt+/ opens search, Ctrl+G / Alt+N next.',
|
|
403
|
+
'help.intro5': '/model changes model and effort for the current provider. /provider switches provider (then model); next request, no restart.',
|
|
404
|
+
'help.intro6': '/setup adds or updates one API-key provider without wiping others. SuperGrok uses local OAuth; no key.',
|
|
405
|
+
'help.intro7': '/status labels DeepSeek official, SuperGrok, OpenCode Go / Zen, plus link, quota window, and subagent family fit.',
|
|
406
|
+
'help.modelCancel': 'Model picker cancelled.',
|
|
407
|
+
'help.providerCancel': 'Provider picker cancelled.',
|
|
408
|
+
'help.submodelCancel': 'Subagent model picker cancelled.',
|
|
409
|
+
'help.subeffortCancel': 'Subagent effort picker cancelled.',
|
|
410
|
+
'help.modeCancel': 'Mode picker cancelled.',
|
|
411
|
+
'models.ellipsis': '{text}… ({count} total)',
|
|
412
|
+
'lock.held': 'Session {session} is already running as pid {pid}{tty}.\nDo not open a second TUI. If SSH dropped: tmux attach -t dsh\nIf that process is dead, delete the matching file in $DSH_HOME/tui-locks/ and start again.',
|
|
413
|
+
'lock.busy': 'Could not take session lock {path}',
|
|
414
|
+
'update.notice': 'New dsh-ssh-tui {latest} (current {current}). Update: dsh plugin --profile tui add dsh-ssh-tui',
|
|
415
|
+
'grok.refreshFail': 'SuperGrok token refresh failed (HTTP {status}{detail})',
|
|
416
|
+
'grok.writeFail': 'Could not write SuperGrok token ({path})',
|
|
417
|
+
'grok.noRefresh': 'SuperGrok token has no refresh_token; run dsh-llm-xai-oauth login --force',
|
|
418
|
+
'lang.pick': 'Interface language',
|
|
419
|
+
'lang.zh': '中文',
|
|
420
|
+
'lang.en': 'English',
|
|
421
|
+
'lang.zhDesc': 'Chinese UI (default for jump-host SSH)',
|
|
422
|
+
'lang.enDesc': 'English UI',
|
|
423
|
+
'lang.current': 'current',
|
|
424
|
+
'lang.switched': 'Interface language: {name}.',
|
|
425
|
+
'lang.unknown': 'Unknown language "{id}". Use zh or en.',
|
|
426
|
+
'lang.settingsMissing': 'settings service unavailable; language is this session only.',
|
|
427
|
+
'lang.cmd': 'switch UI language (zh / en); empty opens a picker',
|
|
428
|
+
};
|
|
429
|
+
//# sourceMappingURL=en.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"en.js","sourceRoot":"","sources":["../../src/i18n/en.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime UI locale for the SSH TUI.
|
|
3
|
+
*
|
|
4
|
+
* Order: `DSH_TUI_LANG` → settings `ssh-tui.language` (`/language`) →
|
|
5
|
+
* `LC_ALL` / `LC_MESSAGES` / `LANG`. Unrecognized and C/POSIX stay Chinese:
|
|
6
|
+
* jump-host SSH is the default audience, and CI often runs with `LANG=C`.
|
|
7
|
+
*/
|
|
8
|
+
import z from '@deepseek-ai/schemastery';
|
|
9
|
+
import { installSettingsSection, settingsNamespace } from '@deepseek-ai/dsh-settings';
|
|
10
|
+
import { en } from './en.js';
|
|
11
|
+
import { zh } from './zh.js';
|
|
12
|
+
const TABLES = { zh, en };
|
|
13
|
+
export const UI_LOCALE_NAMESPACE = settingsNamespace('ssh-tui');
|
|
14
|
+
export const UI_LOCALE_SCHEMA = z.object({
|
|
15
|
+
language: z.string(),
|
|
16
|
+
});
|
|
17
|
+
let current = resolveLocale();
|
|
18
|
+
export function localeFromTag(tag) {
|
|
19
|
+
const raw = tag.trim().toLowerCase();
|
|
20
|
+
if (raw === '')
|
|
21
|
+
return undefined;
|
|
22
|
+
if (raw === 'chinese' || raw === '中文')
|
|
23
|
+
return 'zh';
|
|
24
|
+
if (raw === 'english')
|
|
25
|
+
return 'en';
|
|
26
|
+
const primary = raw.replace(/_/gu, '-').split(/[-.]/u)[0] ?? '';
|
|
27
|
+
if (primary === 'c' || primary === 'posix')
|
|
28
|
+
return undefined;
|
|
29
|
+
if (primary === 'en')
|
|
30
|
+
return 'en';
|
|
31
|
+
if (primary === 'zh')
|
|
32
|
+
return 'zh';
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
/** Pick zh/en from env, optionally after a saved settings value. */
|
|
36
|
+
export function resolveLocale(env = process.env, saved) {
|
|
37
|
+
const override = localeFromTag(env.DSH_TUI_LANG ?? '');
|
|
38
|
+
if (override !== undefined)
|
|
39
|
+
return override;
|
|
40
|
+
const fromSaved = localeFromTag(saved ?? '');
|
|
41
|
+
if (fromSaved !== undefined)
|
|
42
|
+
return fromSaved;
|
|
43
|
+
for (const key of ['LC_ALL', 'LC_MESSAGES', 'LANG']) {
|
|
44
|
+
const fromEnv = localeFromTag(env[key] ?? '');
|
|
45
|
+
if (fromEnv !== undefined)
|
|
46
|
+
return fromEnv;
|
|
47
|
+
}
|
|
48
|
+
return 'zh';
|
|
49
|
+
}
|
|
50
|
+
export function getLocale() {
|
|
51
|
+
return current;
|
|
52
|
+
}
|
|
53
|
+
export function setLocale(locale) {
|
|
54
|
+
current = locale;
|
|
55
|
+
}
|
|
56
|
+
export function t(key, vars, fallback) {
|
|
57
|
+
const template = TABLES[current][key] ?? TABLES.zh[key];
|
|
58
|
+
if (template === undefined)
|
|
59
|
+
return fallback ?? key;
|
|
60
|
+
if (vars === undefined)
|
|
61
|
+
return template;
|
|
62
|
+
return template.replace(/\{(\w+)\}/gu, (whole, name) => {
|
|
63
|
+
const value = vars[name];
|
|
64
|
+
return value === undefined ? whole : String(value);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
export function refreshLocale(env = process.env, saved) {
|
|
68
|
+
current = resolveLocale(env, saved);
|
|
69
|
+
return current;
|
|
70
|
+
}
|
|
71
|
+
export function applySavedLocale(raw) {
|
|
72
|
+
const saved = raw !== null && typeof raw === 'object' && !Array.isArray(raw)
|
|
73
|
+
&& typeof raw.language === 'string'
|
|
74
|
+
? raw.language
|
|
75
|
+
: undefined;
|
|
76
|
+
return refreshLocale(process.env, saved);
|
|
77
|
+
}
|
|
78
|
+
/** Register `$DSH_HOME/settings.yaml` `ssh-tui.language` and apply it now. */
|
|
79
|
+
export function installUiLocale(ctx) {
|
|
80
|
+
let source = () => ({});
|
|
81
|
+
installSettingsSection(ctx, UI_LOCALE_NAMESPACE, UI_LOCALE_SCHEMA, {}, {
|
|
82
|
+
setSource: (currentSource) => {
|
|
83
|
+
source = () => currentSource();
|
|
84
|
+
},
|
|
85
|
+
onChange: () => {
|
|
86
|
+
applySavedLocale(source());
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
applySavedLocale(source());
|
|
90
|
+
}
|
|
91
|
+
export function localeDisplayName(locale) {
|
|
92
|
+
return locale === 'en' ? t('lang.en') : t('lang.zh');
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/i18n/index.ts"],"names":[],"mappings":"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"}
|