@hncode/hncode 0.3.6 → 0.4.0

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.
Files changed (146) hide show
  1. package/package.json +4 -2
  2. package/src/agent-task.js +154 -84
  3. package/src/agent.js +533 -145
  4. package/src/clipboard.js +5 -2
  5. package/src/colors.js +242 -238
  6. package/src/config.js +217 -17
  7. package/src/file-history.js +177 -0
  8. package/src/hooks.js +11 -1
  9. package/src/i18n.js +389 -0
  10. package/src/index.js +46 -3
  11. package/src/llm.js +139 -16
  12. package/src/permissions.js +120 -0
  13. package/src/session-hub.js +407 -0
  14. package/src/session.js +31 -0
  15. package/src/term.js +19 -3
  16. package/src/tool-result.js +236 -0
  17. package/src/tools/agent.js +11 -0
  18. package/src/tools/bash.js +84 -17
  19. package/src/tools/edit.js +192 -32
  20. package/src/tools/file-lines.js +5 -0
  21. package/src/tools/index.js +4 -0
  22. package/src/tools/memory.js +88 -0
  23. package/src/tools/read-media-file.js +85 -68
  24. package/src/tools/read.js +15 -1
  25. package/src/tools/utils.js +14 -0
  26. package/src/tools/write.js +35 -5
  27. package/src/tui.js +11665 -9179
  28. package/src/web-auth.js +98 -0
  29. package/src/web-daemon-cli.js +63 -0
  30. package/src/web-daemon-client.js +203 -0
  31. package/src/web-daemon.js +871 -0
  32. package/src/web-public/app.css +1509 -0
  33. package/src/web-public/app.js +2913 -0
  34. package/src/web-public/complete.js +154 -0
  35. package/src/web-public/fonts/JetBrainsMono-Bold.woff2 +0 -0
  36. package/src/web-public/fonts/JetBrainsMono-Regular.woff2 +0 -0
  37. package/src/web-public/fonts/noto-sans-sc-100-400-normal.woff2 +0 -0
  38. package/src/web-public/fonts/noto-sans-sc-101-400-normal.woff2 +0 -0
  39. package/src/web-public/fonts/noto-sans-sc-102-400-normal.woff2 +0 -0
  40. package/src/web-public/fonts/noto-sans-sc-103-400-normal.woff2 +0 -0
  41. package/src/web-public/fonts/noto-sans-sc-104-400-normal.woff2 +0 -0
  42. package/src/web-public/fonts/noto-sans-sc-105-400-normal.woff2 +0 -0
  43. package/src/web-public/fonts/noto-sans-sc-106-400-normal.woff2 +0 -0
  44. package/src/web-public/fonts/noto-sans-sc-107-400-normal.woff2 +0 -0
  45. package/src/web-public/fonts/noto-sans-sc-108-400-normal.woff2 +0 -0
  46. package/src/web-public/fonts/noto-sans-sc-109-400-normal.woff2 +0 -0
  47. package/src/web-public/fonts/noto-sans-sc-110-400-normal.woff2 +0 -0
  48. package/src/web-public/fonts/noto-sans-sc-111-400-normal.woff2 +0 -0
  49. package/src/web-public/fonts/noto-sans-sc-112-400-normal.woff2 +0 -0
  50. package/src/web-public/fonts/noto-sans-sc-113-400-normal.woff2 +0 -0
  51. package/src/web-public/fonts/noto-sans-sc-114-400-normal.woff2 +0 -0
  52. package/src/web-public/fonts/noto-sans-sc-115-400-normal.woff2 +0 -0
  53. package/src/web-public/fonts/noto-sans-sc-116-400-normal.woff2 +0 -0
  54. package/src/web-public/fonts/noto-sans-sc-117-400-normal.woff2 +0 -0
  55. package/src/web-public/fonts/noto-sans-sc-118-400-normal.woff2 +0 -0
  56. package/src/web-public/fonts/noto-sans-sc-119-400-normal.woff2 +0 -0
  57. package/src/web-public/fonts/noto-sans-sc-21-400-normal.woff2 +0 -0
  58. package/src/web-public/fonts/noto-sans-sc-22-400-normal.woff2 +0 -0
  59. package/src/web-public/fonts/noto-sans-sc-23-400-normal.woff2 +0 -0
  60. package/src/web-public/fonts/noto-sans-sc-24-400-normal.woff2 +0 -0
  61. package/src/web-public/fonts/noto-sans-sc-25-400-normal.woff2 +0 -0
  62. package/src/web-public/fonts/noto-sans-sc-26-400-normal.woff2 +0 -0
  63. package/src/web-public/fonts/noto-sans-sc-27-400-normal.woff2 +0 -0
  64. package/src/web-public/fonts/noto-sans-sc-28-400-normal.woff2 +0 -0
  65. package/src/web-public/fonts/noto-sans-sc-29-400-normal.woff2 +0 -0
  66. package/src/web-public/fonts/noto-sans-sc-30-400-normal.woff2 +0 -0
  67. package/src/web-public/fonts/noto-sans-sc-31-400-normal.woff2 +0 -0
  68. package/src/web-public/fonts/noto-sans-sc-32-400-normal.woff2 +0 -0
  69. package/src/web-public/fonts/noto-sans-sc-33-400-normal.woff2 +0 -0
  70. package/src/web-public/fonts/noto-sans-sc-34-400-normal.woff2 +0 -0
  71. package/src/web-public/fonts/noto-sans-sc-35-400-normal.woff2 +0 -0
  72. package/src/web-public/fonts/noto-sans-sc-36-400-normal.woff2 +0 -0
  73. package/src/web-public/fonts/noto-sans-sc-37-400-normal.woff2 +0 -0
  74. package/src/web-public/fonts/noto-sans-sc-38-400-normal.woff2 +0 -0
  75. package/src/web-public/fonts/noto-sans-sc-39-400-normal.woff2 +0 -0
  76. package/src/web-public/fonts/noto-sans-sc-4-400-normal.woff2 +0 -0
  77. package/src/web-public/fonts/noto-sans-sc-40-400-normal.woff2 +0 -0
  78. package/src/web-public/fonts/noto-sans-sc-41-400-normal.woff2 +0 -0
  79. package/src/web-public/fonts/noto-sans-sc-42-400-normal.woff2 +0 -0
  80. package/src/web-public/fonts/noto-sans-sc-43-400-normal.woff2 +0 -0
  81. package/src/web-public/fonts/noto-sans-sc-44-400-normal.woff2 +0 -0
  82. package/src/web-public/fonts/noto-sans-sc-45-400-normal.woff2 +0 -0
  83. package/src/web-public/fonts/noto-sans-sc-46-400-normal.woff2 +0 -0
  84. package/src/web-public/fonts/noto-sans-sc-47-400-normal.woff2 +0 -0
  85. package/src/web-public/fonts/noto-sans-sc-48-400-normal.woff2 +0 -0
  86. package/src/web-public/fonts/noto-sans-sc-49-400-normal.woff2 +0 -0
  87. package/src/web-public/fonts/noto-sans-sc-5-400-normal.woff2 +0 -0
  88. package/src/web-public/fonts/noto-sans-sc-50-400-normal.woff2 +0 -0
  89. package/src/web-public/fonts/noto-sans-sc-51-400-normal.woff2 +0 -0
  90. package/src/web-public/fonts/noto-sans-sc-52-400-normal.woff2 +0 -0
  91. package/src/web-public/fonts/noto-sans-sc-53-400-normal.woff2 +0 -0
  92. package/src/web-public/fonts/noto-sans-sc-54-400-normal.woff2 +0 -0
  93. package/src/web-public/fonts/noto-sans-sc-55-400-normal.woff2 +0 -0
  94. package/src/web-public/fonts/noto-sans-sc-56-400-normal.woff2 +0 -0
  95. package/src/web-public/fonts/noto-sans-sc-57-400-normal.woff2 +0 -0
  96. package/src/web-public/fonts/noto-sans-sc-58-400-normal.woff2 +0 -0
  97. package/src/web-public/fonts/noto-sans-sc-59-400-normal.woff2 +0 -0
  98. package/src/web-public/fonts/noto-sans-sc-6-400-normal.woff2 +0 -0
  99. package/src/web-public/fonts/noto-sans-sc-60-400-normal.woff2 +0 -0
  100. package/src/web-public/fonts/noto-sans-sc-61-400-normal.woff2 +0 -0
  101. package/src/web-public/fonts/noto-sans-sc-62-400-normal.woff2 +0 -0
  102. package/src/web-public/fonts/noto-sans-sc-63-400-normal.woff2 +0 -0
  103. package/src/web-public/fonts/noto-sans-sc-64-400-normal.woff2 +0 -0
  104. package/src/web-public/fonts/noto-sans-sc-65-400-normal.woff2 +0 -0
  105. package/src/web-public/fonts/noto-sans-sc-66-400-normal.woff2 +0 -0
  106. package/src/web-public/fonts/noto-sans-sc-67-400-normal.woff2 +0 -0
  107. package/src/web-public/fonts/noto-sans-sc-68-400-normal.woff2 +0 -0
  108. package/src/web-public/fonts/noto-sans-sc-69-400-normal.woff2 +0 -0
  109. package/src/web-public/fonts/noto-sans-sc-70-400-normal.woff2 +0 -0
  110. package/src/web-public/fonts/noto-sans-sc-71-400-normal.woff2 +0 -0
  111. package/src/web-public/fonts/noto-sans-sc-72-400-normal.woff2 +0 -0
  112. package/src/web-public/fonts/noto-sans-sc-73-400-normal.woff2 +0 -0
  113. package/src/web-public/fonts/noto-sans-sc-74-400-normal.woff2 +0 -0
  114. package/src/web-public/fonts/noto-sans-sc-75-400-normal.woff2 +0 -0
  115. package/src/web-public/fonts/noto-sans-sc-76-400-normal.woff2 +0 -0
  116. package/src/web-public/fonts/noto-sans-sc-77-400-normal.woff2 +0 -0
  117. package/src/web-public/fonts/noto-sans-sc-78-400-normal.woff2 +0 -0
  118. package/src/web-public/fonts/noto-sans-sc-79-400-normal.woff2 +0 -0
  119. package/src/web-public/fonts/noto-sans-sc-80-400-normal.woff2 +0 -0
  120. package/src/web-public/fonts/noto-sans-sc-81-400-normal.woff2 +0 -0
  121. package/src/web-public/fonts/noto-sans-sc-82-400-normal.woff2 +0 -0
  122. package/src/web-public/fonts/noto-sans-sc-83-400-normal.woff2 +0 -0
  123. package/src/web-public/fonts/noto-sans-sc-84-400-normal.woff2 +0 -0
  124. package/src/web-public/fonts/noto-sans-sc-85-400-normal.woff2 +0 -0
  125. package/src/web-public/fonts/noto-sans-sc-86-400-normal.woff2 +0 -0
  126. package/src/web-public/fonts/noto-sans-sc-87-400-normal.woff2 +0 -0
  127. package/src/web-public/fonts/noto-sans-sc-88-400-normal.woff2 +0 -0
  128. package/src/web-public/fonts/noto-sans-sc-89-400-normal.woff2 +0 -0
  129. package/src/web-public/fonts/noto-sans-sc-90-400-normal.woff2 +0 -0
  130. package/src/web-public/fonts/noto-sans-sc-91-400-normal.woff2 +0 -0
  131. package/src/web-public/fonts/noto-sans-sc-97-400-normal.woff2 +0 -0
  132. package/src/web-public/fonts/noto-sans-sc-98-400-normal.woff2 +0 -0
  133. package/src/web-public/fonts/noto-sans-sc-99-400-normal.woff2 +0 -0
  134. package/src/web-public/fonts/noto-sans-sc.css +775 -0
  135. package/src/web-public/fonts.css +31 -0
  136. package/src/web-public/home.css +222 -0
  137. package/src/web-public/home.html +33 -0
  138. package/src/web-public/home.js +160 -0
  139. package/src/web-public/i18n.js +983 -0
  140. package/src/web-public/index.html +196 -0
  141. package/src/web-public/login.css +123 -0
  142. package/src/web-public/login.html +25 -0
  143. package/src/web-public/login.js +46 -0
  144. package/src/web-public/settings.js +290 -0
  145. package/src/web-ws.js +226 -0
  146. package/src/web.js +380 -0
