nx-ce 0.1.1 → 0.1.4
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 +90 -51
- package/package.json +3 -2
- package/src/cli.js +16 -2
- package/src/index.js +10 -1
- package/src/serve.js +553 -198
- package/src/session-store.js +56 -2
- package/src/skills.js +56 -0
- package/src/util.js +124 -0
package/README.md
CHANGED
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
[](https://github.com/joke-lx/nx-ce/actions/workflows/npm-publish.yml)
|
|
5
5
|
|
|
6
6
|
**nx-ce** 是一个轻量级 Node.js 适配器,封装了 `@anthropic-ai/claude-agent-sdk`。
|
|
7
|
-
通过长度前缀的 JSON
|
|
8
|
-
|
|
7
|
+
通过长度前缀的 JSON 协议在 stdin/stdout 上暴露 SDK 接口,
|
|
8
|
+
支持一次性冷启动查询与 WebSocket 持久化服务器两种运行模式。
|
|
9
9
|
|
|
10
10
|
**nx-ce** is a lightweight Node.js adapter for `@anthropic-ai/claude-agent-sdk`.
|
|
11
|
-
It exposes the SDK
|
|
12
|
-
supporting both one-shot cold-start queries and persistent
|
|
11
|
+
It exposes the SDK via a WebSocket server or stdin/stdout protocol,
|
|
12
|
+
supporting both one-shot cold-start queries and persistent server sessions.
|
|
13
13
|
|
|
14
14
|
---
|
|
15
15
|
|
|
@@ -55,23 +55,27 @@ nx-ce query "Analyze" --skill all
|
|
|
55
55
|
| `--no-persist` | 不持久化会话 / Don't persist session |
|
|
56
56
|
| `--env "KEY=value,KEY2=val"` | 额外环境变量 / Extra environment variables |
|
|
57
57
|
|
|
58
|
-
### `nx-ce serve` —
|
|
58
|
+
### `nx-ce serve` — WebSocket 持久化服务器 / WebSocket server
|
|
59
|
+
|
|
60
|
+
单例进程,多客户端共享一个 SDK 会话,请求排队处理。
|
|
61
|
+
Single process with multi-client support and FIFO query queue.
|
|
59
62
|
|
|
60
63
|
```bash
|
|
64
|
+
nx-ce serve # 默认端口 3100
|
|
65
|
+
nx-ce serve --port 3100 # 指定端口
|
|
61
66
|
nx-ce serve --name chat-tab-1
|
|
62
|
-
nx-ce serve --name default --model claude-sonnet-4-6
|
|
63
67
|
```
|
|
64
68
|
|
|
65
|
-
通过 stdin/stdout 接收 4B+JSON 协议消息,保持一个持久化的 SDK 会话。
|
|
66
|
-
Reads/writes 4B+JSON protocol messages over stdin/stdout, maintaining a persistent SDK session.
|
|
67
|
-
|
|
68
69
|
| 选项 / Flag | 说明 / Description |
|
|
69
70
|
|-------------|-------------------|
|
|
70
71
|
| `--name <name>` | 实例名称(默认 `"default"`)/ Instance name |
|
|
72
|
+
| `--port <port>` | WebSocket 端口(默认 `3100`)/ WebSocket port |
|
|
71
73
|
| `--model <id>` | 模型 ID 覆盖 / Model override |
|
|
72
74
|
| `--claude-path <path>` | Claude CLI 可执行文件路径 / Path to Claude CLI binary |
|
|
73
75
|
| `--env "KEY=value,..."` | 额外环境变量 / Extra environment variables |
|
|
74
76
|
|
|
77
|
+
> WebSocket 地址: `ws://127.0.0.1:3100`
|
|
78
|
+
|
|
75
79
|
### `nx-ce status` — 查看实例状态 / Show instance state
|
|
76
80
|
|
|
77
81
|
```bash
|
|
@@ -87,60 +91,96 @@ nx-ce help
|
|
|
87
91
|
|
|
88
92
|
---
|
|
89
93
|
|
|
90
|
-
## 协议 / Protocol
|
|
94
|
+
## WebSocket 协议 / WebSocket Protocol
|
|
95
|
+
|
|
96
|
+
服务端地址 `ws://127.0.0.1:PORT`(默认 3100)。所有消息均为 JSON 字符串(不含长度前缀)。
|
|
97
|
+
|
|
98
|
+
Server at `ws://127.0.0.1:PORT` (default 3100). All messages are JSON strings (no length prefix).
|
|
91
99
|
|
|
92
|
-
|
|
100
|
+
### 客户端发送 / Client → Server
|
|
93
101
|
|
|
94
|
-
|
|
102
|
+
| type | 字段 / Fields | 说明 / Description |
|
|
103
|
+
|------|---------------|-------------------|
|
|
104
|
+
| `query` | `prompt: string`, `id?: string` | 发起查询 / Submit a query |
|
|
105
|
+
| `ping` | 无 | 心跳检测 / Heartbeat |
|
|
106
|
+
| `getSkills` | 无 | 拉取技能/工具列表 / Fetch skills & tools |
|
|
95
107
|
|
|
108
|
+
```json
|
|
109
|
+
→ { "type": "query", "prompt": "解释这段代码" }
|
|
110
|
+
→ { "type": "ping" }
|
|
111
|
+
→ { "type": "getSkills" }
|
|
96
112
|
```
|
|
97
|
-
|
|
113
|
+
|
|
114
|
+
### 服务端发送 / Server → Client
|
|
115
|
+
|
|
116
|
+
**连接建立 / On connect:**
|
|
117
|
+
|
|
118
|
+
```json
|
|
119
|
+
← { "type": "connected", "sessionId": "sess_xxx", "port": 3100 }
|
|
120
|
+
← { "type": "init", "sessionId": "sess_xxx", "model": "claude-sonnet-4-6",
|
|
121
|
+
"skills": [...], "tools": [...], "slashCommands": [...], "agents": [...] }
|
|
98
122
|
```
|
|
99
123
|
|
|
100
|
-
|
|
124
|
+
**查询响应 / Query response (streamed chunks):**
|
|
101
125
|
|
|
126
|
+
```json
|
|
127
|
+
← { "type": "text", "content": "这是一段回复..." }
|
|
128
|
+
← { "type": "thinking", "content": "模型思考过程..." }
|
|
129
|
+
← { "type": "tool_use", "name": "readFile", "input": {...}, "id": "toolu_xxx" }
|
|
130
|
+
← { "type": "done", "sessionId": "sess_xxx" }
|
|
102
131
|
```
|
|
103
|
-
→ { "prompt": "...", "model": "...", "systemPrompt": "..." }
|
|
104
|
-
← { "text": "...", "sessionId": "sess_xxx" }
|
|
105
132
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
133
|
+
**其他 / Other:**
|
|
134
|
+
|
|
135
|
+
```json
|
|
136
|
+
← { "type": "pong", "sessionId": "sess_xxx" }
|
|
137
|
+
← { "type": "skills", "skills": [...], "tools": [...], "slashCommands": [...], "agents": [...] }
|
|
138
|
+
← { "type": "error", "content": "error message" }
|
|
109
139
|
```
|
|
110
140
|
|
|
111
|
-
###
|
|
141
|
+
### 完整示例 / Full exchange
|
|
112
142
|
|
|
113
143
|
```
|
|
114
|
-
→ { "
|
|
115
|
-
← { "
|
|
116
|
-
← { "
|
|
117
|
-
← { "id":"1", "type":"thinking", "content":"..." }
|
|
118
|
-
← { "id":"1", "type":"done", "sessionId":"..." }
|
|
144
|
+
→ { "type": "query", "prompt": "Hello" }
|
|
145
|
+
← { "type": "text", "content": "Hello! How can I help you today?" }
|
|
146
|
+
← { "type": "done", "sessionId": "sess_abc123" }
|
|
119
147
|
|
|
120
|
-
→ { "type":"ping" }
|
|
121
|
-
← { "type":"pong",
|
|
148
|
+
→ { "type": "ping" }
|
|
149
|
+
← { "type": "pong", "sessionId": "sess_abc123" }
|
|
150
|
+
```
|
|
122
151
|
|
|
123
|
-
|
|
124
|
-
← { "type":"skills", "skills":["browse",...], "tools":["Read",...], "slashCommands":[...], "agents":[...] }
|
|
152
|
+
### 单例机制 / Singleton guarantee
|
|
125
153
|
|
|
126
|
-
|
|
127
|
-
|
|
154
|
+
重复启动 `nx-ce serve` 会在同一端口上失败:
|
|
155
|
+
|
|
156
|
+
```
|
|
157
|
+
端口 3100 已被占用 — nx-ce 单例进程已在运行中
|
|
158
|
+
Port 3100 already in use — another nx-ce instance is running
|
|
128
159
|
```
|
|
129
160
|
|
|
130
|
-
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## 协议 / Protocol (stdin/stdout)
|
|
164
|
+
|
|
165
|
+
`nx-ce query` 子命令仍使用长度前缀 JSON(Chrome Native Messaging 格式):
|
|
166
|
+
|
|
167
|
+
```
|
|
168
|
+
[4 bytes LE uint32 = 负载长度 / payload length][UTF-8 JSON payload]
|
|
169
|
+
```
|
|
131
170
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
171
|
+
### 查询(一次性)/ Query (one-shot)
|
|
172
|
+
|
|
173
|
+
```
|
|
174
|
+
→ { "prompt": "...", "model": "...", "systemPrompt": "..." }
|
|
175
|
+
← { "text": "...", "sessionId": "sess_xxx" }
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### 带元数据输出 / With metadata
|
|
179
|
+
|
|
180
|
+
```
|
|
181
|
+
← { "text": "...", "sessionId": "sess_xxx",
|
|
182
|
+
"metadata": { "skills": [...], "tools": [...], "slashCommands": [...] } }
|
|
183
|
+
```
|
|
144
184
|
|
|
145
185
|
---
|
|
146
186
|
|
|
@@ -148,10 +188,8 @@ All IPC uses the same wire format as Chrome native messaging:
|
|
|
148
188
|
|
|
149
189
|
```
|
|
150
190
|
Chrome Extension / 浏览器扩展
|
|
151
|
-
↕
|
|
152
|
-
|
|
153
|
-
↕ 4B+JSON (via executor.startProcess)
|
|
154
|
-
nx-ce serve (Node.js)
|
|
191
|
+
↕ WebSocket (ws://127.0.0.1:3100)
|
|
192
|
+
nx-ce serve (Node.js) ← 单例进程 / singleton process
|
|
155
193
|
↕ @anthropic-ai/claude-agent-sdk
|
|
156
194
|
Claude Code CLI (子进程 / subprocess)
|
|
157
195
|
```
|
|
@@ -165,8 +203,6 @@ Claude Code CLI (子进程 / subprocess)
|
|
|
165
203
|
|
|
166
204
|
Persisted to `~/.nx-ce/instances/{name}.json`. Each named instance stores its PID, session ID, and start time for crash recovery and session resumption.
|
|
167
205
|
|
|
168
|
-
示例状态文件 / Example state file:
|
|
169
|
-
|
|
170
206
|
```json
|
|
171
207
|
{
|
|
172
208
|
"name": "chat-tab-1",
|
|
@@ -182,9 +218,12 @@ Persisted to `~/.nx-ce/instances/{name}.json`. Each named instance stores its PI
|
|
|
182
218
|
## 开发 / Development
|
|
183
219
|
|
|
184
220
|
```bash
|
|
185
|
-
#
|
|
221
|
+
# 本地运行一次查询 / Run a one-shot query
|
|
186
222
|
node ./bin/nx-ce.js query "你好"
|
|
187
223
|
|
|
224
|
+
# 启动 WebSocket 服务 / Start WebSocket server
|
|
225
|
+
node ./bin/nx-ce.js serve --port 3100
|
|
226
|
+
|
|
188
227
|
# 检查语法 / Check syntax
|
|
189
228
|
node -c src/*.js
|
|
190
229
|
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nx-ce",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Claude Engine — SDK adapter layer for native messaging host. Bridges @anthropic-ai/claude-agent-sdk calls over a length-prefixed JSON protocol.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
],
|
|
31
31
|
"license": "MIT",
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@anthropic-ai/claude-agent-sdk": "^0.3.159"
|
|
33
|
+
"@anthropic-ai/claude-agent-sdk": "^0.3.159",
|
|
34
|
+
"ws": "^8.21.0"
|
|
34
35
|
}
|
|
35
36
|
}
|
package/src/cli.js
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import { existsSync } from 'node:fs';
|
|
9
9
|
import { runQuery } from './query.js';
|
|
10
10
|
import { startServe } from './serve.js';
|
|
11
|
+
import { listSkills } from './skills.js';
|
|
11
12
|
import { readState, listStates } from './session-store.js';
|
|
12
13
|
|
|
13
14
|
/**
|
|
@@ -82,7 +83,7 @@ export async function runCli() {
|
|
|
82
83
|
}
|
|
83
84
|
|
|
84
85
|
case 'serve': {
|
|
85
|
-
// 持久化服务模式
|
|
86
|
+
// WebSocket 持久化服务模式
|
|
86
87
|
const name = flags.name || 'default';
|
|
87
88
|
|
|
88
89
|
const result = await startServe({
|
|
@@ -91,6 +92,7 @@ export async function runCli() {
|
|
|
91
92
|
model: flags.model,
|
|
92
93
|
cwd: flags.cwd || process.cwd(),
|
|
93
94
|
env: flags.env ? parseEnvString(flags.env) : undefined,
|
|
95
|
+
port: flags.port ? parseInt(flags.port, 10) : undefined,
|
|
94
96
|
});
|
|
95
97
|
|
|
96
98
|
return result;
|
|
@@ -105,6 +107,15 @@ export async function runCli() {
|
|
|
105
107
|
return listStates(); // 列出所有实例
|
|
106
108
|
}
|
|
107
109
|
|
|
110
|
+
case 'skills': {
|
|
111
|
+
const result = await listSkills({
|
|
112
|
+
cwd: flags.cwd || process.cwd(),
|
|
113
|
+
claudePath: resolveClaudePath(flags['claude-path']),
|
|
114
|
+
env: flags.env ? parseEnvString(flags.env) : undefined,
|
|
115
|
+
});
|
|
116
|
+
return result;
|
|
117
|
+
}
|
|
118
|
+
|
|
108
119
|
case 'help':
|
|
109
120
|
default:
|
|
110
121
|
// 显示帮助信息
|
|
@@ -122,14 +133,17 @@ export async function runCli() {
|
|
|
122
133
|
--no-persist 不持久化会话
|
|
123
134
|
--env "KEY=value,KEY2=val" 额外环境变量
|
|
124
135
|
|
|
125
|
-
nx-ce serve
|
|
136
|
+
nx-ce serve WebSocket 持久化服务器(单一进程 / 多客户端)
|
|
126
137
|
--name <name> 实例名称(默认: "default")
|
|
138
|
+
--port <port> WebSocket 端口(默认: 3100)
|
|
127
139
|
--model <id> 模型覆盖
|
|
128
140
|
--claude-path <path> Claude CLI 路径
|
|
129
141
|
--env "KEY=value,..." 额外环境变量
|
|
130
142
|
|
|
131
143
|
nx-ce status [--name <name>] 查看实例状态
|
|
132
144
|
|
|
145
|
+
nx-ce skills [--cwd <path>] 列出 SDK 可用 skill/tool/agent
|
|
146
|
+
|
|
133
147
|
nx-ce help 显示此帮助
|
|
134
148
|
`);
|
|
135
149
|
return null;
|
package/src/index.js
CHANGED
|
@@ -7,5 +7,14 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
export { runQuery } from './query.js';
|
|
10
|
-
export {
|
|
10
|
+
export { listSkills } from './skills.js';
|
|
11
|
+
export {
|
|
12
|
+
readState,
|
|
13
|
+
writeState,
|
|
14
|
+
deleteState,
|
|
15
|
+
listStates,
|
|
16
|
+
LifecycleState,
|
|
17
|
+
createState,
|
|
18
|
+
} from './session-store.js';
|
|
11
19
|
export { readMessage, writeMessage } from './protocol.js';
|
|
20
|
+
export { generateId, MonotonicClock, getMachineId, formatBytes } from './util.js';
|