dsh-um-proxy-ondemand
Manages the lifecycle of the local UM GenAI proxy (127.0.0.1:8788) that DSH's um-genai provider talks to: wakes it on demand for llm/stream calls, stops it after an idle period, and reports health plus a read-only status endpoint. Also ships a DSH settings page for port, always-on mode, idle minutes
Install
dsh plugin --profile web add dsh-um-proxy-ondemand
Sandbox test results
| Stage | Result |
|---|---|
| 1 install | ✓ |
| 2 list | ✓ |
| 3 mount | ✓ |
| 4 boot | — |
Four stages run in an isolated sandbox: install (network on) → list → mount → boot (last three with no network).
README
dsh-um-proxy-ondemand
讓 UM GenAI 本機代理(http://127.0.0.1:8788)只在你真的用到它的時候才活著。
DSH 的 um-genai provider 指向這個代理;以前它靠一個「登入時啟動 + 每 2 分鐘保活」
的排程工作常駐,即使整天沒用到該模型也一直佔著一個 Python 行程(以及它自己的
headless Chrome)。這個外掛把它改成 按需喚醒 + 閒置 15 分鐘自動關閉。
安裝
前置條件
需要 · 說明
UM 帳號 · 本外掛服務的是澳門大學的 GenAI 校園 gateway(https://chat.genai.um.edu.mo)。沒有 UM 帳號就沒有東西可以代理。
um_opencode_setup.py · 代理本體(OpenAI 相容的本機服務),UM 校內發放的單檔工具。外掛自帶一份在 [vendor/um_opencode_setup.py](vendor/um_opencode_setup.py),所以乾淨的機器裝完就能直接跑。~/.um-opencode/ 那份優先(你自己更新過、或 UM 發了新版就以它為準),家目錄沒有才退回自帶副本;只有在兩邊都沒有時才會失敗。
Node.js 22 以上 · 宿主本身的需求;跑本 repo 的測試要 24(用到實驗性的 module mock)。
Python 3.10 以上 · 建議 3.12。Windows 安裝時勾 Add python.exe to PATH,或稍後在設定頁直接填絕對路徑。
外掛不是模型、不產生 token、不代理其他 provider。它管的只有一件事:那個本機代理行程的生死。代理本體是 UM 發放的um_opencode_setup.py,本 repo 只附一份原封不動的副本(見 [vendor/](vendor/))。
安裝指令
dsh plugin --profile desktop add dsh-um-proxy-ondemand
這是首選:從 npm registry 抓發佈快照(latest 標籤,目前是 1.4.x),不必讓 pnpm 從 git 建置,也吃得到 registry 的快取。
想跟 main 最新 commit(例如還沒發版的修正)就改用 git 來源:
dsh plugin --profile desktop add github:TINGOD2006/dsh-um-proxy-ondemand
兩者差別只在版本來源:npm 版是發佈當下的快照,github: 版跟著 main 走、每次裝都是當下最新的 commit。功能上沒有其他差異,vendor/um_opencode_setup.py 兩邊都有。
dsh plugin 會把參數原樣轉給 profile 目錄裡的 pnpm,裝好後 dsh.profile.bundles 會自動補上這一項。
裝完重新啟動 DSH(新增設定分頁需要重啟一次,之後改設定不用)。
兩個常見的卡點:
- 要用桌面版內建的
dsh。 桌面版的 profile 由 Electron 獨佔,npm 全域那份會直接拒絕:
error: profile "desktop" is managed exclusively by the Electron application。
確認 Get-Command dsh 第一個是 ...\DeepSeek Harness\resources\runtime\cli\bin\dsh.cmd。
- 檔案被佔用導致換不上(DSH 正開著、pnpm 拿不到檔案鎖)。完全退出 DSH,然後在 profile 目錄手動裝:
cd $env:USERPROFILE\.dsh\profiles\desktop pnpm add dsh-um-proxy-ondemand --config.minimum-release-age=0
再啟動 DSH。
第一次設定
外掛啟動時會自己推導預設值,多數情況不必填任何東西:
- 家目錄:
UM_OPENCODE_HOME有設就用它,否則~/.um-opencode。 - Python:
UM_PYTHON→%LOCALAPPDATA%\Programs\Python\Python3(取版本最高)→C:\Python3→PATH上的pythonw.exe。 - 代理腳本:
~/.um-opencode/um_opencode_setup.py優先,沒有才用外掛自帶的vendor/um_opencode_setup.py(lib/paths.js的resolveScript())。 - 日誌/狀態檔:都在家目錄下,狀態檔帶埠號(
ondemand-8788.state.json)。腳本自己的資料(token、credentials.dat、proxy.log)一律寫在家目錄,不會寫進外掛目錄。
要覆寫就到 DSH 設定 → 外掛 → 「UM 代理」 分頁,那裡有狀態列、一般設定(埠號、常駐模式、閒置分鐘、啟動逾時、Python 路徑、腳本路徑、日誌、狀態檔)、UM 帳號(寫入 um_opencode_setup.py set-credentials,密碼不經過命令列)、代理金鑰(UM_GENAI_API_KEY)。
同樣的值也可以直接寫進 profile 的 cordis.patch.yml:
- insert:
- id: dsh-um-proxy-ondemand
name: dsh-um-proxy-ondemand
config:
port: 8788
alwaysOn: true
# python: 'C:\Users\you\AppData\Local\Programs\Python\Python312\pythonw.exe'
# script: 'C:\Users\you\.um-opencode\um_opencode_setup.py'
模型選單(um-genai provider)
外掛不註冊 provider —— 它只負責那個代理行程的生死。DSH 模型選單裡的那些 UM 模型,來自內建的 @deepseek-ai/dsh-llm-pi-ai 底下的一段 providers.um-genai 設定,而那段設定寫在 profile 的 cordis.patch.yml,新裝的機器上本來沒有,所以選單會是空的。
補的方法有兩種:
1. 設定頁按鈕(建議):DSH 設定 → 外掛 →「UM 代理」→「模型選單(um-genai provider)」那張卡 → 按 建立 um-genai provider。它會用 configEditor 把 displayName / apiKeyEnv / api / baseURL / models 寫進 profile patch,接著跑 scripts/um-models-sync.py --apply 連本機代理抓 gateway 目前提供的模型 id(代理沒開會自己醒),最後提示你重啟 DSH。
2. 手動:把下面這段貼進 profile 的 cordis.patch.yml,再跑 python -B scripts/um-models-sync.py --apply 補模型清單。
- insert:
- id: llm-pi-ai
name: "@deepseek-ai/dsh-llm-pi-ai"
config:
providers:
um-genai:
displayName: UM GenAI (local proxy)
apiKeyEnv: UM_GENAI_API_KEY
api: openai-completions
baseURL: http://127.0.0.1:8788/v1
models: []
models: [] 只是佔位,um-models-sync.py --apply 會把它換成真正的清單(並留下 .bak-models-<時間> 備份)。跑完要重啟 DSH,選單才會重讀。
按鈕已經有 provider 時只會補缺的鍵,你手動調過的 displayName、埠號、模型子集都不會被蓋掉。
如果按鈕剛建立 provider 卻抓不到模型清單(最常見是還沒登入 UM 帳號、代理起不來),它會把剛寫進去的 provider 收回,而不是留下一個 models 空白的 provider —— 後者會讓 DSH 載入時直接報 provider "um-genai" resolves no models。先到「UM 帳號」登入、確認代理跑得起來,再按一次就好。
環境變數
變數 · 預設 · 作用
UM_OPENCODE_HOME · ~/.um-opencode · 代理腳本、日誌、狀態檔、續期看門狗紀錄的家目錄。JS 與 Python 兩邊共用同一條規則。
UM_PYTHON · 自動偵測 · 明確指定 Python 解譯器;設了就跳過偵測。
UM_UPSTREAM_BASE · https://chat.genai.um.edu.mo · 上游 gateway。換校區或測試環境才需要改。
UM_HIDDEN_LOGIN · 1 · 設 0 可關掉「隱藏桌面登入」,回到會彈出可見視窗的舊行為。
UM_TEST_PYTHON · — · 只影響測試,不影響正式代理。
驗證裝好了
# 代理本身(要先被喚醒過一次;alwaysOn: true 的話 DSH 一開就有)
curl.exe http://127.0.0.1:8788/health
# {"status":"ok","service":"um-opencode-proxy"}
# 外掛自己(把埠換成你 DSH 的 GUI 埠)
curl.exe http://127.0.0.1:<GUI埠>/um-proxy-ondemand/api/status
用curl.exe而不是curl:Windows PowerShell 5.1 把curl別名成Invoke-WebRequest,
參數與輸出都不是 curl 的樣子。
設定頁的「狀態」區塊看得到同樣的資訊:running、pid、alwaysOn、idleTimerArmed、請求數與喚醒數。/api/status 另外回報 host.script: { path, exists }——path 是實際會跑的那一份(家目錄或 vendor/),所以正常安裝下 exists 是 true;false 代表兩邊都找不到腳本,設定頁會同時顯示紅字警告。實際用法是回 DSH 選一個 um-genai 的模型送一句話——第一次會冷啟動(幾秒),之後走熱路徑。
常見錯誤
症狀 · 原因 · 處理
設定頁顯示「找不到腳本」 · ~/.um-opencode/um_opencode_setup.py 不存在,而且外掛自帶的 vendor/um_opencode_setup.py 也不在(例如只裝了 lib/、或有人刪掉了 vendor/) · 通常不必處理——自帶副本會接手。真的兩邊都沒有時:重裝外掛補回 vendor/,或把 UM_OPENCODE_HOME / 設定頁的「腳本路徑」指到正確位置
喚醒失敗,錯誤訊息是 proxy script not found: <路徑> — this file is not part of the plugin · 家目錄與 vendor/ 都沒有代理腳本,所以連 spawn 都沒發生。正常安裝下不該出現 · 這句是外掛自己給的(不是 Python 的 can't open file)。重裝外掛取回 vendor/ 副本,或把腳本放到那個路徑、設 UM_OPENCODE_HOME。狀態端點會回報 host.script: { path, exists: false },設定頁狀態區塊同時顯示紅字警告
冷啟動失敗,日誌有 ENOENT · Python 路徑不對 · 在設定頁填 pythonw.exe 的絕對路徑,或設 UM_PYTHON
回 401 · 上游 UM 登入 token 過期(不是 API key 錯) · 跑 `powershel
…(truncated)
Rendered from the README published on npm. Formatted only, not edited.
Versions
Published on npm::9,最后更新 2026-11-03