Skip to main content
Glama
README.md
# 理脈 limai

理華與理月的**共享神經系統**——從角色中按第一性原理提取的獨立器官。

## 第一性原理推導

| 角色裡的樣子 | 本質 | 模組 | MCP 工具 |
|---|---|---|---|
| 心跳輪詢+錯誤退避(on_idle.mjs) | **節律** | heartbeat.mjs | heartbeat_now・vitals_latest・vitals_history |
| 截圖/視窗/剪貼簿(screenshot.mjs) | **視覺** | vision.mjs | screen_capture(回圖片)・list_windows・read_clipboard |
| todo-tasks.json+權重融合心跳 | **意圖** | todo.mjs | todo_add・todo_list・todo_update |
| 長期記憶(名×關鍵字×內容) | **記憶** | memory.mjs | memory_add・memory_search・memory_list・memory_forget |
| o-pi 六文件工具 | **檔案行動** | filesys.mjs | fs_ls/read/write/edit/find/grep |
| o-pi websearch/webfetch | **網路行動** | web.mjs | web_search・web_fetch |

捨棄的:角色的 LLM 任務提示詞(人格不搬)、記憶的 JS eval 觸發器(安全)。
保留的精髓:加權隨機排程思想→心跳退避;STALE_READ 守衛;SSRF 防護;有界讀取。

## 架構:檔案/網頁工具直接內嵌 o-pi 原始碼

`fs_*` 與 `web_*` 八個工具直接呼叫 vendored 上游原始碼(不再使用自製重寫版):
- 位置:`third_party/o-pi/`(commit 見其 PROVENANCE.txt;含 AGPL-3.0 LICENSE)
- 載入:jiti 執行期 TypeScript 轉譯,相對匯入在上游樹內自解析
- 行為:回傳 o-pi 原生模型可見信封(<read>/<write>/<edit>/<grep>/<websearch_results>/<webfetch>),守衛、上限、錯誤碼完全等價
- 本地補丁僅一處:ports/read-pdf.ts 資源目錄改由宿主注入(記錄於 PROVENANCE.txt)
- 搜尋可靠性:DDG 免費備援可能被 bot challenge(PROVIDER_BLOCKED);穩定使用請設 BRAVE_SEARCH_API_KEY / EXA_API_KEY / TAVILY_API_KEY,o-pi 路由器自動採用

## 啟動

```bash
npm install
npm run start          # ① stdio → Claude Desktop / Cursor 等本地客戶端
npm run serve:http     # ② HTTP MCP → GPT 客戶端 / 區網 / 遠端
npm run tick           # ③ 手動跑一次心跳(驗證感知層)
```

## CLI 為 AI agent 而設計

```bash
limai shot                       # → {"file":...,"width":1920,"height":1080,"bytes":...}
limai win                        # → {"foreground":...,"windows":[{process,title},…]}
limai clip [--json]              # 剪貼簿原文走 stdout(利於管線)
limai tick                       # 心跳一次,生命徵象 JSON
limai web search <q>             # → [{title,url,snippet},…]
limai web fetch <url>            # 正文走 stdout、中繼 stderr;--json 得全包裝
limai fs ls|read|write|edit|find|grep …
limai mem … / limai todo …       # 同前
```

**Agent 契約**:
- 輸出預設 JSON、錯誤碼前綴進 stderr 訊息(`STALE_READ: …`)、退出碼非零表失敗
- `fs edit` 嚴格契約與 MCP 相同:須先 `fs read`;觀測狀態持久化於 `fs-state.json`,
  「read 行程 → edit 行程」跨呼叫依然成立,外部變更必被攔截(--force 可越過)
- 成功的 `fs write` 亦建立觀測,可接 edit(同 o-pi「緊接成功 write」規則)

架構上 MCP 只是核心模組之上的其中一種介面:同一套 vision/web/filesys/memory/todo/heartbeat
同時供 CLI 子命令與 MCP 工具呼叫,兩種介面共用同一份資料與同一套安全契約。`

首次執行自動建立 `~/.limai/`(config.json・memory.json・todo.json・vitals.*・screenshots/)並印出 token。

## 客戶端接入

### 本地(stdio)
```jsonc
// claude_desktop_config.json
{ "mcpServers": { "limai": { "command": "node", "args": ["F:\\fount開發項目\\理脈\\src\\cli.mjs", "serve", "--stdio"] } } }
```

### 區網/同機 GPT 客戶端(Cherry Studio、LobeChat、OpenWebUI…)
```bash
node src/cli.mjs serve --http                # 預設 127.0.0.1:8931
# 對區網開放:--host 0.0.0.0 --token <強密碼>
```
```jsonc
{ "type": "http", "url": "http://192.168.x.x:8931/mcp",
  "headers": { "Authorization": "Bearer <token>" } }
```

### 雙傳輸端點(內建)
| 端點 | 用途 |
|---|---|
| `/mcp` | Streamable HTTP(主要;Claude/Cursor/ChatGPT 新版) |
| `/sse` + `/messages` | 舊式 SSE 備援(相容性最大化) |
| `/health` | 健康檢查 |

自我診斷(模擬 ChatGPT 完整握手,5 項體檢):`limai doctor https://mcp.plocomcomui.cc --token <token>`

### 雲端 ChatGPT(Connectors/開發者模式)
ChatGPT 摸不到你的 localhost,需要公網 HTTPS——一行隧道:
```bash
cloudflared tunnel --url http://127.0.0.1:8931
# → https://xxxx.trycloudflare.com
```
連接器 URL 填 `https://xxxx.trycloudflare.com/mcp?token=<token>`(GPT 類客戶端多不能自訂 header,故支援 query 傳 token)。
長期方案:Tailscale Funnel(免開埠)或 Caddy 反代自有網域。

