dsh-code 1.0.6 → 1.2.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 (86) hide show
  1. package/README.en.md +123 -26
  2. package/README.md +124 -27
  3. package/bin/deepseek.mjs +283 -35
  4. package/cordis.patch.yml +97 -0
  5. package/lib/index.mjs +5008 -881
  6. package/lib/session-query.mjs +150 -0
  7. package/lib/startup.mjs +4 -4
  8. package/lib/{theme-DCT8Y2xf.mjs → theme-7u5Qo3dF.mjs} +657 -20
  9. package/lib/types/app.d.ts +106 -62
  10. package/lib/types/authorization-panel.d.ts +3 -3
  11. package/lib/types/git-workflow.d.ts +91 -2
  12. package/lib/types/i18n.d.ts +39 -0
  13. package/lib/types/index.d.ts +100 -1
  14. package/lib/types/input-split.d.ts +1 -1
  15. package/lib/types/kernel-panels.d.ts +107 -29
  16. package/lib/types/language-panel.d.ts +12 -0
  17. package/lib/types/locales/en.d.ts +450 -0
  18. package/lib/types/locales/zh.d.ts +9 -0
  19. package/lib/types/mentions.d.ts +7 -3
  20. package/lib/types/models.d.ts +14 -0
  21. package/lib/types/panel-accent.d.ts +28 -0
  22. package/lib/types/rainbow.d.ts +69 -0
  23. package/lib/types/render/animations.d.ts +42 -0
  24. package/lib/types/render/editor.d.ts +4 -3
  25. package/lib/types/render/ime-cursor.d.ts +60 -0
  26. package/lib/types/render/inspector.d.ts +26 -0
  27. package/lib/types/render/lines.d.ts +21 -1
  28. package/lib/types/render/markdown.d.ts +1 -1
  29. package/lib/types/render/projection.d.ts +130 -4
  30. package/lib/types/render/status.d.ts +9 -9
  31. package/lib/types/render/text.d.ts +6 -0
  32. package/lib/types/render/usage.d.ts +113 -0
  33. package/lib/types/session-directory.d.ts +17 -0
  34. package/lib/types/session-query.d.ts +92 -0
  35. package/lib/types/startup.d.ts +1 -1
  36. package/lib/types/terminal-title.d.ts +66 -0
  37. package/lib/types/theme-panel.d.ts +2 -2
  38. package/lib/types/theme.d.ts +271 -52
  39. package/lib/types/update-panel.d.ts +49 -0
  40. package/lib/types/update.d.ts +75 -0
  41. package/lib/types/version.d.ts +4 -3
  42. package/package.json +246 -90
  43. package/src/app.ts +1369 -509
  44. package/src/approval.ts +166 -166
  45. package/src/authorization-panel.ts +19 -16
  46. package/src/editor-keys.ts +371 -371
  47. package/src/git-workflow.ts +229 -3
  48. package/src/i18n.ts +68 -0
  49. package/src/index.ts +534 -80
  50. package/src/input-split.ts +3 -3
  51. package/src/internals.ts +5 -0
  52. package/src/kernel-panels.ts +554 -86
  53. package/src/keyboard.ts +5 -4
  54. package/src/language-panel.ts +53 -0
  55. package/src/locales/en.ts +489 -0
  56. package/src/locales/zh.ts +488 -0
  57. package/src/mentions.ts +8 -4
  58. package/src/models.ts +264 -212
  59. package/src/panel-accent.ts +41 -0
  60. package/src/presets.ts +1 -1
  61. package/src/provider-settings.ts +1 -1
  62. package/src/rainbow.ts +208 -0
  63. package/src/render/animations.ts +104 -6
  64. package/src/render/editor.ts +25 -24
  65. package/src/render/export.ts +116 -95
  66. package/src/render/ime-cursor.ts +147 -0
  67. package/src/render/inspector.ts +42 -0
  68. package/src/render/lines.ts +628 -415
  69. package/src/render/markdown.ts +15 -3
  70. package/src/render/projection.ts +572 -21
  71. package/src/render/status.ts +59 -39
  72. package/src/render/text.ts +14 -0
  73. package/src/render/tool-preview.ts +77 -77
  74. package/src/render/usage.ts +430 -0
  75. package/src/render/width.ts +2 -2
  76. package/src/session-directory.ts +8 -6
  77. package/src/session-query.ts +239 -0
  78. package/src/startup.ts +3 -3
  79. package/src/subagents.ts +229 -229
  80. package/src/terminal-title.ts +190 -0
  81. package/src/theme-panel.ts +17 -21
  82. package/src/theme.ts +281 -33
  83. package/src/update-panel.ts +256 -0
  84. package/src/update.ts +126 -0
  85. package/src/version.ts +58 -20
  86. package/src/whale-glyph.ts +23 -23
