@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.
- package/config/agent-presets/code/agent.cordis.yml +1 -1
- package/config/agent-presets/cordis/agent.cordis.yml +1 -1
- package/config/agent-presets/minimal/agent.cordis.yml +21 -2
- package/config/agent-presets/standard/agent.cordis.yml +1 -1
- package/config/cordis.yml +268 -17
- package/lib/agent-behavior.js +1 -2
- package/lib/args.js +1 -1
- package/lib/boot.js +8 -4
- package/lib/config-paths.d.ts +10 -0
- package/lib/config-paths.js +30 -0
- package/lib/lsp-config.d.ts +27 -0
- package/lib/lsp-config.js +147 -0
- package/lib/mcp-config.d.ts +0 -2
- package/lib/mcp-config.js +2 -21
- package/lib/plugin.js +1 -1
- package/lib/profile.d.ts +4 -3
- package/lib/profile.js +11 -6
- package/package.json +113 -69
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
- id: persona
|
|
2
2
|
name: '@deepseek-ai/dsh-persona'
|
|
3
3
|
config:
|
|
4
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
-
|
|
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
|
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
|
|
48
|
-
#
|
|
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:
|
|
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-
|
|
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-
|
|
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
|
-
|
|
168
|
-
|
|
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
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
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-
|
|
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
|
|
package/lib/agent-behavior.js
CHANGED
|
@@ -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(
|
|
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-
|
|
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
|
package/lib/mcp-config.d.ts
CHANGED
|
@@ -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 {
|
|
12
|
-
import {
|
|
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 "./
|
|
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
|
-
*
|
|
31
|
-
*
|
|
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,
|
|
13
|
-
import {
|
|
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
|
-
*
|
|
59
|
-
*
|
|
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.
|
|
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.
|
|
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
|
-
"@
|
|
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.
|
|
162
|
+
"@deepseek-ai/cordis": "^4.0.2"
|
|
119
163
|
},
|
|
120
164
|
"devDependencies": {
|
|
121
|
-
"@deepseek-ai/cordis": "4.0.
|
|
122
|
-
"
|
|
165
|
+
"@deepseek-ai/cordis": "4.0.2",
|
|
166
|
+
"@types/node": "^22.10.0",
|
|
123
167
|
"tsx": "^4.19.0",
|
|
124
|
-
"
|
|
125
|
-
"
|
|
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})\"",
|