- JavaScript 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| .gitignore | ||
| fj.mjs | ||
| patch.mjs | ||
| publish.mjs | ||
| README.md | ||
| sync-repos.mjs | ||
dsh fork utilities
Utilities for maintaining forked DSH plugins on your own Forgejo instance.
The DSH webserver plugin only allows binding to 127.0.0.1 or 0.0.0.0,
which is too restrictive for container use. These tools let you patch the
plugin and publish a forked version under your own npm scope.
Layout
| File | Purpose |
|---|---|
fj.mjs |
Minimal Forgejo REST + npm-registry client (no deps). |
patch.mjs |
Re-apply the two source patches to the npx cache. |
publish.mjs |
Rewrite package.json and npm publish a fork to the registry. |
sync-repos.mjs |
Push source files to a Forgejo git repo via the contents API. |
One-time setup
Two credentials are needed: a personal access token for the REST API and the npm registry, and an SSH key for git operations.
SSH key (for git push/pull)
ssh-keygen -t ed25519 -C "dsh@fake.com" -f /root/.ssh/dsh-forgejo -N ""
PUBKEY=$(cat /root/.ssh/dsh-forgejo.pub)
curl -X POST -H "Authorization: token <your-token>" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg k "$PUBKEY" '{key: $k, title: "dsh-container", read_only: false}')" \
https://git.kytech.fr/api/v1/user/keys
Then add to ~/.ssh/config:
Host git.kytech.fr
HostName git.kytech.fr
Port 2222
User git
IdentityFile /root/.ssh/dsh-forgejo
IdentitiesOnly yes
Convert any existing remotes:
git remote set-url origin git@git.kytech.fr:<owner>/<repo>.git
REST API + npm registry token (for the API and npm publish)
Generate an access token on the Forgejo instance (Settings → Applications), then:
export FORGEJO_BASE=https://git.kytech.fr
export FORGEJO_TOKEN=<your-token-here>
Security notes:
- Never commit the token. Keep it in
~/.npmrcor env vars only. - The
publish.mjsandsync-repos.mjsscripts explicitly skip.npmrc,.git,node_modules, and.publish-staging/to prevent accidental leaks. - The npm tarball's
package.jsonfilesfield must list only the runtime assets; never include.npmrcinfiles.
Workflow
1. Re-apply patches to the npx cache (fast, no install)
The npx cache at /root/.npm/_npx/<hash>/node_modules/ already contains the
full dsh tree. Patching files in place is instantaneous and survives across
npx runs. This is the recommended way to use the fork on the agent's
container, because doing a full npm install @deepseek-ai/dsh pulls ~80
packages and is very slow.
node patch.mjs # apply
node patch.mjs --check # report only
Then run dsh normally:
npx @deepseek-ai/dsh web --host 10.20.194.127 --no-open
2. Publish a fork to the registry (slow, real install)
Use this when you want a clean install path (npm install @dsh/dsh-...)
instead of patching the cache.
# 1. Get a clean copy of the upstream package
npm pack @deepseek-ai/dsh-host-webserver
mkdir build/dsh-host-webserver && tar -xzf deepseek-ai-dsh-host-webserver-*.tgz -C build/dsh-host-webserver --strip-components=1
# 2. Apply your edits in build/dsh-host-webserver/lib/index.js
# 3. Publish
node publish.mjs --pkg ./build/dsh-host-webserver --scope dsh --version 0.0.1-rc.1
3. Mirror the source to a git repo
node sync-repos.mjs --pkg ./build/dsh-host-webserver --owner dsh --repo dsh-host-webserver
What the patches do
@deepseek-ai/dsh-host-webserver/lib/index.js — relax the bind host from
z.union([z.const("127.0.0.1"), z.const("0.0.0.0")]) to
z.string().min(1).default("127.0.0.1"). This is required for --host to
accept a real interface IP (e.g. 10.20.194.127).
@deepseek-ai/dsh-web-app/lib/startup.js — drop the early-reject of
--host 0.0.0.0. Newer npm versions already allow it; the patch is here for
older npx caches that still have the block.
@deepseek-ai/dsh-client-ui-conversation/lib/client.js — six small
edits to add an "Edit" button under user messages. Hovering a user message
now shows: ⏱ Copy · Edit · Branch. Clicking Edit copies the message
text into the prompt input and focuses it. Implementation:
MessageIconActionsgains anonEditprop and renders a Tooltip-wrapped button withIconEditOutline16right after Copy, only whenonEditis provided.UserStyleBubbleaccepts anonEditprop and forwards it to theactionscallback.UserMessageNodeViewreadsinputActionsfrom the session scope's standard kit, builds anonEditcallback that callsinputActions.setDraft(text)and focuses the textarea via a microtaskdocument.querySelector("[data-input-backdrop] textarea, ...")selector. Assistant messages are untouched (noonEditpassed).
The fork is also published as @dsh/dsh-client-ui-conversation for use
with npm overrides.
Already-published packages
@dsh/dsh-host-webserver@0.0.1-rc.1— patched webserver@dsh/dsh-web-app@0.0.1-rc.1— patched web app (depends on the above)@dsh/dsh-client-ui-conversation@0.0.1-rc.1— patched conversation UI (Edit button on user messages)
Installable directly:
npm install --registry=https://git.kytech.fr/api/packages/dsh/npm/ \
@dsh/dsh-host-webserver @dsh/dsh-client-ui-conversation
Reloading the running browser
The patches in the npx cache only take effect when dsh re-reads the file
on next startup. The HMR chain (dsh --dev) auto-detects changes via
mtime polling, but only if started with --dev. Without --dev, restart
dsh and reload the page to see new patches.