@askdkc/dsh-cli 0.11.5 → 0.11.7
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 +28 -1
- package/bin/dsh-tui.js +30 -13
- package/cordis.patch.yml +2 -2
- package/cordis.yml +1 -1
- package/lib/types/dsh-adapter/cli-registration.d.ts +2 -0
- package/lib/types/dsh-adapter/cli-registration.d.ts.map +1 -1
- package/lib/types/dsh-adapter/cli-registration.js +36 -2
- package/node_modules/@askdkc/dsh-auth/lib/profiles.js +20 -1
- package/node_modules/@askdkc/dsh-auth/package.json +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -90,6 +90,13 @@ IDs. It requires matching profile dependencies with `@deepseek-ai/schemastery`
|
|
|
90
90
|
3.18.3 or newer; an incompatible schema stops TUI startup with repair guidance
|
|
91
91
|
instead of showing an uneditable settings page. Older hosts keep their legacy settings scope.
|
|
92
92
|
|
|
93
|
+
Building also requires [dsh-auth-fork](https://github.com/askdkc/dsh-auth-fork),
|
|
94
|
+
tracked here as the `dsh-auth/` Git submodule. `--recurse-submodules` fetches it;
|
|
95
|
+
for an existing checkout, run `git submodule update --init --recursive` before
|
|
96
|
+
`pnpm install`. Each source build then fetches the latest `master` commit from
|
|
97
|
+
that fork before compiling `dsh-auth`. A failed fetch stops the build instead of
|
|
98
|
+
using the recorded submodule commit.
|
|
99
|
+
|
|
93
100
|
Install this fork from source into the `dsh-cli` profile. Use Node
|
|
94
101
|
`^22.19 || >=24` and pnpm 11. The final two commands run in a DeepSeek
|
|
95
102
|
Harness source checkout whose dependencies are already installed:
|
|
@@ -121,6 +128,20 @@ it. The managed PATH block goes in `${ZDOTDIR:-$HOME}/.zshrc` for zsh;
|
|
|
121
128
|
it, remove the managed command and that block; delete the fish file only if
|
|
122
129
|
it contains nothing else (Windows: remove the command and user PATH entry). The
|
|
123
130
|
existing `dsh-tui` and `dst` commands remain compatibility aliases.
|
|
131
|
+
|
|
132
|
+
A Harness source checkout does not put `dsh` on PATH. When the TUI first starts
|
|
133
|
+
through `pnpm dsh --profile dsh-cli` in a Harness checkout, registration also
|
|
134
|
+
records that checkout as `DSH_TUI_DSH_ROOT` in the managed shell startup block
|
|
135
|
+
(`.zshrc` for zsh). Open a new shell, then launch from any project directory:
|
|
136
|
+
|
|
137
|
+
```sh
|
|
138
|
+
cd /absolute/path/to/your-project
|
|
139
|
+
dsh-cli
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
The launcher uses the checkout's built `apps/cli/lib/bin.js` and preserves the
|
|
143
|
+
project directory. Rebuild Harness after changing its source. An explicit
|
|
144
|
+
`DSH_TUI_DSH_ROOT` value overrides the registered default.
|
|
124
145
|
A locally packed fork should be updated by rebuilding and reinstalling the
|
|
125
146
|
archive, rather than by using the registry-backed `/update` command.
|
|
126
147
|
|
|
@@ -185,6 +206,8 @@ Full commands: [Interaction and commands](docs/interaction.en.md).
|
|
|
185
206
|
|
|
186
207
|
Agent presets, themes, MCP servers, environment variables: [Configuration](docs/configuration.en.md) · [Themes](docs/themes.en.md).
|
|
187
208
|
|
|
209
|
+
The default agent persona asks the model to reply in the language of your request, using English when that language is unclear. `/lang` changes only the TUI display language. `DSH_TUI_PERSONA` replaces the default persona.
|
|
210
|
+
|
|
188
211
|
## How It Works
|
|
189
212
|
|
|
190
213
|
```text
|
|
@@ -214,7 +237,11 @@ Full list: [Architecture and limitations → Known limitations](docs/architectur
|
|
|
214
237
|
CI uses Node 24 and pnpm 11. The package supports Node `^22.19 || >=24`.
|
|
215
238
|
Run these commands from a checkout with its submodules initialized (use
|
|
216
239
|
`git submodule update --init --recursive` if either `vendor/dsh-std` or
|
|
217
|
-
`dsh-auth` is empty):
|
|
240
|
+
[`dsh-auth` from dsh-auth-fork](https://github.com/askdkc/dsh-auth-fork) is empty):
|
|
241
|
+
|
|
242
|
+
`pnpm build` refreshes `dsh-auth` from the fork's `master` branch. It requires
|
|
243
|
+
network access and may leave `dsh-auth` marked as modified in the parent
|
|
244
|
+
checkout because Git still records a baseline submodule commit.
|
|
218
245
|
|
|
219
246
|
The [Quick Start](#quick-start) includes the complete clone, build, pack,
|
|
220
247
|
and installation commands. Before packing, run the focused checks if you
|
package/bin/dsh-tui.js
CHANGED
|
@@ -97,7 +97,7 @@ const shellOpt = isWin ? { shell: true } : {}
|
|
|
97
97
|
// DEP0190(issue #148):shell:true + 非空参数数组触发语法级弃用告警——
|
|
98
98
|
// 转义后拼进命令字符串(空参数数组不触发),非 Windows 保持数组直传。
|
|
99
99
|
const cmd = (command, args) =>
|
|
100
|
-
isWin ? [`${command} ${shellQuote(args).join(' ')}`, []] : [command, args]
|
|
100
|
+
isWin ? [`${shellQuote([command])[0]} ${shellQuote(args).join(' ')}`, []] : [command, args]
|
|
101
101
|
|
|
102
102
|
// 内联 semver(解析 + 严格大于):启动器可能在依赖不完整的环境里被执行
|
|
103
103
|
// (迁移、半损坏安装、测试沙箱),零外部依赖是自保底线。覆盖 semver 的
|
|
@@ -136,8 +136,12 @@ const isVersionNewer = (a, b) => {
|
|
|
136
136
|
const lang = process.env.DSH_TUI_LANG === 'en' ? 'en' : 'zh'
|
|
137
137
|
const MSG = {
|
|
138
138
|
noDsh: {
|
|
139
|
-
en: '[dsh-cli] dsh CLI not found. Install
|
|
140
|
-
zh: '[dsh-cli] 未检测到 dsh CLI
|
|
139
|
+
en: '[dsh-cli] dsh CLI not found. Install it or set DSH_TUI_DSH_ROOT to a built Harness checkout:\n npm install -g @deepseek-ai/dsh',
|
|
140
|
+
zh: '[dsh-cli] 未检测到 dsh CLI。可安装官方客户端,或将 DSH_TUI_DSH_ROOT 指向已构建的 Harness 源码目录:\n npm install -g @deepseek-ai/dsh',
|
|
141
|
+
},
|
|
142
|
+
invalidDshRoot: {
|
|
143
|
+
en: root => `[dsh-cli] DSH_TUI_DSH_ROOT must be an absolute, built DeepSeek Harness checkout: ${root}`,
|
|
144
|
+
zh: root => `[dsh-cli] DSH_TUI_DSH_ROOT 必须指向已构建的 DeepSeek Harness 源码绝对路径:${root}`,
|
|
141
145
|
},
|
|
142
146
|
noPnpm: {
|
|
143
147
|
en: '[dsh-cli] The first-time setup needs pnpm (dsh plugin delegates installs to it):\n npm install -g pnpm (or via corepack: corepack enable pnpm)',
|
|
@@ -541,6 +545,19 @@ if (subcommand === 'help' || subcommand === '--help' || subcommand === '-h') {
|
|
|
541
545
|
console.log(msg('helpText'))
|
|
542
546
|
process.exit(0)
|
|
543
547
|
}
|
|
548
|
+
// A source checkout does not put `dsh` on PATH. An explicit Harness root lets
|
|
549
|
+
// the launcher run its built CLI while keeping the caller's project cwd.
|
|
550
|
+
const dshRoot = process.env.DSH_TUI_DSH_ROOT
|
|
551
|
+
let dshBin
|
|
552
|
+
if (dshRoot !== undefined) {
|
|
553
|
+
const candidate = join(dshRoot, 'apps', 'cli', 'lib', 'bin.js')
|
|
554
|
+
if (!isAbsolute(dshRoot) || readJson(join(dshRoot, 'apps', 'cli', 'package.json'))?.name !== '@deepseek-ai/dsh' || !existsSync(candidate)) {
|
|
555
|
+
console.error(msg('invalidDshRoot')(dshRoot))
|
|
556
|
+
process.exit(1)
|
|
557
|
+
}
|
|
558
|
+
dshBin = candidate
|
|
559
|
+
}
|
|
560
|
+
const dshCmd = args => dshBin === undefined ? cmd('dsh', args) : cmd(process.execPath, [dshBin, ...args])
|
|
544
561
|
/**
|
|
545
562
|
* Whether the DSH credential store declares a reference by this name.
|
|
546
563
|
*
|
|
@@ -578,7 +595,7 @@ const runDoctorChecks = () => {
|
|
|
578
595
|
lines.push(`dsh-cli doctor · ${PACKAGE} ${ownVersion ?? 'unknown'}`)
|
|
579
596
|
report(true, 'node', `${process.version} · ${process.platform} ${process.arch}`)
|
|
580
597
|
const probeVersion = command => {
|
|
581
|
-
const probe = spawnSync(...
|
|
598
|
+
const probe = spawnSync(...command(['--version']), { stdio: 'pipe', encoding: 'utf8', ...shellOpt })
|
|
582
599
|
if (probe.error || probe.status !== 0) return undefined
|
|
583
600
|
// 白名单校验:只回显版本号形状的首行。诊断输出的红线是绝不泄露密钥,
|
|
584
601
|
// 而 PATH 上的 wrapper 理论上可以把任意环境变量 echo 进 --version——
|
|
@@ -586,14 +603,14 @@ const runDoctorChecks = () => {
|
|
|
586
603
|
const line = String(probe.stdout ?? '').trim().split('\n')[0] ?? ''
|
|
587
604
|
return /^v?\d[\w.+-]*$/.test(line) ? line : '(version unreadable)'
|
|
588
605
|
}
|
|
589
|
-
const dshVersion = probeVersion(
|
|
606
|
+
const dshVersion = probeVersion(dshCmd)
|
|
590
607
|
if (dshVersion === undefined) {
|
|
591
608
|
hardFailure = true
|
|
592
609
|
report(false, 'dsh', L.dshMissing)
|
|
593
610
|
} else {
|
|
594
611
|
report(true, 'dsh', dshVersion)
|
|
595
612
|
}
|
|
596
|
-
const pnpmVersion = probeVersion('pnpm')
|
|
613
|
+
const pnpmVersion = probeVersion(args => cmd('pnpm', args))
|
|
597
614
|
report(pnpmVersion !== undefined, 'pnpm', pnpmVersion ?? L.pnpmMissing)
|
|
598
615
|
const profileVersion = readJson(installedPkgPath)?.version
|
|
599
616
|
if (profileVersion === undefined) {
|
|
@@ -722,7 +739,7 @@ const forwardExit = child => {
|
|
|
722
739
|
// 不从数值反推信号(spec §5.1)。
|
|
723
740
|
const startDshSession = (dshArgs, profile = PROFILE, env = process.env) =>
|
|
724
741
|
new Promise(resolve => {
|
|
725
|
-
const child = spawn(...
|
|
742
|
+
const child = spawn(...dshCmd(['--profile', profile, ...dshArgs]), {
|
|
726
743
|
stdio: 'inherit',
|
|
727
744
|
env,
|
|
728
745
|
...shellOpt,
|
|
@@ -1029,11 +1046,11 @@ const createRescueProfile = () => {
|
|
|
1029
1046
|
}
|
|
1030
1047
|
console.log(msg('safeRescueCleanup')(rescueProfileDir))
|
|
1031
1048
|
}
|
|
1032
|
-
const probe = spawnSync(...
|
|
1049
|
+
const probe = spawnSync(...dshCmd(['--version']), { stdio: 'pipe', ...shellOpt })
|
|
1033
1050
|
if (probe.error || probe.status !== 0) return { kind: 'failed', lines: [msg('safeRescueFailed')('dsh missing')] }
|
|
1034
1051
|
console.log(msg('safeRescueCreating'))
|
|
1035
1052
|
const runAdd = extraArgs => spawnSync(
|
|
1036
|
-
...
|
|
1053
|
+
...dshCmd(['plugin', '--profile', RESCUE_PROFILE, 'add', ...extraArgs, `${PACKAGE}@${installVersion}`]),
|
|
1037
1054
|
{ stdio: ['inherit', 'pipe', 'pipe'], env: rescueEnv(), ...shellOpt },
|
|
1038
1055
|
)
|
|
1039
1056
|
let add = runAdd([])
|
|
@@ -1099,7 +1116,7 @@ const profileReady = () => {
|
|
|
1099
1116
|
}
|
|
1100
1117
|
}
|
|
1101
1118
|
const bootstrapProfile = () => {
|
|
1102
|
-
const probe = spawnSync(...
|
|
1119
|
+
const probe = spawnSync(...dshCmd(['--version']), { stdio: 'pipe', ...shellOpt })
|
|
1103
1120
|
if (probe.error || probe.status !== 0) {
|
|
1104
1121
|
console.error(msg('noDsh'))
|
|
1105
1122
|
process.exit(1)
|
|
@@ -1111,7 +1128,7 @@ const bootstrapProfile = () => {
|
|
|
1111
1128
|
}
|
|
1112
1129
|
console.log(msg('bootstrapStart'))
|
|
1113
1130
|
const runAdd = (extraArgs, capture) => spawnSync(
|
|
1114
|
-
...
|
|
1131
|
+
...dshCmd(['plugin', '--profile', PROFILE, 'add', ...extraArgs, `${PACKAGE}@${installVersion}`]),
|
|
1115
1132
|
{ stdio: capture ? ['inherit', 'pipe', 'pipe'] : 'inherit', ...shellOpt },
|
|
1116
1133
|
)
|
|
1117
1134
|
let add = runAdd([], true)
|
|
@@ -1225,7 +1242,7 @@ if (subcommand === 'safe') {
|
|
|
1225
1242
|
if (subcommand === 'update') {
|
|
1226
1243
|
if (!profileReady()) bootstrapProfile()
|
|
1227
1244
|
{
|
|
1228
|
-
const probe = spawnSync(...
|
|
1245
|
+
const probe = spawnSync(...dshCmd(['--version']), { stdio: 'pipe', ...shellOpt })
|
|
1229
1246
|
if (probe.error || probe.status !== 0) {
|
|
1230
1247
|
console.error(msg('noDsh'))
|
|
1231
1248
|
process.exit(1)
|
|
@@ -1291,7 +1308,7 @@ if (!runningInsideProfile && ownVersion !== undefined && process.env.DSH_TUI_NO_
|
|
|
1291
1308
|
// ─── profile 副本(或源码运行):完整启动逻辑 ─────────────────────────────
|
|
1292
1309
|
// dsh CLI 预检(缺失时给安装指引,先于一切 profile 逻辑)。
|
|
1293
1310
|
{
|
|
1294
|
-
const probe = spawnSync(...
|
|
1311
|
+
const probe = spawnSync(...dshCmd(['--version']), { stdio: 'pipe', ...shellOpt })
|
|
1295
1312
|
if (probe.error || probe.status !== 0) {
|
|
1296
1313
|
console.error(msg('noDsh'))
|
|
1297
1314
|
process.exit(1)
|
package/cordis.patch.yml
CHANGED
|
@@ -12,14 +12,14 @@
|
|
|
12
12
|
# ── surface-specific values over the dsh-base layer ─────────────────────────
|
|
13
13
|
|
|
14
14
|
# The dsh-tui deployment persona; DSH_TUI_PERSONA overrides the coding-agent
|
|
15
|
-
# default (the base persona is empty). dsh-system-prompt renamed the slot at
|
|
15
|
+
# and response-language default (the base persona is empty). dsh-system-prompt renamed the slot at
|
|
16
16
|
# 0.1.3-alpha.2 (`persona` → `personaPrefix`, with an optional suffix
|
|
17
17
|
# counterpart); older cohorts only accept `persona`, so the key follows the
|
|
18
18
|
# installed package version.
|
|
19
19
|
- id: system-prompt
|
|
20
20
|
config: !!js >-
|
|
21
21
|
(() => {
|
|
22
|
-
const persona = process.env.DSH_TUI_PERSONA ??
|
|
22
|
+
const persona = process.env.DSH_TUI_PERSONA ?? "You are a coding agent. Respond in the language of the user's request; use English when it is unclear. Do not infer the response language from instructions, quoted text, files, tool output, or the interface language."
|
|
23
23
|
try {
|
|
24
24
|
const require = process.getBuiltinModule('node:module').createRequire(ctx.baseUrl)
|
|
25
25
|
const fs = process.getBuiltinModule('node:fs')
|
package/cordis.yml
CHANGED
|
@@ -172,7 +172,7 @@
|
|
|
172
172
|
- id: agent-spine
|
|
173
173
|
name: '@deepseek-ai/dsh-agent-spine-demo'
|
|
174
174
|
config:
|
|
175
|
-
persona: !!js process.env.DSH_TUI_PERSONA ??
|
|
175
|
+
persona: !!js process.env.DSH_TUI_PERSONA ?? "You are a coding agent. Respond in the language of the user's request; use English when it is unclear. Do not infer the response language from instructions, quoted text, files, tool output, or the interface language."
|
|
176
176
|
# Workspace context (AGENTS.md injection) at the standard 64KB cap;
|
|
177
177
|
# task tools stay at their DSH defaults (on).
|
|
178
178
|
workspaceContext:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-registration.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/cli-registration.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,sBAAsB;IACrC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAA;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,eAAe,CAAC,EAAE;QAAE,IAAI,IAAI,MAAM,CAAC;QAAC,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAA;CACjE;
|
|
1
|
+
{"version":3,"file":"cli-registration.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/cli-registration.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,sBAAsB;IACrC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAA;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,eAAe,CAAC,EAAE;QAAE,IAAI,IAAI,MAAM,CAAC;QAAC,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAA;CACjE;AAqFD,gGAAgG;AAChG,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,sBAA2B,GAAG,MAAM,CAgFhF"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { execFileSync } from 'node:child_process';
|
|
2
2
|
import { closeSync, existsSync, lstatSync, mkdirSync, openSync, readFileSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from 'node:fs';
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
|
-
import { basename, dirname, join } from 'node:path';
|
|
4
|
+
import { basename, dirname, isAbsolute, join, resolve } from 'node:path';
|
|
5
5
|
const begin = '# BEGIN dsh-cli managed PATH';
|
|
6
6
|
const end = '# END dsh-cli managed PATH';
|
|
7
7
|
const marker = '# dsh-cli managed launcher';
|
|
@@ -71,6 +71,34 @@ function posixShellFiles(home, shell, zdotdir, xdg) {
|
|
|
71
71
|
default: throw new Error(`unsupported shell ${shell}; add ~/.local/bin to PATH manually`);
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
|
+
/** Resolve a Harness source entry, never the caller's project directory. */
|
|
75
|
+
function harnessSourceRoot(cliEntry) {
|
|
76
|
+
if (cliEntry === undefined)
|
|
77
|
+
return undefined;
|
|
78
|
+
try {
|
|
79
|
+
const entry = realpathSync(cliEntry);
|
|
80
|
+
const root = resolve(dirname(entry), '../../..');
|
|
81
|
+
if (entry !== join(root, 'apps', 'cli', 'src', 'bin.ts')
|
|
82
|
+
&& entry !== join(root, 'apps', 'cli', 'lib', 'bin.js'))
|
|
83
|
+
return undefined;
|
|
84
|
+
const pkg = JSON.parse(readFileSync(join(root, 'apps', 'cli', 'package.json'), 'utf8'));
|
|
85
|
+
return pkg.name === '@deepseek-ai/dsh' ? root : undefined;
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function configuredHarnessRoot(root) {
|
|
92
|
+
if (root === undefined || !isAbsolute(root))
|
|
93
|
+
return undefined;
|
|
94
|
+
try {
|
|
95
|
+
const pkg = JSON.parse(readFileSync(join(root, 'apps', 'cli', 'package.json'), 'utf8'));
|
|
96
|
+
return pkg.name === '@deepseek-ai/dsh' ? realpathSync(root) : undefined;
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
74
102
|
/** Register a user-owned launcher for the existing dsh-cli profile. No DSH state is changed. */
|
|
75
103
|
export function ensureCliRegistered(options = {}) {
|
|
76
104
|
const home = options.home ?? homedir();
|
|
@@ -78,6 +106,8 @@ export function ensureCliRegistered(options = {}) {
|
|
|
78
106
|
const platform = options.platform ?? process.platform;
|
|
79
107
|
const shell = options.shell ?? process.env.SHELL ?? '';
|
|
80
108
|
const pathValue = options.path ?? process.env.PATH ?? '';
|
|
109
|
+
const sourceRoot = harnessSourceRoot(options.cliEntry ?? process.argv[1])
|
|
110
|
+
?? configuredHarnessRoot(options.dshRoot ?? process.env.DSH_TUI_DSH_ROOT);
|
|
81
111
|
const binDir = platform === 'win32'
|
|
82
112
|
? join(options.localAppData ?? process.env.LOCALAPPDATA ?? join(home, 'AppData', 'Local'), 'dsh-cli', 'bin')
|
|
83
113
|
: join(home, '.local', 'bin');
|
|
@@ -140,9 +170,13 @@ export function ensureCliRegistered(options = {}) {
|
|
|
140
170
|
}
|
|
141
171
|
else {
|
|
142
172
|
const files = posixShellFiles(home, shell, options.zdotdir ?? process.env.ZDOTDIR, options.xdgConfigHome ?? process.env.XDG_CONFIG_HOME);
|
|
143
|
-
const
|
|
173
|
+
const pathLine = basename(shell) === 'fish'
|
|
144
174
|
? `contains -- ${quoted(binDir)} $PATH; or set -gx PATH ${quoted(binDir)} $PATH`
|
|
145
175
|
: `case ":$PATH:" in *:${quoted(binDir)}:*) ;; *) export PATH=${quoted(binDir)}:"$PATH" ;; esac`;
|
|
176
|
+
const sourceLine = sourceRoot === undefined ? '' : basename(shell) === 'fish'
|
|
177
|
+
? `\nset -q DSH_TUI_DSH_ROOT; or set -gx DSH_TUI_DSH_ROOT ${quoted(sourceRoot)}`
|
|
178
|
+
: `\nif [ -z "\${DSH_TUI_DSH_ROOT:-}" ]; then export DSH_TUI_DSH_ROOT=${quoted(sourceRoot)}; fi`;
|
|
179
|
+
const line = pathLine + sourceLine;
|
|
146
180
|
for (const file of files)
|
|
147
181
|
updateShellFile(file, line);
|
|
148
182
|
}
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
*
|
|
10
10
|
* @module dsh-auth/profiles
|
|
11
11
|
*/
|
|
12
|
+
import { randomUUID } from 'node:crypto';
|
|
12
13
|
import { resolveRetryPolicy } from '@deepseek-ai/dsh-llm';
|
|
13
14
|
import { adapterBuiltinProviders } from './pi-ai.js';
|
|
14
15
|
/** Provider routes this build mounts, in picker order. */
|
|
@@ -40,6 +41,23 @@ function catalogProviderOf(id) {
|
|
|
40
41
|
}
|
|
41
42
|
return found;
|
|
42
43
|
}
|
|
44
|
+
/** Add the per-request routing header that the installed pi-ai catalog omits. */
|
|
45
|
+
function withOpenCodeSessionHeader(catalog) {
|
|
46
|
+
return {
|
|
47
|
+
...catalog,
|
|
48
|
+
streamSimple(model, context, options) {
|
|
49
|
+
return catalog.streamSimple(model, context, {
|
|
50
|
+
...options,
|
|
51
|
+
headers: {
|
|
52
|
+
...options?.headers,
|
|
53
|
+
// Agent turns keep their durable id; direct calls without one still
|
|
54
|
+
// need a distinct routing identity instead of a gateway 400.
|
|
55
|
+
'x-opencode-session': options?.sessionId || randomUUID(),
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
}
|
|
43
61
|
/** The OAuth flow object for one mounted route (login/refresh/toAuth live here). */
|
|
44
62
|
export function oauthOf(route) {
|
|
45
63
|
const oauth = route.auth.oauth;
|
|
@@ -91,7 +109,8 @@ export function buildOAuthProfile(id, modelOverrides) {
|
|
|
91
109
|
if (!CATALOG_PROVIDER_IDS.includes(id)) {
|
|
92
110
|
throw new Error(`dsh-auth: "${id}" is not a catalog provider this build mounts (${CATALOG_PROVIDER_IDS.join(', ')})`);
|
|
93
111
|
}
|
|
94
|
-
const
|
|
112
|
+
const provider = catalogProviderOf(id);
|
|
113
|
+
const catalog = withModelOverrides(id === 'opencode' || id === 'opencode-go' ? withOpenCodeSessionHeader(provider) : provider, modelOverrides);
|
|
95
114
|
return {
|
|
96
115
|
provider: id,
|
|
97
116
|
displayName: catalog.name,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@askdkc/dsh-cli",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.7",
|
|
4
4
|
"description": "Interactive terminal interface for DeepSeek Harness agents, sessions and tools.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dsh",
|
|
@@ -113,7 +113,7 @@
|
|
|
113
113
|
"scripts": {
|
|
114
114
|
"clean": "node scripts/clean-lib.mjs",
|
|
115
115
|
"build:dsh-std": "pnpm --dir vendor/dsh-std install --frozen-lockfile --ignore-scripts && pnpm --dir vendor/dsh-std --filter @dsh-std/core --filter @dsh-std/manifest --filter @dsh-std/connection --filter @dsh-std/presentation --filter @dsh-std/command --filter @dsh-std/storage --filter @dsh-std/messages -r build",
|
|
116
|
-
"build:dsh-auth": "pnpm --dir dsh-auth install --frozen-lockfile --ignore-scripts && pnpm --dir dsh-auth run build",
|
|
116
|
+
"build:dsh-auth": "git submodule update --init --remote --checkout dsh-auth && pnpm --dir dsh-auth install --frozen-lockfile --ignore-scripts && pnpm --dir dsh-auth run build",
|
|
117
117
|
"compile": "npm run build:dsh-std && npm run build:dsh-auth && npm run clean && tsc -p tsconfig.json",
|
|
118
118
|
"compile:src": "tsc -p tsconfig.json",
|
|
119
119
|
"typecheck": "tsc -p tsconfig.typecheck.json",
|