功能 操作文档 接入文档 下载 GitHub 仓库

本地推送 API

把脚本的进度、构建状态、提醒推到信息岛「动态」页。胶囊会显示最新卡片的标题(带进度百分比)并脉冲一次,卡片到期自动消失。接口只监听回环地址,不需要任何云端账号。

dcx-island v0.1.2 127.0.0.1:9841 仅本机 约 8 分钟

01概览#

信息岛在本地起一个极小的 HTTP 服务。脚本用一个 JSON 描述卡片,POST 过来即可;同一个 id 再次推送就是「更新并续期」,不会堆一屏卡片。

Base URL
http://127.0.0.1:9841
鉴权
Bearer <token>
请求体上限
64 KB 头部 8 KB
卡片存活
12 s 上限 3600 s
  • 只监听 127.0.0.1,局域网与公网不可达。
  • 除健康检查外,所有请求都要 Authorization: Bearer <token>。
  • dcx-island.exe --push 在单实例检查之前运行:信息岛已经在跑也能用,而且不会打开或收起面板。
  • 一次请求只处理一个 JSON 卡片;不支持 chunked 编码。

02鉴权#

令牌在 %LOCALAPPDATA%\dcx\island_api_token.txt,信息岛首次启动时生成。设置页「桌面信息岛 → 推送 API」可以复制或重置;重置后立即生效,不需要重启信息岛。

# 读取令牌(注意 -Raw 与 Trim)
$token = (Get-Content "$env:LOCALAPPDATA\dcx\island_api_token.txt" -Raw).Trim()

为什么令牌在文件里

这是刻意的例外:脚本需要一行就能读到它,因此不放 Windows 凭据管理器。它只授予「往岛上推卡片」这一项能力,不能读剪贴板、不能读消息、不能执行命令。

从设置页「复制」令牌后,岛内剪贴板历史会跳过与当前令牌完全相同的文本,不会落盘。

令牌等价于「推卡片」权限。不要把它写进公开仓库、CI 日志或截图;泄露后到设置页重置即可,旧令牌立刻失效。

03快速开始#

两种方式:调用信息岛自带的 --push / --push-file,或者直接 POST HTTP。前者最省事,后者适合已经在写脚本的进程。

方式一:命令行推送

先确保信息岛在运行,并且设置里的推送 API 是开启状态(默认开启)。

PowerShell 5.1 在把带内嵌双引号的参数交给原生程序时会重新加引号,而且不同写法结果不一致。可靠做法是让 PowerShell 写文件、程序读文件:

$j = '{"id":"test","title":"测试推送","progress":0.4,"ttl_secs":30}'
[IO.File]::WriteAllText("$env:TEMP\dcx-island-push.json", $j, [Text.Encoding]::UTF8)
& "D:\dcx-dist\dcx-island.exe" --push-file "$env:TEMP\dcx-island-push.json" | Out-Host

| Out-Host 让 PowerShell 等待这个 GUI 子系统的程序并显示返回的 JSON;不加的话提示符会先回来,输出稍后才出现(卡片本身仍会正常推送)。

方式二:直接 HTTP

Windows PowerShell 5.1 会用 ANSI 编码发送字符串 body,中文会变成 ?。显式发送 UTF-8 字节即可:

