dsh-code 1.0.3 → 1.0.5
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 +293 -285
- package/bin/deepseek.mjs +245 -12
- package/cordis.patch.yml +12 -14
- package/lib/index.mjs +1939 -903
- package/lib/types/app.d.ts +11 -2
- package/lib/types/commands.d.ts +13 -0
- package/lib/types/git-workflow.d.ts +7 -2
- package/lib/types/history.d.ts +18 -11
- package/lib/types/index.d.ts +28 -0
- package/lib/types/input-split.d.ts +54 -0
- package/lib/types/kernel-panels.d.ts +3 -1
- package/lib/types/keyboard.d.ts +8 -0
- package/lib/types/presets.d.ts +4 -1
- package/lib/types/provider-settings.d.ts +77 -0
- package/lib/types/questions.d.ts +16 -12
- package/lib/types/render/projection.d.ts +9 -2
- package/lib/types/render/status.d.ts +22 -15
- package/lib/types/settings-file.d.ts +8 -0
- package/lib/types/skills.d.ts +1 -1
- package/package.json +49 -46
- package/src/app.ts +5459 -4900
- package/src/approval.ts +8 -3
- package/src/authorization-panel.ts +2 -4
- package/src/commands.ts +27 -3
- package/src/git-workflow.ts +29 -10
- package/src/history.ts +22 -13
- package/src/index.ts +203 -61
- package/src/input-split.ts +191 -0
- package/src/internals.ts +26 -8
- package/src/kernel-panels.ts +26 -10
- package/src/keyboard.ts +123 -88
- package/src/mentions.ts +42 -9
- package/src/permissions.ts +1 -1
- package/src/presets.ts +19 -6
- package/src/provider-settings.ts +204 -0
- package/src/questions.ts +58 -55
- package/src/render/export.ts +7 -7
- package/src/render/lines.ts +24 -12
- package/src/render/markdown.ts +15 -13
- package/src/render/projection.ts +101 -13
- package/src/render/status.ts +76 -71
- package/src/render/text.ts +9 -3
- package/src/settings-file.ts +38 -6
- package/src/skills.ts +19 -6
- package/src/theme-panel.ts +79 -72
package/src/theme-panel.ts
CHANGED
|
@@ -1,72 +1,79 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The `/theme` picker (the Codex `/theme` contract): one bounded list over
|
|
3
|
-
* the three color themes — dark, light, and auto (terminal-sensed; auto
|
|
4
|
-
* falls back to dark until OSC-11 detection lands). Enter applies the row
|
|
5
|
-
* and the runner persists it; Esc closes without changing the theme.
|
|
6
|
-
*
|
|
7
|
-
* @module @deepseek-ai/dsh-tui/theme-panel
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { createElement, useState, type ReactElement } from 'react'
|
|
11
|
-
import { Box, Text, useInput, useStdout } from 'ink'
|
|
12
|
-
import { panelViewport } from './render/inspector.ts'
|
|
13
|
-
import { truncateColumns } from './render/text.ts'
|
|
14
|
-
import { getPalette, inkColor, type ThemeName } from './theme.ts'
|
|
15
|
-
|
|
16
|
-
/** The three theme rows in canonical order (the /theme selection surface). */
|
|
17
|
-
const THEME_ROWS: readonly { id: ThemeName; label: string; description: string }[] = [
|
|
18
|
-
{ id: 'dark', label: 'dark', description: 'DeepSeek dark palette (default)' },
|
|
19
|
-
{ id: 'light', label: 'light', description: 'light palette for bright terminals' },
|
|
20
|
-
{ id: 'auto', label: 'auto', description: 'follow the terminal; dark until detection lands' },
|
|
21
|
-
]
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* The /theme list: one row per theme, the current one marked with ●, the
|
|
25
|
-
* focused one with ›. Enter applies the focused theme (the runner persists
|
|
26
|
-
* it), Esc/q closes without changing anything. Colors read the ACTIVE
|
|
27
|
-
* palette, so the panel itself adapts to a light theme once applied.
|
|
28
|
-
*/
|
|
29
|
-
export function ThemePanel({ current, select, close }: {
|
|
30
|
-
/** Theme name in force (the requested name; 'auto' included). */
|
|
31
|
-
current: ThemeName
|
|
32
|
-
/** Accept one theme name: applied immediately and persisted by the runner. */
|
|
33
|
-
select(name: ThemeName): void
|
|
34
|
-
/** Close without changing the theme. */
|
|
35
|
-
close(): void
|
|
36
|
-
}): ReactElement {
|
|
37
|
-
const [cursor, setCursor] = useState(() => {
|
|
38
|
-
const index = THEME_ROWS.findIndex(theme => theme.id === current)
|
|
39
|
-
return index < 0 ? 0 : index
|
|
40
|
-
})
|
|
41
|
-
const stdout = useStdout().stdout
|
|
42
|
-
const viewport = panelViewport(stdout?.columns ?? 80, stdout?.rows ?? 30)
|
|
43
|
-
useInput((input, key) => {
|
|
44
|
-
if (key.escape || input === 'q') return close()
|
|
45
|
-
if (key.upArrow) return setCursor(value => (value + THEME_ROWS.length - 1) % THEME_ROWS.length)
|
|
46
|
-
if (key.downArrow) return setCursor(value => (value + 1) % THEME_ROWS.length)
|
|
47
|
-
if (key.return) return select(THEME_ROWS[cursor]!.id)
|
|
48
|
-
})
|
|
49
|
-
if (viewport.maxHeight === 0
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
1
|
+
/**
|
|
2
|
+
* The `/theme` picker (the Codex `/theme` contract): one bounded list over
|
|
3
|
+
* the three color themes — dark, light, and auto (terminal-sensed; auto
|
|
4
|
+
* falls back to dark until OSC-11 detection lands). Enter applies the row
|
|
5
|
+
* and the runner persists it; Esc closes without changing the theme.
|
|
6
|
+
*
|
|
7
|
+
* @module @deepseek-ai/dsh-tui/theme-panel
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { createElement, useState, type ReactElement } from 'react'
|
|
11
|
+
import { Box, Text, useInput, useStdout } from 'ink'
|
|
12
|
+
import { clampScroll, panelViewport } from './render/inspector.ts'
|
|
13
|
+
import { truncateColumns } from './render/text.ts'
|
|
14
|
+
import { getPalette, inkColor, type ThemeName } from './theme.ts'
|
|
15
|
+
|
|
16
|
+
/** The three theme rows in canonical order (the /theme selection surface). */
|
|
17
|
+
const THEME_ROWS: readonly { id: ThemeName; label: string; description: string }[] = [
|
|
18
|
+
{ id: 'dark', label: 'dark', description: 'DeepSeek dark palette (default)' },
|
|
19
|
+
{ id: 'light', label: 'light', description: 'light palette for bright terminals' },
|
|
20
|
+
{ id: 'auto', label: 'auto', description: 'follow the terminal; dark until detection lands' },
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The /theme list: one row per theme, the current one marked with ●, the
|
|
25
|
+
* focused one with ›. Enter applies the focused theme (the runner persists
|
|
26
|
+
* it), Esc/q closes without changing anything. Colors read the ACTIVE
|
|
27
|
+
* palette, so the panel itself adapts to a light theme once applied.
|
|
28
|
+
*/
|
|
29
|
+
export function ThemePanel({ current, select, close }: {
|
|
30
|
+
/** Theme name in force (the requested name; 'auto' included). */
|
|
31
|
+
current: ThemeName
|
|
32
|
+
/** Accept one theme name: applied immediately and persisted by the runner. */
|
|
33
|
+
select(name: ThemeName): void
|
|
34
|
+
/** Close without changing the theme. */
|
|
35
|
+
close(): void
|
|
36
|
+
}): ReactElement {
|
|
37
|
+
const [cursor, setCursor] = useState(() => {
|
|
38
|
+
const index = THEME_ROWS.findIndex(theme => theme.id === current)
|
|
39
|
+
return index < 0 ? 0 : index
|
|
40
|
+
})
|
|
41
|
+
const stdout = useStdout().stdout
|
|
42
|
+
const viewport = panelViewport(stdout?.columns ?? 80, stdout?.rows ?? 30)
|
|
43
|
+
useInput((input, key) => {
|
|
44
|
+
if (key.escape || input === 'q') return close()
|
|
45
|
+
if (key.upArrow) return setCursor(value => (value + THEME_ROWS.length - 1) % THEME_ROWS.length)
|
|
46
|
+
if (key.downArrow) return setCursor(value => (value + 1) % THEME_ROWS.length)
|
|
47
|
+
if (key.return) return select(THEME_ROWS[cursor]!.id)
|
|
48
|
+
})
|
|
49
|
+
if (viewport.maxHeight === 0 || viewport.compact) {
|
|
50
|
+
return createElement(Text, { wrap: 'truncate-end' }, truncateColumns('/theme · esc close', viewport.contentColumns))
|
|
51
|
+
}
|
|
52
|
+
// The theme rows share the panel's body budget like every other panel: an
|
|
53
|
+
// unsliced three-row list reached terminal-height equality on short
|
|
54
|
+
// terminals, where Ink rewrites the whole Static region every frame.
|
|
55
|
+
// Reveal-cursor slicing keeps the focused row visible instead.
|
|
56
|
+
const rowBudget = Math.max(1, viewport.bodyRows)
|
|
57
|
+
const first = clampScroll(cursor, THEME_ROWS.length, rowBudget)
|
|
58
|
+
const visibleThemes = THEME_ROWS.slice(first, first + rowBudget)
|
|
59
|
+
const hiddenThemes = THEME_ROWS.length - visibleThemes.length
|
|
60
|
+
return createElement(
|
|
61
|
+
Box,
|
|
62
|
+
{ width: viewport.outerColumns, borderStyle: 'round', borderColor: inkColor(getPalette().dim), flexDirection: 'column', paddingX: 1 },
|
|
63
|
+
createElement(Text, { color: inkColor(getPalette().brandBright), wrap: 'truncate-end' }, truncateColumns('/theme — color palette', viewport.contentColumns)),
|
|
64
|
+
...visibleThemes.map((theme, index) => {
|
|
65
|
+
const selected = first + index === cursor
|
|
66
|
+
const active = theme.id === current
|
|
67
|
+
return createElement(
|
|
68
|
+
Text,
|
|
69
|
+
{
|
|
70
|
+
key: theme.id,
|
|
71
|
+
color: selected ? inkColor(getPalette().brandBright) : undefined,
|
|
72
|
+
wrap: 'truncate-end',
|
|
73
|
+
},
|
|
74
|
+
truncateColumns(`${selected ? '› ' : ' '}${active ? '● ' : '○ '}${theme.label}${active ? ' · current' : ''} · ${theme.description}`, viewport.contentColumns),
|
|
75
|
+
)
|
|
76
|
+
}),
|
|
77
|
+
createElement(Text, { dimColor: true, wrap: 'truncate-end' }, truncateColumns(`↑↓ choose · enter apply · esc/q close${hiddenThemes > 0 ? ` · +${hiddenThemes} more` : ''}`, viewport.contentColumns)),
|
|
78
|
+
)
|
|
79
|
+
}
|