@deepseek-insight/dsi 0.5.19 → 0.5.22
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/.agents/skills/dsh-jump-prepare-fix/SKILL.md +99 -0
- package/.agents/skills/dsi-ov-setup/SKILL.md +150 -0
- package/.agents/skills/dsi-sync/SKILL.md +69 -0
- package/README.md +23 -29
- package/bin/dsi.mjs +79 -16
- package/build/client/_app/immutable/assets/2.DRj7JwRK.css +1 -0
- package/build/client/_app/immutable/chunks/Ch36fHI9.js +1 -0
- package/build/client/_app/immutable/chunks/{BeeAmuEs.js → D94Od7GQ.js} +2 -2
- package/build/client/_app/immutable/chunks/DUawi_ZZ.js +1 -0
- package/build/client/_app/immutable/chunks/DXSIz1Bv.js +1 -0
- package/build/client/_app/immutable/chunks/DlfWhx6l.js +1 -0
- package/build/client/_app/immutable/chunks/{CLNDb8QN.js → zBRTraNY.js} +2 -2
- package/build/client/_app/immutable/entry/{app.C8CwtYTr.js → app.DLUi0EIr.js} +2 -2
- package/build/client/_app/immutable/entry/start.CWU06EOY.js +1 -0
- package/build/client/_app/immutable/nodes/{0.VWq3h0rH.js → 0.DfmjWWCy.js} +1 -1
- package/build/client/_app/immutable/nodes/1.Cy_8L_sF.js +1 -0
- package/build/client/_app/immutable/nodes/2.hEv7awQ2.js +171 -0
- package/build/client/_app/version.json +1 -1
- package/build/handler.js +4 -4
- package/build/index.js +4 -4
- package/build/server/chunks/chunks/{app-config.svelte.js-rN4N5yAI.js → app-config.svelte.js-DX-xENzY.js} +8 -4
- package/build/server/chunks/chunks/{config.js-iG_1bK3r.js → config.js-BvW5LrfQ.js} +3 -2
- package/build/server/chunks/chunks/{db.js-DbbYS9o8.js → db.js-DUiYPVrk.js} +2 -2
- package/build/server/chunks/chunks/{db2.js-BQWa7bEG.js → db2.js-B2wnWJ5y.js} +7 -5
- package/build/server/chunks/chunks/{dsh-connection.js-CpcCtA42.js → dsh-connection.js-DLLvHgxn.js} +5 -4
- package/build/server/chunks/chunks/{dsh-events.js-BtDxaV6Q.js → dsh-events.js-DEZgATm-.js} +4 -2
- package/build/server/chunks/chunks/{git-probe.js-CvkToKO4.js → git-probe.js-CNhqEFLP.js} +4 -4
- package/build/server/chunks/chunks/{insight-config.js-Dw_Qi0fO.js → insight-config.js-BgiNeS6f.js} +15 -6
- package/build/server/chunks/chunks/{internal.js-BDS_h7zE.js → internal.js-Du2x925l.js} +3 -3
- package/build/server/chunks/chunks/{permission-state.js-yvwUSnug.js → permission-state.js-B7UpAHBv.js} +20 -16
- package/build/server/chunks/chunks/{runtime.js-BPLc5RLR.js → runtime.js-CCJi3XaY.js} +3 -2
- package/build/server/chunks/chunks/{settings-document.js-BKnRkLVq.js → settings-document.js-i5MkkSFH.js} +2 -2
- package/build/server/chunks/chunks/settings-home.js-CqnqJVOu.js +9 -0
- package/build/server/chunks/chunks/settings-home2.js-f75-B6RI.js +102 -0
- package/build/server/chunks/chunks/{state.js-eZmA7eF7.js → state.js-BOUZ4Mdx.js} +4 -4
- package/build/server/chunks/chunks/{watcher.js-C97Xyorx.js → watcher.js-DMNZ6PC_.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/a2a/_id_/{_server.ts.js-Cqh1iqgu.js → _server.ts.js-BFZR8uHn.js} +6 -5
- package/build/server/chunks/entries/endpoints/api/a2a/{_server.ts.js-DNKD4rZu.js → _server.ts.js-BgqhjoUU.js} +9 -8
- package/build/server/chunks/entries/endpoints/api/a2a/register/{_server.ts.js-CJ-FwkrZ.js → _server.ts.js-CLVptu9i.js} +9 -8
- package/build/server/chunks/entries/endpoints/api/config/{_server.ts.js-CMM4kYVx.js → _server.ts.js-D8M_XizI.js} +7 -5
- package/build/server/chunks/entries/endpoints/api/dsh/directory/{_server.ts.js-epVplzwB.js → _server.ts.js-DS8L3_Bt.js} +6 -5
- package/build/server/chunks/entries/endpoints/api/dsh/pick-directory/{_server.ts.js-bXHb97gT.js → _server.ts.js-BUEokCIX.js} +6 -5
- package/build/server/chunks/entries/endpoints/api/dsh/presets/{_server.ts.js-BNOHhtzy.js → _server.ts.js-lLG8ls0C.js} +6 -5
- package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/attachment/{_server.ts.js-BBi6jeVj.js → _server.ts.js-BSenSXeg.js} +6 -5
- package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/cancel/{_server.ts.js-N0nKPuqL.js → _server.ts.js-DCXKkJ0v.js} +6 -5
- package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/catalog/{_server.ts.js-VGFCPAbs.js → _server.ts.js-BED7HhEP.js} +6 -5
- package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/command/{_server.ts.js-na_sUb0Z.js → _server.ts.js-Bg8nHHOZ.js} +6 -5
- package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/events/{_server.ts.js-CeNf028P.js → _server.ts.js-Dyo678sQ.js} +8 -7
- package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/fork/{_server.ts.js-DfqO-GO4.js → _server.ts.js-Bo1MLZzv.js} +6 -5
- package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/goal/{_server.ts.js-Dj9GYNl7.js → _server.ts.js-B5hEmzA3.js} +6 -5
- package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/history/{_server.ts.js-DqShsRl9.js → _server.ts.js-B0YMraSe.js} +7 -6
- package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/models/{_server.ts.js-BQSBUf70.js → _server.ts.js-B7E_ugh9.js} +6 -5
- package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/path/{_server.ts.js-CeCKDyKB.js → _server.ts.js-CpSm33QW.js} +5 -4
- package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/permission/{_server.ts.js-CadTCNUJ.js → _server.ts.js-qX_48Xfk.js} +6 -5
- package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/prompt/{_server.ts.js-BXzgi8xX.js → _server.ts.js-BmMx7VT-.js} +6 -5
- package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/rename/{_server.ts.js-BfD5FXiL.js → _server.ts.js-D9WGgQkP.js} +6 -5
- package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/respond/{_server.ts.js-CiDPC9TY.js → _server.ts.js-JNQ1THCO.js} +6 -5
- package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/select-model/{_server.ts.js-DGcZgN96.js → _server.ts.js-CyYEK2YZ.js} +6 -5
- package/build/server/chunks/entries/endpoints/api/dsh/sessions/{_server.ts.js-DnU1CCOw.js → _server.ts.js-9teKQw8I.js} +6 -5
- package/build/server/chunks/entries/endpoints/api/dsh/workspace-file/{_server.ts.js-BZ0UV1n2.js → _server.ts.js-D0EtJceT.js} +6 -5
- package/build/server/chunks/entries/endpoints/api/dsh/workspace-file-bytes/{_server.ts.js-lxLpuPFL.js → _server.ts.js-DVBe8VFL.js} +6 -5
- package/build/server/chunks/entries/endpoints/api/dsh/workspace-tree/{_server.ts.js-Cw3vl704.js → _server.ts.js-_ICn-AJI.js} +6 -5
- package/build/server/chunks/entries/endpoints/api/dsh/workspaces/{_server.ts.js-KKnR2UO4.js → _server.ts.js-deEnJXis.js} +6 -5
- package/build/server/chunks/entries/endpoints/api/dsh/workspaces/_workspaceId_/delete/{_server.ts.js-I1eSZn60.js → _server.ts.js-C99S7qPG.js} +6 -5
- package/build/server/chunks/entries/endpoints/api/dsh/workspaces/_workspaceId_/rename/{_server.ts.js-B0zqAKnV.js → _server.ts.js-DIbV5U-C.js} +6 -5
- package/build/server/chunks/entries/endpoints/api/prompts/_id_/{_server.ts.js-C-QN0enK.js → _server.ts.js-C9sx5xeq.js} +6 -5
- package/build/server/chunks/entries/endpoints/api/prompts/{_server.ts.js-CwTGUPIp.js → _server.ts.js-BQN2GfYg.js} +14 -6
- package/build/server/chunks/entries/endpoints/api/prompts/use/{_server.ts.js-Bvotxm37.js → _server.ts.js-Ya8ewOIo.js} +6 -5
- package/build/server/chunks/entries/endpoints/api/settings/{_server.ts.js-CRRLXk0y.js → _server.ts.js-Dtq_vXJc.js} +5 -4
- package/build/server/chunks/entries/endpoints/api/settings-home/file/_server.ts.js-C1gSFX1P.js +68 -0
- package/build/server/chunks/entries/endpoints/api/settings-home/file-write/_server.ts.js-Dx0glK_q.js +68 -0
- package/build/server/chunks/entries/endpoints/api/settings-home/tree/_server.ts.js-CAmn2SKB.js +61 -0
- package/build/server/chunks/entries/endpoints/api/workspace/file-write/{_server.ts.js-DY_NDlYl.js → _server.ts.js-DptPqI-s.js} +9 -8
- package/build/server/chunks/entries/endpoints/api/workspace/git-events/{_server.ts.js-DHEaymrG.js → _server.ts.js-B4C7kLHl.js} +9 -8
- package/build/server/chunks/entries/endpoints/api/workspace/git-file-head/{_server.ts.js-AQgNkfCV.js → _server.ts.js-Db9JKnPM.js} +13 -21
- package/build/server/chunks/entries/endpoints/api/workspace/git-map/{_server.ts.js-C9vxPbB3.js → _server.ts.js-C8gzgR2I.js} +15 -23
- package/build/server/chunks/entries/endpoints/api/workspace/git-status/{_server.ts.js-BlMRR11v.js → _server.ts.js-BIlHfNA_.js} +15 -23
- package/build/server/chunks/entries/endpoints/api/workspace/write-gate/_server.ts.js-DRza8q_m.js +54 -0
- package/build/server/chunks/entries/{hooks.server.js-B_E1wCwG.js → hooks.server.js-Bt6VP5fg.js} +4 -4
- package/build/server/chunks/entries/pages/{_error.svelte.js-DIRRk8AK.js → _error.svelte.js-B6QZqJkc.js} +30 -10
- package/build/server/chunks/entries/pages/{_page.server.ts.js-ze2dUhXW.js → _page.server.ts.js-BOFnfJKx.js} +4 -4
- package/build/server/chunks/entries/pages/{_page.svelte.js-CYT_NWww.js → _page.svelte.js-GQS2SRws.js} +3098 -755
- package/build/server/chunks/{handler-jvQdYpdY.js → handler-cx07G9-G.js} +3 -3
- package/build/server/chunks/{index.js-BGLJR092.js → index.js-Dfzyw-2i.js} +2 -2
- package/build/server/chunks/{manifest.js-CIb6Wm5j.js → manifest.js-CFJqE5Kz.js} +71 -43
- package/build/server/chunks/nodes/{0.js-CQ3k21rg.js → 0.js-CLm26i36.js} +2 -2
- package/build/server/chunks/nodes/1.js-cfJjJ8lx.js +9 -0
- package/build/server/chunks/nodes/2.js-BtKfdVVe.js +27 -0
- package/package.json +2 -2
- package/template/.dsi/config.json +2 -2
- package/template/.dsi/prompts.sqlite +0 -0
- package/template/.dsi/settings.yaml +2 -1
- package/build/client/_app/immutable/assets/2.Da1CnqbG.css +0 -1
- package/build/client/_app/immutable/chunks/7MCZCUsX.js +0 -1
- package/build/client/_app/immutable/chunks/BgF4MPCH.js +0 -1
- package/build/client/_app/immutable/chunks/Dv2f6AVG.js +0 -1
- package/build/client/_app/immutable/chunks/h_AAZIXW.js +0 -1
- package/build/client/_app/immutable/entry/start.CCr7WSxA.js +0 -1
- package/build/client/_app/immutable/nodes/1.Dnl1P2aB.js +0 -1
- package/build/client/_app/immutable/nodes/2.0fqLf_Nw.js +0 -170
- package/build/server/chunks/nodes/1.js-NI6SZ6un.js +0 -9
- package/build/server/chunks/nodes/2.js-BG_HkTrm.js +0 -26
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# DSH Jump Unstick — the `prepare` Scheduler-Symbol Split
|
|
2
|
+
|
|
3
|
+
Every DSH edition jump that dies with `Cannot read properties of undefined
|
|
4
|
+
(reading 'prepare')` on the first tool call has ONE verified cause class and ONE
|
|
5
|
+
validated fix. This skill exists so the jump is never blocked twice on the same
|
|
6
|
+
bug — the 2026-09-18 jump to `dsh-v0.1.6-alpha.2` lost the session to it, and
|
|
7
|
+
the diagnosis had to be rebuilt from scratch on 2026-09-19.
|
|
8
|
+
|
|
9
|
+
Authority: upstream [discussion 783](https://github.com/deepseek-ai/deepseek-harness/discussions/783)
|
|
10
|
+
names the mechanism for global installs; the 2026-09-19 probe (below) proved the
|
|
11
|
+
source-checkout variant and validated the fix end to end.
|
|
12
|
+
|
|
13
|
+
## When to use
|
|
14
|
+
|
|
15
|
+
- A DSH checkout just moved (pull / tag checkout / rebuild) and EVERY tool call
|
|
16
|
+
in EVERY session fails with `Cannot read properties of undefined (reading
|
|
17
|
+
'prepare')`, code `UNKNOWN`, ending the turn.
|
|
18
|
+
- Or the jump aborted earlier and `~/.dsh/sessions/**/session.v3.jsonl.zstd`
|
|
19
|
+
shows a `turn/end` with that exact message.
|
|
20
|
+
- Do NOT use for other `undefined` errors — the message must name `prepare`.
|
|
21
|
+
|
|
22
|
+
## The mechanism, in one paragraph
|
|
23
|
+
|
|
24
|
+
`packages/core/tools` exports `TOOL_RUNTIME_SCHEDULER = Symbol(...)` — a plain
|
|
25
|
+
Symbol, so each loaded copy of the module mints a distinct key. The tools
|
|
26
|
+
registry registers the scheduler under ONE copy's Symbol; the agent loop reads
|
|
27
|
+
it through the OTHER copy's Symbol; the lookup yields `undefined` and
|
|
28
|
+
`.prepare` throws. What splits the copies depends on launch mode: in a global
|
|
29
|
+
install it is a profile-local `pnpm install` materializing `@deepseek-ai/*`
|
|
30
|
+
under `~/.dsh/profiles/<name>/node_modules` (discussion 783); in a
|
|
31
|
+
source-checkout launch (`pnpm dsh …` = `node --import tsx/esm apps/cli/src/bin.ts`)
|
|
32
|
+
the 2026-09-19 probe caught the cordis plugin loader importing BOTH
|
|
33
|
+
`packages/core/tools/src/index.ts` (via tsx tsconfig `paths`) AND
|
|
34
|
+
`packages/core/tools/lib/index.js` (via package `exports`) in the same process.
|
|
35
|
+
Any jump that changes plugin resolution can re-trigger it.
|
|
36
|
+
|
|
37
|
+
## Confirm before fixing (2 minutes, optional but cheap)
|
|
38
|
+
|
|
39
|
+
Instrument both copies, reproduce, read the stacks:
|
|
40
|
+
|
|
41
|
+
```sh
|
|
42
|
+
# in the moved checkout, add after the Symbol line in BOTH
|
|
43
|
+
# packages/core/tools/src/index.ts and packages/core/tools/lib/index.js:
|
|
44
|
+
if (process.env.DSH_PROBE_SYMBOL) console.error('[PROBE]', import.meta.url, new Error('stack').stack)
|
|
45
|
+
|
|
46
|
+
export DSH_PROBE_SYMBOL=1
|
|
47
|
+
pnpm dsh --profile headless "Use the bash tool to run: echo probe" 2>&1 | grep PROBE
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Two `[PROBE]` lines with different URLs (one `src/`, one `lib/`, or two
|
|
51
|
+
distinct trees) = this bug. One line only = something else; stop and re-diagnose.
|
|
52
|
+
|
|
53
|
+
## The fix (validated 2026-09-19 against a pristine alpha.2 worktree)
|
|
54
|
+
|
|
55
|
+
Make the scheduler key copy-robust with the global symbol registry, in BOTH
|
|
56
|
+
copies of `packages/core/tools`:
|
|
57
|
+
|
|
58
|
+
- `src/index.ts`:
|
|
59
|
+
`export const TOOL_RUNTIME_SCHEDULER: unique symbol = Symbol.for('@deepseek-ai/dsh-tools.scheduler')`
|
|
60
|
+
- `lib/index.js` (after the line `const TOOL_RUNTIME_SCHEDULER = …`):
|
|
61
|
+
`Symbol.for("@deepseek-ai/dsh-tools.scheduler")`
|
|
62
|
+
|
|
63
|
+
Patching only one copy does NOT work — either copy may provide the registry or
|
|
64
|
+
read it, and a `Symbol.for` key on one side still mismatches a plain `Symbol()`
|
|
65
|
+
on the other.
|
|
66
|
+
|
|
67
|
+
## Verify, then clean up
|
|
68
|
+
|
|
69
|
+
1. Remove any `[PROBE]` instrumentation lines added above.
|
|
70
|
+
2. Headless proof (isolated home so the running web host is untouched):
|
|
71
|
+
```sh
|
|
72
|
+
export DSH_HOME="$(mktemp -d)" && cp ~/.dsh/settings.yaml "$DSH_HOME/"
|
|
73
|
+
export ZAI_API_KEY="$(grep -oE 'ZAI_API_KEY=?["'"'"']?[A-Za-z0-9._-]+' ~/.zshrc | head -1 | sed -E 's/^ZAI_API_KEY=?["'"'"']?//')"
|
|
74
|
+
pnpm dsh --profile headless "Use the bash tool to run: echo <tag> — then reply with exactly its output."
|
|
75
|
+
```
|
|
76
|
+
Green = the reply is exactly the echoed tag.
|
|
77
|
+
3. Web profile: boot briefly with the isolated `DSH_HOME`; plugin activation
|
|
78
|
+
must pass (an `EADDRINUSE` on the running host's port means plugins are
|
|
79
|
+
healthy). Only then restart the real `pnpm dsh web`.
|
|
80
|
+
|
|
81
|
+
## Standing caveats
|
|
82
|
+
|
|
83
|
+
- `lib/` is a build artifact: re-apply the lib patch after every
|
|
84
|
+
`pnpm run build`. The src patch dirties the tree across pulls — re-apply
|
|
85
|
+
after checking out a new edition, drop when upstream adopts the fix.
|
|
86
|
+
- Never commit the patched files; this is a local unblock only.
|
|
87
|
+
- The error also litters the session ledger with orphan `tool/call` events
|
|
88
|
+
(persisted before the throwing lookup). DeepSeek's endpoint rejects later
|
|
89
|
+
turns of such sessions with a 400 (`tool_calls` must be followed by `tool`
|
|
90
|
+
messages) — affected sessions are lost for that provider; start a new session
|
|
91
|
+
rather than resuming.
|
|
92
|
+
|
|
93
|
+
## Retire this skill when
|
|
94
|
+
|
|
95
|
+
Upstream ships the key as `Symbol.for` (or otherwise guarantees singleton
|
|
96
|
+
resolution) in a tag this machine runs — verify with:
|
|
97
|
+
`git grep -n "Symbol.for('@deepseek-ai/dsh-tools.scheduler')" <tag> -- packages/core/tools/src/index.ts`,
|
|
98
|
+
then delete the repo copy and the mirror and note the retirement in the DSI
|
|
99
|
+
release KB note covering that jump.
|
|
@@ -0,0 +1,150 @@
|
|
|
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
|
+
| Plugin installed | `grep @openviking ~/.dsh/profiles/web/package.json` + `ls ~/.dsh/profiles/web/node_modules/@openviking/dsh-memory-plugin` | both the bundle entry and the package exist |
|
|
21
|
+
| MCP connection | harness tool list shows `mcp__openviking__*` | tools present |
|
|
22
|
+
|
|
23
|
+
- Health fails + `ov.conf` missing → **Recovery path (§2)**, the common case.
|
|
24
|
+
- Health fails + `ov.conf` exists → run `openviking-server doctor`, fix what it names, go to §2 step 4.
|
|
25
|
+
- Plugin missing from manifest or `node_modules` → reinstall via the sanctioned path (§2 step 6): from the running host's checkout, `pnpm dsh plugin --profile web add @openviking/dsh-memory-plugin`. This persists both the dependency and the `dsh.profile.bundles` entry, so profile rebuilds keep it. A bare `pnpm install` in the profile dir is a dead end — bundles are not `dependencies` and pnpm reports "Already up to date" while the plugin stays missing (RCA 2026-09-18 — The Vanished Plugin).
|
|
26
|
+
- 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.
|
|
27
|
+
- Package missing → fresh install: do §2 steps 1–6 from scratch.
|
|
28
|
+
|
|
29
|
+
## 1. Facts to keep straight (most-confused pair)
|
|
30
|
+
|
|
31
|
+
- `~/.openviking/ovcli.conf` — **client** pointer: `{"url": "http://127.0.0.1:1933", "api_key": ""}`. Missing it breaks CLI commands only.
|
|
32
|
+
- `~/.openviking/ov.conf` — **server** model config (embedding + VLM). Missing it means the server process cannot start at all. This is the usual blocker.
|
|
33
|
+
- 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.
|
|
34
|
+
- `openviking`/`ov` = CLI/SDK; `openviking-server` = the daemon. Same pip package.
|
|
35
|
+
|
|
36
|
+
## 2. Recovery / install path
|
|
37
|
+
|
|
38
|
+
### Step 1 — Install the package (skip if `openviking-server --version` works)
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
pip install openviking --upgrade --force-reinstall
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Entry points land in `~/.local/bin`: `ov`, `openviking`, `openviking-server`, `vikingbot`.
|
|
45
|
+
|
|
46
|
+
### Step 2 — CLI housekeeping
|
|
47
|
+
|
|
48
|
+
```sh
|
|
49
|
+
ov language en # v0.3.23+ refuses most commands without this; writes ovcli.settings.conf
|
|
50
|
+
ov config add custom --name local --url http://127.0.0.1:1933 --activate -o json # only if ovcli.conf missing
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Note: both write under `~/.openviking/` — they fail under a workspace-only file sandbox; run with full file access.
|
|
54
|
+
|
|
55
|
+
### Step 3 — Create the server config: `openviking-server init`
|
|
56
|
+
|
|
57
|
+
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:
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
1 # mode: step-by-step
|
|
61
|
+
3 # embedding: lightweight CPU (llama.cpp, bge-small-zh-v1.5-f16, no key)
|
|
62
|
+
1 # embedding model: (only option — EASY TO MISS; missing this shifts every later answer)
|
|
63
|
+
6 # VLM: GLM (subscription API key)
|
|
64
|
+
2 # GLM plan: coding
|
|
65
|
+
<key> # API key — pass via stdin from an env var; NEVER in the command line or logs
|
|
66
|
+
N # query planner via Ollama: no
|
|
67
|
+
1 # bind 127.0.0.1 (dev, no auth)
|
|
68
|
+
1933 # port
|
|
69
|
+
Y # save
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
After saving the wizard echoes the resolved API key in its summary — **redact any captured log** before storing it.
|
|
73
|
+
|
|
74
|
+
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.
|
|
75
|
+
|
|
76
|
+
### Step 4 — Wait out the build
|
|
77
|
+
|
|
78
|
+
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"`.
|
|
79
|
+
|
|
80
|
+
### Step 5 — Validate and start
|
|
81
|
+
|
|
82
|
+
```sh
|
|
83
|
+
openviking-server doctor # expect: all checks PASS (config, auth, disk ≥ several GB)
|
|
84
|
+
openviking-server # foreground proof; then move to a supervisor
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Sandbox warning: server startup acquires a PID lock at
|
|
88
|
+
`~/.openviking/data/.openviking.pid` — under a workspace-only file sandbox it
|
|
89
|
+
dies with `PermissionError` / exit 3 at once. Start the server with full file
|
|
90
|
+
access (same as step 2's CLI housekeeping).
|
|
91
|
+
|
|
92
|
+
For persistence: launchd/nohup/systemd — never rely on an agent shell outliving the session. Verify:
|
|
93
|
+
|
|
94
|
+
```sh
|
|
95
|
+
curl -s http://127.0.0.1:1933/health # {"status":"ok","healthy":true,...}
|
|
96
|
+
ov status # "Connected (Healthy)", queue 0 pending / 0 errors
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
A stale `~/.openviking/pending/` queue (hundreds of files) from the downtime drains on its own — do not delete it.
|
|
100
|
+
|
|
101
|
+
### Step 6 — Confirm the integration
|
|
102
|
+
|
|
103
|
+
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`).
|
|
104
|
+
|
|
105
|
+
If the plugin must be (re)installed, run from the **running host's checkout** (find it: `lsof -p <dsh-web-pid> | grep cwd`):
|
|
106
|
+
|
|
107
|
+
```sh
|
|
108
|
+
pnpm dsh plugin --profile web add @openviking/dsh-memory-plugin
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
This is the only install path that reconciles `dsh.profile.bundles` and survives profile rebuilds. With `patchReload: "live"` in the manifest the profile recomposes without a host restart and `<openviking-context>` returns mid-session.
|
|
112
|
+
|
|
113
|
+
## 3. Verification checklist (all seven, in order)
|
|
114
|
+
|
|
115
|
+
1. `openviking-server --version` → prints version
|
|
116
|
+
2. `ls ~/.openviking/ov.conf ~/.openviking/ovcli.conf` → both exist
|
|
117
|
+
3. `openviking-server doctor` → all PASS
|
|
118
|
+
4. `curl -s http://127.0.0.1:1933/health` → `"healthy":true`
|
|
119
|
+
5. `ov status` → Connected (Healthy), 0 errors
|
|
120
|
+
6. `ov find "smoke test"` after any resource exists → ranked hits, not a connection error
|
|
121
|
+
7. New session → `<openviking-context>` block present
|
|
122
|
+
|
|
123
|
+
## 4. Known traps
|
|
124
|
+
|
|
125
|
+
- `ov status` saying "Unreachable" while the server is fine → the language gate; run `ov language en` first.
|
|
126
|
+
- Two config files, one directory (§1) — check the right one for the symptom.
|
|
127
|
+
- `auth_mode: "dev"` = no auth, localhost only. Never bind `0.0.0.0` without switching to API-key auth (docs: Authentication guide).
|
|
128
|
+
- Piped `init` answers are prompt-order-fragile (Step 3) — count prompts, don't trust defaults.
|
|
129
|
+
- 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.
|
|
130
|
+
|
|
131
|
+
## 5. Report the run — always, before finishing
|
|
132
|
+
|
|
133
|
+
Every execution of this skill — recovery, install, or clean-bill-of-health —
|
|
134
|
+
ends by writing an RCA report so the next run diffs from a written baseline.
|
|
135
|
+
|
|
136
|
+
- Path: `~/.dsi/dev/ov/YYYY-MM-DD HH-MM - <Short Name> — <What Happened>.md`
|
|
137
|
+
(mkdir the directory first; date = when the analysis ran, 24h `HH-MM` to
|
|
138
|
+
keep colons out of the filename).
|
|
139
|
+
- Required sections: TL;DR (+ layman glossary), symptom & diagnosis path
|
|
140
|
+
(the §0 gate table with pass/fail per gate), one RCA block per root cause
|
|
141
|
+
with file/line evidence, a mermaid **flowchart** (the journey, failed
|
|
142
|
+
branches colored) and a mermaid **sequenceDiagram** (who talks to whom),
|
|
143
|
+
fix application & testing (command → result table), corrective actions,
|
|
144
|
+
and a closing **open question**.
|
|
145
|
+
- Exemplar: `~/.dsi/dev/ov/2026-09-18 09-56 - The Vanished Plugin and the
|
|
146
|
+
Sandboxed Lock — OpenViking Recovery RCA.md`.
|
|
147
|
+
- If the run surfaced a new trap or fixed a gap in this skill, update this
|
|
148
|
+
SKILL.md (repo copy at `deepseek-insight/.agents/skills/dsi-ov-setup/`),
|
|
149
|
+
then re-copy to the mirror `~/.agents/skills/dsi-ov-setup/` — a skill the
|
|
150
|
+
slash menu never sees is a skill nobody invokes.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dsi-sync
|
|
3
|
+
description: Use when the user runs /dsi-sync or says to sync/mirror DeepSeek Insight (DSI) to its GitHub mirror — re-syncs ~/agentic-ai/deepseek-insight into ~/github/deepseek-insight (excluding dev/ and .git/), then commits and pushes the mirror. Covers resync, commit, push, and no-change skip.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# DSI → GitHub Mirror Sync
|
|
7
|
+
|
|
8
|
+
Mirror DSI into a publishable GitHub repo, then commit & push. The mirror lives at
|
|
9
|
+
`~/github/deepseek-insight` and has its own `.git` (origin:
|
|
10
|
+
`git@github.com:mitmplay/deepseek-insight.git`). Never touch the mirror's `.git`
|
|
11
|
+
or DSI's `dev/` folder.
|
|
12
|
+
|
|
13
|
+
## Source of truth
|
|
14
|
+
|
|
15
|
+
- SOURCE: `~/agentic-ai/deepseek-insight/`
|
|
16
|
+
- MIRROR: `~/github/deepseek-insight/`
|
|
17
|
+
- EXCLUDED from sync (always): `dev/`, `.git/`
|
|
18
|
+
- The mirror's own `.git` is protected because rsync excludes `.git/` — with
|
|
19
|
+
`--delete`, excluded target paths are never deleted.
|
|
20
|
+
|
|
21
|
+
## 1. Re-sync
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
rsync -a --delete \
|
|
25
|
+
--exclude 'dev/' \
|
|
26
|
+
--exclude '.git/' \
|
|
27
|
+
~/agentic-ai/deepseek-insight/ \
|
|
28
|
+
~/github/deepseek-insight/
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Trailing slashes matter: they copy CONTENTS of source into target, not the folder itself.
|
|
32
|
+
|
|
33
|
+
## 2. Verify the exclusions held
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
test -d ~/github/deepseek-insight/dev && echo 'BAD: dev leaked' || echo 'ok: no dev'
|
|
37
|
+
test -d ~/github/deepseek-insight/.git && echo 'ok: .git intact' || echo 'BAD: .git lost'
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
If either BAD line prints, stop and fix before committing — do not push a broken mirror.
|
|
41
|
+
|
|
42
|
+
## 3. Commit & push (skip if nothing changed)
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
cd ~/github/deepseek-insight
|
|
46
|
+
git add -A
|
|
47
|
+
if git diff --cached --quiet; then
|
|
48
|
+
echo 'no changes to sync'
|
|
49
|
+
else
|
|
50
|
+
git commit -m "sync from DSI $(date '+%Y-%m-%d %H:%M')"
|
|
51
|
+
git push origin main
|
|
52
|
+
fi
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
- Always use `git add -A` then check the staged diff — never commit blind.
|
|
56
|
+
- Quote the date format: `(date '+%Y-%m-%d %H:%M')` — unquoted, the space
|
|
57
|
+
word-splits the expansion and `date` errors with "illegal time format"
|
|
58
|
+
(observed 2026-09-18).
|
|
59
|
+
- Report to the user: file count changed (or "no changes"), commit hash, push result.
|
|
60
|
+
- If push is rejected (non-fast-forward), STOP and ask the user — never force-push
|
|
61
|
+
without explicit approval.
|
|
62
|
+
|
|
63
|
+
## Failure handling
|
|
64
|
+
|
|
65
|
+
- `rsync` errors: report the failing path; do not commit a partial sync.
|
|
66
|
+
- Remote unreachable (SSH): report the error verbatim; the sync itself is still
|
|
67
|
+
complete and committed locally.
|
|
68
|
+
- Mirror `.git` missing entirely: ask the user before re-initializing — do not
|
|
69
|
+
invent a remote URL.
|
package/README.md
CHANGED
|
@@ -1,48 +1,42 @@
|
|
|
1
1
|
# DeepSeek Insight
|
|
2
2
|
|
|
3
|
-
-
|
|
4
|
-
- [DeepSeek Insight](https://gitlab.com/wharsojo.dev/deepseek-insight) (DSI) shows you the **whole floor**
|
|
3
|
+
> [DeepSeek Insight](https://github.com/mitmplay/deepseek-insight) (**DSI**) **See your multiple agents run on the floor (agent, sub-agent, etc)**, each **conversation on the floor are updated instantly**.
|
|
5
4
|
|
|
6
|
-
>
|
|
5
|
+
> A `Control room` built on [Deepseek Harness's](https://github.com/deepseek-ai/deepseek-harness) (**DSH**) **records**: any (running) session, show side by side on the floor; **Lineage tree** of **parent to sub-agents**; Clean conversation with **tool-call(s) chips** with status **+** auto-expand **thingking chips**.
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
> A `Prompt Input` with **Slash-command(/)**, **Macros(!)** and **Auto-complete(?)**. Prompt-manager you can search it and to manage macros & autocomplete; user-prompts worth keeping is one-click-away tobe reuse.
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
>
|
|
9
|
+
> Included skills for:
|
|
10
|
+
> - Spec and Tasks execution,
|
|
11
|
+
> - Integration helper for [OpenViking](https://openviking.ai/)
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
> **Your language.** The interface speaks English, Chinese, Indonesian & Spanish.
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
<details>
|
|
16
|
+
<summary>Deepseek-insight-panels</summary>
|
|
17
|
+
<img src="docs/images/deepseek-insight-panels.png"/>
|
|
18
|
+
</details>
|
|
16
19
|
|
|
17
|
-
|
|
18
|
-
- **The workspace explorer, with git diff.** A side panel shows the files your agent is touching. Changed files are flagged and pulsing while the agent works; click one and you get a **real git diff** — additions in green, removals in red — rendered from the file's live buffer, so it updates as the agent edits and refreshes if you (or anything else) change the file underneath.
|
|
19
|
-
- **Presets and workspaces.** Start each chat with the right agent for the job — a coder, a researcher, a generalist — pointed at the right folder.
|
|
20
|
-
- **Many conversations, one page.** Conversations live in panels you can open side by side; compare two runs, or keep a scratch chat next to the main one.
|
|
21
|
-
- **A family tree under every chat.** When your agent spawns sub-agents, they appear as their own panels **below the parent that made them** — a ghost-tinted panel that stays put on refresh, so you always know who was working for whom. And when one conversation is worth a second try, **fork it**: one click clones the loaded context into a fresh session that starts exactly where the original stood — same history, new task.
|
|
22
|
-
- **A prompt library that files itself.** Save any bubble into the library and give it short filing words (tags) at save time; filter the prompt manager by tag chips or `+tag` words in the search box, and narrow the suggestion strip with its own tag chips — filters survive a reload. Tune the offered tags in `~/.dsi/settings.yaml` under `prompts.tags`.
|
|
23
|
-
- **Your language.** The interface speaks English, Chinese, and Indonesian.
|
|
20
|
+
---
|
|
24
21
|
|
|
25
|
-
|
|
22
|
+
## Quick Start
|
|
26
23
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
```sh
|
|
24
|
+
```bash
|
|
30
25
|
npx @deepseek-insight/dsi@latest dsh --sync --zai
|
|
26
|
+
# Open http://localhost:5174
|
|
31
27
|
```
|
|
32
28
|
|
|
33
|
-
|
|
29
|
+
- **`npx @deepseek-insight/dsi@latest`** — get latest DSI.
|
|
30
|
+
- `dsh` — starts **DSH** (`dsh web`) and **DSI** together, as one pair and runs it.
|
|
31
|
+
- `--sync` — copies DSH token to DSI config — **one window, one Ctrl-C stops both**.
|
|
32
|
+
- `--zai` — **optional.** It bootstraps the GLM (Z.AI) provider into the harness settings (`~/.dsh/settings.yaml`). **If you do not have a GLM account, simply leave it off** — DSI will use whatever provider your harness is already configured with.
|
|
33
|
+
|
|
34
34
|
|
|
35
|
-
- `npx @deepseek-insight/dsi@latest` — fetches the newest published DSI and runs it, **no install step**; nothing is added to your project, and `@latest` is what keeps it the latest.
|
|
36
|
-
- `dsh` — talk to the harness side: this subcommand starts the **DSH host** (`dsh web`) and the **DSI page** together, as one pair.
|
|
37
|
-
- `--sync` — copies the harness one-time launch token into DSI config (`~/.dsi/settings.yaml`) so the page can speak to the host, then serves both in the foreground — **one window, one Ctrl-C stops both**.
|
|
38
|
-
- `--zai` — **optional.** It bootstraps the GLM (Z.AI) provider into the harness settings (`~/.dsh/settings.yaml`). **If you do not have a GLM account, simply leave it off** — DSI will use whatever provider your harness is already configured with:
|
|
39
35
|
|
|
40
|
-
```sh
|
|
41
|
-
npx @deepseek-insight/dsi@latest dsh --sync
|
|
42
|
-
```
|
|
43
36
|
|
|
44
|
-
When it is up, your browser opens the page by itself (default `http://127.0.0.1:5174`).
|
|
37
|
+
When it is up, your browser opens the page by itself (default `http://127.0.0.1:5174`).
|
|
45
38
|
|
|
46
39
|
## License
|
|
47
40
|
|
|
48
|
-
[Apache-2.0](LICENSE) — Copyright © 2026 Widi Harsojo
|
|
41
|
+
[Apache-2.0](LICENSE) — Copyright © 2026 [Widi Harsojo](https://www.linkedin.com/in/wharsojo/)
|
|
42
|
+
> OPEN TO WORK (SG_PR)
|
package/bin/dsi.mjs
CHANGED
|
@@ -4,14 +4,19 @@
|
|
|
4
4
|
// prepares the artifacts, this launcher only runs them. The build is resolved
|
|
5
5
|
// relative to this file, not the cwd, so a globally installed or npx-run
|
|
6
6
|
// package serves its own bundled build from any directory.
|
|
7
|
-
// `dsi
|
|
8
|
-
// default model to ~/.dsh/settings.yaml
|
|
7
|
+
// `--zai` (on `dsi web` / `dsi dsh --sync`) bootstraps a fresh DSH install:
|
|
8
|
+
// it adds the ZAI provider and the default model to ~/.dsh/settings.yaml
|
|
9
|
+
// (idempotent — existing entries win). The standalone `dsi zai` command was
|
|
10
|
+
// decommissioned — the flag does the same work before anything boots.
|
|
9
11
|
// `dsi dsh --token <token>` copies a dsh launch token into DSI's config
|
|
10
12
|
// ($DSI_CONFIG_PATH or ~/.dsi/settings.yaml, key dsh.authToken — the same
|
|
11
13
|
// file scripts/dsh-web-synced.sh keeps fresh). `dsi dsh --sync` runs that
|
|
12
14
|
// script AND serves the dsi build — one foreground pair, one Ctrl-C.
|
|
13
15
|
// `--dev` serves the Vite dev server instead of the build (sources only).
|
|
14
16
|
// `dsi dsh --sync-kills` sweeps orphans a lost previous run left behind.
|
|
17
|
+
// `dsi dsh --ov` (or --sync --ov, or web --ov) installs the OpenViking
|
|
18
|
+
// memory plugin into
|
|
19
|
+
// the active dsh profile by delegating to `dsh plugin ... add` (idempotent).
|
|
15
20
|
|
|
16
21
|
import { spawn, spawnSync } from 'node:child_process';
|
|
17
22
|
import net from 'node:net';
|
|
@@ -53,6 +58,9 @@ const USAGE = [
|
|
|
53
58
|
' port 5175; needs a full checkout: pnpm install)',
|
|
54
59
|
' --sync-kills',
|
|
55
60
|
' kill orphaned dsh/dsi processes left by an earlier run',
|
|
61
|
+
' --ov install the OpenViking memory plugin into the active dsh',
|
|
62
|
+
' profile (dsh plugin ... add). Client only — the memory',
|
|
63
|
+
' server itself is set up separately (dsi-ov-setup skill)',
|
|
56
64
|
'',
|
|
57
65
|
' Ports: `dsi dsh --sync` serves the DSI page on 5174 and opens your',
|
|
58
66
|
' browser there. With --dev the Vite dev server takes 5175 instead',
|
|
@@ -60,16 +68,17 @@ const USAGE = [
|
|
|
60
68
|
'',
|
|
61
69
|
' All commands (flags — see above):',
|
|
62
70
|
'',
|
|
63
|
-
' dsi web [--zai] [--dev] [--token <token>]',
|
|
71
|
+
' dsi web [--zai] [--ov] [--dev] [--token <token>]',
|
|
64
72
|
' serve the DSI page alone (PORT env default 5174,',
|
|
65
73
|
' HOST env default 127.0.0.1)',
|
|
66
|
-
' dsi zai add the ZAI provider + default model to',
|
|
67
|
-
' ~/.dsh/settings.yaml',
|
|
68
74
|
' dsi dsh --token <token>',
|
|
69
75
|
' store the dsh launch token in ~/.dsi/settings.yaml',
|
|
70
|
-
' dsi dsh --sync [--zai] [--dev]',
|
|
76
|
+
' dsi dsh --sync [--zai] [--dev] [--ov]',
|
|
71
77
|
' run dsh-web-synced.sh (dsh web + token sync) AND serve',
|
|
72
78
|
' dsi — see the recommended command above',
|
|
79
|
+
' dsi dsh --ov',
|
|
80
|
+
' install the OpenViking memory plugin into the active',
|
|
81
|
+
' dsh profile (idempotent; alone, without --sync)',
|
|
73
82
|
' dsi dsh --sync-kills',
|
|
74
83
|
' kill orphaned dsh/dsi processes left by an earlier run'
|
|
75
84
|
].join('\n');
|
|
@@ -79,7 +88,7 @@ if (command === '--help' || command === '-h' || command === 'help') {
|
|
|
79
88
|
console.log(USAGE);
|
|
80
89
|
process.exit(0);
|
|
81
90
|
}
|
|
82
|
-
if (command !== 'web' && command !== '
|
|
91
|
+
if (command !== 'web' && command !== 'dsh') {
|
|
83
92
|
console.error(command === undefined ? 'dsi: missing command' : `dsi: unknown command "${command}"`);
|
|
84
93
|
console.error(USAGE);
|
|
85
94
|
process.exit(64);
|
|
@@ -87,6 +96,11 @@ if (command !== 'web' && command !== 'zai' && command !== 'dsh') {
|
|
|
87
96
|
|
|
88
97
|
const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
89
98
|
|
|
99
|
+
/** The OpenViking memory plugin DSI's host profile wants. Client-side only:
|
|
100
|
+
* it never starts openviking-server — it reconnects on its own once the
|
|
101
|
+
* server is healthy (KB 2026-09-16 §2). */
|
|
102
|
+
const OV_PLUGIN = '@openviking/dsh-memory-plugin';
|
|
103
|
+
|
|
90
104
|
// ── dsi zai ────────────────────────────────────────────────────────────────
|
|
91
105
|
|
|
92
106
|
/** The ZAI provider block, byte-for-byte the fresh-install shape. */
|
|
@@ -124,11 +138,6 @@ function isRecord(value) {
|
|
|
124
138
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
125
139
|
}
|
|
126
140
|
|
|
127
|
-
if (command === 'zai') {
|
|
128
|
-
addZaiProvider();
|
|
129
|
-
process.exit(0);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
141
|
// ── dsi dsh ────────────────────────────────────────────────────────────────
|
|
133
142
|
|
|
134
143
|
/** One pkill -f sweep per orphan signature. The patterns match only the
|
|
@@ -156,6 +165,10 @@ if (command === 'dsh') {
|
|
|
156
165
|
setDshAuthToken(token);
|
|
157
166
|
process.exit(0);
|
|
158
167
|
}
|
|
168
|
+
if (flag === '--ov') {
|
|
169
|
+
runOvPlugin();
|
|
170
|
+
process.exit(0);
|
|
171
|
+
}
|
|
159
172
|
if (flag === '--sync') {
|
|
160
173
|
// --zai and --dev are dsi-side flags, stripped from the args the sync
|
|
161
174
|
// script forwards to `dsh web` (which would refuse them):
|
|
@@ -166,10 +179,12 @@ if (command === 'dsh') {
|
|
|
166
179
|
const rest = process.argv.slice(4);
|
|
167
180
|
const withZai = rest.includes('--zai');
|
|
168
181
|
const withDev = rest.includes('--dev');
|
|
182
|
+
const withOv = rest.includes('--ov');
|
|
169
183
|
if (withZai) addZaiProvider();
|
|
184
|
+
if (withOv) runOvPlugin();
|
|
170
185
|
runSkillsMirror();
|
|
171
186
|
runSyncedPair(
|
|
172
|
-
rest.filter((arg) => arg !== '--zai' && arg !== '--dev'),
|
|
187
|
+
rest.filter((arg) => arg !== '--zai' && arg !== '--dev' && arg !== '--ov'),
|
|
173
188
|
withDev
|
|
174
189
|
);
|
|
175
190
|
} else if (flag === '--sync-kills') {
|
|
@@ -387,6 +402,47 @@ function addZaiProvider() {
|
|
|
387
402
|
console.log(`dsi zai: ${settingsPath} updated — set ZAI_API_KEY in the harness env, then restart dsh web`);
|
|
388
403
|
}
|
|
389
404
|
|
|
405
|
+
/** Install the OpenViking memory plugin into the active dsh profile by
|
|
406
|
+
* delegating to `dsh plugin --profile <profile> add` — the same dsh
|
|
407
|
+
* launcher `dsi dsh --sync` uses (DSH_WEB_CMD override, else the published
|
|
408
|
+
* pin via npx). dsh's own reconcilePlugins appends the package to
|
|
409
|
+
* dsh.profile.bundles (it declares a dsh.bundle), so nothing is hand-edited
|
|
410
|
+
* here. Idempotent: a profile that already has the dependency AND the bundle
|
|
411
|
+
* entry skips the pnpm round-trip. Fail-loud: a nonzero child exit (or a
|
|
412
|
+
* missing pnpm — dsh exits 127 for it) propagates. */
|
|
413
|
+
function runOvPlugin() {
|
|
414
|
+
const profile = process.env.DSH_PROFILE ?? 'web';
|
|
415
|
+
const manifestPath = path.join(
|
|
416
|
+
homedir(), '.dsh', 'profiles', profile, 'package.json'
|
|
417
|
+
);
|
|
418
|
+
if (existsSync(manifestPath)) {
|
|
419
|
+
try {
|
|
420
|
+
const manifest = JSON.parse(readFileSync(manifestPath, 'utf-8'));
|
|
421
|
+
const deps = manifest?.dependencies ?? {};
|
|
422
|
+
const bundles = manifest?.dsh?.profile?.bundles ?? [];
|
|
423
|
+
if (deps[OV_PLUGIN] !== undefined && bundles.includes(OV_PLUGIN)) {
|
|
424
|
+
console.log(`dsi dsh: ${OV_PLUGIN} already installed in the ${profile} profile — nothing to do`);
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
} catch (error) {
|
|
428
|
+
console.error(`dsi dsh: cannot parse ${manifestPath}: ${error?.message ?? error}`);
|
|
429
|
+
process.exit(65);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
const cmd = process.env.DSH_WEB_CMD
|
|
433
|
+
? `${process.env.DSH_WEB_CMD} plugin --profile ${profile} add ${OV_PLUGIN}`
|
|
434
|
+
: `npx --yes @deepseek-ai/dsh@${dshWebVersion()} plugin --profile ${profile} add ${OV_PLUGIN}`;
|
|
435
|
+
console.log(`dsi dsh: installing ${OV_PLUGIN} into the ${profile} profile (${cmd})`);
|
|
436
|
+
const result = spawnSync('/bin/sh', ['-c', cmd], { stdio: 'inherit' });
|
|
437
|
+
if (result.error !== undefined) throw result.error;
|
|
438
|
+
const code = result.status ?? 1;
|
|
439
|
+
if (code !== 0) {
|
|
440
|
+
console.error(`dsi dsh: plugin install failed (exit ${code}) — pnpm on PATH is required; fix the cause above, then re-run`);
|
|
441
|
+
process.exit(code);
|
|
442
|
+
}
|
|
443
|
+
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)`);
|
|
444
|
+
}
|
|
445
|
+
|
|
390
446
|
/** Plant the shipped skills into the operator's skill mirror
|
|
391
447
|
* (~/.agents/skills) — ADR "The Skill Mirror" 2026-09-15, D1–D5:
|
|
392
448
|
* per-skill copy-only-if-absent, every repo skill, failures warn and
|
|
@@ -465,12 +521,14 @@ function startDsiServer(defaultPort = '5174') {
|
|
|
465
521
|
if (command === 'web') {
|
|
466
522
|
// Optional dsi-side flags, the same meanings as `dsi dsh --sync`: --zai
|
|
467
523
|
// bootstraps the ZAI provider BEFORE anything boots (so this run picks it
|
|
468
|
-
// up), --token stores the dsh launch token before the page serves, --
|
|
469
|
-
//
|
|
524
|
+
// up), --token stores the dsh launch token before the page serves, --ov
|
|
525
|
+
// installs the OpenViking memory plugin, --dev swaps the built server for
|
|
526
|
+
// the Vite dev server. Everything is done
|
|
470
527
|
// first, then the one child spawns and the script falls off the end.
|
|
471
528
|
const rest = process.argv.slice(3);
|
|
472
529
|
const withZai = rest.includes('--zai');
|
|
473
530
|
const withDev = rest.includes('--dev');
|
|
531
|
+
const withOv = rest.includes('--ov');
|
|
474
532
|
const tokenIdx = rest.indexOf('--token');
|
|
475
533
|
let token;
|
|
476
534
|
if (tokenIdx !== -1) {
|
|
@@ -481,7 +539,7 @@ if (command === 'web') {
|
|
|
481
539
|
}
|
|
482
540
|
}
|
|
483
541
|
const unknown = rest.filter((arg, i) =>
|
|
484
|
-
arg !== '--zai' && arg !== '--dev'
|
|
542
|
+
arg !== '--zai' && arg !== '--ov' && arg !== '--dev'
|
|
485
543
|
&& arg !== '--token' && !(tokenIdx !== -1 && i === tokenIdx + 1)
|
|
486
544
|
);
|
|
487
545
|
if (unknown.length > 0) {
|
|
@@ -490,9 +548,14 @@ if (command === 'web') {
|
|
|
490
548
|
process.exit(64);
|
|
491
549
|
}
|
|
492
550
|
if (withZai) addZaiProvider();
|
|
551
|
+
if (withOv) runOvPlugin();
|
|
493
552
|
if (token !== undefined) setDshAuthToken(token);
|
|
494
553
|
runSkillsMirror();
|
|
495
554
|
const child = withDev ? startDsiDevServer() : startDsiServer();
|
|
555
|
+
// Same browser-follows-the-UI contract as the pair (runSyncedPair): open
|
|
556
|
+
// the default browser at the serving port — --dev's Vite server takes
|
|
557
|
+
// 5175, the built server 5174; PORT/HOST overrides apply.
|
|
558
|
+
openBrowser(`http://${process.env.HOST ?? '127.0.0.1'}:${process.env.PORT ?? (withDev ? '5175' : '5174')}/`);
|
|
496
559
|
|
|
497
560
|
for (const signal of ['SIGINT', 'SIGTERM']) {
|
|
498
561
|
process.on(signal, () => {
|