@deepseek-insight/dsi 0.5.19 → 0.5.20

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.
Files changed (88) hide show
  1. package/.agents/skills/dsi-ov-setup/SKILL.md +114 -0
  2. package/bin/dsi.mjs +62 -2
  3. package/build/client/_app/immutable/assets/{2.Da1CnqbG.css → 2.Dk-hwaP_.css} +1 -1
  4. package/build/client/_app/immutable/chunks/CodI3RGj.js +1 -0
  5. package/build/client/_app/immutable/chunks/{CLNDb8QN.js → CxmtCU9s.js} +1 -1
  6. package/build/client/_app/immutable/chunks/DKDzTags.js +2 -0
  7. package/build/client/_app/immutable/chunks/{Dv2f6AVG.js → azDKH4zi.js} +1 -1
  8. package/build/client/_app/immutable/chunks/qIBjcgkE.js +1 -0
  9. package/build/client/_app/immutable/entry/{app.C8CwtYTr.js → app.CqYGeqRv.js} +2 -2
  10. package/build/client/_app/immutable/entry/start.CIXiL_7f.js +1 -0
  11. package/build/client/_app/immutable/nodes/{0.VWq3h0rH.js → 0.u99aBgpL.js} +1 -1
  12. package/build/client/_app/immutable/nodes/{1.Dnl1P2aB.js → 1.qcRcZCY6.js} +1 -1
  13. package/build/client/_app/immutable/nodes/2.GgqfB5rv.js +171 -0
  14. package/build/client/_app/version.json +1 -1
  15. package/build/handler.js +4 -4
  16. package/build/index.js +4 -4
  17. package/build/server/chunks/chunks/{app-config.svelte.js-rN4N5yAI.js → app-config.svelte.js-CFb4kaFl.js} +7 -3
  18. package/build/server/chunks/chunks/{db.js-DbbYS9o8.js → db.js-9wP1ySFv.js} +2 -2
  19. package/build/server/chunks/chunks/{db2.js-BQWa7bEG.js → db2.js-B_Un4Zvq.js} +7 -5
  20. package/build/server/chunks/chunks/{dsh-connection.js-CpcCtA42.js → dsh-connection.js-CwL9I98w.js} +4 -3
  21. package/build/server/chunks/chunks/{git-probe.js-CvkToKO4.js → git-probe.js-C7z6xDzg.js} +3 -3
  22. package/build/server/chunks/chunks/{insight-config.js-Dw_Qi0fO.js → insight-config.js-COS9LOWZ.js} +13 -4
  23. package/build/server/chunks/chunks/{internal.js-BDS_h7zE.js → internal.js-Bf2uRIVS.js} +2 -2
  24. package/build/server/chunks/chunks/{permission-state.js-yvwUSnug.js → permission-state.js-BoJAoWqi.js} +18 -15
  25. package/build/server/chunks/chunks/settings-home.js-CqnqJVOu.js +9 -0
  26. package/build/server/chunks/chunks/settings-home2.js-f75-B6RI.js +102 -0
  27. package/build/server/chunks/chunks/{state.js-eZmA7eF7.js → state.js-OWX1K3Yj.js} +2 -2
  28. package/build/server/chunks/chunks/{watcher.js-C97Xyorx.js → watcher.js-Dc9hzRLI.js} +4 -4
  29. package/build/server/chunks/entries/endpoints/api/a2a/_id_/{_server.ts.js-Cqh1iqgu.js → _server.ts.js-0rfV7w20.js} +4 -3
  30. package/build/server/chunks/entries/endpoints/api/a2a/{_server.ts.js-DNKD4rZu.js → _server.ts.js-DX0DUIja.js} +6 -5
  31. package/build/server/chunks/entries/endpoints/api/a2a/register/{_server.ts.js-CJ-FwkrZ.js → _server.ts.js-zB-V9Naa.js} +6 -5
  32. package/build/server/chunks/entries/endpoints/api/config/{_server.ts.js-CMM4kYVx.js → _server.ts.js-Bo4VgIna.js} +5 -3
  33. package/build/server/chunks/entries/endpoints/api/dsh/directory/{_server.ts.js-epVplzwB.js → _server.ts.js-_Wc4NU0Q.js} +4 -3
  34. package/build/server/chunks/entries/endpoints/api/dsh/pick-directory/{_server.ts.js-bXHb97gT.js → _server.ts.js-CvoINUYy.js} +4 -3
  35. package/build/server/chunks/entries/endpoints/api/dsh/presets/{_server.ts.js-BNOHhtzy.js → _server.ts.js-B4UwZ8nd.js} +4 -3
  36. package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/attachment/{_server.ts.js-BBi6jeVj.js → _server.ts.js-Hml2J0Bq.js} +4 -3
  37. package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/cancel/{_server.ts.js-N0nKPuqL.js → _server.ts.js-CsZ2u8cs.js} +4 -3
  38. package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/catalog/{_server.ts.js-VGFCPAbs.js → _server.ts.js-BhF1Nzig.js} +4 -3
  39. package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/command/{_server.ts.js-na_sUb0Z.js → _server.ts.js-BGXjV_Ak.js} +4 -3
  40. package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/events/{_server.ts.js-CeNf028P.js → _server.ts.js-BF4vBIja.js} +5 -4
  41. package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/fork/{_server.ts.js-DfqO-GO4.js → _server.ts.js-B2OwrEQD.js} +4 -3
  42. package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/goal/{_server.ts.js-Dj9GYNl7.js → _server.ts.js-DboY_7cp.js} +4 -3
  43. package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/history/{_server.ts.js-DqShsRl9.js → _server.ts.js-BpioYdnc.js} +4 -3
  44. package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/models/{_server.ts.js-BQSBUf70.js → _server.ts.js-CLrgUoq0.js} +4 -3
  45. package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/path/{_server.ts.js-CeCKDyKB.js → _server.ts.js-BlZr_mA6.js} +3 -2
  46. package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/permission/{_server.ts.js-CadTCNUJ.js → _server.ts.js-BiU_IgYD.js} +4 -3
  47. package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/prompt/{_server.ts.js-BXzgi8xX.js → _server.ts.js-FV-4ougZ.js} +4 -3
  48. package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/rename/{_server.ts.js-BfD5FXiL.js → _server.ts.js-ChxB0XU5.js} +4 -3
  49. package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/respond/{_server.ts.js-CiDPC9TY.js → _server.ts.js-DkSydg_X.js} +4 -3
  50. package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/select-model/{_server.ts.js-DGcZgN96.js → _server.ts.js-Wbuf-vse.js} +4 -3
  51. package/build/server/chunks/entries/endpoints/api/dsh/sessions/{_server.ts.js-DnU1CCOw.js → _server.ts.js-B-BfCKKL.js} +4 -3
  52. package/build/server/chunks/entries/endpoints/api/dsh/workspace-file/{_server.ts.js-BZ0UV1n2.js → _server.ts.js-fKfv5g19.js} +4 -3
  53. package/build/server/chunks/entries/endpoints/api/dsh/workspace-file-bytes/{_server.ts.js-lxLpuPFL.js → _server.ts.js-DZpRzvas.js} +4 -3
  54. package/build/server/chunks/entries/endpoints/api/dsh/workspace-tree/{_server.ts.js-Cw3vl704.js → _server.ts.js-Hn5-fnsU.js} +4 -3
  55. package/build/server/chunks/entries/endpoints/api/dsh/workspaces/{_server.ts.js-KKnR2UO4.js → _server.ts.js-CtPDRjV7.js} +4 -3
  56. package/build/server/chunks/entries/endpoints/api/dsh/workspaces/_workspaceId_/delete/{_server.ts.js-I1eSZn60.js → _server.ts.js-DOp3nIcK.js} +4 -3
  57. package/build/server/chunks/entries/endpoints/api/dsh/workspaces/_workspaceId_/rename/{_server.ts.js-B0zqAKnV.js → _server.ts.js-DiwcZfK9.js} +4 -3
  58. package/build/server/chunks/entries/endpoints/api/prompts/_id_/{_server.ts.js-C-QN0enK.js → _server.ts.js-SoNSMvWj.js} +4 -3
  59. package/build/server/chunks/entries/endpoints/api/prompts/{_server.ts.js-CwTGUPIp.js → _server.ts.js-DIZiiHk-.js} +12 -4
  60. package/build/server/chunks/entries/endpoints/api/prompts/use/{_server.ts.js-Bvotxm37.js → _server.ts.js-CbsUk0fk.js} +4 -3
  61. package/build/server/chunks/entries/endpoints/api/settings/{_server.ts.js-CRRLXk0y.js → _server.ts.js-DCeIpzKT.js} +3 -2
  62. package/build/server/chunks/entries/endpoints/api/settings-home/file/_server.ts.js-C1gSFX1P.js +68 -0
  63. package/build/server/chunks/entries/endpoints/api/settings-home/file-write/_server.ts.js-Dx0glK_q.js +68 -0
  64. package/build/server/chunks/entries/endpoints/api/settings-home/tree/_server.ts.js-CAmn2SKB.js +61 -0
  65. package/build/server/chunks/entries/endpoints/api/workspace/file-write/{_server.ts.js-DY_NDlYl.js → _server.ts.js-Blw1UFX2.js} +6 -5
  66. package/build/server/chunks/entries/endpoints/api/workspace/git-events/{_server.ts.js-DHEaymrG.js → _server.ts.js-yflU8VH2.js} +6 -5
  67. package/build/server/chunks/entries/endpoints/api/workspace/git-file-head/{_server.ts.js-AQgNkfCV.js → _server.ts.js-q9jXuJ1p.js} +10 -18
  68. package/build/server/chunks/entries/endpoints/api/workspace/git-map/{_server.ts.js-C9vxPbB3.js → _server.ts.js-YjwnbPfG.js} +12 -20
  69. package/build/server/chunks/entries/endpoints/api/workspace/git-status/{_server.ts.js-BlMRR11v.js → _server.ts.js-DRQay15h.js} +12 -20
  70. package/build/server/chunks/entries/endpoints/api/workspace/write-gate/_server.ts.js-BiCzLyNH.js +54 -0
  71. package/build/server/chunks/entries/pages/{_error.svelte.js-DIRRk8AK.js → _error.svelte.js-DkmmDHjP.js} +3 -3
  72. package/build/server/chunks/entries/pages/{_page.server.ts.js-ze2dUhXW.js → _page.server.ts.js-BHW1mzYQ.js} +3 -3
  73. package/build/server/chunks/entries/pages/{_page.svelte.js-CYT_NWww.js → _page.svelte.js-BSt3-Adz.js} +993 -532
  74. package/build/server/chunks/{handler-jvQdYpdY.js → handler-CEAxnB4f.js} +3 -3
  75. package/build/server/chunks/{index.js-BGLJR092.js → index.js-B-3rUYGC.js} +2 -2
  76. package/build/server/chunks/{manifest.js-CIb6Wm5j.js → manifest.js--ZDTDlzU.js} +71 -43
  77. package/build/server/chunks/nodes/{0.js-CQ3k21rg.js → 0.js-BQXxAZac.js} +2 -2
  78. package/build/server/chunks/nodes/{1.js-NI6SZ6un.js → 1.js-DMcugevB.js} +3 -3
  79. package/build/server/chunks/nodes/{2.js-BG_HkTrm.js → 2.js-BrT7uCAN.js} +9 -8
  80. package/package.json +2 -2
  81. package/template/.dsi/config.json +2 -2
  82. package/template/.dsi/prompts.sqlite +0 -0
  83. package/template/.dsi/settings.yaml +2 -1
  84. package/build/client/_app/immutable/chunks/BeeAmuEs.js +0 -2
  85. package/build/client/_app/immutable/chunks/BgF4MPCH.js +0 -1
  86. package/build/client/_app/immutable/chunks/h_AAZIXW.js +0 -1
  87. package/build/client/_app/immutable/entry/start.CCr7WSxA.js +0 -1
  88. package/build/client/_app/immutable/nodes/2.0fqLf_Nw.js +0 -170