@@ -0,0 +1,450 @@
1
+ /**
2
+ * The English message catalog: every user-visible UI string the terminal
3
+ * renders, keyed for {@link t}. The catalog is a plain record so missing
4
+ * keys fail typecheck against the shared key union, not at runtime.
5
+ *
6
+ * @module @deepseek-ai/dsh-tui/locales/en
7
+ */
8
+ export declare const en: {
9
+ readonly 'panel.close': "esc/q close";
10
+ readonly 'panel.moveEnterSelect': "↑↓ move · enter select · esc close";
11
+ readonly 'panel.moveEnterSelectBack': "↑↓ move · enter select · esc back · q close";
12
+ readonly 'panel.scrollEnds': "↑↓ scroll · pgup/pgdn page · g/G ends · esc/q close";
13
+ readonly 'panel.loading': "loading…";
14
+ readonly 'panel.loadFailed': "load failed";
15
+ readonly 'panel.noMatch': "no matching entries";
16
+ readonly 'panel.emptyClose': "esc close";
17
+ readonly 'panel.searchIdle': "search: type to filter";
18
+ readonly 'panel.searchIdleStop': "search: type to filter · esc stops";
19
+ readonly 'panel.searchPrefix': "search: ";
20
+ readonly 'language.title': "/language — interface language";
21
+ readonly 'language.hint': "↑↓ move · enter apply · esc/q close";
22
+ readonly 'theme.title': "/theme — color palette";
23
+ readonly 'theme.compact': "/theme · esc close";
24
+ readonly 'theme.current': "current";
25
+ readonly 'theme.dark.label': "dark";
26
+ readonly 'theme.dark.description': "DeepSeek dark palette (default)";
27
+ readonly 'theme.light.label': "light";
28
+ readonly 'theme.light.description': "light palette for bright terminals";
29
+ readonly 'theme.prismatic.label': "prismatic";
30
+ readonly 'theme.prismatic.description': "neon synthwave palette (violet/magenta/cyan)";
31
+ readonly 'theme.rainbow.label': "rainbow";
32
+ readonly 'theme.rainbow.description': "randomized carnival palette (/rainbow to reroll)";
33
+ readonly 'theme.auto.label': "auto";
34
+ readonly 'theme.auto.description': "follow the terminal; dark until detection lands";
35
+ readonly 'history.title.prompts': "/history · {count} prompts · type to filter";
36
+ readonly 'history.title.match': "/history · {matches} of {count} match '{query}'";
37
+ readonly 'history.filterHint': "filter {state}, enter fills the composer";
38
+ readonly 'history.filterEmpty': "· type to search prompts";
39
+ readonly 'history.filterQuery': "· {query}";
40
+ readonly 'history.empty': "no matching prompts";
41
+ readonly 'history.compact.none': "no matching prompts";
42
+ readonly 'history.footer': "↑↓ move · g/G ends · enter fill · esc close";
43
+ readonly 'search.title.type': "/search · type a query and press enter";
44
+ readonly 'search.title.hits': "/search · {count} hit for '{query}'";
45
+ readonly 'search.title.hitsPlural': "/search · {count} hits for '{query}'";
46
+ readonly 'search.hint': "{state} · enter searches or resumes";
47
+ readonly 'search.hintEmpty': "type to search sessions";
48
+ readonly 'search.empty.idle': "full-text search across every persisted session";
49
+ readonly 'search.empty.noHits': "no matching sessions{loading}";
50
+ readonly 'search.compact.noResults': "no results yet";
51
+ readonly 'search.compact.searching': "searching…";
52
+ readonly 'search.compact.error': "error: {message}";
53
+ readonly 'search.footer': "↑↓ move · enter search/resume · esc close";
54
+ readonly 'statusline.title': "/statusline · items apply to the live status line below";
55
+ readonly 'schedule.title': "/schedule · {count} active reminder";
56
+ readonly 'schedule.titlePlural': "/schedule · {count} active reminders";
57
+ readonly 'schedule.empty': "no active reminders — the model creates them with schedule_create";
58
+ readonly 'document.loading': "loading transcript…";
59
+ readonly 'document.compact': "transcript · esc close";
60
+ readonly 'document.footer': "lines {from}-{to}/{total} · ↑↓/pg/g/G · t/esc close";
61
+ readonly 'review.picker.title': "/review · choose a target";
62
+ readonly 'review.picker.uncommitted': "Review uncommitted changes (staged / unstaged / new files)";
63
+ readonly 'review.picker.branch': "Compare against a base branch (lists local branches)";
64
+ readonly 'review.picker.commit': "Review a commit on the current branch (lists recent commits)";
65
+ readonly 'review.picker.custom': "Custom review focus (type it)";
66
+ readonly 'review.picker.customHint': "type your focus, then enter to start the review";
67
+ readonly 'review.picker.branches': "{filtered} of {total} branches";
68
+ readonly 'review.picker.commits': "{filtered} of {total} commits";
69
+ readonly 'review.picker.loadingBranches': "loading branches…";
70
+ readonly 'review.picker.loadingCommits': "loading commits…";
71
+ readonly 'review.picker.empty': "no candidates";
72
+ readonly 'review.picker.noMatch': "no matches";
73
+ readonly 'review.picker.loading': "loading…";
74
+ readonly 'review.picker.loadFailed': "load failed";
75
+ readonly 'review.picker.compact': "pick a review target";
76
+ readonly 'review.picker.footer': "↑↓ move · enter select · esc back · q close";
77
+ readonly 'review.summary.untagged': "untagged×{n}";
78
+ readonly 'review.summary.incorrect': "patch incorrect";
79
+ readonly 'review.summary.correctClean': "no issues found";
80
+ readonly 'review.summary.correct': "patch correct";
81
+ readonly 'review.summary.noConclusion': "review finished: no structured conclusion";
82
+ readonly 'review.summary.zero': "review finished: 0 findings · {verdict}";
83
+ readonly 'review.summary.count': "review finished: {count} findings ({parts})";
84
+ readonly 'review.summary.countVerdict': "review finished: {count} findings ({parts}) · {verdict}";
85
+ readonly 'review.notice.started': "review started under read-only permissions";
86
+ readonly 'review.notice.failed': "review failed: {message}";
87
+ readonly 'review.notice.unavailable': "review unavailable: {message}";
88
+ readonly 'cmd.help': "show this overlay";
89
+ readonly 'cmd.model': "switch the model and manage providers";
90
+ readonly 'cmd.effort': "adjust reasoning effort for the current model";
91
+ readonly 'cmd.mode': "inspect or select the agent preset (/mode [preset])";
92
+ readonly 'cmd.permission': "inspect or select the permission preset (/permission [preset])";
93
+ readonly 'cmd.new': "create and switch to a fresh session (/new [preset])";
94
+ readonly 'cmd.fork': "fork at the latest completed turn (/fork [event-seq])";
95
+ readonly 'cmd.resume': "browse or switch root sessions (/resume [id|prefix])";
96
+ readonly 'cmd.search': "full-text search across persisted sessions (/search [query])";
97
+ readonly 'cmd.plugin': "inspect the live plugin composition";
98
+ readonly 'cmd.update': "update dsh-code, the harness host, and profile plugins in one aligned step";
99
+ readonly 'cmd.jobs': "inspect background jobs";
100
+ readonly 'cmd.schedule': "inspect active reminders (created through schedule tools)";
101
+ readonly 'cmd.statusline': "customize the status line items";
102
+ readonly 'cmd.theme': "switch the color theme";
103
+ readonly 'cmd.language': "switch the interface language (/language [en|zh])";
104
+ readonly 'cmd.rainbow': "reroll or pin the rainbow palette (/rainbow [seed])";
105
+ readonly 'cmd.animation': "toggle timed animations (/animation [on|off])";
106
+ readonly 'cmd.history': "search and recall past prompts";
107
+ readonly 'cmd.queue': "manage messages queued for the next turn";
108
+ readonly 'cmd.usage': "show this session token usage";
109
+ readonly 'cmd.agents': "inspect subagent sessions of this conversation";
110
+ readonly 'cmd.todos': "inspect the full todo list";
111
+ readonly 'cmd.subagent': "choose the model delegated subagents run on";
112
+ readonly 'cmd.vscode-keys': "pass ctrl+r through the vs code terminal";
113
+ readonly 'cmd.delete': "delete a session and its subagent threads";
114
+ readonly 'cmd.clear': "clear the screen";
115
+ readonly 'cmd.export': "export the transcript to markdown (/export [path])";
116
+ readonly 'cmd.title': "rename this session (/title <text>)";
117
+ readonly 'cmd.copy': "copy the latest assistant response";
118
+ readonly 'cmd.diff': "inspect Git changes (/diff [--staged|ref])";
119
+ readonly 'cmd.review': "review Git changes with the diff pasted in this session (/review [note])";
120
+ readonly 'cmd.quit': "exit";
121
+ readonly 'help.keysTitle': " keys";
122
+ readonly 'help.key.submit': "enter submit · ctrl+j / alt+enter newline · up/down history · tab complete";
123
+ readonly 'help.key.mentions': "@ mentions workspace files and sessions";
124
+ readonly 'help.key.inspector': "ctrl+o history details · ctrl/alt+r thinking · shift+tab permission preset";
125
+ readonly 'help.key.cancel': "esc interrupt the running turn · ctrl+c cancel / clear / quit · ctrl+d exit";
126
+ readonly 'help.key.queue': "empty tab picks queue or steer · /queue manages queued messages · delete cancels the newest one";
127
+ readonly 'help.key.edit': "ctrl+k cut to end of line · ctrl+u clear line · ctrl+a / ctrl+e line ends";
128
+ readonly 'help.commandsTitle': " commands";
129
+ readonly 'help.skillsTitle': " skills";
130
+ readonly 'help.footer': "↑↓ scroll · pgup/pgdn page · g/G ends · esc/q close";
131
+ readonly 'help.compact': "/help · esc/q close";
132
+ readonly 'panel.queue.title': "/queue — {count} queued · rows {from}-{to}";
133
+ readonly 'panel.queue.empty': " no messages queued for the next turn";
134
+ readonly 'panel.queue.attachments': "[attachments: read-only]";
135
+ readonly 'panel.queue.footerBusy': "↑↓ select · enter steer · e edit text · d remove · esc/q close";
136
+ readonly 'panel.queue.footerIdle': "↑↓ select · e edit text · d remove · esc/q close";
137
+ readonly 'panel.queue.editFooter': "type · ←→ move · enter save · esc cancel";
138
+ readonly 'panel.queue.compact': "/queue · esc/q close";
139
+ readonly 'panel.usage.title': "/usage — usage of this session";
140
+ readonly 'panel.usage.compact': "/usage · esc/q close";
141
+ readonly 'panel.usage.footer': "↑↓ scroll · pgup/pgdn page · g/G ends · esc/q close";
142
+ readonly 'panel.usage.totals': "Totals (whole session)";
143
+ readonly 'panel.usage.uncached': "uncached in";
144
+ readonly 'panel.usage.cacheWrite': "cache write";
145
+ readonly 'panel.usage.cacheRead': "cache read";
146
+ readonly 'panel.usage.output': "out";
147
+ readonly 'panel.usage.total': "total";
148
+ readonly 'panel.usage.cacheHit': "cache hit";
149
+ readonly 'panel.usage.turns': "Per turn";
150
+ readonly 'panel.usage.byModel': "By model";
151
+ readonly 'panel.usage.colTurns': "turns";
152
+ readonly 'panel.usage.unknownModel': "unattributed";
153
+ readonly 'panel.usage.colTurn': "turn";
154
+ readonly 'panel.usage.colTotal': "total";
155
+ readonly 'panel.usage.colUncached': "uncached";
156
+ readonly 'panel.usage.colCacheRead': "cache R";
157
+ readonly 'panel.usage.colCacheHit': "hit";
158
+ readonly 'panel.usage.colCacheWrite': "cache W";
159
+ readonly 'panel.usage.colOut': "out";
160
+ readonly 'panel.usage.colThink': "think";
161
+ readonly 'panel.usage.colModel': "model";
162
+ readonly 'panel.usage.partialNote': "+ marks a group where some turns did not report that bucket; only reported turns are counted";
163
+ readonly 'panel.usage.unavailable': "token projections are not mounted in this deployment (dsh-token-meter is missing)";
164
+ readonly 'panel.usage.noTurns': "no completed turn yet";
165
+ readonly 'status.cycleHint': "(shift+tab to cycle)";
166
+ readonly 'approval.compact': "approval{queued} · enter/y allow · esc/n reject";
167
+ readonly 'approval.overflow': "… +{count} more lines · ctrl+o shows the full call in the transcript";
168
+ readonly 'question.compact.plan': "plan review · esc cancel";
169
+ readonly 'question.compact.normal': "question · esc cancel";
170
+ readonly 'approval.submitted': "submitted…";
171
+ readonly 'approval.footer': "↑↓ choose · enter confirm · y/n/d quick · esc reject";
172
+ readonly 'question.footer': "↑↓ choose · 1-9 select · space toggle · enter submit · esc cancel";
173
+ readonly 'question.custom': "type a custom answer";
174
+ readonly 'question.submitted': "submitted…";
175
+ readonly 'question.customNoOptions': "↑↓/pgup/pgdn scroll · type answer · enter submit · esc interrupt";
176
+ readonly 'question.customOptions': "↑↓/pgup/pgdn scroll · type answer · enter submit · tab/esc or empty backspace: options";
177
+ readonly 'question.multiOptions': "↑↓ choose · pgup/pgdn scroll · space/1-9 toggle · enter submit · c custom · esc interrupt";
178
+ readonly 'question.singleOptions': "↑↓ choose · pgup/pgdn scroll · 1-9 pick · enter submit · c custom · esc interrupt";
179
+ readonly 'question.switch': " · ←→/ctrl+p/n switch question";
180
+ readonly 'question.title.plan': "📋 plan review";
181
+ readonly 'question.title.normal': "❓ question";
182
+ readonly 'composer.placeholder': "type a message · / commands · @ mentions · tab steers";
183
+ readonly 'composer.placeholderSteer': "steer into this turn · tab queues for the next one";
184
+ readonly 'notice.submitMode.queue': "send → queue for the next turn";
185
+ readonly 'notice.submitMode.steer': "send → steer into this turn (only while one runs; idle it sends normally)";
186
+ readonly 'entry.delivery.queued': "queued";
187
+ readonly 'entry.delivery.steered': "steered";
188
+ readonly 'status.shiftTabHint': "(shift+tab to cycle)";
189
+ readonly 'status.label.turns': "turns";
190
+ readonly 'status.label.steps': "steps";
191
+ readonly 'status.label.modelTime': "model";
192
+ readonly 'status.label.latency': "latency";
193
+ readonly 'status.label.tokensPerSec': " tokens/s";
194
+ readonly 'status.label.tool': "tool";
195
+ readonly 'status.label.cache': "cache";
196
+ readonly 'status.label.in': "in";
197
+ readonly 'status.label.out': "out";
198
+ readonly 'status.label.mode': "/mode";
199
+ readonly 'status.label.context': "context";
200
+ readonly 'frozen.keysGoTo': "keys go to {owner} · esc {action}";
201
+ readonly 'frozen.action.rejects': "rejects";
202
+ readonly 'frozen.action.cancels': "cancels";
203
+ readonly 'frozen.action.closes': "closes";
204
+ readonly 'time.justNow': "now";
205
+ readonly 'time.minutesAgo': "{n}m ago";
206
+ readonly 'time.hoursAgo': "{n}h ago";
207
+ readonly 'time.daysAgo': "{n}d ago";
208
+ readonly 'notice.themeSaved': "theme → {name}";
209
+ readonly 'notice.themeRainbow': "theme → rainbow · seed {seed} · /rainbow to reroll";
210
+ readonly 'notice.rainbowRolled': "rainbow · seed {seed} · /rainbow to reroll · /rainbow {seed} to pin";
211
+ readonly 'notice.languageSaved': "language → {name}";
212
+ readonly 'notice.themeSaveFailed': "theme save failed: {message}";
213
+ readonly 'notice.languageSaveFailed': "language save failed: {message}";
214
+ readonly 'notice.alreadyActive': "that session is already active";
215
+ readonly 'notice.queueCancelled': "queued message cancelled";
216
+ readonly 'notice.queueActionFailed': "queue action failed: {message}";
217
+ readonly 'notice.queueUnavailable': "queued message is no longer pending";
218
+ readonly 'notice.queueSteerUnavailable': "steering is available only while the turn is running";
219
+ readonly 'notice.queueEditEmpty': "queued message cannot be empty";
220
+ readonly 'notice.queueEdited': "queued message edited";
221
+ readonly 'notice.queueSteered': "queued message moved into this turn";
222
+ readonly 'notice.historySaveFailed': "history save failed: {message}";
223
+ readonly 'notice.turnCancelled': "turn cancelled — Ctrl+C or /quit to exit";
224
+ readonly 'notice.turnCancelledKeepQueue': "turn cancelled — pending messages are preserved · Ctrl+C or /quit to exit";
225
+ readonly 'notice.noSessionYet': "no session yet — submit a message to start";
226
+ readonly 'notice.usage.animation': "usage: /animation [on|off]";
227
+ readonly 'notice.usage.language': "usage: /language [en|zh]";
228
+ readonly 'notice.usage.rainbow': "usage: /rainbow [seed]";
229
+ readonly 'notice.imageCancelled': "image submission cancelled";
230
+ readonly 'notice.themeConfigUnreadable': "theme config unreadable, using dark: {message}";
231
+ readonly 'notice.languageConfigUnreadable': "language config unreadable, using english: {message}";
232
+ readonly 'notice.animationsConfigUnreadable': "animations config unreadable, animations stay on: {message}";
233
+ readonly 'notice.statuslineConfigUnreadable': "statusline config unreadable, using defaults: {message}";
234
+ readonly 'notice.sessionSearchUnavailable': "session search is unavailable in this deployment";
235
+ readonly 'notice.subagentsReadOnly': "subagent conversations are read-only";
236
+ readonly 'notice.statuslineSaveFailed': "statusline save failed: {message}";
237
+ readonly 'notice.animationsSaveFailed': "animations save failed: {message}";
238
+ readonly 'notice.commandRegistryMissing': "no command registry is mounted in this composition";
239
+ readonly 'notice.commandFallbackFailed': "command fallback failed: {message}";
240
+ readonly 'notice.commandFailed': "command failed: {message}";
241
+ readonly 'notice.invalidReference': "invalid session reference: {message}";
242
+ readonly 'notice.messageFailed': "{kind} failed: {message}";
243
+ readonly 'notice.referenceFailed': "session reference failed: {message}";
244
+ readonly 'notice.activationFailed': "session activation failed: {message}";
245
+ readonly 'notice.creationFailed': "session creation failed: {message}";
246
+ readonly 'notice.modeChanged': "mode → {value}";
247
+ readonly 'notice.modeSwitchFailed': "mode switch failed: {message}";
248
+ readonly 'notice.permissionChanged': "permission → {value}";
249
+ readonly 'notice.permissionChangeFailed': "permission change failed: {message}";
250
+ readonly 'notice.cancelFailed': "cancel failed: {message}";
251
+ readonly 'notice.modeChangeFailed': "mode change failed: {message}";
252
+ readonly 'notice.modelNotDefault': "model switch applies to this session but was not saved as the default: {message}";
253
+ readonly 'notice.modelSelectionRejected': "model selection rejected: {message} — reopen /model to pick again";
254
+ readonly 'notice.exported': "exported to {path}";
255
+ readonly 'notice.exportFailed': "export failed: {message}";
256
+ readonly 'notice.resumeFailed': "resume failed: {message}";
257
+ readonly 'notice.forkFailed': "fork failed: {message}";
258
+ readonly 'notice.sessionSwitchFailed': "session switch failed: {message}";
259
+ readonly 'notice.switchQueued': "will switch to {label} when the current turn finishes · /resume cancel to abort";
260
+ readonly 'notice.reviewStarted': "review started under read-only permissions";
261
+ readonly 'notice.reviewFailed': "review failed: {message}";
262
+ readonly 'notice.reviewUnavailable': "review unavailable: {message}";
263
+ readonly 'notice.startupImages': "processing {count} startup image{plural}…";
264
+ readonly 'notice.startupImagesAttached': "{count} startup image{plural} attached";
265
+ readonly 'notice.initialPromptFailed': "initial prompt failed: {message}";
266
+ readonly 'notice.rejected': "rejected — type below what it should do differently (it steers the next step)";
267
+ readonly 'notice.attachmentAlready': "{name} is already attached";
268
+ readonly 'notice.attachmentsChecking': "checking {count} attachment{plural}…";
269
+ readonly 'notice.attachmentsAlready': "those attachments are already attached";
270
+ readonly 'notice.attachmentDraftChanged': "draft changed at the attachment drop point; drop the files again";
271
+ readonly 'notice.attachmentsReady': "{count} attachment{plural} ready for the next message";
272
+ readonly 'notice.attachmentFailed': "attachment failed: {message}";
273
+ readonly 'notice.imageChecking': "checking image {name}…";
274
+ readonly 'notice.imageDraftChanged': "draft changed around the image mention; select it again";
275
+ readonly 'notice.imageReady': "{name} ready for the next message";
276
+ readonly 'notice.imageFailed': "image attachment failed: {message}";
277
+ readonly 'notice.cancelBeforeExit': "cancel the running turn before exiting (Esc or Ctrl+C)";
278
+ readonly 'notice.commandAttachments': "commands cannot carry attachments; the line will be sent to the model as a prompt";
279
+ readonly 'notice.copyFailed': "copy failed: {message}";
280
+ readonly 'notice.vscodeKeysFailed': "vscode-keys failed: {message}";
281
+ readonly 'notice.animationState': "animations {state}";
282
+ readonly 'notice.deleteFailed': "delete failed: {message}";
283
+ readonly 'notice.modelChangedPlaceholder': "model → {model} · image history will be sent as text placeholders";
284
+ readonly 'notice.modelNextStep': "model → next step uses {model}";
285
+ readonly 'notice.modelSwitchFailed': "model switch failed: {message}";
286
+ readonly 'notice.loggedIn': "logged in to {provider}; select a model";
287
+ readonly 'notice.loggedOut': "logged out from {provider}";
288
+ readonly 'notice.providerSaved': "provider configuration saved: {provider}{suffix}";
289
+ readonly 'notice.apiKeyRemoved': "API key removed for {provider}";
290
+ readonly 'notice.providerRemoved': "provider removed: {provider}";
291
+ readonly 'notice.providerUnavailable': "provider configuration is unavailable in this profile";
292
+ readonly 'notice.apiKeyUnavailable': "API key removal is unavailable in this profile";
293
+ readonly 'notice.providerRemovalUnavailable': "provider removal is unavailable in this profile";
294
+ readonly 'notice.loginIdleOnly': "provider login is available only while the agent is idle";
295
+ readonly 'notice.loginUnavailable': "provider login is unavailable in this profile";
296
+ readonly 'notice.logoutUnavailable': "provider logout is unavailable in this profile";
297
+ readonly 'notice.modeChangedSimple': "mode → {value}";
298
+ readonly 'notice.permissionChangedSimple': "permission → {value}";
299
+ readonly 'notice.subagentsChanged': "subagents → {value}";
300
+ readonly 'notice.subagentsInherited': "subagents → inherit current model";
301
+ readonly 'notice.subagentChangeFailed': "subagent model change failed: {message}";
302
+ readonly 'notice.modelMissing': "current model is not in the catalog";
303
+ readonly 'notice.effortUnavailable': "reasoning levels temporarily unavailable (capability lookup failed) — try again";
304
+ readonly 'notice.modelLookupFailed': "model lookup failed: {message}";
305
+ readonly 'notice.diffFailed': "diff failed: {message}";
306
+ readonly 'panel.footer.chooseSwitch': "↑↓ choose · enter switch · r refresh · esc close";
307
+ readonly 'panel.footer.chooseSelect': "↑↓ choose · enter select · r refresh · esc close";
308
+ readonly 'panel.footer.inspectDetails': "↑↓ inspect · enter details · r refresh · esc close";
309
+ readonly 'panel.footer.inspectRefresh': "↑↓ inspect · r refresh · esc close";
310
+ readonly 'panel.footer.resume': "tab/←→ filters · ↑↓/pg navigate · ctrl+f search · e details · t transcript · d delete · enter resume";
311
+ readonly 'panel.footer.transcript': "lines {from}-{to}/{total} · ↑↓/pg/g/G · t/esc close";
312
+ readonly 'panel.footer.history': "↑↓ move · g/G ends · enter fill · esc close";
313
+ readonly 'panel.footer.review': "↑↓ move · enter select · esc back · q close";
314
+ readonly 'panel.footer.statusline': "↑↓ move · space toggle · ←→ reorder · d default · esc close";
315
+ readonly 'panel.footer.schedule': "esc/q close{more} · the model schedules via schedule_create";
316
+ readonly 'panel.mode.title': "/mode · current {current}";
317
+ readonly 'panel.permission.title': "/permission · current {current}";
318
+ readonly 'panel.plugin.title': "/plugin · loader inspector";
319
+ readonly 'panel.jobs.title': "/jobs · background tasks · {count}";
320
+ readonly 'panel.resume.deleteTitle': "permanently delete {target}? this cannot be undone · subagent threads go too";
321
+ readonly 'panel.resume.title': "/resume{mode}{search} · {toolbar}";
322
+ readonly 'panel.noActiveReminders': "no active reminders — the model schedules via schedule_create";
323
+ readonly 'panel.notMounted': "not mounted";
324
+ readonly 'panel.broken': "broken: {message}";
325
+ readonly 'panel.live': "live";
326
+ readonly 'panel.parent': "parent {id}";
327
+ readonly 'panel.deleteMode': "delete mode";
328
+ readonly 'panel.searching': "searching";
329
+ readonly 'panel.noPresets': "no presets";
330
+ readonly 'panel.noPermissions': "no permission presets";
331
+ readonly 'panel.noJobs': "no background jobs";
332
+ readonly 'panel.diff.compact': "{title} · {files} files · esc/q close";
333
+ readonly 'panel.diff.noFiles': "no files";
334
+ readonly 'panel.diff.footer': "↑/↓ scroll · g/G ends · esc/q close";
335
+ readonly 'panel.todos.compact': "todos · esc/q close";
336
+ readonly 'panel.todos.title': "todos · {done}/{total} done · {active} active · {pending} pending · rows {from}-{to}/{rows}";
337
+ readonly 'panel.todos.empty': "no todos yet";
338
+ readonly 'panel.todos.footer': "↑↓ scroll · pgup/pgdn page · g/G ends · esc/q close";
339
+ readonly 'panel.verbose.compact': "history details · ctrl+o / esc / q close";
340
+ readonly 'panel.verbose.footer': "←→ entry · ↑↓ scroll · pgup/pgdn page · g/G ends · ctrl+o/esc/q close";
341
+ readonly 'panel.model.compact': "/model · {state}{providers} · {tail}";
342
+ readonly 'panel.model.noMatch': "no models match '{query}'";
343
+ readonly 'panel.model.compactNoMatch': "no match for '{query}'";
344
+ readonly 'panel.model.loading': "loading…";
345
+ readonly 'panel.model.error': "error";
346
+ readonly 'panel.model.noModels': "no models available";
347
+ readonly 'panel.model.selectTitle': "/model — select model";
348
+ readonly 'panel.model.matches': "{filtered} of {total} match '{query}'";
349
+ readonly 'panel.model.footer.filter': "type to filter · r retry · esc/q close";
350
+ readonly 'panel.model.footer.filtered': "backspace edits · esc close";
351
+ readonly 'panel.model.title': "/model — select model";
352
+ readonly 'panel.model.titleCount': "/model — select model · {index}/{total}";
353
+ readonly 'panel.model.titleMatches': "/model — select model · {filtered} of {total} match '{query}'";
354
+ readonly 'panel.model.footer.select': "type to filter · ↑↓ move · pgup/pgdn page · enter select{providers} · r retry · esc/q close";
355
+ readonly 'panel.model.footer.filteredSelect': "↑↓ move · pgup/pgdn page · enter select · backspace edits · esc close";
356
+ readonly 'panel.model.providers': "tab providers";
357
+ readonly 'panel.provider.failure': "unavailable providers: {providers}";
358
+ readonly 'panel.provider.loading': "loading providers…";
359
+ readonly 'panel.provider.empty': "no configurable providers";
360
+ readonly 'panel.provider.notConfigured': "not configured";
361
+ readonly 'panel.provider.configured': "configured";
362
+ readonly 'panel.provider.keyMissing': "key missing";
363
+ readonly 'panel.provider.keyStatusUnavailable': "key status unavailable";
364
+ readonly 'panel.provider.auth': "provider auth";
365
+ readonly 'panel.provider.active': "active";
366
+ readonly 'panel.provider.dormant': "dormant";
367
+ readonly 'panel.provider.readOnly': "read-only";
368
+ readonly 'panel.provider.custom': "custom";
369
+ readonly 'panel.provider.notConfiguredDivider': "── not configured ──";
370
+ readonly 'panel.provider.title': "/model — providers";
371
+ readonly 'panel.provider.titleCount': "/model — providers · {index}/{total}";
372
+ readonly 'panel.provider.state': "{route} · {value}";
373
+ readonly 'panel.provider.key': "key {value}";
374
+ readonly 'panel.provider.authConfigured': "provider auth";
375
+ readonly 'panel.provider.noKey': "key missing";
376
+ readonly 'panel.provider.noLogin': "not configured";
377
+ readonly 'panel.provider.loginStatusUnavailable': "login status unavailable: {message}";
378
+ readonly 'panel.provider.noConfiguredKey': "this provider has no configured API key to remove";
379
+ readonly 'panel.provider.readOnlyKey': "this API key is supplied read-only by the environment";
380
+ readonly 'panel.provider.notRemovable': "this provider profile is not removable";
381
+ readonly 'panel.provider.noLoginFlow': "this provider offers no interactive login flow";
382
+ readonly 'panel.provider.loginRunning': "a login attempt is already running for this provider";
383
+ readonly 'panel.provider.noLoginRecord': "this provider has no login record to remove";
384
+ readonly 'panel.provider.readOnlyLogin': "this login record is read-only";
385
+ readonly 'panel.provider.notManaged': "this provider is not managed by Harness settings";
386
+ readonly 'panel.providers.compact': "/model providers · enter configure · d remove key · esc back";
387
+ readonly 'panel.providers.footer': "↑↓ move · enter configure · l login · o logout · d remove key · x remove provider · r retry · esc back";
388
+ readonly 'panel.update.compact': "/update · {summary}";
389
+ readonly 'panel.update.checking': "checking…";
390
+ readonly 'panel.update.probeFailed': "probe failed";
391
+ readonly 'panel.update.updating': "updating…";
392
+ readonly 'panel.update.installed': "installed — restart to activate";
393
+ readonly 'panel.update.failed': "failed";
394
+ readonly 'panel.update.upToDate': "up to date";
395
+ readonly 'panel.update.aheadOfNpm': "newer than npm";
396
+ readonly 'panel.update.enter': "enter updates";
397
+ readonly 'panel.update.blocked': "blocked";
398
+ readonly 'panel.update.title': "/update · aligned upgrade";
399
+ readonly 'panel.auth.methodsFooter': "↑↓ choose · enter continue · esc/q back";
400
+ readonly 'panel.auth.answerFooter': "enter answer · c copy URL/code · esc cancel login";
401
+ readonly 'panel.auth.title': "/model · login {provider}";
402
+ readonly 'panel.auth.waiting': "waiting for provider…";
403
+ readonly 'panel.auth.compact': "provider login · esc cancel";
404
+ readonly 'panel.auth.logoutCompact': "y logout · n/esc back";
405
+ readonly 'panel.auth.logoutTitle': "/model · logout provider";
406
+ readonly 'panel.auth.removeRecord': "remove {provider} login record";
407
+ readonly 'panel.auth.unchanged': "provider endpoint and model configuration stay unchanged";
408
+ readonly 'panel.auth.working': "working…";
409
+ readonly 'panel.auth.logoutFooter': "y confirm · n/esc back";
410
+ readonly 'panel.setup.compact': "provider setup · terminal too small · esc back";
411
+ readonly 'panel.setup.noDonors': "no model with declared efforts yet; declare one with e, or hand-write settings";
412
+ readonly 'panel.setup.copyInto': "copy verbatim into {id}";
413
+ readonly 'panel.setup.copyTitle': "/model — copy efforts";
414
+ readonly 'panel.setup.copyFooter': "↑↓ move · enter copy · esc back";
415
+ readonly 'panel.setup.title': "/model — configure {provider}";
416
+ readonly 'panel.setup.footer': "↑↓ move · ←→ in/out · space remove · e efforts · c copy efforts · tab discover · enter save · esc back";
417
+ readonly 'panel.discovery.compact': "model discovery · terminal too small · esc back";
418
+ readonly 'panel.discovery.loading': "discovering models…";
419
+ readonly 'panel.discovery.empty': "the endpoint advertised no models; add ids by hand on the setup page";
420
+ readonly 'panel.discovery.summary': "{advertised} advertised · {newCount} new · {checked} checked";
421
+ readonly 'panel.discovery.title': "/model — discover {provider}";
422
+ readonly 'panel.discovery.footer': "↑↓ move · space check · enter adopt · f refetch · esc back";
423
+ readonly 'panel.update.footer.probe': "checking… · esc close";
424
+ readonly 'panel.update.footer.error': "r recheck · esc close";
425
+ readonly 'panel.update.footer.apply': "updating… · ↑↓ scroll · esc waits";
426
+ readonly 'panel.update.footer.current': "up to date · r recheck · esc close";
427
+ readonly 'panel.update.footer.ahead': "newer than npm — not downgrading · r recheck · esc close";
428
+ readonly 'panel.update.footer.update': "enter update · r recheck · esc close";
429
+ readonly 'panel.update.footer.blocked': "blocked · r recheck · esc close";
430
+ readonly 'panel.footer.effortEmpty': "esc back";
431
+ readonly 'panel.footer.effort': "↑↓ choose · enter apply · esc/q back";
432
+ readonly 'panel.effort.title': "/model — effort for {provider} · {model}";
433
+ readonly 'panel.effort.empty': "this model advertises no reasoning effort levels — the provider default applies";
434
+ readonly 'panel.default': "default";
435
+ readonly 'panel.footer.agents': "↑↓ choose · enter/t transcript · r refresh · esc close";
436
+ readonly 'panel.agents.title': "/agents · {live} live · {total} total";
437
+ readonly 'panel.document.title': "transcript · {id}";
438
+ readonly 'panel.subagent.transcriptTitle': "subagent · {id}";
439
+ readonly 'panel.footer.subagent': "↑↓ choose · enter apply · r refresh · esc close";
440
+ readonly 'panel.subagent.title': "/subagent — model for delegated agents";
441
+ readonly 'panel.subagent.override': " · override {value}";
442
+ readonly 'panel.subagent.inherit': "inherit — follow the current model (/model switches apply)";
443
+ readonly 'panel.statusline.compact': "/statusline · esc close";
444
+ readonly 'panel.schedule.compact': "/schedule · {summary}";
445
+ readonly 'panel.schedule.none': "no active reminders";
446
+ readonly 'panel.schedule.more': " · +{count} more";
447
+ readonly 'panel.schedule.footer': "esc/q close{more} · the model schedules via schedule_create";
448
+ };
449
+ export type MessageKey = keyof typeof en;
450
+ export type MessageCatalog = Record<MessageKey, string>;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * The Chinese message catalog: mirrors {@link en} key-for-key; the shared
3
+ * key union comes from the English catalog, so a missing key here fails
4
+ * typecheck.
5
+ *
6
+ * @module @deepseek-ai/dsh-tui/locales/zh
7
+ */
8
+ import type { MessageCatalog } from './en.ts';
9
+ export declare const zh: MessageCatalog;
@@ -6,7 +6,10 @@
6
6
  * canonical `@[label](dsh-session:…)` tokens; on submit the text is parsed
