@deepseek-harness-tui/dsh-tui 0.11.2 → 0.12.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.
- package/README.md +21 -5
- package/bin/dsh-tui.js +30 -3
- package/cordis.patch.yml +24 -5
- package/guide/dsh-tui-guide/SKILL.md +37 -0
- package/guide/dsh-tui-guide/configuration.en.md +410 -0
- package/guide/dsh-tui-guide/configuration.md +349 -0
- package/guide/dsh-tui-guide/getting-started.en.md +398 -0
- package/guide/dsh-tui-guide/getting-started.md +397 -0
- package/guide/dsh-tui-guide/interaction.en.md +674 -0
- package/guide/dsh-tui-guide/interaction.md +747 -0
- package/guide/dsh-tui-guide/migrate.en.md +166 -0
- package/guide/dsh-tui-guide/migrate.md +132 -0
- package/guide/dsh-tui-guide/plugins.en.md +68 -0
- package/guide/dsh-tui-guide/plugins.md +56 -0
- package/guide/dsh-tui-guide/themes.en.md +192 -0
- package/guide/dsh-tui-guide/themes.md +185 -0
- package/guide/dsh-tui-guide/user-guide.en.md +608 -0
- package/guide/dsh-tui-guide/user-guide.md +586 -0
- package/guide/dsh-tui-guide/vscode.en.md +301 -0
- package/guide/dsh-tui-guide/vscode.md +272 -0
- package/lib/settings.json +5 -5
- package/lib/types/adapter/channel/ui-policy.d.ts +3 -2
- package/lib/types/adapter/channel/ui-policy.d.ts.map +1 -1
- package/lib/types/adapter/channel/ui-policy.js +4 -0
- package/lib/types/adapter/ports/channel-settings.d.ts +2 -1
- package/lib/types/adapter/ports/channel-settings.d.ts.map +1 -1
- package/lib/types/adapter/ports/channel-ui.d.ts +29 -2
- package/lib/types/adapter/ports/channel-ui.d.ts.map +1 -1
- package/lib/types/adapter/ports/channel-view.d.ts +43 -9
- package/lib/types/adapter/ports/channel-view.d.ts.map +1 -1
- package/lib/types/components/Chat/JobCard.d.ts +9 -0
- package/lib/types/components/Chat/JobCard.d.ts.map +1 -1
- package/lib/types/components/Chat/JobCard.js +42 -15
- package/lib/types/components/Chat/SubagentMessage.js +6 -6
- package/lib/types/components/JobsPanel.d.ts.map +1 -1
- package/lib/types/components/JobsPanel.js +80 -33
- package/lib/types/components/MessageList.js +3 -3
- package/lib/types/components/PresetPicker.d.ts +4 -0
- package/lib/types/components/PresetPicker.d.ts.map +1 -1
- package/lib/types/components/PresetPicker.js +5 -1
- package/lib/types/components/PromptInput.d.ts.map +1 -1
- package/lib/types/components/PromptInput.js +12 -1
- package/lib/types/components/StarPrompt.d.ts +6 -0
- package/lib/types/components/StarPrompt.d.ts.map +1 -1
- package/lib/types/components/StarPrompt.js +45 -0
- package/lib/types/components/SubagentCard.d.ts.map +1 -1
- package/lib/types/components/SubagentCard.js +8 -8
- package/lib/types/components/SubagentDetailScene.d.ts.map +1 -1
- package/lib/types/components/SubagentDetailScene.js +108 -10
- package/lib/types/components/WhaleGirl.d.ts +6 -0
- package/lib/types/components/WhaleGirl.d.ts.map +1 -1
- package/lib/types/components/WhaleGirl.js +18 -0
- package/lib/types/components/messages/AssistantThinkingMessage.js +4 -4
- package/lib/types/components/trajectory/MiniWake.d.ts +11 -1
- package/lib/types/components/trajectory/MiniWake.d.ts.map +1 -1
- package/lib/types/components/trajectory/MiniWake.js +9 -3
- package/lib/types/dsh-adapter/channel/external-commands.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/external-commands.js +8 -2
- package/lib/types/dsh-adapter/channel/job-projection.d.ts +1 -0
- package/lib/types/dsh-adapter/channel/job-projection.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/job-projection.js +88 -3
- package/lib/types/dsh-adapter/channel/mode-actions.d.ts +13 -0
- package/lib/types/dsh-adapter/channel/mode-actions.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/mode-actions.js +48 -7
- package/lib/types/dsh-adapter/channel/mode-permission-actions.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/mode-permission-actions.js +25 -9
- package/lib/types/dsh-adapter/channel/preferences.d.ts +1 -1
- package/lib/types/dsh-adapter/channel/preferences.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/preferences.js +17 -7
- package/lib/types/dsh-adapter/channel/state.d.ts +4 -2
- package/lib/types/dsh-adapter/channel/state.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/state.js +1 -1
- package/lib/types/dsh-adapter/channel/subagent-projection.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/subagent-projection.js +5 -0
- package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel.js +16 -1
- package/lib/types/dsh-adapter/contract.d.ts +5 -4
- package/lib/types/dsh-adapter/contract.d.ts.map +1 -1
- package/lib/types/dsh-adapter/contract.js +9 -3
- package/lib/types/dsh-adapter/jobs.d.ts +82 -16
- package/lib/types/dsh-adapter/jobs.d.ts.map +1 -1
- package/lib/types/dsh-adapter/jobs.js +104 -9
- package/lib/types/dsh-adapter/oauth/bonus.d.ts +27 -0
- package/lib/types/dsh-adapter/oauth/bonus.d.ts.map +1 -0
- package/lib/types/dsh-adapter/oauth/bonus.js +69 -0
- package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/command.d.ts +2 -1
- package/lib/types/dsh-adapter/oauth/command.d.ts.map +1 -0
- package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/command.js +7 -4
- package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/credentials.d.ts +13 -10
- package/lib/types/dsh-adapter/oauth/credentials.d.ts.map +1 -0
- package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/credentials.js +61 -23
- package/lib/types/dsh-adapter/oauth/deepseek.d.ts +39 -0
- package/lib/types/dsh-adapter/oauth/deepseek.d.ts.map +1 -0
- package/lib/types/dsh-adapter/oauth/deepseek.js +189 -0
- package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/index.d.ts +24 -16
- package/lib/types/dsh-adapter/oauth/index.d.ts.map +1 -0
- package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/index.js +34 -20
- package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/interaction.d.ts +14 -12
- package/lib/types/dsh-adapter/oauth/interaction.d.ts.map +1 -0
- package/lib/types/dsh-adapter/oauth/interaction.js +283 -0
- package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/opener.d.ts +2 -1
- package/lib/types/dsh-adapter/oauth/opener.d.ts.map +1 -0
- package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/opener.js +1 -1
- package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/pi-ai.d.ts +10 -3
- package/lib/types/dsh-adapter/oauth/pi-ai.d.ts.map +1 -0
- package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/pi-ai.js +8 -3
- package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/profiles.d.ts +6 -3
- package/lib/types/dsh-adapter/oauth/profiles.d.ts.map +1 -0
- package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/profiles.js +11 -3
- package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/service.d.ts +14 -7
- package/lib/types/dsh-adapter/oauth/service.d.ts.map +1 -0
- package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/service.js +82 -17
- package/lib/types/dsh-adapter/plugin.d.ts +8 -1
- package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
- package/lib/types/dsh-adapter/plugin.js +72 -12
- package/lib/types/dsh-adapter/presets.d.ts +6 -4
- package/lib/types/dsh-adapter/presets.d.ts.map +1 -1
- package/lib/types/dsh-adapter/presets.js +6 -4
- package/lib/types/dsh-adapter/providerWizard.d.ts.map +1 -1
- package/lib/types/dsh-adapter/providerWizard.js +6 -2
- package/lib/types/dsh-adapter/subagents.d.ts +1 -0
- package/lib/types/dsh-adapter/subagents.d.ts.map +1 -1
- package/lib/types/dsh-adapter/subagents.js +10 -1
- package/lib/types/i18n.d.ts +174 -18
- package/lib/types/i18n.d.ts.map +1 -1
- package/lib/types/i18n.js +53 -11
- package/lib/types/ink/components/App.d.ts.map +1 -1
- package/lib/types/ink/components/App.js +10 -1
- package/lib/types/ink/parse-keypress.d.ts +35 -0
- package/lib/types/ink/parse-keypress.d.ts.map +1 -1
- package/lib/types/ink/parse-keypress.js +611 -83
- package/lib/types/ink/terminal-querier.d.ts +25 -0
- package/lib/types/ink/terminal-querier.d.ts.map +1 -1
- package/lib/types/ink/terminal-querier.js +42 -0
- package/lib/types/ink/update-overflow-guard.d.ts +24 -0
- package/lib/types/ink/update-overflow-guard.d.ts.map +1 -1
- package/lib/types/ink/update-overflow-guard.js +25 -3
- package/lib/types/minimalUiMode.d.ts +19 -0
- package/lib/types/minimalUiMode.d.ts.map +1 -0
- package/lib/types/minimalUiMode.js +23 -0
- package/lib/types/oauth.d.ts +5 -10
- package/lib/types/oauth.d.ts.map +1 -1
- package/lib/types/oauth.js +5 -10
- package/lib/types/screens/Chat.d.ts +4 -1
- package/lib/types/screens/Chat.d.ts.map +1 -1
- package/lib/types/screens/Chat.js +27 -7
- package/lib/types/screens/StatusLine.d.ts +4 -0
- package/lib/types/screens/StatusLine.d.ts.map +1 -1
- package/lib/types/screens/StatusLine.js +12 -12
- package/lib/types/settings/definitions.js +4 -4
- package/lib/types/tips.d.ts.map +1 -1
- package/lib/types/tips.js +10 -4
- package/lib/types/update.js +2 -2
- package/lib/types/utils/pastedImagePath.d.ts +8 -0
- package/lib/types/utils/pastedImagePath.d.ts.map +1 -1
- package/lib/types/utils/pastedImagePath.js +29 -5
- package/package.json +111 -100
- package/presets/liangshen/agent.cordis.yml +4 -1
- package/presets/liangshen/preset.yml +1 -1
- package/lib/types/minimalMode.d.ts +0 -13
- package/lib/types/minimalMode.d.ts.map +0 -1
- package/lib/types/minimalMode.js +0 -17
- package/node_modules/@deepseek-harness-tui/dsh-auth/LICENSE +0 -21
- package/node_modules/@deepseek-harness-tui/dsh-auth/README.md +0 -143
- package/node_modules/@deepseek-harness-tui/dsh-auth/cordis.patch.yml +0 -11
- package/node_modules/@deepseek-harness-tui/dsh-auth/dsh-plugin.json +0 -44
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/interaction.js +0 -193
- package/node_modules/@deepseek-harness-tui/dsh-auth/package.json +0 -69
|
@@ -28,6 +28,11 @@ export type TerminalQuery<T extends TerminalResponse = TerminalResponse> = {
|
|
|
28
28
|
request: string;
|
|
29
29
|
/** Recognizes the expected response in the inbound stream */
|
|
30
30
|
match: (r: TerminalResponse) => r is T;
|
|
31
|
+
/** The response type this query can be answered by, declared separately
|
|
32
|
+
* from `match` (a predicate cannot be introspected). The input parser
|
|
33
|
+
* reads it through {@link TerminalQuerier.pendingResponseTypes} to bind
|
|
34
|
+
* an ambiguous reply tail to the queries actually awaiting an answer. */
|
|
35
|
+
responseType: TerminalResponse['type'];
|
|
31
36
|
};
|
|
32
37
|
type DecrpmResponse = Extract<TerminalResponse, {
|
|
33
38
|
type: 'decrpm';
|
|
@@ -139,6 +144,26 @@ export declare class TerminalQuerier {
|
|
|
139
144
|
constructor(stdout: NodeJS.WriteStream, setRawMode?: ((enabled: boolean) => void) | undefined);
|
|
140
145
|
/** Whether terminal query I/O is paused for an external process handoff. */
|
|
141
146
|
get isSuspended(): boolean;
|
|
147
|
+
/**
|
|
148
|
+
* In-flight evidence for the input parser (read-only observation): true
|
|
149
|
+
* while at least one query or flush sentinel is still waiting for its
|
|
150
|
+
* reply. Purely observational — queue semantics are untouched.
|
|
151
|
+
*/
|
|
152
|
+
get hasPending(): boolean;
|
|
153
|
+
/**
|
|
154
|
+
* In-flight evidence for the input parser (read-only observation): the
|
|
155
|
+
* response types of the queries still awaiting a reply, plus `da1` when a
|
|
156
|
+
* flush() sentinel is still open (DA1 is the reply that resolves it).
|
|
157
|
+
*
|
|
158
|
+
* This is bound to the query lifecycle on purpose. A boolean "something
|
|
159
|
+
* was sent recently" lets any recent query authorize a claim for bytes
|
|
160
|
+
* that may belong to no query at all, so the parser receives the expected
|
|
161
|
+
* types instead: a reply tail is only claimed when its shape can complete
|
|
162
|
+
* into one of them, and a query resolved by a sentinel stops counting the
|
|
163
|
+
* moment its promise settles. Purely observational — queue semantics are
|
|
164
|
+
* untouched.
|
|
165
|
+
*/
|
|
166
|
+
get pendingResponseTypes(): ReadonlySet<TerminalResponse['type']>;
|
|
142
167
|
private holdRawMode;
|
|
143
168
|
/**
|
|
144
169
|
* Send a query and wait for its response.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terminal-querier.d.ts","sourceRoot":"","sources":["../../../src/ink/terminal-querier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAI3D;;4CAE4C;AAC5C,MAAM,MAAM,aAAa,CAAC,CAAC,SAAS,gBAAgB,GAAG,gBAAgB,IAAI;IACzE,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAA;IACf,6DAA6D;IAC7D,KAAK,EAAE,CAAC,CAAC,EAAE,gBAAgB,KAAK,CAAC,IAAI,CAAC,CAAA;CACvC,CAAA;AAED,KAAK,cAAc,GAAG,OAAO,CAAC,gBAAgB,EAAE;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC,CAAA;AACnE,KAAK,WAAW,GAAG,OAAO,CAAC,gBAAgB,EAAE;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC,CAAA;AAC7D,KAAK,WAAW,GAAG,OAAO,CAAC,gBAAgB,EAAE;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC,CAAA;AAC7D,KAAK,aAAa,GAAG,OAAO,CAAC,gBAAgB,EAAE;IAAE,IAAI,EAAE,eAAe,CAAA;CAAE,CAAC,CAAA;AACzE,KAAK,qBAAqB,GAAG,OAAO,CAAC,gBAAgB,EAAE;IAAE,IAAI,EAAE,eAAe,CAAA;CAAE,CAAC,CAAA;AACjF,KAAK,yBAAyB,GAAG,OAAO,CACtC,gBAAgB,EAChB;IAAE,IAAI,EAAE,mBAAmB,CAAA;CAAE,CAC9B,CAAA;AACD,KAAK,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,EAAE;IAAE,IAAI,EAAE,gBAAgB,CAAA;CAAE,CAAC,CAAA;AAC9E,KAAK,WAAW,GAAG,OAAO,CAAC,gBAAgB,EAAE;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC,CAAA;AAC7D,KAAK,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,EAAE;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,CAAC,CAAA;AAIzE;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CAAC,cAAc,CAAC,
|
|
1
|
+
{"version":3,"file":"terminal-querier.d.ts","sourceRoot":"","sources":["../../../src/ink/terminal-querier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAI3D;;4CAE4C;AAC5C,MAAM,MAAM,aAAa,CAAC,CAAC,SAAS,gBAAgB,GAAG,gBAAgB,IAAI;IACzE,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAA;IACf,6DAA6D;IAC7D,KAAK,EAAE,CAAC,CAAC,EAAE,gBAAgB,KAAK,CAAC,IAAI,CAAC,CAAA;IACtC;;;8EAG0E;IAC1E,YAAY,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAA;CACvC,CAAA;AAED,KAAK,cAAc,GAAG,OAAO,CAAC,gBAAgB,EAAE;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC,CAAA;AACnE,KAAK,WAAW,GAAG,OAAO,CAAC,gBAAgB,EAAE;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC,CAAA;AAC7D,KAAK,WAAW,GAAG,OAAO,CAAC,gBAAgB,EAAE;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC,CAAA;AAC7D,KAAK,aAAa,GAAG,OAAO,CAAC,gBAAgB,EAAE;IAAE,IAAI,EAAE,eAAe,CAAA;CAAE,CAAC,CAAA;AACzE,KAAK,qBAAqB,GAAG,OAAO,CAAC,gBAAgB,EAAE;IAAE,IAAI,EAAE,eAAe,CAAA;CAAE,CAAC,CAAA;AACjF,KAAK,yBAAyB,GAAG,OAAO,CACtC,gBAAgB,EAChB;IAAE,IAAI,EAAE,mBAAmB,CAAA;CAAE,CAC9B,CAAA;AACD,KAAK,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,EAAE;IAAE,IAAI,EAAE,gBAAgB,CAAA;CAAE,CAAC,CAAA;AAC9E,KAAK,WAAW,GAAG,OAAO,CAAC,gBAAgB,EAAE;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC,CAAA;AAC7D,KAAK,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,EAAE;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,CAAC,CAAA;AAIzE;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CAAC,cAAc,CAAC,CAMlE;AAED;;;;;GAKG;AACH,wBAAgB,GAAG,IAAI,aAAa,CAAC,WAAW,CAAC,CAMhD;AAED;;;GAGG;AACH,wBAAgB,GAAG,IAAI,aAAa,CAAC,WAAW,CAAC,CAMhD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,IAAI,aAAa,CAAC,aAAa,CAAC,CAM5D;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,GACd,aAAa,CAAC,qBAAqB,CAAC,CAUtC;AAED,0EAA0E;AAC1E,wBAAgB,sBAAsB,IAAI,aAAa,CAAC,yBAAyB,CAAC,CAOjF;AAED,0EAA0E;AAC1E,wBAAgB,wBAAwB,IAAI,aAAa,CAAC,yBAAyB,CAAC,CAOnF;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,IAAI,aAAa,CAAC,iBAAiB,CAAC,CAMjE;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CAAC,WAAW,CAAC,CAMjE;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,IAAI,aAAa,CAAC,iBAAiB,CAAC,CAM5D;AAiBD;;;GAGG;AACH,qBAAa,eAAe;IAmBxB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,UAAU,CAAC;IAnBrB;;;;OAIG;IACH,OAAO,CAAC,KAAK,CAAgB;IAE7B;;;;;;OAMG;IACH,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,SAAS,CAAQ;gBAGf,MAAM,EAAE,MAAM,CAAC,WAAW,EAC1B,UAAU,CAAC,GAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,aAAA;IAGjD,4EAA4E;IAC5E,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED;;;;OAIG;IACH,IAAI,UAAU,IAAI,OAAO,CAExB;IAED;;;;;;;;;;;;OAYG;IACH,IAAI,oBAAoB,IAAI,WAAW,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAOhE;IAED,OAAO,CAAC,WAAW;IAKnB;;;;;;;;;;;;OAYG;IACH,IAAI,CAAC,CAAC,SAAS,gBAAgB,EAC7B,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,GACtB,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;IAczB;;;;;;;;OAQG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IACtB,KAAK,CAAC,OAAO,EAAE;QAAE,UAAU,EAAE,IAAI,CAAA;KAAE,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC;IAatE,8EAA8E;IAC9E,OAAO,IAAI,IAAI;IAMf;;;OAGG;IACH,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,gBAAgB,KAAK,IAAI,CAAC,GAAG,SAAS,CAAY;IAEtE;;;;;;;;;;;;;;;;;;;OAmBG;IACH,UAAU,CAAC,CAAC,EAAE,gBAAgB,GAAG,IAAI;IA4BrC;;;;OAIG;IACH,OAAO,IAAI,IAAI;IAMf,6EAA6E;IAC7E,MAAM,IAAI,IAAI;IAId,OAAO,CAAC,YAAY;CAOrB"}
|
|
@@ -32,6 +32,7 @@ export function decrqm(mode) {
|
|
|
32
32
|
return {
|
|
33
33
|
request: csi(`?${mode}$p`),
|
|
34
34
|
match: (r) => r.type === 'decrpm' && r.mode === mode,
|
|
35
|
+
responseType: 'decrpm',
|
|
35
36
|
};
|
|
36
37
|
}
|
|
37
38
|
/**
|
|
@@ -44,6 +45,7 @@ export function da1() {
|
|
|
44
45
|
return {
|
|
45
46
|
request: csi('c'),
|
|
46
47
|
match: (r) => r.type === 'da1',
|
|
48
|
+
responseType: 'da1',
|
|
47
49
|
};
|
|
48
50
|
}
|
|
49
51
|
/**
|
|
@@ -54,6 +56,7 @@ export function da2() {
|
|
|
54
56
|
return {
|
|
55
57
|
request: csi('>c'),
|
|
56
58
|
match: (r) => r.type === 'da2',
|
|
59
|
+
responseType: 'da2',
|
|
57
60
|
};
|
|
58
61
|
}
|
|
59
62
|
/**
|
|
@@ -65,6 +68,7 @@ export function kittyKeyboard() {
|
|
|
65
68
|
return {
|
|
66
69
|
request: csi('?u'),
|
|
67
70
|
match: (r) => r.type === 'kittyKeyboard',
|
|
71
|
+
responseType: 'kittyKeyboard',
|
|
68
72
|
};
|
|
69
73
|
}
|
|
70
74
|
/**
|
|
@@ -78,6 +82,7 @@ export function kittyGraphics(imageId) {
|
|
|
78
82
|
// same direct-data + compression path used by real renderer uploads.
|
|
79
83
|
request: `\u001b_Gi=${id},s=1,v=1,a=q,t=d,f=32,o=z;eAFjYGBgAAAABAAB\u001b\\`,
|
|
80
84
|
match: (r) => r.type === 'kittyGraphics' && r.imageId === id,
|
|
85
|
+
responseType: 'kittyGraphics',
|
|
81
86
|
};
|
|
82
87
|
}
|
|
83
88
|
/** XTWINOPS: query the physical pixel dimensions of one terminal cell. */
|
|
@@ -85,6 +90,7 @@ export function terminalCellSizePixels() {
|
|
|
85
90
|
return {
|
|
86
91
|
request: csi('16t'),
|
|
87
92
|
match: (r) => r.type === 'terminalPixelSize' && r.scope === 'cell',
|
|
93
|
+
responseType: 'terminalPixelSize',
|
|
88
94
|
};
|
|
89
95
|
}
|
|
90
96
|
/** XTWINOPS: query the terminal text area's physical pixel dimensions. */
|
|
@@ -92,6 +98,7 @@ export function terminalWindowSizePixels() {
|
|
|
92
98
|
return {
|
|
93
99
|
request: csi('14t'),
|
|
94
100
|
match: (r) => r.type === 'terminalPixelSize' && r.scope === 'window',
|
|
101
|
+
responseType: 'terminalPixelSize',
|
|
95
102
|
};
|
|
96
103
|
}
|
|
97
104
|
/**
|
|
@@ -105,6 +112,7 @@ export function cursorPosition() {
|
|
|
105
112
|
return {
|
|
106
113
|
request: csi('?6n'),
|
|
107
114
|
match: (r) => r.type === 'cursorPosition',
|
|
115
|
+
responseType: 'cursorPosition',
|
|
108
116
|
};
|
|
109
117
|
}
|
|
110
118
|
/**
|
|
@@ -117,6 +125,7 @@ export function oscColor(code) {
|
|
|
117
125
|
return {
|
|
118
126
|
request: osc(code, '?'),
|
|
119
127
|
match: (r) => r.type === 'osc' && r.code === code,
|
|
128
|
+
responseType: 'osc',
|
|
120
129
|
};
|
|
121
130
|
}
|
|
122
131
|
/**
|
|
@@ -131,6 +140,7 @@ export function xtversion() {
|
|
|
131
140
|
return {
|
|
132
141
|
request: csi('>0q'),
|
|
133
142
|
match: (r) => r.type === 'xtversion',
|
|
143
|
+
responseType: 'xtversion',
|
|
134
144
|
};
|
|
135
145
|
}
|
|
136
146
|
// -- Querier --
|
|
@@ -166,6 +176,37 @@ export class TerminalQuerier {
|
|
|
166
176
|
get isSuspended() {
|
|
167
177
|
return this.suspended;
|
|
168
178
|
}
|
|
179
|
+
/**
|
|
180
|
+
* In-flight evidence for the input parser (read-only observation): true
|
|
181
|
+
* while at least one query or flush sentinel is still waiting for its
|
|
182
|
+
* reply. Purely observational — queue semantics are untouched.
|
|
183
|
+
*/
|
|
184
|
+
get hasPending() {
|
|
185
|
+
return this.queue.length > 0;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* In-flight evidence for the input parser (read-only observation): the
|
|
189
|
+
* response types of the queries still awaiting a reply, plus `da1` when a
|
|
190
|
+
* flush() sentinel is still open (DA1 is the reply that resolves it).
|
|
191
|
+
*
|
|
192
|
+
* This is bound to the query lifecycle on purpose. A boolean "something
|
|
193
|
+
* was sent recently" lets any recent query authorize a claim for bytes
|
|
194
|
+
* that may belong to no query at all, so the parser receives the expected
|
|
195
|
+
* types instead: a reply tail is only claimed when its shape can complete
|
|
196
|
+
* into one of them, and a query resolved by a sentinel stops counting the
|
|
197
|
+
* moment its promise settles. Purely observational — queue semantics are
|
|
198
|
+
* untouched.
|
|
199
|
+
*/
|
|
200
|
+
get pendingResponseTypes() {
|
|
201
|
+
const types = new Set();
|
|
202
|
+
for (const pending of this.queue) {
|
|
203
|
+
if (pending.kind === 'query')
|
|
204
|
+
types.add(pending.responseType);
|
|
205
|
+
else
|
|
206
|
+
types.add('da1');
|
|
207
|
+
}
|
|
208
|
+
return types;
|
|
209
|
+
}
|
|
169
210
|
holdRawMode() {
|
|
170
211
|
this.setRawMode?.(true);
|
|
171
212
|
return () => this.setRawMode?.(false);
|
|
@@ -190,6 +231,7 @@ export class TerminalQuerier {
|
|
|
190
231
|
this.queue.push({
|
|
191
232
|
kind: 'query',
|
|
192
233
|
match: query.match,
|
|
234
|
+
responseType: query.responseType,
|
|
193
235
|
resolve: r => resolve(r),
|
|
194
236
|
releaseRawMode: this.holdRawMode(),
|
|
195
237
|
});
|
|
@@ -58,5 +58,29 @@ export declare function swallowNestedUpdateOverflow(error: unknown, source: stri
|
|
|
58
58
|
* @param onChange - The subscriber callback about to run.
|
|
59
59
|
*/
|
|
60
60
|
export declare function callWithUpdateOverflowGuard(source: string, onChange: () => void): void;
|
|
61
|
+
/**
|
|
62
|
+
* Origin of a process-level fatal error, as reported to the sink.
|
|
63
|
+
*/
|
|
64
|
+
export type ProcessGuardOrigin = 'uncaughtException' | 'unhandledRejection';
|
|
65
|
+
/**
|
|
66
|
+
* Fatal-error sink installed by the process owner (the dsh-tui runtime, which
|
|
67
|
+
* routes it into the TUI's single exit funnel). Returning true means the sink
|
|
68
|
+
* took ownership of the process — it runs the teardown (resume marker,
|
|
69
|
+
* terminal restore, `dsh-tui crashed: …`) and exits non-zero. Returning false
|
|
70
|
+
* leaves the error to Node's default crash, which keeps "fail loud, non-zero"
|
|
71
|
+
* true when no sink is registered or the tree is being torn down.
|
|
72
|
+
*/
|
|
73
|
+
export type ProcessGuardFatalSink = (error: unknown, origin: ProcessGuardOrigin) => boolean;
|
|
74
|
+
/** Register (or clear, with undefined) the fatal-error sink. */
|
|
75
|
+
export declare function registerProcessGuardFatalSink(sink: ProcessGuardFatalSink | undefined): void;
|
|
76
|
+
/**
|
|
77
|
+
* Normalize the reason handed to a fatal sink so the exit funnel can never
|
|
78
|
+
* mistake a fatal error for a clean user exit. `Promise.reject()` and
|
|
79
|
+
* `throw undefined` deliver `undefined`, and the funnel selects its crash path
|
|
80
|
+
* with `error !== undefined` — passing the raw reason through would run the
|
|
81
|
+
* zero-exit path while the sink reported that it owned the process. Defined
|
|
82
|
+
* reasons (including non-Error values) are returned unchanged.
|
|
83
|
+
*/
|
|
84
|
+
export declare function fatalReasonForExit(error: unknown, origin: ProcessGuardOrigin): unknown;
|
|
61
85
|
export declare function installNestedUpdateOverflowProcessGuard(): void;
|
|
62
86
|
//# sourceMappingURL=update-overflow-guard.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update-overflow-guard.d.ts","sourceRoot":"","sources":["../../../src/ink/update-overflow-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAoBH,2EAA2E;AAC3E,MAAM,MAAM,cAAc,GAAG,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;AAOjD,+CAA+C;AAC/C,wBAAgB,+BAA+B,IAAI,IAAI,CAEtD;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,CAEnF;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAG9D;AAED;;;;;;;;GAQG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAmDnF;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAOtF;
|
|
1
|
+
{"version":3,"file":"update-overflow-guard.d.ts","sourceRoot":"","sources":["../../../src/ink/update-overflow-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAoBH,2EAA2E;AAC3E,MAAM,MAAM,cAAc,GAAG,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;AAOjD,+CAA+C;AAC/C,wBAAgB,+BAA+B,IAAI,IAAI,CAEtD;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,CAEnF;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAG9D;AAED;;;;;;;;GAQG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAmDnF;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAOtF;AAED;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,mBAAmB,GAAG,oBAAoB,CAAA;AAE3E;;;;;;;GAOG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,kBAAkB,KAAK,OAAO,CAAA;AAG3F,gEAAgE;AAChE,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,qBAAqB,GAAG,SAAS,GAAG,IAAI,CAE3F;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAEtF;AAiBD,wBAAgB,uCAAuC,IAAI,IAAI,CAgB9D"}
|
|
@@ -130,6 +130,22 @@ export function callWithUpdateOverflowGuard(source, onChange) {
|
|
|
130
130
|
throw error;
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
|
+
let fatalSink;
|
|
134
|
+
/** Register (or clear, with undefined) the fatal-error sink. */
|
|
135
|
+
export function registerProcessGuardFatalSink(sink) {
|
|
136
|
+
fatalSink = sink;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Normalize the reason handed to a fatal sink so the exit funnel can never
|
|
140
|
+
* mistake a fatal error for a clean user exit. `Promise.reject()` and
|
|
141
|
+
* `throw undefined` deliver `undefined`, and the funnel selects its crash path
|
|
142
|
+
* with `error !== undefined` — passing the raw reason through would run the
|
|
143
|
+
* zero-exit path while the sink reported that it owned the process. Defined
|
|
144
|
+
* reasons (including non-Error values) are returned unchanged.
|
|
145
|
+
*/
|
|
146
|
+
export function fatalReasonForExit(error, origin) {
|
|
147
|
+
return error === undefined ? new Error(`${origin} with undefined reason`) : error;
|
|
148
|
+
}
|
|
133
149
|
/**
|
|
134
150
|
* Process-level backstop for the overflow error. The hotspot guards above
|
|
135
151
|
* cover the known enqueue sites (clock tick, reveal tick, channel emit,
|
|
@@ -138,9 +154,11 @@ export function callWithUpdateOverflowGuard(source, onChange) {
|
|
|
138
154
|
* feeder, a future timer, a plugin's store) would still kill the process.
|
|
139
155
|
* This installs uncaughtException/unhandledRejection handlers that absorb
|
|
140
156
|
* exactly the overflow error class (same self-healing contract: React
|
|
141
|
-
* already reset the counter before throwing) and
|
|
142
|
-
*
|
|
143
|
-
*
|
|
157
|
+
* already reset the counter before throwing) and hand everything else to the
|
|
158
|
+
* registered fatal sink — or rethrow it unchanged when there is none, so the
|
|
159
|
+
* process still fails loud with a non-zero exit rather than continuing in an
|
|
160
|
+
* unknown state. Idempotent; opt out with DSH_TUI_NO_185_PROCESS_GUARD=1 when
|
|
161
|
+
* a host owns process error policy.
|
|
144
162
|
*/
|
|
145
163
|
let processGuardInstalled = false;
|
|
146
164
|
export function installNestedUpdateOverflowProcessGuard() {
|
|
@@ -152,6 +170,8 @@ export function installNestedUpdateOverflowProcessGuard() {
|
|
|
152
170
|
process.on('uncaughtException', error => {
|
|
153
171
|
if (swallowNestedUpdateOverflow(error, 'process.uncaught'))
|
|
154
172
|
return;
|
|
173
|
+
if (fatalSink?.(error, 'uncaughtException') === true)
|
|
174
|
+
return;
|
|
155
175
|
// Unknown errors keep Node's default semantics: rethrowing from a
|
|
156
176
|
// listener crashes the process with the original error.
|
|
157
177
|
throw error;
|
|
@@ -159,6 +179,8 @@ export function installNestedUpdateOverflowProcessGuard() {
|
|
|
159
179
|
process.on('unhandledRejection', error => {
|
|
160
180
|
if (swallowNestedUpdateOverflow(error, 'process.rejection'))
|
|
161
181
|
return;
|
|
182
|
+
if (fatalSink?.(error, 'unhandledRejection') === true)
|
|
183
|
+
return;
|
|
162
184
|
throw error;
|
|
163
185
|
});
|
|
164
186
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal UI: one process-wide flag gating decorative UI (header splash,
|
|
3
|
+
* emoji status glyphs, non-tool text colors, status-bar extras). The flag is
|
|
4
|
+
* owned by the channel (settings key `dsh-tui.minimal`, applied live through
|
|
5
|
+
* scope.watch); leaf components read it here instead of threading a prop
|
|
6
|
+
* through four render layers. Code highlighting and tool-name colors are
|
|
7
|
+
* deliberately NOT gated — the minimal UI keeps those.
|
|
8
|
+
*
|
|
9
|
+
* This is the INTERFACE switch only. It is unrelated to the kernel's agent
|
|
10
|
+
* preset `minimal` (极简模式 / "Minimal"), which changes the model-facing
|
|
11
|
+
* world (a single persistent-shell tool — bash on POSIX, pwsh on Windows —
|
|
12
|
+
* with no compaction, no plan mode and no runtime context). Renamed from
|
|
13
|
+
* `minimalMode` so the two concepts cannot be read as one.
|
|
14
|
+
*/
|
|
15
|
+
/** True when the minimal UI is active (settings key `dsh-tui.minimal`). */
|
|
16
|
+
export declare function isMinimalUiMode(): boolean;
|
|
17
|
+
/** @internal channel-owned setter; also called once at boot. */
|
|
18
|
+
export declare function setMinimalUiMode(enabled: boolean): void;
|
|
19
|
+
//# sourceMappingURL=minimalUiMode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"minimalUiMode.d.ts","sourceRoot":"","sources":["../../src/minimalUiMode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,2EAA2E;AAC3E,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAED,gEAAgE;AAChE,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAEvD"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal UI: one process-wide flag gating decorative UI (header splash,
|
|
3
|
+
* emoji status glyphs, non-tool text colors, status-bar extras). The flag is
|
|
4
|
+
* owned by the channel (settings key `dsh-tui.minimal`, applied live through
|
|
5
|
+
* scope.watch); leaf components read it here instead of threading a prop
|
|
6
|
+
* through four render layers. Code highlighting and tool-name colors are
|
|
7
|
+
* deliberately NOT gated — the minimal UI keeps those.
|
|
8
|
+
*
|
|
9
|
+
* This is the INTERFACE switch only. It is unrelated to the kernel's agent
|
|
10
|
+
* preset `minimal` (极简模式 / "Minimal"), which changes the model-facing
|
|
11
|
+
* world (a single persistent-shell tool — bash on POSIX, pwsh on Windows —
|
|
12
|
+
* with no compaction, no plan mode and no runtime context). Renamed from
|
|
13
|
+
* `minimalMode` so the two concepts cannot be read as one.
|
|
14
|
+
*/
|
|
15
|
+
let minimalUi = false;
|
|
16
|
+
/** True when the minimal UI is active (settings key `dsh-tui.minimal`). */
|
|
17
|
+
export function isMinimalUiMode() {
|
|
18
|
+
return minimalUi;
|
|
19
|
+
}
|
|
20
|
+
/** @internal channel-owned setter; also called once at boot. */
|
|
21
|
+
export function setMinimalUiMode(enabled) {
|
|
22
|
+
minimalUi = enabled;
|
|
23
|
+
}
|
package/lib/types/oauth.d.ts
CHANGED
|
@@ -1,15 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* resolves row names from the *profile* directory, where only the profile's
|
|
7
|
-
* direct dependencies are linked, and pnpm's isolated layout never hoists a
|
|
8
|
-
* transitive dependency there. Mounting through this subpath keeps plugin
|
|
9
|
-
* resolution anchored at @deepseek-harness-tui/dsh-tui itself, always a
|
|
10
|
-
* direct profile dependency, under every package-manager layout.
|
|
2
|
+
* Public entry for the built-in OAuth Cordis module. The bundle patch keeps
|
|
3
|
+
* mounting this subpath so existing profile overrides and loader ordering
|
|
4
|
+
* remain compatible after the former dsh-auth package was folded into the
|
|
5
|
+
* TUI's adapter tree.
|
|
11
6
|
*
|
|
12
7
|
* @module @deepseek-harness-tui/dsh-tui/oauth
|
|
13
8
|
*/
|
|
14
|
-
export * from '
|
|
9
|
+
export * from './dsh-adapter/oauth/index.js';
|
|
15
10
|
//# sourceMappingURL=oauth.d.ts.map
|
package/lib/types/oauth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../src/oauth.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../src/oauth.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,cAAc,8BAA8B,CAAA"}
|
package/lib/types/oauth.js
CHANGED
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* resolves row names from the *profile* directory, where only the profile's
|
|
7
|
-
* direct dependencies are linked, and pnpm's isolated layout never hoists a
|
|
8
|
-
* transitive dependency there. Mounting through this subpath keeps plugin
|
|
9
|
-
* resolution anchored at @deepseek-harness-tui/dsh-tui itself, always a
|
|
10
|
-
* direct profile dependency, under every package-manager layout.
|
|
2
|
+
* Public entry for the built-in OAuth Cordis module. The bundle patch keeps
|
|
3
|
+
* mounting this subpath so existing profile overrides and loader ordering
|
|
4
|
+
* remain compatible after the former dsh-auth package was folded into the
|
|
5
|
+
* TUI's adapter tree.
|
|
11
6
|
*
|
|
12
7
|
* @module @deepseek-harness-tui/dsh-tui/oauth
|
|
13
8
|
*/
|
|
14
|
-
export * from '
|
|
9
|
+
export * from './dsh-adapter/oauth/index.js';
|
|
@@ -8,9 +8,10 @@ import type { TuiShortcutHost } from '../dsh-adapter/shortcuts.js';
|
|
|
8
8
|
import type { TuiThemeHost } from '../dsh-adapter/themes.js';
|
|
9
9
|
import { ApprovalStore } from '../dsh-adapter/approvals.js';
|
|
10
10
|
import { type StarAttempt } from '../components/StarPrompt.js';
|
|
11
|
+
import type { WhaleCouponStore } from '../dsh-adapter/oauth/bonus.js';
|
|
11
12
|
import { type PromptController } from '../components/PromptInput.js';
|
|
12
13
|
import type { InjectController } from '../dsh-adapter/inject-channel.js';
|
|
13
|
-
export declare function Chat({ channel, questionStore, approvalStore, extensionDialogs, extensionStatus, activityStore, extensionShortcuts, themeHost, onExit, onUpdate, onRestart, fullscreen, trajectorySeen: trajectorySeenProp, injectControllerRef, promptControllerRef: promptControllerRefProp, renderScene, openHomeOnBoot, starPrompt, }: {
|
|
14
|
+
export declare function Chat({ channel, questionStore, approvalStore, extensionDialogs, bonusNotices, extensionStatus, activityStore, extensionShortcuts, themeHost, onExit, onUpdate, onRestart, fullscreen, trajectorySeen: trajectorySeenProp, injectControllerRef, promptControllerRef: promptControllerRefProp, renderScene, openHomeOnBoot, starPrompt, }: {
|
|
14
15
|
channel: Channel;
|
|
15
16
|
renderScene?: (id: string, channel: Channel) => React.ReactNode;
|
|
16
17
|
questionStore: QuestionStore;
|
|
@@ -26,6 +27,8 @@ export declare function Chat({ channel, questionStore, approvalStore, extensionD
|
|
|
26
27
|
* park unanswered (their `timeoutMs` is the plugin's guard).
|
|
27
28
|
*/
|
|
28
29
|
extensionDialogs?: TuiDialogStore;
|
|
30
|
+
/** Server-confirmed login bonuses awaiting presentation in the TUI. */
|
|
31
|
+
bonusNotices?: WhaleCouponStore;
|
|
29
32
|
/** Plugin text and bounded rich status contributions. */
|
|
30
33
|
extensionStatus?: TuiStatusStore;
|
|
31
34
|
/** Session-scoped activity values published by the working-activity plugin. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Chat.d.ts","sourceRoot":"","sources":["../../../src/screens/Chat.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AA2BzB,OAAO,KAAK,EAAE,SAAS,IAAI,OAAO,EAAE,MAAM,iCAAiC,CAAA;AAE3E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC1D,OAAO,EAAE,cAAc,EAAwB,MAAM,0BAA0B,CAAA;AAC/E,OAAO,EAAE,aAAa,EAAe,MAAM,kCAAkC,CAAA;AAW7E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAG5D,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAa3D,OAAO,
|
|
1
|
+
{"version":3,"file":"Chat.d.ts","sourceRoot":"","sources":["../../../src/screens/Chat.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AA2BzB,OAAO,KAAK,EAAE,SAAS,IAAI,OAAO,EAAE,MAAM,iCAAiC,CAAA;AAE3E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC1D,OAAO,EAAE,cAAc,EAAwB,MAAM,0BAA0B,CAAA;AAC/E,OAAO,EAAE,aAAa,EAAe,MAAM,kCAAkC,CAAA;AAW7E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAG5D,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAa3D,OAAO,EAAiC,KAAK,WAAW,EAAE,MAAM,6BAA6B,CAAA;AAC7F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AAQrE,OAAO,EAAe,KAAK,gBAAgB,EAAE,MAAM,8BAA8B,CAAA;AAEjF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAA;AA8NxE,wBAAgB,IAAI,CAAC,EACnB,OAAO,EACP,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,YAAY,EACZ,eAAe,EACf,aAAa,EACb,kBAAkB,EAClB,SAAS,EACT,MAAM,EACN,QAAQ,EACR,SAAS,EACT,UAAkB,EAClB,cAAc,EAAE,kBAAkB,EAClC,mBAAmB,EACnB,mBAAmB,EAAE,uBAAuB,EAC5C,WAAW,EACX,cAAc,EACd,UAAU,GACX,EAAE;IACD,OAAO,EAAE,OAAO,CAAA;IAChB,WAAW,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,KAAK,CAAC,SAAS,CAAA;IAC/D,aAAa,EAAE,aAAa,CAAA;IAC5B;;;;OAIG;IACH,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,cAAc,CAAA;IACjC,uEAAuE;IACvE,YAAY,CAAC,EAAE,gBAAgB,CAAA;IAC/B,yDAAyD;IACzD,eAAe,CAAC,EAAE,cAAc,CAAA;IAChC,+EAA+E;IAC/E,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B,iDAAiD;IACjD,kBAAkB,CAAC,EAAE,eAAe,CAAA;IACpC,uEAAuE;IACvE,SAAS,CAAC,EAAE,YAAY,CAAA;IACxB,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB;;;;;;OAMG;IACH,mBAAmB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAA;IAC9D;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;KAAE,GAAG,IAAI,CAAA;IAC5G;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAA;CAC/D,4BAywJA"}
|
|
@@ -43,7 +43,7 @@ import { useSelection } from '../ink/hooks/use-selection.js';
|
|
|
43
43
|
import { NoSelect } from '../ink/components/NoSelect.js';
|
|
44
44
|
import { LogoHeader, MessageList } from '../components/MessageList.js';
|
|
45
45
|
import { splashFontIdOf } from '../components/splashFonts.js';
|
|
46
|
-
import { StarPrompt } from '../components/StarPrompt.js';
|
|
46
|
+
import { StarPrompt, WhaleCouponPrompt } from '../components/StarPrompt.js';
|
|
47
47
|
import { dueStarModal, markStarAsked, STAR_MILESTONES } from '../usageStats.js';
|
|
48
48
|
import { TimelineRail } from '../components/TimelineRail.js';
|
|
49
49
|
import { ScrollbarGutter } from '../components/ScrollbarGutter.js';
|
|
@@ -223,12 +223,14 @@ let fallbackDialogStore;
|
|
|
223
223
|
let fallbackStatusStore;
|
|
224
224
|
/** Standalone mounts (tests, bare embeds) without the composition root's store. */
|
|
225
225
|
let fallbackActivityStore;
|
|
226
|
+
const noCouponSubscription = () => () => undefined;
|
|
227
|
+
const noCouponSnapshot = () => null;
|
|
226
228
|
/** Identity of one caret-preview dismissal: the token (its title) on the
|
|
227
229
|
* image, so the same image staged twice is dismissed per token. */
|
|
228
230
|
function peekKey(image, title) {
|
|
229
231
|
return `${title ?? ''} ${image.id}`;
|
|
230
232
|
}
|
|
231
|
-
export function Chat({ channel, questionStore, approvalStore, extensionDialogs, extensionStatus, activityStore, extensionShortcuts, themeHost, onExit, onUpdate, onRestart, fullscreen = false, trajectorySeen: trajectorySeenProp, injectControllerRef, promptControllerRef: promptControllerRefProp, renderScene, openHomeOnBoot, starPrompt, }) {
|
|
233
|
+
export function Chat({ channel, questionStore, approvalStore, extensionDialogs, bonusNotices, extensionStatus, activityStore, extensionShortcuts, themeHost, onExit, onUpdate, onRestart, fullscreen = false, trajectorySeen: trajectorySeenProp, injectControllerRef, promptControllerRef: promptControllerRefProp, renderScene, openHomeOnBoot, starPrompt, }) {
|
|
232
234
|
const writeRaw = React.useContext(TerminalWriteContext);
|
|
233
235
|
// Re-render whenever the channel mutates; rows/status are read fresh below.
|
|
234
236
|
// DEFAULT lane on purpose (useExternalVersion): the channel version bumps
|
|
@@ -258,6 +260,7 @@ export function Chat({ channel, questionStore, approvalStore, extensionDialogs,
|
|
|
258
260
|
// extensions row share one inert store that never holds a dialog.
|
|
259
261
|
const dialogs = extensionDialogs ?? (fallbackDialogStore ??= new TuiDialogStore());
|
|
260
262
|
const dialogSnapshot = React.useSyncExternalStore(listener => dialogs.subscribe(listener), () => dialogs.getSnapshot());
|
|
263
|
+
const coupon = React.useSyncExternalStore(bonusNotices?.subscribe ?? noCouponSubscription, bonusNotices?.getSnapshot ?? noCouponSnapshot);
|
|
261
264
|
// Plugin status contributions: text keys join into one line; bounded rich
|
|
262
265
|
// views keep their own rows immediately above the prompt.
|
|
263
266
|
const statusContributions = extensionStatus ?? (fallbackStatusStore ??= new TuiStatusStore());
|
|
@@ -2415,7 +2418,9 @@ export function Chat({ channel, questionStore, approvalStore, extensionDialogs,
|
|
|
2415
2418
|
...oauth.map(row => t('login-oauth-row', {
|
|
2416
2419
|
provider: row.provider,
|
|
2417
2420
|
state: row.signedIn
|
|
2418
|
-
?
|
|
2421
|
+
? row.expiresAt === undefined
|
|
2422
|
+
? t('login-oauth-in-no-expiry')
|
|
2423
|
+
: t('login-oauth-in', { time: new Date(row.expiresAt).toISOString() })
|
|
2419
2424
|
: row.expired
|
|
2420
2425
|
? t('login-oauth-expired')
|
|
2421
2426
|
: t('login-oauth-signed-out'),
|
|
@@ -3014,11 +3019,23 @@ export function Chat({ channel, questionStore, approvalStore, extensionDialogs,
|
|
|
3014
3019
|
}, []);
|
|
3015
3020
|
/** Deduplicate terminals that report one Enter as parsed Return then raw CR/LF. */
|
|
3016
3021
|
const lastModalEnterAtRef = React.useRef(0);
|
|
3022
|
+
const couponVisible = coupon !== null && starModal === null
|
|
3023
|
+
&& approvalSnapshot === null && dialogSnapshot === null && questionSnapshot === null
|
|
3024
|
+
&& overlay.kind === 'none' && btw === null && recap === null
|
|
3025
|
+
&& !supervisorOpen && !treeOpen && !settingsOpen && !jobsPanelOpen
|
|
3026
|
+
&& !sceneOpen && !subagentDashboardOpen && subagentDetailId === null;
|
|
3027
|
+
const markCouponShown = React.useCallback((orderId) => {
|
|
3028
|
+
bonusNotices?.shown(orderId);
|
|
3029
|
+
}, [bonusNotices]);
|
|
3030
|
+
const closeCoupon = React.useCallback(() => {
|
|
3031
|
+
if (coupon !== null)
|
|
3032
|
+
bonusNotices?.dismiss(coupon.orderId);
|
|
3033
|
+
}, [bonusNotices, coupon]);
|
|
3017
3034
|
useInput((input, key, event) => {
|
|
3018
3035
|
// 开屏"求 star"弹窗开着时键盘全归它(↑/↓/Enter/Esc 由它自己的
|
|
3019
3036
|
// useInput 处理),滚轮也不许滚动它身后的转录——和下面的整屏界面
|
|
3020
3037
|
// 同一套让位规则。
|
|
3021
|
-
if (starModal !== null)
|
|
3038
|
+
if (starModal !== null || couponVisible)
|
|
3022
3039
|
return;
|
|
3023
3040
|
// Prompt-slot panels own the keyboard while visible. Their own useInput
|
|
3024
3041
|
// handles the relevant keys; Chat registered first, so yielding here
|
|
@@ -4030,7 +4047,7 @@ export function Chat({ channel, questionStore, approvalStore, extensionDialogs,
|
|
|
4030
4047
|
// Who owns the spinner slot: with the working-activity line on, that slot
|
|
4031
4048
|
// draws the user's `/activity` preset, so the compaction row borrows the same
|
|
4032
4049
|
// indicator instead of answering with the classic dot.
|
|
4033
|
-
const activitySlot = channel.activityEnabled && !channel.
|
|
4050
|
+
const activitySlot = channel.activityEnabled && !channel.minimalUi;
|
|
4034
4051
|
// An automatic compaction runs INSIDE the turn, so it rides whichever spinner
|
|
4035
4052
|
// the slot shows as a badge instead of a second row (the spinner's timer is
|
|
4036
4053
|
// the turn's, not the compaction's).
|
|
@@ -4235,7 +4252,8 @@ export function Chat({ channel, questionStore, approvalStore, extensionDialogs,
|
|
|
4235
4252
|
|| (recap !== null && (!recap.auto || recap.expanded))
|
|
4236
4253
|
|| btw !== null
|
|
4237
4254
|
|| questionPanelNode !== null
|
|
4238
|
-
|| starModal !== null
|
|
4255
|
+
|| starModal !== null
|
|
4256
|
+
|| couponVisible;
|
|
4239
4257
|
// The trajectory scene replaces the conversation for as long as it is open.
|
|
4240
4258
|
// Rendering it INSTEAD of (not above) the transcript is what makes it a
|
|
4241
4259
|
// screen rather than an overlay: it owns the full viewport, and the
|
|
@@ -4392,6 +4410,8 @@ export function Chat({ channel, questionStore, approvalStore, extensionDialogs,
|
|
|
4392
4410
|
band: wakeBand,
|
|
4393
4411
|
hint: trajectorySeen ? undefined : primaryComboString('trajectory'),
|
|
4394
4412
|
tick: Math.floor(wakeTime / 120),
|
|
4413
|
+
onOpen: openScene,
|
|
4414
|
+
hoverHint: primaryComboString('trajectory'),
|
|
4395
4415
|
} }), dialogOverlayOpen && (_jsxs(OverlayAbove, { maxHeight: Math.max(terminalRows - 8, 1), children: [overlay.kind === 'thinking' && (_jsx(ThinkingToggle, { currentValue: thinkingVisible, focusIndex: overlay.focus, onPick: (index) => {
|
|
4396
4416
|
// 点击行 = 设焦点 + 应用(与 Enter 同一条路径)
|
|
4397
4417
|
const visible = index === 0;
|
|
@@ -4534,7 +4554,7 @@ export function Chat({ channel, questionStore, approvalStore, extensionDialogs,
|
|
|
4534
4554
|
const path = overlay.path;
|
|
4535
4555
|
dispatchOverlay({ type: 'close' });
|
|
4536
4556
|
runFileAction(index, path);
|
|
4537
|
-
} }) })), overlay.kind === 'search' && _jsx(TranscriptSearch, { query: searchQuery, cursorOffset: searchCursor, count: searchCount, current: searchCurrent })] }))] })] }), _jsx(TooltipLayer, { invalidationKey: `${overlay.kind}:${dialogOverlayOpen}:${btw !== null}`, subscribeInvalidation: subscribeTooltipInvalidation }), _jsx(PromptEditorLayer, {}), promptEditorOpen && imagePreviewNode, starModal !== null && STAR_MILESTONES[starModal.index] !== undefined && (_jsx(StarPrompt, { milestone: STAR_MILESTONES[starModal.index], actions: starModalActions, onClose: closeStarModal, initialPhase: starModal.phase }))] }));
|
|
4557
|
+
} }) })), overlay.kind === 'search' && _jsx(TranscriptSearch, { query: searchQuery, cursorOffset: searchCursor, count: searchCount, current: searchCurrent })] }))] })] }), _jsx(TooltipLayer, { invalidationKey: `${overlay.kind}:${dialogOverlayOpen}:${btw !== null}`, subscribeInvalidation: subscribeTooltipInvalidation }), _jsx(PromptEditorLayer, {}), promptEditorOpen && imagePreviewNode, starModal !== null && STAR_MILESTONES[starModal.index] !== undefined && (_jsx(StarPrompt, { milestone: STAR_MILESTONES[starModal.index], actions: starModalActions, onClose: closeStarModal, initialPhase: starModal.phase })), couponVisible && coupon !== null && (_jsx(WhaleCouponPrompt, { notice: coupon, onShown: markCouponShown, onClose: closeCoupon }))] }));
|
|
4538
4558
|
}
|
|
4539
4559
|
/**
|
|
4540
4560
|
* The pinned prompt header shown above the ScrollBox while the user has
|
|
@@ -22,6 +22,10 @@ export declare function StatusLine({ channel, selectionActive, helpOpen, wake, a
|
|
|
22
22
|
band: WaveBand;
|
|
23
23
|
hint?: string;
|
|
24
24
|
tick: number;
|
|
25
|
+
/** Click target for the strip: opens the trajectory scene. */
|
|
26
|
+
onOpen?: () => void;
|
|
27
|
+
/** Chord revealed while the pointer rests on the strip. */
|
|
28
|
+
hoverHint?: string;
|
|
25
29
|
};
|
|
26
30
|
}): React.JSX.Element;
|
|
27
31
|
type UsageSnapshot = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StatusLine.d.ts","sourceRoot":"","sources":["../../../src/screens/StatusLine.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAOzB,OAAO,EAAoC,KAAK,iBAAiB,EAAE,MAAM,+BAA+B,CAAA;AAOxG,OAAO,KAAK,EAAE,SAAS,IAAI,OAAO,EAAE,MAAM,iCAAiC,CAAA;AAqB3E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAqHvD,wBAAgB,UAAU,CAAC,EACzB,OAAO,EACP,eAAuB,EACvB,QAAgB,EAChB,IAAI,EACJ,QAAQ,EAAE,iBAAiB,GAC5B,EAAE;IACD,OAAO,EAAE,OAAO,CAAA;IAChB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;kFAC8E;IAC9E,QAAQ,CAAC,EAAE,iBAAiB,CAAA;IAC5B;;;;;;;;OAQG;IACH,IAAI,CAAC,EAAE;
|
|
1
|
+
{"version":3,"file":"StatusLine.d.ts","sourceRoot":"","sources":["../../../src/screens/StatusLine.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAOzB,OAAO,EAAoC,KAAK,iBAAiB,EAAE,MAAM,+BAA+B,CAAA;AAOxG,OAAO,KAAK,EAAE,SAAS,IAAI,OAAO,EAAE,MAAM,iCAAiC,CAAA;AAqB3E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAqHvD,wBAAgB,UAAU,CAAC,EACzB,OAAO,EACP,eAAuB,EACvB,QAAgB,EAChB,IAAI,EACJ,QAAQ,EAAE,iBAAiB,GAC5B,EAAE;IACD,OAAO,EAAE,OAAO,CAAA;IAChB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;kFAC8E;IAC9E,QAAQ,CAAC,EAAE,iBAAiB,CAAA;IAC5B;;;;;;;;OAQG;IACH,IAAI,CAAC,EAAE;QACL,IAAI,EAAE,QAAQ,CAAA;QACd,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,IAAI,EAAE,MAAM,CAAA;QACZ,8DAA8D;QAC9D,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;QACnB,2DAA2D;QAC3D,SAAS,CAAC,EAAE,MAAM,CAAA;KACnB,CAAA;CACF,qBA+aA;AAED,KAAK,aAAa,GAAG;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;CACnB,CAAA;AA0LD,8EAA8E;AAC9E,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,aAAa,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAKvF;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EACL;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GACzD,SAAS,GACZ,MAAM,GAAG,SAAS,CAIpB"}
|
|
@@ -38,20 +38,20 @@ import { FREE_SEGMENT_FILL, USED_SEGMENTS, contextBarBreakdown, renderMiniContex
|
|
|
38
38
|
* own, so hovering it is how its colors get their names and numbers.
|
|
39
39
|
*/
|
|
40
40
|
/**
|
|
41
|
-
*
|
|
41
|
+
* The minimal UI's footer config. It ignores every SAVED preference (built from
|
|
42
42
|
* scratch rather than `normalizeStatusBar(channel.statusBar)`) and pins the
|
|
43
43
|
* DECORATION switches OFF — the shared defaults are free to change
|
|
44
|
-
* (`contextBar` became default-on in 2026-09) and minimal
|
|
44
|
+
* (`contextBar` became default-on in 2026-09) and the minimal UI must not follow
|
|
45
45
|
* them into the footer.
|
|
46
46
|
*
|
|
47
|
-
* The metric fields keep their `DEFAULT_STATUS_BAR` values on purpose:
|
|
48
|
-
*
|
|
47
|
+
* The metric fields keep their `DEFAULT_STATUS_BAR` values on purpose: the
|
|
48
|
+
* minimal UI has ALWAYS shown the default-on metrics (thinking / contextUsage /
|
|
49
49
|
* cache / cost / goal) next to model + cwd — that predates the long-line fold
|
|
50
50
|
* and the context-bar flip, and trimming them further is a product decision,
|
|
51
51
|
* not a regression fix. Module scope: one frozen object, no per-render
|
|
52
52
|
* allocation.
|
|
53
53
|
*/
|
|
54
|
-
const
|
|
54
|
+
const MINIMAL_UI_STATUS_BAR = Object.freeze({
|
|
55
55
|
...DEFAULT_STATUS_BAR,
|
|
56
56
|
compact: true,
|
|
57
57
|
model: true,
|
|
@@ -82,10 +82,10 @@ export function StatusLine({ channel, selectionActive = false, helpOpen = false,
|
|
|
82
82
|
// not clobber the field it entered.
|
|
83
83
|
onMouseLeave: () => setHover(current => (current === id ? null : current)),
|
|
84
84
|
}), []);
|
|
85
|
-
const statusBar = channel.
|
|
86
|
-
//
|
|
85
|
+
const statusBar = channel.minimalUi
|
|
86
|
+
// The minimal UI overrides every field switch: model + cwd only, so the
|
|
87
87
|
// footer can never grow decorations regardless of saved preferences.
|
|
88
|
-
?
|
|
88
|
+
? MINIMAL_UI_STATUS_BAR
|
|
89
89
|
: normalizeStatusBar(channel.statusBar);
|
|
90
90
|
// Provider workspaces expose a remote display path alongside a host alias;
|
|
91
91
|
// only the local target has identical cwd/displayCwd values to fold.
|
|
@@ -259,7 +259,7 @@ export function StatusLine({ channel, selectionActive = false, helpOpen = false,
|
|
|
259
259
|
? [{
|
|
260
260
|
key: 'goal',
|
|
261
261
|
id: 'goal',
|
|
262
|
-
node: _jsx(GoalStatusChip, { goal: channel.goal, minimal: channel.
|
|
262
|
+
node: _jsx(GoalStatusChip, { goal: channel.goal, minimal: channel.minimalUi }),
|
|
263
263
|
}]
|
|
264
264
|
: []),
|
|
265
265
|
...(statusBar.gitBranch && channel.gitBranch
|
|
@@ -345,13 +345,13 @@ export function StatusLine({ channel, selectionActive = false, helpOpen = false,
|
|
|
345
345
|
// on hover is what made the footer grow mid-gesture and shoved the
|
|
346
346
|
// transcript up (user feedback). Idle it may sit blank: a stable footer
|
|
347
347
|
// outranks a reclaimable row, and hovering only ever swaps this line's
|
|
348
|
-
// content.
|
|
348
|
+
// content. The minimal UI keeps the old contract — no hover details, the
|
|
349
349
|
// row appears only for real content (which its defaults never produce).
|
|
350
|
-
const showSupplementalRow = (!channel.
|
|
350
|
+
const showSupplementalRow = (!channel.minimalUi && (hasStatusFields || barVisible)) ||
|
|
351
351
|
showActivity ||
|
|
352
352
|
showTrajectory ||
|
|
353
353
|
hint !== '';
|
|
354
|
-
return (_jsx(Box, { paddingX: 1, width: columns, flexShrink: 0, children: _jsxs(Box, { flexDirection: "column", width: "100%", children: [barVisible ? (_jsx(ContextBarView, { segments: channel.contextSegments, usedTokens: contextUsed ?? 0, contextWindow: channel.contextWindow ?? 0, width: barWidth, colors: barColors, onHover: hovered => setHover(current => hovered ? 'bar' : current === 'bar' ? null : current) })) : null, hasStatusFields ? statusBar.compact ? (_jsxs(Box, { flexDirection: "row", justifyContent: "space-between", gap: 2, children: [_jsx(Box, { flexGrow: 1, flexShrink: 1, flexDirection: "row", overflow: "hidden", children: _jsx(FieldLine, { parts: compactFields, hoverProps: hoverProps }) }), ctxNode !== undefined ? (_jsx(Box, { flexShrink: 0, ...hoverProps('ctx'), children: _jsx(Text, { wrap: "truncate", children: ctxNode }) })) : null] })) : (_jsxs(Box, { flexDirection: "row", justifyContent: "space-between", gap: 2, children: [_jsx(Box, { flexGrow: 1, flexShrink: 1, flexDirection: "row", overflow: "hidden", children: _jsx(FieldLine, { parts: fullLeftFields, hoverProps: hoverProps }) }), _jsx(Box, { justifyContent: "flex-end", flexShrink: 2, flexDirection: "row", overflow: "hidden", children: _jsx(FieldLine, { parts: rightFields, hoverProps: hoverProps }) })] })) : null, showSupplementalRow ? _jsxs(Box, { height: 1, overflow: "hidden", flexDirection: "row", justifyContent: "space-between", gap: 2, children: [_jsxs(Box, { flexDirection: "row", flexGrow: 1, justifyContent: showActivity && trailer !== null ? 'space-between' : 'flex-start', gap: 2, children: [showActivity && activity !== undefined ? (_jsx(ActivityLine, { activity: activity, activityFrames: channel.activityFrames, warnPct: contextPressurePct(usage, channel.contextWindow), warnDanger: (contextPressurePct(usage, channel.contextWindow) ?? 0) >= 95 })) : trailer, showActivity ? trailer : null] }), showTrajectory && wake !== undefined ? (_jsx(MiniWake, { band: wake.band, hint: wake.hint, tick: wake.tick })) : null] }) : null] }) }));
|
|
354
|
+
return (_jsx(Box, { paddingX: 1, width: columns, flexShrink: 0, children: _jsxs(Box, { flexDirection: "column", width: "100%", children: [barVisible ? (_jsx(ContextBarView, { segments: channel.contextSegments, usedTokens: contextUsed ?? 0, contextWindow: channel.contextWindow ?? 0, width: barWidth, colors: barColors, onHover: hovered => setHover(current => hovered ? 'bar' : current === 'bar' ? null : current) })) : null, hasStatusFields ? statusBar.compact ? (_jsxs(Box, { flexDirection: "row", justifyContent: "space-between", gap: 2, children: [_jsx(Box, { flexGrow: 1, flexShrink: 1, flexDirection: "row", overflow: "hidden", children: _jsx(FieldLine, { parts: compactFields, hoverProps: hoverProps }) }), ctxNode !== undefined ? (_jsx(Box, { flexShrink: 0, ...hoverProps('ctx'), children: _jsx(Text, { wrap: "truncate", children: ctxNode }) })) : null] })) : (_jsxs(Box, { flexDirection: "row", justifyContent: "space-between", gap: 2, children: [_jsx(Box, { flexGrow: 1, flexShrink: 1, flexDirection: "row", overflow: "hidden", children: _jsx(FieldLine, { parts: fullLeftFields, hoverProps: hoverProps }) }), _jsx(Box, { justifyContent: "flex-end", flexShrink: 2, flexDirection: "row", overflow: "hidden", children: _jsx(FieldLine, { parts: rightFields, hoverProps: hoverProps }) })] })) : null, showSupplementalRow ? _jsxs(Box, { height: 1, overflow: "hidden", flexDirection: "row", justifyContent: "space-between", gap: 2, children: [_jsxs(Box, { flexDirection: "row", flexGrow: 1, justifyContent: showActivity && trailer !== null ? 'space-between' : 'flex-start', gap: 2, children: [showActivity && activity !== undefined ? (_jsx(ActivityLine, { activity: activity, activityFrames: channel.activityFrames, warnPct: contextPressurePct(usage, channel.contextWindow), warnDanger: (contextPressurePct(usage, channel.contextWindow) ?? 0) >= 95 })) : trailer, showActivity ? trailer : null] }), showTrajectory && wake !== undefined ? (_jsx(MiniWake, { band: wake.band, hint: wake.hint, tick: wake.tick, onOpen: wake.onOpen, hoverHint: wake.hoverHint })) : null] }) : null] }) }));
|
|
355
355
|
}
|
|
356
356
|
/**
|
|
357
357
|
* The supplemental-row readout for a hovered footer field. Technical label
|
|
@@ -124,11 +124,11 @@ export const SETTING_DEFINITIONS = {
|
|
|
124
124
|
kind: 'boolean',
|
|
125
125
|
},
|
|
126
126
|
'minimal': {
|
|
127
|
-
label: 'Minimal
|
|
128
|
-
descriptions: { zh: '
|
|
127
|
+
label: 'Minimal UI',
|
|
128
|
+
descriptions: { zh: '极简界面' },
|
|
129
129
|
group: 'appearance',
|
|
130
|
-
hint: '
|
|
131
|
-
hintDescriptions: { zh: '
|
|
130
|
+
hint: 'Interface only: hide the header splash, emoji glyphs and decorative colors, and trim the status bar to model + cwd; code highlight and tool colors stay. NOT the agent preset — the kernel\'s own `minimal` preset is a separate, model-facing choice that decides which tools the model can use (see /preset).',
|
|
131
|
+
hintDescriptions: { zh: '只精简界面:隐藏开屏头部、emoji 状态符与装饰性配色,底栏只留模型与目录;代码高亮与工具配色保留。这是界面开关,不是 Agent 预设——模型能用哪些工具由内核预设决定(见 /preset)。' },
|
|
132
132
|
kind: 'boolean',
|
|
133
133
|
},
|
|
134
134
|
'pageMargin': {
|