@agi-fans/oh-my-dsh 0.13.0 → 0.15.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,12 +101,13 @@
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'
107
108
  config:
108
109
  default: standard
110
+ includeShippedRoot: false
109
111
  roots:
110
112
  - path: !!js "process.getBuiltinModule('node:url').fileURLToPath(new URL('./agent-presets/', baseUrl))"
111
113
  trust: system
@@ -133,7 +135,7 @@
133
135
  workspaceRoot: !!js process.cwd()
134
136
 
135
137
  - id: fs
136
- name: '@deepseek-ai/dsh-fs-local'
138
+ name: '@deepseek-ai/dsh-fs-sandbox'
137
139
 
138
140
  - id: fs-observation-policy
139
141
  name: '@deepseek-ai/dsh-fs-observation-policy'
@@ -141,8 +143,23 @@
141
143
  - id: subprocess
142
144
  name: '@deepseek-ai/dsh-subprocess-local'
143
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.
144
152
  - id: bash
145
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
146
163
 
147
164
  - id: permission
148
165
  name: '@deepseek-ai/dsh-permission-presets'
@@ -164,19 +181,95 @@
164
181
  name: Full access
165
182
  description: Full filesystem access without approval prompts.
166
183
 
167
- - id: spine
168
- name: '@deepseek-ai/dsh-agent-spine-demo'
184
+ # — spine 展开块(替代已删除的 @deepseek-ai/dsh-agent-spine-demo)—
185
+ # 顺序遵循上游 spine apply() 的挂载顺序;agent-instructions 必须先于
186
+ # tool-skill 注册(两者都以 session 前缀消息注入,注册顺序即渲染顺序)。
187
+ - id: system-prompt
188
+ name: '@deepseek-ai/dsh-system-prompt'
189
+
190
+ - id: tools
191
+ name: '@deepseek-ai/dsh-tools'
192
+ config:
193
+ mode: native
194
+
195
+ - id: skill
196
+ name: '@deepseek-ai/dsh-skill'
197
+
198
+ - id: skill-filesystem
199
+ name: '@deepseek-ai/dsh-skill-filesystem'
169
200
  config:
170
- workspaceContext:
171
- maxBytes: 65536
172
201
  dshHome: !!js process.env.OMDSH_HOME || undefined
173
- skills:
174
- enabled: true
175
- goals:
176
- domain: {}
177
- tool: {}
178
- tools:
179
- mode: native
202
+
203
+ - id: llm-retry
204
+ name: '@deepseek-ai/dsh-llm-retry'
205
+
206
+ - id: goal
207
+ name: '@deepseek-ai/dsh-goal'
208
+
209
+ - id: tool-goal
210
+ name: '@deepseek-ai/dsh-tool-goal'
211
+
212
+ - id: goal-round-driver
213
+ name: '@deepseek-ai/dsh-goal-round-driver'
214
+
215
+ - id: jobs
216
+ name: '@deepseek-ai/dsh-jobs-local'
217
+
218
+ - id: invariants
219
+ name: '@deepseek-ai/dsh-invariants'
220
+
221
+ - id: session-invariant
222
+ name: '@deepseek-ai/dsh-session/invariant'
223
+
224
+ - id: agent-invariant
225
+ name: '@deepseek-ai/dsh-agent/invariant'
226
+
227
+ - id: scope-invariant
228
+ name: '@deepseek-ai/dsh-scope/invariant'
229
+
230
+ - id: agent-loop-invariant
231
+ name: '@deepseek-ai/dsh-agent-loop/invariant'
232
+
233
+ - id: shell-env
234
+ name: '@deepseek-ai/dsh-shell-env'
235
+ config:
236
+ dshHome: !!js process.env.OMDSH_HOME || undefined
237
+
238
+ - id: tool-bash
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'
245
+
246
+ - id: agent-instructions
247
+ name: '@deepseek-ai/dsh-agent-instructions'
248
+ config:
249
+ maxBytes: 65536
250
+
251
+ - id: tool-skill
252
+ name: '@deepseek-ai/dsh-tool-skill'
253
+
254
+ - id: tool-jobs
255
+ name: '@deepseek-ai/dsh-tool-jobs'
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
+
269
+ - id: agent-loop
270
+ name: '@deepseek-ai/dsh-agent-loop'
271
+ config:
272
+ agents: []
180
273
 