$token = (Get-Content "$env:LOCALAPPDATA\dcx\island_api_token.txt" -Raw).Trim()
$json  = '{"id":"build-42","title":"构建中","progress":0.3,"ttl_secs":600}'
Invoke-RestMethod -Method Post -Uri "http://127.0.0.1:9841/v1/island/push" `
  -Headers @{ Authorization = "Bearer $token" } `
  -ContentType "application/json; charset=utf-8" `
  -Body ([Text.Encoding]::UTF8.GetBytes($json))

04端点#

方法路径鉴权说明
GET/v1/health否{"ok":true,"app":"dcx-island","version":"…"}
POST/v1/island/pushBearer推送 / 更新卡片,返回 {"ok":true,"id":"…","expires_at":…}
GET/v1/island/activeBearer当前未过期卡片,最新在前
DELETE/v1/island/push/{id}Bearer撤回卡片,幂等

请求体上限 64 KB,头部上限 8 KB,一次只处理一个 JSON 卡片。健康检查不带鉴权,可以拿来探测信息岛是否在跑:

GET http://127.0.0.1:9841/v1/health

200 OK
{"ok":true,"app":"dcx-island","version":"0.1.2"}

05卡片字段#

字段必填说明
id是1–64 位 [A-Za-z0-9._-];同 id 再推 = 更新并续期
title是≤200 字符;胶囊显示它(有进度时带百分比)
body否≤2000 字符;面板「动态」页的卡片正文
progress否0–1 的小数;显示进度条与百分比(0.4 = 40%)
ttl_secs否存活秒数,默认 12,上限 3600;0 视为默认
action否见下一节;没有动作就只有文字

完整示例

{
  "id": "build-42",
  "title": "构建中",
  "body": "正在编译 dcx-island(12/40)",
  "progress": 0.3,
  "ttl_secs": 600,
  "action": { "kind": "show_panel", "tab": "live" }
}

最小卡片是 {"id":"ping","title":"完成"},TTL 默认 12 秒。固定的 id 可以「同一张卡持续更新」,每次推送续期,不会堆一屏卡片。

06动作白名单#

卡片可以带一个动作,点击卡片上的按钮时执行。动作只有三种,没有执行命令一类动作:

kind参数行为
open_urlurl(http / https)用默认浏览器打开
open_folderpath打开文件夹;不存在则报错提示
show_paneltab:tasks / clip / inbox / perf / live / search打开信息岛并切到该页

open_url 只接受 http / https;show_panel 的页签 id 与面板内部一致,写错会被忽略。推送接口永远不能启动进程或读写文件。

07命令行推送#

dcx-island.exe 支持两个模式,参数都是一个 JSON 卡片的文本:

参数说明
--push <json>直接把 JSON 作为参数
--push-file <path>从文件读取;UTF-8 BOM 会被自动跳过
  • 退出码 0 = HTTP 200;失败时 stderr 给出原因。
  • 两种模式都先于单实例检查运行:岛已经在跑也能用,且不会打开 / 收起面板。
  • 推送 API 关闭时,--push 会直接报「推送 API 未启用」。

PowerShell 5.1 的引号问题不是偶发:--push '{"id":"test"}' 会被吃成 {id:test},改成 \" 转义后有时能过、有时又变成 EOF 错误。脚本里请一律用 --push-file。

08排错#

现象原因
JSON 解析失败:key must be a string at line 1 column 2PowerShell 5.1 把 JSON 里的双引号吃掉了({id:test});改用 --push-file
JSON 解析失败:EOF while parsing a string…同上,另一种引号变形;改用 --push-file
401没带 token,或 token 已重置(重置后立即生效)
400 + id 需为…id 字符不合法或超过 64 位
400 + open_url 仅支持…动作链接不是 http / https
无法连接 127.0.0.1:9841信息岛未运行,或设置里关掉了推送 API / 改了端口
卡片不出现TTL 太短(先被下一条顶掉);卡片最多 16 张,新的顶旧的

09边界与安全#

  • 仅回环:服务只绑定 127.0.0.1,局域网与公网不可达,也没有跨域开放。
  • 能力最小:令牌只允许推卡片;没有读剪贴板、读消息、执行命令、读写文件的端点。
  • 令牌是文件:island_api_token.txt 刻意不放进凭据管理器,方便脚本读取;泄露后重置即可。
  • 数据留在本地:剪贴板与通知内容全部本地保存;推送卡片只存在内存里,到期即消失,TTL 最长 1 小时。
  • 卡片数量:最多 16 张,新的顶旧的。高频推送请复用固定 id。
  • 默认开启:推送 API 默认开启;关掉后 --push 直接报「推送 API 未启用」。

10扩展平台#

接入 DCX 不只有推送 API。平台本身是「宿主 + 独立 exe」的结构,新增一个应用不需要改设置窗口的导航结构,也不需要动任务栏引擎。

新增一个独立应用

三件事:新增一个 crate、在 dcx-host/src/apps.rs 的注册表加一条 AppEntry、在设置中心对应页面加一组卡片。可执行文件必须与 dcx-host.exe 同目录——宿主按 current_exe() 的父目录找它。

AppEntry {
    id: "search",
    name: "文件检索",
    exe: "dcx-search.exe",
    window_title: "文件检索", // 必须与应用的 WIN_TITLE 逐字一致
    description: "全盘文件名与内容检索,由全局热键唤起",
    default_on: false,      // 缺省不随平台自启
}
  • default_on = false 表示缺省关闭:宿主不会拉起它,也不预建索引。全局热键由常驻宿主监听,按下时才 launch_on_demand。
  • 一个应用只能有一个主开关,同时写应用自己的 TOML 与 apps.toml,避免两处状态不一致。
  • 不要给新应用单独写开机启动项。自启永远只有一条:dcx-host.exe --no-settings,其余由 apps.toml 管理。

配置写入协议

五个 TOML 与两个 JSON 是多进程读写,所有保存都要走 dcx-win32::config_file,不要直接 fs::write + rename:

  • FileLock:按文件全路径哈希生成命名互斥体,保护整个「读—改—写」;同线程可重入。
  • write_atomic:临时文件带 PID 与序号并 sync_all,再 ReplaceFileW / MoveFileExW 换入。没有「rename 失败就直写」的回退。
  • poisoned:解析失败的文件只读,save 返回错误,不许用默认值覆盖——否则会丢 overrides 或 library_root。

不要改的线协议

settings.toml、organizer.toml、apps.toml、box_slot.txt、box_host_alive、no_reserve 是引擎与收纳盒之间的稳定契约:文件名与语义都不改。新增应用不需要替换 dcx_engine.dll。

引擎 DLL 被 Explorer 映射时不能直接覆盖:先 mv 旧文件再 cp 新文件,随后用 grep -a "box_slot.txt" 确认产物带槽位代码,并重算 SHA256SUMS.txt。