@agi-fans/oh-my-dsh 0.14.0 → 0.16.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.
@@ -1,5 +1,5 @@
1
1
  - id: persona
2
2
  name: '@deepseek-ai/dsh-persona'
3
3
  config:
4
- text: >-
4
+ prefix: >-
5
5
  You are a coding agent powered by the {{model}} model. Your working directory is {{cwd}}. Prefer programmatic tool calling for multi-step operations when the generated tools SDK is available.
@@ -1,7 +1,7 @@
1
1
  - id: persona
2
2
  name: '@deepseek-ai/dsh-persona'
3
3
  config:
4
- text: |-
4
+ prefix: |-
5
5
  You are a coding agent powered by the {{model}} model, running on the DeepSeek Harness. Your working directory is {{cwd}}.
6
6
 
7
7
  You can inspect and experiment with the live Cordis runtime. Host composition owns shared registries and backends; an Agent preset owns one session's tools, persona, prompt sections, and isolated services. Treat runtime mutation as shell-level authority and explain the affected composition boundary before changing it.
@@ -1,16 +1,19 @@
1
1
  - id: persona
2
2
  name: '@deepseek-ai/dsh-persona'
3
3
  config:
4
- text: You are a helpful software engineer assistant.{{omdsh_agent_behavior}}
4
+ prefix: You are a helpful software engineer assistant.{{omdsh_agent_behavior}}
5
5
  complete: true
6
6
  includeRuntimeContext: false
7
7
 
8
+ # `shell` is an omdsh alias for the host's one shell tool (`bash` on POSIX,
9
+ # `pwsh` on Windows), so this two-tool shape holds on every platform without a
10
+ # name that `tools.restrict()` would reject.
8
11
  - id: profile
9
12
  name: '@agi-fans/dsh-tui/agent-profile'
10
13
  config:
11
14
  tools:
12
15
  allow:
13
- - bash
16
+ - shell
14
17
  - str_replace_editor
15
18
 
16
19
  - id: persistent-shell
@@ -24,10 +27,26 @@
24
27
 
25
28
  - id: terminal-bash
26
29
  name: '@deepseek-ai/dsh-terminal-bash'
30
+ disabled: !!js process.platform === 'win32'
27
31
  config:
28
32
  timeoutMs: 300000
29
33
 
30
34
  - id: persistent-bash
31
35
  name: '@deepseek-ai/dsh-tool-bash-persistent'
36
+ disabled: !!js process.platform === 'win32'
37
+ config:
38
+ timeoutMs: 300000
39
+
40
+ # The PTY backend is shared; the dialect selects PowerShell on Windows.
41
+ - id: terminal-pwsh
42
+ name: '@deepseek-ai/dsh-terminal-bash'
43
+ disabled: !!js process.platform !== 'win32'
44
+ config:
45
+ shellDialect: pwsh
46
+ timeoutMs: 300000
47
+
48
+ - id: persistent-pwsh
49
+ name: '@deepseek-ai/dsh-tool-pwsh-persistent'
50
+ disabled: !!js process.platform !== 'win32'
32
51
  config:
33
52
  timeoutMs: 300000
@@ -1,5 +1,5 @@
1
1
  - id: persona
2
2
  name: '@deepseek-ai/dsh-persona'
3
3
  config:
4
- text: >-
4
+ prefix: >-
5
5
  You are a coding agent powered by the {{model}} model. Your working directory is {{cwd}}.
package/config/cordis.yml CHANGED
@@ -44,13 +44,14 @@
44
44
  - id: session-stats
45
45
  name: '@deepseek-ai/dsh-session-stats'
46
46
 
47
- # Exact session reads for @session mentions. openAt: never keeps FTS closed so
48
- # Node 22 never loads experimental node:sqlite; list/read still work over JSONL.
47
+ # Exact session reads for @session mentions, plus lazy full-text search.
48
+ # openAt: first-search keeps startup free of experimental node:sqlite; the
49
+ # index opens only when a human actually searches the session library.
49
50
  - id: session-query
50
51
  name: '@deepseek-ai/dsh-session-query-sqlite'
51
52
  config:
52
53
  path: ':memory:'
53
- openAt: never
54
+ openAt: first-search
54
55
 
55
56
  - id: session-reference
56
57
  name: '@deepseek-ai/dsh-session-reference'
@@ -100,7 +101,7 @@
100
101
  name: '@deepseek-ai/dsh-agent-default-model'
101
102
  config:
102
103
  provider: !!js process.env.OMDSH_PROVIDER || 'deepseek-official'
103
- model: !!js process.env.OMDSH_MODEL || 'deepseek-v4-flash'
104
+ model: !!js process.env.OMDSH_MODEL || 'deepseek-flash'
104
105
 
105
106
  - id: agent-presets
106
107
  name: '@deepseek-ai/dsh-agent-presets'
@@ -134,7 +135,7 @@
134
135
  workspaceRoot: !!js process.cwd()
135
136
 
136
137
  - id: fs
137
- name: '@deepseek-ai/dsh-fs-local'
138
+ name: '@deepseek-ai/dsh-fs-sandbox'
138
139
 
139
140
  - id: fs-observation-policy
140
141
  name: '@deepseek-ai/dsh-fs-observation-policy'
@@ -142,8 +143,23 @@
142
143
  - id: subprocess
143
144
  name: '@deepseek-ai/dsh-subprocess-local'
144
145
 
146
+ # Exactly one shell stack mounts per host: the bash stack gates off Windows
147
+ # and its PowerShell twin gates off everything else, so a session always has
148
+ # one confined shell and never a tool whose interpreter is missing. Timeouts
149
+ # are pinned rather than inherited: upstream's 60s base default is short for
150
+ # ordinary builds and test suites, and the model can still raise the limit
151
+ # per call or run the command in the background.
145
152
  - id: bash
146
153
  name: '@deepseek-ai/dsh-bash-sandbox'
154
+ disabled: !!js process.platform === 'win32'
155
+ config:
156
+ timeoutMs: 120000
157
+
158
+ - id: pwsh
159
+ name: '@deepseek-ai/dsh-pwsh-sandbox'
160
+ disabled: !!js process.platform !== 'win32'
161
+ config:
162
+ timeoutMs: 120000
147
163
 
148
164
  - id: permission
149
165
  name: '@deepseek-ai/dsh-permission-presets'
@@ -221,6 +237,11 @@
221
237
 
222
238
  - id: tool-bash
223
239
  name: '@deepseek-ai/dsh-tool-bash'