181
274
  - id: code-runtime
182
275
  name: '@deepseek-ai/dsh-code-runtime-worker-thread'
@@ -226,15 +319,72 @@
226
319
  config:
227
320
  maxOutputChars: 16000
228
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
+
229
358
  - id: token-meter
230
359
  name: '@deepseek-ai/dsh-token-meter'
231
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
+
232
371
  - id: compaction
233
372
  name: '@deepseek-ai/dsh-compaction-basic'
234
373
 
235
374
  - id: command-compact
236
375
  name: '@deepseek-ai/dsh-command-compact'
237
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
+
238
388
  - id: subagent
239
389
  name: '@deepseek-ai/dsh-subagent'
240
390
 
@@ -243,6 +393,43 @@
243
393
  config:
244
394
  providerName: spawn
245
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
+
246
433
  - id: subagent-control
247
434
  name: '@deepseek-ai/dsh-tool-subagent-control'
248
435
 
@@ -256,10 +443,68 @@
256
443
  toolName: subagent
257
444
  backgroundMode: continuable
258
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
+
259
504
  - id: tui
260
505
  name: '@agi-fans/dsh-tui'
261
506
  config:
262
- model: !!js process.env.OMDSH_MODEL || 'deepseek-v4-flash'
507
+ model: !!js process.env.OMDSH_MODEL || 'deepseek-flash'
263
508
 
264
509
  - id: agent-behavior
265
510
  name: '@agi-fans/oh-my-dsh/agent-behavior'
@@ -294,12 +539,18 @@
294
539
  - id: tui-command-export
295
540
  name: '@agi-fans/dsh-tui/command-export'
296
541
 
542
+ - id: tui-command-diff
543
+ name: '@agi-fans/dsh-tui/command-diff'
544
+
297
545
  - id: tui-command-trajectory
298
546
  name: '@agi-fans/dsh-tui/command-trajectory'
299
547
 
300
548
  - id: tui-command-integrations
301
549
  name: '@agi-fans/dsh-tui/command-integrations'
302
550
 
551
+ - id: tui-command-jobs
552
+ name: '@agi-fans/dsh-tui/command-jobs'
553
+
303
554
  - id: tui-startup-notices
304
555
  name: '@agi-fans/dsh-tui/startup-notices'
305
556
 
@@ -2,7 +2,6 @@
2
2
  * Product-owned Agent behavior settings projected into the Harness system prompt.
3
3
  * @module @agi-fans/oh-my-dsh/agent-behavior
4
4
  */
5
- import { settingsNamespace } from '@deepseek-ai/dsh-settings';
6
5
  import z from '@deepseek-ai/schemastery';
7
6
  export const name = 'omdsh-agent-behavior';
8
7
  export const inject = ['settings', 'systemPrompt'];
@@ -46,7 +45,7 @@ export class AgentBehaviorPrompt {
46
45
  }
47
46
  }
