@johpaz/hive 1.1.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/CONTRIBUTING.md +44 -0
- package/README.md +310 -0
- package/package.json +96 -0
- package/packages/cli/package.json +28 -0
- package/packages/cli/src/commands/agent-run.ts +168 -0
- package/packages/cli/src/commands/agents.ts +398 -0
- package/packages/cli/src/commands/chat.ts +142 -0
- package/packages/cli/src/commands/config.ts +50 -0
- package/packages/cli/src/commands/cron.ts +161 -0
- package/packages/cli/src/commands/dev.ts +95 -0
- package/packages/cli/src/commands/doctor.ts +133 -0
- package/packages/cli/src/commands/gateway.ts +443 -0
- package/packages/cli/src/commands/logs.ts +57 -0
- package/packages/cli/src/commands/mcp.ts +175 -0
- package/packages/cli/src/commands/message.ts +77 -0
- package/packages/cli/src/commands/onboard.ts +1868 -0
- package/packages/cli/src/commands/security.ts +144 -0
- package/packages/cli/src/commands/service.ts +50 -0
- package/packages/cli/src/commands/sessions.ts +116 -0
- package/packages/cli/src/commands/skills.ts +187 -0
- package/packages/cli/src/commands/update.ts +25 -0
- package/packages/cli/src/index.ts +185 -0
- package/packages/cli/src/utils/token.ts +6 -0
- package/packages/code-bridge/README.md +78 -0
- package/packages/code-bridge/package.json +18 -0
- package/packages/code-bridge/src/index.ts +95 -0
- package/packages/code-bridge/src/process-manager.ts +212 -0
- package/packages/code-bridge/src/schemas.ts +133 -0
- package/packages/core/package.json +46 -0
- package/packages/core/src/agent/agent-loop.ts +369 -0
- package/packages/core/src/agent/compaction.ts +140 -0
- package/packages/core/src/agent/context-compiler.ts +378 -0
- package/packages/core/src/agent/context-guard.ts +91 -0
- package/packages/core/src/agent/context.ts +138 -0
- package/packages/core/src/agent/conversation-store.ts +198 -0
- package/packages/core/src/agent/curator.ts +158 -0
- package/packages/core/src/agent/hooks.ts +166 -0
- package/packages/core/src/agent/index.ts +116 -0
- package/packages/core/src/agent/llm-client.ts +503 -0
- package/packages/core/src/agent/native-tools.ts +505 -0
- package/packages/core/src/agent/prompt-builder.ts +532 -0
- package/packages/core/src/agent/providers/index.ts +167 -0
- package/packages/core/src/agent/providers.ts +1 -0
- package/packages/core/src/agent/reflector.ts +170 -0
- package/packages/core/src/agent/service.ts +64 -0
- package/packages/core/src/agent/stuck-loop.ts +133 -0
- package/packages/core/src/agent/supervisor.ts +39 -0
- package/packages/core/src/agent/tracer.ts +102 -0
- package/packages/core/src/agent/workspace.ts +110 -0
- package/packages/core/src/canvas/canvas-manager.test.ts +161 -0
- package/packages/core/src/canvas/canvas-manager.ts +319 -0
- package/packages/core/src/canvas/canvas-tools.ts +420 -0
- package/packages/core/src/canvas/emitter.ts +115 -0
- package/packages/core/src/canvas/index.ts +2 -0
- package/packages/core/src/channels/base.ts +138 -0
- package/packages/core/src/channels/discord.ts +260 -0
- package/packages/core/src/channels/index.ts +7 -0
- package/packages/core/src/channels/manager.ts +383 -0
- package/packages/core/src/channels/slack.ts +287 -0
- package/packages/core/src/channels/telegram.ts +502 -0
- package/packages/core/src/channels/webchat.ts +128 -0
- package/packages/core/src/channels/whatsapp.ts +375 -0
- package/packages/core/src/config/index.ts +12 -0
- package/packages/core/src/config/loader.ts +529 -0
- package/packages/core/src/events/event-bus.ts +169 -0
- package/packages/core/src/gateway/index.ts +5 -0
- package/packages/core/src/gateway/initializer.ts +290 -0
- package/packages/core/src/gateway/lane-queue.ts +169 -0
- package/packages/core/src/gateway/resolver.ts +108 -0
- package/packages/core/src/gateway/router.ts +124 -0
- package/packages/core/src/gateway/server.ts +3317 -0
- package/packages/core/src/gateway/session.ts +95 -0
- package/packages/core/src/gateway/slash-commands.ts +192 -0
- package/packages/core/src/heartbeat/index.ts +157 -0
- package/packages/core/src/index.ts +19 -0
- package/packages/core/src/integrations/catalog.ts +286 -0
- package/packages/core/src/integrations/env.ts +64 -0
- package/packages/core/src/integrations/index.ts +2 -0
- package/packages/core/src/memory/index.ts +1 -0
- package/packages/core/src/memory/notes.ts +68 -0
- package/packages/core/src/plugins/api.ts +128 -0
- package/packages/core/src/plugins/index.ts +2 -0
- package/packages/core/src/plugins/loader.ts +365 -0
- package/packages/core/src/resilience/circuit-breaker.ts +225 -0
- package/packages/core/src/security/google-chat.ts +269 -0
- package/packages/core/src/security/index.ts +192 -0
- package/packages/core/src/security/pairing.ts +250 -0
- package/packages/core/src/security/rate-limit.ts +270 -0
- package/packages/core/src/security/signal.ts +321 -0
- package/packages/core/src/state/store.ts +312 -0
- package/packages/core/src/storage/bun-sqlite-store.ts +188 -0
- package/packages/core/src/storage/crypto.ts +101 -0
- package/packages/core/src/storage/db-context.ts +333 -0
- package/packages/core/src/storage/onboarding.ts +1087 -0
- package/packages/core/src/storage/schema.ts +541 -0
- package/packages/core/src/storage/seed.ts +571 -0
- package/packages/core/src/storage/sqlite.ts +387 -0
- package/packages/core/src/storage/usage.ts +212 -0
- package/packages/core/src/tools/bridge-events.ts +74 -0
- package/packages/core/src/tools/browser.ts +275 -0
- package/packages/core/src/tools/codebridge.ts +421 -0
- package/packages/core/src/tools/coordinator-tools.ts +179 -0
- package/packages/core/src/tools/cron.ts +611 -0
- package/packages/core/src/tools/exec.ts +140 -0
- package/packages/core/src/tools/fs.ts +364 -0
- package/packages/core/src/tools/index.ts +12 -0
- package/packages/core/src/tools/memory.ts +176 -0
- package/packages/core/src/tools/notify.ts +113 -0
- package/packages/core/src/tools/project-management.ts +376 -0
- package/packages/core/src/tools/project.ts +375 -0
- package/packages/core/src/tools/read.ts +158 -0
- package/packages/core/src/tools/web.ts +436 -0
- package/packages/core/src/tools/workspace.ts +171 -0
- package/packages/core/src/utils/benchmark.ts +80 -0
- package/packages/core/src/utils/crypto.ts +73 -0
- package/packages/core/src/utils/date.ts +42 -0
- package/packages/core/src/utils/index.ts +4 -0
- package/packages/core/src/utils/logger.ts +388 -0
- package/packages/core/src/utils/retry.ts +70 -0
- package/packages/core/src/voice/index.ts +583 -0
- package/packages/core/tsconfig.json +9 -0
- package/packages/mcp/package.json +26 -0
- package/packages/mcp/src/config.ts +13 -0
- package/packages/mcp/src/index.ts +1 -0
- package/packages/mcp/src/logger.ts +42 -0
- package/packages/mcp/src/manager.ts +434 -0
- package/packages/mcp/src/transports/index.ts +67 -0
- package/packages/mcp/src/transports/sse.ts +241 -0
- package/packages/mcp/src/transports/websocket.ts +159 -0
- package/packages/skills/package.json +21 -0
- package/packages/skills/src/bundled/agent_management/SKILL.md +24 -0
- package/packages/skills/src/bundled/browser_automation/SKILL.md +30 -0
- package/packages/skills/src/bundled/context_compact/SKILL.md +35 -0
- package/packages/skills/src/bundled/cron_manager/SKILL.md +52 -0
- package/packages/skills/src/bundled/file_manager/SKILL.md +76 -0
- package/packages/skills/src/bundled/http_client/SKILL.md +24 -0
- package/packages/skills/src/bundled/memory/SKILL.md +42 -0
- package/packages/skills/src/bundled/project_management/SKILL.md +26 -0
- package/packages/skills/src/bundled/shell/SKILL.md +43 -0
- package/packages/skills/src/bundled/system_notify/SKILL.md +52 -0
- package/packages/skills/src/bundled/voice/SKILL.md +25 -0
- package/packages/skills/src/bundled/web_search/SKILL.md +29 -0
- package/packages/skills/src/index.ts +1 -0
- package/packages/skills/src/loader.ts +282 -0
- package/packages/tools/package.json +43 -0
- package/packages/tools/src/browser/browser.test.ts +111 -0
- package/packages/tools/src/browser/index.ts +272 -0
- package/packages/tools/src/canvas/index.ts +220 -0
- package/packages/tools/src/cron/cron.test.ts +164 -0
- package/packages/tools/src/cron/index.ts +304 -0
- package/packages/tools/src/filesystem/filesystem.test.ts +240 -0
- package/packages/tools/src/filesystem/index.ts +379 -0
- package/packages/tools/src/git/index.ts +239 -0
- package/packages/tools/src/index.ts +4 -0
- package/packages/tools/src/shell/detect-env.ts +70 -0
- package/packages/tools/tsconfig.json +9 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import * as p from "@clack/prompts";
|
|
2
|
+
import * as fs from "fs";
|
|
3
|
+
import * as path from "path";
|
|
4
|
+
import { getHiveDir } from "@johpaz/hive-core/config/loader";
|
|
5
|
+
|
|
6
|
+
const getHiveDirConst = () => getHiveDir();
|
|
7
|
+
const getCronDir = () => path.join(getHiveDirConst(), "cron");
|
|
8
|
+
const CRON_DB = path.join(getCronDir(), "jobs.json");
|
|
9
|
+
|
|
10
|
+
interface CronJob {
|
|
11
|
+
id: string;
|
|
12
|
+
schedule: string;
|
|
13
|
+
command: string;
|
|
14
|
+
enabled: boolean;
|
|
15
|
+
lastRun?: string;
|
|
16
|
+
nextRun?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function loadJobs(): CronJob[] {
|
|
20
|
+
if (!fs.existsSync(CRON_DB)) return [];
|
|
21
|
+
try {
|
|
22
|
+
return JSON.parse(fs.readFileSync(CRON_DB, "utf-8"));
|
|
23
|
+
} catch {
|
|
24
|
+
return [];
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function saveJobs(jobs: CronJob[]): void {
|
|
29
|
+
if (!fs.existsSync(getCronDir())) {
|
|
30
|
+
fs.mkdirSync(getCronDir(), { recursive: true });
|
|
31
|
+
}
|
|
32
|
+
fs.writeFileSync(CRON_DB, JSON.stringify(jobs, null, 2));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export async function cron(subcommand: string | undefined, args: string[]): Promise<void> {
|
|
36
|
+
switch (subcommand) {
|
|
37
|
+
case "list":
|
|
38
|
+
await listCron();
|
|
39
|
+
break;
|
|
40
|
+
case "add":
|
|
41
|
+
await addCron();
|
|
42
|
+
break;
|
|
43
|
+
case "remove":
|
|
44
|
+
await removeCron(args[0]);
|
|
45
|
+
break;
|
|
46
|
+
case "logs":
|
|
47
|
+
await cronLogs();
|
|
48
|
+
break;
|
|
49
|
+
default:
|
|
50
|
+
console.log(`
|
|
51
|
+
Usage: hive cron <command>
|
|
52
|
+
|
|
53
|
+
Commands:
|
|
54
|
+
list Listar cron jobs
|
|
55
|
+
add Añadir cron job
|
|
56
|
+
remove <id> Eliminar cron job
|
|
57
|
+
logs Ver logs de cron
|
|
58
|
+
`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function listCron(): Promise<void> {
|
|
63
|
+
const jobs = loadJobs();
|
|
64
|
+
|
|
65
|
+
if (jobs.length === 0) {
|
|
66
|
+
console.log("No hay cron jobs configurados");
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
console.log("\n⏰ Cron Jobs:\n");
|
|
71
|
+
|
|
72
|
+
for (const job of jobs) {
|
|
73
|
+
const status = job.enabled ? "✅ Activo" : "⏸️ Pausado";
|
|
74
|
+
console.log(` ${job.id}`);
|
|
75
|
+
console.log(` Estado: ${status}`);
|
|
76
|
+
console.log(` Schedule: ${job.schedule}`);
|
|
77
|
+
console.log(` Comando: ${job.command}`);
|
|
78
|
+
if (job.lastRun) {
|
|
79
|
+
console.log(` Última: ${job.lastRun}`);
|
|
80
|
+
}
|
|
81
|
+
console.log();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async function addCron(): Promise<void> {
|
|
86
|
+
const idValue = await p.text({
|
|
87
|
+
message: "ID del cron job:",
|
|
88
|
+
placeholder: "daily-report",
|
|
89
|
+
validate: (v) => (!v ? "El ID es requerido" : undefined),
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
if (p.isCancel(idValue)) {
|
|
93
|
+
p.cancel("Cancelado");
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const scheduleValue = await p.text({
|
|
98
|
+
message: "Schedule (cron expression):",
|
|
99
|
+
placeholder: "0 9 * * *",
|
|
100
|
+
validate: (v) => (!v ? "El schedule es requerido" : undefined),
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
if (p.isCancel(scheduleValue)) {
|
|
104
|
+
p.cancel("Cancelado");
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const commandValue = await p.text({
|
|
109
|
+
message: "Comando a ejecutar:",
|
|
110
|
+
placeholder: "hive chat --agent work 'Genera el reporte diario'",
|
|
111
|
+
validate: (v) => (!v ? "El comando es requerido" : undefined),
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
if (p.isCancel(commandValue)) {
|
|
115
|
+
p.cancel("Cancelado");
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const jobs = loadJobs();
|
|
120
|
+
jobs.push({
|
|
121
|
+
id: idValue as string,
|
|
122
|
+
schedule: scheduleValue as string,
|
|
123
|
+
command: commandValue as string,
|
|
124
|
+
enabled: true,
|
|
125
|
+
});
|
|
126
|
+
saveJobs(jobs);
|
|
127
|
+
|
|
128
|
+
console.log(`✅ Cron job "${idValue}" creado`);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async function removeCron(id: string | undefined): Promise<void> {
|
|
132
|
+
if (!id) {
|
|
133
|
+
console.log("❌ Especifica el ID: hive cron remove <id>");
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const jobs = loadJobs();
|
|
138
|
+
const index = jobs.findIndex((j) => j.id === id);
|
|
139
|
+
|
|
140
|
+
if (index === -1) {
|
|
141
|
+
console.log(`❌ Cron job no encontrado: ${id}`);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
jobs.splice(index, 1);
|
|
146
|
+
saveJobs(jobs);
|
|
147
|
+
|
|
148
|
+
console.log(`✅ Cron job "${id}" eliminado`);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
async function cronLogs(): Promise<void> {
|
|
152
|
+
const logFile = path.join(getCronDir(), "cron.log");
|
|
153
|
+
|
|
154
|
+
if (!fs.existsSync(logFile)) {
|
|
155
|
+
console.log("No hay logs de cron");
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const content = fs.readFileSync(logFile, "utf-8");
|
|
160
|
+
console.log(content);
|
|
161
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import * as p from "@clack/prompts";
|
|
2
|
+
import * as fs from "fs";
|
|
3
|
+
import * as path from "path";
|
|
4
|
+
import { getHiveDir } from "../../../core/src/config/loader";
|
|
5
|
+
|
|
6
|
+
function showDevBanner(): void {
|
|
7
|
+
const hiveDir = getHiveDir();
|
|
8
|
+
console.log(`
|
|
9
|
+
╔══════════════════════════════════════════════════╗
|
|
10
|
+
║ 🔧 HIVE DEV MODE ║
|
|
11
|
+
║ Configuración en: ${hiveDir}
|
|
12
|
+
║ Tu configuración real en ~/.hive/ no será modificada. ║
|
|
13
|
+
╚══════════════════════════════════════════════════╝
|
|
14
|
+
`);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export async function dev(): Promise<void> {
|
|
18
|
+
const hiveDir = getHiveDir();
|
|
19
|
+
const dbPath = path.join(hiveDir, "data", "hive.db");
|
|
20
|
+
|
|
21
|
+
// Create hiveDir if it doesn't exist
|
|
22
|
+
if (!fs.existsSync(hiveDir)) {
|
|
23
|
+
fs.mkdirSync(hiveDir, { recursive: true });
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// ── Step 1: Si existe sesión anterior, preguntar si limpiar ──
|
|
27
|
+
if (fs.readdirSync(hiveDir).length > 0) {
|
|
28
|
+
const stats = fs.statSync(hiveDir);
|
|
29
|
+
const hoursAgo = Math.floor((Date.now() - stats.mtime.getTime()) / (1000 * 60 * 60));
|
|
30
|
+
const timeAgo = hoursAgo < 1 ? "hace unos minutos" : `hace ${hoursAgo} hora${hoursAgo > 1 ? "s" : ""}`;
|
|
31
|
+
|
|
32
|
+
console.log(`\n⚠️ Se encontró una sesión de dev anterior en ${hiveDir}\n Última configuración: ${timeAgo}\n`);
|
|
33
|
+
|
|
34
|
+
const shouldClean = await p.confirm({
|
|
35
|
+
message: "¿Limpiar y empezar de nuevo?",
|
|
36
|
+
initialValue: true,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
if (p.isCancel(shouldClean)) {
|
|
40
|
+
p.cancel("Operación cancelada.");
|
|
41
|
+
process.exit(0);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (shouldClean) {
|
|
45
|
+
console.log("🧹 Limpiando entorno de dev anterior...");
|
|
46
|
+
fs.rmSync(hiveDir, { recursive: true, force: true });
|
|
47
|
+
fs.mkdirSync(hiveDir, { recursive: true });
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
showDevBanner();
|
|
52
|
+
|
|
53
|
+
// ── Step 2: Verificar si ya hay un agente configurado ──
|
|
54
|
+
let hasCompletedAgent = false;
|
|
55
|
+
|
|
56
|
+
if (fs.existsSync(dbPath)) {
|
|
57
|
+
try {
|
|
58
|
+
const { initializeDatabase, getDb } = await import("../../../core/src/storage/sqlite");
|
|
59
|
+
initializeDatabase();
|
|
60
|
+
const db = getDb();
|
|
61
|
+
const agent = db.query("SELECT id FROM agents WHERE is_coordinator = 1 AND status = 'idle' LIMIT 1").get();
|
|
62
|
+
hasCompletedAgent = !!agent;
|
|
63
|
+
} catch {
|
|
64
|
+
hasCompletedAgent = false;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// ── Step 3: Si no hay agente, ejecutar onboarding (él crea dir + BD) ──
|
|
69
|
+
if (!hasCompletedAgent) {
|
|
70
|
+
console.log("🚀 Ejecutando onboarding interactivo...\n");
|
|
71
|
+
const { onboard } = await import("./onboard");
|
|
72
|
+
await onboard();
|
|
73
|
+
|
|
74
|
+
// Verificar que onboarding creó el agente
|
|
75
|
+
try {
|
|
76
|
+
const { getDb } = await import("../../../core/src/storage/sqlite");
|
|
77
|
+
const db = getDb();
|
|
78
|
+
const agent = db.query("SELECT id FROM agents WHERE is_coordinator = 1 AND status = 'idle' LIMIT 1").get();
|
|
79
|
+
if (!agent) {
|
|
80
|
+
console.error("❌ Onboard no creó la configuración en BD");
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
} catch (e) {
|
|
84
|
+
console.error("❌ Error verificando configuración:", (e as Error).message);
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
87
|
+
console.log("\n✅ Onboarding completado. Arrancando el servidor...\n");
|
|
88
|
+
} else {
|
|
89
|
+
console.log("🚀 Arrancando gateway con configuración existente...\n");
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// ── Step 4: Arrancar gateway ──
|
|
93
|
+
const { start } = await import("./gateway");
|
|
94
|
+
await start(["--skip-check"]);
|
|
95
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import * as p from "@clack/prompts";
|
|
2
|
+
import * as fs from "fs";
|
|
3
|
+
import * as path from "path";
|
|
4
|
+
import { execSync } from "child_process";
|
|
5
|
+
import { loadConfig, getHiveDir } from "@johpaz/hive-core/config/loader";
|
|
6
|
+
|
|
7
|
+
const getHiveDirConst = () => getHiveDir();
|
|
8
|
+
const getWorkspace = () => path.join(getHiveDirConst(), "workspace");
|
|
9
|
+
const getPidFile = () => path.join(getHiveDirConst(), "hive.pid");
|
|
10
|
+
const getDbFile = () => path.join(getHiveDirConst(), "hive.db");
|
|
11
|
+
|
|
12
|
+
function checkBun(): { ok: boolean; version: string } {
|
|
13
|
+
try {
|
|
14
|
+
const version = execSync("bun --version", { encoding: "utf-8" }).trim();
|
|
15
|
+
return { ok: true, version };
|
|
16
|
+
} catch {
|
|
17
|
+
return { ok: false, version: "no instalado" };
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function checkNode(): { ok: boolean; version: string } {
|
|
22
|
+
try {
|
|
23
|
+
const version = execSync("node --version", { encoding: "utf-8" }).trim();
|
|
24
|
+
return { ok: true, version };
|
|
25
|
+
} catch {
|
|
26
|
+
return { ok: false, version: "no instalado" };
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function isGatewayRunning(): boolean {
|
|
31
|
+
if (!fs.existsSync(getPidFile())) return false;
|
|
32
|
+
const pid = parseInt(fs.readFileSync(getPidFile(), "utf-8").trim(), 10);
|
|
33
|
+
if (isNaN(pid)) return false;
|
|
34
|
+
try {
|
|
35
|
+
process.kill(pid, 0);
|
|
36
|
+
return true;
|
|
37
|
+
} catch {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export async function doctor(): Promise<void> {
|
|
43
|
+
console.log("\n🐝 Hive Doctor — Diagnóstico del sistema\n");
|
|
44
|
+
|
|
45
|
+
const checks: Array<{ category: string; name: string; status: "ok" | "warn" | "error"; message: string; hint?: string }> = [];
|
|
46
|
+
|
|
47
|
+
// Runtime
|
|
48
|
+
const bun = checkBun();
|
|
49
|
+
checks.push({ category: "Runtime", name: "Bun", status: bun.ok ? "ok" : "error", message: `v${bun.version}` });
|
|
50
|
+
|
|
51
|
+
const node = checkNode();
|
|
52
|
+
checks.push({ category: "Runtime", name: "Node.js", status: node.ok ? "ok" : "warn", message: `${node.version} (para MCP servers)` });
|
|
53
|
+
|
|
54
|
+
// Directorio Base
|
|
55
|
+
if (fs.existsSync(getHiveDirConst())) {
|
|
56
|
+
checks.push({ category: "Sistema", name: "Directorio Hive", status: "ok", message: getHiveDirConst() });
|
|
57
|
+
} else {
|
|
58
|
+
checks.push({ category: "Sistema", name: "Directorio Hive", status: "error", message: "no existe", hint: "Ejecuta 'hive onboard'" });
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Base de Datos
|
|
62
|
+
if (fs.existsSync(getDbFile())) {
|
|
63
|
+
checks.push({ category: "Sistema", name: "Base de Datos", status: "ok", message: "hive.db presente" });
|
|
64
|
+
} else {
|
|
65
|
+
checks.push({ category: "Sistema", name: "Base de Datos", status: "warn", message: "hive.db no existe" });
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Configuración (In-memory/Env)
|
|
69
|
+
try {
|
|
70
|
+
const config = loadConfig();
|
|
71
|
+
const gateway = config.gateway;
|
|
72
|
+
if (gateway) {
|
|
73
|
+
checks.push({ category: "Configuración", name: "Gateway Config", status: "ok", message: "cargada" });
|
|
74
|
+
} else {
|
|
75
|
+
checks.push({ category: "Configuración", name: "Gateway Config", status: "warn", message: "usando valores por defecto" });
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const models = config.models;
|
|
79
|
+
const provider = models?.defaultProvider;
|
|
80
|
+
if (provider) {
|
|
81
|
+
checks.push({ category: "Configuración", name: "Proveedor LLM", status: "ok", message: provider });
|
|
82
|
+
} else {
|
|
83
|
+
checks.push({ category: "Configuración", name: "Proveedor LLM", status: "warn", message: "no configurado" });
|
|
84
|
+
}
|
|
85
|
+
} catch (e) {
|
|
86
|
+
checks.push({ category: "Configuración", name: "Carga", status: "error", message: `Error: ${(e as Error).message}` });
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Workspace
|
|
90
|
+
checks.push({ category: "Workspace", name: "Directorio", status: fs.existsSync(getWorkspace()) ? "ok" : "warn", message: fs.existsSync(getWorkspace()) ? "existe" : "no existe" });
|
|
91
|
+
|
|
92
|
+
// Gateway
|
|
93
|
+
const running = isGatewayRunning();
|
|
94
|
+
checks.push({ category: "Gateway", name: "Estado", status: running ? "ok" : "warn", message: running ? "corriendo" : "detenido" });
|
|
95
|
+
|
|
96
|
+
// Mostrar resultados
|
|
97
|
+
const categories = [...new Set(checks.map((c) => c.category))];
|
|
98
|
+
|
|
99
|
+
for (const category of categories) {
|
|
100
|
+
console.log(`${category}`);
|
|
101
|
+
const categoryChecks = checks.filter((c) => c.category === category);
|
|
102
|
+
for (const check of categoryChecks) {
|
|
103
|
+
const icon = check.status === "ok" ? "✅" : check.status === "warn" ? "⚠️ " : "❌";
|
|
104
|
+
console.log(` ${icon} ${check.name}: ${check.message}`);
|
|
105
|
+
if (check.hint) {
|
|
106
|
+
console.log(` 💡 ${check.hint}`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
console.log();
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Resumen
|
|
113
|
+
const errors = checks.filter((c) => c.status === "error");
|
|
114
|
+
const warns = checks.filter((c) => c.status === "warn");
|
|
115
|
+
|
|
116
|
+
if (errors.length > 0) {
|
|
117
|
+
console.log(`❌ ${errors.length} error(es) encontrado(s)`);
|
|
118
|
+
|
|
119
|
+
const fix = await p.confirm({
|
|
120
|
+
message: "¿Deseas ejecutar el onboarding para reparar?",
|
|
121
|
+
initialValue: false,
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
if (fix) {
|
|
125
|
+
const { onboard } = await import("./onboard");
|
|
126
|
+
await onboard();
|
|
127
|
+
}
|
|
128
|
+
} else if (warns.length > 0) {
|
|
129
|
+
console.log(`⚠️ ${warns.length} advertencia(s)`);
|
|
130
|
+
} else {
|
|
131
|
+
console.log("✅ Todo en orden");
|
|
132
|
+
}
|
|
133
|
+
}
|