240
+ disabled: !!js process.platform === 'win32'
241
+
242
+ - id: tool-pwsh
243
+ name: '@deepseek-ai/dsh-tool-pwsh'
244
+ disabled: !!js process.platform !== 'win32'
224
245
 
225
246
  - id: agent-instructions
226
247
  name: '@deepseek-ai/dsh-agent-instructions'
@@ -233,6 +254,18 @@
233
254
  - id: tool-jobs
234
255
  name: '@deepseek-ai/dsh-tool-jobs'
235
256
 
257
+ # Persistent, owner-scoped terminal sessions for interactive stdin and
258
+ # cross-call state (REPLs, debuggers, a shell to return to). The one-shot
259
+ # bash/pwsh tools remain the default for bounded commands.
260
+ - id: terminal
261
+ name: '@deepseek-ai/dsh-terminal'
262
+
263
+ - id: terminal-bash
264
+ name: '@deepseek-ai/dsh-terminal-bash'
265
+
266
+ - id: tool-terminal
267
+ name: '@deepseek-ai/dsh-tool-terminal'
268
+
236
269
  - id: agent-loop
237
270
  name: '@deepseek-ai/dsh-agent-loop'
238
271
  config:
@@ -286,15 +319,72 @@
286
319
  config:
287
320
  maxOutputChars: 16000
288
321
 
322
+ # Deliverables: the model declares the workspace files it finished so the
323
+ # user can find them afterwards. The files are not copied or preserved — the
324
+ # card lists their source paths, and the TUI renders that list instead of the
325
+ # raw call arguments.
326
+ - id: tool-present
327
+ name: '@deepseek-ai/dsh-tool-present'
328
+
329
+ # Anonymous public web fetch, no credential and no search provider: a fetch
330
+ # costs nothing and the TUI already renders web sources. Search stays off
331
+ # because DeepSeek's native search spends a whole model turn per query; a
332
+ # deployment that wants it mounts a provider in its own overlay and flips
333
+ # `search` on here.
334
+ - id: web
335
+ name: '@deepseek-ai/dsh-web'
336
+
337
+ - id: web-fetch-http
338
+ name: '@deepseek-ai/dsh-web-fetch-http'
339
+
340
+ - id: tool-web
341
+ name: '@deepseek-ai/dsh-tool-web'
342
+ config:
343
+ search: false
344
+ fetch: true
345
+
346
+ # Spills one oversized plain-text tool result to a private file and hands the
347
+ # model a bounded preview plus the path. The cap is deliberately far above
348
+ # upstream's 50 KB: the session log carries the replacement, so a lower cap
349
+ # would shorten what a human can expand in the transcript.
350
+ - id: spill-local
351
+ name: '@deepseek-ai/dsh-spill-local'
352
+
353
+ - id: spill-policy
354
+ name: '@deepseek-ai/dsh-spill-policy'
355
+ config:
356
+ maxInlineBytes: 200000
357
+
289
358
  - id: token-meter
290
359
  name: '@deepseek-ai/dsh-token-meter'
291
360
 
361
+ # Trims oversized tool results before condensation, so the model-visible
362
+ # result stays inside the budget; the full original stays in the session log.
363
+ # compaction-basic reads this through ctx.get, so the row must precede it.
364
+ - id: tool-result-pruner
365
+ name: '@deepseek-ai/dsh-compaction-tool-result-pruner'
366
+ config:
367
+ thresholdChars: 8192
368
+ headChars: 4096
369
+ tailChars: 1024
370
+
292
371
  - id: compaction
293
372
  name: '@deepseek-ai/dsh-compaction-basic'
294
373
 
295
374
  - id: command-compact
296
375
  name: '@deepseek-ai/dsh-command-compact'
297
376
 
377
+ # Guard rails on the tool chain: a cooperative per-tool deadline, and an
378
+ # advisory reminder when an agent repeats an identical call.
379
+ - id: timeout-policy
380
+ name: '@deepseek-ai/dsh-tool-call-timeout-policy'
381
+
382
+ - id: repeat-tool-reminder
383
+ name: '@deepseek-ai/dsh-repeat-tool-reminder'
384
+ config:
385
+ thresholds: [3, 5, 8]
386
+ argumentsPreviewChars: 500
387
+
298
388
  - id: subagent
299
389
  name: '@deepseek-ai/dsh-subagent'
300
390
 
@@ -303,6 +393,43 @@
303
393
  config:
304
394
  providerName: spawn
305
395
 
396
+ # Fork seeds the child with the parent's completed turns, so the inherited
397
+ # prefix stays eligible for KV cache reuse. Model selection is deliberately
398
+ # absent: a child that switched routes would pay for the inherited history
399
+ # again.
400
+ - id: subagent-fork
401
+ name: '@deepseek-ai/dsh-subagent-fork-in-process'
402
+ config:
403
+ providerName: fork
404
+
405
+ # Process-isolated transport. Every in-process backend above runs the child
406
+ # agent on the TUI's own event loop, so a heavy delegation starves rendering
407
+ # and the activity animation. This backend spawns a whole child runtime
408
+ # instead, moving that CPU off the TUI thread. It is an extra opt-in
409
+ # transport: `spawn`/`fork` stay mounted and keep their parent-shared
410
+ # features, which ACP cannot honour.
411
+ #
412
+ # ACP advertises no start-time capabilities and implements no continuable
413
+ # runs, so `providerName: acp` must not be selected by a tool that needs
414
+ # `agentOptions`, `persona`, `toolFilter`, a numeric `maxDepth`, or
415
+ # `backgroundMode: continuable`.
416
+ - id: subagent-acp
417
+ name: '@deepseek-ai/dsh-subagent-acp'
418
+ config:
419
+ providerName: acp
420
+ command: !!js process.env.OMDSH_ACP_COMMAND || 'dsh'
421
+ args: !!js (process.env.OMDSH_ACP_ARGS || '--profile acp').split(' ')
422
+ permission: allow
423
+ # The child boots its own profile, so it gets its own home. Leaving the
424
+ # parent's home visible would let the child read the parent's profiles
425
+ # and credentials, and a composition that also delegated by ACP would
426
+ # recurse.
427
+ env:
428
+ DSH_HOME: !!js (process.env.OMDSH_HOME || process.env.DSH_HOME || process.env.HOME + '/.dsh') + '/acp-child'
429
+ OMDSH_HOME: !!js process.env.OMDSH_HOME || process.env.DSH_HOME || undefined
430
+ OMDSH_DEEPSEEK_API_KEY: !!js process.env.OMDSH_DEEPSEEK_API_KEY || undefined
431
+ DEEPSEEK_API_KEY: !!js process.env.DEEPSEEK_API_KEY || process.env.OMDSH_DEEPSEEK_API_KEY || undefined
432
+
306
433
  - id: subagent-control