48
47
  export function apply(ctx) {
49
- const scope = ctx.settings.register(settingsNamespace(AGENT_BEHAVIOR_SETTINGS_NAMESPACE), AgentBehaviorSettingsSchema, { applies: 'live' });
48
+ const scope = ctx.settings.register(AGENT_BEHAVIOR_SETTINGS_NAMESPACE, AgentBehaviorSettingsSchema, { applies: 'live' });
50
49
  const prompt = new AgentBehaviorPrompt();
51
50
  ctx.on('agent/pre-step', async (payload, next) => {
52
51
  prompt.snapshot(payload.agent, payload.turn, scope.get().language);
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
@@ -4,11 +4,12 @@
4
4
  * before any entry mounts.
5
5
  * @module @agi-fans/oh-my-dsh
6
6
  */
7
- import { boot, installFailLoud } from '@deepseek-ai/dsh-app-boot';
7
+ import { boot, healProfilesModuleFallback, installFailLoud } from '@deepseek-ai/dsh-app-boot';
8
8
  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
- import { composeLaunch } from "./profile.js";
11
+ import { composeLaunch, INSTALL_ANCHOR } from "./profile.js";
12
+ import { omdshHome } from "./config-paths.js";
12
13
  import { createProcessShutdown } from "./process-shutdown.js";
13
14
  export { NAME } from "./composition.js";
14
15
  /**
@@ -20,9 +21,7 @@ export { NAME } from "./composition.js";
20
21
  export async function runOmdsh(prompt, resume) {
21
22
  const app = {};
22
23
  const shutdown = createProcessShutdown(async () => { await app.current?.fiber.dispose(); });
23
- const signalShutdown = new AbortController();
24
24
  const interrupt = (code) => {
25
- signalShutdown.abort();
26
25
  shutdown.interrupt(code);
27
26
  };
28
27
  // SIGINT only fires outside raw mode (a raw tty delivers Ctrl-C as a
@@ -32,6 +31,11 @@ export async function runOmdsh(prompt, resume) {
32
31
  installFailLoud(NAME, process, async () => { await app.current?.fiber.dispose(); });
33
32
  const environment = prepareLaunchEnvironment();
34
33
  const composed = composeLaunch();
34
+ await healProfilesModuleFallback({
35
+ installAnchor: INSTALL_ANCHOR,
36
+ profile: composed.profile,
37
+ home: omdshHome(),
38
+ });
35
39
  const ctx = await boot(NAME, composed.rootConfig, structuredClone(composed.patches), (hostCtx) => {
36
40
  app.current = hostCtx;
37
41
  hostCtx.provide(DSH_LAUNCH_ENVIRONMENT_KEY, environment);
@@ -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
@@ -27,8 +27,9 @@ export declare function ensureProductBundleFirst(dir: string): void;
27
27
  */
28
28
  export declare function ensureOmdshProfile(home: string): string;
29
29
  /**
30
- * Heal the shared module fallback, ensure the Profile exists, load its
31
- * bundles, and rewrite the empty root include.
30
+ * Ensure the Profile exists, load its bundles, and rewrite the empty root
31
+ * include. Module fallback healing happens asynchronously in runOmdsh after
32
+ * this function returns the resolved Profile.
32
33
  */
33
34
  export declare function prepareProfile(home: string, userLayer?: boolean): Profile;
34
35
  /** One launch's labeled layers and the flattened patch list `boot()` mounts. */
@@ -46,7 +47,7 @@ export interface LaunchComposition {
46
47
  export declare function agentPresetsOverlay(layerPatches: readonly PatchOptions[][]): PatchOptions | undefined;
47
48
  /**
48
49
  * Compose the live launch layers in product → user bundles → Profile patch
49
- * → home patch → MCP → agent-presets overlay order.
50
+ * → home patch → MCP → LSP → agent-presets overlay order.
50
51
  */
51
52
  export declare function composeLaunch(cwd?: string, environment?: NodeJS.ProcessEnv, options?: {
52
53
  userLayer?: boolean;
package/lib/profile.js CHANGED
@@ -9,8 +9,10 @@
9
9
  import { existsSync, writeFileSync } from 'node:fs';
10
10
  import { join } from 'node:path';
11
11
  import { fileURLToPath } from 'node:url';
12
- import { composeEntries, healProfilesModuleFallback, initProfile, loadOptionalPatches, loadProfile, PROFILE_PATCH_FILENAME, readProfileManifest, resolveProfileDir, writeProfileManifest, } from '@deepseek-ai/dsh-app-boot';
13
- import { loadMcpPatches, omdshHome } from "./mcp-config.js";
12
+ import { composeEntries, initProfile, loadOptionalPatches, loadProfile, PROFILE_PATCH_FILENAME, readProfileManifest, resolveProfileDir, writeProfileManifest, } from '@deepseek-ai/dsh-app-boot';
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';
@@ -55,11 +57,11 @@ export function ensureOmdshProfile(home) {
55
57
  return dir;
56
58
  }
57
59
  /**
58
- * Heal the shared module fallback, ensure the Profile exists, load its
59
- * bundles, and rewrite the empty root include.
60
+ * Ensure the Profile exists, load its bundles, and rewrite the empty root
61
+ * include. Module fallback healing happens asynchronously in runOmdsh after
62
+ * this function returns the resolved Profile.
60
63
  */
61
64
  export function prepareProfile(home, userLayer = true) {
62
- healProfilesModuleFallback(INSTALL_ANCHOR, home);
63
65
  ensureOmdshProfile(home);
64
66
  const profile = loadProfile(NAME, PROFILE_NAME, INSTALL_ANCHOR, home, { userLayer });
65
67
  writeFileSync(join(profile.dir, PROFILE_ROOT_FILENAME), PROFILE_ROOT_CONFIG);
@@ -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.13.0",
4
+ "version": "0.15.0",
5
5
  "homepage": "https://omdsh.agi.fans/",
6
6
  "keywords": [
7
7
  "omdsh",
@@ -49,80 +49,124 @@
49
49
  "access": "public"
50
50
  },
51
51
  "dependencies": {
52
- "@deepseek-ai/cordis-plugin-loader": "1.0.2",
52
+ "@deepseek-ai/cordis-plugin-loader": "1.0.3",
53
+ "@deepseek-ai/cordis-plugin-timer": "1.1.4",
54
+ "@deepseek-ai/dsh-agent": "0.1.5-rc.1",
55
+ "@deepseek-ai/dsh-agent-default-model": "0.1.5-rc.1",
56
+ "@deepseek-ai/dsh-agent-instructions": "0.1.5-rc.1",
57
+ "@deepseek-ai/dsh-agent-loop": "0.1.5-rc.1",
58
+ "@deepseek-ai/dsh-agent-presets": "0.1.5-rc.1",
59
+ "@deepseek-ai/dsh-app-boot": "0.1.5-rc.1",
60
+ "@deepseek-ai/dsh-attachment-local": "0.1.5-rc.1",
61
+ "@deepseek-ai/dsh-authorization": "0.1.5-rc.1",
62
+ "@deepseek-ai/dsh-bash-sandbox": "0.1.5-rc.1",
63
+ "@deepseek-ai/dsh-cmdline": "0.1.5-rc.1",
64
+ "@deepseek-ai/dsh-code-runtime-worker-thread": "0.1.5-rc.1",
65
+ "@deepseek-ai/dsh-command-compact": "0.1.5-rc.1",
66
+ "@deepseek-ai/dsh-command-goal": "0.1.5-rc.1",
67
+ "@deepseek-ai/dsh-commands": "0.1.5-rc.1",
68
+ "@deepseek-ai/dsh-compaction-basic": "0.1.5-rc.1",
69
+ "@deepseek-ai/dsh-compaction-tool-result-pruner": "0.1.5-rc.1",
70
+ "@deepseek-ai/dsh-cordis-host-runner": "0.1.5-rc.1",
71
+ "@deepseek-ai/dsh-credentials-local": "0.1.5-rc.1",
72
+ "@deepseek-ai/dsh-file-reference": "0.1.5-rc.1",
73
+ "@deepseek-ai/dsh-file-reference-local": "0.1.5-rc.1",
74
+ "@deepseek-ai/dsh-fs-local": "0.1.5-rc.1",
75
+ "@deepseek-ai/dsh-fs-observation-policy": "0.1.5-rc.1",
76
+ "@deepseek-ai/dsh-fs-sandbox": "0.1.5-rc.1",
77
+ "@deepseek-ai/dsh-goal": "0.1.5-rc.1",
78
+ "@deepseek-ai/dsh-goal-round-driver": "0.1.5-rc.1",
79
+ "@deepseek-ai/dsh-http-proxy": "0.1.5-rc.1",
80
+ "@deepseek-ai/dsh-invariants": "0.1.5-rc.1",
81
+ "@deepseek-ai/dsh-jobs-local": "0.1.5-rc.1",
82
+ "@deepseek-ai/dsh-launch-environment": "0.1.5-rc.1",
83
+ "@deepseek-ai/dsh-llm": "0.1.5-rc.1",
84
+ "@deepseek-ai/dsh-llm-deepseek": "0.1.5-rc.1",
85
+ "@deepseek-ai/dsh-llm-pi-ai": "0.1.5-rc.1",
86
+ "@deepseek-ai/dsh-llm-retry": "0.1.5-rc.1",
87
+ "@deepseek-ai/dsh-lsp": "0.1.5-rc.1",
88
+ "@deepseek-ai/dsh-lsp-stdio": "0.1.5-rc.1",
89
+ "@deepseek-ai/dsh-mcp-client": "0.1.5-rc.1",
90
+ "@deepseek-ai/dsh-output-retention": "0.1.5-rc.1",
91
+ "@deepseek-ai/dsh-permission-presets": "0.1.5-rc.1",
92
+ "@deepseek-ai/dsh-persona": "0.1.5-rc.1",
93
+ "@deepseek-ai/dsh-plan-mode": "0.1.5-rc.1",
94
+ "@deepseek-ai/dsh-pwsh-local": "0.1.5-rc.1",
95
+ "@deepseek-ai/dsh-pwsh-sandbox": "0.1.5-rc.1",
96
+ "@deepseek-ai/dsh-repeat-tool-reminder": "0.1.5-rc.1",
97
+ "@deepseek-ai/dsh-sandbox-local": "0.1.5-rc.1",
98
+ "@deepseek-ai/dsh-sandbox-policy": "0.1.5-rc.1",
99
+ "@deepseek-ai/dsh-scope": "0.1.5-rc.1",
100
+ "@deepseek-ai/dsh-session": "0.1.5-rc.1",
101
+ "@deepseek-ai/dsh-session-checkpoint-policy": "0.1.5-rc.1",
102
+ "@deepseek-ai/dsh-session-persistence-jsonl": "0.1.5-rc.1",
103
+ "@deepseek-ai/dsh-session-projection": "0.1.5-rc.1",
104
+ "@deepseek-ai/dsh-session-query": "0.1.5-rc.1",
105
+ "@deepseek-ai/dsh-session-query-sqlite": "0.1.5-rc.1",
106
+ "@deepseek-ai/dsh-session-reference": "0.1.5-rc.1",
107
+ "@deepseek-ai/dsh-session-stats": "0.1.5-rc.1",
108
+ "@deepseek-ai/dsh-session-title": "0.1.5-rc.1",
109
+ "@deepseek-ai/dsh-settings": "0.1.5-rc.1",
110
+ "@deepseek-ai/dsh-settings-file": "0.1.5-rc.1",
111
+ "@deepseek-ai/dsh-shell-env": "0.1.5-rc.1",
112
+ "@deepseek-ai/dsh-skill": "0.1.5-rc.1",
113
+ "@deepseek-ai/dsh-skill-filesystem": "0.1.5-rc.1",
114
+ "@deepseek-ai/dsh-spill": "0.1.5-rc.1",
115
+ "@deepseek-ai/dsh-spill-local": "0.1.5-rc.1",
116
+ "@deepseek-ai/dsh-spill-policy": "0.1.5-rc.1",
117
+ "@deepseek-ai/dsh-subagent": "0.1.5-rc.1",
118
+ "@deepseek-ai/dsh-subagent-acp": "0.1.5-rc.1",
119
+ "@deepseek-ai/dsh-subagent-fork-in-process": "0.1.5-rc.1",
120
+ "@deepseek-ai/dsh-subagent-in-process-driver": "0.1.5-rc.1",
121
+ "@deepseek-ai/dsh-subagent-spawn-in-process": "0.1.5-rc.1",
122
+ "@deepseek-ai/dsh-subprocess-local": "0.1.5-rc.1",
123
+ "@deepseek-ai/dsh-system-prompt": "0.1.5-rc.1",
124
+ "@deepseek-ai/dsh-terminal": "0.1.5-rc.1",
125
+ "@deepseek-ai/dsh-terminal-bash": "0.1.5-rc.1",
126
+ "@deepseek-ai/dsh-timeout": "0.1.5-rc.1",
127
+ "@deepseek-ai/dsh-token-meter": "0.1.5-rc.1",
128
+ "@deepseek-ai/dsh-tool-ask-user": "0.1.5-rc.1",
129
+ "@deepseek-ai/dsh-tool-bash": "0.1.5-rc.1",
130
+ "@deepseek-ai/dsh-tool-bash-persistent": "0.1.5-rc.1",
131
+ "@deepseek-ai/dsh-tool-call-timeout-policy": "0.1.5-rc.1",
132
+ "@deepseek-ai/dsh-tool-cordis": "0.1.5-rc.1",
133
+ "@deepseek-ai/dsh-tool-fs": "0.1.5-rc.1",
134
+ "@deepseek-ai/dsh-tool-fs-search": "0.1.5-rc.1",
135
+ "@deepseek-ai/dsh-tool-goal": "0.1.5-rc.1",
136
+ "@deepseek-ai/dsh-tool-jobs": "0.1.5-rc.1",
137
+ "@deepseek-ai/dsh-tool-lsp": "0.1.5-rc.1",
138
+ "@deepseek-ai/dsh-tool-present": "0.1.5-rc.1",
139
+ "@deepseek-ai/dsh-tool-pwsh": "0.1.5-rc.1",
140
+ "@deepseek-ai/dsh-tool-pwsh-persistent": "0.1.5-rc.1",
141
+ "@deepseek-ai/dsh-tool-ralph": "0.1.5-rc.1",
142
+ "@deepseek-ai/dsh-tool-skill": "0.1.5-rc.1",
143
+ "@deepseek-ai/dsh-tool-str-replace-editor": "0.1.5-rc.1",
144
+ "@deepseek-ai/dsh-tool-subagent": "0.1.5-rc.1",
145
+ "@deepseek-ai/dsh-tool-subagent-control": "0.1.5-rc.1",
146
+ "@deepseek-ai/dsh-tool-terminal": "0.1.5-rc.1",
147
+ "@deepseek-ai/dsh-tool-todo": "0.1.5-rc.1",
148
+ "@deepseek-ai/dsh-tool-web": "0.1.5-rc.1",
149
+ "@deepseek-ai/dsh-tool-workflow": "0.1.5-rc.1",
150
+ "@deepseek-ai/dsh-tools": "0.1.5-rc.1",
151
+ "@deepseek-ai/dsh-user-approval": "0.1.5-rc.1",
152
+ "@deepseek-ai/dsh-user-questions": "0.1.5-rc.1",
153
+ "@deepseek-ai/dsh-web": "0.1.5-rc.1",
154
+ "@deepseek-ai/dsh-web-fetch-http": "0.1.5-rc.1",
155
+ "@deepseek-ai/dsh-workflow": "0.1.5-rc.1",
156
+ "@deepseek-ai/dsh-workflow-worker-thread": "0.1.5-rc.1",
157
+ "@deepseek-ai/schemastery": "3.18.2",
53
158
  "node-addon-require-builtin": "0.1.4",
54
- "@deepseek-ai/cordis-plugin-timer": "1.1.3",
55
- "@deepseek-ai/dsh-agent": "0.1.1-rc.2",
56
- "@deepseek-ai/dsh-agent-default-model": "0.1.1-rc.2",
57
- "@deepseek-ai/dsh-agent-presets": "0.1.1-rc.2",
58
- "@deepseek-ai/dsh-agent-spine-demo": "0.1.1-rc.2",
59
- "@deepseek-ai/dsh-attachment-local": "0.1.1-rc.2",
60
- "@deepseek-ai/dsh-command-compact": "0.1.1-rc.2",
61
- "@deepseek-ai/dsh-command-goal": "0.1.1-rc.2",
62
- "@deepseek-ai/dsh-commands": "0.1.1-rc.2",
63
- "@deepseek-ai/dsh-compaction-basic": "0.1.1-rc.2",
64
- "@deepseek-ai/dsh-code-runtime-worker-thread": "0.1.1-rc.2",
65
- "@deepseek-ai/dsh-cordis-host-runner": "0.1.1-rc.2",
66
- "@deepseek-ai/dsh-app-boot": "0.1.1-rc.2",
67
- "@deepseek-ai/dsh-bash-sandbox": "0.1.1-rc.2",
68
- "@deepseek-ai/dsh-cmdline": "0.1.1-rc.2",
69
- "@deepseek-ai/dsh-file-reference": "0.1.1-rc.2",
70
- "@deepseek-ai/dsh-file-reference-local": "0.1.1-rc.2",
71
- "@deepseek-ai/dsh-fs-local": "0.1.1-rc.2",
72
- "@deepseek-ai/dsh-fs-observation-policy": "0.1.1-rc.2",
73
- "@deepseek-ai/dsh-launch-environment": "0.1.1-rc.2",
74
- "@deepseek-ai/dsh-llm": "0.1.1-rc.2",
75
- "@deepseek-ai/dsh-llm-deepseek": "0.1.1-rc.2",
76
- "@deepseek-ai/dsh-llm-pi-ai": "0.1.1-rc.2",
77
- "@deepseek-ai/dsh-mcp-client": "0.1.1-rc.2",
78
- "@deepseek-ai/dsh-permission-presets": "0.1.1-rc.2",
79
- "@deepseek-ai/dsh-persona": "0.1.1-rc.2",
80
- "@deepseek-ai/dsh-plan-mode": "0.1.1-rc.2",
81
- "@deepseek-ai/dsh-sandbox-local": "0.1.1-rc.2",
82
- "@deepseek-ai/dsh-sandbox-policy": "0.1.1-rc.2",
83
- "@deepseek-ai/dsh-session": "0.1.1-rc.2",
84
- "@deepseek-ai/dsh-session-checkpoint-policy": "0.1.1-rc.2",
85
- "@deepseek-ai/dsh-session-persistence-jsonl": "0.1.1-rc.2",
86
- "@deepseek-ai/dsh-session-projection": "0.1.1-rc.2",
87
- "@deepseek-ai/dsh-session-query": "0.1.1-rc.2",
88
- "@deepseek-ai/dsh-session-query-sqlite": "0.1.1-rc.2",
89
- "@deepseek-ai/dsh-session-reference": "0.1.1-rc.2",
90
- "@deepseek-ai/dsh-session-stats": "0.1.1-rc.2",
91
- "@deepseek-ai/dsh-session-title": "0.1.1-rc.2",
92
- "@deepseek-ai/dsh-subagent": "0.1.1-rc.2",
93
- "@deepseek-ai/dsh-subagent-spawn-in-process": "0.1.1-rc.2",
94
- "@deepseek-ai/dsh-terminal": "0.1.1-rc.2",
95
- "@deepseek-ai/dsh-terminal-bash": "0.1.1-rc.2",
96
- "@deepseek-ai/dsh-token-meter": "0.1.1-rc.2",
97
- "@deepseek-ai/dsh-tool-ask-user": "0.1.1-rc.2",
98
- "@deepseek-ai/dsh-tool-bash-persistent": "0.1.1-rc.2",
99
- "@deepseek-ai/dsh-tool-cordis": "0.1.1-rc.2",
100
- "@deepseek-ai/dsh-tool-fs": "0.1.1-rc.2",
101
- "@deepseek-ai/dsh-tool-fs-search": "0.1.1-rc.2",
102
- "@deepseek-ai/dsh-tool-str-replace-editor": "0.1.1-rc.2",
103
- "@deepseek-ai/dsh-tool-subagent": "0.1.1-rc.2",
104
- "@deepseek-ai/dsh-tool-subagent-control": "0.1.1-rc.2",
105
- "@deepseek-ai/dsh-tool-todo": "0.1.1-rc.2",
106
- "@deepseek-ai/dsh-user-approval": "0.1.1-rc.2",
107
- "@deepseek-ai/dsh-user-questions": "0.1.1-rc.2",
108
- "@deepseek-ai/dsh-subprocess-local": "0.1.1-rc.2",
109
- "@deepseek-ai/dsh-settings-file": "0.1.1-rc.2",
110
- "@deepseek-ai/dsh-settings": "0.1.1-rc.2",
111
- "@deepseek-ai/dsh-system-prompt": "0.1.1-rc.2",
112
- "@deepseek-ai/schemastery": "3.18.1",
113
- "@deepseek-ai/dsh-credentials-local": "0.1.1-rc.2",
114
- "@deepseek-ai/dsh-authorization": "0.1.1-rc.2",
115
- "@agi-fans/dsh-tui": "^0.13.0"
159
+ "@agi-fans/dsh-tui": "^0.15.0"
116
160
  },
117
161
  "peerDependencies": {
118
- "@deepseek-ai/cordis": "^4.0.1"
162
+ "@deepseek-ai/cordis": "^4.0.2"
119
163
  },
120
164
  "devDependencies": {
121
- "@deepseek-ai/cordis": "4.0.1",
122
- "typescript": "^5.6.0",
165
+ "@deepseek-ai/cordis": "4.0.2",
166
+ "@types/node": "^22.10.0",
123
167
  "tsx": "^4.19.0",
124
- "vitest": "^2.1.0",
125
- "@types/node": "^22.10.0"
168
+ "typescript": "^5.6.0",
169
+ "vitest": "^2.1.0"
126
170
  },
127
171
  "scripts": {
128
172
  "clean": "node -e \"const fs=require('node:fs');fs.rmSync('lib',{recursive:true,force:true});fs.rmSync('tsconfig.tsbuildinfo',{force:true})\"",