dsh-obsidian-bridge
A DeepSeek Harness (DSH) plugin that connects the served DSH Web GUI with
Obsidian running in an iframe next to it. One host module — index.mjs, a
plain DSH plugin with export const name / export function apply(ctx) and no
browser bundle of its own. The browser half is a single script it injects into
the served index.html.
What it adds
| Direction | Feature |
|---|---|
| Obsidian → DSH | Fill the composer draft from a selected region (postMessage dsh-fill-draft), with a reply the Obsidian side can act on (dsh-fill-ack: applied / stale / separator present). The injected script merges into what is already typed instead of overwriting it. |
| DSH → Obsidian | Open a file in Obsidian by clicking a path that appears in the chat (tool output, titles, file cards), and click [[wikilinks]] — the injected script renders them as links and forwards dsh-wikilink to the Obsidian side. |
| Obsidian → DSH | Keyboard shortcuts pressed inside the DSH iframe are forwarded to the host window (dsh-kbd-shortcut), with the Obsidian side pushing its key list through dsh-kbd-cfg. Editing keys (Enter, arrows, Ctrl+Z …) stay local. |
| DSH → agent | Edit-instruction injection. When the newest user message carries the implicit [BRIDGES is delivering packages for you…… · N words · L4:1-L9:20 · label ·] line, a pre-step hook turns it into a deterministic edit instruction ("read the region, present the result, ask for consent, then write it back with fs edit"). The instruction is delivered through the DSH-native one-shot inbox (agent.inbox.prepend('next-step', …)), so it never shows up in the chat transcript as a message of its own. |
| Embed auth | Cross-site iframe auth adapter (since 2.3.2). DSH's browser-session Strict cookie is structurally unusable inside a cross-site iframe, so this plugin accepts one extra credential: GET /?token=<T>&ob=1 answers 200 instead of the original 303 cookie flow (without ob, real browsers keep the original path untouched), and /api 401 verdicts are overridden when the request carries a matching Bearer header or query token. 403 fence verdicts are never touched. |
Requirements
- DSH
0.1.xwith awebprofile (the injected script targets the shipped Web GUI's DOM:textarea[data-phase],role="tree", the composer dock). - The Obsidian-side plugin that speaks the
dsh-*postMessageprotocol and pushesvaultRoot/ key bindings.
The host half is feature-detected: if a service or method it patches is missing (older DSH) or has moved (a refactor), the plugin degrades to inert instead of failing the profile.
Install
This plugin has no dsh.bundle metadata, so it is not installed with
dsh plugin add and does not appear on the sidebar 插件 page — the built-in
plugin manager owns bundles only. It is loaded as a plain plugin module by
absolute path, from the profile's own patch layer
(~/.dsh/profiles/web/cordis.patch.yml):
- insert:
- id: dsh-obsidian-bridge
name: file:///C:/Users/wuw/.dsh/profiles/web/dsh-obsidian-bridge/index.mjs
Point the file:// URL at wherever you keep this directory, then reload the
profile (HMR picks the patch layer up live).
Runtime files (not in git)
Written next to index.mjs on every injection attempt:
| File | Purpose |
|---|---|
inject-ledger.json |
Compaction-proof ledger: one entry per delivered instruction, keyed by sha256(path | location | instruction), plus per-session counters. |
inject-log.jsonl |
Append-only decision log (action, reason, keyHits, sessionCount); truncated past 256 KB. |
Both are per-install state, and the log records session activity — they are
listed in .gitignore and must stay out of the repository.
Injection limits
INJECT_LIMITS keeps a repeated selection from turning into a loop:
{ ttlMs: 600000, maxKeyHits: 1, maxSessionInjections: 20, maxItems: 200 }
One delivery per key within ten minutes, at most 20 per session, at most 200 ledger items retained.
Version notes
| Version | Change |
|---|---|
| 2.6.x | Current line; wikilink rendering, path → Obsidian clicks, UI-state pings. |
| 2.4.4 | Inject-once: editor instructions ride the one-shot inbox instead of appending a persisted user message every step; ledger and session cap added. |
| 2.3.2 | Embedder-auth adapter for DSH ≥ 0.1.2 browser-session auth inside cross-site iframes. |
Notes
- The plugin touches DSH only through the loader (rows, hooks, an
index.htmltransform) and the DSH web connection service's auth verdicts. No DSH source change is required, andindex.mjsis the whole host half. - No
licensefield is declared here, so the repository carries no license grant; add one before publishing.
No comments yet. Be the first to write one.