7
7
  * back into readable `@label` text plus structured references, snapshots are
8
8
  * injected via `agent.inject()` before the readable message wakes the driver
9
- * (`followup` idle, `steer` running) exactly the upstream README's wiring.
9
+ * (`followup`, which queues the next turn whether or not one is running) —
10
+ * exactly the upstream README's wiring. Steering the current turn is a
11
+ * deliberate user action through the `/queue` panel, never an implicit
12
+ * consequence of submitting while busy.
10
13
  *
11
14
  * File discovery lives entirely in the Harness service (per-agent bounded
12
15
  * index, `@dir/` listing, symlink guards, tool/result invalidation); this
@@ -21,6 +24,7 @@
21
24
  */
22
25
  import type { Context } from '@deepseek-ai/cordis';
23
26
  import type { Agent } from '@deepseek-ai/dsh-agent';
27
+ import type { UserMessage } from '@deepseek-ai/dsh-session';
24
28
  import { parseSessionReferenceText, type SessionReferenceCandidate, type SessionReferenceInput } from '@deepseek-ai/dsh-session-reference';
25
29
  /** Parsed submission text: readable text plus structured references. */
26
30
  type ParsedSessionReferenceText = ReturnType<typeof parseSessionReferenceText>;
@@ -42,14 +46,14 @@ export interface PreparedMention {
42
46
  /** Structured source sessions in appearance order (empty when none). */
43
47
  references: SessionReferenceInput[];
44
48
  /** Aggregated snapshot for `agent.inject()`, undefined without references. */
45
- additionalContext?: import('@deepseek-ai/dsh-session').UserMessage;
49
+ additionalContext?: UserMessage;
46
50
  }