@@ -0,0 +1,114 @@
1
+ ---
2
+ name: dsi-ov-setup
3
+ description: Use when OpenViking memory is broken or missing in DeepSeek Harness — server disconnected, server not installed, ov.conf missing, plugin not loaded, or a fresh machine needs the whole OpenViking + DSH memory integration set up (plugin, skill, server). Covers diagnosis, install, config, start, and verification.
4
+ ---
5
+
6
+ # OpenViking + DSH Setup and Recovery
7
+
8
+ Companion KB: `dev/kb/setup/2026-09-16 - OpenViking Server + DSH Memory Plugin — From Cold Start to Recalled Memory.md` — read it for the why behind every step. This skill is the do-path.
9
+
10
+ ## 0. Diagnose first — which failure is this?
11
+
12
+ Run in order; stop at the first failing gate:
13
+
14
+ | Gate | Command | Healthy looks like |
15
+ |---|---|---|
16
+ | Server process | `curl -s --max-time 3 http://127.0.0.1:1933/health` | `{"status":"ok","healthy":true,...}` |
17
+ | Server config | `ls ~/.openviking/ov.conf` | exists |
18
+ | Client config | `cat ~/.openviking/ovcli.conf` | `url` = `http://127.0.0.1:1933` |
19
+ | Package | `openviking-server --version` | prints a version |
20
+ | MCP connection | harness tool list shows `mcp__openviking__*` | tools present |
21
+
22
+ - Health fails + `ov.conf` missing → **Recovery path (§2)**, the common case.
23
+ - Health fails + `ov.conf` exists → run `openviking-server doctor`, fix what it names, go to §2 step 4.
24
+ - Health ok but MCP disconnected → the plugin reconnects on its own within a turn or two; if not after a full turn, restart the harness session. Do not reinstall anything.
25
+ - Package missing → fresh install: do §2 steps 1–6 from scratch.
26
+
27
+ ## 1. Facts to keep straight (most-confused pair)
28
+
29
+ - `~/.openviking/ovcli.conf` — **client** pointer: `{"url": "http://127.0.0.1:1933", "api_key": ""}`. Missing it breaks CLI commands only.
30
+ - `~/.openviking/ov.conf` — **server** model config (embedding + VLM). Missing it means the server process cannot start at all. This is the usual blocker.
31
+ - The DSH plugin (`@openviking/dsh-memory-plugin`, in the profile bundles at `~/.dsh/profiles/web/package.json`) is a **client only** — it never starts the server, and it reconnects automatically once the server is healthy. Never "fix" a disconnected MCP by touching the plugin.
32
+ - `openviking`/`ov` = CLI/SDK; `openviking-server` = the daemon. Same pip package.
33
+
34
+ ## 2. Recovery / install path
35
+
36
+ ### Step 1 — Install the package (skip if `openviking-server --version` works)
37
+
38
+ ```sh
39
+ pip install openviking --upgrade --force-reinstall
40
+ ```
41
+
42
+ Entry points land in `~/.local/bin`: `ov`, `openviking`, `openviking-server`, `vikingbot`.
43
+
44
+ ### Step 2 — CLI housekeeping
45
+
46
+ ```sh
47
+ ov language en # v0.3.23+ refuses most commands without this; writes ovcli.settings.conf
48
+ ov config add custom --name local --url http://127.0.0.1:1933 --activate -o json # only if ovcli.conf missing
49
+ ```
50
+
51
+ Note: both write under `~/.openviking/` — they fail under a workspace-only file sandbox; run with full file access.
52
+
53
+ ### Step 3 — Create the server config: `openviking-server init`
54
+
55
+ Preferred: run it interactively and let the human answer. If driving it with piped answers, the wizard's prompt order is exact and hidden prompts exist — the tested sequence for the recommended local setup:
56
+
57
+ ```
58
+ 1 # mode: step-by-step
59
+ 3 # embedding: lightweight CPU (llama.cpp, bge-small-zh-v1.5-f16, no key)
60
+ 1 # embedding model: (only option — EASY TO MISS; missing this shifts every later answer)
61
+ 6 # VLM: GLM (subscription API key)
62
+ 2 # GLM plan: coding
63
+ <key> # API key — pass via stdin from an env var; NEVER in the command line or logs
64
+ N # query planner via Ollama: no
65
+ 1 # bind 127.0.0.1 (dev, no auth)
66
+ 1933 # port
67
+ Y # save
68
+ ```
69
+
70
+ After saving the wizard echoes the resolved API key in its summary — **redact any captured log** before storing it.
71
+
72
+ Decision guardrails (from the KB §4): embedding `[3]` CPU is the default because it is keyless and tiny; offer `[1]` cloud embedding only when the user cares about retrieval quality and has a key; VLM is the piece worth a strong model — GLM via an existing subscription beats skipping it. `[9]` skip-VLM gives a server that stores but extracts poorly.
73
+
74
+ ### Step 4 — Wait out the build
75
+
76
+ Choosing CPU embedding triggers `pip install "openviking[local-embed]"`, which **builds `llama-cpp-python` from source** — several minutes of silent wheel-building. It is not hung. Do not kill it; verify with `ps aux | grep "openviking-server init"`.
77
+
78
+ ### Step 5 — Validate and start
79
+
80
+ ```sh
81
+ openviking-server doctor # expect: all checks PASS (config, auth, disk ≥ several GB)
82
+ openviking-server # foreground proof; then move to a supervisor
83
+ ```
84
+
85
+ For persistence: launchd/nohup/systemd — never rely on an agent shell outliving the session. Verify:
86
+
87
+ ```sh
88
+ curl -s http://127.0.0.1:1933/health # {"status":"ok","healthy":true,...}
89
+ ov status # "Connected (Healthy)", queue 0 pending / 0 errors
90
+ ```
91
+
92
+ A stale `~/.openviking/pending/` queue (hundreds of files) from the downtime drains on its own — do not delete it.
93
+
94
+ ### Step 6 — Confirm the integration
95
+
96
+ Within a turn of the server going healthy, the plugin reconnects (MCP tools answer, `<openviking-context>` appears at the next session start). If MCP tools still error after a full turn: restart the harness session once. Only then suspect the bundle (`~/.dsh/profiles/web/package.json` must list `@openviking/dsh-memory-plugin` in `dsh.profile.bundles`).
97
+
98
+ ## 3. Verification checklist (all seven, in order)
99
+
100
+ 1. `openviking-server --version` → prints version
101
+ 2. `ls ~/.openviking/ov.conf ~/.openviking/ovcli.conf` → both exist
102
+ 3. `openviking-server doctor` → all PASS
103
+ 4. `curl -s http://127.0.0.1:1933/health` → `"healthy":true`
104
+ 5. `ov status` → Connected (Healthy), 0 errors
105
+ 6. `ov find "smoke test"` after any resource exists → ranked hits, not a connection error
106
+ 7. New session → `<openviking-context>` block present
107
+
108
+ ## 4. Known traps
109
+
110
+ - `ov status` saying "Unreachable" while the server is fine → the language gate; run `ov language en` first.
111
+ - Two config files, one directory (§1) — check the right one for the symptom.
112
+ - `auth_mode: "dev"` = no auth, localhost only. Never bind `0.0.0.0` without switching to API-key auth (docs: Authentication guide).
113
+ - Piped `init` answers are prompt-order-fragile (Step 3) — count prompts, don't trust defaults.
114
+ - Re-examine actual prompt output on every version bump; this sequence was tested against OpenViking 0.4.20 / plugin 0.3.2 (2026-09-16) and the wizard's prompts are not a stable contract.
package/bin/dsi.mjs CHANGED
@@ -12,6 +12,8 @@
12
12
  // script AND serves the dsi build — one foreground pair, one Ctrl-C.
