@pic-ai/pic-agent-call 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,217 @@
1
+ # @pic-ai/pic-agent-call
2
+
3
+ > Cross-AI MCP server — Memory · Channel · Task-Broker · Agent Identity
4
+
5
+ 讓 Claude Code、Gemini CLI、Copilot、Codex 共享記憶、溝通、協作的 MCP server。
6
+
7
+ ---
8
+
9
+ ## Features
10
+
11
+ - **20 MCP tools** 涵蓋四大功能層
12
+ - **Memory** — 知識圖譜(SQLite),相容官方 MCP memory server schema
13
+ - **Channel** — 跨 AI 訊息傳遞,狀態機:UNREAD → IN_PROGRESS → READ / ORPHANED
14
+ - **Task-Broker** — 任務派發,feature+payload 冪等建立,BEGIN IMMEDIATE 原子搶鎖
15
+ - **Agent Identity** — `register_agent` / `agent_status`,per-session 身份管理與 statusline 顯示
16
+
17
+ ---
18
+
19
+ ## Requirements
20
+
21
+ - **Node.js >= 22.0.0**(需要 `node:sqlite` built-in module)
22
+
23
+ ---
24
+
25
+ ## Installation
26
+
27
+ ### Option A: npm / npx
28
+
29
+ ```bash
30
+ npm install @pic-ai/pic-agent-call
31
+ # or run directly without installing
32
+ npx @pic-ai/pic-agent-call
33
+ ```
34
+
35
+ ### Option B: Local path(推薦用於 `.mcp.json` 設定)
36
+
37
+ ```bash
38
+ git clone https://github.com/Vance-PIC/pic-agent-call.git
39
+ cd pic-agent-call
40
+ npm install
41
+ ```
42
+
43
+ ---
44
+
45
+ ## Configuration
46
+
47
+ ### Claude Code (`.mcp.json`)
48
+
49
+ 在專案根目錄建立 `.mcp.json`:
50
+
51
+ ```json
52
+ {
53
+ "mcpServers": {
54
+ "agent-call": {
55
+ "command": "node",
56
+ "args": ["YOUR_PATH/pic-agent-call/bin/server.mjs"]
57
+ }
58
+ }
59
+ }
60
+ ```
61
+
62
+ 將 `YOUR_PATH` 替換為你的本地絕對路徑,例如 `/Users/yourname/projects/pic-agent-call`。
63
+
64
+ ### Gemini CLI (`~/.gemini/config/mcp_config.json`)
65
+
66
+ ```json
67
+ {
68
+ "mcpServers": {
69
+ "agent-call": {
70
+ "command": "node",
71
+ "args": ["YOUR_PATH/pic-agent-call/bin/server.mjs"]
72
+ }
73
+ }
74
+ }
75
+ ```
76
+
77
+ ### 環境變數
78
+
79
+ | Variable | Description | Default |
80
+ |----------|-------------|---------|
81
+ | `MEMORY_DB_PATH` | SQLite DB 路徑 | `.memory/memory-graph.db`(自動解析至 cwd 或 `~/.memory`)|
82
+ | `AGENT_ID` | Agent 識別名稱(可選,配合 `register_agent` 使用)| — |
83
+
84
+ DB 路徑解析優先序:`MEMORY_DB_PATH` env → `settings.local.json` → `cwd/.memory` → `~/.memory`
85
+
86
+ ---
87
+
88
+ ## Tools (20)
89
+
90
+ ### Memory — Custom
91
+
92
+ | Tool | Description |
93
+ |------|-------------|
94
+ | `add-observation` | 向指定記憶實體寫入觀測紀錄。實體不存在時自動建立,並同步更新 JSON 快照。 |
95
+ | `query-entity` | 查詢指定記憶實體的完整資訊,含屬性、關係及所有歷程觀測紀錄。 |
96
+ | `stats` | 取得 SQLite 資料庫統計資訊(entities / relations / observations 筆數與路徑)。 |
97
+
98
+ ### Memory — Official Compatible
99
+
100
+ 相容 [官方 MCP memory server](https://github.com/modelcontextprotocol/servers/tree/main/src/memory) schema,可直接替換使用。
101
+
102
+ | Tool | Description |
103
+ |------|-------------|
104
+ | `create_entities` | 批次建立知識實體。同名實體已存在則忽略。 |
105
+ | `add_observations` | 向多個已存在實體添加觀測記錄。實體不存在則失敗。 |
106
+ | `create_relations` | 建立兩實體之間的單向關聯。實體不存在時自動建立臨時節點。 |
107
+ | `read_graph` | 讀取並匯出完整知識圖譜(所有實體、觀測紀錄及關係)。 |
108
+ | `search_nodes` | 模糊搜尋知識圖譜(範圍:實體名稱、類型、觀測紀錄內容)。 |
109
+
110
+ ### Task-Broker
111
+
112
+ | Tool | Description |
113
+ |------|-------------|
114
+ | `create_task` | 建立任務。相同 feature+payload 具備冪等保護,不會重複建立。 |
115
+ | `list_pending_tasks` | 列出待處理任務。自動釋放逾時(>30 分鐘)的 claimed 任務。 |
116
+ | `claim_task` | 原子操作領取任務,BEGIN IMMEDIATE 確保排他性,防搶單。 |
117
+ | `complete_task` | 標記任務完成並寫回執行結果。任務須為 claimed 狀態。 |
118
+ | `fail_task` | 標記任務失敗並記錄原因。任務須為 claimed 狀態。 |
119
+ | `get_task` | 查詢單一任務的完整詳情。 |
120
+
121
+ ### Channel
122
+
123
+ | Tool | Description |
124
+ |------|-------------|
125
+ | `channel_send` | 傳送訊息給指定 AI 視窗或 pool(receiver 支援具體 ID / 萬用字元 / `all`)。 |
126
+ | `channel_list_unread` | 列出指定接收者的未讀訊息。自動釋放逾時 IN_PROGRESS(>15 分鐘)。 |
127
+ | `channel_claim` | 原子搶鎖:將 UNREAD 訊息標記為 IN_PROGRESS。BEGIN IMMEDIATE 保證同一訊息只有一個視窗成功。 |
128
+ | `channel_ack` | 確認完成:將 IN_PROGRESS 訊息標記為 READ。只有搶鎖者才能 ACK。 |
129
+
130
+ ### Agent Identity
131
+
132
+ | Tool | Description |
133
+ |------|-------------|
134
+ | `register_agent` | 登記或更新當前 AI 視窗的身份(`agent_id` + `role`)。`session_id` 自動從環境變數讀取。換角色時自動處理孤兒訊息並通知原始發送者。 |
135
+ | `agent_status` | 查詢當前 AI 視窗的身份與未讀訊息數量。`session_id` 自動讀取。 |
136
+
137
+ ---
138
+
139
+ ## Agent Identity & Statusline
140
+
141
+ `register_agent` 讓每個 AI session 具備獨立身份,供 Channel 路由與 statusline 顯示使用。
142
+
143
+ **Session ID 解析優先序:**
144
+
145
+ ```
146
+ CLAUDE_CODE_SESSION_ID → ANTIGRAVITY_CONVERSATION_ID → AGENT_SESSION_ID → hostname-pid
147
+ ```
148
+
149
+ **呼叫範例:**
150
+
151
+ ```json
152
+ // Tool: register_agent
153
+ {
154
+ "agent_id": "CC-SA1",
155
+ "role": "SA"
156
+ }
157
+ ```
158
+
159
+ **Statusline 顯示格式:**
160
+
161
+ ```
162
+ [CC-SA1|SA] 📨3
163
+ ```
164
+
165
+ 表示 agent `CC-SA1`,角色 `SA`,有 3 則未讀訊息。
166
+
167
+ Claude Code 使用者可搭配 `bin/statusline.mjs` 將此資訊顯示在 statusbar(詳見 `bin/statusline.mjs`)。
168
+
169
+ ---
170
+
171
+ ## Multi-Agent Workflow Example
172
+
173
+ 三步驟跨 AI 任務協作:
174
+
175
+ ```
176
+ Step 1 — SA creates a task for PG:
177
+
178
+ create_task(
179
+ feature="auth-feature",
180
+ assign_to="CC-PG1",
181
+ payload='{"action":"implement login endpoint"}'
182
+ )
183
+
184
+ Step 2 — PG polls and claims:
185
+
186
+ list_pending_tasks(assign_to="CC-PG1")
187
+ claim_task(task_id="...", agent_id="CC-PG1")
188
+
189
+ Step 3 — PG completes:
190
+
191
+ complete_task(task_id="...", result='{"status":"done","pr":"#42"}')
192
+ ```
193
+
194
+ 完整跨平台中繼鏈(CC → Gemini)範例見 `skills/agent-call.md`。
195
+
196
+ ---
197
+
198
+ ## Development
199
+
200
+ ```bash
201
+ npm test # runs unit tests + P5 function tests
202
+ ```
203
+
204
+ 專案包含 unit tests(Jest)與 P5 功能驗收測試,測試報告產出至 `evidence/` 資料夾。
205
+
206
+ ---
207
+
208
+ ## License
209
+
210
+ MIT
211
+
212
+ ---
213
+
214
+ ## Project
215
+
216
+ - **GitHub**: https://github.com/Vance-PIC/pic-agent-call
217
+ - **npm**: https://www.npmjs.com/package/@pic-ai/pic-agent-call
package/bin/server.mjs CHANGED
@@ -2,6 +2,8 @@
2
2
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
3
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
4
  import { z } from 'zod';
5
+ import fs from 'node:fs';
6
+ import path from 'node:path';
5
7
  import { resolveMemoryPaths, initDatabase } from '../src/db.mjs';
6
8
  import * as memory from '../src/memory.mjs';
7
9
  import * as channel from '../src/channel.mjs';
@@ -201,6 +203,23 @@ server.tool('channel_ack',
201
203
 
202
204
  // ── Agent 身份管理 ────────────────────────────────────────────────────────────
203
205
 
206
+ function resolveTermKey() {
207
+ const ccId = process.env.CLAUDE_CODE_SESSION_ID;
208
+ if (ccId) return `cc-${ccId.slice(0, 8)}`;
209
+ const agyId = process.env.ANTIGRAVITY_CONVERSATION_ID;
210
+ if (agyId) return `agy-${agyId.slice(0, 8)}`;
211
+ return `ppid-${process.ppid}`;
212
+ }
213
+
214
+ function writeAgentSessionCache(agentId, termKey) {
215
+ try {
216
+ const sessionDir = path.join(path.dirname(dbPath), 'agent-sessions');
217
+ fs.mkdirSync(sessionDir, { recursive: true });
218
+ const filePath = path.join(sessionDir, `${termKey}.json`);
219
+ fs.writeFileSync(filePath, JSON.stringify({ agent_id: agentId, term_key: termKey, ts: new Date().toISOString() }), 'utf8');
220
+ } catch (_) {}
221
+ }
222
+
204
223
  server.tool('register_agent',
205
224
  '【agent】登記或更新當前 AI 視窗的身份(agent_id + role)。session_id 自動從環境變數讀取。若 agent_id 已被其他 session 占用,回傳 conflict 資訊供 AI 詢問 user。換角色時自動處理孤兒訊息並通知原始發送者。',
206
225
  {
@@ -222,7 +241,12 @@ server.tool('register_agent',
222
241
  }
223
242
 
224
243
  const result = registerAgent(db, sessionId, agent_id, role);
225
- return textJson(result);
244
+
245
+ // 同步寫入本地快取(供 statusline hook 識別身分)
246
+ const termKey = resolveTermKey();
247
+ writeAgentSessionCache(agent_id, termKey);
248
+
249
+ return textJson({ ...result, term_key: termKey });
226
250
  }
227
251
  );
228
252
 
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@pic-ai/pic-agent-call",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "AI multi-agent communication MCP server — Memory, Channel, Task-Broker",
5
5
  "type": "module",
6
6
  "bin": {
7
- "pic-agent-call": "./bin/pic-agent-call.js"
7
+ "pic-agent-call": "bin/pic-agent-call.js"
8
8
  },
9
9
  "engines": {
10
10
  "node": ">=22.0.0"
package/src/status.mjs CHANGED
@@ -146,10 +146,19 @@ export function getAgentStatus(db, sessionId) {
146
146
 
147
147
  const { agent_id, role } = reg;
148
148
 
149
- const row = db.prepare(
150
- `SELECT COUNT(*) as count FROM agent_collaboration_channel
151
- WHERE receiver = ? AND status = 'UNREAD'`
152
- ).get(agent_id);
149
+ let row;
150
+ if (role) {
151
+ const pool = `${role}?`;
152
+ row = db.prepare(
153
+ `SELECT COUNT(*) as count FROM agent_collaboration_channel
154
+ WHERE status = 'UNREAD' AND (receiver = ? OR receiver = 'all' OR receiver = ?)`
155
+ ).get(agent_id, pool);
156
+ } else {
157
+ row = db.prepare(
158
+ `SELECT COUNT(*) as count FROM agent_collaboration_channel
159
+ WHERE status = 'UNREAD' AND (receiver = ? OR receiver = 'all')`
160
+ ).get(agent_id);
161
+ }
153
162
 
154
163
  const unread = row?.count || 0;
155
164
  const roleLabel = role ? `|${role}` : '';