Repository navigation
Expand file tree
/
Copy pathcordis.patch.yml
More file actions
539 lines (484 loc) · 26.4 KB
/
Copy pathcordis.patch.yml
File metadata and controls
539 lines (484 loc) · 26.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
# The dsh-tui bundle patch: the interactive terminal front door over the
# dsh-base layer. Applied after dsh-base's insert; rows here override base
# rows by id, with the profile's own cordis.patch.yml and any --patch
# overlays still to come.
#
# A patch replaces the targeted row's whole `config`, so each row below
# restates every key it owns (see the dsh-base patch for the shared
# defaults). The dsh-base core rows that need no dsh-tui value — tools,
# sandbox/approval policy, skills, goal, plan mode, workspace context,
# telemetry — are inherited unless this surface explicitly restates them.
# ── surface-specific values over the dsh-base layer ─────────────────────────
# The dsh-tui deployment persona; DSH_TUI_PERSONA overrides the coding-agent
# default (the base persona is empty). dsh-system-prompt renamed the slot at
# 0.1.3-alpha.2 (`persona` → `personaPrefix`, with an optional suffix
# counterpart); older cohorts only accept `persona`, so the key follows the
# installed package version.
- id: system-prompt
config: !!js >-
(() => {
const persona = process.env.DSH_TUI_PERSONA ?? 'You are a coding agent.'
try {
const require = process.getBuiltinModule('node:module').createRequire(ctx.baseUrl)
const fs = process.getBuiltinModule('node:fs')
const manifest = require.resolve('@deepseek-ai/dsh-system-prompt/package.json')
const version = String(JSON.parse(fs.readFileSync(manifest, 'utf8')).version ?? '')
const match = /^(\d+)\.(\d+)\.(\d+)/u.exec(version)
const [major, minor, patch] = match === null ? [0, 0, 0] : [Number(match[1]), Number(match[2]), Number(match[3])]
if (major > 0 || minor > 1 || (minor === 1 && patch >= 3)) return { personaPrefix: persona }
return { persona }
} catch {
return { personaPrefix: persona }
}
})()
# The native DeepSeek adapter, pinned to the harness defaults: full thinking
# at max effort, key and base URL from the launching environment. The base
# entry supplies the adapter defaults; /settings edits the profile config
# on 0.1.7 (older hosts apply their separate settings document per request).
# rc.6 schema key is `apiKeyEnv` (credential-ref env var NAME, default
# DEEPSEEK_API_KEY); the old snapshot's `apiKey` key no longer exists.
- id: llm-deepseek
config:
apiKeyEnv: 'DEEPSEEK_API_KEY'
baseURL: !!js process.env.DEEPSEEK_BASE_URL
thinking: enabled
reasoningEffort: max
# The TUI creates (or resumes) its agent at runtime through the agent
# factory; no declarative agents are started at boot, and the configured
# agent list stays the base's empty default.
- id: agent-loop
config:
agents: []
# Preserve the TUI's opt-in privacy stance across the 0.1.2 base default
# change to FEEDBACK_ONLY. An explicit DSH_TELEMETRY_MODE still wins. This
# restates the whole 0.1.2 config because include patches replace config
# objects rather than merging them. The 0.2.0 base moved the collector to
# dsh-otel-collector and added maxRequestBytes; older cohorts keep the
# endpoint (and the key set) their base shipped, so both follow the
# installed package version.
- id: session-telemetry-otel
config: !!js >-
(() => {
let url = 'https://dsh-otel-collector.deepseeksvc.com/v1/logs'
let modern = false
try {
const require = process.getBuiltinModule('node:module').createRequire(ctx.baseUrl)
const fs = process.getBuiltinModule('node:fs')
const manifest = require.resolve('@deepseek-ai/dsh-session-telemetry-otel/package.json')
const version = String(JSON.parse(fs.readFileSync(manifest, 'utf8')).version ?? '')
const match = /^(\d+)\.(\d+)\./u.exec(version)
modern = match === null || Number(match[1]) > 0 || Number(match[2]) >= 2
if (!modern) url = 'https://harness-telemetry.deepseeksvc.com/v1/logs'
} catch {}
return {
mode: process.env.DSH_TELEMETRY_MODE || 'DISABLED',
shutdownTimeoutMillis: 3000,
// 0.2.0's base config caps one request at 4 MB; the older plugin's
// schema has no such key, so only a probed 0.2+ host gets it.
...(modern ? { maxRequestBytes: 4000000 } : {}),
exporter: {
url: process.env.DSH_TELEMETRY_OTLP_URL ?? url,
compression: 'gzip',
timeoutMillis: 1000,
},
processor: {
scheduledDelayMillis: 10000,
maxQueueSize: 2048,
maxExportBatchSize: 2048,
exportTimeoutMillis: 1500,
},
}
})()
# The 0.1.2 base sends the active Loader package inventory on official
# DeepSeek requests by default. TUI keeps that diagnostic metadata opt-in.
- id: plugin-package-inventory-deepseek
config:
enabled: false
# ── agent presets (issue #8) ────────────────────────────────────────────────
#
# The model-facing plugin set moves INTO the preset registry: every
# session composes its tools/prompt sections from one preset
# (standard/ptc/minimal/cordis) instead of the host rows below. The TUI's
# roster row uses the scoped `dsh-tui-agent-presets` id. The 0.1.2 generation
# prepends its bundled system root; legacy 0.1.1-rc.2 still needs the dsh CLI's
# `config/agent-presets/` directory supplied explicitly. Both append
# `$DSH_HOME/.agent-presets`. Mirroring the official dsh-web-app patch: every
# dsh-base row a preset now owns is disabled here, so a minimal agent does not
# leak host-layer tools (an agent's registry view resolves agent → preset →
# global). On 0.1.7, the adapter registers official declarative bundles;
# directory discovery and the old code-runtime host row stay disabled.
- id: agent-instructions
disabled: true
- id: command-compact
disabled: true
# compaction lives in the preset's own isolate realm (standard/ptc/cordis
# carry `compaction-basic` with package defaults; minimal has none). The old
# ratio/retain tunables retired with this host row — preset compositions own
# their compaction config.
- id: compaction-basic
disabled: true
- id: plan-mode
disabled: true
- id: skill-filesystem
disabled: true
- id: tool-bash
disabled: true
- id: tool-fs
disabled: true
- id: tool-fs-search
disabled: true
- id: command-goal
# rc.2 presets do not carry this command, so their host row must remain
# active. Newer packages disable it only when the shipped standard preset
# really owns the command; reading the capability avoids guessing from
# another optional Loader row.
disabled: !!js >-
(() => {
const require = process.getBuiltinModule('node:module').createRequire(ctx.baseUrl)
const fs = process.getBuiltinModule('node:fs')
const path = process.getBuiltinModule('node:path')
try {
require.resolve('@deepseek-ai/dsh-agent-preset-registry/package.json')
return true
} catch {}
try {
const manifest = require.resolve('@deepseek-ai/dsh-agent-presets/package.json')
const preset = path.join(path.dirname(manifest), 'presets', 'standard', 'agent.cordis.yml')
return fs.readFileSync(preset, 'utf8')
.split(/\r?\n/u)
.some(line => line.trim() === '- id: command-goal')
} catch {
return false
}
})()
- id: tool-goal
disabled: true
- id: tool-jobs
disabled: true
- id: tool-pwsh
disabled: true
- id: tool-ralph
disabled: true
- id: tool-result-pruner
disabled: true
- id: tool-skill
disabled: true
# `tool-str-replace-editor` carries no disable row: dsh-base registered that
# entry only up to the 0.1.2 line, and from 0.1.3-alpha.2 it is opt-in (see the
# dsh-base README). A row here would target a missing id and log
# `patch: entry "tool-str-replace-editor" not found` on every 0.1.3+ boot.
# Presets that expose the tool re-add the entry themselves.
# Delegation tools (subagent spawn/fork, controls, workflows) are preset rows
# now; the preset's `delegation` group re-adds them with package defaults, so
# the former TUI's depth-1 cap no longer applies.
- id: tool-subagent
disabled: true
- id: tool-subagent-control
disabled: true
- id: tool-subagent-fork
disabled: true
- id: tool-subagent-list-agents
disabled: true
- id: tool-todo
disabled: true
- id: tool-web
disabled: true
- id: tool-workflow
disabled: true
# Windows has no sandbox confinement backend yet (sandbox-local's win32
# chain is empty); use danger-full-access on Windows so bash commands can
# run. Other platforms keep the base workspace-write default. DSH_PERMISSION_MODE
# is the INITIAL state of a launch — the remembered /permission pick
# (~/.dsh-tui/permission.json) outranks it whenever it is not set.
- id: sandbox-policy
config:
mode: !!js "process.platform === 'win32' ? 'danger-full-access' : (process.env.DSH_PERMISSION_MODE ?? 'workspace-write')"
workspaceRoot: !!js process.cwd()
# On Windows, skip approval prompts (no sandbox = the user's terminal trust
# model, matching every other terminal coding agent).
- id: approval
config:
policy: !!js "process.platform === 'win32' ? 'never' : ((process.env.DSH_PERMISSION_MODE ?? 'workspace-write') === 'danger-full-access' ? 'never' : 'ask')"
# Sessions live in the shared JSONL store (~/.dsh/sessions) — the same
# backend dsh web writes — so /resume here and the web session list see each
# other (#24). The row itself comes from the dsh-base layer; this override
# only re-points the root when DSH_TUI_SESSION_ROOT is set (test isolation).
- id: session-persistence-jsonl
config:
root: !!js process.env.DSH_TUI_SESSION_ROOT ?? dshHomePath('sessions')
# ── dsh-tui rows ────────────────────────────────────────────────────────────
# The `user-interaction` service row comes from the dsh-base bundle layer
# (mounted before this layer); do not insert it again — the include patch
# semantics would create a duplicate row. dsh-tui defensively creates the
# service on its own context when no composition provides it (bare
# `dsh --config cordis.yml` boots), then mounts the model-facing
# ask_user_question tool. On legacy hosts it registers the TUI provider on
# `ctx.userQuestions`; on Alpha it answers the scoped
# `user-questions/request` waterfall.
- insert:
# Workspace grouping is a separate durable ledger, not a cwd-derived
# projection. Mount the same domain stack and storage root as dsh-web-app
# so TUI-created sessions can attach to the exact registry Web reads.
#
# These rows own host-plane services that the official web-app bundle may
# already mount. Loader entry ids are process-global, so these
# rows use dsh-tui-* scoped ids and self-disable when an enabled row with
# the official id/name is already present in the tree. The disabled check
# is evaluated during the same include update that inserts every row, so
# it sees the web-app rows regardless of their activation state.
- id: dsh-tui-storage
name: '@deepseek-ai/dsh-storage'
disabled: !!js "[...ctx.loader.entries()].some(entry => entry.options.id === 'storage' && entry.options.name === '@deepseek-ai/dsh-storage' && !entry.disabled)"
- id: dsh-tui-storage-json
name: '@deepseek-ai/dsh-storage-json'
disabled: !!js "[...ctx.loader.entries()].some(entry => entry.options.id === 'storage-json' && entry.options.name === '@deepseek-ai/dsh-storage-json' && !entry.disabled)"
config:
root: !!js dshHomePath('storages')
- id: dsh-tui-storage-domain
name: '@deepseek-ai/dsh-storage-domain'
disabled: !!js "[...ctx.loader.entries()].some(entry => entry.options.id === 'storage-domain' && entry.options.name === '@deepseek-ai/dsh-storage-domain' && !entry.disabled)"
config:
backend: json
# Alpha moved the durable storage stack into dsh-base, so these three
# scoped copies self-disable there. Keep them for the validated rc lines,
# whose base layer does not provide the stack to a TUI-only profile.
- id: dsh-tui-workspace
name: '@deepseek-ai/dsh-workspace'
disabled: !!js "[...ctx.loader.entries()].some(entry => entry.options.id === 'workspace' && entry.options.name === '@deepseek-ai/dsh-workspace' && !entry.disabled)"
# PTC presentation waits on this Host service. The scoped row supports a
# TUI-only profile and yields to the official web-app row in mixed profiles.
- id: dsh-tui-code-runtime
name: '@deepseek-ai/dsh-code-runtime-worker-thread'
disabled: !!js >-
(() => {
const require = process.getBuiltinModule('node:module').createRequire(ctx.baseUrl)
try { require.resolve('@deepseek-ai/dsh-ptc-runtime-node/package.json'); return true } catch {}
return [...ctx.loader.entries()].some(entry => entry.options.id === 'code-runtime' && entry.options.name === '@deepseek-ai/dsh-code-runtime-worker-thread' && !entry.disabled)
})()
# 0.1.2 presets opt their delegation tool into Host-owned model-selection
# settings. Without this service standard/ptc/cordis preset mounting fails.
# The package subpath does not exist on rc.2, so resolve that capability
# directly before Loader attempts the import. An enabled official row still
# owns the seat in mixed profiles.
- id: dsh-tui-subagent-model-selection-settings
name: '@deepseek-ai/dsh-tool-subagent/model-selection-settings'
disabled: !!js >-
(() => {
const require = process.getBuiltinModule('node:module').createRequire(ctx.baseUrl)
try {
require.resolve('@deepseek-ai/dsh-tool-subagent/model-selection-settings')
} catch {
return true
}
return [...ctx.loader.entries()].some(entry => entry.options.id === 'subagent-model-selection-settings' && entry.options.name === '@deepseek-ai/dsh-tool-subagent/model-selection-settings' && !entry.disabled)
})()
# Generic terminal workspace registry. Optional plugins add providers;
# the TUI itself always supplies LOCAL and has no provider-specific code.
- id: dsh-tui-workspaces
name: '@deepseek-harness-tui/dsh-tui/workspaces'
# Optional plugins contribute nested slash-command completion here;
# execution and durable command events remain owned by dsh-commands.
- id: dsh-tui-command-trees
name: '@deepseek-harness-tui/dsh-tui/command-trees'
# Optional plugins declare editable settings sections here (issue #165);
# storage, validation and writes remain owned by the dsh settings service.
- id: dsh-tui-settings-sections
name: '@deepseek-harness-tui/dsh-tui/settings-sections'
# Optional plugins register full-screen scenes (trajectory-style whole-
# terminal views) here and open them from their own command handlers;
# rendering and input ownership remain owned by the TUI's Chat screen.
- id: dsh-tui-scenes
name: '@deepseek-harness-tui/dsh-tui/scenes'
# Optional plugins register side-panel surfaces (sidebar Panel +
# compact row, experimental §18) here; admission, budgets and crash
# isolation remain owned by the tuiPanels runtime + PanelStore.
- id: dsh-tui-panels
name: '@deepseek-harness-tui/dsh-tui/panels'
# Plugin-interop anchor (Community Consensus v0.15): the unified grant
# store, runtime generation id, and Host Descriptor live here; later
# contract surfaces (plugin storage, message observation, effect
# ledger) mount off THIS row's apply, so the patch surface changes only
# once for the whole alignment. Mounted ahead of the extensions row and
# any third-party plugin row.
- id: dsh-tui-plugin-host
name: '@deepseek-harness-tui/dsh-tui/plugin-host'
# Plugin-facing UI seams (the pi-style extension surface): managed
# dialogs (select/confirm/input), keyed status-line contributions,
# keyboard shortcuts, and custom session-entry text renderers. The
# decision events (tui/input, tui/rewind-prompt, tui/session-switch,
# tui/compact, …) are fired by the channel on the cordis bus directly
# and need no row.
- id: dsh-tui-extensions
name: '@deepseek-harness-tui/dsh-tui/extensions'
# The agent-preset roster (issue #8): `ctx.agentPresets`, the service the
# TUI composes every session's model-facing world from. 0.1.2 packages
# prepend their bundled presets as the read-only system root; legacy rc.2
# packages have no bundled root and still scan the dsh CLI directory. Both append
# `$DSH_HOME/.agent-presets` as the user root. Deployment-added roots may
# still be supplied by a later patch.
- id: dsh-tui-agent-presets
name: '@deepseek-ai/dsh-agent-presets'
disabled: !!js >-
(() => {
const require = process.getBuiltinModule('node:module').createRequire(ctx.baseUrl)
try { require.resolve('@deepseek-ai/dsh-agent-preset-registry/package.json'); return true } catch {}
return [...ctx.loader.entries()].some(entry => entry.options.id === 'agent-presets' && entry.options.name === '@deepseek-ai/dsh-agent-presets' && !entry.disabled)
})()
config: !!js >-
(() => {
const require = process.getBuiltinModule('node:module').createRequire(ctx.baseUrl)
const fs = process.getBuiltinModule('node:fs')
const path = process.getBuiltinModule('node:path')
try {
const manifest = require.resolve('@deepseek-ai/dsh-agent-presets/package.json')
if (fs.existsSync(path.join(path.dirname(manifest), 'presets'))) {
return { default: 'standard' }
}
} catch {
// Let the roster import report a missing package; preserve the rc
// root fallback below for every package generation without one.
}
const base = ctx.baseUrl
if (!base) return { default: 'standard' }
const root = new URL('../node_modules/@deepseek-ai/dsh/config/agent-presets/', base)
let rootPath = decodeURIComponent(root.pathname)
if (/^\/[A-Za-z]:/.test(rootPath)) rootPath = rootPath.slice(1)
return { default: 'standard', roots: [{ path: rootPath, trust: 'system' }] }
})()
# 0.1.7 replaces directory discovery with declarations in a registry.
# The TUI registers the official bundle defaults only when Web has not
# already declared them. PTC's host runtime now comes from dsh-base.
- id: dsh-tui-agent-preset-registry
name: '@deepseek-ai/dsh-agent-preset-registry'
disabled: !!js >-
(() => {
const require = process.getBuiltinModule('node:module').createRequire(ctx.baseUrl)
try { require.resolve('@deepseek-ai/dsh-agent-preset-registry/package.json') } catch { return true }
return [...ctx.loader.entries()].some(entry => entry.options.id === 'agent-preset-registry' && entry.options.name === '@deepseek-ai/dsh-agent-preset-registry' && !entry.disabled)
})()
config:
default: standard
# Host-plane services the `cordis` preset's plugin-experimentation tool
# waits on (dynamicCordisRunner/cordisInspect); dsh-base carries no such
# row — the official web app inserts it the same way, so this copy yields
# to it when it is already present.
- id: dsh-tui-cordis-host-runner
name: '@deepseek-ai/dsh-cordis-host-runner'
disabled: !!js "[...ctx.loader.entries()].some(entry => entry.options.id === 'cordis-host-runner' && entry.options.name === '@deepseek-ai/dsh-cordis-host-runner' && !entry.disabled)"
# DeepSeek account sign-in uses the Host-owned /oauth/callback route. A
# TUI-only profile needs a loopback listener; a mixed Web+TUI profile
# reuses Web's official webserver instead of opening a second one. Hosts
# without an enabled account service row leave this listener disabled.
- id: dsh-tui-webserver
name: '@deepseek-ai/dsh-host-webserver'
disabled: !!js >-
(() => {
const require = process.getBuiltinModule('node:module').createRequire(ctx.baseUrl)
try { require.resolve('@deepseek-ai/dsh-host-webserver/package.json') } catch { return true }
const entries = [...ctx.loader.entries()]
return !entries.some(entry => entry.options.name === '@deepseek-ai/dsh-deepseek-account-platform' && !entry.disabled)
|| entries.some(entry => entry.options.id === 'webserver' && entry.options.name === '@deepseek-ai/dsh-host-webserver' && !entry.disabled)
})()
config:
host: 127.0.0.1
port: 0
# Built-in subscription OAuth sign-in: mounts available pi-ai routes
# (ChatGPT/Codex, Claude, Grok; newer pi-ai adds OpenAI direct and Meta)
# plus the /auth command. Its facade also delegates DeepSeek sign-in to
# the Host-owned account service when available. The TUI's /provider
# wizard gains its OAuth branch from ctx.dshAuth. Entry-level inject only —
# the internal module's own inject is empty so a stale patch cannot
# deadlock a composition lacking these services (#183 pattern).
- id: dsh-tui-auth
name: '@deepseek-harness-tui/dsh-tui/oauth'
inject: [llm, commands]
# The interactive front door. The plugin creates/resumes its agent at
# runtime, seeds the startup status line, and disposes the whole app tree
# (exiting the process) when the TUI unmounts. `dsh-tui --resume`
# feeds the session id through DSH_TUI_RESUME_SESSION (see
# src/sessionHistory.ts for the launcher contract).
- id: dsh-tui
name: '@deepseek-harness-tui/dsh-tui'
# The entry-level dependency augments the plugin's `agents` inject and
# prevents startup Session creation from racing WorkspaceRegistry init.
inject: [workspaceRegistry, agents, tuiWorkspaces, tuiScenes, tuiPanels, tuiDialogs, tuiStatus, tuiShortcuts, tuiRenderers, tuiThemes]
# `tuiWorkspaces`/`tuiScenes` (and the dsh-tui-extensions services,
# including `tuiThemes`)
# live in the entry-level inject ONLY as an ordering (and reload-rebind)
# guarantee alongside their service rows
# above — they are deliberately absent from the plugin's code-level
# inject (issue #183): the dsh CLI may read this patch from an older
# copy of the package than the plugin module it loads, and a hard
# code-level inject then deadlocks the tree at boot ("pending (waiting
# for service: tuiWorkspaces)"). Without the rows the TUI degrades:
# /workspace falls back to the local-only runtime, plugin scenes never
# open. (The comment sits below the inject line:
# verify-workspace-attachment.mjs asserts the name→inject distance.)
config:
# `provider` + `model` are the deployment DEFAULT route (used until a
# `/model` pick is persisted in ~/.dsh-tui/model.json, which then wins
# whole); a half-pinned pair is ignored outright (issue #67).
provider: deepseek-official
# Alt-screen fullscreen 布局:应用内鼠标选区(选择即复制, OSC 52 +
# wl-copy/xclip/xsel 兜底)、滚轮滚动、双击选词/三击选行。出厂默认开启,
# 与 schema 默认(index.ts fullscreen default true)保持一致——两处必须
# 同步翻转,否则本覆盖层会盖住 schema 默认,更新后用户仍落在 inline。
# 想退回 inline 主屏(终端原生滚动/选择):/settings 全屏开关或 cordis.yml
# `fullscreen: false`——显式选择始终优先于默认。
fullscreen: true
# 以下为 /settings 可改的显示设置;每项说明与默认值见应用内 /settings 屏。
terminalImages: true
# diffLayout: auto
# mermaidDiagrams: true
# 回复中 LaTeX 公式的显示方式:auto(默认,目前为 Unicode)/ image(支持图形的终端里块级公式显示为图片)/ unicode / source(保留源码)。/settings 可实时改。
# mathRendering: auto
# 每个请求实际生效的推理强度,按当前路由的 adapter 档位校验
#(deepseek: off/low/high/max);非法值回落 adapter 默认。
# 这是部署默认值:上一次 /effort 的持久化选择(~/.dsh-tui/effort.json)
# 优先于它,它只决定"还没有选择过"的会话。
effort: max
# Shift+Tab session-mode cycle (array order IS the cycle order;
# absent → the built-in default/plan/full trio below). Each entry
# may declare any subset of the plan (on/off), sandbox (read-only/
# workspace-write/danger-full-access), and approval (ask/never)
# atoms; undeclared atoms are untouched. Entry index 0 is the
# unmarked base mode.
# modes:
# - id: default
# plan: false
# sandbox: workspace-write
# approval: ask
# - id: plan
# plan: true
# sandbox: read-only
# approval: ask
# - id: full
# plan: false
# sandbox: danger-full-access
# approval: never
# Deployment default for the Agent preset: the persisted `/preset`
# preference (~/.dsh-tui/agent-preset.json) outranks it, and
# DSH_TUI_PRESET (this run's explicit instruction) outranks both; the
# roster default (standard) closes the chain.
preset: !!js process.env.DSH_TUI_PRESET ?? undefined
workspace: !!js process.env.DSH_TUI_WORKSPACE_TARGET ?? undefined
sessionId: !!js process.env.DSH_TUI_RESUME_SESSION ?? undefined
# Agent backend (`dsh-tui --backend claude` → DSH_TUI_BACKEND); unset → /kernel's remembered pick, else dsh.
backend: !!js process.env.DSH_TUI_BACKEND || undefined
# Live working-line data source (thinking copy / running tool / turn
# summary). Mounted through @deepseek-harness-tui/dsh-tui's own
# `./working-activity` re-export, NOT the bare `dsh-working-activity`
# name: the dsh Loader resolves row names from the profile directory,
# and pnpm's isolated node_modules layout never links a transitive
# dependency into the profile root (npm's flat layout hid this), so the
# bare name died with ERR_MODULE_NOT_FOUND and disposed the whole app at
# boot (#60).
# The plugin stays mounted for its narration/system-prompt features and
# publishes the `workingActivity` session projection, which is where the
# TUI's working line comes from; never persist activity/status, so the
# shared log remains Web-readable.
- id: working-activity
name: '@deepseek-harness-tui/dsh-tui/working-activity'
config:
publish: false
publishIntervalMs: 500