307
434
  name: '@deepseek-ai/dsh-tool-subagent-control'
308
435
 
@@ -316,10 +443,68 @@
316
443
  toolName: subagent
317
444
  backgroundMode: continuable
318
445
 
446
+ - id: tool-subagent-fork
447
+ name: '@deepseek-ai/dsh-tool-subagent'
448
+ config:
449
+ provider: fork
450
+ toolName: subagent_fork
451
+ backgroundMode: continuable
452
+
453
+ # The isolated delegation tool. It is a second `dsh-tool-subagent` over the
454
+ # out-of-process backend, so a caller chooses isolation per delegation
455
+ # instead of trading the parent-shared features away globally.
456
+ #
457
+ # Three settings are forced by ACP's absent capabilities, not preferences:
458
+ # - `maxDepth: provider-managed` — a numeric cap is refused because the
459
+ # provider cannot enforce recursion depth across a process boundary, and
460
+ # the child's own composition already bounds it.
461
+ # - `backgroundMode: one-shot` — the published ACP provider implements no
462
+ # `prepareContinuable`, so a continuable run is refused at mount.
463
+ # - no `agentOptions`/`persona`/`toolFilter` — all three are refused.
464
+ # The consequence is user-visible: an isolated child cannot be steered or
465
+ # followed up after dispatch. Use `subagent` when that matters.
466
+ - id: tool-subagent-isolated
467
+ name: '@deepseek-ai/dsh-tool-subagent'
468
+ config:
469
+ provider: acp
470
+ toolName: subagent_isolated
471
+ backgroundMode: one-shot
472
+ maxDepth: provider-managed
473
+
474
+ # Workflow and Ralph, as the upstream base bundle mounts them.
475
+ #
476
+ # The worker-thread engine is the seam provider: `dsh-workflow-worker-thread`
477
+ # executes model-written orchestration scripts off the host event loop, which
478
+ # is the same isolation the ACP subagent transport buys for delegation.
479
+ # Mounting `dsh-workflow` as well would double-register `workflowEngine`, so
480
+ # it stays a dependency the engine resolves rather than a composition row.
481
+ - id: workflow-worker-thread
482
+ name: '@deepseek-ai/dsh-workflow-worker-thread'
483
+ config:
484
+ provider: spawn
485
+
486
+ # `toolName` is renamed because omdsh already owns a `/workflow` slash command
487
+ # that switches the Default/Plan workflow. The two live in different
488
+ # namespaces (tool vs command) and never collide at runtime, but a bare
489
+ # `workflow` entry in `/tools` would read as that command.
490
+ - id: tool-workflow
491
+ name: '@deepseek-ai/dsh-tool-workflow'
492
+ config:
493
+ toolName: workflow_run
494
+
495
+ # Ralph iterates fresh agents over a build-time-fixed script; it reuses the
496
+ # continuable in-process `spawn` provider, so it depends on that transport
497
+ # staying mounted.
498
+ - id: tool-ralph
499
+ name: '@deepseek-ai/dsh-tool-ralph'
500
+ config:
501
+ subagentProvider: spawn
502
+ maxRounds: 64
503
+
319
504
  - id: tui
320
505
  name: '@agi-fans/dsh-tui'
321
506
  config:
322
- model: !!js process.env.OMDSH_MODEL || 'deepseek-v4-flash'
507
+ model: !!js process.env.OMDSH_MODEL || 'deepseek-flash'
323
508
 
324
509
  - id: agent-behavior
325
510
  name: '@agi-fans/oh-my-dsh/agent-behavior'
@@ -354,12 +539,18 @@
354
539
  - id: tui-command-export
355
540
  name: '@agi-fans/dsh-tui/command-export'
356
541
 
542
+ - id: tui-command-diff
543
+ name: '@agi-fans/dsh-tui/command-diff'
544
+
357
545
  - id: tui-command-trajectory
358
546
  name: '@agi-fans/dsh-tui/command-trajectory'
359
547
 
360
548
  - id: tui-command-integrations
361
549
  name: '@agi-fans/dsh-tui/command-integrations'
362
550
 
551
+ - id: tui-command-jobs
552
+ name: '@agi-fans/dsh-tui/command-jobs'
553
+
363
554
  - id: tui-startup-notices
364
555
  name: '@agi-fans/dsh-tui/startup-notices'
365
556
 
package/lib/args.js CHANGED
@@ -26,7 +26,7 @@ Usage:
26
26
  omdsh completions bash|zsh|fish
27
27
 
28
28
  Options:
29
- --model <name> model route (default deepseek-v4-flash)
29
+ --model <name> model route (default deepseek-flash)
30
30
  --provider <name> provider route (default deepseek-official)
31
31
  -r, --resume <id> resume a durable session
32
32
  --dump-config print the composed plugin tree and exit
package/lib/boot.js CHANGED
@@ -9,7 +9,7 @@ import { provideCmdline } from '@deepseek-ai/dsh-cmdline';
9
9
  import { DSH_LAUNCH_ENVIRONMENT_KEY } from '@deepseek-ai/dsh-launch-environment';
10
10
  import { NAME, prepareLaunchEnvironment } from "./composition.js";
11
11
  import { composeLaunch, INSTALL_ANCHOR } from "./profile.js";
12
- import { omdshHome } from "./mcp-config.js";
12
+ import { omdshHome } from "./config-paths.js";
13
13
  import { createProcessShutdown } from "./process-shutdown.js";
14
14
  export { NAME } from "./composition.js";
