img-share 技能
把瀏覽器截圖或本地圖片變成聊天框內的可點大圖(縮圖+點擊看原圖),並且手機/其他設備也能存取。跨平台(Linux/macOS/WSL/Windows 原生均可使用)。
whenToUse(何時觸發)
- 使用者要「打開某個網站/頁面截圖給我」;
- 把某張圖貼到聊天框,且希望「手機也能看、能點開放放大看細節」;
- 想把工作區圖片做成可點大圖的聊天內嵌圖。
依賴
| 依賴 | 用途 | 取得 |
|---|---|---|
| web-access skill | 截圖(CDP 驅動瀏覽器) | 需安裝:https://github.com/eze-is/web-access |
| python3/python | 編排器(serve.py) | 系統內建 |
| cloudflared | 兜底公網隧道 | mac: brew install cloudflared;win: winget install Cloudflare.cloudflared;linux: 參見其官方 README;或設定 CLOUDFLARED=/路徑 |
| ffmpeg(可選) | 多圖拼網格 | 系統安裝(scripts/montage.sh 使用) |
執行步驟
-
宿主可達性判定(必選,最先做) —— 決定圖片 URL 的基址,以及是否需要另開公網隧道。圖片位址必須跟隨宿主位址,不要為了「能跑通」就擅自另開一條與宿主不同源的隧道:
判定 結論(行動) 宿主已被隧道化/公網可達(使用者手機正是透過該位址存取本會話),且宿主暴露了靜態圖片路徑(如 /img/*)圖片放進宿主靜態目錄,內嵌使用 宿主公網位址,不開新隧道 宿主公網可達,但未暴露靜態圖片路徑 不靜默兜底:先告訴使用者「需給宿主配置靜態圖片映射」;僅當使用者知情同意後才走「顯式獨立隧道兜底」 宿主僅 localhost(如 DSH_WEB_URL=http://127.0.0.1:*,未開公網)圖片只有本機/區域網路位址,手機本來也到不了本會話 —— 先提示使用者把 DSH 開成公網,或經使用者同意走顯式兜底;禁止把 localhost/127.0.0.1 位址內嵌並宣稱手機可看 探測不到 / 不確定 不猜測,先問使用者:「你手機存取本會話用的是哪個位址(公網域名還是 localhost)?」再按上表執行 探測方式:讀環境變數(
DSH_WEB_URL、DSH_PUBLIC_BASE、DSH_IMG_BASE等)、查宿主靜態路由配置;取不到即視為「宿主未提供」,按上表走「問使用者/提示」,不得靜默降級為另開隧道。宿主契約(前瞻約定,當前 DSH 宿主尚未提供):宿主若暴露
DSH_PUBLIC_BASE/DSH_IMG_BASE或等價的靜態路徑宣告,agent 必須優先將圖片掛到宿主域名下;未提供時不要假設存在。 -
截圖(如需):使用 web-access skill,
/screenshot渲染頁面成 PNG。- 若 CDP/Chromium 在受限環境跑不起來(禁聯網/程序崩潰),降級到雲端截圖:使用 thum.io / mshots / microlink 等,帶
?wait=N&width=W,返回後校驗「非白像素佔比>閾值、色簇數>N」,不是空白才可使用。
- 若 CDP/Chromium 在受限環境跑不起來(禁聯網/程序崩潰),降級到雲端截圖:使用 thum.io / mshots / microlink 等,帶
-
存圖:放到工作區(如
img/x.png,檔案名使用 ASCII/無空格)。 -
分享(按第 0 步結論,二選一):
- 宿主路徑(第 0 步判定為可複用宿主時):把圖片放到宿主暴露的靜態目錄,內嵌
https://<宿主域名>/img/x.png;不要開獨立隧道。 - 顯式兜底(第 0 步判定為需兜底且使用者同意時):只分享這一個檔案,不開整個目錄;啟動圖庫[僅回環]+公網隧道,端到端校驗,輸出 PUBLIC_BASE:
bash <skill>/scripts/setup.sh <img>/x.png # Unix/WSL python <skill>/scripts/serve.py --share <img>/x.png # Windows 原生
- 宿主路徑(第 0 步判定為可複用宿主時):把圖片放到宿主暴露的靜態目錄,內嵌
-
回覆裡內嵌(縮圖=原圖 URL,點擊開原圖全螢幕):
[](https://<基址>/x.png)基址必須是第 0 步判定的結果(宿主公網位址,或使用者知情同意的顯式隧道位址);禁止 embed localhost/127.0.0.1 並聲稱手機可看。告知使用者:聊天框顯示縮圖,點擊開原圖;手機用同一公網位址也可存取(已驗證 DSH 能渲染公網 markdown 圖片)。
-
分享完畢→撤隧道(顯式兜底場景,避免長期公開):
bash <skill>/scripts/teardown.sh # 停止圖庫+隧道+清理
失敗處理
- 宿主可達性無法判定:不猜、不靜默另開隧道;先問使用者手機存取本會話所用的位址(見第 0 步)。
- 宿主公網但無靜態圖片路徑:提示使用者配置靜態映射,或徵得同意後走顯式兜底,並說明該隧道與宿主不同源。
- 缺依賴:serve.py 報「缺 cloudflared/python」,按提示安裝或設定
CLOUDFLARED;截圖缺 web-access 則走雲端截圖(見上)或讓使用者傳圖。 - 連接埠被佔:serve.py 自動選空閒連接埠。
- 隧道域名取不到(網路慢/斷連 Cloudflare):serve.py 輪詢重試;仍失敗則告知「網路無法建隧道」,回退為僅本機/區域網路(給本機位址,並說明手機場景需先讓宿主/服務公網可達)。
- 端到端校驗失敗:serve.py 會 curl 真實檔案名校驗(200 才成功),失敗即撤,避免「看似 live 實則 404」。
- 域名飄移:快捷隧道重啟會換域名,舊內嵌 URL 失效;宿主路徑無此問題;兜底場景長期穩定使用命名隧道/固定域名。
環境自檢(Agent 先做)
開始前先探測:能否出網(curl 一個公網位址)、能否spawn 瀏覽器進程(CDP)、宿主是否為公網可達(見第 0 步)。出網/CDP 都不行 → 走雲端截圖 + 提示需要更高權限,不要直接給使用者一個「看起來能用但實際裂開」的圖。
安全(預設動作,非提醒)
- 只分享指定檔案:serve.py 把要分享的檔案拷進隨機命名子目錄再啟動服務,絕不開整個 img/ 目錄(否則隧道 URL 能列出/下載該目錄所有檔案);宿主靜態目錄同理只放要分享的檔案。
- 圖庫僅綁定 127.0.0.1(區域網路不能直連);公網隧道 URL 無鑑權——分享完立即 teardown。
- 想更嚴格:給 URL 加隨機 token / 使用短時隧道;別放敏感圖。
- 別把所有圖都放公網:只讓「本次要分享的那一張/幾張」出現在可公開存取的目錄/隧道中。
宿主隧道優先(判定見執行步驟第 0 步)
- 圖位址跟隨宿主位址:宿主已被隧道化/公網化時,圖片應掛在宿主同一域名(如靜態
/img/*路徑)下——使用者手機上打開會話即能載入,無需、也不應另開一條與宿主不同源的臨時隧道。 - 若宿主透過 dsh-trust-proxy 等暴露了
/img/靜態規則,圖片 URL 形式如https://<DSH域名>/img/x.png,跨設備、免多開隧道。 - serve.py 的獨立 cloudflared 隧道只是可移植兜底(任何機器都能跑):僅在第 0 步判定「宿主不可公網複用」且使用者知情同意後使用,並明確告知其侷限(與宿主不同源、快捷隧道重啟即換域名)。
邊界
- 進程要常駐/可撤:serve.py 記錄 PID 供 teardown;DSH 會話裡服務需跨會話(可用託管後台 + teardown 明確清理)。
- 檔案名:使用 ASCII、無空格;腳本對檔案存在做校驗,中文/空格由 URL 編碼處理,但建議避免。
- 工作區不同:不同會話工作區不同,按該會話路徑分享;serve.py 使用系統臨時目錄,不依賴工作區。