@deepseek-harness-tui/dsh-tui 0.9.2 → 0.9.3
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 +4 -4
- package/bin/dsh-tui.js +26 -4
- package/dsh-ecosystem-spec/protocols/profile-definitions.d.ts +13 -13
- package/dsh-ecosystem-spec/protocols/profile-definitions.js +59 -59
- package/dsh-ecosystem-spec/protocols/tui-channel-http.d.ts +15 -15
- package/dsh-ecosystem-spec/protocols/tui-channel-http.js +32 -32
- package/dsh-ecosystem-spec/protocols/tui-channel.d.ts +59 -59
- package/dsh-ecosystem-spec/protocols/tui-channel.js +166 -166
- package/dsh-ecosystem-spec/protocols/tui-contributions.d.ts +42 -42
- package/dsh-ecosystem-spec/protocols/tui-contributions.js +143 -143
- package/dsh-ecosystem-spec/registry/README.md +14 -14
- package/dsh-ecosystem-spec/registry/host-descriptor.tui.example.json +56 -56
- package/dsh-ecosystem-spec/registry/permissions-0.1.json +13 -13
- package/dsh-ecosystem-spec/registry/registry-0.15.json +149 -149
- package/lib/types/commands.d.ts.map +1 -1
- package/lib/types/commands.js +7 -8
- package/lib/types/components/BalanceReportRow.d.ts +24 -0
- package/lib/types/components/BalanceReportRow.d.ts.map +1 -0
- package/lib/types/components/BalanceReportRow.js +87 -0
- package/lib/types/components/HistorySearchDialog.js +1 -1
- package/lib/types/components/MessageList.d.ts +3 -1
- package/lib/types/components/MessageList.d.ts.map +1 -1
- package/lib/types/components/MessageList.js +11 -7
- package/lib/types/components/PluginSceneBoundary.d.ts +1 -1
- package/lib/types/components/PluginSceneBoundary.js +1 -1
- package/lib/types/components/PromptInput.d.ts.map +1 -1
- package/lib/types/components/PromptInput.js +16 -0
- package/lib/types/components/Whale.d.ts +15 -4
- package/lib/types/components/Whale.d.ts.map +1 -1
- package/lib/types/components/Whale.js +9 -8
- package/lib/types/components/messages/AssistantToolUseMessage.d.ts +7 -1
- package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
- package/lib/types/components/messages/AssistantToolUseMessage.js +34 -4
- package/lib/types/deepseekBalance.d.ts +53 -0
- package/lib/types/deepseekBalance.d.ts.map +1 -0
- package/lib/types/deepseekBalance.js +86 -0
- package/lib/types/deepseekPricing.d.ts +82 -0
- package/lib/types/deepseekPricing.d.ts.map +1 -0
- package/lib/types/deepseekPricing.js +133 -0
- package/lib/types/dsh-adapter/channel.d.ts +46 -1
- package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel.js +84 -10
- package/lib/types/dsh-adapter/index.d.ts +5 -0
- package/lib/types/dsh-adapter/index.d.ts.map +1 -1
- package/lib/types/dsh-adapter/index.js +1 -0
- package/lib/types/dsh-adapter/packaged-skills.d.ts +9 -0
- package/lib/types/dsh-adapter/packaged-skills.d.ts.map +1 -1
- package/lib/types/dsh-adapter/packaged-skills.js +19 -4
- package/lib/types/dsh-adapter/plugin.d.ts +6 -0
- package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
- package/lib/types/dsh-adapter/plugin.js +122 -18
- package/lib/types/dsh-adapter/settings-sections.d.ts +1 -0
- package/lib/types/dsh-adapter/settings-sections.d.ts.map +1 -1
- package/lib/types/dsh-adapter/settings-sections.js +35 -2
- package/lib/types/history.d.ts +4 -3
- package/lib/types/history.d.ts.map +1 -1
- package/lib/types/history.js +66 -18
- package/lib/types/i18n.d.ts +122 -55
- package/lib/types/i18n.d.ts.map +1 -1
- package/lib/types/i18n.js +39 -18
- package/lib/types/ink/ink.d.ts.map +1 -1
- package/lib/types/ink/ink.js +67 -17
- package/lib/types/ink/root.d.ts +16 -0
- package/lib/types/ink/root.d.ts.map +1 -1
- package/lib/types/ink/root.js +2 -0
- package/lib/types/ink/terminal-querier.d.ts +8 -0
- package/lib/types/ink/terminal-querier.d.ts.map +1 -1
- package/lib/types/ink/terminal-querier.js +13 -0
- package/lib/types/ink/terminal.d.ts +42 -0
- package/lib/types/ink/terminal.d.ts.map +1 -1
- package/lib/types/ink/terminal.js +52 -2
- package/lib/types/plugin-spec/registry.d.ts +1 -1
- package/lib/types/plugin-spec/registry.js +1 -1
- package/lib/types/screens/Chat.d.ts.map +1 -1
- package/lib/types/screens/Chat.js +72 -37
- package/lib/types/screens/SessionBrowser.d.ts.map +1 -1
- package/lib/types/screens/SessionBrowser.js +28 -13
- package/lib/types/screens/SessionTree.d.ts.map +1 -1
- package/lib/types/screens/SessionTree.js +33 -9
- package/lib/types/screens/Settings.d.ts +7 -5
- package/lib/types/screens/Settings.d.ts.map +1 -1
- package/lib/types/screens/Settings.js +206 -99
- package/lib/types/screens/StatusLine.d.ts.map +1 -1
- package/lib/types/screens/StatusLine.js +32 -1
- package/lib/types/sessionHistory.d.ts +11 -0
- package/lib/types/sessionHistory.d.ts.map +1 -1
- package/lib/types/sessionHistory.js +29 -0
- package/lib/types/sessions/format.d.ts.map +1 -1
- package/lib/types/sessions/format.js +14 -4
- package/lib/types/tips.js +2 -2
- package/lib/types/tuiDisplayPrefs.d.ts +3 -0
- package/lib/types/tuiDisplayPrefs.d.ts.map +1 -1
- package/lib/types/tuiDisplayPrefs.js +1 -0
- package/lib/types/update.d.ts +46 -0
- package/lib/types/update.d.ts.map +1 -1
- package/lib/types/update.js +232 -3
- package/node_modules/@deepseek-harness-tui/dsh-auth/LICENSE +21 -21
- package/node_modules/@deepseek-harness-tui/dsh-auth/dsh-plugin.json +44 -44
- package/node_modules/@dsh-std/command/CHANGELOG.md +8 -8
- package/node_modules/@dsh-std/command/LICENSE +21 -21
- package/node_modules/@dsh-std/command/README.md +26 -26
- package/node_modules/@dsh-std/command/README.zh.md +28 -28
- package/node_modules/@dsh-std/command/lib/index.js.map +1 -1
- package/node_modules/@dsh-std/command/package.json +22 -22
- package/node_modules/@dsh-std/connection/CHANGELOG.md +8 -8
- package/node_modules/@dsh-std/connection/LICENSE +21 -21
- package/node_modules/@dsh-std/connection/README.md +42 -42
- package/node_modules/@dsh-std/connection/README.zh.md +42 -42
- package/node_modules/@dsh-std/connection/lib/index.js.map +1 -1
- package/node_modules/@dsh-std/connection/lib/memory.js.map +1 -1
- package/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js.map +1 -1
- package/node_modules/@dsh-std/connection/package.json +20 -20
- package/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
- package/node_modules/@dsh-std/core/LICENSE +21 -21
- package/node_modules/@dsh-std/core/README.md +13 -13
- package/node_modules/@dsh-std/core/README.zh.md +13 -13
- package/node_modules/@dsh-std/core/lib/index.js.map +1 -1
- package/node_modules/@dsh-std/core/package.json +21 -21
- package/node_modules/@dsh-std/manifest/CHANGELOG.md +9 -9
- package/node_modules/@dsh-std/manifest/LICENSE +21 -21
- package/node_modules/@dsh-std/manifest/README.md +5 -5
- package/node_modules/@dsh-std/manifest/README.zh.md +5 -5
- package/node_modules/@dsh-std/manifest/lib/index.js.map +1 -1
- package/node_modules/@dsh-std/manifest/package.json +20 -20
- package/node_modules/@dsh-std/manifest/schema/dsh-plugin-0.15.schema.json +144 -144
- package/node_modules/@dsh-std/messages/CHANGELOG.md +8 -8
- package/node_modules/@dsh-std/messages/LICENSE +21 -21
- package/node_modules/@dsh-std/messages/README.md +5 -5
- package/node_modules/@dsh-std/messages/README.zh.md +7 -7
- package/node_modules/@dsh-std/messages/lib/index.js.map +1 -1
- package/node_modules/@dsh-std/messages/package.json +20 -20
- package/node_modules/@dsh-std/messages/schema/message-observer-envelope-0.15.schema.json +54 -54
- package/node_modules/@dsh-std/presentation/CHANGELOG.md +9 -9
- package/node_modules/@dsh-std/presentation/LICENSE +21 -21
- package/node_modules/@dsh-std/presentation/README.md +27 -27
- package/node_modules/@dsh-std/presentation/README.zh.md +29 -29
- package/node_modules/@dsh-std/presentation/lib/callback.js.map +1 -1
- package/node_modules/@dsh-std/presentation/lib/index.js.map +1 -1
- package/node_modules/@dsh-std/presentation/package.json +25 -25
- package/node_modules/@dsh-std/storage/CHANGELOG.md +8 -8
- package/node_modules/@dsh-std/storage/LICENSE +21 -21
- package/node_modules/@dsh-std/storage/README.md +5 -5
- package/node_modules/@dsh-std/storage/README.zh.md +7 -7
- package/node_modules/@dsh-std/storage/lib/index.js.map +1 -1
- package/node_modules/@dsh-std/storage/package.json +20 -20
- package/node_modules/@dsh-std/storage/schema/local-storage-0.15.schema.json +56 -56
- package/package.json +95 -5
- package/skills/pr-comments/SKILL.md +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/CHANGELOG.md +8 -8
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/LICENSE +21 -21
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/README.md +42 -42
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/README.zh.md +42 -42
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/memory.js.map +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js.map +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/package.json +20 -20
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/LICENSE +21 -21
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/README.md +13 -13
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/README.zh.md +13 -13
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/package.json +21 -21
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/CHANGELOG.md +9 -9
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/LICENSE +21 -21
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/README.md +5 -5
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/README.zh.md +5 -5
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/package.json +20 -20
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/schema/dsh-plugin-0.15.schema.json +144 -144
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/CHANGELOG.md +9 -9
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/LICENSE +21 -21
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/README.md +27 -27
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/README.zh.md +29 -29
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/callback.js.map +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/package.json +25 -25
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/LICENSE +21 -21
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/README.md +13 -13
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/README.zh.md +13 -13
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/package.json +21 -21
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/LICENSE +21 -21
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/README.md +13 -13
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/README.zh.md +13 -13
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/package.json +21 -21
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/LICENSE +21 -21
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/README.md +13 -13
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/README.zh.md +13 -13
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/package.json +21 -21
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/CHANGELOG.md +8 -8
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/LICENSE +21 -21
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/README.md +42 -42
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/README.zh.md +42 -42
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/memory.js.map +1 -1
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js.map +1 -1
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/package.json +20 -20
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/LICENSE +21 -21
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/README.md +13 -13
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/README.zh.md +13 -13
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/package.json +21 -21
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/LICENSE +21 -21
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/README.md +13 -13
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/README.zh.md +13 -13
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/package.json +21 -21
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { type WhaleFrame } from './whaleFrames.js';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* The DeepSeek pixel whale from the hand-drawn Excel art (whale_frames.zip):
|
|
5
|
+
* a 40×25 sprite in four true-color tones (deep-navy outline, DeepSeek-blue
|
|
6
|
+
* body, ice-blue belly, white mouth). Rendered with the half-block
|
|
7
|
+
* technique — each terminal cell packs two vertical pixels into one `▀`/`▄`
|
|
8
|
+
* glyph (foreground = upper pixel, background = lower), so the whale shows
|
|
9
|
+
* at 40 columns × 13 rows with visually square pixels.
|
|
7
10
|
*/
|
|
8
|
-
|
|
11
|
+
type Rgb = readonly [number, number, number];
|
|
12
|
+
/**
|
|
13
|
+
* Render one frame to ANSI rows (one per sprite row pair) under its own
|
|
14
|
+
* palette. Consecutive cells sharing one style are run-length encoded;
|
|
15
|
+
* trailing transparent cells are dropped so the rows measure exactly the
|
|
16
|
+
* sprite's bounding box.
|
|
17
|
+
*/
|
|
18
|
+
export declare function renderSpriteRows(frame: WhaleFrame, palette: Record<string, Rgb | undefined>): string[];
|
|
9
19
|
/** Index of the `standard` frame — the settled header's static pose. */
|
|
10
20
|
export declare const STANDARD_FRAME_INDEX = 0;
|
|
11
21
|
/**
|
|
@@ -19,4 +29,5 @@ export declare function WhaleArt({ frameIndex, width, }: {
|
|
|
19
29
|
frameIndex?: number;
|
|
20
30
|
width?: number;
|
|
21
31
|
}): React.ReactNode;
|
|
32
|
+
export {};
|
|
22
33
|
//# sourceMappingURL=Whale.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Whale.d.ts","sourceRoot":"","sources":["../../../src/components/Whale.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"Whale.d.ts","sourceRoot":"","sources":["../../../src/components/Whale.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAEhE;;;;;;;GAOG;AAEH,KAAK,GAAG,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;AAc5C;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,GAAG,SAAS,CAAC,GAAG,MAAM,EAAE,CAwCtG;AAMD,wEAAwE;AACxE,eAAO,MAAM,oBAAoB,IAAI,CAAA;AAErC;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,EACvB,UAAiC,EACjC,KAAK,GACN,EAAE;IACD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,GAAG,KAAK,CAAC,SAAS,CAWlB"}
|
|
@@ -12,11 +12,12 @@ const fg = (rgb) => `\x1b[38;2;${rgb[0]};${rgb[1]};${rgb[2]}m`;
|
|
|
12
12
|
const bg = (rgb) => `\x1b[48;2;${rgb[0]};${rgb[1]};${rgb[2]}m`;
|
|
13
13
|
const RESET = '\x1b[0m';
|
|
14
14
|
/**
|
|
15
|
-
* Render
|
|
16
|
-
* cells sharing one style are run-length encoded;
|
|
17
|
-
* cells are dropped so the rows measure exactly the
|
|
15
|
+
* Render one frame to ANSI rows (one per sprite row pair) under its own
|
|
16
|
+
* palette. Consecutive cells sharing one style are run-length encoded;
|
|
17
|
+
* trailing transparent cells are dropped so the rows measure exactly the
|
|
18
|
+
* sprite's bounding box.
|
|
18
19
|
*/
|
|
19
|
-
export function
|
|
20
|
+
export function renderSpriteRows(frame, palette) {
|
|
20
21
|
const sprite = frame.rows;
|
|
21
22
|
const rows = [];
|
|
22
23
|
for (let r = 0; r < sprite.length; r += 2) {
|
|
@@ -25,8 +26,8 @@ export function renderWhaleRows(frame) {
|
|
|
25
26
|
let out = '';
|
|
26
27
|
let current = '';
|
|
27
28
|
for (let x = 0; x < upper.length; x++) {
|
|
28
|
-
const up =
|
|
29
|
-
const lo =
|
|
29
|
+
const up = palette[upper[x]];
|
|
30
|
+
const lo = palette[lower[x]];
|
|
30
31
|
let seq;
|
|
31
32
|
let ch;
|
|
32
33
|
if (up !== undefined && lo !== undefined) {
|
|
@@ -61,8 +62,8 @@ export function renderWhaleRows(frame) {
|
|
|
61
62
|
}
|
|
62
63
|
return rows;
|
|
63
64
|
}
|
|
64
|
-
/** Pre-rendered ANSI rows for every frame, computed once at module load. */
|
|
65
|
-
const RENDERED = WHALE_FRAMES.map(
|
|
65
|
+
/** Pre-rendered ANSI rows for every whale frame, computed once at module load. */
|
|
66
|
+
const RENDERED = WHALE_FRAMES.map(frame => renderSpriteRows(frame, PALETTE));
|
|
66
67
|
/** Index of the `standard` frame — the settled header's static pose. */
|
|
67
68
|
export const STANDARD_FRAME_INDEX = 0;
|
|
68
69
|
/**
|
|
@@ -39,6 +39,12 @@ type Props = {
|
|
|
39
39
|
* the row's own fold-toggle does not fire.
|
|
40
40
|
*/
|
|
41
41
|
onOpenFile?: (path: string) => void;
|
|
42
|
+
/**
|
|
43
|
+
* Terminal-card header folding (settings `dsh-tui.foldTerminalCommand`):
|
|
44
|
+
* collapsed cards keep the command title's first source line plus a
|
|
45
|
+
* `+N lines` hint; verbose/expanded cards render the full title.
|
|
46
|
+
*/
|
|
47
|
+
foldTerminalCommand?: boolean;
|
|
42
48
|
};
|
|
43
49
|
export declare function toolNameColor(raw: string): keyof Theme;
|
|
44
50
|
/**
|
|
@@ -47,6 +53,6 @@ export declare function toolNameColor(raw: string): keyof Theme;
|
|
|
47
53
|
* output, read content — instead of the raw result dump (mirroring Claude Code's `AssistantToolUseMessage.tsx` + the dsh-tools presentation views the
|
|
48
54
|
* channel captures per call).
|
|
49
55
|
*/
|
|
50
|
-
export declare function AssistantToolUseMessage({ tool, addMargin, verbose, isSelected, isExpanded, onClick, footnote, diffLayout, toolBackground, onOpenFile, }: Props): React.ReactNode;
|
|
56
|
+
export declare function AssistantToolUseMessage({ tool, addMargin, verbose, isSelected, isExpanded, onClick, footnote, diffLayout, toolBackground, onOpenFile, foldTerminalCommand, }: Props): React.ReactNode;
|
|
51
57
|
export {};
|
|
52
58
|
//# sourceMappingURL=AssistantToolUseMessage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssistantToolUseMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/messages/AssistantToolUseMessage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAKzB,OAAO,KAAK,EAA8C,OAAO,EAAE,MAAM,8BAA8B,CAAA;AAKvG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAC9D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAC3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAEjE,KAAK,KAAK,GAAG;IACX,IAAI,EAAE,OAAO,CAAA;IACb,4DAA4D;IAC5D,SAAS,EAAE,OAAO,CAAA;IAClB,iEAAiE;IACjE,OAAO,EAAE,OAAO,CAAA;IAChB,wCAAwC;IACxC,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,sEAAsE;IACtE,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;OAIG;IACH,OAAO,CAAC,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAA;IACjC;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,oEAAoE;IACpE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAA;IACzC,2EAA2E;IAC3E,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B;;;;;OAKG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"AssistantToolUseMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/messages/AssistantToolUseMessage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAKzB,OAAO,KAAK,EAA8C,OAAO,EAAE,MAAM,8BAA8B,CAAA;AAKvG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAC9D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAC3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAEjE,KAAK,KAAK,GAAG;IACX,IAAI,EAAE,OAAO,CAAA;IACb,4DAA4D;IAC5D,SAAS,EAAE,OAAO,CAAA;IAClB,iEAAiE;IACjE,OAAO,EAAE,OAAO,CAAA;IAChB,wCAAwC;IACxC,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,sEAAsE;IACtE,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;OAIG;IACH,OAAO,CAAC,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAA;IACjC;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,oEAAoE;IACpE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAA;IACzC,2EAA2E;IAC3E,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B;;;;;OAKG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACnC;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAA;CAC9B,CAAA;AAsFD,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,KAAK,CAKtD;AAuOD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,EACtC,IAAI,EACJ,SAAS,EACT,OAAO,EACP,UAAkB,EAClB,UAAkB,EAClB,OAAO,EACP,QAAQ,EACR,UAAmB,EACnB,cAAuB,EACvB,UAAU,EACV,mBAA2B,GAC5B,EAAE,KAAK,GAAG,KAAK,CAAC,SAAS,CA6MzB"}
|
|
@@ -200,12 +200,34 @@ function clipHeaderArgs(args) {
|
|
|
200
200
|
return args;
|
|
201
201
|
return `${args.slice(0, HEADER_ARGS_BUDGET)}…`;
|
|
202
202
|
}
|
|
203
|
-
|
|
203
|
+
/** Fold a multi-line terminal command title to its first SOURCE line.
|
|
204
|
+
* Counts '\n' separators in place instead of materializing a line array —
|
|
205
|
+
* running cards re-render every second and a streamed command can reach
|
|
206
|
+
* hundreds of KB, and the exact cost the HEADER_ARGS_BUDGET comment above
|
|
207
|
+
* keeps out of the header must not sneak back in through folding. (Lone-\r
|
|
208
|
+
* titles are not a thing presentCall produces; CRLF is normalized on the
|
|
209
|
+
* first line only.) Single-line titles return undefined: nothing to fold,
|
|
210
|
+
* rendering stays byte-identical to the unfolded card. */
|
|
211
|
+
function foldTerminalTitle(title) {
|
|
212
|
+
const firstEnd = title.indexOf('\n');
|
|
213
|
+
if (firstEnd === -1)
|
|
214
|
+
return undefined;
|
|
215
|
+
let separators = 1;
|
|
216
|
+
for (let at = title.indexOf('\n', firstEnd + 1); at !== -1; at = title.indexOf('\n', at + 1))
|
|
217
|
+
separators++;
|
|
218
|
+
// Same trailing-newline rule as sideLines: a terminator is not a line.
|
|
219
|
+
const hidden = separators - (title.endsWith('\n') ? 1 : 0);
|
|
220
|
+
if (hidden <= 0)
|
|
221
|
+
return undefined;
|
|
222
|
+
const first = title.slice(0, title.charCodeAt(firstEnd - 1) === 13 ? firstEnd - 1 : firstEnd);
|
|
223
|
+
return { first, hidden };
|
|
224
|
+
}
|
|
225
|
+
function HeaderTitle({ name, title, isTerminal, folded, displayArgs, argsLanguage, nameColor, filePath, onOpenFile }) {
|
|
204
226
|
if (title === undefined) {
|
|
205
227
|
return (_jsxs(_Fragment, { children: [_jsx(Box, { flexShrink: 0, children: _jsx(Text, { bold: true, color: nameColor, wrap: "truncate-end", children: name }) }), displayArgs !== '' && (_jsxs(Box, { flexWrap: "nowrap", children: [_jsx(Text, { children: "(" }), _jsx(SyntaxText, { text: clipHeaderArgs(displayArgs), sourceText: displayArgs, language: argsLanguage }), _jsx(Text, { children: ")" })] }))] }));
|
|
206
228
|
}
|
|
207
229
|
if (isTerminal) {
|
|
208
|
-
return (_jsxs(_Fragment, { children: [_jsx(Box, { flexShrink: 0, children: _jsx(Text, { bold: true, color: nameColor, wrap: "truncate-end", children: name }) }), _jsx(Box, { flexWrap: "nowrap", children: _jsxs(Text, { children: ["(", title, ")"] }) })] }));
|
|
230
|
+
return (_jsxs(_Fragment, { children: [_jsx(Box, { flexShrink: 0, children: _jsx(Text, { bold: true, color: nameColor, wrap: "truncate-end", children: name }) }), _jsx(Box, { flexWrap: "nowrap", children: folded === undefined ? (_jsxs(Text, { children: ["(", title, ")"] })) : (_jsxs(_Fragment, { children: [_jsxs(Text, { children: ["(", folded.first, ")"] }), _jsx(Text, { dimColor: true, children: ` … +${folded.hidden} lines (ctrl+o to expand)` })] })) })] }));
|
|
209
231
|
}
|
|
210
232
|
const trimmed = title.trim();
|
|
211
233
|
if (trimmed === '') {
|
|
@@ -236,7 +258,7 @@ function HeaderTitle({ name, title, isTerminal, displayArgs, argsLanguage, nameC
|
|
|
236
258
|
* output, read content — instead of the raw result dump (mirroring Claude Code's `AssistantToolUseMessage.tsx` + the dsh-tools presentation views the
|
|
237
259
|
* channel captures per call).
|
|
238
260
|
*/
|
|
239
|
-
export function AssistantToolUseMessage({ tool, addMargin, verbose, isSelected = false, isExpanded = false, onClick, footnote, diffLayout = 'auto', toolBackground = 'none', onOpenFile, }) {
|
|
261
|
+
export function AssistantToolUseMessage({ tool, addMargin, verbose, isSelected = false, isExpanded = false, onClick, footnote, diffLayout = 'auto', toolBackground = 'none', onOpenFile, foldTerminalCommand = false, }) {
|
|
240
262
|
const isRunning = tool.status === 'running';
|
|
241
263
|
const isError = tool.status === 'error';
|
|
242
264
|
const displayArgs = verbose ? tool.argsFull ?? tool.argsText : tool.argsText;
|
|
@@ -254,6 +276,14 @@ export function AssistantToolUseMessage({ tool, addMargin, verbose, isSelected =
|
|
|
254
276
|
// command) — then the call view's title stands.
|
|
255
277
|
const headerTitle = tool.resultView?.title ?? tool.callView?.title;
|
|
256
278
|
const headerIsTerminal = view?.card === 'terminal';
|
|
279
|
+
// Fold only the terminal header: multi-line command script, folding on,
|
|
280
|
+
// and the card not verbose/expanded (Ctrl+O and row click both land in
|
|
281
|
+
// `verbose`, so expansion reuses the existing state machine). Memoized on
|
|
282
|
+
// the title reference: settled titles never change, so the 1s
|
|
283
|
+
// useAnimationFrame tick of a running card re-renders without rescanning.
|
|
284
|
+
const foldedHeader = React.useMemo(() => headerIsTerminal && foldTerminalCommand && !verbose && headerTitle !== undefined
|
|
285
|
+
? foldTerminalTitle(headerTitle)
|
|
286
|
+
: undefined, [headerIsTerminal, foldTerminalCommand, verbose, headerTitle]);
|
|
257
287
|
// Live elapsed clock while the call runs (CC's bash elapsed timer): the
|
|
258
288
|
// 1s tick re-renders the card; elapsed derives from wall-clock refs.
|
|
259
289
|
const [viewportRef] = useAnimationFrame(isRunning ? 1000 : null);
|
|
@@ -314,7 +344,7 @@ export function AssistantToolUseMessage({ tool, addMargin, verbose, isSelected =
|
|
|
314
344
|
return (_jsx(Box, { ref: viewportRef, flexDirection: "row", justifyContent: "space-between", marginTop: addMargin ? 1 : 0, width: "100%", onClick: onClick,
|
|
315
345
|
// Only selection paints a highlight; the configured treatment applies
|
|
316
346
|
// to an ordinary card. Diff line tints stay - they are content, not chrome.
|
|
317
|
-
backgroundColor: isSelected ? 'messageActionsBackground' : hoverTint ? 'toolCardBackground' : ordinaryBackground, onMouseEnter: interactive ? () => setHovered(true) : undefined, onMouseLeave: interactive ? () => setHovered(false) : undefined, children: _jsxs(Box, { flexDirection: "column", flexGrow: 1, children: [_jsxs(Box, { flexDirection: "row", flexWrap: "nowrap", minWidth: minWidth, children: [_jsx(ToolUseLoader, { shouldAnimate: isRunning, isUnresolved: isRunning, isError: isError, toolName: tool.name }), _jsx(HeaderTitle, { name: name, title: headerTitle, isTerminal: headerIsTerminal, displayArgs: displayArgs, argsLanguage: argsLanguage, nameColor: toolNameColor(tool.name), filePath: filePath, onOpenFile: onOpenFile }), !isRunning && (_jsx(Box, { flexWrap: "nowrap", children: _jsx(Text, { dimColor: !hovered, children: elapsedText }) })), hovered && (_jsx(Box, { flexShrink: 0, children: _jsx(Text, { dimColor: true, children: isExpanded ? '▴' : '▾' }) }))] }), useSplitDiff && view?.card === 'diff' ? (_jsxs(Box, { flexDirection: "row", children: [_jsx(Box, { width: 3, flexShrink: 0, children: _jsx(Text, { dimColor: true, children: GUTTER_FIRST }) }), _jsx(SplitDiffView, { diffs: view.diffs, width: columns - 4, maxRows: DIFF_BODY_MAX_LINES, verbose: verbose, toolBackground: ordinaryToolBackground })] })) : (rendered.map((line, index) => (_jsxs(Box, { flexDirection: "row", children: [_jsx(Box, { width: 3, flexShrink: 0, children: _jsx(Text, { color: line.tone === 'add'
|
|
347
|
+
backgroundColor: isSelected ? 'messageActionsBackground' : hoverTint ? 'toolCardBackground' : ordinaryBackground, onMouseEnter: interactive ? () => setHovered(true) : undefined, onMouseLeave: interactive ? () => setHovered(false) : undefined, children: _jsxs(Box, { flexDirection: "column", flexGrow: 1, children: [_jsxs(Box, { flexDirection: "row", flexWrap: "nowrap", minWidth: minWidth, children: [_jsx(ToolUseLoader, { shouldAnimate: isRunning, isUnresolved: isRunning, isError: isError, toolName: tool.name }), _jsx(HeaderTitle, { name: name, title: headerTitle, isTerminal: headerIsTerminal, folded: foldedHeader, displayArgs: displayArgs, argsLanguage: argsLanguage, nameColor: toolNameColor(tool.name), filePath: filePath, onOpenFile: onOpenFile }), !isRunning && (_jsx(Box, { flexWrap: "nowrap", children: _jsx(Text, { dimColor: !hovered, children: elapsedText }) })), hovered && (_jsx(Box, { flexShrink: 0, children: _jsx(Text, { dimColor: true, children: isExpanded ? '▴' : '▾' }) }))] }), useSplitDiff && view?.card === 'diff' ? (_jsxs(Box, { flexDirection: "row", children: [_jsx(Box, { width: 3, flexShrink: 0, children: _jsx(Text, { dimColor: true, children: GUTTER_FIRST }) }), _jsx(SplitDiffView, { diffs: view.diffs, width: columns - 4, maxRows: DIFF_BODY_MAX_LINES, verbose: verbose, toolBackground: ordinaryToolBackground })] })) : (rendered.map((line, index) => (_jsxs(Box, { flexDirection: "row", children: [_jsx(Box, { width: 3, flexShrink: 0, children: _jsx(Text, { color: line.tone === 'add'
|
|
318
348
|
? 'diffAddedWord'
|
|
319
349
|
: line.tone === 'del'
|
|
320
350
|
? 'diffRemovedWord'
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DeepSeek 官方账户余额查询(`GET /user/balance`)。
|
|
3
|
+
*
|
|
4
|
+
* 纯函数模块:只负责"用 key 换余额",密钥由调用方(channel 的 credentials
|
|
5
|
+
* seam → 环境变量兜底)解析,绝不在此打印或持久化。查询接口本身是只读的,
|
|
6
|
+
* 不消耗 API 额度(社区插件均按秒/分钟级轮询使用)。
|
|
7
|
+
*
|
|
8
|
+
* 响应结构(官方文档):
|
|
9
|
+
* { "is_available": true, "balance_infos": [
|
|
10
|
+
* { "currency": "CNY", "total_balance": "110.00",
|
|
11
|
+
* "granted_balance": "10.00", "topped_up_balance": "100.00" } ] }
|
|
12
|
+
* 余额字段是字符串数字;`granted` 为赠送余额,`topped_up` 为充值余额,
|
|
13
|
+
* 扣费优先扣赠送余额。
|
|
14
|
+
*/
|
|
15
|
+
/** 单个币种的余额快照(元)。 */
|
|
16
|
+
export interface BalanceInfo {
|
|
17
|
+
currency: string;
|
|
18
|
+
/** 总余额 = granted + toppedUp。 */
|
|
19
|
+
total: number;
|
|
20
|
+
/** 赠送余额。 */
|
|
21
|
+
granted: number;
|
|
22
|
+
/** 充值余额。 */
|
|
23
|
+
toppedUp: number;
|
|
24
|
+
}
|
|
25
|
+
export type BalanceResult = {
|
|
26
|
+
readonly ok: true;
|
|
27
|
+
/** 账户是否可用(是否有可用额度)。 */
|
|
28
|
+
readonly isAvailable: boolean;
|
|
29
|
+
readonly balances: readonly BalanceInfo[];
|
|
30
|
+
} | {
|
|
31
|
+
readonly ok: false;
|
|
32
|
+
/** 失败分类:无 key / 网络或超时 / 认证失败 / 非 2xx / 响应结构非法。 */
|
|
33
|
+
readonly reason: 'no-key' | 'network' | 'unauthorized' | 'http' | 'invalid';
|
|
34
|
+
/** 非 2xx 时的 HTTP 状态码(其余分类无)。 */
|
|
35
|
+
readonly status?: number;
|
|
36
|
+
};
|
|
37
|
+
/** 查询选项;fetchImpl 供无头回归注入。 */
|
|
38
|
+
export interface BalanceQueryOptions {
|
|
39
|
+
/** 覆盖全局 fetch(测试注入)。 */
|
|
40
|
+
fetchImpl?: typeof fetch;
|
|
41
|
+
/** 覆盖 API 根地址(测试或镜像)。 */
|
|
42
|
+
baseUrl?: string;
|
|
43
|
+
/** 超时毫秒数,默认 8000。 */
|
|
44
|
+
timeoutMs?: number;
|
|
45
|
+
}
|
|
46
|
+
export declare const DEEPSEEK_BALANCE_ENDPOINT = "https://api.deepseek.com/user/balance";
|
|
47
|
+
/**
|
|
48
|
+
* 查询 DeepSeek 官方账户余额。
|
|
49
|
+
* @param apiKey - `DEEPSEEK_API_KEY` 值;空字符串返回 no-key。
|
|
50
|
+
* @param options - 查询选项。
|
|
51
|
+
*/
|
|
52
|
+
export declare function fetchBalance(apiKey: string, options?: BalanceQueryOptions): Promise<BalanceResult>;
|
|
53
|
+
//# sourceMappingURL=deepseekBalance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deepseekBalance.d.ts","sourceRoot":"","sources":["../../src/deepseekBalance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,oBAAoB;AACpB,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAA;IAChB,gCAAgC;IAChC,KAAK,EAAE,MAAM,CAAA;IACb,YAAY;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,YAAY;IACZ,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,MAAM,aAAa,GACrB;IACA,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAA;IACjB,uBAAuB;IACvB,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAA;IAC7B,QAAQ,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAA;CAC1C,GACC;IACA,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAA;IAClB,kDAAkD;IAClD,QAAQ,CAAC,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,cAAc,GAAG,MAAM,GAAG,SAAS,CAAA;IAC3E,gCAAgC;IAChC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CACzB,CAAA;AAEH,8BAA8B;AAC9B,MAAM,WAAW,mBAAmB;IAClC,wBAAwB;IACxB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;IACxB,yBAAyB;IACzB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,qBAAqB;IACrB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,eAAO,MAAM,yBAAyB,0CAA0C,CAAA;AAIhF;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,aAAa,CAAC,CA4BxB"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DeepSeek 官方账户余额查询(`GET /user/balance`)。
|
|
3
|
+
*
|
|
4
|
+
* 纯函数模块:只负责"用 key 换余额",密钥由调用方(channel 的 credentials
|
|
5
|
+
* seam → 环境变量兜底)解析,绝不在此打印或持久化。查询接口本身是只读的,
|
|
6
|
+
* 不消耗 API 额度(社区插件均按秒/分钟级轮询使用)。
|
|
7
|
+
*
|
|
8
|
+
* 响应结构(官方文档):
|
|
9
|
+
* { "is_available": true, "balance_infos": [
|
|
10
|
+
* { "currency": "CNY", "total_balance": "110.00",
|
|
11
|
+
* "granted_balance": "10.00", "topped_up_balance": "100.00" } ] }
|
|
12
|
+
* 余额字段是字符串数字;`granted` 为赠送余额,`topped_up` 为充值余额,
|
|
13
|
+
* 扣费优先扣赠送余额。
|
|
14
|
+
*/
|
|
15
|
+
export const DEEPSEEK_BALANCE_ENDPOINT = 'https://api.deepseek.com/user/balance';
|
|
16
|
+
const DEFAULT_TIMEOUT_MS = 8000;
|
|
17
|
+
/**
|
|
18
|
+
* 查询 DeepSeek 官方账户余额。
|
|
19
|
+
* @param apiKey - `DEEPSEEK_API_KEY` 值;空字符串返回 no-key。
|
|
20
|
+
* @param options - 查询选项。
|
|
21
|
+
*/
|
|
22
|
+
export async function fetchBalance(apiKey, options = {}) {
|
|
23
|
+
if (apiKey === '')
|
|
24
|
+
return { ok: false, reason: 'no-key' };
|
|
25
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
26
|
+
const endpoint = options.baseUrl === undefined
|
|
27
|
+
? DEEPSEEK_BALANCE_ENDPOINT
|
|
28
|
+
: `${options.baseUrl.replace(/\/+$/, '')}/user/balance`;
|
|
29
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
30
|
+
const controller = new AbortController();
|
|
31
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
32
|
+
try {
|
|
33
|
+
const response = await fetchImpl(endpoint, {
|
|
34
|
+
headers: { authorization: `Bearer ${apiKey}` },
|
|
35
|
+
signal: controller.signal,
|
|
36
|
+
});
|
|
37
|
+
if (response.status === 401 || response.status === 403) {
|
|
38
|
+
return { ok: false, reason: 'unauthorized', status: response.status };
|
|
39
|
+
}
|
|
40
|
+
if (!response.ok) {
|
|
41
|
+
return { ok: false, reason: 'http', status: response.status };
|
|
42
|
+
}
|
|
43
|
+
const payload = await response.json().catch(() => undefined);
|
|
44
|
+
const parsed = parseBalancePayload(payload);
|
|
45
|
+
return parsed ?? { ok: false, reason: 'invalid' };
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return { ok: false, reason: 'network' };
|
|
49
|
+
}
|
|
50
|
+
finally {
|
|
51
|
+
clearTimeout(timer);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function parseBalancePayload(payload) {
|
|
55
|
+
if (payload === null || typeof payload !== 'object' || Array.isArray(payload))
|
|
56
|
+
return undefined;
|
|
57
|
+
const record = payload;
|
|
58
|
+
const infos = record.balance_infos;
|
|
59
|
+
if (!Array.isArray(infos))
|
|
60
|
+
return undefined;
|
|
61
|
+
const balances = [];
|
|
62
|
+
for (const raw of infos) {
|
|
63
|
+
if (raw === null || typeof raw !== 'object' || Array.isArray(raw))
|
|
64
|
+
return undefined;
|
|
65
|
+
const info = raw;
|
|
66
|
+
const currency = info.currency;
|
|
67
|
+
const total = parseCny(info.total_balance);
|
|
68
|
+
const granted = parseCny(info.granted_balance);
|
|
69
|
+
const toppedUp = parseCny(info.topped_up_balance);
|
|
70
|
+
if (typeof currency !== 'string' || currency === '' || total === undefined || granted === undefined || toppedUp === undefined) {
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
balances.push({ currency, total, granted, toppedUp });
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
ok: true,
|
|
77
|
+
isAvailable: record.is_available === true,
|
|
78
|
+
balances,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function parseCny(value) {
|
|
82
|
+
if (typeof value !== 'string' && typeof value !== 'number')
|
|
83
|
+
return undefined;
|
|
84
|
+
const parsed = Number(value);
|
|
85
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
86
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DeepSeek 官方定价与"本会话花费"估算(人民币口径)。
|
|
3
|
+
*
|
|
4
|
+
* 数据来源:DeepSeek 官方文档「模型 & 价格」页(2026-08 快照),单位为人民
|
|
5
|
+
* 币/百万 tokens。DeepSeek 官方 API 只返回 token 用量、不返回金额,本模块按
|
|
6
|
+
* 官方公开单价把会话累计 token 换算成金额 —— 这是**估算**,不是账单:
|
|
7
|
+
* 定价可能变动,且余额扣费发生在 DeepSeek 侧(以平台账单为准)。
|
|
8
|
+
*
|
|
9
|
+
* 计价规则(来自官方页面):
|
|
10
|
+
* - 扣减费用 = token 消耗量 × 模型单价;
|
|
11
|
+
* - 缓存命中的输入按命中价计费,其余输入(含写入缓存)按未命中价计费;
|
|
12
|
+
* - 高峰时段为北京时间周一至周五 9:00-12:00、14:00-18:00,其余为空闲时段
|
|
13
|
+
* (空闲价为高峰价的一半)。
|
|
14
|
+
*/
|
|
15
|
+
/** 单价对:`[空闲价, 高峰价]`,单位 元/百万 tokens。 */
|
|
16
|
+
export type CnyPerMillion = readonly [number, number];
|
|
17
|
+
/** 一个官方模型的完整价目(人民币/百万 tokens)。 */
|
|
18
|
+
export interface DeepSeekModelPrice {
|
|
19
|
+
/** 输入(缓存未命中,含写入缓存部分)。 */
|
|
20
|
+
inputMiss: CnyPerMillion;
|
|
21
|
+
/** 输入(缓存命中)。 */
|
|
22
|
+
inputHit: CnyPerMillion;
|
|
23
|
+
/** 输出。 */
|
|
24
|
+
output: CnyPerMillion;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* 在售模型价目表,按 API model id 前缀匹配(最长前缀优先)。
|
|
28
|
+
* 新模型上线而本表未收录时,估算返回 undefined,界面不显示金额(只显示
|
|
29
|
+
* token 用量),不会给出错误数字。
|
|
30
|
+
*/
|
|
31
|
+
export declare const DEEPSEEK_MODEL_PRICES: Readonly<Record<string, DeepSeekModelPrice>>;
|
|
32
|
+
/**
|
|
33
|
+
* DeepSeek 官方 API key 路由(余额/花费估算只对它们有意义)。参考社区
|
|
34
|
+
* dsh-balance 的 provider 判定:DSH 自带官方路由 `deepseek-official`
|
|
35
|
+
* (modelRoute.ts 默认路由),另兼容裸 `deepseek` 与 dsh-vision-router
|
|
36
|
+
* 的 `deepseek-vision` 包装路由。
|
|
37
|
+
*/
|
|
38
|
+
export declare const DEEPSEEK_OFFICIAL_PROVIDERS: readonly string[];
|
|
39
|
+
/** 是否 DeepSeek 官方 provider(余额与定价只适用于官方计费口径)。 */
|
|
40
|
+
export declare function isDeepSeekOfficialProvider(provider: string): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* 是否处于高峰计费时段:北京时间周一至周五 9:00-12:00、14:00-18:00。
|
|
43
|
+
* 北京时间为 UTC+8 固定偏移(无夏令时),用 UTC 时刻加偏移换算。
|
|
44
|
+
*/
|
|
45
|
+
export declare function isPeakHour(date?: Date): boolean;
|
|
46
|
+
/** 按前缀匹配模型价目,最长前缀优先;未收录返回 undefined。 */
|
|
47
|
+
export declare function priceForModel(model: string): DeepSeekModelPrice | undefined;
|
|
48
|
+
/** 会话累计 token(与 Channel.tokens 同构,含缓存分项)。 */
|
|
49
|
+
export interface CostTokenTotals {
|
|
50
|
+
input: number;
|
|
51
|
+
output: number;
|
|
52
|
+
cacheRead: number;
|
|
53
|
+
cacheWrite: number;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* 按计价时段分桶的会话 token:每笔 usage 按其发生时刻(event.time)落入
|
|
57
|
+
* 高峰或空闲桶,估算时各按对应单价——跨时段会话不会整段按当前时段计价。
|
|
58
|
+
*/
|
|
59
|
+
export interface CostTokenBuckets {
|
|
60
|
+
peak: CostTokenTotals;
|
|
61
|
+
idle: CostTokenTotals;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* 估算本会话花费拆分(人民币,元):高峰桶按高峰价、空闲桶按空闲价。
|
|
65
|
+
* 公式(每桶):(input − cacheRead) × 输入未命中价 + cacheRead × 输入命中价
|
|
66
|
+
* + output × 输出价;cacheWrite 不单独计价(写入缓存的 token 已计入 input
|
|
67
|
+
* 的未命中部分)。模型未收录或所有 token 均为零时返回 undefined(调用方
|
|
68
|
+
* 不显示金额)。这是**估算**,不是账单——定价可能变动,以 DeepSeek 平台
|
|
69
|
+
* 账单为准。
|
|
70
|
+
* @param tokens - 按计价时段分桶的会话累计 token。
|
|
71
|
+
* @param model - 当前模型 id(前缀匹配价目)。
|
|
72
|
+
*/
|
|
73
|
+
export declare function estimateSessionCostSplitCny(tokens: CostTokenBuckets, model: string): {
|
|
74
|
+
total: number;
|
|
75
|
+
peak: number;
|
|
76
|
+
idle: number;
|
|
77
|
+
} | undefined;
|
|
78
|
+
/**
|
|
79
|
+
* 估算本会话花费(人民币,元)——estimateSessionCostSplitCny 的总价捷径。
|
|
80
|
+
*/
|
|
81
|
+
export declare function estimateSessionCostCny(tokens: CostTokenBuckets, model: string): number | undefined;
|
|
82
|
+
//# sourceMappingURL=deepseekPricing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deepseekPricing.d.ts","sourceRoot":"","sources":["../../src/deepseekPricing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,uCAAuC;AACvC,MAAM,MAAM,aAAa,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAErD,kCAAkC;AAClC,MAAM,WAAW,kBAAkB;IACjC,yBAAyB;IACzB,SAAS,EAAE,aAAa,CAAA;IACxB,gBAAgB;IAChB,QAAQ,EAAE,aAAa,CAAA;IACvB,UAAU;IACV,MAAM,EAAE,aAAa,CAAA;CACtB;AAED;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAgB9E,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,EAAE,SAAS,MAAM,EAIxD,CAAA;AAED,gDAAgD;AAChD,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEpE;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,GAAE,IAAiB,GAAG,OAAO,CAM3D;AAED,wCAAwC;AACxC,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAU3E;AAED,6CAA6C;AAC7C,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,eAAe,CAAA;IACrB,IAAI,EAAE,eAAe,CAAA;CACtB;AAiCD;;;;;;;;;GASG;AACH,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,gBAAgB,EACxB,KAAK,EAAE,MAAM,GACZ;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAc3D;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,gBAAgB,EACxB,KAAK,EAAE,MAAM,GACZ,MAAM,GAAG,SAAS,CAEpB"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DeepSeek 官方定价与"本会话花费"估算(人民币口径)。
|
|
3
|
+
*
|
|
4
|
+
* 数据来源:DeepSeek 官方文档「模型 & 价格」页(2026-08 快照),单位为人民
|
|
5
|
+
* 币/百万 tokens。DeepSeek 官方 API 只返回 token 用量、不返回金额,本模块按
|
|
6
|
+
* 官方公开单价把会话累计 token 换算成金额 —— 这是**估算**,不是账单:
|
|
7
|
+
* 定价可能变动,且余额扣费发生在 DeepSeek 侧(以平台账单为准)。
|
|
8
|
+
*
|
|
9
|
+
* 计价规则(来自官方页面):
|
|
10
|
+
* - 扣减费用 = token 消耗量 × 模型单价;
|
|
11
|
+
* - 缓存命中的输入按命中价计费,其余输入(含写入缓存)按未命中价计费;
|
|
12
|
+
* - 高峰时段为北京时间周一至周五 9:00-12:00、14:00-18:00,其余为空闲时段
|
|
13
|
+
* (空闲价为高峰价的一半)。
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* 在售模型价目表,按 API model id 前缀匹配(最长前缀优先)。
|
|
17
|
+
* 新模型上线而本表未收录时,估算返回 undefined,界面不显示金额(只显示
|
|
18
|
+
* token 用量),不会给出错误数字。
|
|
19
|
+
*/
|
|
20
|
+
export const DEEPSEEK_MODEL_PRICES = {
|
|
21
|
+
'deepseek-v4-flash': {
|
|
22
|
+
inputMiss: [1.5, 3.0],
|
|
23
|
+
inputHit: [0.05, 0.10],
|
|
24
|
+
output: [4.5, 9.0],
|
|
25
|
+
},
|
|
26
|
+
'deepseek-v4-pro': {
|
|
27
|
+
inputMiss: [4.5, 9.0],
|
|
28
|
+
inputHit: [0.15, 0.30],
|
|
29
|
+
output: [13.5, 27.0],
|
|
30
|
+
},
|
|
31
|
+
'deepseek-v4-flash-vision-exp': {
|
|
32
|
+
inputMiss: [1.5, 3.0],
|
|
33
|
+
inputHit: [0.05, 0.10],
|
|
34
|
+
output: [4.5, 9.0],
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* DeepSeek 官方 API key 路由(余额/花费估算只对它们有意义)。参考社区
|
|
39
|
+
* dsh-balance 的 provider 判定:DSH 自带官方路由 `deepseek-official`
|
|
40
|
+
* (modelRoute.ts 默认路由),另兼容裸 `deepseek` 与 dsh-vision-router
|
|
41
|
+
* 的 `deepseek-vision` 包装路由。
|
|
42
|
+
*/
|
|
43
|
+
export const DEEPSEEK_OFFICIAL_PROVIDERS = [
|
|
44
|
+
'deepseek',
|
|
45
|
+
'deepseek-official',
|
|
46
|
+
'deepseek-vision',
|
|
47
|
+
];
|
|
48
|
+
/** 是否 DeepSeek 官方 provider(余额与定价只适用于官方计费口径)。 */
|
|
49
|
+
export function isDeepSeekOfficialProvider(provider) {
|
|
50
|
+
return DEEPSEEK_OFFICIAL_PROVIDERS.includes(provider);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* 是否处于高峰计费时段:北京时间周一至周五 9:00-12:00、14:00-18:00。
|
|
54
|
+
* 北京时间为 UTC+8 固定偏移(无夏令时),用 UTC 时刻加偏移换算。
|
|
55
|
+
*/
|
|
56
|
+
export function isPeakHour(date = new Date()) {
|
|
57
|
+
const shifted = new Date(date.getTime() + 8 * 3_600_000);
|
|
58
|
+
const weekday = shifted.getUTCDay(); // 0 = Sunday
|
|
59
|
+
const hour = shifted.getUTCHours();
|
|
60
|
+
if (weekday === 0 || weekday === 6)
|
|
61
|
+
return false;
|
|
62
|
+
return (hour >= 9 && hour < 12) || (hour >= 14 && hour < 18);
|
|
63
|
+
}
|
|
64
|
+
/** 按前缀匹配模型价目,最长前缀优先;未收录返回 undefined。 */
|
|
65
|
+
export function priceForModel(model) {
|
|
66
|
+
let best;
|
|
67
|
+
let bestLength = 0;
|
|
68
|
+
for (const [prefix, price] of Object.entries(DEEPSEEK_MODEL_PRICES)) {
|
|
69
|
+
if (model.startsWith(prefix) && prefix.length > bestLength) {
|
|
70
|
+
best = price;
|
|
71
|
+
bestLength = prefix.length;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return best;
|
|
75
|
+
}
|
|
76
|
+
/** 空桶(防御 tokens.peak/idle 缺失的旧数据/测试桩)。 */
|
|
77
|
+
const EMPTY_TOTALS = Object.freeze({
|
|
78
|
+
input: 0,
|
|
79
|
+
output: 0,
|
|
80
|
+
cacheRead: 0,
|
|
81
|
+
cacheWrite: 0,
|
|
82
|
+
});
|
|
83
|
+
/** 按高峰/空闲单价分别计价,返回 [高峰元, 空闲元](未除 1e6)。 */
|
|
84
|
+
function costSplit(tokens, price) {
|
|
85
|
+
// 分桶字段在真实 Channel 上恒有(emptyTokenUsage 初始化),但旧快照与
|
|
86
|
+
// 测试桩可能缺桶——缺失时按空桶计,绝不抛错。
|
|
87
|
+
const peak = tokens.peak ?? EMPTY_TOTALS;
|
|
88
|
+
const idle = tokens.idle ?? EMPTY_TOTALS;
|
|
89
|
+
const costOf = (bucket, rateIndex) => {
|
|
90
|
+
const input = Math.max(0, bucket.input);
|
|
91
|
+
const output = Math.max(0, bucket.output);
|
|
92
|
+
const cacheRead = Math.max(0, Math.min(input, bucket.cacheRead));
|
|
93
|
+
return (input - cacheRead) * price.inputMiss[rateIndex]
|
|
94
|
+
+ cacheRead * price.inputHit[rateIndex]
|
|
95
|
+
+ output * price.output[rateIndex];
|
|
96
|
+
};
|
|
97
|
+
return {
|
|
98
|
+
peak: costOf(peak, 1),
|
|
99
|
+
idle: costOf(idle, 0),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* 估算本会话花费拆分(人民币,元):高峰桶按高峰价、空闲桶按空闲价。
|
|
104
|
+
* 公式(每桶):(input − cacheRead) × 输入未命中价 + cacheRead × 输入命中价
|
|
105
|
+
* + output × 输出价;cacheWrite 不单独计价(写入缓存的 token 已计入 input
|
|
106
|
+
* 的未命中部分)。模型未收录或所有 token 均为零时返回 undefined(调用方
|
|
107
|
+
* 不显示金额)。这是**估算**,不是账单——定价可能变动,以 DeepSeek 平台
|
|
108
|
+
* 账单为准。
|
|
109
|
+
* @param tokens - 按计价时段分桶的会话累计 token。
|
|
110
|
+
* @param model - 当前模型 id(前缀匹配价目)。
|
|
111
|
+
*/
|
|
112
|
+
export function estimateSessionCostSplitCny(tokens, model) {
|
|
113
|
+
const price = priceForModel(model);
|
|
114
|
+
if (price === undefined)
|
|
115
|
+
return undefined;
|
|
116
|
+
const split = costSplit(tokens, price);
|
|
117
|
+
const peak = tokens.peak ?? EMPTY_TOTALS;
|
|
118
|
+
const idle = tokens.idle ?? EMPTY_TOTALS;
|
|
119
|
+
const totalTokens = peak.input + peak.output + idle.input + idle.output;
|
|
120
|
+
if (totalTokens <= 0)
|
|
121
|
+
return undefined;
|
|
122
|
+
return {
|
|
123
|
+
total: split.peak / 1_000_000 + split.idle / 1_000_000,
|
|
124
|
+
peak: split.peak / 1_000_000,
|
|
125
|
+
idle: split.idle / 1_000_000,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* 估算本会话花费(人民币,元)——estimateSessionCostSplitCny 的总价捷径。
|
|
130
|
+
*/
|
|
131
|
+
export function estimateSessionCostCny(tokens, model) {
|
|
132
|
+
return estimateSessionCostSplitCny(tokens, model)?.total;
|
|
133
|
+
}
|