15
15
  /**
@@ -21,9 +21,7 @@ export { NAME } from "./composition.js";
21
21
  export async function runOmdsh(prompt, resume) {
22
22
  const app = {};
23
23
  const shutdown = createProcessShutdown(async () => { await app.current?.fiber.dispose(); });
24
- const signalShutdown = new AbortController();
25
24
  const interrupt = (code) => {
26
- signalShutdown.abort();
27
25
  shutdown.interrupt(code);
28
26
  };
29
27
  // SIGINT only fires outside raw mode (a raw tty delivers Ctrl-C as a
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Shared discovery paths for omdsh's native configuration adapters: the user
3
+ * directory (`$OMDSH_HOME` / `$DSH_HOME`, else `~/.dsh`) and the project root a
4
+ * `.dsh/` directory belongs to.
5
+ * @module @agi-fans/oh-my-dsh
6
+ */
7
+ /** Resolve the native user-level configuration directory. */
8
+ export declare function omdshHome(environment?: NodeJS.ProcessEnv): string;
9
+ /** Nearest ancestor holding `.git`, else the resolved cwd. */
10
+ export declare function projectRoot(cwd: string): string;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Shared discovery paths for omdsh's native configuration adapters: the user
3
+ * directory (`$OMDSH_HOME` / `$DSH_HOME`, else `~/.dsh`) and the project root a
4
+ * `.dsh/` directory belongs to.
5
+ * @module @agi-fans/oh-my-dsh
6
+ */
7
+ import { existsSync } from 'node:fs';
8
+ import { homedir } from 'node:os';
9
+ import { dirname, isAbsolute, join, resolve } from 'node:path';
10
+ /** Resolve the native user-level configuration directory. */
11
+ export function omdshHome(environment = process.env) {
12
+ const configured = environment.OMDSH_HOME?.trim() || environment.DSH_HOME?.trim();
13
+ return configured === undefined
14
+ ? join(homedir(), '.dsh')
15
+ : (isAbsolute(configured) ? configured : resolve(configured));
16
+ }
17
+ /** Nearest ancestor holding `.git`, else the resolved cwd. */
18
+ export function projectRoot(cwd) {
19
+ const fallback = resolve(cwd);
20
+ let current = fallback;
21
+ for (;;) {
22
+ if (existsSync(join(current, '.git')))
23
+ return current;
24
+ const parent = dirname(current);
25
+ if (parent === current)
26
+ return fallback;
27
+ current = parent;
28
+ }
29
+ }
30
+ //# sourceMappingURL=config-paths.js.map
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Native omdsh language-server configuration adapter.
3
+ *
4
+ * This module owns only deployment discovery: it translates a `servers` JSON
5
+ * shape into the three Harness rows a language server needs — the `dsh-lsp`
6
+ * seam, the `dsh-lsp-stdio` host, and the model-facing `dsh-tool-lsp` tool.
7
+ * Server process lifecycle, protocol framing, and result normalization remain
8
+ * owned by the Harness packages. Nothing is mounted when no server is
9
+ * configured, so a composition without language servers never advertises an
10
+ * `lsp` tool that can only fail.
11
+ * @module @agi-fans/oh-my-dsh
12
+ */
13
+ export interface LspPluginRow {
14
+ id: string;
15
+ name: string;
16
+ config?: Record<string, unknown>;
17
+ }
18
+ export interface LspInsertPatch {
19
+ insert: LspPluginRow[];
20
+ }
21
+ /**
22
+ * Load user and project language-server definitions and turn them into Loader
23
+ * insert patches. Project definitions override same-named user definitions.
24
+ * All three rows are emitted together or not at all: the seam and tool without
25
+ * a provider would advertise an `lsp` tool whose every call fails.
26
+ */
27
+ export declare function loadLspPatches(cwd?: string, environment?: NodeJS.ProcessEnv): LspInsertPatch[];
@@ -0,0 +1,147 @@
1
+ /**
2
+ * Native omdsh language-server configuration adapter.
3
+ *
4
+ * This module owns only deployment discovery: it translates a `servers` JSON
5
+ * shape into the three Harness rows a language server needs — the `dsh-lsp`
6
+ * seam, the `dsh-lsp-stdio` host, and the model-facing `dsh-tool-lsp` tool.
7
+ * Server process lifecycle, protocol framing, and result normalization remain
8
+ * owned by the Harness packages. Nothing is mounted when no server is
9
+ * configured, so a composition without language servers never advertises an
10
+ * `lsp` tool that can only fail.
11
+ * @module @agi-fans/oh-my-dsh
12
+ */
13
+ import { existsSync, readFileSync } from 'node:fs';
14
+ import { join } from 'node:path';
15
+ import { omdshHome, projectRoot } from "./config-paths.js";
16
+ function configError(path, detail) {
17
+ return new Error(`omdsh: invalid LSP config ${path}: ${detail}`);
18
+ }
19
+ function object(value) {
20
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
21
+ }
22
+ function readDocument(path) {
23
+ if (!existsSync(path))
24
+ return undefined;
25
+ let parsed;
26
+ try {
27
+ parsed = JSON.parse(readFileSync(path, 'utf8'));
28
+ }
29
+ catch (error) {
30
+ throw configError(path, error instanceof Error ? error.message : String(error));
31
+ }
32
+ if (!object(parsed) || !object(parsed.servers)) {
33
+ throw configError(path, 'expected an object with a "servers" object');
34
+ }
35
+ return { servers: parsed.servers };
36
+ }
37
+ function stringArray(value, path, field) {
38
+ if (value === undefined)
39
+ return undefined;
40
+ if (!Array.isArray(value) || value.some(item => typeof item !== 'string')) {
41
+ throw configError(path, `"${field}" must be an array of strings`);
42
+ }
43
+ return value;
44
+ }
45
+ function stringRecord(value, path, field) {
46
+ if (value === undefined)
47
+ return undefined;
48
+ if (!object(value) || Object.values(value).some(item => typeof item !== 'string')) {
49
+ throw configError(path, `"${field}" must be an object of string values`);
50
+ }
51
+ return value;
52
+ }
53
+ function optionalBoolean(value, path, field) {
54
+ if (value === undefined)
55
+ return undefined;
56
+ if (typeof value !== 'boolean')
57
+ throw configError(path, `"${field}" must be a boolean`);
58
+ return value;
59
+ }
60
+ /** Lowercase leading-dot extension → LSP language id, as the stdio host requires. */
61
+ function extensionToLanguage(value, path, field) {
62
+ if (!object(value))
63
+ throw configError(path, `"${field}" must be an object of extension-to-language entries`);
64
+ const entries = Object.entries(value);
65
+ if (entries.length === 0)
66
+ throw configError(path, `"${field}" must map at least one extension`);
67
+ for (const [extension, language] of entries) {
68
+ if (!/^\.[a-z0-9]+$/u.test(extension)) {
69
+ throw configError(path, `"${field}.${extension}" must be a lowercase leading-dot extension`);
70
+ }
71
+ if (typeof language !== 'string' || language === '') {
72
+ throw configError(path, `"${field}.${extension}" must name a non-empty language id`);
73
+ }
74
+ }
75
+ return value;
76
+ }
77
+ function expandEnvironment(value, environment) {
78
+ if (typeof value === 'string') {
79
+ return value.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)(?::-([^}]*))?\}/gu, (token, name, fallback) => environment[name] ?? fallback ?? token);
80
+ }
81
+ if (Array.isArray(value))
82
+ return value.map(item => expandEnvironment(item, environment));
83
+ if (!object(value))
84
+ return value;
85
+ return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, expandEnvironment(item, environment)]));
86
+ }
87
+ function serverConfig(name, raw, path, environment) {
88
+ if (!/^[A-Za-z0-9_-]{1,32}$/u.test(name)) {
89
+ throw configError(path, `server name "${name}" must match [A-Za-z0-9_-]{1,32}`);
90
+ }
91
+ const value = expandEnvironment(raw, environment);
92
+ if (!object(value))
93
+ throw configError(path, `server "${name}" must be an object`);
94
+ if (optionalBoolean(value.enabled, path, `${name}.enabled`) === false)
95
+ return undefined;
96
+ const command = value.command;
97
+ if (typeof command !== 'string' || command === '') {
98
+ throw configError(path, `server "${name}" requires a non-empty "command"`);
99
+ }
100
+ const args = stringArray(value.args, path, `${name}.args`);
101
+ const env = stringRecord(value.env, path, `${name}.env`);
102
+ const languages = extensionToLanguage(value.extensionToLanguage, path, `${name}.extensionToLanguage`);
103
+ return {
104
+ command,
105
+ ...(args === undefined ? {} : { args }),
106
+ ...(env === undefined ? {} : { env }),
107
+ extensionToLanguage: languages,
108
+ ...(value.initializationOptions === undefined ? {} : { initializationOptions: value.initializationOptions }),
109
+ ...(value.configuration === undefined ? {} : { configuration: value.configuration }),
110
+ };
111
+ }
112
+ /**
113
+ * Load user and project language-server definitions and turn them into Loader
114
+ * insert patches. Project definitions override same-named user definitions.
115
+ * All three rows are emitted together or not at all: the seam and tool without
116
+ * a provider would advertise an `lsp` tool whose every call fails.
117
+ */
118
+ export function loadLspPatches(cwd = process.cwd(), environment = process.env) {
119
+ const files = [
120
+ join(omdshHome(environment), 'lsp.json'),
121
+ join(projectRoot(cwd), '.dsh', 'lsp.json'),
122
+ ];
123
+ const merged = new Map();
124
+ for (const path of files) {
125
+ const document = readDocument(path);
126
+ if (document === undefined)
127
+ continue;
128
+ for (const [name, value] of Object.entries(document.servers))
129
+ merged.set(name, { value, path });
130
+ }
131
+ const servers = {};
132
+ for (const [name, source] of merged) {
133
+ const config = serverConfig(name, source.value, source.path, environment);
134
+ if (config !== undefined)
135
+ servers[name] = config;
136
+ }
137
+ if (Object.keys(servers).length === 0)
138
+ return [];
139
+ return [{
140
+ insert: [
141
+ { id: 'lsp', name: '@deepseek-ai/dsh-lsp' },
142
+ { id: 'lsp-stdio', name: '@deepseek-ai/dsh-lsp-stdio', config: { servers } },
143
+ { id: 'tool-lsp', name: '@deepseek-ai/dsh-tool-lsp' },
144
+ ],
145
+ }];
146
+ }
147
+ //# sourceMappingURL=lsp-config.js.map
@@ -15,8 +15,6 @@ export interface McpPluginRow {
15
15
  export interface McpInsertPatch {
16
16
  insert: McpPluginRow[];
17
17
  }
18
- /** Resolve the native user-level MCP document. */
19
- export declare function omdshHome(environment?: NodeJS.ProcessEnv): string;
20
18
  /**
21
19
  * Load user and project MCP definitions and turn them into Loader insert
22
20
  * patches. Project definitions override same-named user definitions.
package/lib/mcp-config.js CHANGED
@@ -8,8 +8,8 @@
8
8
  * @module @agi-fans/oh-my-dsh
9
9
  */
10
10
  import { existsSync, readFileSync } from 'node:fs';
11
- import { homedir } from 'node:os';
12
- import { dirname, isAbsolute, join, resolve } from 'node:path';
11
+ import { join } from 'node:path';
12
+ import { omdshHome, projectRoot } from "./config-paths.js";
13
13
  function configError(path, detail) {
14
14
  return new Error(`omdsh: invalid MCP config ${path}: ${detail}`);
15
15
  }
@@ -129,25 +129,6 @@ function serverConfig(name, raw, path, environment) {
129
129
  function safeId(name) {
130
130
  return 'mcp-' + name;
131
131
  }
132
- /** Resolve the native user-level MCP document. */
133
- export function omdshHome(environment = process.env) {
134
- const configured = environment.OMDSH_HOME?.trim() || environment.DSH_HOME?.trim();
135
- return configured === undefined
136
- ? join(homedir(), '.dsh')
137
- : (isAbsolute(configured) ? configured : resolve(configured));
138
- }
139
- function projectRoot(cwd) {
140
- const fallback = resolve(cwd);
141
- let current = fallback;
142
- for (;;) {
143
- if (existsSync(join(current, '.git')))
144
- return current;
145
- const parent = dirname(current);
146
- if (parent === current)
147
- return fallback;
148
- current = parent;
149
- }
150
- }
151
132
  /**
152
133
  * Load user and project MCP definitions and turn them into Loader insert
153
134
  * patches. Project definitions override same-named user definitions.
package/lib/plugin.js CHANGED
@@ -13,7 +13,7 @@ import { createRequire } from 'node:module';
13
13
  import { existsSync, readFileSync } from 'node:fs';
14
14
  import { dirname, join, resolve } from 'node:path';
15
15
  import { readProfileManifest, resolveBundleDir, resolveProfileDir, writeProfileManifest, } from '@deepseek-ai/dsh-app-boot';
16
- import { omdshHome } from "./mcp-config.js";
16
+ import { omdshHome } from "./config-paths.js";
17
17
  import { ensureOmdshProfile, INSTALL_ANCHOR, NAME, PRODUCT_BUNDLE, PROFILE_NAME, } from "./profile.js";
18
18
  export const PLUGIN_USAGE = `
19
19
  omdsh plugin — install DSH bundles into the omdsh Profile
package/lib/profile.d.ts CHANGED
@@ -47,7 +47,7 @@ export interface LaunchComposition {
47
47
  export declare function agentPresetsOverlay(layerPatches: readonly PatchOptions[][]): PatchOptions | undefined;
48
48
  /**
49
49
  * Compose the live launch layers in product → user bundles → Profile patch
50
- * → home patch → MCP → agent-presets overlay order.
50
+ * → home patch → MCP → LSP → agent-presets overlay order.
51
51
  */
52
52
  export declare function composeLaunch(cwd?: string, environment?: NodeJS.ProcessEnv, options?: {
53
53
  userLayer?: boolean;
package/lib/profile.js CHANGED
@@ -10,7 +10,9 @@ import { existsSync, writeFileSync } from 'node:fs';
10
10
  import { join } from 'node:path';
11
11
  import { fileURLToPath } from 'node:url';
12
12
  import { composeEntries, initProfile, loadOptionalPatches, loadProfile, PROFILE_PATCH_FILENAME, readProfileManifest, resolveProfileDir, writeProfileManifest, } from '@deepseek-ai/dsh-app-boot';
13
- import { loadMcpPatches, omdshHome } from "./mcp-config.js";
13
+ import { omdshHome } from "./config-paths.js";
14
+ import { loadLspPatches } from "./lsp-config.js";
15
+ import { loadMcpPatches } from "./mcp-config.js";
14
16
  export const NAME = 'omdsh';
15
17
  export const PROFILE_NAME = 'omdsh';
16
18
  export const PRODUCT_BUNDLE = '@agi-fans/oh-my-dsh';
@@ -84,7 +86,7 @@ export function agentPresetsOverlay(layerPatches) {
84
86
  }
85
87
  /**
86
88
  * Compose the live launch layers in product → user bundles → Profile patch
87
- * → home patch → MCP → agent-presets overlay order.
89
+ * → home patch → MCP → LSP → agent-presets overlay order.
88
90
  */
89
91
  export function composeLaunch(cwd = process.cwd(), environment = process.env, options = {}) {
90
92
  const userLayer = options.userLayer !== false;
@@ -103,6 +105,9 @@ export function composeLaunch(cwd = process.cwd(), environment = process.env, op
103
105
  const mcp = loadMcpPatches(cwd, environment);
104
106
  if (mcp.length > 0)
105
107
  layers.push({ label: 'mcp.json', patches: mcp });
108
+ const lsp = loadLspPatches(cwd, environment);
109
+ if (lsp.length > 0)
110
+ layers.push({ label: 'lsp.json', patches: lsp });
106
111
  const overlay = agentPresetsOverlay(layers.map(layer => layer.patches));
107
112
  if (overlay !== undefined)
108
113
  layers.push({ label: 'agent-presets', patches: [overlay] });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@agi-fans/oh-my-dsh",
3
3
  "description": "omdsh: a keyboard-first DeepSeek TUI coding agent on the DeepSeek Harness runtime",
4
- "version": "0.14.0",
4
+ "version": "0.16.0",
5
5
  "homepage": "https://omdsh.agi.fans/",
6
6
  "keywords": [
7
7
  "omdsh",
@@ -51,83 +51,112 @@
51
51
  "dependencies": {
52
52
  "@deepseek-ai/cordis-plugin-loader": "1.0.3",
53
53
  "@deepseek-ai/cordis-plugin-timer": "1.1.4",
54
- "@deepseek-ai/dsh-agent": "0.1.2-rc.1",
55
- "@deepseek-ai/dsh-agent-default-model": "0.1.2-rc.1",
56
- "@deepseek-ai/dsh-agent-instructions": "0.1.2-rc.1",
57
- "@deepseek-ai/dsh-agent-loop": "0.1.2-rc.1",
58
- "@deepseek-ai/dsh-agent-presets": "0.1.2-rc.1",
59
- "@deepseek-ai/dsh-app-boot": "0.1.2-rc.1",
60
- "@deepseek-ai/dsh-attachment-local": "0.1.2-rc.1",
61
- "@deepseek-ai/dsh-authorization": "0.1.2-rc.1",
62
- "@deepseek-ai/dsh-bash-sandbox": "0.1.2-rc.1",
63
- "@deepseek-ai/dsh-cmdline": "0.1.2-rc.1",
64
- "@deepseek-ai/dsh-code-runtime-worker-thread": "0.1.2-rc.1",
65
- "@deepseek-ai/dsh-command-compact": "0.1.2-rc.1",
66
- "@deepseek-ai/dsh-command-goal": "0.1.2-rc.1",
67
- "@deepseek-ai/dsh-commands": "0.1.2-rc.1",
68
- "@deepseek-ai/dsh-compaction-basic": "0.1.2-rc.1",
69
- "@deepseek-ai/dsh-cordis-host-runner": "0.1.2-rc.1",
70
- "@deepseek-ai/dsh-credentials-local": "0.1.2-rc.1",
71
- "@deepseek-ai/dsh-file-reference": "0.1.2-rc.1",
72
- "@deepseek-ai/dsh-file-reference-local": "0.1.2-rc.1",
73
- "@deepseek-ai/dsh-fs-local": "0.1.2-rc.1",
74
- "@deepseek-ai/dsh-fs-observation-policy": "0.1.2-rc.1",
75
- "@deepseek-ai/dsh-goal": "0.1.2-rc.1",
76
- "@deepseek-ai/dsh-goal-round-driver": "0.1.2-rc.1",
77
- "@deepseek-ai/dsh-invariants": "0.1.2-rc.1",
78
- "@deepseek-ai/dsh-jobs-local": "0.1.2-rc.1",
79
- "@deepseek-ai/dsh-launch-environment": "0.1.2-rc.1",
80
- "@deepseek-ai/dsh-llm": "0.1.2-rc.1",
81
- "@deepseek-ai/dsh-llm-deepseek": "0.1.2-rc.1",
82
- "@deepseek-ai/dsh-llm-pi-ai": "0.1.2-rc.1",
83
- "@deepseek-ai/dsh-llm-retry": "0.1.2-rc.1",
84
- "@deepseek-ai/dsh-mcp-client": "0.1.2-rc.1",
85
- "@deepseek-ai/dsh-permission-presets": "0.1.2-rc.1",
86
- "@deepseek-ai/dsh-persona": "0.1.2-rc.1",
87
- "@deepseek-ai/dsh-plan-mode": "0.1.2-rc.1",
88
- "@deepseek-ai/dsh-sandbox-local": "0.1.2-rc.1",
89
- "@deepseek-ai/dsh-sandbox-policy": "0.1.2-rc.1",
90
- "@deepseek-ai/dsh-scope": "0.1.2-rc.1",
91
- "@deepseek-ai/dsh-session": "0.1.2-rc.1",
92
- "@deepseek-ai/dsh-session-checkpoint-policy": "0.1.2-rc.1",
93
- "@deepseek-ai/dsh-session-persistence-jsonl": "0.1.2-rc.1",
94
- "@deepseek-ai/dsh-session-projection": "0.1.2-rc.1",
95
- "@deepseek-ai/dsh-session-query": "0.1.2-rc.1",
96
- "@deepseek-ai/dsh-session-query-sqlite": "0.1.2-rc.1",
97
- "@deepseek-ai/dsh-session-reference": "0.1.2-rc.1",
98
- "@deepseek-ai/dsh-session-stats": "0.1.2-rc.1",
99
- "@deepseek-ai/dsh-session-title": "0.1.2-rc.1",
100
- "@deepseek-ai/dsh-settings": "0.1.2-rc.1",
101
- "@deepseek-ai/dsh-settings-file": "0.1.2-rc.1",
102
- "@deepseek-ai/dsh-shell-env": "0.1.2-rc.1",
103
- "@deepseek-ai/dsh-skill": "0.1.2-rc.1",
104
- "@deepseek-ai/dsh-skill-filesystem": "0.1.2-rc.1",
105
- "@deepseek-ai/dsh-subagent": "0.1.2-rc.1",
106
- "@deepseek-ai/dsh-subagent-spawn-in-process": "0.1.2-rc.1",
107
- "@deepseek-ai/dsh-subprocess-local": "0.1.2-rc.1",
108
- "@deepseek-ai/dsh-system-prompt": "0.1.2-rc.1",
109
- "@deepseek-ai/dsh-terminal": "0.1.2-rc.1",
110
- "@deepseek-ai/dsh-terminal-bash": "0.1.2-rc.1",
111
- "@deepseek-ai/dsh-token-meter": "0.1.2-rc.1",
112
- "@deepseek-ai/dsh-tool-ask-user": "0.1.2-rc.1",
113
- "@deepseek-ai/dsh-tool-bash": "0.1.2-rc.1",
114
- "@deepseek-ai/dsh-tool-bash-persistent": "0.1.2-rc.1",
115
- "@deepseek-ai/dsh-tool-cordis": "0.1.2-rc.1",
116
- "@deepseek-ai/dsh-tool-fs": "0.1.2-rc.1",
117
- "@deepseek-ai/dsh-tool-fs-search": "0.1.2-rc.1",
118
- "@deepseek-ai/dsh-tool-goal": "0.1.2-rc.1",
119
- "@deepseek-ai/dsh-tool-jobs": "0.1.2-rc.1",
120
- "@deepseek-ai/dsh-tool-skill": "0.1.2-rc.1",
121
- "@deepseek-ai/dsh-tool-str-replace-editor": "0.1.2-rc.1",
122
- "@deepseek-ai/dsh-tool-subagent": "0.1.2-rc.1",
123
- "@deepseek-ai/dsh-tool-subagent-control": "0.1.2-rc.1",
124
- "@deepseek-ai/dsh-tool-todo": "0.1.2-rc.1",
125
- "@deepseek-ai/dsh-tools": "0.1.2-rc.1",
126
- "@deepseek-ai/dsh-user-approval": "0.1.2-rc.1",
127
- "@deepseek-ai/dsh-user-questions": "0.1.2-rc.1",
54
+ "@deepseek-ai/dsh-agent": "0.1.5-rc.2",
55
+ "@deepseek-ai/dsh-agent-default-model": "0.1.5-rc.2",
56
+ "@deepseek-ai/dsh-agent-instructions": "0.1.5-rc.2",
57
+ "@deepseek-ai/dsh-agent-loop": "0.1.5-rc.2",
58
+ "@deepseek-ai/dsh-agent-presets": "0.1.5-rc.2",
59
+ "@deepseek-ai/dsh-app-boot": "0.1.5-rc.2",
60
+ "@deepseek-ai/dsh-attachment-local": "0.1.5-rc.2",
61
+ "@deepseek-ai/dsh-authorization": "0.1.5-rc.2",
62
+ "@deepseek-ai/dsh-bash-sandbox": "0.1.5-rc.2",
63
+ "@deepseek-ai/dsh-cmdline": "0.1.5-rc.2",
64
+ "@deepseek-ai/dsh-code-runtime-worker-thread": "0.1.5-rc.2",
65
+ "@deepseek-ai/dsh-command-compact": "0.1.5-rc.2",
66
+ "@deepseek-ai/dsh-command-goal": "0.1.5-rc.2",
67
+ "@deepseek-ai/dsh-commands": "0.1.5-rc.2",
68
+ "@deepseek-ai/dsh-compaction-basic": "0.1.5-rc.2",
69
+ "@deepseek-ai/dsh-compaction-tool-result-pruner": "0.1.5-rc.2",
70
+ "@deepseek-ai/dsh-cordis-host-runner": "0.1.5-rc.2",
71
+ "@deepseek-ai/dsh-credentials-local": "0.1.5-rc.2",
72
+ "@deepseek-ai/dsh-file-reference": "0.1.5-rc.2",
73
+ "@deepseek-ai/dsh-file-reference-local": "0.1.5-rc.2",
74
+ "@deepseek-ai/dsh-fs-local": "0.1.5-rc.2",
75
+ "@deepseek-ai/dsh-fs-observation-policy": "0.1.5-rc.2",
76
+ "@deepseek-ai/dsh-fs-sandbox": "0.1.5-rc.2",
77
+ "@deepseek-ai/dsh-goal": "0.1.5-rc.2",
78
+ "@deepseek-ai/dsh-goal-round-driver": "0.1.5-rc.2",
79
+ "@deepseek-ai/dsh-http-proxy": "0.1.5-rc.2",
80
+ "@deepseek-ai/dsh-invariants": "0.1.5-rc.2",
81
+ "@deepseek-ai/dsh-jobs-local": "0.1.5-rc.2",
82
+ "@deepseek-ai/dsh-launch-environment": "0.1.5-rc.2",
83
+ "@deepseek-ai/dsh-llm": "0.1.5-rc.2",
84
+ "@deepseek-ai/dsh-llm-deepseek": "0.1.5-rc.2",
85
+ "@deepseek-ai/dsh-llm-pi-ai": "0.1.5-rc.2",
86
+ "@deepseek-ai/dsh-llm-retry": "0.1.5-rc.2",
87
+ "@deepseek-ai/dsh-lsp": "0.1.5-rc.2",
88
+ "@deepseek-ai/dsh-lsp-stdio": "0.1.5-rc.2",
89
+ "@deepseek-ai/dsh-mcp-client": "0.1.5-rc.2",
90
+ "@deepseek-ai/dsh-output-retention": "0.1.5-rc.2",
91
+ "@deepseek-ai/dsh-permission-presets": "0.1.5-rc.2",
92
+ "@deepseek-ai/dsh-persona": "0.1.5-rc.2",
93
+ "@deepseek-ai/dsh-plan-mode": "0.1.5-rc.2",
94
+ "@deepseek-ai/dsh-pwsh-local": "0.1.5-rc.2",
95
+ "@deepseek-ai/dsh-pwsh-sandbox": "0.1.5-rc.2",
96
+ "@deepseek-ai/dsh-repeat-tool-reminder": "0.1.5-rc.2",
97
+ "@deepseek-ai/dsh-sandbox-local": "0.1.5-rc.2",
98
+ "@deepseek-ai/dsh-sandbox-policy": "0.1.5-rc.2",
99
+ "@deepseek-ai/dsh-scope": "0.1.5-rc.2",
100
+ "@deepseek-ai/dsh-session": "0.1.5-rc.2",
101
+ "@deepseek-ai/dsh-session-checkpoint-policy": "0.1.5-rc.2",
102
+ "@deepseek-ai/dsh-session-persistence-jsonl": "0.1.5-rc.2",
103
+ "@deepseek-ai/dsh-session-projection": "0.1.5-rc.2",
104
+ "@deepseek-ai/dsh-session-query": "0.1.5-rc.2",
105
+ "@deepseek-ai/dsh-session-query-sqlite": "0.1.5-rc.2",
106
+ "@deepseek-ai/dsh-session-reference": "0.1.5-rc.2",
107
+ "@deepseek-ai/dsh-session-stats": "0.1.5-rc.2",
108
+ "@deepseek-ai/dsh-session-title": "0.1.5-rc.2",
109
+ "@deepseek-ai/dsh-settings": "0.1.5-rc.2",
110
+ "@deepseek-ai/dsh-settings-file": "0.1.5-rc.2",
111
+ "@deepseek-ai/dsh-shell-env": "0.1.5-rc.2",
112
+ "@deepseek-ai/dsh-skill": "0.1.5-rc.2",
113
+ "@deepseek-ai/dsh-skill-filesystem": "0.1.5-rc.2",
114
+ "@deepseek-ai/dsh-spill": "0.1.5-rc.2",
115
+ "@deepseek-ai/dsh-spill-local": "0.1.5-rc.2",
116
+ "@deepseek-ai/dsh-spill-policy": "0.1.5-rc.2",
117
+ "@deepseek-ai/dsh-subagent": "0.1.5-rc.2",
118
+ "@deepseek-ai/dsh-subagent-acp": "0.1.5-rc.2",
119
+ "@deepseek-ai/dsh-subagent-fork-in-process": "0.1.5-rc.2",
120
+ "@deepseek-ai/dsh-subagent-in-process-driver": "0.1.5-rc.2",
121
+ "@deepseek-ai/dsh-subagent-spawn-in-process": "0.1.5-rc.2",
122
+ "@deepseek-ai/dsh-subprocess-local": "0.1.5-rc.2",
123
+ "@deepseek-ai/dsh-system-prompt": "0.1.5-rc.2",
124
+ "@deepseek-ai/dsh-terminal": "0.1.5-rc.2",
125
+ "@deepseek-ai/dsh-terminal-bash": "0.1.5-rc.2",
126
+ "@deepseek-ai/dsh-timeout": "0.1.5-rc.2",
127
+ "@deepseek-ai/dsh-token-meter": "0.1.5-rc.2",
128
+ "@deepseek-ai/dsh-tool-ask-user": "0.1.5-rc.2",
129
+ "@deepseek-ai/dsh-tool-bash": "0.1.5-rc.2",
130
+ "@deepseek-ai/dsh-tool-bash-persistent": "0.1.5-rc.2",
131
+ "@deepseek-ai/dsh-tool-call-timeout-policy": "0.1.5-rc.2",
132
+ "@deepseek-ai/dsh-tool-cordis": "0.1.5-rc.2",
133
+ "@deepseek-ai/dsh-tool-fs": "0.1.5-rc.2",
134
+ "@deepseek-ai/dsh-tool-fs-search": "0.1.5-rc.2",
135
+ "@deepseek-ai/dsh-tool-goal": "0.1.5-rc.2",
136
+ "@deepseek-ai/dsh-tool-jobs": "0.1.5-rc.2",
137
+ "@deepseek-ai/dsh-tool-lsp": "0.1.5-rc.2",
138
+ "@deepseek-ai/dsh-tool-present": "0.1.5-rc.2",
139
+ "@deepseek-ai/dsh-tool-pwsh": "0.1.5-rc.2",
140
+ "@deepseek-ai/dsh-tool-pwsh-persistent": "0.1.5-rc.2",
141
+ "@deepseek-ai/dsh-tool-ralph": "0.1.5-rc.2",
142
+ "@deepseek-ai/dsh-tool-skill": "0.1.5-rc.2",
143
+ "@deepseek-ai/dsh-tool-str-replace-editor": "0.1.5-rc.2",
144
+ "@deepseek-ai/dsh-tool-subagent": "0.1.5-rc.2",
145
+ "@deepseek-ai/dsh-tool-subagent-control": "0.1.5-rc.2",
146
+ "@deepseek-ai/dsh-tool-terminal": "0.1.5-rc.2",
147
+ "@deepseek-ai/dsh-tool-todo": "0.1.5-rc.2",
148
+ "@deepseek-ai/dsh-tool-web": "0.1.5-rc.2",
149
+ "@deepseek-ai/dsh-tool-workflow": "0.1.5-rc.2",
150
+ "@deepseek-ai/dsh-tools": "0.1.5-rc.2",
151
+ "@deepseek-ai/dsh-user-approval": "0.1.5-rc.2",
152
+ "@deepseek-ai/dsh-user-questions": "0.1.5-rc.2",
153
+ "@deepseek-ai/dsh-web": "0.1.5-rc.2",
154
+ "@deepseek-ai/dsh-web-fetch-http": "0.1.5-rc.2",
155
+ "@deepseek-ai/dsh-workflow": "0.1.5-rc.2",
156
+ "@deepseek-ai/dsh-workflow-worker-thread": "0.1.5-rc.2",
128
157
  "@deepseek-ai/schemastery": "3.18.2",
129
158
  "node-addon-require-builtin": "0.1.4",
130
- "@agi-fans/dsh-tui": "^0.14.0"
159
+ "@agi-fans/dsh-tui": "^0.16.0"
131
160
  },
132
161
  "peerDependencies": {
133
162
  "@deepseek-ai/cordis": "^4.0.2"