@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,442 @@
|
|
|
1
|
+
# 11 — File Formats
|
|
2
|
+
|
|
3
|
+
## agent.json
|
|
4
|
+
|
|
5
|
+
Agent configuration. Defines modes, model, tools, permissions.
|
|
6
|
+
|
|
7
|
+
> **Critical field types — common mistakes:**
|
|
8
|
+
> - `model` must be a **string** (e.g. `"moonshotai/kimi-k2.5"`), NOT an object like `{ "role": "main" }`
|
|
9
|
+
> - Each `modes.*` entry must be an **object** with at minimum `{ "enabled": boolean }`, NOT a bare boolean like `true`
|
|
10
|
+
> - Both of these were real bugs found during testing that caused every agent to fail validation
|
|
11
|
+
|
|
12
|
+
```json
|
|
13
|
+
{
|
|
14
|
+
"name": "researcher",
|
|
15
|
+
"description": "Deep research agent that investigates topics",
|
|
16
|
+
"model": "anthropic/claude-3.5-sonnet",
|
|
17
|
+
"temperature": 0.7,
|
|
18
|
+
"reasoning": "medium",
|
|
19
|
+
"memory": { "enabled": true, "maxLines": 200 },
|
|
20
|
+
"skillDiscovery": true,
|
|
21
|
+
"modes": {
|
|
22
|
+
"chat": {
|
|
23
|
+
"enabled": true,
|
|
24
|
+
"tools": [],
|
|
25
|
+
"disallowedTools": [],
|
|
26
|
+
"skills": [],
|
|
27
|
+
"autoLoadSkills": [],
|
|
28
|
+
"mcpServers": [],
|
|
29
|
+
"permissions": {}
|
|
30
|
+
},
|
|
31
|
+
"task": {
|
|
32
|
+
"enabled": true,
|
|
33
|
+
"tools": [],
|
|
34
|
+
"disallowedTools": ["bash"],
|
|
35
|
+
"skills": [],
|
|
36
|
+
"autoLoadSkills": [],
|
|
37
|
+
"mcpServers": [],
|
|
38
|
+
"maxIterations": 50,
|
|
39
|
+
"maxDurationSeconds": 300,
|
|
40
|
+
"permissions": {}
|
|
41
|
+
},
|
|
42
|
+
"subagent": {
|
|
43
|
+
"enabled": true,
|
|
44
|
+
"tools": ["web_search", "read_file", "grep"],
|
|
45
|
+
"disallowedTools": [],
|
|
46
|
+
"skills": ["summarize"],
|
|
47
|
+
"autoLoadSkills": [],
|
|
48
|
+
"mcpServers": [],
|
|
49
|
+
"allowedAgents": [],
|
|
50
|
+
"disallowedAgents": [],
|
|
51
|
+
"maxIterations": 20,
|
|
52
|
+
"maxDurationSeconds": 120,
|
|
53
|
+
"permissions": {}
|
|
54
|
+
},
|
|
55
|
+
"daemon": {
|
|
56
|
+
"enabled": false,
|
|
57
|
+
"cron": "*/5 * * * *",
|
|
58
|
+
"triggers": [],
|
|
59
|
+
"conflictPolicy": "skip",
|
|
60
|
+
"alertRouting": ["log", "webhook:https://slack.com/webhook/xxx"],
|
|
61
|
+
"heartbeatFile": "",
|
|
62
|
+
"tools": [],
|
|
63
|
+
"disallowedTools": [],
|
|
64
|
+
"skills": [],
|
|
65
|
+
"autoLoadSkills": [],
|
|
66
|
+
"mcpServers": [],
|
|
67
|
+
"permissions": {}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
| Field | Type | Description |
|
|
74
|
+
|-------|------|-------------|
|
|
75
|
+
| `name` | string | Agent identifier (overrides folder name) |
|
|
76
|
+
| `description` | string | Human-readable description |
|
|
77
|
+
| `model` | string | Default model for all modes |
|
|
78
|
+
| `temperature` | number | 0.0–1.0 |
|
|
79
|
+
| `reasoning` | string | Enable reasoning mode for this agent (default: "medium"). Options: "low", "medium", "high" |
|
|
80
|
+
| `memory.enabled` | boolean | Enable persistent memory for this agent (default: true) |
|
|
81
|
+
| `memory.maxLines` | number | MEMORY.md line cap before auto-export (default: 200 from settings.json) |
|
|
82
|
+
| `skillDiscovery` | boolean | List skill names in system prompt (default: true). When false, agent is skill-blind. |
|
|
83
|
+
| `modes.chat.enabled` | boolean | Whether chat mode is supported |
|
|
84
|
+
| `modes.task.enabled` | boolean | Whether task mode is supported |
|
|
85
|
+
| `modes.task.maxIterations` | number | Override global limit |
|
|
86
|
+
| `modes.task.maxDurationSeconds` | number | Override global limit |
|
|
87
|
+
| `modes.subagent.enabled` | boolean | Whether sub-agent mode is supported |
|
|
88
|
+
| `modes.subagent.maxIterations` | number | Limit when called as sub-agent |
|
|
89
|
+
| `modes.subagent.maxDurationSeconds` | number | Limit when called as sub-agent |
|
|
90
|
+
| `modes.subagent.allowedAgents` | string[] | Agents this sub-agent can spawn/message (empty = all) |
|
|
91
|
+
| `modes.subagent.disallowedAgents` | string[] | Agents this sub-agent cannot spawn/message |
|
|
92
|
+
| `modes.daemon.enabled` | boolean | Whether daemon mode is supported |
|
|
93
|
+
| `modes.daemon.cron` | string | Cron expression for scheduling |
|
|
94
|
+
| `modes.daemon.triggers` | string[] | System-wide event triggers: `task.completed`, `task.failed`, `agent.error`. See **Daemon Trigger Payload** below. |
|
|
95
|
+
| `modes.daemon.conflictPolicy` | string | skip / queue / restart |
|
|
96
|
+
| `modes.daemon.alertRouting` | string \| string[] | Array of routing targets: `"log"`, `"webhook:<url>"`, `"agent:<name>"`, `"ably:<channel>"`. Single string also accepted. |
|
|
97
|
+
| `modes.daemon.heartbeatFile` | string | Custom path to heartbeat file (default: `.veil/heartbeats/<name>.md`) |
|
|
98
|
+
| `modes.*.tools` | string[] | Tool whitelist (empty = all) |
|
|
99
|
+
| `modes.*.disallowedTools` | string[] | Tool blacklist (mutually exclusive with `tools`) |
|
|
100
|
+
| `modes.*.skills` | string[] | Skill whitelist (empty = all) |
|
|
101
|
+
| `modes.*.autoLoadSkills` | string[] | Skills always loaded in full |
|
|
102
|
+
| `modes.*.mcpServers` | string[] | MCP server whitelist (empty = all configured) |
|
|
103
|
+
| `modes.*.permissions` | object | `{ allow: [], deny: [] }` per-mode overrides |
|
|
104
|
+
|
|
105
|
+
**Minimal valid example** (guaranteed to pass schema validation):
|
|
106
|
+
```json
|
|
107
|
+
{
|
|
108
|
+
"name": "hello",
|
|
109
|
+
"description": "A minimal reference agent",
|
|
110
|
+
"model": "anthropic/claude-3-haiku",
|
|
111
|
+
"temperature": 0.5,
|
|
112
|
+
"reasoning": null,
|
|
113
|
+
"modes": {
|
|
114
|
+
"chat": { "enabled": true },
|
|
115
|
+
"task": { "enabled": false },
|
|
116
|
+
"subagent": { "enabled": false },
|
|
117
|
+
"daemon": { "enabled": false }
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
This example is the basis for `examples/agents/hello/agent.json` in the source tree — it is validated in CI and used as the reference for documentation.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## AGENT.md
|
|
127
|
+
|
|
128
|
+
Plain markdown. Agent instructions and system prompt content. No configuration — that's in agent.json.
|
|
129
|
+
|
|
130
|
+
```markdown
|
|
131
|
+
You are a research agent. Your job is to investigate topics thoroughly
|
|
132
|
+
and produce detailed, well-sourced reports.
|
|
133
|
+
|
|
134
|
+
## Rules
|
|
135
|
+
- Always cite your sources
|
|
136
|
+
- Prefer primary sources over summaries
|
|
137
|
+
- If you can't find reliable information, say so
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## SOUL.md
|
|
143
|
+
|
|
144
|
+
Optional. Plain markdown. Persona and behavioral identity. Loaded after AGENT.md.
|
|
145
|
+
|
|
146
|
+
```markdown
|
|
147
|
+
You speak in a concise, professional tone.
|
|
148
|
+
You never apologize unnecessarily.
|
|
149
|
+
You prefer bullet points over long paragraphs.
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Memory Files
|
|
155
|
+
|
|
156
|
+
Persistent memory lives in `.veil/memory/`, NOT in agent folders (agent folders are static/read-only).
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
.veil/memory/
|
|
160
|
+
├── MEMORY.md ← global memory (always loaded, ~200-line cap)
|
|
161
|
+
├── <topic>.md ← auto-exported global memory files
|
|
162
|
+
└── agents/
|
|
163
|
+
└── <agentName>/
|
|
164
|
+
├── MEMORY.md ← agent-specific memory (always loaded, ~200-line cap)
|
|
165
|
+
└── <topic>.md ← auto-exported agent memory files
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
**Main MEMORY.md** is always loaded into the system prompt (Layer 4). Capped at ~200 lines (configurable).
|
|
169
|
+
**Auto-export:** When MEMORY.md exceeds the line cap, the compact model moves older entries into a separate `<topic>.md` file.
|
|
170
|
+
**Memory tools:** `memory_write` (append), `memory_read` (read), `memory_search` (search across all memory files).
|
|
171
|
+
**System prompt includes:** Main MEMORY.md content + list of available memory files with descriptions.
|
|
172
|
+
**Pre-compaction:** Before context compaction, runtime asks model to extract key learnings → writes to MEMORY.md (model can return `NO_MEMORY` to skip).
|
|
173
|
+
|
|
174
|
+
```markdown
|
|
175
|
+
# Memory
|
|
176
|
+
|
|
177
|
+
## User Preferences
|
|
178
|
+
- Prefers reports in markdown format
|
|
179
|
+
- Works in EST timezone
|
|
180
|
+
|
|
181
|
+
## Known Facts
|
|
182
|
+
- Main project is called ProjectX
|
|
183
|
+
- Production server is at 192.168.1.100
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Heartbeat Files
|
|
189
|
+
|
|
190
|
+
Daemon checklists live in `.veil/heartbeats/`, NOT in agent folders.
|
|
191
|
+
|
|
192
|
+
```
|
|
193
|
+
.veil/heartbeats/
|
|
194
|
+
└── <agentName>.md ← per-agent heartbeat checklist
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Plain markdown. Read on each daemon tick. Agent.json `heartbeatFile` field can override the default path.
|
|
198
|
+
|
|
199
|
+
```markdown
|
|
200
|
+
# Heartbeat Checklist
|
|
201
|
+
|
|
202
|
+
- Check if any tasks have been in "processing" state for more than 1 hour
|
|
203
|
+
- Monitor ./logs/ folder for new ERROR lines since last check
|
|
204
|
+
- If it's Monday morning, generate a weekly summary
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
**Output contract:** Agent MUST output `HEARTBEAT_OK` or `HEARTBEAT_ALERT: <message>`.
|
|
208
|
+
|
|
209
|
+
### Daemon Trigger Payload
|
|
210
|
+
|
|
211
|
+
When a daemon is triggered by a system event (not cron), it receives context via a system message:
|
|
212
|
+
|
|
213
|
+
```
|
|
214
|
+
[System] Daemon triggered by event: task.completed
|
|
215
|
+
{
|
|
216
|
+
"event": "task.completed",
|
|
217
|
+
"taskId": "task_abc123",
|
|
218
|
+
"agentName": "researcher",
|
|
219
|
+
"status": "finished",
|
|
220
|
+
"output": { ... },
|
|
221
|
+
"timestamp": "2026-03-01T08:00:00Z"
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
The daemon can then decide what action to take based on the event payload.
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## SKILL.md
|
|
230
|
+
|
|
231
|
+
Markdown with YAML frontmatter. Prompt template invokable by agents.
|
|
232
|
+
|
|
233
|
+
```markdown
|
|
234
|
+
---
|
|
235
|
+
name: review-code
|
|
236
|
+
description: Review code for security and performance issues
|
|
237
|
+
argument-hint: [file-path]
|
|
238
|
+
allowed-tools: bash, read_file, edit_file
|
|
239
|
+
context: fork
|
|
240
|
+
agent: anthropic/claude-3-haiku
|
|
241
|
+
disable-model-invocation: false
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
Review the following file: $1
|
|
245
|
+
|
|
246
|
+
Focus on:
|
|
247
|
+
1. Security vulnerabilities
|
|
248
|
+
2. Performance bottlenecks
|
|
249
|
+
3. Code style issues
|
|
250
|
+
|
|
251
|
+
Additional context: $ARGUMENTS
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
| Field | Type | Description |
|
|
255
|
+
|-------|------|-------------|
|
|
256
|
+
| `name` | string | Skill identifier |
|
|
257
|
+
| `description` | string | Human-readable description |
|
|
258
|
+
| `argument-hint` | string | Hint shown for usage |
|
|
259
|
+
| `allowed-tools` | string | Comma-separated tool whitelist |
|
|
260
|
+
| `context` | main / fork | `main` = inject into conversation. `fork` = isolated sub-agent. |
|
|
261
|
+
| `agent` | string | Model to use (fork mode only). Named `agent` for Claude Code heritage; functionally equivalent to `model`. |
|
|
262
|
+
| `disable-model-invocation` | boolean | Only user/API can trigger this skill, not the agent itself (default: false) |
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
## tool.json
|
|
267
|
+
|
|
268
|
+
Custom tool manifest.
|
|
269
|
+
|
|
270
|
+
```json
|
|
271
|
+
{
|
|
272
|
+
"name": "send_slack_message",
|
|
273
|
+
"description": "Sends a message to a Slack channel",
|
|
274
|
+
"input_schema": {
|
|
275
|
+
"type": "object",
|
|
276
|
+
"properties": {
|
|
277
|
+
"channel": { "type": "string", "description": "Slack channel name" },
|
|
278
|
+
"message": { "type": "string", "description": "Message to send" }
|
|
279
|
+
},
|
|
280
|
+
"required": ["channel", "message"]
|
|
281
|
+
},
|
|
282
|
+
"timeout": 30
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## config.json (Forkable, Source Code Only)
|
|
289
|
+
|
|
290
|
+
All branding/naming values. This is a **source code file** inside the VeilCLI repository (`config/config.json`), NOT a user-facing config file. Anyone forking VeilCLI changes only this file to rebrand.
|
|
291
|
+
|
|
292
|
+
```json
|
|
293
|
+
{
|
|
294
|
+
"productName": "VeilCli",
|
|
295
|
+
"productNameShort": "veil",
|
|
296
|
+
"domain": "veil.com",
|
|
297
|
+
"configDir": ".veil",
|
|
298
|
+
"globalConfigDir": "~/.veil",
|
|
299
|
+
"defaultPort": 5050,
|
|
300
|
+
"authHeader": "X-Veil-Secret",
|
|
301
|
+
"tokenPrefix": "kbt_",
|
|
302
|
+
"sessionIdPrefix": "sess_",
|
|
303
|
+
"taskIdPrefix": "task_"
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
## auth.json
|
|
310
|
+
|
|
311
|
+
Local authentication. Gitignored. The `llm` section provides **default** LLM credentials. If `settings.json` also defines `models.main.base_url` / `models.main.api_key`, the settings.json values take precedence per model role.
|
|
312
|
+
|
|
313
|
+
```json
|
|
314
|
+
{
|
|
315
|
+
"veil_token": "kbt_xxxxxxxxxxxx",
|
|
316
|
+
"llm": {
|
|
317
|
+
"base_url": "https://openrouter.ai/api/v1",
|
|
318
|
+
"api_key": "sk-or-xxxxxxxxxxxx"
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
---
|
|
324
|
+
|
|
325
|
+
## settings.json
|
|
326
|
+
|
|
327
|
+
Full configuration. Merged across layers (global → project → local → CLI flags).
|
|
328
|
+
|
|
329
|
+
> **Location:** Project settings go in `.veil/settings.json` — NOT in the project root as `settings.json`. A common mistake is placing settings at `./settings.json` which is never read by the runtime.
|
|
330
|
+
|
|
331
|
+
> **Canonical field names:** The LLM credential fields are `base_url` and `api_key` (snake_case). Do NOT use `apiEndpoint`, `apiKey`, or other variants. These names match the fields in `auth.json` and are exported as constants from `src/settings/fields.js` to prevent inconsistency across the codebase.
|
|
332
|
+
|
|
333
|
+
```json
|
|
334
|
+
{
|
|
335
|
+
"models": {
|
|
336
|
+
"main": {
|
|
337
|
+
"model": "anthropic/claude-3.5-sonnet",
|
|
338
|
+
"base_url": "",
|
|
339
|
+
"api_key": ""
|
|
340
|
+
},
|
|
341
|
+
"compact": {
|
|
342
|
+
"model": "anthropic/claude-3-haiku"
|
|
343
|
+
},
|
|
344
|
+
"title": {
|
|
345
|
+
"model": "anthropic/claude-3-haiku"
|
|
346
|
+
}
|
|
347
|
+
},
|
|
348
|
+
"permissions": {
|
|
349
|
+
"allow": [],
|
|
350
|
+
"ask": [],
|
|
351
|
+
"deny": []
|
|
352
|
+
},
|
|
353
|
+
"hooks": {
|
|
354
|
+
"PreToolUse": "",
|
|
355
|
+
"PostToolUse": ""
|
|
356
|
+
},
|
|
357
|
+
"mcpServers": {
|
|
358
|
+
"filesystem": {
|
|
359
|
+
"transport": "stdio",
|
|
360
|
+
"command": "npx",
|
|
361
|
+
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/project"]
|
|
362
|
+
},
|
|
363
|
+
"web-search": {
|
|
364
|
+
"transport": "http",
|
|
365
|
+
"url": "http://localhost:3001/mcp"
|
|
366
|
+
}
|
|
367
|
+
},
|
|
368
|
+
"api": {
|
|
369
|
+
"port": 5050,
|
|
370
|
+
"secret": ""
|
|
371
|
+
},
|
|
372
|
+
"compaction": {
|
|
373
|
+
"threshold": 0.85,
|
|
374
|
+
"enabled": true,
|
|
375
|
+
"observationMaskingTurns": 10
|
|
376
|
+
},
|
|
377
|
+
"memory": {
|
|
378
|
+
"enabled": true,
|
|
379
|
+
"maxLines": 200,
|
|
380
|
+
"preCompactionExtraction": true
|
|
381
|
+
},
|
|
382
|
+
"storage": {
|
|
383
|
+
"retention": {
|
|
384
|
+
"sessions": { "maxAgeDays": 90, "maxCount": 10000 },
|
|
385
|
+
"tasks": { "maxAgeDays": 30, "maxCount": 5000 }
|
|
386
|
+
}
|
|
387
|
+
},
|
|
388
|
+
"limits": {
|
|
389
|
+
"maxIterations": 50,
|
|
390
|
+
"maxDurationSeconds": 300,
|
|
391
|
+
"maxConcurrentTasks": 5,
|
|
392
|
+
"maxSubAgentDepth": 3
|
|
393
|
+
},
|
|
394
|
+
"retry": {
|
|
395
|
+
"maxAttempts": 3,
|
|
396
|
+
"delaySeconds": 5,
|
|
397
|
+
"onExhausted": "fail"
|
|
398
|
+
},
|
|
399
|
+
"ably": {
|
|
400
|
+
"enabled": false,
|
|
401
|
+
"instanceId": "",
|
|
402
|
+
"tokenEndpoint": "https://veil.com/api/v1/ably/token",
|
|
403
|
+
"requestTimeout": 30000,
|
|
404
|
+
"maxRequestAge": 60000
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
**`onExhausted` valid values:** `"fail"` (default — task fails) or `"wait"` (task pauses in `waiting` status for human retry via `task_respond`).
|
|
410
|
+
|
|
411
|
+
Settings resolution order (last wins):
|
|
412
|
+
```
|
|
413
|
+
1. VeilCLI hardcoded defaults
|
|
414
|
+
2. ~/.veil/settings.json
|
|
415
|
+
3. ./.veil/settings.json
|
|
416
|
+
4. ./.veil/settings.local.json ← same format as settings.json, partial overrides merged
|
|
417
|
+
5. CLI flags
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
`settings.local.json` uses the same schema as `settings.json`. Only the fields present are merged — omitted fields inherit from the previous layer. This file is gitignored and intended for developer-specific overrides (e.g., different API keys, ports).
|
|
421
|
+
|
|
422
|
+
**Settings field names are defined as constants in `src/settings/fields.js`** and used everywhere in the runtime code. Never hardcode field name strings (`'api_key'`, `'base_url'`) inline — always import from `fields.js`. This prevents the class of bugs where one module reads `settings.apiKey` and another writes `settings.api_key`.
|
|
423
|
+
|
|
424
|
+
---
|
|
425
|
+
|
|
426
|
+
## version.json
|
|
427
|
+
|
|
428
|
+
Present **only** in globally cached agents/tools from the Veil.com registry (`~/.veil/agents/<name>/`, `~/.veil/tools/<name>/`). Project-level agents/tools (`.veil/agents/`, `.veil/tools/`) do NOT have this file — they are user-owned and not registry-managed.
|
|
429
|
+
|
|
430
|
+
```json
|
|
431
|
+
{
|
|
432
|
+
"hash": "sha256:a1b2c3d4e5f6...",
|
|
433
|
+
"version": "1.2.0",
|
|
434
|
+
"updatedAt": "2026-03-01T08:00:00Z"
|
|
435
|
+
}
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
| Field | Type | Description |
|
|
439
|
+
|-------|------|-------------|
|
|
440
|
+
| `hash` | string | SHA256 hash of agent/tool contents |
|
|
441
|
+
| `version` | string | Version from Veil.com registry |
|
|
442
|
+
| `updatedAt` | string | ISO 8601 timestamp of last update |
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# 12 — Folder Structure
|
|
2
|
+
|
|
3
|
+
## Project-Level
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
./ ← any folder user runs veil from (clean, no Veil files at root)
|
|
7
|
+
└── .veil/
|
|
8
|
+
├── AGENT.md ← global instructions for all agents in this project
|
|
9
|
+
├── settings.json ← project settings (committed to git)
|
|
10
|
+
├── settings.local.json ← local overrides (gitignored)
|
|
11
|
+
├── auth.json ← local auth override (gitignored)
|
|
12
|
+
├── runtime.pid ← written on server start, deleted on stop
|
|
13
|
+
├── agents/ ← agent definitions (STATIC, read-only)
|
|
14
|
+
│ └── <agentName>/ ← $AGENT_FOLDER resolves to this path
|
|
15
|
+
│ ├── AGENT.md ← agent instructions
|
|
16
|
+
│ ├── agent.json ← agent config (modes, model, tools)
|
|
17
|
+
│ ├── SOUL.md ← optional persona
|
|
18
|
+
│ ├── skills/
|
|
19
|
+
│ │ └── <skillName>/
|
|
20
|
+
│ │ ├── SKILL.md
|
|
21
|
+
│ │ └── scripts/ ← scripts referenced by the skill
|
|
22
|
+
│ └── tools/ ← agent-level custom tools
|
|
23
|
+
│ └── <toolName>/
|
|
24
|
+
│ ├── tool.json
|
|
25
|
+
│ └── index.js
|
|
26
|
+
├── memory/ ← persistent memory (MUTABLE)
|
|
27
|
+
│ ├── MEMORY.md ← global memory (always loaded, ~200-line cap)
|
|
28
|
+
│ ├── <topic>.md ← auto-exported global memory files
|
|
29
|
+
│ └── agents/
|
|
30
|
+
│ └── <agentName>/
|
|
31
|
+
│ ├── MEMORY.md ← agent-specific memory (always loaded, ~200-line cap)
|
|
32
|
+
│ └── <topic>.md ← auto-exported agent memory files
|
|
33
|
+
├── heartbeats/ ← daemon checklists (MUTABLE)
|
|
34
|
+
│ └── <agentName>.md ← per-agent heartbeat checklist
|
|
35
|
+
├── skills/ ← shared skills available to all agents
|
|
36
|
+
│ └── <skillName>/
|
|
37
|
+
│ └── SKILL.md
|
|
38
|
+
└── tools/ ← project-level custom tools
|
|
39
|
+
└── <toolName>/
|
|
40
|
+
├── tool.json
|
|
41
|
+
└── index.js
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**Global instructions:** `.veil/AGENT.md` only. No fallback to project root. Claude Code projects must be converted via `veil import`.
|
|
45
|
+
|
|
46
|
+
> **Common mistake:** Placing agents in `./agents/` (project root) instead of `./.veil/agents/`. The runtime only scans `.veil/agents/`.
|
|
47
|
+
|
|
48
|
+
## Global
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
~/.veil/
|
|
52
|
+
├── auth.json ← Veil.com token + LLM API config
|
|
53
|
+
├── settings.json ← global default settings
|
|
54
|
+
├── data.db ← SQLite database (all runtime data)
|
|
55
|
+
├── agents/ ← agents cached from Veil.com (static)
|
|
56
|
+
│ └── <agentName>/
|
|
57
|
+
│ ├── version.json ← SHA256 hash for registry version checking
|
|
58
|
+
│ └── ... ← same structure as project agent
|
|
59
|
+
├── skills/ ← global shared skills
|
|
60
|
+
│ └── <skillName>/
|
|
61
|
+
│ └── SKILL.md
|
|
62
|
+
├── tools/ ← global custom tools
|
|
63
|
+
│ └── <toolName>/
|
|
64
|
+
│ ├── tool.json
|
|
65
|
+
│ ├── index.js
|
|
66
|
+
│ └── version.json ← SHA256 hash for registry version checking
|
|
67
|
+
├── backups/ ← auto-backups of data.db
|
|
68
|
+
│ └── data-2026-03-01.db
|
|
69
|
+
└── archive/ ← archived old sessions/tasks (gzipped JSONL)
|
|
70
|
+
└── sessions-2026-03.jsonl.gz
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Source Code (Runtime)
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
veilcli/
|
|
77
|
+
├── package.json ← bin: { "veil": "./src/cli/index.js" } ← MUST point here
|
|
78
|
+
├── config/
|
|
79
|
+
│ └── config.json ← forkable branding/naming
|
|
80
|
+
├── src/
|
|
81
|
+
│ ├── core/ ← Pure business logic (transport agnostic)
|
|
82
|
+
│ │ ├── loop.js ← Agentic loop (async generator)
|
|
83
|
+
│ │ ├── router.js ← Multi-model delegation (IntelligenceRouter)
|
|
84
|
+
│ │ ├── registry.js ← Tool registration + ajv compilation
|
|
85
|
+
│ │ ├── prompt.js ← System prompt assembly (7 layers)
|
|
86
|
+
│ │ ├── compaction.js ← Context compaction logic
|
|
87
|
+
│ │ ├── agent.js ← Agent loader + discovery
|
|
88
|
+
│ │ ├── memory.js ← Memory management (read/write/search/export)
|
|
89
|
+
│ │ └── queue.js ← Agent message queue
|
|
90
|
+
│ ├── api/ ← REST-specific transport
|
|
91
|
+
│ │ ├── routes.js
|
|
92
|
+
│ │ ├── middleware.js
|
|
93
|
+
│ │ └── controllers.js
|
|
94
|
+
│ ├── cli/
|
|
95
|
+
│ │ ├── index.js ← CLI entry point (bin target)
|
|
96
|
+
│ │ ├── parser.js
|
|
97
|
+
│ │ └── formatter.js
|
|
98
|
+
│ ├── llm/
|
|
99
|
+
│ │ └── client.js ← Native fetch-based LLM client (no SDK)
|
|
100
|
+
│ ├── settings/
|
|
101
|
+
│ │ └── fields.js ← Settings field name constants (single source of truth)
|
|
102
|
+
│ ├── utils/
|
|
103
|
+
│ │ ├── context.js ← CWD singleton — set once at startup, read everywhere
|
|
104
|
+
│ │ ├── id.js ← generateId() via crypto.randomBytes (no nanoid)
|
|
105
|
+
│ │ └── paths.js ← Path helpers: getProjectAgentsDir(cwd), etc.
|
|
106
|
+
│ ├── tools/ ← Built-in tool implementations
|
|
107
|
+
│ │ ├── bash.js
|
|
108
|
+
│ │ ├── read-file.js
|
|
109
|
+
│ │ ├── write-file.js
|
|
110
|
+
│ │ └── ...
|
|
111
|
+
│ ├── infrastructure/ ← External resource management
|
|
112
|
+
│ │ ├── database.js ← SQLite setup, migrations, queries
|
|
113
|
+
│ │ ├── scheduler.js ← Cron scheduling for daemons
|
|
114
|
+
│ │ ├── ably.js ← Ably bridge
|
|
115
|
+
│ │ └── mcp.js ← MCP client wrapper
|
|
116
|
+
│ └── system-prompts/ ← System prompt fragments
|
|
117
|
+
│ ├── base-core.md
|
|
118
|
+
│ ├── safety-rules.md
|
|
119
|
+
│ ├── environment.md
|
|
120
|
+
│ ├── task-heuristics.md
|
|
121
|
+
│ └── reminders/
|
|
122
|
+
│ ├── anti-drift.md
|
|
123
|
+
│ ├── stall-recovery.md
|
|
124
|
+
│ └── ...
|
|
125
|
+
├── migrations/ ← SQLite migration files (all use IF NOT EXISTS)
|
|
126
|
+
│ ├── 001-initial.sql
|
|
127
|
+
│ └── ...
|
|
128
|
+
├── examples/ ← Reference agents guaranteed to pass schema validation
|
|
129
|
+
│ └── agents/
|
|
130
|
+
│ └── hello/ ← Minimal chat-only agent (used in smoke test)
|
|
131
|
+
│ ├── AGENT.md
|
|
132
|
+
│ └── agent.json
|
|
133
|
+
└── test/
|
|
134
|
+
├── unit/
|
|
135
|
+
├── api/
|
|
136
|
+
└── smoke.js ← Fast startup + health + one chat call
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Critical Implementation Rules
|
|
140
|
+
|
|
141
|
+
**1. CWD singleton (`src/utils/context.js`):**
|
|
142
|
+
The server's working directory is set **once** at startup (in `src/cli/index.js`) and stored in a singleton. All routes, agents, and tools read from `context.getCwd()`. **Never call `process.cwd()` inside `src/core/`, `src/api/`, `src/tools/`, or `src/infrastructure/`.** Only `src/cli/index.js` may call `process.cwd()` (at launch time).
|
|
143
|
+
|
|
144
|
+
```javascript
|
|
145
|
+
// src/utils/context.js
|
|
146
|
+
let _cwd = null;
|
|
147
|
+
module.exports = {
|
|
148
|
+
setCwd(cwd) { _cwd = cwd; },
|
|
149
|
+
getCwd() {
|
|
150
|
+
if (!_cwd) throw new Error('Context not initialized — call setCwd() at startup');
|
|
151
|
+
return _cwd;
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
// Usage in routes:
|
|
155
|
+
const { getCwd } = require('../utils/context');
|
|
156
|
+
const agentsDir = paths.getProjectAgentsDir(getCwd());
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
This also eliminates the circular dependency that arises when routes import from `server.js` to get `cwd` and `server.js` imports routes.
|
|
160
|
+
|
|
161
|
+
**2. Path helpers (`src/utils/paths.js`):**
|
|
162
|
+
All path construction goes through named helpers. **Do not construct `.veil/` paths inline.**
|
|
163
|
+
|
|
164
|
+
```javascript
|
|
165
|
+
// Correct — explicit, clear:
|
|
166
|
+
const agentsDir = paths.getProjectAgentsDir(cwd); // → cwd/.veil/agents
|
|
167
|
+
|
|
168
|
+
// Wrong — was getAgentsDir(cwd) which returned cwd/agents (missing .veil):
|
|
169
|
+
const agentsDir = paths.getAgentsDir(cwd); // REMOVED — ambiguous name
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Key functions in `paths.js`:
|
|
173
|
+
- `getProjectConfigDir(cwd)` → `cwd/.veil/`
|
|
174
|
+
- `getProjectAgentsDir(cwd)` → `cwd/.veil/agents/`
|
|
175
|
+
- `getProjectSettingsPath(cwd)` → `cwd/.veil/settings.json`
|
|
176
|
+
- `getGlobalAgentsDir()` → `~/.veil/agents/`
|
|
177
|
+
- `getAgentDir(cwd, agentName)` → full path for a named agent
|
|
178
|
+
|
|
179
|
+
**3. Settings field names (`src/settings/fields.js`):**
|
|
180
|
+
```javascript
|
|
181
|
+
// src/settings/fields.js — single source of truth
|
|
182
|
+
module.exports = {
|
|
183
|
+
MODEL_BASE_URL: 'base_url',
|
|
184
|
+
MODEL_API_KEY: 'api_key',
|
|
185
|
+
MODEL_NAME: 'model',
|
|
186
|
+
// ... all other field names
|
|
187
|
+
};
|
|
188
|
+
// Never hardcode 'api_key' or 'base_url' as strings in any other file.
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
**4. `package.json` bin path:**
|
|
192
|
+
```json
|
|
193
|
+
{ "bin": { "veil": "./src/cli/index.js" } }
|
|
194
|
+
```
|
|
195
|
+
The root `index.js` does NOT exist. The CLI entry is always `src/cli/index.js`.
|
|
196
|
+
|
|
197
|
+
**5. Version reading:**
|
|
198
|
+
Do NOT use `require('../../package.json')` inside deeply-nested route files — the relative depth varies and causes `Cannot find module` errors. Instead, read version at startup and pass it via `context.js` or a `constants.js` file:
|
|
199
|
+
```javascript
|
|
200
|
+
// Set once at startup in src/cli/index.js:
|
|
201
|
+
const { version } = require('../package.json'); // correct relative path from cli/
|
|
202
|
+
context.setVersion(version);
|
|
203
|
+
// In routes:
|
|
204
|
+
const version = context.getVersion();
|
|
205
|
+
```
|