@johpaz/hive-cli 1.0.7 → 1.0.10

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@johpaz/hive-cli",
3
- "version": "1.0.7",
3
+ "version": "1.0.10",
4
4
  "description": "Hive CLI — Command line interface for the Hive AI Gateway",
5
5
  "bin": {
6
6
  "hive": "src/index.ts"
@@ -14,13 +14,13 @@
14
14
  "test": "bun test"
15
15
  },
16
16
  "dependencies": {
17
- "@clack/prompts": "^1.0.1",
18
- "@johpaz/hive-core": "^1.0.7",
19
- "@johpaz/hive-orchestrator": "workspace:*",
17
+ "@clack/prompts": "^",
18
+ "@johpaz/hive-core": "^1.0.10",
19
+ "@johpaz/hive-orchestrator": "^1.0.10",
20
20
  "js-yaml": "latest"
21
21
  },
22
22
  "devDependencies": {
23
23
  "typescript": "latest",
24
24
  "@types/bun": "latest"
25
25
  }
26
- }
26
+ }
@@ -0,0 +1,180 @@
1
+ import * as p from "@clack/prompts";
2
+ import * as fs from "fs";
3
+ import * as path from "path";
4
+ import * as yaml from "js-yaml";
5
+
6
+ const HIVE_DIR = path.join(process.env.HOME || "", ".hive");
7
+ const CONFIG_PATH = path.join(HIVE_DIR, "hive.yaml");
8
+
9
+ function loadConfig(): Record<string, unknown> | null {
10
+ if (!fs.existsSync(CONFIG_PATH)) return null;
11
+
12
+ const content = fs.readFileSync(CONFIG_PATH, "utf-8");
13
+ return yaml.load(content) as Record<string, unknown>;
14
+ }
15
+
16
+ function getGatewayUrl(config: Record<string, unknown> | null): string {
17
+ const gateway = config?.gateway as Record<string, unknown> | undefined;
18
+ const host = (gateway?.host as string) ?? "localhost";
19
+ const port = (gateway?.port as number) ?? 3000;
20
+ return `http://${host}:${port}`;
21
+ }
22
+
23
+ export async function agent(subcommand: string | undefined, args: string[]): Promise<void> {
24
+ switch (subcommand) {
25
+ case "run":
26
+ await agentRun(args);
27
+ break;
28
+ default:
29
+ console.log(`
30
+ Usage: hive agent <command>
31
+
32
+ Commands:
33
+ run --message <text> Ejecutar agente con mensaje
34
+ run --thinking <level> Nivel de razonamiento (low/medium/high)
35
+ run --wait Esperar respuesta completa
36
+ `);
37
+ }
38
+ }
39
+
40
+ async function agentRun(args: string[]): Promise<void> {
41
+ const messageIndex = args.indexOf("--message");
42
+ const thinkingIndex = args.indexOf("--thinking");
43
+ const toolsIndex = args.indexOf("--tools");
44
+ const agentIndex = args.indexOf("--agent");
45
+ const waitIndex = args.indexOf("--wait");
46
+
47
+ if (messageIndex === -1) {
48
+ const msg = await p.text({
49
+ message: "Mensaje para el agente:",
50
+ placeholder: "Analiza el archivo README.md",
51
+ validate: (v) => (!v ? "El mensaje es requerido" : undefined),
52
+ });
53
+
54
+ if (p.isCancel(msg)) {
55
+ p.cancel("Cancelado");
56
+ return;
57
+ }
58
+
59
+ args.push("--message", msg as string);
60
+ return agentRun(args);
61
+ }
62
+
63
+ const message = args[messageIndex + 1];
64
+ const thinking = thinkingIndex !== -1 ? args[thinkingIndex + 1] : "medium";
65
+ const tools = toolsIndex !== -1 ? args[toolsIndex + 1] : "all";
66
+ const agentId = agentIndex !== -1 ? args[agentIndex + 1] : "main";
67
+ const wait = waitIndex !== -1;
68
+
69
+ if (!message) {
70
+ console.log("❌ Mensaje requerido");
71
+ return;
72
+ }
73
+
74
+ const config = loadConfig();
75
+ const gatewayUrl = getGatewayUrl(config);
76
+
77
+ const spinner = p.spinner();
78
+ spinner.start("Conectando con el agente...");
79
+
80
+ try {
81
+ if (wait) {
82
+ await executeWithStream(gatewayUrl, { message, thinking, tools, agentId }, spinner);
83
+ } else {
84
+ await executeAsync(gatewayUrl, { message, thinking, tools, agentId }, spinner);
85
+ }
86
+ } catch (error) {
87
+ spinner.stop("Error");
88
+ console.log(`❌ ${(error as Error).message}`);
89
+ console.log(" ¿Está corriendo el Gateway? Ejecuta: hive start");
90
+ }
91
+ }
92
+
93
+ async function executeWithStream(
94
+ gatewayUrl: string,
95
+ payload: { message: string; thinking: string; tools: string; agentId: string },
96
+ spinner: ReturnType<typeof p.spinner>
97
+ ): Promise<void> {
98
+ const response = await fetch(`${gatewayUrl}/api/agent/execute`, {
99
+ method: "POST",
100
+ headers: { "Content-Type": "application/json" },
101
+ body: JSON.stringify({ ...payload, stream: true }),
102
+ });
103
+
104
+ if (!response.ok) {
105
+ throw new Error(`Error: ${response.statusText}`);
106
+ }
107
+
108
+ spinner.stop("Conectado");
109
+
110
+ const reader = response.body?.getReader();
111
+ if (!reader) {
112
+ throw new Error("No se pudo obtener el stream");
113
+ }
114
+
115
+ const decoder = new TextDecoder();
116
+ let buffer = "";
117
+ let thinking = true;
118
+
119
+ process.stdout.write("\n");
120
+
121
+ while (true) {
122
+ const { done, value } = await reader.read();
123
+ if (done) break;
124
+
125
+ buffer += decoder.decode(value, { stream: true });
126
+ const lines = buffer.split("\n");
127
+ buffer = lines.pop() ?? "";
128
+
129
+ for (const line of lines) {
130
+ if (!line.trim() || !line.startsWith("data: ")) continue;
131
+
132
+ try {
133
+ const data = JSON.parse(line.slice(6));
134
+
135
+ if (data.type === "thinking" && thinking) {
136
+ process.stdout.write(".");
137
+ } else if (data.type === "response") {
138
+ if (thinking) {
139
+ process.stdout.write("\n\n");
140
+ thinking = false;
141
+ }
142
+ process.stdout.write(data.content ?? "");
143
+ } else if (data.type === "tool_call") {
144
+ process.stdout.write(`\n[Tool: ${data.toolName}]`);
145
+ } else if (data.type === "complete") {
146
+ process.stdout.write("\n\n");
147
+ }
148
+ } catch {
149
+ // Ignore parse errors
150
+ }
151
+ }
152
+ }
153
+ }
154
+
155
+ async function executeAsync(
156
+ gatewayUrl: string,
157
+ payload: { message: string; thinking: string; tools: string; agentId: string },
158
+ spinner: ReturnType<typeof p.spinner>
159
+ ): Promise<void> {
160
+ const response = await fetch(`${gatewayUrl}/api/agent/execute`, {
161
+ method: "POST",
162
+ headers: { "Content-Type": "application/json" },
163
+ body: JSON.stringify({ ...payload, stream: false }),
164
+ });
165
+
166
+ if (!response.ok) {
167
+ throw new Error(`Error: ${response.statusText}`);
168
+ }
169
+
170
+ const result = await response.json() as { taskId?: string; success: boolean };
171
+
172
+ spinner.stop("Enviado");
173
+
174
+ if (result.taskId) {
175
+ console.log(`✓ Tarea enviada: ${result.taskId}`);
176
+ console.log(" Usa `hive tasks list` para ver el estado");
177
+ } else {
178
+ console.log("✓ Tarea enviada");
179
+ }
180
+ }
@@ -64,7 +64,7 @@ export async function start(flags: string[]): Promise<void> {
64
64
  ║ ██║ ██║██║ ╚████╔╝ ███████╗ ║
65
65
  ║ ╚═╝ ╚═╝╚═╝ ╚═══╝ ╚══════╝ ║
66
66
  ║ ║
67
- ║ Personal AI Gateway — v1.0.7
67
+ ║ Personal AI Gateway — v1.0.10
68
68
  ╚════════════════════════════════════════════╝
69
69
  `);
70
70
 
@@ -0,0 +1,90 @@
1
+ import * as p from "@clack/prompts";
2
+ import * as fs from "fs";
3
+ import * as path from "path";
4
+ import * as yaml from "js-yaml";
5
+
6
+ const HIVE_DIR = path.join(process.env.HOME || "", ".hive");
7
+ const CONFIG_PATH = path.join(HIVE_DIR, "hive.yaml");
8
+
9
+ interface MessageResult {
10
+ success: boolean;
11
+ messageId?: string;
12
+ error?: string;
13
+ }
14
+
15
+ function loadConfig(): Record<string, unknown> | null {
16
+ if (!fs.existsSync(CONFIG_PATH)) return null;
17
+
18
+ const content = fs.readFileSync(CONFIG_PATH, "utf-8");
19
+ return yaml.load(content) as Record<string, unknown>;
20
+ }
21
+
22
+ function getGatewayUrl(config: Record<string, unknown> | null): string {
23
+ const gateway = config?.gateway as Record<string, unknown> | undefined;
24
+ const host = (gateway?.host as string) ?? "localhost";
25
+ const port = (gateway?.port as number) ?? 3000;
26
+ return `http://${host}:${port}`;
27
+ }
28
+
29
+ export async function message(subcommand: string | undefined, args: string[]): Promise<void> {
30
+ switch (subcommand) {
31
+ case "send":
32
+ await messageSend(args);
33
+ break;
34
+ default:
35
+ console.log(`
36
+ Usage: hive message <command>
37
+
38
+ Commands:
39
+ send --to <id> --content <text> Enviar mensaje
40
+ `);
41
+ }
42
+ }
43
+
44
+ async function messageSend(args: string[]): Promise<void> {
45
+ const toIndex = args.indexOf("--to");
46
+ const contentIndex = args.indexOf("--content");
47
+ const channelIndex = args.indexOf("--channel");
48
+
49
+ if (toIndex === -1 || contentIndex === -1) {
50
+ console.log("❌ Faltan parámetros requeridos");
51
+ console.log(" hive message send --to <id> --content <texto>");
52
+ return;
53
+ }
54
+
55
+ const to = args[toIndex + 1];
56
+ const content = args[contentIndex + 1];
57
+ const channel = channelIndex !== -1 ? args[channelIndex + 1] : "default";
58
+
59
+ if (!to || !content) {
60
+ console.log("❌ Parámetros inválidos");
61
+ return;
62
+ }
63
+
64
+ const config = loadConfig();
65
+ const gatewayUrl = getGatewayUrl(config);
66
+
67
+ try {
68
+ const response = await fetch(`${gatewayUrl}/api/messages/send`, {
69
+ method: "POST",
70
+ headers: { "Content-Type": "application/json" },
71
+ body: JSON.stringify({ to, content, channel }),
72
+ });
73
+
74
+ if (!response.ok) {
75
+ console.log(`❌ Error: ${response.statusText}`);
76
+ return;
77
+ }
78
+
79
+ const result = (await response.json()) as MessageResult;
80
+
81
+ if (result.success) {
82
+ console.log(`✓ Mensaje enviado: ${result.messageId}`);
83
+ } else {
84
+ console.log(`❌ Error: ${result.error}`);
85
+ }
86
+ } catch (error) {
87
+ console.log(`❌ No se pudo conectar al Gateway: ${(error as Error).message}`);
88
+ console.log(" ¿Está corriendo? Ejecuta: hive start");
89
+ }
90
+ }
@@ -3,7 +3,7 @@ import * as fs from "fs";
3
3
  import * as path from "path";
