@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
package/llm/client.js
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Native fetch-based LLM client.
|
|
5
|
+
* No SDK dependency — works with any OpenAI-compatible endpoint.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Build the request body shared by streaming and non-streaming calls.
|
|
10
|
+
*/
|
|
11
|
+
function buildRequestBody({ model, messages, tools = [], temperature, reasoning, maxTokens, thinking, modalities, audio, stream }) {
|
|
12
|
+
const body = { model, messages };
|
|
13
|
+
if (tools.length > 0) body.tools = tools;
|
|
14
|
+
if (temperature !== undefined) body.temperature = temperature;
|
|
15
|
+
if (reasoning) body.reasoning = { effort: reasoning };
|
|
16
|
+
if (thinking) body.thinking = thinking;
|
|
17
|
+
if (maxTokens !== undefined) body.max_tokens = maxTokens;
|
|
18
|
+
if (modalities) body.modalities = modalities;
|
|
19
|
+
if (audio) body.audio = audio;
|
|
20
|
+
if (stream) body.stream = true;
|
|
21
|
+
return body;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function buildHeaders(apiKey) {
|
|
25
|
+
return {
|
|
26
|
+
'Content-Type': 'application/json',
|
|
27
|
+
'Authorization': `Bearer ${apiKey || ''}`,
|
|
28
|
+
'HTTP-Referer': 'https://veil.com',
|
|
29
|
+
'X-Title': 'VeilCLI',
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Call the LLM API.
|
|
35
|
+
* If `onChunk` is provided, uses server-sent events streaming internally and calls
|
|
36
|
+
* `onChunk(text)` for each content delta. The return value is always the same shape
|
|
37
|
+
* as a non-streaming response.
|
|
38
|
+
*
|
|
39
|
+
* @param {{ baseUrl: string, apiKey: string, model: string, messages: Object[], tools?: Object[], temperature?: number, reasoning?: string, maxTokens?: number, thinking?: Object, onChunk?: (text: string) => void }} opts
|
|
40
|
+
* @returns {Promise<Object>} Raw API response body (OpenAI-compatible shape)
|
|
41
|
+
*/
|
|
42
|
+
async function callLLM({ baseUrl, apiKey, model, messages, tools = [], temperature, reasoning, maxTokens, thinking, modalities, audio, onChunk, onToolStart }) {
|
|
43
|
+
if (!Array.isArray(messages) || messages.length === 0) {
|
|
44
|
+
throw new Error('callLLM: messages must be a non-empty array');
|
|
45
|
+
}
|
|
46
|
+
if (!Array.isArray(tools)) {
|
|
47
|
+
throw new Error('callLLM: tools must be an array');
|
|
48
|
+
}
|
|
49
|
+
if (!model) throw new Error('callLLM: model is required');
|
|
50
|
+
if (!baseUrl) throw new Error('callLLM: baseUrl is required');
|
|
51
|
+
|
|
52
|
+
// Audio output requires streaming internally (provider requirement)
|
|
53
|
+
const needsStreaming = !!onChunk || (Array.isArray(modalities) && modalities.includes('audio'));
|
|
54
|
+
if (needsStreaming) {
|
|
55
|
+
return callLLMStreaming({ baseUrl, apiKey, model, messages, tools, temperature, reasoning, maxTokens, thinking, modalities, audio, onChunk: onChunk || (() => {}), onToolStart });
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const body = buildRequestBody({ model, messages, tools, temperature, reasoning, maxTokens, thinking, modalities, audio });
|
|
59
|
+
|
|
60
|
+
const response = await fetch(`${baseUrl}/chat/completions`, {
|
|
61
|
+
method: 'POST',
|
|
62
|
+
headers: buildHeaders(apiKey),
|
|
63
|
+
body: JSON.stringify(body),
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
if (!response.ok) {
|
|
67
|
+
let errText = '';
|
|
68
|
+
try { errText = await response.text(); } catch {}
|
|
69
|
+
throw new Error(`LLM API error ${response.status}: ${errText.slice(0, 500)}`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return response.json();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Internal: streaming callLLM. Parses SSE deltas, calls onChunk for content tokens,
|
|
77
|
+
* reassembles tool call deltas, and returns a response in the same shape as callLLM.
|
|
78
|
+
*/
|
|
79
|
+
async function callLLMStreaming({ baseUrl, apiKey, model, messages, tools = [], temperature, reasoning, maxTokens, thinking, modalities, audio, onChunk, onToolStart }) {
|
|
80
|
+
const body = buildRequestBody({ model, messages, tools, temperature, reasoning, maxTokens, thinking, modalities, audio, stream: true });
|
|
81
|
+
|
|
82
|
+
const response = await fetch(`${baseUrl}/chat/completions`, {
|
|
83
|
+
method: 'POST',
|
|
84
|
+
headers: buildHeaders(apiKey),
|
|
85
|
+
body: JSON.stringify(body),
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
if (!response.ok) {
|
|
89
|
+
let errText = '';
|
|
90
|
+
try { errText = await response.text(); } catch {}
|
|
91
|
+
throw new Error(`LLM API error ${response.status}: ${errText.slice(0, 500)}`);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const reader = response.body.getReader();
|
|
95
|
+
const decoder = new TextDecoder();
|
|
96
|
+
let buffer = '';
|
|
97
|
+
|
|
98
|
+
let fullContent = '';
|
|
99
|
+
let finishReason = 'stop';
|
|
100
|
+
const toolCallBuffers = {};
|
|
101
|
+
const toolNameEmitted = new Set();
|
|
102
|
+
const audioChunks = [];
|
|
103
|
+
let usageData = null;
|
|
104
|
+
|
|
105
|
+
while (true) {
|
|
106
|
+
const { done, value } = await reader.read();
|
|
107
|
+
if (done) break;
|
|
108
|
+
buffer += decoder.decode(value, { stream: true });
|
|
109
|
+
const lines = buffer.split('\n');
|
|
110
|
+
buffer = lines.pop();
|
|
111
|
+
|
|
112
|
+
for (const line of lines) {
|
|
113
|
+
const trimmed = line.trim();
|
|
114
|
+
if (!trimmed.startsWith('data: ')) continue;
|
|
115
|
+
const payload = trimmed.slice(6);
|
|
116
|
+
if (payload === '[DONE]') continue;
|
|
117
|
+
|
|
118
|
+
let chunk;
|
|
119
|
+
try { chunk = JSON.parse(payload); } catch { continue; }
|
|
120
|
+
|
|
121
|
+
if (chunk.usage) usageData = chunk.usage;
|
|
122
|
+
|
|
123
|
+
const choice = chunk.choices?.[0];
|
|
124
|
+
if (!choice) continue;
|
|
125
|
+
if (choice.finish_reason) finishReason = choice.finish_reason;
|
|
126
|
+
|
|
127
|
+
const delta = choice.delta || {};
|
|
128
|
+
|
|
129
|
+
if (delta.content) {
|
|
130
|
+
fullContent += delta.content;
|
|
131
|
+
onChunk(delta.content);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (delta.audio?.data) {
|
|
135
|
+
audioChunks.push(delta.audio.data);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (delta.tool_calls) {
|
|
139
|
+
for (const tc of delta.tool_calls) {
|
|
140
|
+
const idx = tc.index ?? 0;
|
|
141
|
+
if (!toolCallBuffers[idx]) {
|
|
142
|
+
toolCallBuffers[idx] = { id: '', type: 'function', function: { name: '', arguments: '' } };
|
|
143
|
+
}
|
|
144
|
+
if (tc.id) toolCallBuffers[idx].id = tc.id;
|
|
145
|
+
if (tc.function?.name) {
|
|
146
|
+
toolCallBuffers[idx].function.name += tc.function.name;
|
|
147
|
+
if (!toolNameEmitted.has(idx) && toolCallBuffers[idx].function.name) {
|
|
148
|
+
toolNameEmitted.add(idx);
|
|
149
|
+
onToolStart?.(toolCallBuffers[idx].function.name);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if (tc.function?.arguments) toolCallBuffers[idx].function.arguments += tc.function.arguments;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const toolCallsArray = Object.keys(toolCallBuffers).length > 0 ? Object.values(toolCallBuffers) : null;
|
|
159
|
+
|
|
160
|
+
return {
|
|
161
|
+
choices: [{
|
|
162
|
+
message: {
|
|
163
|
+
content: fullContent || null,
|
|
164
|
+
audio: audioChunks.length > 0 ? { data: audioChunks.join('') } : null,
|
|
165
|
+
tool_calls: toolCallsArray,
|
|
166
|
+
},
|
|
167
|
+
finish_reason: finishReason,
|
|
168
|
+
}],
|
|
169
|
+
usage: usageData || { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 },
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Extract the assistant message from an API response.
|
|
175
|
+
* @param {Object} response - Raw API response
|
|
176
|
+
* @returns {{ content: string|null, toolCalls: Object[]|null, finishReason: string }}
|
|
177
|
+
*/
|
|
178
|
+
function extractMessage(response) {
|
|
179
|
+
const choice = response.choices && response.choices[0];
|
|
180
|
+
if (!choice) throw new Error('LLM response had no choices');
|
|
181
|
+
|
|
182
|
+
const msg = choice.message;
|
|
183
|
+
return {
|
|
184
|
+
content: msg.content || null,
|
|
185
|
+
audio: msg.audio || null,
|
|
186
|
+
toolCalls: msg.tool_calls && msg.tool_calls.length > 0 ? msg.tool_calls : null,
|
|
187
|
+
finishReason: choice.finish_reason || 'stop',
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Extract token usage from an API response.
|
|
193
|
+
* @param {Object} response - Raw API response
|
|
194
|
+
* @returns {{ input: number, output: number, cache: number, cost: number }}
|
|
195
|
+
*/
|
|
196
|
+
function extractUsage(response) {
|
|
197
|
+
const usage = response.usage || {};
|
|
198
|
+
return {
|
|
199
|
+
input: usage.prompt_tokens || 0,
|
|
200
|
+
output: usage.completion_tokens || 0,
|
|
201
|
+
cache: usage.prompt_tokens_details?.cached_tokens || 0,
|
|
202
|
+
cost: usage.cost || 0,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
module.exports = { callLLM, extractMessage, extractUsage };
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
-- VeilCLI Initial Schema
|
|
2
|
+
-- All statements use IF NOT EXISTS (idempotent — safe to run on every startup)
|
|
3
|
+
|
|
4
|
+
CREATE TABLE IF NOT EXISTS schema_version (
|
|
5
|
+
version INTEGER PRIMARY KEY,
|
|
6
|
+
applied_at TEXT NOT NULL
|
|
7
|
+
);
|
|
8
|
+
|
|
9
|
+
CREATE TABLE IF NOT EXISTS sessions (
|
|
10
|
+
id TEXT PRIMARY KEY,
|
|
11
|
+
agent_name TEXT NOT NULL,
|
|
12
|
+
mode TEXT NOT NULL CHECK(mode IN ('chat','task','daemon','subagent')),
|
|
13
|
+
instance_folder TEXT,
|
|
14
|
+
status TEXT NOT NULL DEFAULT 'active' CHECK(status IN ('active','closed')),
|
|
15
|
+
model TEXT,
|
|
16
|
+
title TEXT,
|
|
17
|
+
message_count INTEGER NOT NULL DEFAULT 0,
|
|
18
|
+
token_input INTEGER NOT NULL DEFAULT 0,
|
|
19
|
+
token_output INTEGER NOT NULL DEFAULT 0,
|
|
20
|
+
token_cache INTEGER NOT NULL DEFAULT 0,
|
|
21
|
+
estimated_cost REAL NOT NULL DEFAULT 0,
|
|
22
|
+
compaction_count INTEGER NOT NULL DEFAULT 0,
|
|
23
|
+
created_at TEXT NOT NULL,
|
|
24
|
+
updated_at TEXT NOT NULL
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
CREATE TABLE IF NOT EXISTS messages (
|
|
28
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
29
|
+
session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
30
|
+
role TEXT NOT NULL CHECK(role IN ('system','user','assistant','tool')),
|
|
31
|
+
content TEXT,
|
|
32
|
+
tool_calls TEXT,
|
|
33
|
+
tool_call_id TEXT,
|
|
34
|
+
token_count INTEGER,
|
|
35
|
+
created_at TEXT NOT NULL
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
CREATE TABLE IF NOT EXISTS tasks (
|
|
39
|
+
id TEXT PRIMARY KEY,
|
|
40
|
+
session_id TEXT REFERENCES sessions(id) ON DELETE SET NULL,
|
|
41
|
+
agent_name TEXT NOT NULL,
|
|
42
|
+
status TEXT NOT NULL DEFAULT 'pending'
|
|
43
|
+
CHECK(status IN ('pending','processing','waiting','finished','failed','canceled')),
|
|
44
|
+
priority TEXT NOT NULL DEFAULT 'normal' CHECK(priority IN ('high','normal','low')),
|
|
45
|
+
parent_task_id TEXT REFERENCES tasks(id) ON DELETE SET NULL,
|
|
46
|
+
input TEXT,
|
|
47
|
+
output TEXT,
|
|
48
|
+
error TEXT,
|
|
49
|
+
tags TEXT,
|
|
50
|
+
iterations INTEGER NOT NULL DEFAULT 0,
|
|
51
|
+
max_iterations INTEGER,
|
|
52
|
+
max_duration_seconds INTEGER,
|
|
53
|
+
token_input INTEGER NOT NULL DEFAULT 0,
|
|
54
|
+
token_output INTEGER NOT NULL DEFAULT 0,
|
|
55
|
+
token_cache INTEGER NOT NULL DEFAULT 0,
|
|
56
|
+
estimated_cost REAL NOT NULL DEFAULT 0,
|
|
57
|
+
instance_folder TEXT,
|
|
58
|
+
created_at TEXT NOT NULL,
|
|
59
|
+
started_at TEXT,
|
|
60
|
+
finished_at TEXT,
|
|
61
|
+
updated_at TEXT NOT NULL
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
CREATE TABLE IF NOT EXISTS task_events (
|
|
65
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
66
|
+
task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
67
|
+
type TEXT NOT NULL,
|
|
68
|
+
data TEXT,
|
|
69
|
+
created_at TEXT NOT NULL
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
CREATE TABLE IF NOT EXISTS todos (
|
|
73
|
+
session_id TEXT PRIMARY KEY REFERENCES sessions(id) ON DELETE CASCADE,
|
|
74
|
+
items TEXT NOT NULL DEFAULT '[]',
|
|
75
|
+
updated_at TEXT NOT NULL
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
CREATE TABLE IF NOT EXISTS agent_messages (
|
|
79
|
+
id TEXT PRIMARY KEY,
|
|
80
|
+
target_agent TEXT NOT NULL,
|
|
81
|
+
target_session_id TEXT REFERENCES sessions(id) ON DELETE SET NULL,
|
|
82
|
+
from_agent TEXT NOT NULL,
|
|
83
|
+
content TEXT NOT NULL,
|
|
84
|
+
followup INTEGER NOT NULL DEFAULT 0,
|
|
85
|
+
skill TEXT,
|
|
86
|
+
status TEXT NOT NULL DEFAULT 'pending' CHECK(status IN ('pending','delivered','expired')),
|
|
87
|
+
correlation_id TEXT,
|
|
88
|
+
response TEXT,
|
|
89
|
+
created_at TEXT NOT NULL,
|
|
90
|
+
delivered_at TEXT
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
CREATE TABLE IF NOT EXISTS task_subscriptions (
|
|
94
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
95
|
+
task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
96
|
+
subscriber_session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
97
|
+
subscriber_agent TEXT NOT NULL,
|
|
98
|
+
status TEXT NOT NULL DEFAULT 'pending' CHECK(status IN ('pending','delivered')),
|
|
99
|
+
created_at TEXT NOT NULL,
|
|
100
|
+
delivered_at TEXT
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
-- Indexes
|
|
104
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_agent ON sessions(agent_name);
|
|
105
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_status ON sessions(status);
|
|
106
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_created ON sessions(created_at);
|
|
107
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_folder ON sessions(instance_folder);
|
|
108
|
+
|
|
109
|
+
CREATE INDEX IF NOT EXISTS idx_messages_session ON messages(session_id);
|
|
110
|
+
|
|
111
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_agent ON tasks(agent_name);
|
|
112
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status);
|
|
113
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_parent ON tasks(parent_task_id);
|
|
114
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_created ON tasks(created_at);
|
|
115
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_folder ON tasks(instance_folder);
|
|
116
|
+
|
|
117
|
+
CREATE INDEX IF NOT EXISTS idx_task_events_task ON task_events(task_id);
|
|
118
|
+
|
|
119
|
+
CREATE INDEX IF NOT EXISTS idx_agent_messages_target ON agent_messages(target_agent, status);
|
|
120
|
+
|
|
121
|
+
CREATE INDEX IF NOT EXISTS idx_task_subscriptions_task ON task_subscriptions(task_id, status);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
-- VeilCLI Debuggability Migration
|
|
2
|
+
-- Adds: token_budget and tags on tasks, task_context table for LLM context snapshots
|
|
3
|
+
-- Note: These columns may already exist from migration 001 - the runtime handles this gracefully
|
|
4
|
+
|
|
5
|
+
CREATE TABLE IF NOT EXISTS task_context (
|
|
6
|
+
task_id TEXT PRIMARY KEY REFERENCES tasks(id) ON DELETE CASCADE,
|
|
7
|
+
messages TEXT NOT NULL,
|
|
8
|
+
tools TEXT,
|
|
9
|
+
iteration INTEGER,
|
|
10
|
+
updated_at TEXT NOT NULL
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
CREATE INDEX IF NOT EXISTS idx_task_context_task ON task_context(task_id);
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
-- Migration 003: Drop orphaned columns
|
|
2
|
+
-- These columns were defined but never read or written by production code
|
|
3
|
+
|
|
4
|
+
-- SQLite doesn't support DROP COLUMN directly, so we need to recreate tables
|
|
5
|
+
-- This migration uses the "rename-copy-drop" pattern
|
|
6
|
+
|
|
7
|
+
-- ============================================================================
|
|
8
|
+
-- Sessions table: drop estimated_cost and compaction_count
|
|
9
|
+
-- ============================================================================
|
|
10
|
+
|
|
11
|
+
CREATE TABLE sessions_new (
|
|
12
|
+
id TEXT PRIMARY KEY,
|
|
13
|
+
agent_name TEXT NOT NULL,
|
|
14
|
+
mode TEXT NOT NULL CHECK(mode IN ('chat', 'task', 'daemon', 'subagent')),
|
|
15
|
+
status TEXT NOT NULL DEFAULT 'active' CHECK(status IN ('active', 'closed')),
|
|
16
|
+
model TEXT,
|
|
17
|
+
token_input INTEGER NOT NULL DEFAULT 0,
|
|
18
|
+
token_output INTEGER NOT NULL DEFAULT 0,
|
|
19
|
+
token_cache INTEGER NOT NULL DEFAULT 0,
|
|
20
|
+
created_at TEXT NOT NULL,
|
|
21
|
+
updated_at TEXT NOT NULL
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
INSERT INTO sessions_new (id, agent_name, mode, status, model, token_input, token_output, token_cache, created_at, updated_at)
|
|
25
|
+
SELECT id, agent_name, mode, status, model, token_input, token_output, token_cache, created_at, updated_at
|
|
26
|
+
FROM sessions;
|
|
27
|
+
|
|
28
|
+
DROP TABLE sessions;
|
|
29
|
+
ALTER TABLE sessions_new RENAME TO sessions;
|
|
30
|
+
|
|
31
|
+
CREATE INDEX idx_sessions_agent ON sessions(agent_name);
|
|
32
|
+
CREATE INDEX idx_sessions_status ON sessions(status);
|
|
33
|
+
|
|
34
|
+
-- ============================================================================
|
|
35
|
+
-- Tasks table: drop estimated_cost
|
|
36
|
+
-- ============================================================================
|
|
37
|
+
|
|
38
|
+
CREATE TABLE tasks_new (
|
|
39
|
+
id TEXT PRIMARY KEY,
|
|
40
|
+
agent_name TEXT NOT NULL,
|
|
41
|
+
input TEXT NOT NULL,
|
|
42
|
+
status TEXT NOT NULL DEFAULT 'pending' CHECK(status IN ('pending', 'processing', 'waiting', 'finished', 'failed', 'canceled')),
|
|
43
|
+
priority TEXT NOT NULL DEFAULT 'normal' CHECK(priority IN ('low', 'normal', 'high')),
|
|
44
|
+
output TEXT,
|
|
45
|
+
error TEXT,
|
|
46
|
+
session_id TEXT,
|
|
47
|
+
parent_task_id TEXT,
|
|
48
|
+
tags TEXT,
|
|
49
|
+
iterations INTEGER NOT NULL DEFAULT 0,
|
|
50
|
+
max_iterations INTEGER,
|
|
51
|
+
max_duration_seconds INTEGER,
|
|
52
|
+
token_input INTEGER NOT NULL DEFAULT 0,
|
|
53
|
+
token_output INTEGER NOT NULL DEFAULT 0,
|
|
54
|
+
token_cache INTEGER NOT NULL DEFAULT 0,
|
|
55
|
+
token_budget INTEGER,
|
|
56
|
+
instance_folder TEXT,
|
|
57
|
+
created_at TEXT NOT NULL,
|
|
58
|
+
started_at TEXT,
|
|
59
|
+
finished_at TEXT,
|
|
60
|
+
updated_at TEXT NOT NULL
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
INSERT INTO tasks_new (id, agent_name, input, status, priority, output, error, session_id, parent_task_id, tags, iterations, max_iterations, max_duration_seconds, token_input, token_output, token_cache, token_budget, instance_folder, created_at, started_at, finished_at, updated_at)
|
|
64
|
+
SELECT id, agent_name, input, status, priority, output, error, session_id, parent_task_id, tags, iterations, max_iterations, max_duration_seconds, token_input, token_output, token_cache, token_budget, instance_folder, created_at, started_at, finished_at, updated_at
|
|
65
|
+
FROM tasks;
|
|
66
|
+
|
|
67
|
+
DROP TABLE tasks;
|
|
68
|
+
ALTER TABLE tasks_new RENAME TO tasks;
|
|
69
|
+
|
|
70
|
+
CREATE INDEX idx_tasks_agent ON tasks(agent_name);
|
|
71
|
+
CREATE INDEX idx_tasks_status ON tasks(status);
|
|
72
|
+
CREATE INDEX idx_tasks_parent ON tasks(parent_task_id);
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
-- Migration 004: Rename token columns in sessions, add context tracking, improve message token fields
|
|
2
|
+
-- Sessions: token_input/output/cache → total_input/output/cache_tokens, estimated_cost → cost
|
|
3
|
+
-- + new context_size and context_size_limit columns
|
|
4
|
+
-- Messages: replace single token_count with per-message model_key + input/output/cache_tokens + cost
|
|
5
|
+
|
|
6
|
+
-- ============================================================================
|
|
7
|
+
-- Sessions table
|
|
8
|
+
-- ============================================================================
|
|
9
|
+
|
|
10
|
+
CREATE TABLE sessions_new (
|
|
11
|
+
id TEXT PRIMARY KEY,
|
|
12
|
+
agent_name TEXT NOT NULL,
|
|
13
|
+
mode TEXT NOT NULL CHECK(mode IN ('chat','task','daemon','subagent')),
|
|
14
|
+
instance_folder TEXT,
|
|
15
|
+
status TEXT NOT NULL DEFAULT 'active' CHECK(status IN ('active','closed')),
|
|
16
|
+
model TEXT,
|
|
17
|
+
title TEXT,
|
|
18
|
+
message_count INTEGER NOT NULL DEFAULT 0,
|
|
19
|
+
total_input_tokens INTEGER NOT NULL DEFAULT 0,
|
|
20
|
+
total_output_tokens INTEGER NOT NULL DEFAULT 0,
|
|
21
|
+
total_cache_tokens INTEGER NOT NULL DEFAULT 0,
|
|
22
|
+
context_size INTEGER NOT NULL DEFAULT 0,
|
|
23
|
+
context_size_limit INTEGER,
|
|
24
|
+
cost REAL NOT NULL DEFAULT 0,
|
|
25
|
+
compaction_count INTEGER NOT NULL DEFAULT 0,
|
|
26
|
+
created_at TEXT NOT NULL,
|
|
27
|
+
updated_at TEXT NOT NULL
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
INSERT INTO sessions_new (
|
|
31
|
+
id, agent_name, mode, instance_folder, status, model, title, message_count,
|
|
32
|
+
total_input_tokens, total_output_tokens, total_cache_tokens, context_size, cost,
|
|
33
|
+
compaction_count, created_at, updated_at
|
|
34
|
+
)
|
|
35
|
+
SELECT
|
|
36
|
+
id, agent_name, mode, instance_folder, status, model, title, COALESCE(message_count, 0),
|
|
37
|
+
COALESCE(token_input, 0), COALESCE(token_output, 0), COALESCE(token_cache, 0),
|
|
38
|
+
0,
|
|
39
|
+
COALESCE(estimated_cost, 0),
|
|
40
|
+
COALESCE(compaction_count, 0),
|
|
41
|
+
created_at, updated_at
|
|
42
|
+
FROM sessions;
|
|
43
|
+
|
|
44
|
+
DROP TABLE sessions;
|
|
45
|
+
ALTER TABLE sessions_new RENAME TO sessions;
|
|
46
|
+
|
|
47
|
+
CREATE INDEX idx_sessions_agent ON sessions(agent_name);
|
|
48
|
+
CREATE INDEX idx_sessions_status ON sessions(status);
|
|
49
|
+
CREATE INDEX idx_sessions_created ON sessions(created_at);
|
|
50
|
+
CREATE INDEX idx_sessions_folder ON sessions(instance_folder);
|
|
51
|
+
|
|
52
|
+
-- ============================================================================
|
|
53
|
+
-- Messages table
|
|
54
|
+
-- ============================================================================
|
|
55
|
+
|
|
56
|
+
CREATE TABLE messages_new (
|
|
57
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
58
|
+
session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
59
|
+
role TEXT NOT NULL CHECK(role IN ('system','user','assistant','tool')),
|
|
60
|
+
content TEXT,
|
|
61
|
+
tool_calls TEXT,
|
|
62
|
+
tool_call_id TEXT,
|
|
63
|
+
model_key TEXT,
|
|
64
|
+
input_tokens INTEGER,
|
|
65
|
+
output_tokens INTEGER,
|
|
66
|
+
cache_tokens INTEGER,
|
|
67
|
+
cost REAL,
|
|
68
|
+
created_at TEXT NOT NULL
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
INSERT INTO messages_new (id, session_id, role, content, tool_calls, tool_call_id, output_tokens, created_at)
|
|
72
|
+
SELECT id, session_id, role, content, tool_calls, tool_call_id, token_count, created_at
|
|
73
|
+
FROM messages;
|
|
74
|
+
|
|
75
|
+
DROP TABLE messages;
|
|
76
|
+
ALTER TABLE messages_new RENAME TO messages;
|
|
77
|
+
|
|
78
|
+
CREATE INDEX idx_messages_session ON messages(session_id);
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
-- Migration 005: Add model_thinking column to sessions
|
|
2
|
+
-- Stores an optional JSON config for extended thinking mode (e.g. Anthropic extended thinking).
|
|
3
|
+
-- Can be set at session creation time to override the agent's default thinking config.
|
|
4
|
+
|
|
5
|
+
ALTER TABLE sessions ADD COLUMN model_thinking TEXT;
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@newsails/veil-cli",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "VeilCLI - Enterprise autonomous agent runtime — local, API-first, multi-model",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=18.3.0"
|
|
8
|
+
},
|
|
9
|
+
"bin": {
|
|
10
|
+
"veil": "./cli/index.js"
|
|
11
|
+
},
|
|
12
|
+
"scripts": {
|
|
13
|
+
"start": "node cli/index.js start",
|
|
14
|
+
"test": "node test/smoke.js",
|
|
15
|
+
"test:smoke": "node test/smoke.js",
|
|
16
|
+
"test:integration": "node test/runner.js",
|
|
17
|
+
"test:integration:quick": "node test/runner.js --quick",
|
|
18
|
+
"test:all": "node test/smoke.js && node test/runner.js",
|
|
19
|
+
"fetch-models": "node scripts/fetch-models.js"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"ajv": "8.17.1",
|
|
23
|
+
"ajv-formats": "3.0.1",
|
|
24
|
+
"better-sqlite3": "11.10.0",
|
|
25
|
+
"cors": "2.8.5",
|
|
26
|
+
"express": "4.21.2",
|
|
27
|
+
"node-cron": "3.0.3",
|
|
28
|
+
"ws": "^8.19.0"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"title": "VeilCLI Agent Configuration",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"required": ["name", "model"],
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"properties": {
|
|
8
|
+
"name": { "type": "string", "minLength": 1 },
|
|
9
|
+
"description": { "type": "string" },
|
|
10
|
+
"model": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"minLength": 1,
|
|
13
|
+
"description": "Model identifier string e.g. 'anthropic/claude-3.5-sonnet'. Must be a string, NOT an object."
|
|
14
|
+
},
|
|
15
|
+
"temperature": { "type": "number", "minimum": 0, "maximum": 2 },
|
|
16
|
+
"reasoning": { "type": "string" },
|
|
17
|
+
"maxTokens": { "type": "integer", "minimum": 1 },
|
|
18
|
+
"memory": {
|
|
19
|
+
"type": "object",
|
|
20
|
+
"additionalProperties": false,
|
|
21
|
+
"properties": {
|
|
22
|
+
"enabled": { "type": "boolean" },
|
|
23
|
+
"maxLines": { "type": "integer", "minimum": 10 }
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"skillDiscovery": { "type": "boolean" },
|
|
27
|
+
"modes": {
|
|
28
|
+
"type": "object",
|
|
29
|
+
"additionalProperties": false,
|
|
30
|
+
"properties": {
|
|
31
|
+
"chat": { "$ref": "#/definitions/chatModeConfig" },
|
|
32
|
+
"task": { "$ref": "#/definitions/taskModeConfig" },
|
|
33
|
+
"subagent": { "$ref": "#/definitions/subagentModeConfig" },
|
|
34
|
+
"daemon": { "$ref": "#/definitions/daemonModeConfig" }
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"definitions": {
|
|
39
|
+
"permissionsConfig": {
|
|
40
|
+
"type": "object",
|
|
41
|
+
"additionalProperties": false,
|
|
42
|
+
"properties": {
|
|
43
|
+
"allow": { "type": "array", "items": { "type": "string" } },
|
|
44
|
+
"deny": { "type": "array", "items": { "type": "string" } }
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"baseModeConfig": {
|
|
48
|
+
"type": "object",
|
|
49
|
+
"required": ["enabled"],
|
|
50
|
+
"properties": {
|
|
51
|
+
"enabled": { "type": "boolean" },
|
|
52
|
+
"tools": { "type": "array", "items": { "type": "string" } },
|
|
53
|
+
"disallowedTools": { "type": "array", "items": { "type": "string" } },
|
|
54
|
+
"skills": { "type": "array", "items": { "type": "string" } },
|
|
55
|
+
"autoLoadSkills": { "type": "array", "items": { "type": "string" } },
|
|
56
|
+
"mcpServers": { "type": "array", "items": { "type": "string" } },
|
|
57
|
+
"allowedAgents": { "type": "array", "items": { "type": "string" } },
|
|
58
|
+
"disallowedAgents": { "type": "array", "items": { "type": "string" } },
|
|
59
|
+
"permissions": { "$ref": "#/definitions/permissionsConfig" }
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
"chatModeConfig": {
|
|
63
|
+
"allOf": [{ "$ref": "#/definitions/baseModeConfig" }],
|
|
64
|
+
"type": "object",
|
|
65
|
+
"additionalProperties": false,
|
|
66
|
+
"properties": {
|
|
67
|
+
"enabled": { "type": "boolean" },
|
|
68
|
+
"tools": { "type": "array", "items": { "type": "string" } },
|
|
69
|
+
"disallowedTools": { "type": "array", "items": { "type": "string" } },
|
|
70
|
+
"skills": { "type": "array", "items": { "type": "string" } },
|
|
71
|
+
"autoLoadSkills": { "type": "array", "items": { "type": "string" } },
|
|
72
|
+
"mcpServers": { "type": "array", "items": { "type": "string" } },
|
|
73
|
+
"allowedAgents": { "type": "array", "items": { "type": "string" } },
|
|
74
|
+
"disallowedAgents": { "type": "array", "items": { "type": "string" } },
|
|
75
|
+
"permissions": { "$ref": "#/definitions/permissionsConfig" }
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"taskModeConfig": {
|
|
79
|
+
"type": "object",
|
|
80
|
+
"required": ["enabled"],
|
|
81
|
+
"additionalProperties": false,
|
|
82
|
+
"properties": {
|
|
83
|
+
"enabled": { "type": "boolean" },
|
|
84
|
+
"tools": { "type": "array", "items": { "type": "string" } },
|
|
85
|
+
"disallowedTools": { "type": "array", "items": { "type": "string" } },
|
|
86
|
+
"skills": { "type": "array", "items": { "type": "string" } },
|
|
87
|
+
"autoLoadSkills": { "type": "array", "items": { "type": "string" } },
|
|
88
|
+
"mcpServers": { "type": "array", "items": { "type": "string" } },
|
|
89
|
+
"allowedAgents": { "type": "array", "items": { "type": "string" } },
|
|
90
|
+
"disallowedAgents": { "type": "array", "items": { "type": "string" } },
|
|
91
|
+
"permissions": { "$ref": "#/definitions/permissionsConfig" },
|
|
92
|
+
"maxIterations": { "type": "integer", "minimum": 1 },
|
|
93
|
+
"maxDurationSeconds": { "type": "integer", "minimum": 1 },
|
|
94
|
+
"onExhausted": { "type": "string", "enum": ["fail", "wait"] }
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
"subagentModeConfig": {
|
|
98
|
+
"type": "object",
|
|
99
|
+
"required": ["enabled"],
|
|
100
|
+
"additionalProperties": false,
|
|
101
|
+
"properties": {
|
|
102
|
+
"enabled": { "type": "boolean" },
|
|
103
|
+
"tools": { "type": "array", "items": { "type": "string" } },
|
|
104
|
+
"disallowedTools": { "type": "array", "items": { "type": "string" } },
|
|
105
|
+
"skills": { "type": "array", "items": { "type": "string" } },
|
|
106
|
+
"autoLoadSkills": { "type": "array", "items": { "type": "string" } },
|
|
107
|
+
"mcpServers": { "type": "array", "items": { "type": "string" } },
|
|
108
|
+
"allowedAgents": { "type": "array", "items": { "type": "string" } },
|
|
109
|
+
"disallowedAgents": { "type": "array", "items": { "type": "string" } },
|
|
110
|
+
"permissions": { "$ref": "#/definitions/permissionsConfig" },
|
|
111
|
+
"maxIterations": { "type": "integer", "minimum": 1 },
|
|
112
|
+
"maxDurationSeconds": { "type": "integer", "minimum": 1 }
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
"daemonModeConfig": {
|
|
116
|
+
"type": "object",
|
|
117
|
+
"required": ["enabled"],
|
|
118
|
+
"additionalProperties": false,
|
|
119
|
+
"properties": {
|
|
120
|
+
"enabled": { "type": "boolean" },
|
|
121
|
+
"tools": { "type": "array", "items": { "type": "string" } },
|
|
122
|
+
"disallowedTools": { "type": "array", "items": { "type": "string" } },
|
|
123
|
+
"skills": { "type": "array", "items": { "type": "string" } },
|
|
124
|
+
"autoLoadSkills": { "type": "array", "items": { "type": "string" } },
|
|
125
|
+
"mcpServers": { "type": "array", "items": { "type": "string" } },
|
|
126
|
+
"allowedAgents": { "type": "array", "items": { "type": "string" } },
|
|
127
|
+
"disallowedAgents": { "type": "array", "items": { "type": "string" } },
|
|
128
|
+
"permissions": { "$ref": "#/definitions/permissionsConfig" },
|
|
129
|
+
"cron": { "type": "string" },
|
|
130
|
+
"maxIterations": { "type": "integer", "minimum": 1 },
|
|
131
|
+
"maxDurationSeconds": { "type": "integer", "minimum": 1 },
|
|
132
|
+
"conflictPolicy": { "type": "string", "enum": ["skip", "queue", "restart"] },
|
|
133
|
+
"alertRouting": {
|
|
134
|
+
"oneOf": [
|
|
135
|
+
{ "type": "string" },
|
|
136
|
+
{ "type": "array", "items": { "type": "string" } }
|
|
137
|
+
]
|
|
138
|
+
},
|
|
139
|
+
"heartbeatFile": { "type": "string" }
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|