47
51
  /** Whether a mention token is already navigating a filesystem path. */
48
52
  export declare function isPathLikeMentionQuery(query: string): boolean;
49
53
  /** The mention API the input editor and the runner share. */
50
54
  export interface MentionsApi {
51
55
  /** Ranked menu candidates for the typed `@` query. */
52
- candidates(query: string, signal?: AbortSignal): Promise<readonly MentionCandidate[]>;
56
+ candidates: (query: string, signal?: AbortSignal) => Promise<readonly MentionCandidate[]>;
53
57
  /** Parse submission text into readable text plus structured references. */
54
58
  parse(text: string): ParsedSessionReferenceText;
55
59
  /**
@@ -9,6 +9,7 @@
9
9
  */
10
10
  import type { Context } from '@deepseek-ai/cordis';
11
11
  import type { ModelSelection } from '@deepseek-ai/dsh-agent';
12
+ import type { SessionEvent } from '@deepseek-ai/dsh-session';
12
13
  import { type LlmCallConfig, type LlmModelReasoningInfo, type ModelModality } from '@deepseek-ai/dsh-llm';
13
14
  /** Display metadata for one adapter-owned reasoning effort (mirrors `LlmReasoningEffortInfo`). */
14
15
  export interface ModelReasoningEffort {
@@ -74,6 +75,19 @@ export declare function resolveEffectiveSelection(picked: ModelSelection | undef
74
75
  model: string;
75
76
  reasoningEffort?: string;
76
77
  } | undefined, defaults: ModelSelection): ModelSelection;
78
+ /**
79
+ * The session log's unconsumed explicit model selection (the resume layer of
80
+ * the documented precedence). `model/selection` events are log-only facts the
81
+ * web host's session-controller appends when its user picks a model for the
82
+ * NEXT request; a request header assembling exactly that selection retires
83
+ * it, while a header for different values (another route forced the request)
84
+ * leaves it armed. Seeding the resumed pick from here restores a selection
85
+ * that was made but never sent — the request header alone would answer with
86
+ * the older model.
87
+ * @param events - the full persisted event list of the resumed session.
88
+ * @returns the still-pending selection, when one exists.
89
+ */
90
+ export declare function pendingModelSelection(events: readonly SessionEvent[]): ModelSelection | undefined;
77
91
  /**
78
92
  * Build the selection one `/model` pick applies, rejecting an effort the
79
93
  * row does not advertise. The row is the picker's source of truth, so a
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Stable per-panel accents for the prismatic theme: every bordered panel
3
+ * claims the next slot in a first-seen sequence keyed by its stable id, so a
4
+ * screen with several open panels shows several ring colors while each panel
5
+ * keeps one learnable color. Deliberately NOT a React hook — several panels
6
+ * render through direct function calls inside conditionals, where hooks are
7
+ * illegal — and identity is by panel id, not by mount. Outside prismatic the
8
+ * helper is an identity: callers pass their usual border/title colors
9
+ * through unchanged and dark/light render pixel-identically.
10
+ *
11
+ * @module @deepseek-ai/dsh-tui/panel-accent
12
+ */
13
+ import { type RgbTriple } from './theme.ts';
14
+ /** One panel's resolved accent pair (border and title share the ring color in prismatic). */
15
+ export interface PanelAccent {
16
+ readonly border: RgbTriple;
17
+ readonly title: RgbTriple;
18
+ }
19
+ /**
20
+ * The accent pair for one panel: in prismatic both entries are the panel's
21
+ * ring color (border and title match, per the design); in every other theme
22
+ * they are exactly the colors passed in.
23
+ * @param id - stable panel identity ('todos', 'model', 'kernel-list', …).
24
+ * @param border - the border color used outside prismatic.
25
+ * @param title - the title color used outside prismatic (defaults to border).
26
+ * @returns the resolved accent pair for this panel.
27
+ */
28
+ export declare function panelAccent(id: string, border: RgbTriple, title?: RgbTriple): PanelAccent;
@@ -0,0 +1,69 @@
1
+ /**
2
+ * The rainbow theme's per-launch roll: a seeded shuffle over a twelve-color
3
+ * bright-tier spectrum that fills every palette role, the status-bar tone map
4
+ * (adjacent tones in canonical on-screen order never share a color, the
5
+ * row1/row2 boundary included), the panel accent ring, and full-spectrum
6
+ * flow anchors with a random phase. The roll happens once per launch and
7
+ * stays stable for the whole run; setting RAINBOW_SEED=<uint32> pins it for
8
+ * reproduction (the /theme notification prints the seed of the current roll).
9
+ *
10
+ * All pool colors clear AA body text (≥4.5:1) on a black terminal by a wide
11
+ * margin (11-17:1); diff rows pair a bright hue with its own 22% dark tint
12
+ * so the foreground stays 7.7-10.2:1 on its background.
13
+ *
14
+ * @module @deepseek-ai/dsh-tui/rainbow
15
+ */
16
+ import type { StatusTone } from './render/status.ts';
17
+ import type { RgbTriple, ThemePalette } from './theme.ts';
18
+ /**
19
+ * The bright-tier spectrum: twelve Tailwind *-300 hues covering red through
20
+ * fuchsia, every one ≥11:1 on black. The roll samples this pool by shuffle;
21
+ * nothing outside it is ever painted.
22
+ */
23
+ export declare const RAINBOW_POOL: readonly RgbTriple[];
24
+ /** One per-launch carnival roll: everything the rainbow theme paints from. */
25
+ export interface RainbowRoll {
26
+ /** The seed this roll came from (print it to reproduce). */
27
+ readonly seed: number;
28
+ /** The full 15-token palette for this launch. */
29
+ readonly palette: ThemePalette;
30
+ /** The four-color panel ring (random order and start). */
31
+ readonly ring: readonly RgbTriple[];
32
+ /** Status-tone → color: adjacent tones in {@link TONE_ORDER} never match. */
33
+ readonly toneColors: Readonly<Record<StatusTone, RgbTriple>>;
34
+ /** Full-spectrum flow anchors in hue order (a different subset every launch). */
35
+ readonly flowAnchors: readonly RgbTriple[];
36
+ /** Random phase offset into the flow lap, milliseconds. */
37
+ readonly flowPhaseMs: number;
38
+ }
39
+ /** Parse a RAINBOW_SEED value: a non-negative decimal uint32, else nothing. */
40
+ export declare function parseRainbowSeed(value: string | undefined): number | undefined;
41
+ /**
42
+ * One parsed `/rainbow` argument: empty means a fresh random roll; a
43
+ * decimal uint32 pins that seed; anything else is a usage error.
44
+ * @param argument - the raw text after `/rainbow`.
45
+ * @returns `{ seed }`, `'random'`, or `'usage'`.
46
+ */
47
+ export declare function parseRainbowArgument(argument: string): {
48
+ seed: number;
49
+ } | 'random' | 'usage';
50
+ /**
51
+ * Build the roll for one seed: pure and deterministic, so tests pin exact
52
+ * outcomes and RAINBOW_SEED reproduces a lucky launch exactly.
53
+ * @param seed - the uint32 seed to roll from.
54
+ * @returns the complete carnival roll.
55
+ */
56
+ export declare function rollRainbow(seed: number): RainbowRoll;
57
+ /** The memoized per-launch roll; computed once, stable for the whole run. */
58
+ export declare function rainbowRoll(): RainbowRoll;
59
+ /**
60
+ * Replace the memoized roll: omit the seed for a fresh random one, or pass
61
+ * a uint32 to pin it. `/rainbow` uses this so a mid-session reroll actually
62
+ * recolors; {@link setTheme}(`'rainbow'`) must run afterwards so the
63
+ * palette accessor picks the new values up.
64
+ * @param seed - the seed to pin, or undefined for a new random roll.
65
+ * @returns the roll now in force.
66
+ */
67
+ export declare function rerollRainbow(seed?: number): RainbowRoll;
68
+ /** The current roll's seed as display copy (also the RAINBOW_SEED value). */
69
+ export declare function rainbowSeedLabel(): string;