4
4
  import * as yaml from "js-yaml";
5
5
 
6
- const VERSION = "1.0.7";
6
+ const VERSION = "";
7
7
 
8
8
  const DEFAULT_MODELS: Record<string, string> = {
9
9
  anthropic: "claude-sonnet-4-6",
@@ -649,7 +649,7 @@ async function runUpdateWizard(configPath: string, existing: ExistingConfig): Pr
649
649
  const keyResult = await p.text({
650
650
  message: `API key de ${provider}:`,
651
651
  placeholder: API_KEY_PLACEHOLDERS[provider] || "sk-...",
652
- validate: (v: string) => (!v || v.length < 10 ? "La key parece muy corta" : undefined),
652
+ validate: (v) => (!v || v.length < 10 ? "La key parece muy corta" : undefined),
653
653
  });
654
654
 
655
655
  if (p.isCancel(keyResult)) {
package/src/index.ts CHANGED
@@ -13,8 +13,10 @@ import { doctor } from "./commands/doctor";
13
13
  import { securityAudit } from "./commands/security";
14
14
  import { installService } from "./commands/service";
15
15
  import { update } from "./commands/update";
16
+ import { message } from "./commands/message";
17
+ import { agent } from "./commands/agent-run";
16
18
 
17
- const VERSION = "1.0.7";
19
+ const VERSION = "1.0.10";
18
20
 
19
21
  const HELP = `
20
22
  🐝 Hive — Personal AI Gateway v${VERSION}
@@ -30,6 +32,10 @@ Commands:
30
32
  chat [--agent <id>] Chat directo en terminal
31
33
  logs [--follow] [--level] Ver logs del Gateway
32
34
 
35
+ message send --to <id> --content <text>
36
+ Enviar mensaje por canal
37
+ agent run --message <text> Ejecutar agente con mensaje
38
+
33
39
  agents add <id> Crear nuevo agente
34
40
  agents list [--bindings] Listar agentes
35
41
  agents remove <id> Eliminar agente
@@ -73,6 +79,8 @@ Examples:
73
79
  hive onboard Configurar Hive por primera vez
74
80
  hive start Arrancar el Gateway
75
81
  hive chat Chatear con el agente en terminal
82
+ hive message send --to 123 --content "Hola"
83
+ hive agent run --message "Analiza README.md" --wait
76
84
  hive agents add work Crear agente "work"
77
85
  hive mcp add Añadir servidor MCP
78
86
  hive doctor Diagnosticar problemas
@@ -110,6 +118,12 @@ async function main(): Promise<void> {
110
118
  case "logs":
111
119
  await logs(flags);
112
120
  break;
121
+ case "message":
122
+ await message(subcommand, args.slice(2));
123
+ break;
124
+ case "agent":
125
+ await agent(subcommand, args.slice(2));
126
+ break;
113
127
  case "agents":
114
128
  await agents(subcommand, args.slice(2));
115
129
  break;