## 安全邊界

- 檔案:鎖在 `config.json` 的 `allowedRoots`;`.git` 永久阻擋;`fs_edit` 必須先 `fs_read`(STALE_READ 版本守衛);old 文本必須唯一
- 網路:拒 localhost/私網/link-local(SSRF)、重定向逐跳複檢、2MB 上限、30 秒逾時
- 認證:HTTP 全程 Bearer/query-token;預設只綁 127.0.0.1
- 隱私:心跳只記視窗標題+剪貼簿雜湊(變化時存前 60 字元預覽);像素截圖僅限明確呼叫 screen_capture

## 心跳語義(沿襲理華)

15 分鐘一跳(可調 `heartbeat.intervalMin`)。每跳收集:前景視窗・視窗清單(top8)・閒置秒數・剪貼簿變化・開放待辦數。失敗時間隔 ×2(上限 8×),成功復位。日誌滾動於 `vitals.ndjson`。

## 上游同步(o-pi)

- **2026-08-23 檢查**:上游當日大量提交為內部重構(file-tools/web-tools/filesystem/lsp 簡化),六工具+兩網頁工具的行為契約不變;`duckduckgo-html-provider` 仍為零-key 備援路徑——理脈提取依然忠實。
- 新能力 `read` 支援 PDF 頁面圖像(d762209):**理脈已對齊實作**——`fs_read` 加 `pages` 參數(N / N-M / N-),回傳頁面 PNG 的 MCP 圖像內容塊;CLI 用 `fs read <pdf> --pages "1-5"`。主路線 **PDF.js(pdfjs-dist legacy)+@napi-rs/canvas** 跨平臺渲染;Windows 上依賴無法載入時自動降級內建 WinRT `Windows.Data.Pdf`。預設單次上限 20 頁,含總頁數與續讀位置。
- skill URI/bash 工具/approval gate 屬 Pi 宿主專屬,不在提取範圍。
- **同日二檢(d795f92 new approval UI)**:僅動 `src/approval/*` 與 TUI,file-tools/web-tools 零變更。據此完成 grep 契約對齊:非法正則降級為精確字面量——有命中→回 `literal_fallback` 警告;零命中→`INVALID_REGEX` 不偽裝空結果。已測試通過。

## 授權與來源(License & Attribution)

本專案以 **GNU Affero General Public License v3.0 或更新版本**(AGPL-3.0-or-later)發佈,完整條款見 [LICENSE](./LICENSE)。

**代碼來源聲明**:

- **檔案工具與網頁工具**:直接內嵌上游完整原始碼於 `third_party/o-pi/`([Orion-zhen/o-pi](https://github.com/Orion-zhen/o-pi),AGPL-3.0),MCP 工具經橋接層直接呼叫,行為完全等價;上游授權文本隨附於該目錄。
- **長期記憶**:`src/core/memory.mjs` 移植自理華 `prompt/memory/long-term-memory.mjs`——完整 JSON 結構(trigger/prompt/name/createdAt/createdContext…)、`long-term-memory.json` 檔名與全部儲存函式語義;觸發器經 [@steve02081504/async-eval](https://www.npmjs.com/package/@steve02081504/async-eval) 執行。
- **match_keys**:`src/core/match.mjs` 移植自理華 `scripts/match.mjs`——中文免邊界/英文\b、繁簡雙變體比對(opencc-js)、getScopedChatLog 完整角色過濾;翻譯管線分支未移植(標註於檔頭)。
- **captureScreen**:`src/core/vision.mjs` 逐行移植自理華 `scripts/tools.mjs` 行428-438(node-screenshots);理脈加子行程隔離(Rust panic 不波及常駐)與 PowerShell 備援。listWindows/readClipboard/idleSeconds 為理脈原創。
- **心跳/todo**:提取自理華 on_idle 與 todo-tasks 的架構思想(閒置輪詢退避、加權任務),未複製程式碼。
- MCP 協議實作基於官方 [@modelcontextprotocol/sdk](https://github.com/modelcontextprotocol/typescript-sdk)。
- PDF 渲染依賴 [pdf.js](https://github.com/mozilla/pdf.js)(Apache-2.0)與 [@napi-rs/canvas](https://github.com/Brooooooklyn/canvas)(MIT)。

TDQS

A3.5/5.0

Scored across 21 tools

Disambiguation5/5

Each tool targets a distinct resource and action—monitoring (screen, windows, clipboard, heartbeat), memory (add/search/list/forget), todo (add/list/update), web (search/fetch), and filesystem (ls/read/write/edit/find/grep). There is no meaningful overlap; even fs_write vs fs_edit are clearly separated by create/overwrite vs precise replacement.

Naming Consistency5/5

All tool names follow a consistent 'domain_action' pattern with snake_case (e.g., memory_add, web_fetch, fs_grep). The verb is consistently after the domain, and every name is lowercase, making the API predictable and easy to navigate.

Tool Count4/5

With 21 tools, the server is slightly above the ideal range but each tool serves a clear purpose across multiple domains (system monitoring, memory, todos, web, filesystem). The count is justified given the broad scope, though a few tools could potentially be consolidated without losing clarity.

Completeness3/5

The server covers most core operations for its domains—memory and todo have full CRUD-ish coverage, web has search and fetch, and filesystem has read/write/edit/find/grep. However, the absence of a file deletion tool (e.g., fs_delete) leaves the filesystem incomplete, and there is no explicit tool for renaming or moving files. This gap could cause agent failures when cleanup is required.

Maintenance

ActivityMaintained
ResponsivenessNo issues