@newsails/veil-cli 1.0.1
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/.veil/agents/analyst/AGENT.md +21 -0
- package/.veil/agents/analyst/agent.json +23 -0
- package/.veil/agents/assistant/AGENT.md +15 -0
- package/.veil/agents/assistant/agent.json +19 -0
- package/.veil/agents/coder/AGENT.md +18 -0
- package/.veil/agents/coder/agent.json +19 -0
- package/.veil/agents/hello/AGENT.md +5 -0
- package/.veil/agents/hello/agent.json +13 -0
- package/.veil/agents/writer/AGENT.md +12 -0
- package/.veil/agents/writer/agent.json +17 -0
- package/.veil/memory/MEMORY.md +343 -0
- package/.veil/memory/agents/analyst/MEMORY.md +55 -0
- package/.veil/memory/agents/hello/MEMORY.md +12 -0
- package/.veil/runtime.pid +1 -0
- package/.veil/settings.json +10 -0
- package/.veil-studio/studio.db +0 -0
- package/.veil-studio/studio.db-shm +0 -0
- package/.veil-studio/studio.db-wal +0 -0
- package/PLAN/01-vision.md +26 -0
- package/PLAN/02-tech-stack.md +94 -0
- package/PLAN/03-agents.md +232 -0
- package/PLAN/04-runtime.md +171 -0
- package/PLAN/05-tools.md +211 -0
- package/PLAN/06-communication.md +243 -0
- package/PLAN/07-storage.md +218 -0
- package/PLAN/08-api-cli.md +153 -0
- package/PLAN/09-permissions.md +108 -0
- package/PLAN/10-ably.md +105 -0
- package/PLAN/11-file-formats.md +442 -0
- package/PLAN/12-folder-structure.md +205 -0
- package/PLAN/13-operations.md +212 -0
- package/PLAN/README.md +23 -0
- package/README.md +128 -0
- package/REPORT.md +174 -0
- package/TODO.md +45 -0
- package/ai-tests/FRONTEND_PROMPT.md +220 -0
- package/ai-tests/Research & Planning.md +814 -0
- package/ai-tests/prompt-001-basic-api.md +230 -0
- package/ai-tests/prompt-002-basic-flows.md +230 -0
- package/ai-tests/prompt-003-agent-behaviors.md +220 -0
- package/api/middleware.js +60 -0
- package/api/routes/agents.js +193 -0
- package/api/routes/chat.js +93 -0
- package/api/routes/completions.js +122 -0
- package/api/routes/daemons.js +80 -0
- package/api/routes/memory.js +169 -0
- package/api/routes/models.js +40 -0
- package/api/routes/remote-methods.js +74 -0
- package/api/routes/sessions.js +208 -0
- package/api/routes/settings.js +108 -0
- package/api/routes/system.js +50 -0
- package/api/routes/tasks.js +270 -0
- package/api/server.js +120 -0
- package/cli/formatter.js +70 -0
- package/cli/index.js +443 -0
- package/cli/parser.js +113 -0
- package/config/config.json +10 -0
- package/config/models.json +6826 -0
- package/core/agent.js +329 -0
- package/core/cancel.js +38 -0
- package/core/compaction.js +176 -0
- package/core/events.js +13 -0
- package/core/loop.js +564 -0
- package/core/memory.js +51 -0
- package/core/prompt.js +185 -0
- package/core/queue.js +96 -0
- package/core/registry.js +291 -0
- package/core/remote-methods.js +124 -0
- package/core/router.js +386 -0
- package/core/running-sessions.js +18 -0
- package/docs/api/01-system.md +84 -0
- package/docs/api/02-agents.md +374 -0
- package/docs/api/03-chat.md +269 -0
- package/docs/api/04-tasks.md +470 -0
- package/docs/api/05-sessions.md +444 -0
- package/docs/api/06-daemons.md +142 -0
- package/docs/api/07-memory.md +186 -0
- package/docs/api/08-settings.md +133 -0
- package/docs/api/09-models.md +119 -0
- package/docs/api/09-websocket.md +350 -0
- package/docs/api/10-completions.md +134 -0
- package/docs/api/README.md +116 -0
- package/docs/guide/01-quickstart.md +220 -0
- package/docs/guide/02-folder-structure.md +185 -0
- package/docs/guide/03-configuration.md +252 -0
- package/docs/guide/04-agents.md +267 -0
- package/docs/guide/05-cli.md +290 -0
- package/docs/guide/06-tools.md +643 -0
- package/docs/guide/07-permissions.md +236 -0
- package/docs/guide/08-memory.md +139 -0
- package/docs/guide/09-multi-agent.md +271 -0
- package/docs/guide/10-daemons.md +226 -0
- package/docs/guide/README.md +53 -0
- package/docs/index.html +623 -0
- package/examples/README.md +151 -0
- package/examples/agents/assistant/AGENT.md +31 -0
- package/examples/agents/assistant/SOUL.md +9 -0
- package/examples/agents/assistant/agent.json +74 -0
- package/examples/agents/hello/AGENT.md +15 -0
- package/examples/agents/hello/agent.json +14 -0
- package/examples/agents/monitor/AGENT.md +51 -0
- package/examples/agents/monitor/agent.json +33 -0
- package/examples/agents/monitor/heartbeats/monitor.md +24 -0
- package/examples/agents/orchestrator/AGENT.md +70 -0
- package/examples/agents/orchestrator/agent.json +30 -0
- package/examples/agents/researcher/AGENT.md +52 -0
- package/examples/agents/researcher/agent.json +49 -0
- package/examples/agents/researcher/skills/web-research.md +28 -0
- package/examples/skills/code-review.md +72 -0
- package/examples/skills/summarise.md +59 -0
- package/examples/skills/web-research.md +42 -0
- package/examples/tools/word-count/index.js +27 -0
- package/examples/tools/word-count/tool.json +18 -0
- package/infrastructure/database.js +563 -0
- package/infrastructure/scheduler.js +122 -0
- package/llm/client.js +206 -0
- package/migrations/001-initial.sql +121 -0
- package/migrations/002-debuggability.sql +13 -0
- package/migrations/003-drop-orphaned-columns.sql +72 -0
- package/migrations/004-session-message-token-fields.sql +78 -0
- package/migrations/005-session-thinking.sql +5 -0
- package/package.json +30 -0
- package/schemas/agent.json +143 -0
- package/schemas/settings.json +111 -0
- package/scripts/fetch-models.js +93 -0
- package/session-debug-scenario.md +248 -0
- package/settings/fields.js +52 -0
- package/system-prompts/base-core.md +7 -0
- package/system-prompts/environment.md +13 -0
- package/system-prompts/reminders/anti-drift.md +6 -0
- package/system-prompts/reminders/stall-recovery.md +10 -0
- package/system-prompts/safety-rules.md +25 -0
- package/system-prompts/task-heuristics.md +27 -0
- package/test/client.js +71 -0
- package/test/integration/01-health.test.js +25 -0
- package/test/integration/02-agents.test.js +80 -0
- package/test/integration/03-chat-hello.test.js +48 -0
- package/test/integration/04-chat-multiturn.test.js +61 -0
- package/test/integration/05-chat-writer.test.js +48 -0
- package/test/integration/06-task-basic.test.js +68 -0
- package/test/integration/07-task-tools.test.js +74 -0
- package/test/integration/08-task-code-analysis.test.js +69 -0
- package/test/integration/09-memory-analyst.test.js +63 -0
- package/test/integration/10-task-advanced.test.js +85 -0
- package/test/integration/11-sessions-advanced.test.js +84 -0
- package/test/integration/12-assistant-chat-tools.test.js +75 -0
- package/test/integration/13-edge-cases.test.js +99 -0
- package/test/integration/14-cancel.test.js +62 -0
- package/test/integration/15-debug.test.js +106 -0
- package/test/integration/16-memory-api.test.js +83 -0
- package/test/integration/17-settings-api.test.js +41 -0
- package/test/integration/18-tool-search-activation.test.js +119 -0
- package/test/results/.gitkeep +0 -0
- package/test/runner.js +206 -0
- package/test/smoke.js +216 -0
- package/tools/agent_message.js +85 -0
- package/tools/agent_send.js +80 -0
- package/tools/agent_spawn.js +44 -0
- package/tools/bash.js +49 -0
- package/tools/edit_file.js +41 -0
- package/tools/glob.js +64 -0
- package/tools/grep.js +82 -0
- package/tools/list_dir.js +63 -0
- package/tools/log_write.js +31 -0
- package/tools/memory_read.js +38 -0
- package/tools/memory_search.js +65 -0
- package/tools/memory_write.js +42 -0
- package/tools/read_file.js +48 -0
- package/tools/sleep.js +22 -0
- package/tools/task_create.js +41 -0
- package/tools/task_respond.js +37 -0
- package/tools/task_spawn.js +64 -0
- package/tools/task_status.js +39 -0
- package/tools/task_subscribe.js +37 -0
- package/tools/todo_read.js +26 -0
- package/tools/todo_write.js +38 -0
- package/tools/tool_activate.js +24 -0
- package/tools/tool_search.js +24 -0
- package/tools/web_fetch.js +50 -0
- package/tools/web_search.js +52 -0
- package/tools/write_file.js +28 -0
- package/ui/api.js +190 -0
- package/ui/app.js +281 -0
- package/ui/index.html +382 -0
- package/ui/views/agents.js +377 -0
- package/ui/views/chat.js +610 -0
- package/ui/views/connection.js +96 -0
- package/ui/views/daemons.js +129 -0
- package/ui/views/feed.js +194 -0
- package/ui/views/memory.js +263 -0
- package/ui/views/models.js +146 -0
- package/ui/views/sessions.js +314 -0
- package/ui/views/settings.js +142 -0
- package/ui/views/tasks.js +415 -0
- package/utils/context.js +49 -0
- package/utils/id.js +16 -0
- package/utils/models.js +88 -0
- package/utils/paths.js +213 -0
- package/utils/settings.js +172 -0
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
# Agents
|
|
2
|
+
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## POST /agents
|
|
6
|
+
|
|
7
|
+
Create a new agent at the project or global level.
|
|
8
|
+
|
|
9
|
+
**Request body**
|
|
10
|
+
|
|
11
|
+
| Field | Type | Required | Description |
|
|
12
|
+
|-------|------|----------|-------------|
|
|
13
|
+
| `name` | string | ✓ | Agent identifier — letters, numbers, hyphens, underscores only |
|
|
14
|
+
| `level` | string | | `"project"` (default) or `"global"` |
|
|
15
|
+
| `config` | object | ✓ | Agent configuration (must satisfy the agent schema — `model` required) |
|
|
16
|
+
| `agentMd` | string | | Content for `AGENT.md` (system prompt / instructions) |
|
|
17
|
+
|
|
18
|
+
**Request example**
|
|
19
|
+
```json
|
|
20
|
+
{
|
|
21
|
+
"name": "researcher",
|
|
22
|
+
"level": "project",
|
|
23
|
+
"config": {
|
|
24
|
+
"model": "anthropic/claude-sonnet-4-5",
|
|
25
|
+
"description": "Deep research agent",
|
|
26
|
+
"modes": {
|
|
27
|
+
"task": { "enabled": true, "tools": ["bash", "read_file", "write_file"] }
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"agentMd": "You are a research assistant. Be thorough and cite sources."
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**Response** `201 Created`
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"agent": {
|
|
38
|
+
"name": "researcher",
|
|
39
|
+
"level": "project",
|
|
40
|
+
"folder": "/home/user/workspace/.veil/agents/researcher"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Error responses**
|
|
46
|
+
|
|
47
|
+
| Code | Condition |
|
|
48
|
+
|------|-----------|
|
|
49
|
+
| `409 AGENT_EXISTS` | An agent with that name already exists at any level (project, global, or bundled) |
|
|
50
|
+
| `400 INVALID_NAME` | Name contains invalid characters |
|
|
51
|
+
| `400 INVALID_CONFIG` | Config fails schema validation (error details included) |
|
|
52
|
+
| `400 VALIDATION_ERROR` | Missing required body fields or invalid `level` |
|
|
53
|
+
|
|
54
|
+
**Example**
|
|
55
|
+
```bash
|
|
56
|
+
curl -X POST http://localhost:5050/agents \
|
|
57
|
+
-H "Content-Type: application/json" \
|
|
58
|
+
-d '{"name":"researcher","config":{"model":"anthropic/claude-sonnet-4-5"}}'
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## GET /agents
|
|
64
|
+
|
|
65
|
+
Returns all agents discovered in the workspace's `.veil/agents/` directory (and the global cache if configured).
|
|
66
|
+
|
|
67
|
+
**Query parameters** — none
|
|
68
|
+
|
|
69
|
+
**Response**
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"agents": [
|
|
73
|
+
{
|
|
74
|
+
"name": "hello",
|
|
75
|
+
"description": "A simple conversational agent",
|
|
76
|
+
"model": "moonshotai/kimi-k2.5",
|
|
77
|
+
"modes": ["chat", "task"],
|
|
78
|
+
"source": "project"
|
|
79
|
+
}
|
|
80
|
+
]
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
| Field | Type | Description |
|
|
85
|
+
|-------|------|-------------|
|
|
86
|
+
| `name` | string | Agent identifier (folder name) |
|
|
87
|
+
| `description` | string | From `agent.json` |
|
|
88
|
+
| `model` | string | LLM model identifier |
|
|
89
|
+
| `modes` | string[] | Enabled modes: `"chat"`, `"task"`, `"daemon"`, `"subagent"` |
|
|
90
|
+
| `source` | string | `"project"` or `"global"` or `"bundled"` |
|
|
91
|
+
|
|
92
|
+
**Example**
|
|
93
|
+
```bash
|
|
94
|
+
curl http://localhost:5050/agents
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## GET /agents/:name
|
|
100
|
+
|
|
101
|
+
Returns the full configuration for a single agent.
|
|
102
|
+
|
|
103
|
+
**Path parameters**
|
|
104
|
+
|
|
105
|
+
| Param | Description |
|
|
106
|
+
|-------|-------------|
|
|
107
|
+
| `name` | Agent name (must match a folder in `.veil/agents/`) |
|
|
108
|
+
|
|
109
|
+
**Response**
|
|
110
|
+
```json
|
|
111
|
+
{
|
|
112
|
+
"agent": {
|
|
113
|
+
"name": "assistant",
|
|
114
|
+
"description": "General-purpose agent with file and shell access",
|
|
115
|
+
"model": "moonshotai/kimi-k2.5",
|
|
116
|
+
"temperature": 0.7,
|
|
117
|
+
"reasoning": "medium",
|
|
118
|
+
"modes": {
|
|
119
|
+
"chat": { "enabled": true },
|
|
120
|
+
"task": {
|
|
121
|
+
"enabled": true,
|
|
122
|
+
"maxIterations": 20,
|
|
123
|
+
"maxDurationSeconds": 120,
|
|
124
|
+
"tools": ["read_file", "list_dir", "bash", "write_file"],
|
|
125
|
+
"permissions": {
|
|
126
|
+
"deny": ["bash(rm *)", "bash(sudo *)", "write_file(/etc/*)"]
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
"skillDiscovery": false,
|
|
131
|
+
"memory": { "enabled": false },
|
|
132
|
+
"agentFolder": "/home/user/workspace/.veil/agents/assistant",
|
|
133
|
+
"source": "project",
|
|
134
|
+
"agentMd": "You are a general-purpose assistant with file and shell access."
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
| Field | Type | Description |
|
|
140
|
+
|-------|------|-------------|
|
|
141
|
+
| `name` | string | Agent identifier |
|
|
142
|
+
| `description` | string | Human-readable description |
|
|
143
|
+
| `model` | string | LLM model string |
|
|
144
|
+
| `temperature` | number | 0–2, sampling temperature |
|
|
145
|
+
| `reasoning` | string | Reasoning level: "minimal", "low", "medium", "high" |
|
|
146
|
+
| `modes` | object | Full mode configs (see [Agent Configuration](../guide/04-agents.md)) |
|
|
147
|
+
| `skillDiscovery` | boolean | Whether the agent auto-discovers skills |
|
|
148
|
+
| `memory` | object | `{ enabled, maxLines }` |
|
|
149
|
+
| `agentFolder` | string | Absolute path to the agent's folder |
|
|
150
|
+
| `source` | string | Where the agent was loaded from: `"project"`, `"global"`, or `"bundled"` |
|
|
151
|
+
| `agentMd` | string | Full content of the agent's `AGENT.md` system prompt file |
|
|
152
|
+
|
|
153
|
+
**Error responses**
|
|
154
|
+
|
|
155
|
+
| Code | Condition |
|
|
156
|
+
|------|-----------|
|
|
157
|
+
| `404 AGENT_NOT_FOUND` | No agent with that name exists |
|
|
158
|
+
|
|
159
|
+
**Example**
|
|
160
|
+
```bash
|
|
161
|
+
curl http://localhost:5050/agents/assistant
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## POST /agents/:name/reload
|
|
167
|
+
|
|
168
|
+
Hot-reload an agent's configuration from disk. Since `loadAgent` always reads from disk, this endpoint simply forces a fresh load and returns the current config. Useful for confirming that config file edits have taken effect, or for programmatically verifying the agent is valid after an update.
|
|
169
|
+
|
|
170
|
+
**Path parameters**
|
|
171
|
+
|
|
172
|
+
| Param | Description |
|
|
173
|
+
|-------|-------------|
|
|
174
|
+
| `name` | Agent name |
|
|
175
|
+
|
|
176
|
+
**Response**
|
|
177
|
+
```json
|
|
178
|
+
{
|
|
179
|
+
"reloaded": true,
|
|
180
|
+
"agent": {
|
|
181
|
+
"name": "assistant",
|
|
182
|
+
"model": "anthropic/claude-sonnet-4-5",
|
|
183
|
+
"description": "General-purpose assistant",
|
|
184
|
+
"modes": { "chat": { "enabled": true } }
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**Error responses**
|
|
190
|
+
|
|
191
|
+
| Code | Condition |
|
|
192
|
+
|------|-----------|
|
|
193
|
+
| `404 AGENT_NOT_FOUND` | No agent with that name exists |
|
|
194
|
+
|
|
195
|
+
**Example**
|
|
196
|
+
```bash
|
|
197
|
+
curl -X POST http://localhost:5050/agents/assistant/reload
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## PUT /agents/:name
|
|
203
|
+
|
|
204
|
+
Update an existing agent's configuration and/or `AGENT.md`. Only project-level and global agents can be updated — bundled agents are read-only.
|
|
205
|
+
|
|
206
|
+
At least one of `config` or `agentMd` must be provided. Config fields are **shallow-merged** with the current `agent.json` (top-level keys are replaced).
|
|
207
|
+
|
|
208
|
+
**Path parameters**
|
|
209
|
+
|
|
210
|
+
| Param | Description |
|
|
211
|
+
|-------|-------------|
|
|
212
|
+
| `name` | Agent name |
|
|
213
|
+
|
|
214
|
+
**Request body**
|
|
215
|
+
|
|
216
|
+
| Field | Type | Required | Description |
|
|
217
|
+
|-------|------|----------|-------------|
|
|
218
|
+
| `config` | object | | Partial or full agent config — merged over current `agent.json` |
|
|
219
|
+
| `agentMd` | string | | New content for `AGENT.md` — fully replaces existing content |
|
|
220
|
+
|
|
221
|
+
**Request example** — update model and add a tool
|
|
222
|
+
```json
|
|
223
|
+
{
|
|
224
|
+
"config": {
|
|
225
|
+
"model": "anthropic/claude-opus-4-5",
|
|
226
|
+
"modes": {
|
|
227
|
+
"chat": { "enabled": true, "tools": ["read_file", "bash"] }
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
**Response**
|
|
234
|
+
```json
|
|
235
|
+
{
|
|
236
|
+
"agent": {
|
|
237
|
+
"name": "researcher",
|
|
238
|
+
"level": "project",
|
|
239
|
+
"folder": "/home/user/workspace/.veil/agents/researcher"
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
**Error responses**
|
|
245
|
+
|
|
246
|
+
| Code | Condition |
|
|
247
|
+
|------|-----------|
|
|
248
|
+
| `404 AGENT_NOT_FOUND` | No agent with that name exists |
|
|
249
|
+
| `403 AGENT_READ_ONLY` | Agent is bundled and cannot be modified |
|
|
250
|
+
| `400 INVALID_CONFIG` | Merged config fails schema validation |
|
|
251
|
+
| `400 VALIDATION_ERROR` | Neither `config` nor `agentMd` provided |
|
|
252
|
+
|
|
253
|
+
**Example**
|
|
254
|
+
```bash
|
|
255
|
+
curl -X PUT http://localhost:5050/agents/researcher \
|
|
256
|
+
-H "Content-Type: application/json" \
|
|
257
|
+
-d '{"config":{"model":"anthropic/claude-opus-4-5"}}'
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## DELETE /agents/:name
|
|
263
|
+
|
|
264
|
+
Delete an agent folder and all its contents (config, AGENT.md, skills, etc.). Only project-level and global agents can be deleted — bundled agents are read-only.
|
|
265
|
+
|
|
266
|
+
> **Warning:** This is irreversible. The agent folder is permanently removed from disk.
|
|
267
|
+
|
|
268
|
+
**Path parameters**
|
|
269
|
+
|
|
270
|
+
| Param | Description |
|
|
271
|
+
|-------|-------------|
|
|
272
|
+
| `name` | Agent name |
|
|
273
|
+
|
|
274
|
+
**Response**
|
|
275
|
+
```json
|
|
276
|
+
{
|
|
277
|
+
"deleted": true,
|
|
278
|
+
"agent": {
|
|
279
|
+
"name": "researcher",
|
|
280
|
+
"level": "project",
|
|
281
|
+
"folder": "/home/user/workspace/.veil/agents/researcher"
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
**Error responses**
|
|
287
|
+
|
|
288
|
+
| Code | Condition |
|
|
289
|
+
|------|-----------|
|
|
290
|
+
| `404 AGENT_NOT_FOUND` | No agent with that name exists |
|
|
291
|
+
| `403 AGENT_READ_ONLY` | Agent is bundled and cannot be deleted |
|
|
292
|
+
|
|
293
|
+
**Example**
|
|
294
|
+
```bash
|
|
295
|
+
curl -X DELETE http://localhost:5050/agents/researcher
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
## GET /agents/:name/sessions
|
|
301
|
+
|
|
302
|
+
List sessions for a specific agent. This is a convenience alias for `GET /sessions?agentName=:name`.
|
|
303
|
+
|
|
304
|
+
**Query parameters**
|
|
305
|
+
|
|
306
|
+
| Param | Type | Description |
|
|
307
|
+
|-------|------|-------------|
|
|
308
|
+
| `status` | string | Filter by `active` or `closed` |
|
|
309
|
+
| `limit` | integer | Max results (default: 20) |
|
|
310
|
+
| `cursor` | string | Pagination cursor |
|
|
311
|
+
|
|
312
|
+
**Response**
|
|
313
|
+
```json
|
|
314
|
+
{
|
|
315
|
+
"agentName": "assistant",
|
|
316
|
+
"sessions": [
|
|
317
|
+
{ "id": "sess_...", "mode": "chat", "status": "active", ... }
|
|
318
|
+
]
|
|
319
|
+
}
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## GET /agents/:name/tasks
|
|
325
|
+
|
|
326
|
+
List tasks for a specific agent. This is a convenience alias for `GET /tasks?agentName=:name`.
|
|
327
|
+
|
|
328
|
+
**Query parameters**
|
|
329
|
+
|
|
330
|
+
| Param | Type | Description |
|
|
331
|
+
|-------|------|-------------|
|
|
332
|
+
| `status` | string | Filter by status |
|
|
333
|
+
| `priority` | string | Filter by priority |
|
|
334
|
+
| `limit` | integer | Max results (default: 20) |
|
|
335
|
+
| `cursor` | string | Pagination cursor |
|
|
336
|
+
|
|
337
|
+
**Response**
|
|
338
|
+
```json
|
|
339
|
+
{
|
|
340
|
+
"agentName": "assistant",
|
|
341
|
+
"tasks": [
|
|
342
|
+
{ "id": "task_...", "status": "finished", ... }
|
|
343
|
+
]
|
|
344
|
+
}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
349
|
+
## GET /agents/:name/skills
|
|
350
|
+
|
|
351
|
+
List skills configured for an agent and their load status.
|
|
352
|
+
|
|
353
|
+
**Response**
|
|
354
|
+
```json
|
|
355
|
+
{
|
|
356
|
+
"agentName": "assistant",
|
|
357
|
+
"skills": [
|
|
358
|
+
{ "name": "web-search", "loaded": true, "source": "project", "path": "/.../.veil/skills/web-search.md" },
|
|
359
|
+
{ "name": "missing-skill", "loaded": false, "error": "File not found" }
|
|
360
|
+
],
|
|
361
|
+
"customTools": [
|
|
362
|
+
{ "name": "my_tool", "source": "project" }
|
|
363
|
+
]
|
|
364
|
+
}
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
| Field | Type | Description |
|
|
368
|
+
|-------|------|-------------|
|
|
369
|
+
| `skills[].name` | string | Skill name from agent config |
|
|
370
|
+
| `skills[].loaded` | boolean | Whether the skill file was found |
|
|
371
|
+
| `skills[].source` | string | `"agent"` or `"project"` |
|
|
372
|
+
| `skills[].path` | string | Absolute path (if loaded) |
|
|
373
|
+
| `skills[].error` | string | Error message (if not loaded) |
|
|
374
|
+
| `customTools` | array | Custom tools discovered for this agent |
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
# Chat
|
|
2
|
+
|
|
3
|
+
The chat endpoint enables multi-turn conversations with an agent. Each call is synchronous — it blocks until the agent finishes its response (including any tool calls).
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## POST /agents/:name/chat
|
|
8
|
+
|
|
9
|
+
Send a message to an agent and receive a reply.
|
|
10
|
+
|
|
11
|
+
**Path parameters**
|
|
12
|
+
|
|
13
|
+
| Param | Description |
|
|
14
|
+
|-------|-------------|
|
|
15
|
+
| `name` | Agent name |
|
|
16
|
+
|
|
17
|
+
**Request body**
|
|
18
|
+
|
|
19
|
+
```json
|
|
20
|
+
{
|
|
21
|
+
"message": "What files are in the current directory?",
|
|
22
|
+
"sessionId": "sess_abc123"
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
| Field | Type | Required | Description |
|
|
27
|
+
|-------|------|----------|-------------|
|
|
28
|
+
| `message` | string | ✓ | User message content |
|
|
29
|
+
| `sessionId` | string | | Existing session ID to continue a conversation. Omit to start a new session. |
|
|
30
|
+
| `sse` | boolean | | `true` to enable SSE streaming — the response is `text/event-stream` instead of JSON. |
|
|
31
|
+
|
|
32
|
+
**Response**
|
|
33
|
+
|
|
34
|
+
```json
|
|
35
|
+
{
|
|
36
|
+
"sessionId": "sess_4f3a1b9c2d8e7f01",
|
|
37
|
+
"message": {
|
|
38
|
+
"role": "assistant",
|
|
39
|
+
"content": "Here are the files in the current directory:\n- README.md\n- package.json\n..."
|
|
40
|
+
},
|
|
41
|
+
"tokenUsage": {
|
|
42
|
+
"input": 1240,
|
|
43
|
+
"output": 183,
|
|
44
|
+
"cache": 0,
|
|
45
|
+
"cost": 0.0021
|
|
46
|
+
},
|
|
47
|
+
"toolCalls": [
|
|
48
|
+
{ "name": "list_dir", "durationMs": 12, "success": true },
|
|
49
|
+
{ "name": "read_file", "durationMs": 8, "success": true }
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
| Field | Type | Description |
|
|
55
|
+
|-------|------|-------------|
|
|
56
|
+
| `sessionId` | string | Session ID (pass this back for multi-turn) |
|
|
57
|
+
| `message.role` | string | Always `"assistant"` |
|
|
58
|
+
| `message.content` | string | Agent reply text (last iteration's response) |
|
|
59
|
+
| `tokenUsage.input` | integer | Total input tokens for this turn |
|
|
60
|
+
| `tokenUsage.output` | integer | Total output tokens for this turn |
|
|
61
|
+
| `tokenUsage.cache` | integer | Cached tokens (if provider supports it) |
|
|
62
|
+
| `tokenUsage.cost` | number | Estimated cost in USD |
|
|
63
|
+
| `toolCalls` | array | Summary of tools called: `{ name, durationMs, success }` |
|
|
64
|
+
|
|
65
|
+
**Error responses**
|
|
66
|
+
|
|
67
|
+
| Code | Condition |
|
|
68
|
+
|------|-----------|
|
|
69
|
+
| `400 VALIDATION_ERROR` | `message` is missing or not a string |
|
|
70
|
+
| `400 MODE_NOT_SUPPORTED` | Agent does not have `chat.enabled: true` |
|
|
71
|
+
| `400 SESSION_CLOSED` | The provided `sessionId` belongs to a closed session |
|
|
72
|
+
| `404 AGENT_NOT_FOUND` | No agent with that name |
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## SSE Streaming Mode
|
|
77
|
+
|
|
78
|
+
Set `"sse": true` in the request body to receive a real-time `text/event-stream` response. The connection stays open across all LLM iterations (including tool call rounds) and closes only when the full turn is complete.
|
|
79
|
+
|
|
80
|
+
**Design principle:** Events are split into two categories — _inference_ events carry transient streaming data not needed for state; _message_ events carry the exact schema returned by `GET /sessions/:id/messages` so clients can update their local state directly without any conversion.
|
|
81
|
+
|
|
82
|
+
**Event types**
|
|
83
|
+
|
|
84
|
+
| Event | Category | Description |
|
|
85
|
+
|-------|----------|-------------|
|
|
86
|
+
| `inference.chunk` | Inference | One streaming token fragment from the current LLM call |
|
|
87
|
+
| `inference.tool` | Inference | Tool name detected in stream before arguments are complete — lets UI show a loading indicator early |
|
|
88
|
+
| `message` | State | An assistant or tool message, identical to the session messages API schema |
|
|
89
|
+
| `done` | State | Turn complete — includes the updated session record and turn-level stats |
|
|
90
|
+
| `error` | — | Emitted instead of `done` if the run fails |
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
**`inference.chunk`**
|
|
95
|
+
```json
|
|
96
|
+
{ "content": "Here are the" }
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**`inference.tool`** — fires once per tool call as soon as the tool name appears in the stream (before arguments are complete)
|
|
100
|
+
```json
|
|
101
|
+
{ "name": "sleep" }
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
**`message`** — session-API-compatible message object, augmented with inference metadata for assistant turns
|
|
107
|
+
|
|
108
|
+
*Assistant turn (text only):*
|
|
109
|
+
```json
|
|
110
|
+
{
|
|
111
|
+
"id": 5,
|
|
112
|
+
"session_id": "sess_4f3a1b9c2d8e7f01",
|
|
113
|
+
"role": "assistant",
|
|
114
|
+
"content": "Here are the files:\n- README.md",
|
|
115
|
+
"tool_calls": null,
|
|
116
|
+
"tool_call_id": null,
|
|
117
|
+
"created_at": "2025-03-02T10:00:04.000Z",
|
|
118
|
+
"finishReason": "stop",
|
|
119
|
+
"iteration": 1,
|
|
120
|
+
"tokenUsage": { "input": 1240, "output": 38, "cache": 0, "cost": 0.0003 }
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
*Assistant turn (with tool calls):*
|
|
125
|
+
```json
|
|
126
|
+
{
|
|
127
|
+
"id": 3,
|
|
128
|
+
"session_id": "sess_4f3a1b9c2d8e7f01",
|
|
129
|
+
"role": "assistant",
|
|
130
|
+
"content": null,
|
|
131
|
+
"tool_calls": [{ "id": "call_abc", "type": "function", "function": { "name": "list_dir", "arguments": "{\"dir\": \".\"}" } }],
|
|
132
|
+
"tool_call_id": null,
|
|
133
|
+
"created_at": "2025-03-02T10:00:02.000Z",
|
|
134
|
+
"finishReason": "tool_calls",
|
|
135
|
+
"iteration": 1,
|
|
136
|
+
"tokenUsage": { "input": 980, "output": 22, "cache": 0, "cost": 0.0002 }
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
*Tool result:*
|
|
141
|
+
```json
|
|
142
|
+
{
|
|
143
|
+
"id": 4,
|
|
144
|
+
"session_id": "sess_4f3a1b9c2d8e7f01",
|
|
145
|
+
"role": "tool",
|
|
146
|
+
"content": "README.md (1.2KB)\npackage.json (544B)",
|
|
147
|
+
"tool_calls": null,
|
|
148
|
+
"tool_call_id": "call_abc",
|
|
149
|
+
"created_at": "2025-03-02T10:00:03.000Z"
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
`finishReason` on assistant turns: `"stop"` = no tools followed | `"tool_calls"` = continued with tool use | `"length"` = token limit hit
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
**`done`**
|
|
158
|
+
```json
|
|
159
|
+
{
|
|
160
|
+
"session": {
|
|
161
|
+
"id": "sess_4f3a1b9c2d8e7f01",
|
|
162
|
+
"agent_name": "assistant",
|
|
163
|
+
"mode": "chat",
|
|
164
|
+
"status": "active",
|
|
165
|
+
"model": "claude-3-5-sonnet",
|
|
166
|
+
"total_input_tokens": 6842,
|
|
167
|
+
"total_output_tokens": 124,
|
|
168
|
+
"cost": 0.0089,
|
|
169
|
+
"message_count": 5,
|
|
170
|
+
"created_at": "2025-03-02T10:00:00.000Z",
|
|
171
|
+
"updated_at": "2025-03-02T10:00:05.000Z"
|
|
172
|
+
},
|
|
173
|
+
"agentName": "assistant",
|
|
174
|
+
"model": "claude-3-5-sonnet",
|
|
175
|
+
"iterations": 3,
|
|
176
|
+
"durationMs": 4210,
|
|
177
|
+
"tokenUsage": { "input": 6842, "output": 124, "cache": 0, "cost": 0.0089 },
|
|
178
|
+
"toolCalls": [
|
|
179
|
+
{ "name": "sleep", "durationMs": 1003, "success": true }
|
|
180
|
+
]
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**`error`**
|
|
185
|
+
```json
|
|
186
|
+
{ "error": "LLM API error 429: rate limit", "code": "INTERNAL_ERROR" }
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
**Behavior notes**
|
|
192
|
+
- `inference.chunk` fires for every LLM iteration across the full turn — all chunks are streamed in order.
|
|
193
|
+
- `inference.tool` fires during streaming as soon as the tool name is known, before arguments finish — use this for tool loading indicators.
|
|
194
|
+
- Each `message` event (role `assistant` or `tool`) matches what `GET /sessions/:id/messages` returns, so clients can append them directly to local state without schema conversion.
|
|
195
|
+
- `done.session` is a snapshot of the session record after the turn — clients can use it to update session state without a separate `GET /sessions/:id` call.
|
|
196
|
+
- The response `Content-Type` is `text/event-stream`; use `EventSource` or an SSE client library.
|
|
197
|
+
|
|
198
|
+
**JavaScript example**
|
|
199
|
+
```js
|
|
200
|
+
const response = await fetch('http://localhost:5050/agents/assistant/chat', {
|
|
201
|
+
method: 'POST',
|
|
202
|
+
headers: { 'Content-Type': 'application/json' },
|
|
203
|
+
body: JSON.stringify({ message: 'List files', sse: true }),
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
const messages = [];
|
|
207
|
+
const reader = response.body.getReader();
|
|
208
|
+
const decoder = new TextDecoder();
|
|
209
|
+
let buffer = '';
|
|
210
|
+
let pendingEvent = null;
|
|
211
|
+
|
|
212
|
+
while (true) {
|
|
213
|
+
const { done, value } = await reader.read();
|
|
214
|
+
if (done) break;
|
|
215
|
+
buffer += decoder.decode(value, { stream: true });
|
|
216
|
+
const lines = buffer.split('\n');
|
|
217
|
+
buffer = lines.pop();
|
|
218
|
+
for (const line of lines) {
|
|
219
|
+
if (line.startsWith('event: ')) { pendingEvent = line.slice(7).trim(); continue; }
|
|
220
|
+
if (line.startsWith('data: ') && pendingEvent) {
|
|
221
|
+
const data = JSON.parse(line.slice(6));
|
|
222
|
+
if (pendingEvent === 'inference.chunk') process.stdout.write(data.content);
|
|
223
|
+
if (pendingEvent === 'inference.tool') console.log(`[tool] ${data.name}…`);
|
|
224
|
+
if (pendingEvent === 'message') messages.push(data); // directly usable
|
|
225
|
+
if (pendingEvent === 'done') console.log('session:', data.session);
|
|
226
|
+
pendingEvent = null;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**curl example**
|
|
233
|
+
```bash
|
|
234
|
+
curl -X POST http://localhost:5050/agents/assistant/chat \
|
|
235
|
+
-H "Content-Type: application/json" \
|
|
236
|
+
-d '{"message": "List files", "sse": true}' \
|
|
237
|
+
--no-buffer
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## Multi-turn Conversation Example
|
|
243
|
+
|
|
244
|
+
Start a new conversation, then continue it:
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
# Turn 1 — new session
|
|
248
|
+
curl -X POST http://localhost:5050/agents/assistant/chat \
|
|
249
|
+
-H "Content-Type: application/json" \
|
|
250
|
+
-d '{"message": "My name is Alice."}'
|
|
251
|
+
|
|
252
|
+
# Response includes sessionId, e.g. "sess_4f3a1b9c2d8e7f01"
|
|
253
|
+
|
|
254
|
+
# Turn 2 — continue the same session
|
|
255
|
+
curl -X POST http://localhost:5050/agents/assistant/chat \
|
|
256
|
+
-H "Content-Type: application/json" \
|
|
257
|
+
-d '{"message": "What is my name?", "sessionId": "sess_4f3a1b9c2d8e7f01"}'
|
|
258
|
+
|
|
259
|
+
# Agent remembers: "Your name is Alice."
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## Notes
|
|
265
|
+
|
|
266
|
+
- The agent's full message history (including tool call messages) is persisted in SQLite and replayed on each turn.
|
|
267
|
+
- If the agent uses tools (e.g. `read_file`, `bash`), those calls happen **before** the reply is returned — the response always contains the final text response.
|
|
268
|
+
- To inspect which tools were called during a chat turn, fetch the session messages after the call: `GET /sessions/:id/messages`.
|
|
269
|
+
- Sessions are scoped to a workspace (`instanceFolder`). A `sessionId` from one server instance will not be found by another.
|