zouroboros-cli 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +64 -0
- package/dist/commands/agents.d.ts +2 -0
- package/dist/commands/agents.js +44 -0
- package/dist/commands/backup.d.ts +2 -0
- package/dist/commands/backup.js +122 -0
- package/dist/commands/config.d.ts +2 -0
- package/dist/commands/config.js +52 -0
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.js +11 -0
- package/dist/commands/heal.d.ts +2 -0
- package/dist/commands/heal.js +51 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.js +234 -0
- package/dist/commands/memory.d.ts +2 -0
- package/dist/commands/memory.js +32 -0
- package/dist/commands/migrate.d.ts +2 -0
- package/dist/commands/migrate.js +112 -0
- package/dist/commands/persona.d.ts +2 -0
- package/dist/commands/persona.js +45 -0
- package/dist/commands/skills.d.ts +2 -0
- package/dist/commands/skills.js +48 -0
- package/dist/commands/swarm.d.ts +2 -0
- package/dist/commands/swarm.js +32 -0
- package/dist/commands/tui.d.ts +2 -0
- package/dist/commands/tui.js +11 -0
- package/dist/commands/workflow.d.ts +3 -0
- package/dist/commands/workflow.js +87 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +83 -0
- package/dist/utils/doctor.d.ts +6 -0
- package/dist/utils/doctor.js +384 -0
- package/package.json +54 -0
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Doctor utility - Health check for Zouroboros components
|
|
3
|
+
*/
|
|
4
|
+
import { existsSync, mkdirSync, readFileSync } from 'fs';
|
|
5
|
+
import { execSync, spawnSync } from 'child_process';
|
|
6
|
+
import { join, dirname } from 'path';
|
|
7
|
+
import { homedir } from 'os';
|
|
8
|
+
import chalk from 'chalk';
|
|
9
|
+
import { saveConfig, DEFAULT_CONFIG, DEFAULT_MEMORY_DB_PATH } from 'zouroboros-core';
|
|
10
|
+
export async function runDoctor(options = {}) {
|
|
11
|
+
const checks = [];
|
|
12
|
+
// Check 1: Configuration exists
|
|
13
|
+
const configPath = join(homedir(), '.zouroboros', 'config.json');
|
|
14
|
+
if (existsSync(configPath)) {
|
|
15
|
+
checks.push({ name: 'Configuration', status: 'ok', message: `Found at ${configPath}` });
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
checks.push({
|
|
19
|
+
name: 'Configuration',
|
|
20
|
+
status: 'error',
|
|
21
|
+
message: 'Not found. Run: zouroboros init',
|
|
22
|
+
fixable: true,
|
|
23
|
+
fix: () => {
|
|
24
|
+
try {
|
|
25
|
+
const configDir = join(homedir(), '.zouroboros');
|
|
26
|
+
mkdirSync(configDir, { recursive: true });
|
|
27
|
+
const config = { ...DEFAULT_CONFIG, initializedAt: new Date().toISOString() };
|
|
28
|
+
saveConfig(config, configPath);
|
|
29
|
+
// Create workspace directories
|
|
30
|
+
for (const sub of ['logs', 'seeds', 'results']) {
|
|
31
|
+
mkdirSync(join(configDir, sub), { recursive: true });
|
|
32
|
+
}
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
// Check 2: Memory database
|
|
42
|
+
const memoryDb = DEFAULT_MEMORY_DB_PATH;
|
|
43
|
+
let factCount = 0;
|
|
44
|
+
let embeddingCount = 0;
|
|
45
|
+
if (existsSync(memoryDb)) {
|
|
46
|
+
try {
|
|
47
|
+
const result = execSync(`sqlite3 "${memoryDb}" "SELECT COUNT(*) FROM facts;"`, { encoding: 'utf-8' });
|
|
48
|
+
factCount = parseInt(result.trim());
|
|
49
|
+
try {
|
|
50
|
+
const embResult = execSync(`sqlite3 "${memoryDb}" "SELECT COUNT(*) FROM fact_embeddings;"`, { encoding: 'utf-8' });
|
|
51
|
+
embeddingCount = parseInt(embResult.trim());
|
|
52
|
+
}
|
|
53
|
+
catch { }
|
|
54
|
+
checks.push({ name: 'Memory Database', status: 'ok', message: `${factCount} facts, ${embeddingCount} embeddings` });
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
checks.push({ name: 'Memory Database', status: 'warning', message: 'Exists but schema may need migration' });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
checks.push({
|
|
62
|
+
name: 'Memory Database',
|
|
63
|
+
status: 'warning',
|
|
64
|
+
message: 'Not initialized. Will be created on first use.',
|
|
65
|
+
fixable: true,
|
|
66
|
+
fix: () => {
|
|
67
|
+
try {
|
|
68
|
+
const dbDir = dirname(memoryDb);
|
|
69
|
+
mkdirSync(dbDir, { recursive: true });
|
|
70
|
+
const schemaSql = `
|
|
71
|
+
PRAGMA journal_mode = WAL;
|
|
72
|
+
CREATE TABLE IF NOT EXISTS facts (id TEXT PRIMARY KEY, persona TEXT, entity TEXT NOT NULL, key TEXT, value TEXT NOT NULL, text TEXT NOT NULL, category TEXT DEFAULT 'fact', decay_class TEXT DEFAULT 'medium', importance REAL DEFAULT 1.0, source TEXT, created_at INTEGER DEFAULT (strftime('%s','now')), expires_at INTEGER, last_accessed INTEGER DEFAULT (strftime('%s','now')), confidence REAL DEFAULT 1.0, metadata TEXT);
|
|
73
|
+
CREATE TABLE IF NOT EXISTS fact_embeddings (fact_id TEXT PRIMARY KEY REFERENCES facts(id) ON DELETE CASCADE, embedding BLOB NOT NULL, model TEXT DEFAULT 'nomic-embed-text', created_at INTEGER DEFAULT (strftime('%s','now')));
|
|
74
|
+
CREATE TABLE IF NOT EXISTS episodes (id TEXT PRIMARY KEY, summary TEXT NOT NULL, outcome TEXT NOT NULL, happened_at INTEGER NOT NULL, duration_ms INTEGER, procedure_id TEXT, metadata TEXT, created_at INTEGER DEFAULT (strftime('%s','now')));
|
|
75
|
+
CREATE TABLE IF NOT EXISTS episode_entities (episode_id TEXT NOT NULL REFERENCES episodes(id) ON DELETE CASCADE, entity TEXT NOT NULL, PRIMARY KEY (episode_id, entity));
|
|
76
|
+
CREATE TABLE IF NOT EXISTS procedures (id TEXT PRIMARY KEY, name TEXT NOT NULL, version INTEGER DEFAULT 1, steps TEXT NOT NULL, success_count INTEGER DEFAULT 0, failure_count INTEGER DEFAULT 0, evolved_from TEXT, created_at INTEGER DEFAULT (strftime('%s','now')));
|
|
77
|
+
CREATE TABLE IF NOT EXISTS open_loops (id TEXT PRIMARY KEY, summary TEXT NOT NULL, entity TEXT NOT NULL, status TEXT DEFAULT 'open', priority INTEGER DEFAULT 1, created_at INTEGER DEFAULT (strftime('%s','now')), resolved_at INTEGER);
|
|
78
|
+
CREATE TABLE IF NOT EXISTS continuation_context (id TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, last_summary TEXT NOT NULL, open_loop_ids TEXT, entity_stack TEXT, last_agent TEXT, updated_at INTEGER DEFAULT (strftime('%s','now')));
|
|
79
|
+
CREATE TABLE IF NOT EXISTS cognitive_profiles (entity TEXT PRIMARY KEY, traits TEXT, preferences TEXT, interaction_count INTEGER DEFAULT 0, last_interaction INTEGER, created_at INTEGER DEFAULT (strftime('%s','now')));
|
|
80
|
+
CREATE TABLE IF NOT EXISTS _migrations (id INTEGER PRIMARY KEY, name TEXT NOT NULL, applied_at INTEGER DEFAULT (strftime('%s','now')));
|
|
81
|
+
CREATE INDEX IF NOT EXISTS idx_facts_entity_key ON facts(entity, key);
|
|
82
|
+
CREATE INDEX IF NOT EXISTS idx_facts_decay ON facts(decay_class, expires_at);
|
|
83
|
+
CREATE INDEX IF NOT EXISTS idx_facts_category ON facts(category);
|
|
84
|
+
CREATE INDEX IF NOT EXISTS idx_episodes_happened ON episodes(happened_at);
|
|
85
|
+
CREATE INDEX IF NOT EXISTS idx_episodes_outcome ON episodes(outcome);
|
|
86
|
+
CREATE INDEX IF NOT EXISTS idx_episode_entities ON episode_entities(entity);
|
|
87
|
+
CREATE INDEX IF NOT EXISTS idx_open_loops_entity ON open_loops(entity, status);
|
|
88
|
+
`;
|
|
89
|
+
execSync(`sqlite3 "${memoryDb}" "${schemaSql.replace(/"/g, '\\"')}"`, {
|
|
90
|
+
shell: '/bin/bash',
|
|
91
|
+
stdio: 'pipe',
|
|
92
|
+
});
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
// Check 3: Ollama (for embeddings)
|
|
102
|
+
let ollamaRunning = false;
|
|
103
|
+
try {
|
|
104
|
+
execSync('curl -sf http://localhost:11434/api/tags > /dev/null', { timeout: 5000 });
|
|
105
|
+
ollamaRunning = true;
|
|
106
|
+
checks.push({ name: 'Ollama', status: 'ok', message: 'Running on localhost:11434' });
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
// Check if ollama is installed but not running
|
|
110
|
+
let ollamaInstalled = false;
|
|
111
|
+
try {
|
|
112
|
+
execSync('command -v ollama', { stdio: 'pipe' });
|
|
113
|
+
ollamaInstalled = true;
|
|
114
|
+
}
|
|
115
|
+
catch { }
|
|
116
|
+
checks.push({
|
|
117
|
+
name: 'Ollama',
|
|
118
|
+
status: 'warning',
|
|
119
|
+
message: ollamaInstalled
|
|
120
|
+
? 'Installed but not running. Start with: ollama serve'
|
|
121
|
+
: 'Not installed. Vector search will be limited.',
|
|
122
|
+
fixable: true,
|
|
123
|
+
fix: () => {
|
|
124
|
+
try {
|
|
125
|
+
if (!ollamaInstalled) {
|
|
126
|
+
console.log(chalk.gray(' Installing Ollama...'));
|
|
127
|
+
execSync('curl -fsSL https://ollama.com/install.sh | sh', {
|
|
128
|
+
stdio: 'inherit',
|
|
129
|
+
timeout: 120000,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
// Start ollama serve in background
|
|
133
|
+
console.log(chalk.gray(' Starting Ollama...'));
|
|
134
|
+
spawnSync('sh', ['-c', 'nohup ollama serve > /dev/null 2>&1 &'], { stdio: 'ignore' });
|
|
135
|
+
execSync('sleep 3');
|
|
136
|
+
// Pull embedding model
|
|
137
|
+
console.log(chalk.gray(' Pulling nomic-embed-text model...'));
|
|
138
|
+
execSync('ollama pull nomic-embed-text', {
|
|
139
|
+
stdio: 'inherit',
|
|
140
|
+
timeout: 300000,
|
|
141
|
+
});
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
// Check 4: Swarm executors
|
|
151
|
+
const executorInfo = {
|
|
152
|
+
'claude-code': { binary: 'claude', install: 'npm install -g @anthropic-ai/claude-code' },
|
|
153
|
+
'codex': { binary: 'codex', install: 'npm install -g @openai/codex' },
|
|
154
|
+
'gemini': { binary: 'gemini', install: 'npm install -g @google/gemini-cli' },
|
|
155
|
+
'hermes': { binary: 'hermes', install: 'pip install hermes-agent && hermes setup' },
|
|
156
|
+
};
|
|
157
|
+
const executors = Object.keys(executorInfo);
|
|
158
|
+
const availableExecutors = [];
|
|
159
|
+
const missingExecutors = [];
|
|
160
|
+
for (const executor of executors) {
|
|
161
|
+
const { binary } = executorInfo[executor];
|
|
162
|
+
try {
|
|
163
|
+
execSync(`command -v ${binary} > /dev/null 2>&1`);
|
|
164
|
+
availableExecutors.push(executor);
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
missingExecutors.push(executor);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
if (availableExecutors.length === executors.length) {
|
|
171
|
+
checks.push({
|
|
172
|
+
name: 'Swarm Executors',
|
|
173
|
+
status: 'ok',
|
|
174
|
+
message: `${availableExecutors.length}/${executors.length} available: ${availableExecutors.join(', ')}`
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
else if (availableExecutors.length > 0) {
|
|
178
|
+
checks.push({
|
|
179
|
+
name: 'Swarm Executors',
|
|
180
|
+
status: 'warning',
|
|
181
|
+
message: `${availableExecutors.length}/${executors.length} available. Missing: ${missingExecutors.join(', ')}`,
|
|
182
|
+
fixable: true,
|
|
183
|
+
fix: () => {
|
|
184
|
+
let allFixed = true;
|
|
185
|
+
for (const executor of missingExecutors) {
|
|
186
|
+
const info = executorInfo[executor];
|
|
187
|
+
try {
|
|
188
|
+
console.log(chalk.gray(` Installing ${executor} (${info.install})...`));
|
|
189
|
+
execSync(info.install, { stdio: 'inherit', timeout: 120000 });
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
console.log(chalk.yellow(` ⚠ Could not auto-install ${executor}. Run manually: ${info.install}`));
|
|
193
|
+
allFixed = false;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return allFixed;
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
checks.push({
|
|
202
|
+
name: 'Swarm Executors',
|
|
203
|
+
status: 'error',
|
|
204
|
+
message: 'None found. Install at least one executor.',
|
|
205
|
+
fixable: true,
|
|
206
|
+
fix: () => {
|
|
207
|
+
const info = executorInfo['claude-code'];
|
|
208
|
+
try {
|
|
209
|
+
console.log(chalk.gray(` Installing claude-code (${info.install})...`));
|
|
210
|
+
execSync(info.install, { stdio: 'inherit', timeout: 120000 });
|
|
211
|
+
return true;
|
|
212
|
+
}
|
|
213
|
+
catch {
|
|
214
|
+
console.log(chalk.yellow(` ⚠ Could not auto-install. Run manually: ${info.install}`));
|
|
215
|
+
return false;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
// Check 5: Git
|
|
221
|
+
try {
|
|
222
|
+
execSync('command -v git > /dev/null 2>&1');
|
|
223
|
+
checks.push({ name: 'Git', status: 'ok', message: 'Available' });
|
|
224
|
+
}
|
|
225
|
+
catch {
|
|
226
|
+
checks.push({ name: 'Git', status: 'error', message: 'Not found. Required for autoloop.' });
|
|
227
|
+
}
|
|
228
|
+
// Check 6: Scheduled Agents (from agents/manifest.json)
|
|
229
|
+
// Agent IDs are instance-specific — no REST API to verify from CLI.
|
|
230
|
+
// Check a local marker file written after agent creation.
|
|
231
|
+
{
|
|
232
|
+
const monorepoRoot = join(__dirname, '..', '..', '..');
|
|
233
|
+
const manifestPath = join(monorepoRoot, 'agents', 'manifest.json');
|
|
234
|
+
const markerPath = join(homedir(), '.zouroboros', 'agents-registered.json');
|
|
235
|
+
if (existsSync(manifestPath)) {
|
|
236
|
+
try {
|
|
237
|
+
const manifest = JSON.parse(readFileSync(manifestPath, 'utf-8'));
|
|
238
|
+
const agentEntries = Object.entries(manifest.agents || {});
|
|
239
|
+
const total = agentEntries.length;
|
|
240
|
+
if (existsSync(markerPath)) {
|
|
241
|
+
try {
|
|
242
|
+
const marker = JSON.parse(readFileSync(markerPath, 'utf-8'));
|
|
243
|
+
const count = Array.isArray(marker.agents) ? marker.agents.length : 0;
|
|
244
|
+
if (count >= total) {
|
|
245
|
+
checks.push({
|
|
246
|
+
name: 'Scheduled Agents',
|
|
247
|
+
status: 'ok',
|
|
248
|
+
message: `${count}/${total} registered (verified at ${marker.registeredAt || 'unknown'})`
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
checks.push({
|
|
253
|
+
name: 'Scheduled Agents',
|
|
254
|
+
status: 'warning',
|
|
255
|
+
message: `${count}/${total} registered. Run: zouroboros agents sync`
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
catch {
|
|
260
|
+
checks.push({
|
|
261
|
+
name: 'Scheduled Agents',
|
|
262
|
+
status: 'warning',
|
|
263
|
+
message: `Marker file corrupt. Run: zouroboros agents sync`
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
checks.push({
|
|
269
|
+
name: 'Scheduled Agents',
|
|
270
|
+
status: 'warning',
|
|
271
|
+
message: `${total} agents defined. After creating in Zo Chat, run: zouroboros agents sync`
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
catch {
|
|
276
|
+
checks.push({
|
|
277
|
+
name: 'Scheduled Agents',
|
|
278
|
+
status: 'warning',
|
|
279
|
+
message: 'Could not parse agents/manifest.json'
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
checks.push({
|
|
285
|
+
name: 'Scheduled Agents',
|
|
286
|
+
status: 'warning',
|
|
287
|
+
message: 'agents/manifest.json not found'
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
// Check 7: Vector DB migration readiness (MEM-201)
|
|
292
|
+
if (factCount > 0) {
|
|
293
|
+
const EARLY_WARNING = 2500;
|
|
294
|
+
const RECOMMEND_THRESHOLD = 5000;
|
|
295
|
+
const URGENT_THRESHOLD = 10000;
|
|
296
|
+
let dbSizeKb = 0;
|
|
297
|
+
try {
|
|
298
|
+
const sizeResult = execSync(`stat -c%s "${memoryDb}" 2>/dev/null || stat -f%z "${memoryDb}"`, { encoding: 'utf-8' });
|
|
299
|
+
dbSizeKb = Math.round(parseInt(sizeResult.trim()) / 1024);
|
|
300
|
+
}
|
|
301
|
+
catch { }
|
|
302
|
+
if (factCount >= URGENT_THRESHOLD) {
|
|
303
|
+
checks.push({
|
|
304
|
+
name: 'Vector Scale',
|
|
305
|
+
status: 'error',
|
|
306
|
+
message: `${factCount} facts (${dbSizeKb}KB) — brute-force scan degraded. Migrate to sqlite-vec. See packages/memory/MIGRATION.md`,
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
else if (factCount >= RECOMMEND_THRESHOLD) {
|
|
310
|
+
checks.push({
|
|
311
|
+
name: 'Vector Scale',
|
|
312
|
+
status: 'warning',
|
|
313
|
+
message: `${factCount} facts (${dbSizeKb}KB) — approaching scale limit. Plan sqlite-vec migration. See packages/memory/MIGRATION.md`,
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
else if (factCount >= EARLY_WARNING) {
|
|
317
|
+
checks.push({
|
|
318
|
+
name: 'Vector Scale',
|
|
319
|
+
status: 'warning',
|
|
320
|
+
message: `${factCount} facts (${dbSizeKb}KB) — early warning. Monitor growth rate.`,
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
checks.push({
|
|
325
|
+
name: 'Vector Scale',
|
|
326
|
+
status: 'ok',
|
|
327
|
+
message: `${factCount} facts (${dbSizeKb}KB) — well within brute-force scan limits`,
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
// Print results
|
|
332
|
+
console.log('Component Status:');
|
|
333
|
+
console.log('─'.repeat(60));
|
|
334
|
+
for (const check of checks) {
|
|
335
|
+
const icon = check.status === 'ok' ? chalk.green('✓') :
|
|
336
|
+
check.status === 'warning' ? chalk.yellow('⚠') : chalk.red('✗');
|
|
337
|
+
const name = chalk.bold(check.name.padEnd(20));
|
|
338
|
+
const message = check.status === 'error' ? chalk.red(check.message) :
|
|
339
|
+
check.status === 'warning' ? chalk.yellow(check.message) :
|
|
340
|
+
chalk.gray(check.message);
|
|
341
|
+
console.log(`${icon} ${name} ${message}`);
|
|
342
|
+
}
|
|
343
|
+
// Attempt fixes if requested
|
|
344
|
+
if (options.fix) {
|
|
345
|
+
const fixable = checks.filter(c => c.fixable && c.status !== 'ok' && c.fix);
|
|
346
|
+
if (fixable.length > 0) {
|
|
347
|
+
console.log(chalk.cyan('\n🔧 Attempting fixes...\n'));
|
|
348
|
+
for (const check of fixable) {
|
|
349
|
+
process.stdout.write(` Fixing ${check.name}... `);
|
|
350
|
+
const success = check.fix();
|
|
351
|
+
if (success) {
|
|
352
|
+
console.log(chalk.green('✅ Fixed'));
|
|
353
|
+
}
|
|
354
|
+
else {
|
|
355
|
+
console.log(chalk.red('❌ Failed'));
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
// Re-run health check to show updated status
|
|
359
|
+
console.log(chalk.cyan('\n🔄 Re-checking...\n'));
|
|
360
|
+
return runDoctor({ fix: false });
|
|
361
|
+
}
|
|
362
|
+
else {
|
|
363
|
+
console.log(chalk.gray('\nNo fixable issues found.'));
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
const hasErrors = checks.some(c => c.status === 'error');
|
|
367
|
+
const hasWarnings = checks.some(c => c.status === 'warning');
|
|
368
|
+
if (hasErrors) {
|
|
369
|
+
console.log(chalk.red('\n⚠ Some issues found'));
|
|
370
|
+
if (checks.some(c => c.fixable && c.status !== 'ok')) {
|
|
371
|
+
console.log(chalk.gray(' Run ' + chalk.yellow('zouroboros doctor --fix') + ' to auto-repair\n'));
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
else if (hasWarnings) {
|
|
375
|
+
console.log(chalk.yellow('\n⚠ Some issues found'));
|
|
376
|
+
if (checks.some(c => c.fixable && c.status !== 'ok')) {
|
|
377
|
+
console.log(chalk.gray(' Run ' + chalk.yellow('zouroboros doctor --fix') + ' to auto-repair\n'));
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
console.log(chalk.green('\n✅ All systems healthy\n'));
|
|
382
|
+
}
|
|
383
|
+
return !hasErrors;
|
|
384
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "zouroboros-cli",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Unified CLI for Zouroboros",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist/",
|
|
16
|
+
"README.md"
|
|
17
|
+
],
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "https://github.com/marlandoj/zouroboros.git",
|
|
21
|
+
"directory": "cli"
|
|
22
|
+
},
|
|
23
|
+
"bin": {
|
|
24
|
+
"zouroboros": "./dist/index.js"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"commander": "^11.0.0",
|
|
28
|
+
"chalk": "^5.3.0",
|
|
29
|
+
"zouroboros-core": "2.0.0",
|
|
30
|
+
"zouroboros-memory": "3.0.0",
|
|
31
|
+
"zouroboros-swarm": "5.0.0",
|
|
32
|
+
"zouroboros-personas": "2.0.0",
|
|
33
|
+
"zouroboros-selfheal": "2.0.0",
|
|
34
|
+
"zouroboros-workflow": "2.0.0"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/bun": "latest",
|
|
38
|
+
"@types/node": "^20.0.0",
|
|
39
|
+
"typescript": "^5.3.0"
|
|
40
|
+
},
|
|
41
|
+
"keywords": [
|
|
42
|
+
"cli",
|
|
43
|
+
"zouroboros",
|
|
44
|
+
"ai",
|
|
45
|
+
"orchestration"
|
|
46
|
+
],
|
|
47
|
+
"license": "MIT",
|
|
48
|
+
"author": "marlandoj.zo.computer",
|
|
49
|
+
"scripts": {
|
|
50
|
+
"build": "tsc",
|
|
51
|
+
"dev": "tsc --watch",
|
|
52
|
+
"test": "echo \"No tests yet\" && exit 0"
|
|
53
|
+
}
|
|
54
|
+
}
|