13
13
  // `--dev` serves the Vite dev server instead of the build (sources only).
14
14
  // `dsi dsh --sync-kills` sweeps orphans a lost previous run left behind.
15
+ // `dsi dsh --ov` (or --sync --ov) installs the OpenViking memory plugin into
16
+ // the active dsh profile by delegating to `dsh plugin ... add` (idempotent).
15
17
 
16
18
  import { spawn, spawnSync } from 'node:child_process';
17
19
  import net from 'node:net';
@@ -53,6 +55,9 @@ const USAGE = [
53
55
  ' port 5175; needs a full checkout: pnpm install)',
54
56
  ' --sync-kills',
55
57
  ' kill orphaned dsh/dsi processes left by an earlier run',
58
+ ' --ov install the OpenViking memory plugin into the active dsh',
59
+ ' profile (dsh plugin ... add). Client only — the memory',
60
+ ' server itself is set up separately (dsi-ov-setup skill)',
56
61
  '',
57
62
  ' Ports: `dsi dsh --sync` serves the DSI page on 5174 and opens your',
58
63
  ' browser there. With --dev the Vite dev server takes 5175 instead',
@@ -67,9 +72,12 @@ const USAGE = [
67
72
  ' ~/.dsh/settings.yaml',
68
73
  ' dsi dsh --token <token>',
69
74
  ' store the dsh launch token in ~/.dsi/settings.yaml',
70
- ' dsi dsh --sync [--zai] [--dev]',
75
+ ' dsi dsh --sync [--zai] [--dev] [--ov]',
71
76
  ' run dsh-web-synced.sh (dsh web + token sync) AND serve',
72
77
  ' dsi — see the recommended command above',
78
+ ' dsi dsh --ov',
79
+ ' install the OpenViking memory plugin into the active',
80
+ ' dsh profile (idempotent; alone, without --sync)',
73
81
  ' dsi dsh --sync-kills',
74
82
  ' kill orphaned dsh/dsi processes left by an earlier run'
75
83
  ].join('\n');
@@ -87,6 +95,11 @@ if (command !== 'web' && command !== 'zai' && command !== 'dsh') {
87
95
 
88
96
  const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
89
97
 
98
+ /** The OpenViking memory plugin DSI's host profile wants. Client-side only:
99
+ * it never starts openviking-server — it reconnects on its own once the
100
+ * server is healthy (KB 2026-09-16 §2). */
101
+ const OV_PLUGIN = '@openviking/dsh-memory-plugin';
102
+
90
103
  // ── dsi zai ────────────────────────────────────────────────────────────────
91
104
 
92
105
  /** The ZAI provider block, byte-for-byte the fresh-install shape. */
@@ -156,6 +169,10 @@ if (command === 'dsh') {
156
169
  setDshAuthToken(token);
157
170
  process.exit(0);
158
171
  }
172
+ if (flag === '--ov') {
173
+ runOvPlugin();
174
+ process.exit(0);
175
+ }
159
176
  if (flag === '--sync') {
160
177
  // --zai and --dev are dsi-side flags, stripped from the args the sync
161
178
  // script forwards to `dsh web` (which would refuse them):
@@ -166,10 +183,12 @@ if (command === 'dsh') {
166
183
  const rest = process.argv.slice(4);
167
184
  const withZai = rest.includes('--zai');
168
185
  const withDev = rest.includes('--dev');
186
+ const withOv = rest.includes('--ov');
169
187
  if (withZai) addZaiProvider();
188
+ if (withOv) runOvPlugin();
170
189
  runSkillsMirror();
171
190
  runSyncedPair(
172
- rest.filter((arg) => arg !== '--zai' && arg !== '--dev'),
191
+ rest.filter((arg) => arg !== '--zai' && arg !== '--dev' && arg !== '--ov'),
173
192
  withDev
174
193
  );
175
194
  } else if (flag === '--sync-kills') {
@@ -387,6 +406,47 @@ function addZaiProvider() {
387
406
  console.log(`dsi zai: ${settingsPath} updated — set ZAI_API_KEY in the harness env, then restart dsh web`);
388
407
  }
389
408
 
409
+ /** Install the OpenViking memory plugin into the active dsh profile by
410
+ * delegating to `dsh plugin --profile <profile> add` — the same dsh
411
+ * launcher `dsi dsh --sync` uses (DSH_WEB_CMD override, else the published
412
+ * pin via npx). dsh's own reconcilePlugins appends the package to
413
+ * dsh.profile.bundles (it declares a dsh.bundle), so nothing is hand-edited
414
+ * here. Idempotent: a profile that already has the dependency AND the bundle
415
+ * entry skips the pnpm round-trip. Fail-loud: a nonzero child exit (or a
416
+ * missing pnpm — dsh exits 127 for it) propagates. */
417
+ function runOvPlugin() {
418
+ const profile = process.env.DSH_PROFILE ?? 'web';
419
+ const manifestPath = path.join(
420
+ homedir(), '.dsh', 'profiles', profile, 'package.json'
421
+ );
422
+ if (existsSync(manifestPath)) {
423
+ try {
424
+ const manifest = JSON.parse(readFileSync(manifestPath, 'utf-8'));
425
+ const deps = manifest?.dependencies ?? {};
426
+ const bundles = manifest?.dsh?.profile?.bundles ?? [];
427
+ if (deps[OV_PLUGIN] !== undefined && bundles.includes(OV_PLUGIN)) {
428
+ console.log(`dsi dsh: ${OV_PLUGIN} already installed in the ${profile} profile — nothing to do`);
429
+ return;
430
+ }
431
+ } catch (error) {
432
+ console.error(`dsi dsh: cannot parse ${manifestPath}: ${error?.message ?? error}`);
433
+ process.exit(65);
434
+ }
435
+ }
436
+ const cmd = process.env.DSH_WEB_CMD
437
+ ? `${process.env.DSH_WEB_CMD} plugin --profile ${profile} add ${OV_PLUGIN}`
438
+ : `npx --yes @deepseek-ai/dsh@${dshWebVersion()} plugin --profile ${profile} add ${OV_PLUGIN}`;
439
+ console.log(`dsi dsh: installing ${OV_PLUGIN} into the ${profile} profile (${cmd})`);
440
+ const result = spawnSync('/bin/sh', ['-c', cmd], { stdio: 'inherit' });
441
+ if (result.error !== undefined) throw result.error;
442
+ const code = result.status ?? 1;
443
+ if (code !== 0) {
444
+ console.error(`dsi dsh: plugin install failed (exit ${code}) — pnpm on PATH is required; fix the cause above, then re-run`);
445
+ process.exit(code);
446
+ }
447
+ console.log(`dsi dsh: ${OV_PLUGIN} installed — it connects on its own once openviking-server answers (see the dsi-ov-setup skill for the server side)`);
448
+ }
449
+
390
450
  /** Plant the shipped skills into the operator's skill mirror
391
451
  * (~/.agents/skills) — ADR "The Skill Mirror" 2026-09-15, D1–D5:
392
452
  * per-skill copy-only-if-absent, every repo skill, failures warn and