glm-acp-agent 1.0.0
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 +365 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +62 -0
- package/dist/index.js.map +1 -0
- package/dist/llm/credentials.d.ts +15 -0
- package/dist/llm/credentials.d.ts.map +1 -0
- package/dist/llm/credentials.js +54 -0
- package/dist/llm/credentials.js.map +1 -0
- package/dist/llm/glm-client.d.ts +63 -0
- package/dist/llm/glm-client.d.ts.map +1 -0
- package/dist/llm/glm-client.js +217 -0
- package/dist/llm/glm-client.js.map +1 -0
- package/dist/llm/logger.d.ts +19 -0
- package/dist/llm/logger.d.ts.map +1 -0
- package/dist/llm/logger.js +44 -0
- package/dist/llm/logger.js.map +1 -0
- package/dist/protocol/agent.d.ts +77 -0
- package/dist/protocol/agent.d.ts.map +1 -0
- package/dist/protocol/agent.js +732 -0
- package/dist/protocol/agent.js.map +1 -0
- package/dist/protocol/connection.d.ts +9 -0
- package/dist/protocol/connection.d.ts.map +1 -0
- package/dist/protocol/connection.js +18 -0
- package/dist/protocol/connection.js.map +1 -0
- package/dist/protocol/image-preprocessor.d.ts +32 -0
- package/dist/protocol/image-preprocessor.d.ts.map +1 -0
- package/dist/protocol/image-preprocessor.js +149 -0
- package/dist/protocol/image-preprocessor.js.map +1 -0
- package/dist/protocol/session-store.d.ts +54 -0
- package/dist/protocol/session-store.d.ts.map +1 -0
- package/dist/protocol/session-store.js +109 -0
- package/dist/protocol/session-store.js.map +1 -0
- package/dist/protocol/system-prompt.d.ts +29 -0
- package/dist/protocol/system-prompt.d.ts.map +1 -0
- package/dist/protocol/system-prompt.js +103 -0
- package/dist/protocol/system-prompt.js.map +1 -0
- package/dist/setup.d.ts +8 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +95 -0
- package/dist/setup.js.map +1 -0
- package/dist/tests/agent.test.d.ts +2 -0
- package/dist/tests/agent.test.d.ts.map +1 -0
- package/dist/tests/agent.test.js +1118 -0
- package/dist/tests/agent.test.js.map +1 -0
- package/dist/tests/credentials.test.d.ts +2 -0
- package/dist/tests/credentials.test.d.ts.map +1 -0
- package/dist/tests/credentials.test.js +112 -0
- package/dist/tests/credentials.test.js.map +1 -0
- package/dist/tests/executor.test.d.ts +2 -0
- package/dist/tests/executor.test.d.ts.map +1 -0
- package/dist/tests/executor.test.js +497 -0
- package/dist/tests/executor.test.js.map +1 -0
- package/dist/tests/glm-client.test.d.ts +2 -0
- package/dist/tests/glm-client.test.d.ts.map +1 -0
- package/dist/tests/glm-client.test.js +205 -0
- package/dist/tests/glm-client.test.js.map +1 -0
- package/dist/tests/image-preprocessor.test.d.ts +2 -0
- package/dist/tests/image-preprocessor.test.d.ts.map +1 -0
- package/dist/tests/image-preprocessor.test.js +133 -0
- package/dist/tests/image-preprocessor.test.js.map +1 -0
- package/dist/tests/integration.test.d.ts +2 -0
- package/dist/tests/integration.test.d.ts.map +1 -0
- package/dist/tests/integration.test.js +192 -0
- package/dist/tests/integration.test.js.map +1 -0
- package/dist/tests/logger.test.d.ts +2 -0
- package/dist/tests/logger.test.d.ts.map +1 -0
- package/dist/tests/logger.test.js +14 -0
- package/dist/tests/logger.test.js.map +1 -0
- package/dist/tests/mcp-arg-remap.test.d.ts +2 -0
- package/dist/tests/mcp-arg-remap.test.d.ts.map +1 -0
- package/dist/tests/mcp-arg-remap.test.js +65 -0
- package/dist/tests/mcp-arg-remap.test.js.map +1 -0
- package/dist/tests/vision-mcp-client.test.d.ts +2 -0
- package/dist/tests/vision-mcp-client.test.d.ts.map +1 -0
- package/dist/tests/vision-mcp-client.test.js +129 -0
- package/dist/tests/vision-mcp-client.test.js.map +1 -0
- package/dist/tests/zai-mcp-client.test.d.ts +2 -0
- package/dist/tests/zai-mcp-client.test.d.ts.map +1 -0
- package/dist/tests/zai-mcp-client.test.js +386 -0
- package/dist/tests/zai-mcp-client.test.js.map +1 -0
- package/dist/tools/definitions.d.ts +18 -0
- package/dist/tools/definitions.d.ts.map +1 -0
- package/dist/tools/definitions.js +149 -0
- package/dist/tools/definitions.js.map +1 -0
- package/dist/tools/executor.d.ts +48 -0
- package/dist/tools/executor.d.ts.map +1 -0
- package/dist/tools/executor.js +670 -0
- package/dist/tools/executor.js.map +1 -0
- package/dist/tools/mcp-arg-remap.d.ts +21 -0
- package/dist/tools/mcp-arg-remap.d.ts.map +1 -0
- package/dist/tools/mcp-arg-remap.js +70 -0
- package/dist/tools/mcp-arg-remap.js.map +1 -0
- package/dist/tools/vision-mcp-client.d.ts +38 -0
- package/dist/tools/vision-mcp-client.d.ts.map +1 -0
- package/dist/tools/vision-mcp-client.js +191 -0
- package/dist/tools/vision-mcp-client.js.map +1 -0
- package/dist/tools/zai-mcp-client.d.ts +24 -0
- package/dist/tools/zai-mcp-client.d.ts.map +1 -0
- package/dist/tools/zai-mcp-client.js +189 -0
- package/dist/tools/zai-mcp-client.js.map +1 -0
- package/package.json +37 -0
package/README.md
ADDED
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
# glm-acp-agent
|
|
2
|
+
|
|
3
|
+
An [Agent Client Protocol (ACP)](https://agentclientprotocol.com) agent written in TypeScript that uses the **Z.AI / Zhipu AI GLM** model family (GLM-5.1, GLM-4.7, GLM-4.6, …) as its reasoning core.
|
|
4
|
+
|
|
5
|
+
The agent connects to any ACP-compatible IDE or client over **stdio**, streams responses back in real time, and can call a rich set of tools to interact with the user's file system, terminal, and the web.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Coding Plan Only
|
|
10
|
+
|
|
11
|
+
`glm-acp-agent` is intentionally built for the **Z.AI GLM Coding Plan**. It is not a general-purpose Z.AI Open Platform API client.
|
|
12
|
+
|
|
13
|
+
By default, model calls use the Coding Plan endpoint:
|
|
14
|
+
|
|
15
|
+
```text
|
|
16
|
+
https://api.z.ai/api/coding/paas/v4
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
The same Coding Plan API key is used for the agent's GLM model calls and supported Coding Plan tools. General Z.AI API/resource-package billing surfaces, such as direct `/api/paas/v4` Tool API calls, are intentionally out of scope for this ACP agent.
|
|
20
|
+
|
|
21
|
+
Built-in web tools use Coding Plan-compatible MCP endpoints, not the general `/api/paas/v4` Tool API. If you need general Z.AI API billing, separate resource packages, or non-Coding Plan endpoints, use a different provider configuration or fork this agent for that purpose.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Features
|
|
26
|
+
|
|
27
|
+
- **Full ACP compliance** – implements `initialize`, `authenticate`, `session/new`, `session/set_mode`, `session/prompt`, `session/cancel`, `session/close`, `session/list`, `session/load`, `session/fork`, `session/resume`, and `session/set_model`
|
|
28
|
+
- **Streaming** – assistant text and reasoning tokens are forwarded as incremental ACP chunks
|
|
29
|
+
- **Tool calling** – agentic loop with up to 20 turns of GLM function calling
|
|
30
|
+
- **Thinking mode** – GLM's `reasoning_content` tokens are surfaced as `agent_thought_chunk` blocks so the client can show the model's chain of thought
|
|
31
|
+
- **Per-session model switching** – `session/set_model` lets clients change the active GLM model mid-conversation; `session/new` returns the curated `availableModels` list
|
|
32
|
+
- **Image input via Coding Plan Vision MCP** – `promptCapabilities.image` is advertised; pasted ACP image blocks are routed through Z.AI Vision MCP (`@z_ai/mcp-server`) and the resulting analysis is fed into the main coding model. Direct chat-image (e.g. `glm-4v-plus`) calls are intentionally not used.
|
|
33
|
+
- **Session persistence** – conversations are written to `~/.local/state/glm-acp-agent/sessions/` and can be reloaded via `session/load`, branched via `session/fork`, or resumed without replay via `session/resume`
|
|
34
|
+
- **Six built-in tools** (see below)
|
|
35
|
+
- **Capability-aware** – every tool is gated on the client capabilities advertised at `initialize` time; tools the client can't run return a clear error to the model instead of crashing
|
|
36
|
+
- **Permissioned writes / commands** – every `write_file` and `run_command` call asks the user via `session/request_permission` before doing anything
|
|
37
|
+
- **Protocol-correct stop reasons** – maps model and runtime conditions to ACP `end_turn`, `max_tokens`, `max_turn_requests`, `refusal`, and `cancelled`
|
|
38
|
+
- **Protocol-correct tool statuses** – `pending` → `in_progress` → `completed` / `failed`
|
|
39
|
+
- **Token usage reporting** – aggregated usage is returned on the `session/prompt` response
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Architecture
|
|
44
|
+
|
|
45
|
+
```text
|
|
46
|
+
ACP Client (IDE plugin, CLI, …)
|
|
47
|
+
│ stdio (ndjson)
|
|
48
|
+
▼
|
|
49
|
+
GlmAcpAgent ← ACP protocol layer (src/protocol/)
|
|
50
|
+
│
|
|
51
|
+
├─ GlmClient ← Z.AI / Zhipu AI Coding Plan Chat Completions (src/llm/)
|
|
52
|
+
│
|
|
53
|
+
├─ ToolExecutor ← executes tool calls (src/tools/)
|
|
54
|
+
│ ├─ read_file / write_file → ACP client (fs.*)
|
|
55
|
+
│ ├─ list_files / run_command → ACP client (terminal)
|
|
56
|
+
│ ├─ web_search / web_reader → Z.AI Coding Plan Web MCP (HTTP)
|
|
57
|
+
│ └─ image_analysis → Z.AI Coding Plan Vision MCP (stdio)
|
|
58
|
+
│
|
|
59
|
+
└─ VisionMcpClient ← spawns `npx @z_ai/mcp-server` on demand
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The agent process needs network access to `api.z.ai` for chat completions and Web MCP, plus `npx` available on `PATH` so it can launch `@z_ai/mcp-server` for vision. Filesystem and shell operations remain delegated to the ACP client; the agent itself only writes to the OS temp directory when it needs to materialize a pasted image for Vision MCP, and those temp files are removed once the prompt completes.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Available Tools
|
|
67
|
+
|
|
68
|
+
| Tool | Runs on | Requires client capability | Description |
|
|
69
|
+
|------|---------|----------------------------|-------------|
|
|
70
|
+
| `read_file` | ACP client | `fs.readTextFile` | Read the text content of a file |
|
|
71
|
+
| `write_file` | ACP client | `fs.writeTextFile` | Write or overwrite a text file (asks for permission) |
|
|
72
|
+
| `list_files` | ACP client | `terminal` | List a directory via `ls -la` (POSIX shell required) |
|
|
73
|
+
| `run_command` | ACP client | `terminal` | Run an arbitrary shell command via `sh -c` (asks for permission) |
|
|
74
|
+
| `web_search` | Agent (Z.AI Coding Plan MCP) | – | Search the web — returns titles, URLs, and summaries |
|
|
75
|
+
| `web_reader` | Agent (Z.AI Coding Plan MCP) | – | Fetch and parse a web page (markdown or plain text) |
|
|
76
|
+
| `image_analysis` | Agent (Z.AI Vision MCP, stdio) | – | Analyze a local image path or remote URL using `@z_ai/mcp-server` |
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Prerequisites
|
|
81
|
+
|
|
82
|
+
- **Node.js** 20 or later (native `fetch` and Web Streams required)
|
|
83
|
+
- **npm** 9 or later
|
|
84
|
+
- A **Z.AI API key** — obtain one at <https://z.ai/manage-apikey/apikey-list>
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Installation
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
git clone https://github.com/stefandevo/glm-acp-agent.git
|
|
92
|
+
cd glm-acp-agent
|
|
93
|
+
npm install
|
|
94
|
+
npm run build
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Configuration
|
|
100
|
+
|
|
101
|
+
The agent reads its configuration from environment variables, plus an optional credentials file written by `glm-acp-agent --setup`.
|
|
102
|
+
|
|
103
|
+
| Variable | Required | Default | Description |
|
|
104
|
+
|----------|----------|---------|-------------|
|
|
105
|
+
| `Z_AI_API_KEY` | One of env / `--setup` | — | API key for the Z.AI / Zhipu AI service. If unset, the credentials file is consulted. |
|
|
106
|
+
| `ACP_GLM_MODEL` | No | `glm-5.1` | Default GLM model for new sessions |
|
|
107
|
+
| `ACP_GLM_AVAILABLE_MODELS` | No | built-in list | Comma-separated list of model ids advertised in `session/set_model` |
|
|
108
|
+
| `ACP_GLM_BASE_URL` | No | `https://api.z.ai/api/coding/paas/v4` | Override the API base URL |
|
|
109
|
+
| `ACP_GLM_MAX_TOKENS` | No | `8192` | Cap on `max_tokens` for each completion |
|
|
110
|
+
| `ACP_GLM_THINKING` | No | auto-detected | Force thinking mode `true` / `false` |
|
|
111
|
+
| `ACP_GLM_SESSION_DIR` | No | `$XDG_STATE_HOME/glm-acp-agent/sessions` | Where session JSON files are persisted |
|
|
112
|
+
| `ACP_GLM_DEBUG` | No | — | Set to `true` or `1` to enable verbose debug logging to stderr (shows model selection, API key resolution, tool calls, and usage stats) |
|
|
113
|
+
| `XDG_CONFIG_HOME` | No | `~/.config` | Where the credentials file is read/written |
|
|
114
|
+
|
|
115
|
+
### One-time setup
|
|
116
|
+
|
|
117
|
+
If you'd rather not pass `Z_AI_API_KEY` through your ACP client's environment block, run the interactive setup once and the agent will read the key from disk on subsequent launches:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
# From the project directory (after npm run build)
|
|
121
|
+
node dist/index.js --setup
|
|
122
|
+
|
|
123
|
+
# Or, if you installed globally
|
|
124
|
+
glm-acp-agent --setup
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
The key is written to `$XDG_CONFIG_HOME/glm-acp-agent/credentials.json` (default: `~/.config/glm-acp-agent/credentials.json`) with `0600` permissions. The `Z_AI_API_KEY` environment variable, when set, always wins over the file.
|
|
128
|
+
|
|
129
|
+
### Supported models
|
|
130
|
+
|
|
131
|
+
The agent advertises only the models on the current Z.AI Coding Plan allowlist:
|
|
132
|
+
|
|
133
|
+
| Model | Notes |
|
|
134
|
+
|-------|-------|
|
|
135
|
+
| `glm-5.1` | **Default.** Long-horizon coding model; thinking mode auto-enabled |
|
|
136
|
+
| `glm-5-turbo` | Faster Coding Plan reasoning model |
|
|
137
|
+
| `glm-4.7` | 200K-context reasoning model |
|
|
138
|
+
| `glm-4.5-air` | Lightweight, lower-latency model |
|
|
139
|
+
|
|
140
|
+
`ACP_GLM_AVAILABLE_MODELS` still lets you advertise custom IDs, but custom IDs sit outside the supported Coding Plan list — the Coding Plan endpoint will reject any model code Z.AI hasn't whitelisted (business code `1211`).
|
|
141
|
+
|
|
142
|
+
Vision (`glm-4v-plus` etc.) is **not** advertised as a chat model: vision on the Coding Plan flows through the [Vision MCP](#vision-mcp) section below instead.
|
|
143
|
+
|
|
144
|
+
When the model name matches `glm-4.5`, `glm-4.6`, `glm-4.7`, or `glm-5.x`, the agent enables Z.AI's `thinking: { type: "enabled" }` extension and forwards reasoning tokens to the client as `agent_thought_chunk` blocks. Override with `ACP_GLM_THINKING=false` if you want plain completions only.
|
|
145
|
+
|
|
146
|
+
### Vision MCP
|
|
147
|
+
|
|
148
|
+
Pasted ACP image blocks are not sent to the chat-completions endpoint. Instead, the agent boots `@z_ai/mcp-server` over stdio (via `npx -y @z_ai/mcp-server@latest`) and calls its `image_analysis` tool. The text result is spliced into the user message as `<image_analysis index="N">…</image_analysis>` so the regular Coding Plan model can reason about it.
|
|
149
|
+
|
|
150
|
+
Prerequisites:
|
|
151
|
+
|
|
152
|
+
- `npx` on `PATH` (Node 18+ / npm 9+).
|
|
153
|
+
- The same `Z_AI_API_KEY` used for chat completions; the agent forwards it to the MCP server as `Z_AI_API_KEY` plus `Z_AI_MODE=ZAI`.
|
|
154
|
+
|
|
155
|
+
The model can also call `image_analysis` explicitly with `{ image_source: "/path/or/url", prompt?: "…" }`. Vision failures (missing `npx`, MCP startup, quota) are surfaced as actionable errors but never abort the prompt; an inline `<image_analysis_error>` annotation is used so the conversation can continue.
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Running
|
|
160
|
+
|
|
161
|
+
### Standalone (stdio)
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
export Z_AI_API_KEY=your_key_here
|
|
165
|
+
node dist/index.js
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
The agent speaks the ACP newline-delimited JSON protocol over stdin/stdout. You can connect any ACP-compatible client to it.
|
|
169
|
+
|
|
170
|
+
### As a global CLI
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
npm install -g .
|
|
174
|
+
export Z_AI_API_KEY=your_key_here
|
|
175
|
+
glm-acp-agent
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Development mode (watch)
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
export Z_AI_API_KEY=your_key_here
|
|
182
|
+
npm run dev # tsc --watch
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## Connecting to an ACP Client
|
|
188
|
+
|
|
189
|
+
### Zed (recommended for local testing)
|
|
190
|
+
|
|
191
|
+
[Zed](https://zed.dev) is currently the most polished editor for trying out ACP agents locally — it spawns the agent process over stdio and surfaces it in the agent panel. This is the fastest way to iterate on `glm-acp-agent` before publishing it to the ACP registry or to npm.
|
|
192
|
+
|
|
193
|
+
#### 1. Prerequisites
|
|
194
|
+
|
|
195
|
+
- A recent build of [Zed](https://zed.dev/download) that supports the `agent_servers` setting
|
|
196
|
+
- Node.js 20 or later on your `PATH` (`node --version`)
|
|
197
|
+
- A Z.AI API key — create one at <https://z.ai/manage-apikey/apikey-list>
|
|
198
|
+
|
|
199
|
+
#### 2. Build the agent
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
git clone https://github.com/stefandevo/glm-acp-agent.git
|
|
203
|
+
cd glm-acp-agent
|
|
204
|
+
npm install
|
|
205
|
+
npm run build
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Take note of the absolute path to the freshly built entry point — Zed needs it (no `~`, no `$HOME` shortcuts):
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
echo "$(pwd)/dist/index.js"
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
#### 3. Wire it into Zed
|
|
215
|
+
|
|
216
|
+
Open (or create) `~/.config/zed/settings.json` and add an `agent_servers` entry. Pick **one** of the two API-key strategies below.
|
|
217
|
+
|
|
218
|
+
**Option A — inline `env` block (simplest):**
|
|
219
|
+
|
|
220
|
+
```json
|
|
221
|
+
{
|
|
222
|
+
"agent_servers": {
|
|
223
|
+
"glm": {
|
|
224
|
+
"command": "node",
|
|
225
|
+
"args": ["/absolute/path/to/glm-acp-agent/dist/index.js"],
|
|
226
|
+
"env": { "Z_AI_API_KEY": "sk-…" }
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**Option B — credentials file (no key in your editor settings):**
|
|
233
|
+
|
|
234
|
+
Run the interactive setup once. From the project directory:
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
node dist/index.js --setup
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
…or, if you `npm install -g .`'d the package:
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
glm-acp-agent --setup
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
The key is written to `~/.config/glm-acp-agent/credentials.json` with `0600` permissions. Then drop the `env` block from the Zed entry — the agent will read the file on launch:
|
|
247
|
+
|
|
248
|
+
```json
|
|
249
|
+
{
|
|
250
|
+
"agent_servers": {
|
|
251
|
+
"glm": {
|
|
252
|
+
"command": "node",
|
|
253
|
+
"args": ["/absolute/path/to/glm-acp-agent/dist/index.js"]
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
If `Z_AI_API_KEY` is set in the environment **and** a credentials file exists, the environment variable wins.
|
|
260
|
+
|
|
261
|
+
#### 4. Verify it works
|
|
262
|
+
|
|
263
|
+
1. Save `settings.json`. Zed reloads settings automatically.
|
|
264
|
+
2. Open the **agent panel** (use the command palette: `agent panel: toggle focus`).
|
|
265
|
+
3. In the agent picker, select **glm** — Zed labels external agents by their `agent_servers` key.
|
|
266
|
+
4. Start a new thread and send a small prompt that exercises a tool, e.g. `Read package.json and tell me the project name.`
|
|
267
|
+
5. You should see streaming text, a `read_file` tool call awaiting permission, and (with a thinking-capable model like `glm-5.1`) reasoning surfaced as a separate thought block.
|
|
268
|
+
|
|
269
|
+
#### 5. Iterating on the agent
|
|
270
|
+
|
|
271
|
+
After editing the source, rebuild:
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
npm run build
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
Zed spawns a fresh agent process per thread, so the easiest way to pick up changes is to **start a new thread** with the glm agent. If you see stale behavior, fully quit and reopen Zed — that guarantees no in-flight process is reused.
|
|
278
|
+
|
|
279
|
+
For a tighter inner loop, run `npm run dev` in a terminal so `dist/` rebuilds on every save; you only need to start a new Zed thread to test the latest code.
|
|
280
|
+
|
|
281
|
+
#### 6. Troubleshooting
|
|
282
|
+
|
|
283
|
+
- **The "glm" agent doesn't appear in the picker.** — `settings.json` likely has a JSON parse error, or your Zed build is older than `agent_servers` support. Open the Zed log via the command palette (`zed: open log`) and look for settings errors.
|
|
284
|
+
- **`Error: Cannot find module '/.../dist/index.js'`** — you skipped `npm run build`, or the path in `args` is wrong. It must be absolute and point at a file that exists.
|
|
285
|
+
- **`No API key found.`** — neither `Z_AI_API_KEY` nor `~/.config/glm-acp-agent/credentials.json` is set. Use Option A or Option B in step 3.
|
|
286
|
+
- **`HTTP 401: Invalid API key`** — your key is wrong, expired, or for the wrong region. Rotate it on <https://z.ai/manage-apikey/apikey-list>.
|
|
287
|
+
- **`client does not advertise the … capability`** — Zed didn't expose that capability to the agent (e.g. `terminal` for `run_command`/`list_files`). Ask the model to use a different tool, or upgrade Zed.
|
|
288
|
+
|
|
289
|
+
### Neovim / VS Code / JetBrains / any ACP client
|
|
290
|
+
|
|
291
|
+
Any client that supports configuring an ACP agent via a `command` + `args` invocation works the same way: point it at `node /absolute/path/to/glm-acp-agent/dist/index.js` and supply `Z_AI_API_KEY` in the environment.
|
|
292
|
+
|
|
293
|
+
### Authentication
|
|
294
|
+
|
|
295
|
+
The agent advertises two authentication methods at `initialize` time:
|
|
296
|
+
|
|
297
|
+
1. An **`agent`-default** method — the agent will read the API key itself, either from the `Z_AI_API_KEY` environment variable or from the credentials file written by `glm-acp-agent --setup`.
|
|
298
|
+
2. An **`env_var`** method (experimental SDK extension) describing the `Z_AI_API_KEY` variable so capable clients can prompt the user and inject it.
|
|
299
|
+
|
|
300
|
+
ACP clients that support the auth-methods proposal will use whichever method they recognise; clients that don't handle auth methods should set `Z_AI_API_KEY` themselves before launching the agent (or run `glm-acp-agent --setup` once and let the agent read it from disk).
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## Project Structure
|
|
305
|
+
|
|
306
|
+
```text
|
|
307
|
+
src/
|
|
308
|
+
├── index.ts # Entry point – starts stdio connection or --setup flow
|
|
309
|
+
├── setup.ts # Interactive credential setup (`--setup`)
|
|
310
|
+
├── llm/
|
|
311
|
+
│ ├── glm-client.ts # OpenAI-compatible client for Z.AI / Zhipu AI
|
|
312
|
+
│ └── credentials.ts # API-key resolution (env var > credentials.json)
|
|
313
|
+
├── protocol/
|
|
314
|
+
│ ├── connection.ts # Sets up the ACP stdio connection
|
|
315
|
+
│ ├── agent.ts # GlmAcpAgent – ACP protocol implementation
|
|
316
|
+
│ └── session-store.ts # On-disk persistence for load/fork/resume
|
|
317
|
+
├── tools/
|
|
318
|
+
│ ├── definitions.ts # Tool JSON schemas (function-calling format)
|
|
319
|
+
│ └── executor.ts # ToolExecutor – dispatches tool calls
|
|
320
|
+
└── tests/
|
|
321
|
+
├── agent.test.ts # Protocol-level tests for GlmAcpAgent
|
|
322
|
+
├── credentials.test.ts # Credential resolution and --setup persistence
|
|
323
|
+
├── executor.test.ts # Tests for ToolExecutor
|
|
324
|
+
├── glm-client.test.ts # Tests for streaming / tool-call assembly
|
|
325
|
+
└── integration.test.ts # End-to-end tests over the real ACP ndjson transport
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
## Building & Testing
|
|
331
|
+
|
|
332
|
+
```bash
|
|
333
|
+
npm run build # one-shot TypeScript compilation → dist/
|
|
334
|
+
npm run dev # watch mode
|
|
335
|
+
npm test # build + run unit tests with the node:test runner
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
The test suite covers:
|
|
339
|
+
|
|
340
|
+
- ACP protocol-version negotiation, capability advertising, and auth method shape
|
|
341
|
+
- Session lifecycle (`new` / `list` / `close`, filter by `cwd`)
|
|
342
|
+
- Prompt loop streaming, tool-call assembly, max-turn cap, cancellation, stop-reason mapping (`stop` → `end_turn`, `length` → `max_tokens`, `content_filter` → `refusal`, `tool_calls` exhausted → `max_turn_requests`)
|
|
343
|
+
- Content-block conversion (`text`, `resource_link`, embedded `resource`)
|
|
344
|
+
- Token usage reporting on the `PromptResponse`
|
|
345
|
+
- Tool call lifecycle (`pending` → `in_progress` → `completed` / `failed`)
|
|
346
|
+
- Capability gating (tools refuse cleanly when the client did not advertise the required capability)
|
|
347
|
+
- Permission flows for `write_file` and `run_command` (allow / reject / cancel)
|
|
348
|
+
- Shell-quoted argument handling for `list_files` and `run_command`
|
|
349
|
+
- GLM streaming: text deltas, `reasoning_content` deltas, multi-chunk tool-call assembly, and trailing usage
|
|
350
|
+
- Image preprocessing through a mocked Vision MCP client and graceful degradation on Vision MCP failures
|
|
351
|
+
|
|
352
|
+
---
|
|
353
|
+
|
|
354
|
+
## Troubleshooting
|
|
355
|
+
|
|
356
|
+
- **`No API key found.`** — either set `Z_AI_API_KEY` in the environment, or run `node dist/index.js --setup` (or `glm-acp-agent --setup` if installed globally) once to store the key on disk.
|
|
357
|
+
- **`HTTP 401: Invalid API key`** — your key is wrong or expired; rotate it on <https://z.ai/manage-apikey/apikey-list>.
|
|
358
|
+
- **The agent says "client does not advertise the … capability".** — your ACP client doesn't expose that capability (e.g. terminal). Ask the model to use a different tool, or upgrade the client.
|
|
359
|
+
- **Tools never get to run.** — make sure the client is sending the `clientCapabilities` field in `initialize`; the agent uses it to decide which tools to expose to the model.
|
|
360
|
+
|
|
361
|
+
---
|
|
362
|
+
|
|
363
|
+
## License
|
|
364
|
+
|
|
365
|
+
Apache 2.0 – see [LICENSE](LICENSE).
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* GLM ACP Agent entry point.
|
|
4
|
+
*
|
|
5
|
+
* Starts an ACP agent over stdio that uses the Zhipu AI GLM model family
|
|
6
|
+
* as its reasoning core. Pass `--setup` instead of starting the protocol
|
|
7
|
+
* loop to interactively store a Z.AI API key on disk.
|
|
8
|
+
*
|
|
9
|
+
* Environment variables:
|
|
10
|
+
* Z_AI_API_KEY - API key for the Z.AI / Zhipu AI service. If unset,
|
|
11
|
+
* falls back to the credentials file written by --setup.
|
|
12
|
+
* ACP_GLM_MODEL - (optional) Override the default model (default: glm-5.1)
|
|
13
|
+
*/
|
|
14
|
+
import { startConnection } from "./protocol/connection.js";
|
|
15
|
+
import { runSetup } from "./setup.js";
|
|
16
|
+
const args = process.argv.slice(2);
|
|
17
|
+
if (args.includes("--setup")) {
|
|
18
|
+
runSetup()
|
|
19
|
+
.then(() => process.exit(0))
|
|
20
|
+
.catch((err) => {
|
|
21
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
22
|
+
process.stderr.write(`Setup failed: ${message}\n`);
|
|
23
|
+
process.exit(1);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
else if (args.includes("--help") || args.includes("-h")) {
|
|
27
|
+
process.stdout.write([
|
|
28
|
+
"glm-acp-agent — ACP agent using Zhipu AI's GLM models",
|
|
29
|
+
"",
|
|
30
|
+
"Usage:",
|
|
31
|
+
" glm-acp-agent Start the ACP stdio loop (run by an ACP client)",
|
|
32
|
+
" glm-acp-agent --setup Interactively store your Z.AI API key on disk",
|
|
33
|
+
" glm-acp-agent --help Show this message",
|
|
34
|
+
"",
|
|
35
|
+
"Environment variables:",
|
|
36
|
+
" Z_AI_API_KEY API key (overrides the stored credentials)",
|
|
37
|
+
" ACP_GLM_MODEL Default model id (e.g. glm-5.1)",
|
|
38
|
+
" ACP_GLM_AVAILABLE_MODELS Comma-separated list of advertised models",
|
|
39
|
+
" ACP_GLM_BASE_URL Override the Z.AI API base URL",
|
|
40
|
+
" ACP_GLM_MAX_TOKENS Per-call max output tokens (default 8192)",
|
|
41
|
+
" ACP_GLM_THINKING Force thinking mode (true / false)",
|
|
42
|
+
" ACP_GLM_SESSION_DIR Where to persist sessions (default: ~/.local/state/glm-acp-agent/sessions)",
|
|
43
|
+
" ACP_GLM_DEBUG Enable verbose stderr logging (true or 1)",
|
|
44
|
+
" XDG_CONFIG_HOME Where to read/write credentials.json (default: ~/.config)",
|
|
45
|
+
"",
|
|
46
|
+
].join("\n"));
|
|
47
|
+
process.exit(0);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
const connection = startConnection();
|
|
51
|
+
// Keep the process alive until the connection closes
|
|
52
|
+
connection.closed
|
|
53
|
+
.then(() => {
|
|
54
|
+
process.exit(0);
|
|
55
|
+
})
|
|
56
|
+
.catch((err) => {
|
|
57
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
58
|
+
process.stderr.write(`Fatal error: ${message}\n`);
|
|
59
|
+
process.exit(1);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAEnC,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;IAC7B,QAAQ,EAAE;SACP,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;SAC3B,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;QACtB,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,OAAO,IAAI,CAAC,CAAC;QACnD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACP,CAAC;KAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;IAC1D,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB;QACE,uDAAuD;QACvD,EAAE;QACF,QAAQ;QACR,2EAA2E;QAC3E,yEAAyE;QACzE,6CAA6C;QAC7C,EAAE;QACF,wBAAwB;QACxB,6EAA6E;QAC7E,kEAAkE;QAClE,4EAA4E;QAC5E,iEAAiE;QACjE,4EAA4E;QAC5E,qEAAqE;QACrE,6GAA6G;QAC7G,4EAA4E;QAC5E,4FAA4F;QAC5F,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;IACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;KAAM,CAAC;IACN,MAAM,UAAU,GAAG,eAAe,EAAE,CAAC;IAErC,qDAAqD;IACrD,UAAU,CAAC,MAAM;SACd,IAAI,CAAC,GAAG,EAAE;QACT,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC;SACD,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;QACtB,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,OAAO,IAAI,CAAC,CAAC;QAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Path to the credentials JSON file. Honours `$XDG_CONFIG_HOME`. */
|
|
2
|
+
export declare function credentialsPath(): string;
|
|
3
|
+
/** Read the API key from the credentials file, returning undefined if absent. */
|
|
4
|
+
export declare function readCredentialsKey(path?: string): string | undefined;
|
|
5
|
+
/**
|
|
6
|
+
* Resolve the API key: env var > credentials file. Returns undefined when
|
|
7
|
+
* neither source has one set.
|
|
8
|
+
*/
|
|
9
|
+
export declare function resolveApiKey(): string | undefined;
|
|
10
|
+
/**
|
|
11
|
+
* Write the API key to the credentials file. Restricts the file to mode 0600
|
|
12
|
+
* so it isn't world-readable on shared machines.
|
|
13
|
+
*/
|
|
14
|
+
export declare function writeCredentials(apiKey: string, path?: string): void;
|
|
15
|
+
//# sourceMappingURL=credentials.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../src/llm/credentials.ts"],"names":[],"mappings":"AAuBA,qEAAqE;AACrE,wBAAgB,eAAe,IAAI,MAAM,CAIxC;AAED,iFAAiF;AACjF,wBAAgB,kBAAkB,CAAC,IAAI,GAAE,MAA0B,GAAG,MAAM,GAAG,SAAS,CASvF;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,MAAM,GAAG,SAAS,CAalD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,MAA0B,GAAG,IAAI,CAOvF"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join, dirname } from "node:path";
|
|
4
|
+
import { debug, maskSecret } from "./logger.js";
|
|
5
|
+
/** Path to the credentials JSON file. Honours `$XDG_CONFIG_HOME`. */
|
|
6
|
+
export function credentialsPath() {
|
|
7
|
+
const xdg = process.env["XDG_CONFIG_HOME"];
|
|
8
|
+
const base = xdg && xdg.length > 0 ? xdg : join(homedir(), ".config");
|
|
9
|
+
return join(base, "glm-acp-agent", "credentials.json");
|
|
10
|
+
}
|
|
11
|
+
/** Read the API key from the credentials file, returning undefined if absent. */
|
|
12
|
+
export function readCredentialsKey(path = credentialsPath()) {
|
|
13
|
+
try {
|
|
14
|
+
const raw = readFileSync(path, "utf8");
|
|
15
|
+
const parsed = JSON.parse(raw);
|
|
16
|
+
const key = parsed.z_ai_api_key;
|
|
17
|
+
return typeof key === "string" && key.length > 0 ? key : undefined;
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Resolve the API key: env var > credentials file. Returns undefined when
|
|
25
|
+
* neither source has one set.
|
|
26
|
+
*/
|
|
27
|
+
export function resolveApiKey() {
|
|
28
|
+
const fromEnv = process.env["Z_AI_API_KEY"];
|
|
29
|
+
if (typeof fromEnv === "string" && fromEnv.length > 0) {
|
|
30
|
+
debug(`resolveApiKey: source=env key=${maskSecret(fromEnv)}`);
|
|
31
|
+
return fromEnv;
|
|
32
|
+
}
|
|
33
|
+
const fromFile = readCredentialsKey();
|
|
34
|
+
if (fromFile) {
|
|
35
|
+
debug(`resolveApiKey: source=file key=${maskSecret(fromFile)}`);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
debug("resolveApiKey: no key found");
|
|
39
|
+
}
|
|
40
|
+
return fromFile;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Write the API key to the credentials file. Restricts the file to mode 0600
|
|
44
|
+
* so it isn't world-readable on shared machines.
|
|
45
|
+
*/
|
|
46
|
+
export function writeCredentials(apiKey, path = credentialsPath()) {
|
|
47
|
+
if (!apiKey || apiKey.length === 0) {
|
|
48
|
+
throw new Error("Refusing to write empty API key");
|
|
49
|
+
}
|
|
50
|
+
mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
|
|
51
|
+
const body = { z_ai_api_key: apiKey };
|
|
52
|
+
writeFileSync(path, JSON.stringify(body, null, 2) + "\n", { mode: 0o600 });
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../src/llm/credentials.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAoBhD,qEAAqE;AACrE,MAAM,UAAU,eAAe;IAC7B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;IACtE,OAAO,IAAI,CAAC,IAAI,EAAE,eAAe,EAAE,kBAAkB,CAAC,CAAC;AACzD,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,kBAAkB,CAAC,OAAe,eAAe,EAAE;IACjE,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACvC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAoB,CAAC;QAClD,MAAM,GAAG,GAAG,MAAM,CAAC,YAAY,CAAC;QAChC,OAAO,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;IACrE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa;IAC3B,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAC5C,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtD,KAAK,CAAC,iCAAiC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC9D,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,MAAM,QAAQ,GAAG,kBAAkB,EAAE,CAAC;IACtC,IAAI,QAAQ,EAAE,CAAC;QACb,KAAK,CAAC,kCAAkC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAClE,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAc,EAAE,OAAe,eAAe,EAAE;IAC/E,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;IACrD,CAAC;IACD,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC3D,MAAM,IAAI,GAAoB,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC;IACvD,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AAC7E,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { ChatCompletionMessageParam } from "openai/resources/index.js";
|
|
2
|
+
import type { ModelInfo, Usage } from "@agentclientprotocol/sdk";
|
|
3
|
+
/**
|
|
4
|
+
* A single message in the GLM conversation history.
|
|
5
|
+
*/
|
|
6
|
+
export type GlmMessage = ChatCompletionMessageParam;
|
|
7
|
+
/**
|
|
8
|
+
* A streamed chunk from the GLM API.
|
|
9
|
+
*/
|
|
10
|
+
export interface GlmStreamChunk {
|
|
11
|
+
/** Incremental assistant text */
|
|
12
|
+
text?: string;
|
|
13
|
+
/** Incremental reasoning/thinking text */
|
|
14
|
+
thinking?: string;
|
|
15
|
+
/** A complete tool call (assembled from streaming deltas) */
|
|
16
|
+
toolCall?: {
|
|
17
|
+
id: string;
|
|
18
|
+
name: string;
|
|
19
|
+
arguments: string;
|
|
20
|
+
};
|
|
21
|
+
/** Token usage reported when the stream finishes */
|
|
22
|
+
usage?: Usage;
|
|
23
|
+
/** Set when the stream is done */
|
|
24
|
+
done?: boolean;
|
|
25
|
+
/** Stop reason when done */
|
|
26
|
+
stopReason?: string;
|
|
27
|
+
}
|
|
28
|
+
/** Options applied to a single `streamChat` call. */
|
|
29
|
+
export interface StreamChatOptions {
|
|
30
|
+
/** GLM model identifier to use for this call. */
|
|
31
|
+
model: string;
|
|
32
|
+
}
|
|
33
|
+
/** Default GLM model when neither client nor user has chosen one. */
|
|
34
|
+
export declare const DEFAULT_MODEL = "glm-5.1";
|
|
35
|
+
/**
|
|
36
|
+
* Resolve the list of advertised models, allowing the user to override the
|
|
37
|
+
* built-in list via `ACP_GLM_AVAILABLE_MODELS`.
|
|
38
|
+
*/
|
|
39
|
+
export declare function getAvailableModels(): ModelInfo[];
|
|
40
|
+
/** Default model for new sessions: env override → built-in default. */
|
|
41
|
+
export declare function getDefaultModel(): string;
|
|
42
|
+
/**
|
|
43
|
+
* Wrapper around the OpenAI-compatible Zhipu AI (Z.AI) API.
|
|
44
|
+
*
|
|
45
|
+
* Uses the standard `openai` npm package pointed at `https://api.z.ai/api/paas/v4`
|
|
46
|
+
* so no Zhipu-specific SDK is required. The Z.AI service speaks the OpenAI
|
|
47
|
+
* Chat Completions wire format, plus a few GLM-specific extras (like the
|
|
48
|
+
* `thinking` field and `delta.reasoning_content` for reasoning tokens).
|
|
49
|
+
*/
|
|
50
|
+
export declare class GlmClient {
|
|
51
|
+
private client;
|
|
52
|
+
private maxTokens;
|
|
53
|
+
constructor();
|
|
54
|
+
/**
|
|
55
|
+
* Stream a chat completion from the GLM model, yielding chunks as they arrive.
|
|
56
|
+
*
|
|
57
|
+
* Reasoning/thinking tokens (from GLM "thinking" mode) are mapped to
|
|
58
|
+
* `thinking` chunks so the ACP agent can forward them as `agent_thought_chunk`
|
|
59
|
+
* blocks.
|
|
60
|
+
*/
|
|
61
|
+
streamChat(messages: GlmMessage[], signal?: AbortSignal, options?: StreamChatOptions): AsyncGenerator<GlmStreamChunk>;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=glm-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glm-client.d.ts","sourceRoot":"","sources":["../../src/llm/glm-client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,0BAA0B,EAAsB,MAAM,2BAA2B,CAAC;AAChG,OAAO,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AAKjE;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,0BAA0B,CAAC;AAEpD;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,iCAAiC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE;QACT,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,oDAAoD;IACpD,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,kCAAkC;IAClC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,4BAA4B;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qDAAqD;AACrD,MAAM,WAAW,iBAAiB;IAChC,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;CACf;AAKD,qEAAqE;AACrE,eAAO,MAAM,aAAa,YAAY,CAAC;AAiCvC;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,SAAS,EAAE,CAYhD;AAED,uEAAuE;AACvE,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED;;;;;;;GAOG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAS;;IAgB1B;;;;;;OAMG;IACI,UAAU,CACf,QAAQ,EAAE,UAAU,EAAE,EACtB,MAAM,CAAC,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,cAAc,CAAC,cAAc,CAAC;CA6IlC"}
|