dsh-code 0.9.0 → 1.0.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.en.md +31 -8
- package/README.md +264 -241
- package/bin/deepseek.mjs +100 -6
- package/cordis.patch.yml +29 -1
- package/lib/index.mjs +2317 -708
- package/lib/startup.mjs +21 -11
- package/lib/{theme-BEi4i_aN.mjs → theme-DCT8Y2xf.mjs} +13 -9
- package/lib/types/app.d.ts +66 -14
- package/lib/types/attachments.d.ts +7 -0
- package/lib/types/editor.d.ts +6 -0
- package/lib/types/fork.d.ts +8 -0
- package/lib/types/git-workflow.d.ts +23 -0
- package/lib/types/index.d.ts +6 -0
- package/lib/types/kernel-panels.d.ts +39 -0
- package/lib/types/keyboard.d.ts +43 -0
- package/lib/types/mentions.d.ts +28 -38
- package/lib/types/presets.d.ts +1 -3
- package/lib/types/provider-settings.d.ts +16 -0
- package/lib/types/render/animations.d.ts +24 -41
- package/lib/types/render/editor.d.ts +137 -0
- package/lib/types/render/export.d.ts +1 -1
- package/lib/types/render/lines.d.ts +6 -2
- package/lib/types/render/markdown.d.ts +3 -1
- package/lib/types/render/projection.d.ts +29 -3
- package/lib/types/render/status.d.ts +5 -12
- package/lib/types/session-directory.d.ts +1 -3
- package/lib/types/startup.d.ts +14 -11
- package/lib/types/store.d.ts +11 -9
- package/lib/types/subagents.d.ts +3 -3
- package/lib/types/theme.d.ts +14 -1
- package/lib/types/version.d.ts +15 -2
- package/package.json +153 -117
- package/src/app.ts +4455 -3904
- package/src/attachments.ts +44 -0
- package/src/editor.ts +51 -0
- package/src/fork.ts +31 -0
- package/src/git-workflow.ts +87 -0
- package/src/index.ts +1510 -1374
- package/src/internals.ts +14 -1
- package/src/kernel-panels.ts +914 -798
- package/src/keyboard.ts +125 -0
- package/src/mentions.ts +72 -117
- package/src/presets.ts +1 -4
- package/src/provider-settings.ts +94 -0
- package/src/render/animations.ts +74 -60
- package/src/render/editor.ts +398 -0
- package/src/render/export.ts +79 -79
- package/src/render/lines.ts +342 -236
- package/src/render/markdown.ts +99 -26
- package/src/render/projection.ts +102 -19
- package/src/render/status.ts +713 -650
- package/src/render/text.ts +150 -150
- package/src/render/tool-detail.ts +3 -1
- package/src/session-directory.ts +3 -3
- package/src/startup.ts +136 -119
- package/src/store.ts +23 -11
- package/src/subagents.ts +13 -5
- package/src/theme.ts +214 -206
- package/src/version.ts +58 -1
package/bin/deepseek.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import { spawn } from 'node:child_process'
|
|
3
|
+
import { spawn, spawnSync } from 'node:child_process'
|
|
4
4
|
import { existsSync, readFileSync, realpathSync } from 'node:fs'
|
|
5
5
|
import { createRequire } from 'node:module'
|
|
6
6
|
import { homedir } from 'node:os'
|
|
@@ -8,10 +8,23 @@ import { join, resolve } from 'node:path'
|
|
|
8
8
|
import { fileURLToPath, pathToFileURL } from 'node:url'
|
|
9
9
|
|
|
10
10
|
const packageRequire = createRequire(import.meta.url)
|
|
11
|
+
const packageVersion = packageRequire('../package.json').version
|
|
11
12
|
|
|
12
13
|
/** Arguments required to boot DSH-Code's conventional profile. */
|
|
13
14
|
export const profileArgs = (args = []) => ['--profile', 'cli', ...args]
|
|
14
15
|
|
|
16
|
+
export const OPERATION_COMMANDS = ['setup', 'doctor', 'completion', 'update']
|
|
17
|
+
|
|
18
|
+
/** Exact first-day package spec used by setup (pnpm delays an unpinned release). */
|
|
19
|
+
export const setupBundle = (args = []) => args.includes('--local')
|
|
20
|
+
? fileURLToPath(new URL('..', import.meta.url))
|
|
21
|
+
: `dsh-code@${packageVersion}`
|
|
22
|
+
|
|
23
|
+
/** Wrapper-owned operation, or undefined when arguments belong to the TUI. */
|
|
24
|
+
export function operationName(args = process.argv.slice(2)) {
|
|
25
|
+
return OPERATION_COMMANDS.includes(args[0]) ? args[0] : undefined
|
|
26
|
+
}
|
|
27
|
+
|
|
15
28
|
/** The conventional cli profile directory under the DSH home. */
|
|
16
29
|
export function cliProfileDir(home = homedir()) {
|
|
17
30
|
return join(home, '.dsh', 'profiles', 'cli')
|
|
@@ -46,20 +59,20 @@ export function globalDshRoots() {
|
|
|
46
59
|
}
|
|
47
60
|
|
|
48
61
|
/** Resolve the DSH entrypoint without passing user arguments through a Windows shell. */
|
|
49
|
-
export function
|
|
62
|
+
export function rawDshCommand(args, {
|
|
50
63
|
platform = process.platform,
|
|
51
64
|
moduleUrl = import.meta.url,
|
|
52
65
|
fileExists = existsSync,
|
|
53
66
|
roots = globalDshRoots(),
|
|
54
67
|
resolvePackage = packageRequire.resolve,
|
|
55
68
|
} = {}) {
|
|
56
|
-
if (platform !== 'win32') return { command: 'dsh', args
|
|
69
|
+
if (platform !== 'win32') return { command: 'dsh', args }
|
|
57
70
|
const adjacentEntrypoint = fileURLToPath(new URL('../../@deepseek-ai/dsh/lib/bin.js', moduleUrl))
|
|
58
|
-
if (fileExists(adjacentEntrypoint)) return { command: process.execPath, args: [adjacentEntrypoint, ...
|
|
71
|
+
if (fileExists(adjacentEntrypoint)) return { command: process.execPath, args: [adjacentEntrypoint, ...args] }
|
|
59
72
|
for (const root of roots) {
|
|
60
73
|
try {
|
|
61
74
|
const entrypoint = resolvePackage('@deepseek-ai/dsh/lib/bin.js', { paths: [root] })
|
|
62
|
-
return { command: process.execPath, args: [entrypoint, ...
|
|
75
|
+
return { command: process.execPath, args: [entrypoint, ...args] }
|
|
63
76
|
} catch {
|
|
64
77
|
// The next configured global prefix may own DSH instead.
|
|
65
78
|
}
|
|
@@ -67,6 +80,86 @@ export function dshCommand(args, {
|
|
|
67
80
|
return undefined
|
|
68
81
|
}
|
|
69
82
|
|
|
83
|
+
/** Resolve the normal TUI boot command. */
|
|
84
|
+
export function dshCommand(args, options = {}) {
|
|
85
|
+
return rawDshCommand(profileArgs(args), options)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** Static shell completion for wrapper commands and the TUI's local flags. */
|
|
89
|
+
export function completionScript(shell) {
|
|
90
|
+
const words = 'setup doctor completion update --help --version --resume --continue --session --mode --theme --image'
|
|
91
|
+
if (shell === 'bash') return `_deepseek_complete() { COMPREPLY=( $(compgen -W "${words}" -- "\${COMP_WORDS[COMP_CWORD]}") ); }\ncomplete -F _deepseek_complete deepseek dsh-code`
|
|
92
|
+
if (shell === 'zsh') return `#compdef deepseek dsh-code\n_arguments '1:command:(${words})'`
|
|
93
|
+
if (shell === 'powershell' || shell === 'pwsh') return `Register-ArgumentCompleter -Native -CommandName deepseek,dsh-code -ScriptBlock { param($wordToComplete) '${words}'.Split(' ') | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object { [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_) } }`
|
|
94
|
+
throw new Error('completion needs one shell: bash, zsh, or powershell')
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function printDoctor(resolveCommand = rawDshCommand, spawnCommand = spawnSync) {
|
|
98
|
+
const checks = []
|
|
99
|
+
const [major, minor] = process.versions.node.split('.').map(Number)
|
|
100
|
+
checks.push({ ok: major > 22 || (major === 22 && minor >= 19), label: `Node ${process.versions.node}`, detail: 'requires ^22.19 or >=24' })
|
|
101
|
+
const command = resolveCommand(['--profile', 'cli', '--dump-config'])
|
|
102
|
+
checks.push({ ok: command !== undefined, label: '@deepseek-ai/dsh', detail: command === undefined ? 'not found beside dsh-code' : 'entrypoint resolved' })
|
|
103
|
+
checks.push({ ok: profileHasDshCode(), label: 'cli profile', detail: cliProfileDir() })
|
|
104
|
+
if (command !== undefined && profileHasDshCode()) {
|
|
105
|
+
const probe = spawnCommand(command.command, command.args, { encoding: 'utf8', windowsHide: true })
|
|
106
|
+
const output = String(probe.stdout ?? '')
|
|
107
|
+
checks.push({ ok: probe.status === 0 && output.includes('dsh-code'), label: 'composition', detail: probe.status === 0 ? 'dump-config contains dsh-code' : String(probe.stderr ?? '').trim() })
|
|
108
|
+
}
|
|
109
|
+
for (const check of checks) console.log(`${check.ok ? 'ok ' : 'fail'} ${check.label} - ${check.detail}`)
|
|
110
|
+
process.exitCode = checks.every(check => check.ok) ? 0 : 1
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function launchChild(command, args) {
|
|
114
|
+
const child = spawn(command, args, { stdio: 'inherit' })
|
|
115
|
+
child.once('error', error => {
|
|
116
|
+
console.error(`dsh-code: command failed: ${error.message}`)
|
|
117
|
+
process.exitCode = 1
|
|
118
|
+
})
|
|
119
|
+
child.once('exit', (code, signal) => { process.exitCode = code ?? (signal === null ? 0 : 1) })
|
|
120
|
+
return child
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** Run one wrapper-owned operational command. */
|
|
124
|
+
export function launchOperation(args = process.argv.slice(2)) {
|
|
125
|
+
const operation = operationName(args)
|
|
126
|
+
if (operation === undefined) return undefined
|
|
127
|
+
if (operation === 'completion') {
|
|
128
|
+
try {
|
|
129
|
+
console.log(completionScript(args[1]))
|
|
130
|
+
} catch (error) {
|
|
131
|
+
console.error(`dsh-code: ${error.message}`)
|
|
132
|
+
process.exitCode = 1
|
|
133
|
+
}
|
|
134
|
+
return true
|
|
135
|
+
}
|
|
136
|
+
if (operation === 'doctor') {
|
|
137
|
+
printDoctor()
|
|
138
|
+
return true
|
|
139
|
+
}
|
|
140
|
+
if (operation === 'setup') {
|
|
141
|
+
// pnpm deliberately delays unpinned packages during their first 24 hours.
|
|
142
|
+
// Setup must mount the exact globally installed release on launch day.
|
|
143
|
+
const command = rawDshCommand(['plugin', '--profile', 'cli', 'add', setupBundle(args)])
|
|
144
|
+
if (command === undefined) {
|
|
145
|
+
console.error('dsh-code: @deepseek-ai/dsh is not installed; run: npm install -g @deepseek-ai/dsh dsh-code')
|
|
146
|
+
process.exitCode = 1
|
|
147
|
+
return true
|
|
148
|
+
}
|
|
149
|
+
return launchChild(command.command, command.args)
|
|
150
|
+
}
|
|
151
|
+
if (args.includes('--apply')) {
|
|
152
|
+
return launchChild(process.platform === 'win32' ? 'npm.cmd' : 'npm', ['install', '-g', '@deepseek-ai/dsh', 'dsh-code'])
|
|
153
|
+
}
|
|
154
|
+
const npm = process.platform === 'win32' ? 'npm.cmd' : 'npm'
|
|
155
|
+
for (const name of ['@deepseek-ai/dsh', 'dsh-code']) {
|
|
156
|
+
const result = spawnSync(npm, ['view', name, 'version'], { encoding: 'utf8', windowsHide: true })
|
|
157
|
+
console.log(`${name}: ${result.status === 0 ? String(result.stdout).trim() : 'version check failed'}`)
|
|
158
|
+
}
|
|
159
|
+
console.log('Run `deepseek update --apply` to install the latest versions.')
|
|
160
|
+
return true
|
|
161
|
+
}
|
|
162
|
+
|
|
70
163
|
/** Launch the installed DSH CLI while preserving its exit status and stdio. */
|
|
71
164
|
export function launchDsh(
|
|
72
165
|
args = process.argv.slice(2),
|
|
@@ -101,5 +194,6 @@ export function launchDsh(
|
|
|
101
194
|
|
|
102
195
|
const entrypoint = process.argv[1]
|
|
103
196
|
if (entrypoint !== undefined && pathToFileURL(realpathSync(resolve(entrypoint))).href === import.meta.url) {
|
|
104
|
-
launchDsh()
|
|
197
|
+
if (operationName() === undefined) launchDsh()
|
|
198
|
+
else launchOperation()
|
|
105
199
|
}
|
package/cordis.patch.yml
CHANGED
|
@@ -69,7 +69,14 @@
|
|
|
69
69
|
- id: tool-todo
|
|
70
70
|
disabled: true
|
|
71
71
|
- id: tool-web
|
|
72
|
-
|
|
72
|
+
config:
|
|
73
|
+
# web_fetch is a core TUI capability, not an opt-in: the fetch provider
|
|
74
|
+
# (web-fetch-http below) needs no API key. The per-preset tool-web rows
|
|
75
|
+
# keep `fetch: false` on the agent plane; through the scope-layered tool
|
|
76
|
+
# registry the preset's web_search shadows the host's same-name tool while
|
|
77
|
+
# the host's web_fetch stays visible, so every model still sees both.
|
|
78
|
+
fetch: true
|
|
79
|
+
searchTimeoutMs: 60000
|
|
73
80
|
|
|
74
81
|
- insert:
|
|
75
82
|
# Code Mode is a core execution capability, not a Web component.
|
|
@@ -82,6 +89,13 @@
|
|
|
82
89
|
- id: session-reference
|
|
83
90
|
name: '@deepseek-ai/dsh-session-reference'
|
|
84
91
|
|
|
92
|
+
# Workspace @file mention discovery: a bounded per-agent fuzzy index over
|
|
93
|
+
# the session cwd (directory listing, symlink guards, tool/result
|
|
94
|
+
# invalidation). The TUI's @ completion consumes ctx.fileReferences
|
|
95
|
+
# instead of running its own workspace scan.
|
|
96
|
+
- id: file-reference-local
|
|
97
|
+
name: '@deepseek-ai/dsh-file-reference-local'
|
|
98
|
+
|
|
85
99
|
# The launcher supplies the shipped preset root beside its own config and
|
|
86
100
|
# the service also discovers the user's local preset root.
|
|
87
101
|
- id: agent-presets
|
|
@@ -89,6 +103,20 @@
|
|
|
89
103
|
config:
|
|
90
104
|
default: standard
|
|
91
105
|
|
|
106
|
+
# Cordis self-inspection (the shipped `cordis` agent preset's toolset):
|
|
107
|
+
# the host runner publishes the `dynamicCordisRunner`/`cordisInspect`
|
|
108
|
+
# services `tool-cordis` injects. Without this host row the preset mount
|
|
109
|
+
# fails ("1 row(s) did not activate: tool-cordis"), because models write
|
|
110
|
+
# composition through the agent plane but the runner is a host singleton.
|
|
111
|
+
- id: cordis-host-runner
|
|
112
|
+
name: '@deepseek-ai/dsh-cordis-host-runner'
|
|
113
|
+
|
|
114
|
+
# Anonymous public HTTP(S) fetch provider for web_fetch (no key): the web
|
|
115
|
+
# service and its search provider stay on the host plane (dsh-base), and
|
|
116
|
+
# this row is what makes fetching real URLs work out of the box.
|
|
117
|
+
- id: web-fetch-http
|
|
118
|
+
name: '@deepseek-ai/dsh-web-fetch-http'
|
|
119
|
+
|
|
92
120
|
- id: tui-startup
|
|
93
121
|
name: 'dsh-code/startup'
|
|
94
122
|
|