@@ -0,0 +1,983 @@
1
+ export const LANGUAGES = [
2
+ {
3
+ "id": "zh",
4
+ "label": "中文"
5
+ },
6
+ {
7
+ "id": "en",
8
+ "label": "English"
9
+ }
10
+ ];
11
+
12
+ export const DEFAULT_LANG = "en";
13
+
14
+ export const MESSAGES = {
15
+ "app.title": {
16
+ "zh": "hncode",
17
+ "en": "hncode"
18
+ },
19
+ "login.heading": {
20
+ "zh": "hncode",
21
+ "en": "hncode"
22
+ },
23
+ "login.lede": {
24
+ "zh": "访问令牌保存在 config.toml 里,第一次运行时自动生成,之后一直不变。",
25
+ "en": "The access token lives in config.toml. It is generated once and stays the same."
26
+ },
27
+ "login.tokenLabel": {
28
+ "zh": "访问令牌",
29
+ "en": "Access token"
30
+ },
31
+ "login.submit": {
32
+ "zh": "进入",
33
+ "en": "Sign in"
34
+ },
35
+ "login.badToken": {
36
+ "zh": "令牌不对。",
37
+ "en": "Invalid token."
38
+ },
39
+ "login.failed": {
40
+ "zh": "登录失败。",
41
+ "en": "Sign-in failed."
42
+ },
43
+ "login.unreachable": {
44
+ "zh": "连不上服务:",
45
+ "en": "Cannot reach the server: "
46
+ },
47
+ "login.foot": {
48
+ "zh": "本地服务,只监听回环地址。在任意一个终端里运行 /web 都能看到这台机器上的所有会话。",
49
+ "en": "Local service, loopback only. Run /web in any terminal to see every session on this machine."
50
+ },
51
+ "home.brandSuffix": {
52
+ "zh": "会话",
53
+ "en": "sessions"
54
+ },
55
+ "home.lede": {
56
+ "zh": "这台机器上的所有会话。运行中的可以继续对话,已退出的只能查看。",
57
+ "en": "Every session on this machine. Running ones accept input; exited ones are read-only."
58
+ },
59
+ "home.empty": {
60
+ "zh": "还没有任何会话。在终端里运行 hncode 开始一个。",
61
+ "en": "No sessions yet. Start one by running hncode in a terminal."
62
+ },
63
+ "home.live": {
64
+ "zh": "运行中",
65
+ "en": "Running"
66
+ },
67
+ "home.saved": {
68
+ "zh": "已退出",
69
+ "en": "Exited"
70
+ },
71
+ "home.readonly": {
72
+ "zh": "只读",
73
+ "en": "Read-only"
74
+ },
75
+ "home.untitled": {
76
+ "zh": "未命名",
77
+ "en": "Untitled"
78
+ },
79
+ "home.noWorkspace": {
80
+ "zh": "未知目录",
81
+ "en": "Unknown directory"
82
+ },
83
+ "home.refresh": {
84
+ "zh": "刷新",
85
+ "en": "Refresh"
86
+ },
87
+ "home.logout": {
88
+ "zh": "退出登录",
89
+ "en": "Sign out"
90
+ },
91
+ "home.colTitle": {
92
+ "zh": "会话",
93
+ "en": "Session"
94
+ },
95
+ "home.colUpdated": {
96
+ "zh": "最后活动",
97
+ "en": "Last active"
98
+ },
99
+ "home.colRounds": {
100
+ "zh": "回合",
101
+ "en": "Turns"
102
+ },
103
+ "home.sessionCount": {
104
+ "zh": "{n} 个会话",
105
+ "en": "{n} session(s)"
106
+ },
107
+ "home.loadFailed": {
108
+ "zh": "读取会话列表失败:",
109
+ "en": "Could not load sessions: "
110
+ },
111
+ "home.justNow": {
112
+ "zh": "刚刚",
113
+ "en": "just now"
114
+ },
115
+ "home.minutesAgo": {
116
+ "zh": "{n} 分钟前",
117
+ "en": "{n}m ago"
118
+ },
119
+ "home.hoursAgo": {
120
+ "zh": "{n} 小时前",
121
+ "en": "{n}h ago"
122
+ },
123
+ "home.daysAgo": {
124
+ "zh": "{n} 天前",
125
+ "en": "{n}d ago"
126
+ },
127
+ "nav.chat": {
128
+ "zh": "对话",
129
+ "en": "Chat"
130
+ },
131
+ "nav.readonly": {
132
+ "zh": "只读",
133
+ "en": "read-only"
134
+ },
135
+ "nav.ariaLabel": {
136
+ "zh": "视图切换",
137
+ "en": "views"
138
+ },
139
+ "rail.ariaLabel": {
140
+ "zh": "会话列表",
141
+ "en": "sessions"
142
+ },
143
+ "nav.tasks": {
144
+ "zh": "任务",
145
+ "en": "Tasks"
146
+ },
147
+ "nav.files": {
148
+ "zh": "文件",
149
+ "en": "Files"
150
+ },
151
+ "nav.logs": {
152
+ "zh": "日志",
153
+ "en": "Logs"
154
+ },
155
+ "nav.tools": {
156
+ "zh": "工具",
157
+ "en": "Tools"
158
+ },
159
+ "nav.commands": {
160
+ "zh": "命令",
161
+ "en": "Commands"
162
+ },
163
+ "nav.connecting": {
164
+ "zh": "连接中",
165
+ "en": "Connecting"
166
+ },
167
+ "nav.connected": {
168
+ "zh": "已连接",
169
+ "en": "Connected"
170
+ },
171
+ "nav.disconnected": {
172
+ "zh": "断开,重连中",
173
+ "en": "Disconnected, retrying"
174
+ },
175
+ "nav.language": {
176
+ "zh": "语言",
177
+ "en": "Language"
178
+ },
179
+ "rail.heading": {
180
+ "zh": "会话",
181
+ "en": "Sessions"
182
+ },
183
+ "rail.empty": {
184
+ "zh": "还没有其它会话",
185
+ "en": "No other sessions"
186
+ },
187
+ "rail.noMatch": {
188
+ "zh": "没有匹配的会话",
189
+ "en": "No session matches"
190
+ },
191
+ "rail.noWorkspace": {
192
+ "zh": "未知目录",
193
+ "en": "Unknown directory"
194
+ },
195
+ "rail.current": {
196
+ "zh": "当前",
197
+ "en": "Current"
198
+ },
199
+ "rail.search": {
200
+ "zh": "搜索 id / 标题 / 目录",
201
+ "en": "search id / title / workspace"
202
+ },
203
+ "rail.all": {
204
+ "zh": "所有会话",
205
+ "en": "All sessions"
206
+ },
207
+ "rail.open": {
208
+ "zh": "会话列表",
209
+ "en": "Sessions"
210
+ },
211
+ "chat.untitled": {
212
+ "zh": "会话",
213
+ "en": "Session"
214
+ },
215
+ "chat.interrupt": {
216
+ "zh": "中断",
217
+ "en": "Interrupt"
218
+ },
219
+ "chat.placeholder": {
220
+ "zh": "输入消息,Enter 发送,Shift+Enter 换行",
221
+ "en": "Message the agent. Enter sends, Shift+Enter adds a line"
222
+ },
223
+ "chat.send": {
224
+ "zh": "发送",
225
+ "en": "Send"
226
+ },
227
+ "chat.shellHint": {
228
+ "zh": "行首加 ! 直接执行命令",
229
+ "en": "A leading ! runs the line in the shell"
230
+ },
231
+ "chat.running": {
232
+ "zh": "运行中",
233
+ "en": "Running"
234
+ },
235
+ "chat.idle": {
236
+ "zh": "空闲",
237
+ "en": "Idle"
238
+ },
239
+ "chat.toggleHint": {
240
+ "zh": "点击展开原文",
241
+ "en": "Click to expand"
242
+ },
243
+ "role.user": {
244
+ "zh": "你",
245
+ "en": "You"
246
+ },
247
+ "role.assistant": {
248
+ "zh": "AI",
249
+ "en": "AI"
250
+ },
251
+ "role.tool": {
252
+ "zh": "工具",
253
+ "en": "Tool"
254
+ },
255
+ "role.toolResult": {
256
+ "zh": "输出",
257
+ "en": "Output"
258
+ },
259
+ "role.system": {
260
+ "zh": "系统",
261
+ "en": "System"
262
+ },
263
+ "role.warn": {
264
+ "zh": "警告",
265
+ "en": "Warn"
266
+ },
267
+ "role.thinking": {
268
+ "zh": "思考",
269
+ "en": "Thinking"
270
+ },
271
+ "role.shell": {
272
+ "zh": "shell",
273
+ "en": "shell"
274
+ },
275
+ "role.plan": {
276
+ "zh": "计划",
277
+ "en": "Plan"
278
+ },
279
+ "role.compaction": {
280
+ "zh": "压缩",
281
+ "en": "Compact"
282
+ },
283
+ "role.aborted": {
284
+ "zh": "中止",
285
+ "en": "Aborted"
286
+ },
287
+ "role.bgTask": {
288
+ "zh": "任务",
289
+ "en": "Task"
290
+ },
291
+ "role.error": {
292
+ "zh": "错误",
293
+ "en": "Error"
294
+ },
295
+ "role.queued": {
296
+ "zh": "队列",
297
+ "en": "Queued"
298
+ },
299
+ "role.steer": {
300
+ "zh": "注入",
301
+ "en": "Steer"
302
+ },
303
+ "tool.running": {
304
+ "zh": "运行中",
305
+ "en": "running"
306
+ },
307
+ "tool.done": {
308
+ "zh": "完成",
309
+ "en": "done"
310
+ },
311
+ "tool.failed": {
312
+ "zh": "失败",
313
+ "en": "failed"
314
+ },
315
+ "compact.running": {
316
+ "zh": "正在压缩",
317
+ "en": "Compacting"
318
+ },
319
+ "compact.done": {
320
+ "zh": "压缩完成",
321
+ "en": "Compaction complete"
322
+ },
323
+ "compact.cancelled": {
324
+ "zh": "压缩取消",
325
+ "en": "Compaction cancelled"
326
+ },
327
+ "compact.amount": {
328
+ "zh": "{before} → {after} tokens",
329
+ "en": "{before} → {after} tokens"
330
+ },
331
+ "tasks.heading": {
332
+ "zh": "后台任务",
333
+ "en": "Background tasks"
334
+ },
335
+ "tasks.refresh": {
336
+ "zh": "刷新",
337
+ "en": "Refresh"
338
+ },
339
+ "tasks.empty": {
340
+ "zh": "没有后台任务。",
341
+ "en": "No background tasks."
342
+ },
343
+ "tasks.colId": {
344
+ "zh": "ID",
345
+ "en": "ID"
346
+ },
347
+ "tasks.colKind": {
348
+ "zh": "类型",
349
+ "en": "Kind"
350
+ },
351
+ "tasks.colStatus": {
352
+ "zh": "状态",
353
+ "en": "Status"
354
+ },
355
+ "tasks.colSummary": {
356
+ "zh": "摘要",
357
+ "en": "Summary"
358
+ },
359
+ "tasks.stop": {
360
+ "zh": "停止",
361
+ "en": "Stop"
362
+ },
363
+ "files.heading": {
364
+ "zh": "会话改动",
365
+ "en": "Session changes"
366
+ },
367
+ "files.sub": {
368
+ "zh": "本轮对话读写过的文件",
369
+ "en": "Files this conversation read or wrote"
370
+ },
371
+ "files.empty": {
372
+ "zh": "本会话还没有读写文件。",
373
+ "en": "No files read or written yet."
374
+ },
375
+ "files.colPath": {
376
+ "zh": "路径",
377
+ "en": "Path"
378
+ },
379
+ "files.colOps": {
380
+ "zh": "操作",
381
+ "en": "Ops"
382
+ },
383
+ "files.colCount": {
384
+ "zh": "次数",
385
+ "en": "Count"
386
+ },
387
+ "logs.heading": {
388
+ "zh": "事件日志",
389
+ "en": "Event log"
390
+ },
391
+ "logs.clear": {
392
+ "zh": "清空",
393
+ "en": "Clear"
394
+ },
395
+ "logs.sub": {
396
+ "zh": "最近的会话事件,最新的在最下面",
397
+ "en": "Recent session events, newest last"
398
+ },
399
+ "tools.heading": {
400
+ "zh": "可用工具",
401
+ "en": "Tools available"
402
+ },
403
+ "tools.sub": {
404
+ "zh": "由本会话的模型调用",
405
+ "en": "Callable by the model in this session"
406
+ },
407
+ "commands.heading": {
408
+ "zh": "斜杠命令",
409
+ "en": "Slash commands"
410
+ },
411
+ "commands.sub": {
412
+ "zh": "与终端完全一致",
413
+ "en": "Identical to the terminal"
414
+ },
415
+ "side.runtime": {
416
+ "zh": "运行",
417
+ "en": "Runtime"
418
+ },
419
+ "settings.open": {
420
+ "zh": "设置",
421
+ "en": "Settings"
422
+ },
423
+ "settings.title": {
424
+ "zh": "设置",
425
+ "en": "Settings"
426
+ },
427
+ "settings.close": {
428
+ "zh": "关闭",
429
+ "en": "Close"
430
+ },
431
+ "settings.save": {
432
+ "zh": "保存",
433
+ "en": "Save"
434
+ },
435
+ "settings.session": {
436
+ "zh": "会话",
437
+ "en": "Session"
438
+ },
439
+ "settings.titleLabel": {
440
+ "zh": "标题",
441
+ "en": "Title"
442
+ },
443
+ "settings.titleSaved": {
444
+ "zh": "标题已保存",
445
+ "en": "Title saved"
446
+ },
447
+ "settings.providers": {
448
+ "zh": "Provider",
449
+ "en": "Providers"
450
+ },
451
+ "settings.noProviders": {
452
+ "zh": "还没有配置 provider",
453
+ "en": "No providers configured"
454
+ },
455
+ "settings.discover": {
456
+ "zh": "拉取模型",
457
+ "en": "discover"
458
+ },
459
+ "settings.foundModels": {
460
+ "zh": "找到 {n} 个模型",
461
+ "en": "Found {n} model(s)"
462
+ },
463
+ "settings.import": {
464
+ "zh": "导入",
465
+ "en": "import"
466
+ },
467
+ "settings.imported": {
468
+ "zh": "已导入 {name},新增 {n} 个模型",
469
+ "en": "Imported {name}, {n} new model(s)"
470
+ },
471
+ "settings.importKnown": {
472
+ "zh": "从 models.dev 导入",
473
+ "en": "Import from models.dev"
474
+ },
475
+ "settings.keyPrompt": {
476
+ "zh": "请输入 {name} 的 API key:",
477
+ "en": "API key for {name}:"
478
+ },
479
+ "settings.addProvider": {
480
+ "zh": "添加",
481
+ "en": "Add"
482
+ },
483
+ "settings.added": {
484
+ "zh": "已添加 {name}",
485
+ "en": "Added {name}"
486
+ },
487
+ "settings.remove": {
488
+ "zh": "删除",
489
+ "en": "remove"
490
+ },
491
+ "settings.removed": {
492
+ "zh": "已删除 {name}",
493
+ "en": "Removed {name}"
494
+ },
495
+ "settings.confirmRemove": {
496
+ "zh": "删除 provider {name}?它的模型也会一并移除。",
497
+ "en": "Delete provider {name}? Its models go too."
498
+ },
499
+ "settings.noMatch": {
500
+ "zh": "没有匹配项",
501
+ "en": "No match"
502
+ },
503
+ "settings.nameRequired": {
504
+ "zh": "名称不能为空",
505
+ "en": "Name is required"
506
+ },
507
+ "settings.failed": {
508
+ "zh": "操作失败:",
509
+ "en": "Failed: "
510
+ },
511
+ "settings.prefs": {
512
+ "zh": "偏好",
513
+ "en": "Preferences"
514
+ },
515
+ "settings.info": {
516
+ "zh": "当前生效",
517
+ "en": "In force"
518
+ },
519
+ "settings.model": {
520
+ "zh": "模型",
521
+ "en": "Model"
522
+ },
523
+ "settings.provider": {
524
+ "zh": "Provider",
525
+ "en": "Provider"
526
+ },
527
+ "settings.protocol": {
528
+ "zh": "协议",
529
+ "en": "Protocol"
530
+ },
531
+ "settings.endpoint": {
532
+ "zh": "端点",
533
+ "en": "Endpoint"
534
+ },
535
+ "settings.key": {
536
+ "zh": "密钥",
537
+ "en": "API key"
538
+ },
539
+ "settings.workspace": {
540
+ "zh": "目录",
541
+ "en": "Workspace"
542
+ },
543
+ "settings.ctx": {
544
+ "zh": "上下文窗口",
545
+ "en": "Context window"
546
+ },
547
+ "settings.phName": {
548
+ "zh": "名称",
549
+ "en": "name"
550
+ },
551
+ "settings.phUrl": {
552
+ "zh": "接口地址",
553
+ "en": "base URL"
554
+ },
555
+ "settings.phKey": {
556
+ "zh": "API key",
557
+ "en": "API key"
558
+ },
559
+ "settings.phFilter": {
560
+ "zh": "筛选",
561
+ "en": "filter"
562
+ },
563
+ "settings.tagKey": {
564
+ "zh": "已设密钥",
565
+ "en": "key"
566
+ },
567
+ "settings.tagNoKey": {
568
+ "zh": "无密钥",
569
+ "en": "no key"
570
+ },
571
+ "settings.noUrl": {
572
+ "zh": "未设置地址",
573
+ "en": "(no url)"
574
+ },
575
+ "settings.modelCount": {
576
+ "zh": "{n} 个模型",
577
+ "en": "{n} model(s)"
578
+ },
579
+ "settings.valSet": {
580
+ "zh": "已设置",
581
+ "en": "set"
582
+ },
583
+ "settings.valNotSet": {
584
+ "zh": "未设置",
585
+ "en": "not set"
586
+ },
587
+ "pref.calm": {
588
+ "zh": "简洁模式",
589
+ "en": "Calm mode"
590
+ },
591
+ "pref.autoCompact": {
592
+ "zh": "自动压缩",
593
+ "en": "Auto compact"
594
+ },
595
+ "pref.autoUpdate": {
596
+ "zh": "自动更新",
597
+ "en": "Auto update"
598
+ },
599
+ "pref.promptCache": {
600
+ "zh": "提示缓存",
601
+ "en": "Prompt cache"
602
+ },
603
+ "pref.external": {
604
+ "zh": "允许工作区外路径",
605
+ "en": "Allow external paths"
606
+ },
607
+ "side.model": {
608
+ "zh": "模型",
609
+ "en": "Model"
610
+ },
611
+ "side.provider": {
612
+ "zh": "Provider",
613
+ "en": "Provider"
614
+ },
615
+ "side.mode": {
616
+ "zh": "权限",
617
+ "en": "Permission"
618
+ },
619
+ "side.cwd": {
620
+ "zh": "目录",
621
+ "en": "Directory"
622
+ },
623
+ "side.plan": {
624
+ "zh": "计划模式",
625
+ "en": "Plan mode"
626
+ },
627
+ "side.effort": {
628
+ "zh": "思考",
629
+ "en": "Thinking"
630
+ },
631
+ "side.focus": {
632
+ "zh": "专注模式",
633
+ "en": "Focus mode"
634
+ },
635
+ "side.busy": {
636
+ "zh": "状态",
637
+ "en": "State"
638
+ },
639
+ "side.context": {
640
+ "zh": "上下文",
641
+ "en": "Context"
642
+ },
643
+ "side.usage": {
644
+ "zh": "用量",
645
+ "en": "Usage"
646
+ },
647
+ "side.rounds": {
648
+ "zh": "轮次",
649
+ "en": "Rounds"
650
+ },
651
+ "side.steps": {
652
+ "zh": "步骤",
653
+ "en": "Steps"
654
+ },
655
+ "side.rate": {
656
+ "zh": "速度",
657
+ "en": "Rate"
658
+ },
659
+ "unit.rounds": {
660
+ "zh": "{n}轮",
661
+ "en": "{n} turns"
662
+ },
663
+ "unit.steps": {
664
+ "zh": "{n}步",
665
+ "en": "{n} steps"
666
+ },
667
+ "unit.rate": {
668
+ "zh": "{n} tok/s",
669
+ "en": "{n} tok/s"
670
+ },
671
+ "unit.none": {
672
+ "zh": "—",
673
+ "en": "—"
674
+ },
675
+ "side.todos": {
676
+ "zh": "待办",
677
+ "en": "Todos"
678
+ },
679
+ "side.queue": {
680
+ "zh": "队列",
681
+ "en": "Queue"
682
+ },
683
+ "side.quick": {
684
+ "zh": "快捷",
685
+ "en": "Quick"
686
+ },
687
+ "side.on": {
688
+ "zh": "开",
689
+ "en": "on"
690
+ },
691
+ "side.off": {
692
+ "zh": "关",
693
+ "en": "off"
694
+ },
695
+ "side.none": {
696
+ "zh": "(无)",
697
+ "en": "(none)"
698
+ },
699
+ "mark.user": {
700
+ "zh": "❯",
701
+ "en": "❯"
702
+ },
703
+ "mark.queued": {
704
+ "zh": "❯",
705
+ "en": "❯"
706
+ },
707
+ "mark.steer": {
708
+ "zh": "❯",
709
+ "en": "❯"
710
+ },
711
+ "mark.bash": {
712
+ "zh": "!",
713
+ "en": "!"
714
+ },
715
+ "mark.warn": {
716
+ "zh": "⚑",
717
+ "en": "⚑"
718
+ },
719
+ "mark.thinking": {
720
+ "zh": "●",
721
+ "en": "●"
722
+ },
723
+ "mark.tool": {
724
+ "zh": "●",
725
+ "en": "●"
726
+ },
727
+ "mark.toolFailed": {
728
+ "zh": "✗",
729
+ "en": "✗"
730
+ },
731
+ "mark.result": {
732
+ "zh": "↳",
733
+ "en": "↳"
734
+ },
735
+ "mark.bgTask": {
736
+ "zh": "●",
737
+ "en": "●"
738
+ },
739
+ "mark.bgTaskFailed": {
740
+ "zh": "✗",
741
+ "en": "✗"
742
+ },
743
+ "tool.verb": {
744
+ "zh": "调用",
745
+ "en": "Used"
746
+ },
747
+ "tool.using": {
748
+ "zh": "调用",
749
+ "en": "Using"
750
+ },
751
+ "tool.used": {
752
+ "zh": "调用",
753
+ "en": "Used"
754
+ },
755
+ "chat.thinking": {
756
+ "zh": "思考…",
757
+ "en": "thinking…"
758
+ },
759
+ "tool.compacting": {
760
+ "zh": "正在压缩上下文…",
761
+ "en": "Compacting context…"
762
+ },
763
+ "tool.compacted": {
764
+ "zh": "压缩完成",
765
+ "en": "Compaction complete"
766
+ },
767
+ "tool.compactCancelled": {
768
+ "zh": "压缩取消",
769
+ "en": "Compaction cancelled"
770
+ },
771
+ "tool.moreLines": {
772
+ "zh": "还有 {n} 行,展开",
773
+ "en": "{n} more lines, expand"
774
+ },
775
+ "tool.collapse": {
776
+ "zh": "收起",
777
+ "en": "collapse"
778
+ },
779
+ "tool.noChanges": {
780
+ "zh": "没有改动",
781
+ "en": "no changes"
782
+ },
783
+ "chat.shellMode": {
784
+ "zh": "shell 模式,Enter 执行",
785
+ "en": "shell mode, Enter runs it"
786
+ },
787
+ "status.usage": {
788
+ "zh": "{turns} 轮 | {steps} 步 | {rate} tok/s",
789
+ "en": "{turns} turns | {steps} steps | {rate} tok/s"
790
+ },
791
+ "status.context": {
792
+ "zh": "上下文 {pct}% ({used}/{max})",
793
+ "en": "context {pct}% ({used}/{max})"
794
+ },
795
+ "status.tasksBash": {
796
+ "zh": "[{n} 个任务运行中]",
797
+ "en": "[{n} task(s) running]"
798
+ },
799
+ "status.tasksAgent": {
800
+ "zh": "[{n} 个 agent 运行中]",
801
+ "en": "[{n} agent(s) running]"
802
+ },
803
+ "status.expandTodos": {
804
+ "zh": "展开全部待办",
805
+ "en": "Show every todo"
806
+ },
807
+ "copy.copy": {
808
+ "zh": "复制",
809
+ "en": "copy"
810
+ },
811
+ "copy.copyTitle": {
812
+ "zh": "复制到剪贴板",
813
+ "en": "Copy to clipboard"
814
+ },
815
+ "copy.done": {
816
+ "zh": "已复制",
817
+ "en": "copied"
818
+ },
819
+ "copy.failed": {
820
+ "zh": "复制失败",
821
+ "en": "failed"
822
+ },
823
+ "drawer.close": {
824
+ "zh": "Esc 关闭",
825
+ "en": "esc ✕"
826
+ },
827
+ "tool.args": {
828
+ "zh": "参数",
829
+ "en": "args"
830
+ },
831
+ "queue.steer": {
832
+ "zh": "注入",
833
+ "en": "Steer"
834
+ },
835
+ "queue.steering": {
836
+ "zh": "注入中…",
837
+ "en": "Steering…"
838
+ },
839
+ "queue.steerHint": {
840
+ "zh": "立即注入到正在进行的回合",
841
+ "en": "Inject this into the running turn now"
842
+ },
843
+ "queue.edit": {
844
+ "zh": "编辑",
845
+ "en": "Edit"
846
+ },
847
+ "queue.editHint": {
848
+ "zh": "取回输入框修改,不再排队",
849
+ "en": "Pull it back into the composer to change it"
850
+ },
851
+ "queue.drop": {
852
+ "zh": "移除",
853
+ "en": "Drop"
854
+ },
855
+ "queue.dropHint": {
856
+ "zh": "从队列中删除这条消息",
857
+ "en": "Remove this message from the queue"
858
+ },
859
+ "queue.moreHint": {
860
+ "zh": "… 还有 {n} 条",
861
+ "en": "… +{n} more"
862
+ },
863
+ "queue.hintRunning": {
864
+ "zh": "等待本回合结束",
865
+ "en": "Sent when this turn ends"
866
+ },
867
+ "queue.hintIdle": {
868
+ "zh": "回合结束后依次发送",
869
+ "en": "Sent in order once the turn ends"
870
+ },
871
+ "popover.click": {
872
+ "zh": "点击切换",
873
+ "en": "Click to change"
874
+ },
875
+ "popover.effortLabel": {
876
+ "zh": "思考等级",
877
+ "en": "Thinking Effort"
878
+ },
879
+ "popover.effort": {
880
+ "zh": "思考 {v}",
881
+ "en": "think {v}"
882
+ },
883
+ "popover.off": {
884
+ "zh": "off",
885
+ "en": "off"
886
+ },
887
+ "popover.unknown": {
888
+ "zh": "—",
889
+ "en": "—"
890
+ },
891
+ "modal.approve": {
892
+ "zh": "批准",
893
+ "en": "Approve"
894
+ },
895
+ "modal.reject": {
896
+ "zh": "拒绝",
897
+ "en": "Reject"
898
+ },
899
+ "modal.allow": {
900
+ "zh": "允许",
901
+ "en": "Allow"
902
+ },
903
+ "modal.deny": {
904
+ "zh": "拒绝",
905
+ "en": "Deny"
906
+ },
907
+ "modal.question": {
908
+ "zh": "需要选择",
909
+ "en": "Question"
910
+ },
911
+ "modal.submit": {
912
+ "zh": "提交",
913
+ "en": "Submit"
914
+ },
915
+ "modal.cancel": {
916
+ "zh": "取消",
917
+ "en": "Cancel"
918
+ },
919
+ "modal.other": {
920
+ "zh": "Other",
921
+ "en": "Other"
922
+ },
923
+ "modal.otherHint": {
924
+ "zh": "自己输入答案",
925
+ "en": "Type your own answer"
926
+ },
927
+ "modal.note": {
928
+ "zh": "补充说明",
929
+ "en": "Add a note"
930
+ },
931
+ "modal.noteHint": {
932
+ "zh": "写给整轮问题的补充,可留空",
933
+ "en": "Optional notes for the whole request"
934
+ },
935
+ "modal.next": {
936
+ "zh": "下一题",
937
+ "en": "Next"
938
+ },
939
+ "modal.progress": {
940
+ "zh": "第 {n}/{total} 题",
941
+ "en": "Question {n}/{total}"
942
+ },
943
+ "err.actionFailed": {
944
+ "zh": "操作失败",
945
+ "en": "Action failed"
946
+ },
947
+ "err.unreachable": {
948
+ "zh": "连不上服务:",
949
+ "en": "Cannot reach the server: "
950
+ },
951
+ "err.unauthorized": {
952
+ "zh": "未授权",
953
+ "en": "Unauthorized"
954
+ },
955
+ "http.notFound": {
956
+ "zh": "找不到",
957
+ "en": "not found"
958
+ },
959
+ "http.badMethod": {
960
+ "zh": "不支持该请求方法",
961
+ "en": "method not allowed"
962
+ },
963
+ "http.unauthorized": {
964
+ "zh": "未授权",
965
+ "en": "unauthorized"
966
+ }
967
+ };
968
+
969
+ export function t(lang, key, vars) {
970
+ const entry = MESSAGES[key];
971
+ if (!entry) return key;
972
+ let s = entry[lang] || entry[DEFAULT_LANG] || entry.en || key;
973
+ if (vars) {
974
+ for (const k of Object.keys(vars)) s = s.split('{' + k + '}').join(String(vars[k]));
975
+ }
976
+ return s;
977
+ }
978
+
979
+ export function catalog(lang) {
980
+ const out = {};
981
+ for (const key of Object.keys(MESSAGES)) out[key] = t(lang, key);
982
+ return out;
983
+ }