dsh-code 1.0.6 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +123 -26
- package/README.md +124 -27
- package/bin/deepseek.mjs +283 -35
- package/cordis.patch.yml +97 -0
- package/lib/index.mjs +5008 -881
- package/lib/session-query.mjs +150 -0
- package/lib/startup.mjs +4 -4
- package/lib/{theme-DCT8Y2xf.mjs → theme-7u5Qo3dF.mjs} +657 -20
- package/lib/types/app.d.ts +106 -62
- package/lib/types/authorization-panel.d.ts +3 -3
- package/lib/types/git-workflow.d.ts +91 -2
- package/lib/types/i18n.d.ts +39 -0
- package/lib/types/index.d.ts +100 -1
- package/lib/types/input-split.d.ts +1 -1
- package/lib/types/kernel-panels.d.ts +107 -29
- package/lib/types/language-panel.d.ts +12 -0
- package/lib/types/locales/en.d.ts +450 -0
- package/lib/types/locales/zh.d.ts +9 -0
- package/lib/types/mentions.d.ts +7 -3
- package/lib/types/models.d.ts +14 -0
- package/lib/types/panel-accent.d.ts +28 -0
- package/lib/types/rainbow.d.ts +69 -0
- package/lib/types/render/animations.d.ts +42 -0
- package/lib/types/render/editor.d.ts +4 -3
- package/lib/types/render/ime-cursor.d.ts +60 -0
- package/lib/types/render/inspector.d.ts +26 -0
- package/lib/types/render/lines.d.ts +21 -1
- package/lib/types/render/markdown.d.ts +1 -1
- package/lib/types/render/projection.d.ts +130 -4
- package/lib/types/render/status.d.ts +9 -9
- package/lib/types/render/text.d.ts +6 -0
- package/lib/types/render/usage.d.ts +113 -0
- package/lib/types/session-directory.d.ts +17 -0
- package/lib/types/session-query.d.ts +92 -0
- package/lib/types/startup.d.ts +1 -1
- package/lib/types/terminal-title.d.ts +66 -0
- package/lib/types/theme-panel.d.ts +2 -2
- package/lib/types/theme.d.ts +271 -52
- package/lib/types/update-panel.d.ts +49 -0
- package/lib/types/update.d.ts +75 -0
- package/lib/types/version.d.ts +4 -3
- package/package.json +246 -90
- package/src/app.ts +1369 -509
- package/src/approval.ts +166 -166
- package/src/authorization-panel.ts +19 -16
- package/src/editor-keys.ts +371 -371
- package/src/git-workflow.ts +229 -3
- package/src/i18n.ts +68 -0
- package/src/index.ts +534 -80
- package/src/input-split.ts +3 -3
- package/src/internals.ts +5 -0
- package/src/kernel-panels.ts +554 -86
- package/src/keyboard.ts +5 -4
- package/src/language-panel.ts +53 -0
- package/src/locales/en.ts +489 -0
- package/src/locales/zh.ts +488 -0
- package/src/mentions.ts +8 -4
- package/src/models.ts +264 -212
- package/src/panel-accent.ts +41 -0
- package/src/presets.ts +1 -1
- package/src/provider-settings.ts +1 -1
- package/src/rainbow.ts +208 -0
- package/src/render/animations.ts +104 -6
- package/src/render/editor.ts +25 -24
- package/src/render/export.ts +116 -95
- package/src/render/ime-cursor.ts +147 -0
- package/src/render/inspector.ts +42 -0
- package/src/render/lines.ts +628 -415
- package/src/render/markdown.ts +15 -3
- package/src/render/projection.ts +572 -21
- package/src/render/status.ts +59 -39
- package/src/render/text.ts +14 -0
- package/src/render/tool-preview.ts +77 -77
- package/src/render/usage.ts +430 -0
- package/src/render/width.ts +2 -2
- package/src/session-directory.ts +8 -6
- package/src/session-query.ts +239 -0
- package/src/startup.ts +3 -3
- package/src/subagents.ts +229 -229
- package/src/terminal-title.ts +190 -0
- package/src/theme-panel.ts +17 -21
- package/src/theme.ts +281 -33
- package/src/update-panel.ts +256 -0
- package/src/update.ts +126 -0
- package/src/version.ts +58 -20
- package/src/whale-glyph.ts +23 -23
package/bin/deepseek.mjs
CHANGED
|
@@ -8,7 +8,8 @@ import { dirname, join, resolve } from 'node:path'
|
|
|
8
8
|
import { fileURLToPath, pathToFileURL } from 'node:url'
|
|
9
9
|
|
|
10
10
|
const packageRequire = createRequire(import.meta.url)
|
|
11
|
-
|
|
11
|
+
/** This launcher's release version (exported for probes and tests). */
|
|
12
|
+
export const packageVersion = packageRequire('../package.json').version
|
|
12
13
|
|
|
13
14
|
/** Arguments required to boot DSH-Code's conventional profile. */
|
|
14
15
|
export const profileArgs = (args = []) => ['--profile', 'cli', ...args]
|
|
@@ -115,6 +116,97 @@ export function harnessLineFromPeers(peers) {
|
|
|
115
116
|
return undefined
|
|
116
117
|
}
|
|
117
118
|
|
|
119
|
+
/**
|
|
120
|
+
* The exact global install that pairs with this launcher: the harness line
|
|
121
|
+
* its own package declares in peers, and its own release. The guidance a
|
|
122
|
+
* missing host prints must not send the user to an unpinned `dsh-code`,
|
|
123
|
+
* which could mount a newer bundle beside this older wrapper.
|
|
124
|
+
*/
|
|
125
|
+
export function selfInstallHint(options = {}) {
|
|
126
|
+
const version = options.version ?? packageVersion
|
|
127
|
+
// An explicitly passed peers value — including undefined, the "no peers
|
|
128
|
+
// were readable" case — must win over this launcher's own manifest, which
|
|
129
|
+
// a destructuring default would conflate with the argument being absent.
|
|
130
|
+
const peers = 'peers' in options ? options.peers : packageRequire('../package.json').peerDependencies
|
|
131
|
+
const line = harnessLineFromPeers(peers)
|
|
132
|
+
return `npm install -g @deepseek-ai/dsh${line === undefined ? '' : `@${line}`} dsh-code@${version}`
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Refusal line when npm's latest dsh-code is OLDER than this running
|
|
137
|
+
* launcher — a registry rollback, or a launcher installed from a GitHub
|
|
138
|
+
* release that sits ahead of the registry — and applying would downgrade
|
|
139
|
+
* the bundle back over the user's profile. Undefined when the upgrade may
|
|
140
|
+
* proceed.
|
|
141
|
+
*/
|
|
142
|
+
export function bundleDowngradeRefusal(latest, running = packageVersion) {
|
|
143
|
+
return latest !== undefined && compareHarnessLines(latest, running) < 0
|
|
144
|
+
? `dsh-code: npm latest is dsh-code@${latest}, older than this launcher (dsh-code@${running}); refusing to downgrade the bundle`
|
|
145
|
+
: undefined
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Refusal reason when a local-checkout profile would pair an older local
|
|
150
|
+
* build with the newer global host this upgrade installs, or undefined when
|
|
151
|
+
* the upgrade may proceed (no checkout mounted, or the checkout already
|
|
152
|
+
* matches the release). The caller prints the lines verbatim.
|
|
153
|
+
*/
|
|
154
|
+
export function localCheckoutRefusal(mounted, latestCode, codeSpec) {
|
|
155
|
+
if (mounted === latestCode) return undefined
|
|
156
|
+
if (mounted === undefined) {
|
|
157
|
+
return [
|
|
158
|
+
'dsh-code: the cli profile mounts a local checkout, but its version could not be read',
|
|
159
|
+
'dsh-code: refusing to upgrade the global host beside an unread checkout',
|
|
160
|
+
'dsh-code: update the checkout first (git pull, pnpm install, pnpm build), or switch the profile to the published package:',
|
|
161
|
+
`dsh-code: dsh plugin --profile cli remove dsh-code && dsh plugin --profile cli add ${codeSpec}`,
|
|
162
|
+
]
|
|
163
|
+
}
|
|
164
|
+
return [
|
|
165
|
+
`dsh-code: the cli profile mounts a local checkout of dsh-code ${mounted}, while this upgrade would install ${latestCode} globally`,
|
|
166
|
+
'dsh-code: upgrading the host beside an older local checkout pairs incompatible code; refusing to install',
|
|
167
|
+
'dsh-code: update the checkout first (git pull, pnpm install, pnpm build), or switch the profile to the published package:',
|
|
168
|
+
`dsh-code: dsh plugin --profile cli remove dsh-code && dsh plugin --profile cli add ${codeSpec}`,
|
|
169
|
+
]
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** Version after the last @ in an npm spec (`dsh-code@1.0.8`). */
|
|
173
|
+
export function specVersion(spec) {
|
|
174
|
+
if (typeof spec !== 'string') return undefined
|
|
175
|
+
const at = spec.lastIndexOf('@')
|
|
176
|
+
if (at <= 0 || at === spec.length - 1) return undefined
|
|
177
|
+
return spec.slice(at + 1)
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Exact install plan passed to `update --apply` after a probe. Missing
|
|
182
|
+
* `--code` means apply should query npm itself (CLI one-shot).
|
|
183
|
+
*/
|
|
184
|
+
export function parsePinnedPlan(args) {
|
|
185
|
+
let dshSpec
|
|
186
|
+
let codeSpec
|
|
187
|
+
const pluginSpecs = []
|
|
188
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
189
|
+
const flag = args[index]
|
|
190
|
+
const value = args[index + 1]
|
|
191
|
+
if (flag === '--dsh' && value !== undefined) {
|
|
192
|
+
dshSpec = value
|
|
193
|
+
index += 1
|
|
194
|
+
continue
|
|
195
|
+
}
|
|
196
|
+
if (flag === '--code' && value !== undefined) {
|
|
197
|
+
codeSpec = value
|
|
198
|
+
index += 1
|
|
199
|
+
continue
|
|
200
|
+
}
|
|
201
|
+
if (flag === '--plugin' && value !== undefined) {
|
|
202
|
+
pluginSpecs.push(value)
|
|
203
|
+
index += 1
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
if (codeSpec === undefined || dshSpec === undefined) return undefined
|
|
207
|
+
return { dshSpec, codeSpec, pluginSpecs }
|
|
208
|
+
}
|
|
209
|
+
|
|
118
210
|
/**
|
|
119
211
|
* Decide what `update --apply` installs. The global DSH launcher is pinned
|
|
120
212
|
* to the harness line the target dsh-code release declares in its peers,
|
|
@@ -138,6 +230,56 @@ export function updatePlan({ latestCode, peers, profileSpec, profilePlugins = []
|
|
|
138
230
|
}
|
|
139
231
|
}
|
|
140
232
|
|
|
233
|
+
/**
|
|
234
|
+
* The concrete steps `update --apply` runs. The host install and the
|
|
235
|
+
* dsh-code mount are fatal: a failure there strands the global host and the
|
|
236
|
+
* profile bundle on different release lines, so the sequence stops. The
|
|
237
|
+
* companion plugin carries are best-effort — one plugin without a build on
|
|
238
|
+
* the target line must not strand the rest of the upgrade, so each reports
|
|
239
|
+
* its manual retry command and lets the sequence finish. Unresolvable dsh
|
|
240
|
+
* commands come back as blockers: they are enforced before any step runs,
|
|
241
|
+
* because starting the host install without a working profile step is
|
|
242
|
+
* exactly the half-updated state the fatal marking exists to prevent.
|
|
243
|
+
*/
|
|
244
|
+
export function updateSteps({ plan, npm = npmInvocation(), resolveCommand = rawDshCommand }) {
|
|
245
|
+
const steps = [{
|
|
246
|
+
command: npm.command,
|
|
247
|
+
args: [...npm.args, 'install', '-g', plan.dshSpec, plan.codeSpec],
|
|
248
|
+
label: 'npm install',
|
|
249
|
+
fatal: true,
|
|
250
|
+
remedy: `npm install -g ${plan.dshSpec} ${plan.codeSpec}`,
|
|
251
|
+
}]
|
|
252
|
+
if (!plan.profileStep) return { steps, blockers: [] }
|
|
253
|
+
const blockers = []
|
|
254
|
+
const codeCommand = resolveCommand(['plugin', '--profile', 'cli', 'add', plan.codeSpec])
|
|
255
|
+
if (codeCommand === undefined) {
|
|
256
|
+
blockers.push('dsh-code: could not resolve the dsh command for the profile update')
|
|
257
|
+
} else {
|
|
258
|
+
steps.push({
|
|
259
|
+
command: codeCommand.command,
|
|
260
|
+
args: codeCommand.args,
|
|
261
|
+
label: 'dsh plugin add',
|
|
262
|
+
fatal: true,
|
|
263
|
+
remedy: `dsh plugin --profile cli add ${plan.codeSpec}`,
|
|
264
|
+
})
|
|
265
|
+
}
|
|
266
|
+
for (const pluginSpec of plan.pluginSpecs) {
|
|
267
|
+
const pluginCommand = resolveCommand(['plugin', '--profile', 'cli', 'add', pluginSpec])
|
|
268
|
+
if (pluginCommand === undefined) {
|
|
269
|
+
blockers.push(`dsh-code: could not resolve the dsh command for ${pluginSpec}`)
|
|
270
|
+
continue
|
|
271
|
+
}
|
|
272
|
+
steps.push({
|
|
273
|
+
command: pluginCommand.command,
|
|
274
|
+
args: pluginCommand.args,
|
|
275
|
+
label: `dsh plugin add ${pluginSpec}`,
|
|
276
|
+
fatal: false,
|
|
277
|
+
remedy: `dsh plugin --profile cli add ${pluginSpec}`,
|
|
278
|
+
})
|
|
279
|
+
}
|
|
280
|
+
return { steps, blockers }
|
|
281
|
+
}
|
|
282
|
+
|
|
141
283
|
/**
|
|
142
284
|
* Compare two @deepseek-ai/dsh release-line versions (`0.1.x`, `0.1.x-rc.N`,
|
|
143
285
|
* `0.1.x-alpha.N`). Positive when `left` is newer, negative when older, and 0
|
|
@@ -184,23 +326,37 @@ export function installedGlobalDshVersion(roots = globalDshRoots(), fileExists =
|
|
|
184
326
|
return undefined
|
|
185
327
|
}
|
|
186
328
|
|
|
187
|
-
/**
|
|
329
|
+
/**
|
|
330
|
+
* Run wrapper-owned child steps in order. A step marked fatal stops the
|
|
331
|
+
* sequence at its failure (the default: the next step depends on this one);
|
|
332
|
+
* a `fatal: false` step is best-effort — its failure is reported with the
|
|
333
|
+
* step's manual retry command, the sequence continues, and the resolved
|
|
334
|
+
* code stays non-zero so the caller still sees the incomplete pass.
|
|
335
|
+
*/
|
|
188
336
|
export function runSequence(steps, spawnProcess = spawn) {
|
|
189
337
|
return new Promise(resolve => {
|
|
338
|
+
const failures = []
|
|
190
339
|
const run = index => {
|
|
191
340
|
const step = steps[index]
|
|
192
341
|
if (step === undefined) {
|
|
193
|
-
resolve(0)
|
|
342
|
+
resolve(failures.length === 0 ? 0 : failures[failures.length - 1])
|
|
194
343
|
return
|
|
195
344
|
}
|
|
196
345
|
const needsShell = process.platform === 'win32' && /\.(cmd|bat)$/iu.test(step.command)
|
|
197
346
|
const child = spawnProcess(step.command, step.args, { stdio: 'inherit', ...(needsShell ? { shell: true } : {}) })
|
|
347
|
+
const report = code => {
|
|
348
|
+
if (step.remedy !== undefined) console.error(`dsh-code: to retry ${step.label} manually: ${step.remedy}`)
|
|
349
|
+
failures.push(code ?? 1)
|
|
350
|
+
run(index + 1)
|
|
351
|
+
}
|
|
198
352
|
child.once('error', error => {
|
|
199
353
|
console.error(`dsh-code: ${step.label} failed: ${error.message}`)
|
|
200
|
-
|
|
354
|
+
if (step.fatal === false) report(undefined)
|
|
355
|
+
else resolve(1)
|
|
201
356
|
})
|
|
202
|
-
child.once('exit',
|
|
357
|
+
child.once('exit', code => {
|
|
203
358
|
if (code === 0) run(index + 1)
|
|
359
|
+
else if (step.fatal === false) report(code)
|
|
204
360
|
else resolve(code ?? 1)
|
|
205
361
|
})
|
|
206
362
|
}
|
|
@@ -384,6 +540,62 @@ function printUpdateStatus() {
|
|
|
384
540
|
console.log('Run `deepseek update --apply` to upgrade the global packages and the cli profile together.')
|
|
385
541
|
}
|
|
386
542
|
|
|
543
|
+
/**
|
|
544
|
+
* The structured form of the update status for machine consumers
|
|
545
|
+
* (`update --json`, consumed by the TUI /update panel): what is running,
|
|
546
|
+
* what npm serves, the exact steps `update --apply` would run, and every
|
|
547
|
+
* refusal that would stop it. One JSON object on stdout; `null` marks an
|
|
548
|
+
* unreadable value so the payload shape stays constant.
|
|
549
|
+
*/
|
|
550
|
+
export function buildUpdateStatus({
|
|
551
|
+
view = viewJson,
|
|
552
|
+
installedDsh = installedDshVersion,
|
|
553
|
+
readSpec = profileDependencySpec,
|
|
554
|
+
readMounted = profileMountedVersion,
|
|
555
|
+
readPlugins = profilePluginDependencies,
|
|
556
|
+
} = {}) {
|
|
557
|
+
const codeLatest = view(['dsh-code', 'version'])
|
|
558
|
+
const installed = installedDsh()
|
|
559
|
+
const spec = readSpec()
|
|
560
|
+
const mounted = readMounted()
|
|
561
|
+
const peers = codeLatest === undefined ? undefined : view([`dsh-code@${codeLatest}`, 'peerDependencies'])
|
|
562
|
+
const plan = updatePlan({
|
|
563
|
+
latestCode: codeLatest ?? 'unknown',
|
|
564
|
+
peers,
|
|
565
|
+
profileSpec: spec,
|
|
566
|
+
profilePlugins: readPlugins(),
|
|
567
|
+
})
|
|
568
|
+
const registry = codeLatest === undefined ? 'could not read the latest dsh-code version from npm' : undefined
|
|
569
|
+
// The same refusals applyUpdate enforces, precomputed so a caller can
|
|
570
|
+
// show them BEFORE any confirmation instead of failing mid-flight.
|
|
571
|
+
const downgrade = plan.line !== undefined && installed !== undefined && compareHarnessLines(plan.line, installed) < 0
|
|
572
|
+
const localCheckout = plan.profileStep ? undefined : localCheckoutRefusal(mounted, codeLatest, plan.codeSpec)
|
|
573
|
+
const hostOnLine = installed !== undefined && (plan.line === undefined || compareHarnessLines(installed, plan.line) === 0)
|
|
574
|
+
// A launcher ahead of the registry (a GitHub-release install) has nothing
|
|
575
|
+
// npm can offer: the registry's older latest must not present as a pending
|
|
576
|
+
// update, and applyUpdate refuses it anyway.
|
|
577
|
+
const bundleAhead = codeLatest !== undefined && compareHarnessLines(codeLatest, packageVersion) < 0
|
|
578
|
+
const upToDate = bundleAhead || (registry === undefined
|
|
579
|
+
&& codeLatest === packageVersion
|
|
580
|
+
&& !downgrade
|
|
581
|
+
&& localCheckout === undefined
|
|
582
|
+
&& hostOnLine
|
|
583
|
+
&& plan.pluginSpecs.length === 0
|
|
584
|
+
&& (mounted === undefined || mounted === codeLatest))
|
|
585
|
+
return {
|
|
586
|
+
code: { running: packageVersion, latest: codeLatest ?? null },
|
|
587
|
+
host: { installed: installed ?? null, targetLine: plan.line ?? null },
|
|
588
|
+
profile: { spec: spec ?? null, mounted: mounted ?? null, localCheckout: !plan.profileStep },
|
|
589
|
+
plan: { dshSpec: plan.dshSpec, codeSpec: plan.codeSpec, pluginSpecs: plan.pluginSpecs },
|
|
590
|
+
// JSON.stringify drops undefined members; every unreadable value must
|
|
591
|
+
// serialize as an explicit null so machine consumers never see a missing
|
|
592
|
+
// key drift into a truthy comparison.
|
|
593
|
+
blockers: { registry: registry ?? null, downgrade, localCheckout: localCheckout ?? null },
|
|
594
|
+
upToDate,
|
|
595
|
+
aheadOfRegistry: bundleAhead,
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
|
|
387
599
|
/**
|
|
388
600
|
* Upgrade the global launcher and the cli profile plugin together. The
|
|
389
601
|
* global install is pinned to the harness line the new dsh-code release
|
|
@@ -394,21 +606,53 @@ async function applyUpdate({
|
|
|
394
606
|
view = viewJson,
|
|
395
607
|
resolveCommand = rawDshCommand,
|
|
396
608
|
spawnProcess = spawn,
|
|
609
|
+
pinned,
|
|
397
610
|
} = {}) {
|
|
398
611
|
const npm = npmInvocation()
|
|
399
|
-
const
|
|
400
|
-
|
|
401
|
-
|
|
612
|
+
const profileSpec = profileDependencySpec()
|
|
613
|
+
const profilePlugins = profilePluginDependencies()
|
|
614
|
+
let latestCode
|
|
615
|
+
let plan
|
|
616
|
+
if (pinned !== undefined) {
|
|
617
|
+
latestCode = specVersion(pinned.codeSpec)
|
|
618
|
+
if (latestCode === undefined) {
|
|
619
|
+
console.error(`dsh-code: could not read a version from ${pinned.codeSpec}`)
|
|
620
|
+
process.exitCode = 1
|
|
621
|
+
return
|
|
622
|
+
}
|
|
623
|
+
const line = specVersion(pinned.dshSpec)
|
|
624
|
+
plan = {
|
|
625
|
+
dshSpec: pinned.dshSpec,
|
|
626
|
+
line,
|
|
627
|
+
lineLocked: line !== undefined,
|
|
628
|
+
codeSpec: pinned.codeSpec,
|
|
629
|
+
profileStep: !(typeof profileSpec === 'string' && /^(link|file):/iu.test(profileSpec)),
|
|
630
|
+
pluginSpecs: pinned.pluginSpecs,
|
|
631
|
+
}
|
|
632
|
+
} else {
|
|
633
|
+
latestCode = view(['dsh-code', 'version'], undefined, npm)
|
|
634
|
+
if (latestCode === undefined) {
|
|
635
|
+
console.error('dsh-code: could not read the latest dsh-code version from npm')
|
|
636
|
+
process.exitCode = 1
|
|
637
|
+
return
|
|
638
|
+
}
|
|
639
|
+
const peers = view([`dsh-code@${latestCode}`, 'peerDependencies'], undefined, npm)
|
|
640
|
+
plan = updatePlan({
|
|
641
|
+
latestCode,
|
|
642
|
+
peers,
|
|
643
|
+
profileSpec,
|
|
644
|
+
profilePlugins,
|
|
645
|
+
})
|
|
646
|
+
}
|
|
647
|
+
// A launcher installed from a GitHub release (or any source ahead of the
|
|
648
|
+
// registry) must not be walked back by an apply targeting npm's older
|
|
649
|
+
// latest - the downgrade guard below only covers the host line.
|
|
650
|
+
const bundleRefusal = bundleDowngradeRefusal(latestCode)
|
|
651
|
+
if (bundleRefusal !== undefined) {
|
|
652
|
+
console.error(bundleRefusal)
|
|
402
653
|
process.exitCode = 1
|
|
403
654
|
return
|
|
404
655
|
}
|
|
405
|
-
const peers = view([`dsh-code@${latestCode}`, 'peerDependencies'], undefined, npm)
|
|
406
|
-
const plan = updatePlan({
|
|
407
|
-
latestCode,
|
|
408
|
-
peers,
|
|
409
|
-
profileSpec: profileDependencySpec(),
|
|
410
|
-
profilePlugins: profilePluginDependencies(),
|
|
411
|
-
})
|
|
412
656
|
if (!plan.lineLocked) {
|
|
413
657
|
console.log('dsh-code: could not read the compatible harness line; installing @deepseek-ai/dsh@latest')
|
|
414
658
|
}
|
|
@@ -424,26 +668,26 @@ async function applyUpdate({
|
|
|
424
668
|
process.exitCode = 1
|
|
425
669
|
return
|
|
426
670
|
}
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
671
|
+
// Local-checkout guard: a link/file-mounted profile runs the checkout's
|
|
672
|
+
// own build, and this command would upgrade the global host beside it.
|
|
673
|
+
// When the checkout is older than the release being installed, upgrading
|
|
674
|
+
// pairs a new host with old local code — the terminal breaks on the next
|
|
675
|
+
// launch. Refuse until the checkout is updated or unmounted.
|
|
676
|
+
if (!plan.profileStep) {
|
|
677
|
+
const refusal = localCheckoutRefusal(profileMountedVersion(), latestCode, plan.codeSpec)
|
|
678
|
+
if (refusal !== undefined) {
|
|
679
|
+
for (const line of refusal) console.error(line)
|
|
432
680
|
process.exitCode = 1
|
|
433
681
|
return
|
|
434
682
|
}
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
for (const
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
return
|
|
444
|
-
}
|
|
445
|
-
steps.push({ command: pluginCommand.command, args: pluginCommand.args, label: `dsh plugin add ${pluginSpec}` })
|
|
446
|
-
}
|
|
683
|
+
}
|
|
684
|
+
const { steps, blockers } = updateSteps({ plan, npm, resolveCommand })
|
|
685
|
+
if (blockers.length > 0) {
|
|
686
|
+
for (const line of blockers) console.error(line)
|
|
687
|
+
process.exitCode = 1
|
|
688
|
+
return
|
|
689
|
+
}
|
|
690
|
+
if (plan.profileStep) {
|
|
447
691
|
if (plan.pluginSpecs.length > 0) {
|
|
448
692
|
console.log(`carrying ${plan.pluginSpecs.length} profile plugin${plan.pluginSpecs.length === 1 ? '' : 's'} to the same line: ${plan.pluginSpecs.join(', ')}`)
|
|
449
693
|
}
|
|
@@ -483,15 +727,19 @@ export function launchOperation(args = process.argv.slice(2)) {
|
|
|
483
727
|
// Setup must mount the exact globally installed release on launch day.
|
|
484
728
|
const command = rawDshCommand(['plugin', '--profile', 'cli', 'add', setupBundle(args)])
|
|
485
729
|
if (command === undefined) {
|
|
486
|
-
console.error(
|
|
730
|
+
console.error(`dsh-code: @deepseek-ai/dsh is not installed; run: ${selfInstallHint()}`)
|
|
487
731
|
process.exitCode = 1
|
|
488
732
|
return true
|
|
489
733
|
}
|
|
490
734
|
return launchChild(command.command, command.args)
|
|
491
735
|
}
|
|
492
736
|
if (operation === 'update') {
|
|
737
|
+
if (args.includes('--json')) {
|
|
738
|
+
console.log(JSON.stringify(buildUpdateStatus()))
|
|
739
|
+
return true
|
|
740
|
+
}
|
|
493
741
|
if (args.includes('--apply')) {
|
|
494
|
-
void applyUpdate()
|
|
742
|
+
void applyUpdate({ pinned: parsePinnedPlan(args) })
|
|
495
743
|
return true
|
|
496
744
|
}
|
|
497
745
|
printUpdateStatus()
|
|
@@ -522,7 +770,7 @@ export function launchDsh(
|
|
|
522
770
|
}
|
|
523
771
|
const command = resolveCommand(args)
|
|
524
772
|
if (command === undefined) {
|
|
525
|
-
console.error(
|
|
773
|
+
console.error(`dsh-code: @deepseek-ai/dsh must be installed globally beside dsh-code; run: ${selfInstallHint()}`)
|
|
526
774
|
process.exitCode = 1
|
|
527
775
|
return undefined
|
|
528
776
|
}
|
package/cordis.patch.yml
CHANGED
|
@@ -24,6 +24,17 @@
|
|
|
24
24
|
config:
|
|
25
25
|
mode: !!js process.env.DSH_TOOLS_MODE
|
|
26
26
|
|
|
27
|
+
# The base row keeps full-text search off entirely (openAt: never) so nothing
|
|
28
|
+
# imports node:sqlite at boot; the terminal replaces it with the bundle's
|
|
29
|
+
# skip-tolerant subclass below. An override row cannot retarget a row's
|
|
30
|
+
# MODULE (name is only honored on inserts), so the base row is disabled and
|
|
31
|
+
# an equivalent row mounts the subclass: the derived index opens lazily on
|
|
32
|
+
# the first search (no startup cost, no Node 22 experimental warning), and
|
|
33
|
+
# one unreadable source (a pre-release artifact the frozen codecs reject)
|
|
34
|
+
# is skipped with a warning instead of failing every cross-session search.
|
|
35
|
+
- id: session-query-sqlite
|
|
36
|
+
disabled: true
|
|
37
|
+
|
|
27
38
|
# Agent-plane rows are mounted by the selected preset. Keep this list aligned
|
|
28
39
|
# with the upstream Web bundle so two sessions can use different compositions
|
|
29
40
|
# without leaking model-facing registrations through the host layer.
|
|
@@ -132,6 +143,92 @@
|
|
|
132
143
|
- id: authorization
|
|
133
144
|
name: '@deepseek-ai/dsh-authorization'
|
|
134
145
|
|
|
146
|
+
# The bundle's skip-tolerant session-query engine replacing the disabled
|
|
147
|
+
# base row above: same SQLite FTS5 service, observation loop patched to
|
|
148
|
+
# skip unreadable sources instead of failing every search.
|
|
149
|
+
- id: session-query-skip
|
|
150
|
+
name: 'dsh-code/session-query'
|
|
151
|
+
config:
|
|
152
|
+
path: ':memory:'
|
|
153
|
+
openAt: first-search
|
|
154
|
+
|
|
155
|
+
# Model-facing session-log search/trace/read tools over the sessionQuery
|
|
156
|
+
# service (read-only, workspace-scoped by exact cwd). A host-plane mount
|
|
157
|
+
# is deployment-global: every preset session sees the five tools. Kept
|
|
158
|
+
# ENABLED deliberately — read-only search leaks no capability — but note
|
|
159
|
+
# it does reach minimal-preset sessions too. The host CLI does not bundle
|
|
160
|
+
# this package, so it ships as a real dependency and resolves from the
|
|
161
|
+
# profile's own node_modules.
|
|
162
|
+
- id: tool-session-query
|
|
163
|
+
name: '@deepseek-ai/dsh-tool-session-query'
|
|
164
|
+
|
|
165
|
+
# Durable reminders: the schedule service arms per-root timers, injects
|
|
166
|
+
# due prompts as plugin-source user messages, and writes schedule/change
|
|
167
|
+
# events the projection folds into the /schedule panel. time-context
|
|
168
|
+
# gives the model a clock reading so 'at' times are phrased against the
|
|
169
|
+
# actual time; the 30s throttle bounds durable snapshot growth.
|
|
170
|
+
- id: schedule
|
|
171
|
+
name: '@deepseek-ai/dsh-schedule'
|
|
172
|
+
|
|
173
|
+
- id: time-context
|
|
174
|
+
name: '@deepseek-ai/dsh-time-context'
|
|
175
|
+
config:
|
|
176
|
+
refreshIntervalMs: 30000
|
|
177
|
+
|
|
178
|
+
# Persistent PTY plumbing: the owner-scoped registry and the one backend
|
|
179
|
+
# package in both dialects (pwsh is the Windows/ConPTY path, bash covers
|
|
180
|
+
# POSIX) mount as host SERVICES — no model-facing surface, so they break
|
|
181
|
+
# no preset boundary. The six terminal_* TOOLS ship DISABLED like LSP:
|
|
182
|
+
# enabling them at the host plane would hand every preset (including the
|
|
183
|
+
# shell-restricted minimal one) raw shell capability, the exact leak the
|
|
184
|
+
# disables above exist to prevent. Flip tool-terminal to disabled: false
|
|
185
|
+
# in the PROFILE layer to opt the deployment into PTY tools — but install
|
|
186
|
+
# @deepseek-ai/dsh-tool-terminal into the profile first (the host CLI does
|
|
187
|
+
# not bundle it; an enabled row over a missing package fails the boot):
|
|
188
|
+
# dsh plugin --profile cli add @deepseek-ai/dsh-tool-terminal
|
|
189
|
+
- id: pty
|
|
190
|
+
name: '@deepseek-ai/dsh-terminal'
|
|
191
|
+
|
|
192
|
+
- id: terminal-pwsh
|
|
193
|
+
name: '@deepseek-ai/dsh-terminal-bash'
|
|
194
|
+
disabled: !!js process.platform !== 'win32'
|
|
195
|
+
config:
|
|
196
|
+
shellDialect: pwsh
|
|
197
|
+
|
|
198
|
+
- id: terminal-bash
|
|
199
|
+
name: '@deepseek-ai/dsh-terminal-bash'
|
|
200
|
+
disabled: !!js process.platform === 'win32'
|
|
201
|
+
|
|
202
|
+
- id: tool-terminal
|
|
203
|
+
name: '@deepseek-ai/dsh-tool-terminal'
|
|
204
|
+
disabled: true
|
|
205
|
+
|
|
206
|
+
# LSP navigation ships DISABLED: lsp-stdio resolves every server command
|
|
207
|
+
# at mount and a missing binary would fail the whole composition boot.
|
|
208
|
+
# Enable in the PROFILE layer with real servers, e.g.:
|
|
209
|
+
# lsp / lsp-stdio / tool-lsp rows with disabled: false and
|
|
210
|
+
# lsp-stdio config.servers mapping extensions to server commands.
|
|
211
|
+
# The three packages are also not bundled by the host CLI: install them
|
|
212
|
+
# into the profile first or the enabled rows fail the boot.
|
|
213
|
+
- id: lsp
|
|
214
|
+
name: '@deepseek-ai/dsh-lsp'
|
|
215
|
+
disabled: true
|
|
216
|
+
|
|
217
|
+
- id: lsp-stdio
|
|
218
|
+
name: '@deepseek-ai/dsh-lsp-stdio'
|
|
219
|
+
disabled: true
|
|
220
|
+
|
|
221
|
+
- id: tool-lsp
|
|
222
|
+
name: '@deepseek-ai/dsh-tool-lsp'
|
|
223
|
+
disabled: true
|
|
224
|
+
|
|
225
|
+
# MCP servers (dsh-mcp-client) and hooks bridges (dsh-hooks-claude-code /
|
|
226
|
+
# -codex) take per-instance config (server transports, hooks.json paths),
|
|
227
|
+
# so they mount as rows in the USER profile layer, not here; the host CLI
|
|
228
|
+
# bundles these peers, so those rows resolve. README documents the row
|
|
229
|
+
# shapes, and rows over packages the host does not bundle need the package
|
|
230
|
+
# added to the profile first.
|
|
231
|
+
|
|
135
232
|
- id: tui-startup
|
|
136
233
|
name: 'dsh-code/startup'
|
|
137
234
|
|