@sesamespace/hivemind 0.5.5 → 0.5.8
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/dist/chunk-4U4GKI3X.js +2413 -0
- package/dist/chunk-4U4GKI3X.js.map +1 -0
- package/dist/chunk-62S2NGMN.js +79 -0
- package/dist/chunk-62S2NGMN.js.map +1 -0
- package/dist/{chunk-RXCV57H3.js → chunk-7RTJSPMX.js} +2 -2
- package/dist/{chunk-2OIRJFI5.js → chunk-GIRXRVRQ.js} +126 -16
- package/dist/chunk-GIRXRVRQ.js.map +1 -0
- package/dist/chunk-IJRAVHQC.js +327 -0
- package/dist/chunk-IJRAVHQC.js.map +1 -0
- package/dist/{chunk-SJI2KAIN.js → chunk-LJHJGDKY.js} +8 -2
- package/dist/chunk-LJHJGDKY.js.map +1 -0
- package/dist/{chunk-OQ272HKA.js → chunk-LSOEUOTO.js} +28 -3
- package/dist/chunk-LSOEUOTO.js.map +1 -0
- package/dist/{chunk-YEOAEJ62.js → chunk-PFN3BITA.js} +322 -2
- package/dist/chunk-PFN3BITA.js.map +1 -0
- package/dist/commands/fleet.js +3 -4
- package/dist/commands/init.js +1 -2
- package/dist/commands/service.js +1 -2
- package/dist/commands/start.js +3 -4
- package/dist/commands/upgrade.js +1 -2
- package/dist/commands/watchdog.js +10 -0
- package/dist/index.js +6 -3
- package/dist/main.js +22 -13
- package/dist/main.js.map +1 -1
- package/dist/start.js +1 -2
- package/dist/start.js.map +1 -1
- package/package.json +4 -3
- package/.github/workflows/memory-release.yml +0 -89
- package/data/lancedb/contexts.lance/_transactions/0-c4755ab9-b604-4d90-851f-0491f3cbcbce.txn +0 -2
- package/data/lancedb/contexts.lance/_versions/1.manifest +0 -0
- package/data/lancedb/episode_access.lance/_transactions/0-407a6366-0dca-490a-868b-ea63bee3b40c.txn +0 -2
- package/data/lancedb/episode_access.lance/_versions/1.manifest +0 -0
- package/data/lancedb/episode_cooccurrence.lance/_transactions/0-0e103c7f-29d7-4f09-8100-505c076f01ae.txn +0 -1
- package/data/lancedb/episode_cooccurrence.lance/_versions/1.manifest +0 -0
- package/data/lancedb/episodes.lance/_transactions/0-e678cbac-792b-4a9d-a457-17b0d4d23607.txn +0 -1
- package/data/lancedb/episodes.lance/_versions/1.manifest +0 -0
- package/data/lancedb/l3_knowledge.lance/_transactions/0-cdb3561f-3a59-4e15-bded-e93c5f9a50e3.txn +0 -1
- package/data/lancedb/l3_knowledge.lance/_versions/1.manifest +0 -0
- package/data/lancedb/tasks.lance/_transactions/0-d1cf10ec-1eb8-48b4-bbbe-34b3a1083664.txn +0 -4
- package/data/lancedb/tasks.lance/_versions/1.manifest +0 -0
- package/dist/chunk-2OIRJFI5.js.map +0 -1
- package/dist/chunk-7D4SUZUM.js +0 -38
- package/dist/chunk-LRK64BAK.js +0 -3601
- package/dist/chunk-LRK64BAK.js.map +0 -1
- package/dist/chunk-MBS5A6BZ.js +0 -132
- package/dist/chunk-MBS5A6BZ.js.map +0 -1
- package/dist/chunk-OQ272HKA.js.map +0 -1
- package/dist/chunk-SJI2KAIN.js.map +0 -1
- package/dist/chunk-YEOAEJ62.js.map +0 -1
- /package/dist/{chunk-RXCV57H3.js.map → chunk-7RTJSPMX.js.map} +0 -0
- /package/dist/{chunk-7D4SUZUM.js.map → commands/watchdog.js.map} +0 -0
|
@@ -3,14 +3,21 @@ import {
|
|
|
3
3
|
} from "./chunk-GPI4RU7N.js";
|
|
4
4
|
|
|
5
5
|
// packages/cli/src/commands/init.ts
|
|
6
|
-
import { resolve } from "path";
|
|
7
|
-
import { existsSync, writeFileSync, mkdirSync } from "fs";
|
|
6
|
+
import { resolve, dirname } from "path";
|
|
7
|
+
import { existsSync, writeFileSync, mkdirSync, copyFileSync, realpathSync, chmodSync } from "fs";
|
|
8
8
|
import { createInterface } from "readline";
|
|
9
|
-
|
|
9
|
+
import { execSync } from "child_process";
|
|
10
|
+
import { homedir, arch, platform } from "os";
|
|
11
|
+
var HIVEMIND_DIR = resolve(process.env.HIVEMIND_HOME || resolve(homedir(), "hivemind"));
|
|
10
12
|
var CONFIG_DIR = resolve(HIVEMIND_DIR, "config");
|
|
11
13
|
var WORKSPACE_DIR = resolve(HIVEMIND_DIR, "workspace");
|
|
14
|
+
var BIN_DIR = resolve(HIVEMIND_DIR, "bin");
|
|
15
|
+
var DATA_DIR = resolve(HIVEMIND_DIR, "data");
|
|
12
16
|
var ENV_FILE = resolve(HIVEMIND_DIR, ".env");
|
|
13
17
|
var LOCAL_TOML = resolve(CONFIG_DIR, "local.toml");
|
|
18
|
+
var MEMORY_BIN = resolve(BIN_DIR, "hivemind-memory");
|
|
19
|
+
var RELEASES_BASE_URL = "https://sesame-hivemind-releases.s3.amazonaws.com";
|
|
20
|
+
var EMBEDDING_MODEL = "nomic-embed-text";
|
|
14
21
|
var VAULT_CONFIG_NAME = "hivemind-config";
|
|
15
22
|
async function prompt(question) {
|
|
16
23
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
@@ -99,18 +106,30 @@ async function runInitCommand(args) {
|
|
|
99
106
|
} finally {
|
|
100
107
|
sdk.disconnect();
|
|
101
108
|
}
|
|
102
|
-
if (!config.llmApiKey
|
|
103
|
-
config.llmApiKey = await prompt("\n OpenRouter API key: ");
|
|
104
|
-
} else if (!config.llmApiKey) {
|
|
109
|
+
if (!config.llmApiKey) {
|
|
105
110
|
console.log(" ! No LLM API key found in vault \u2014 set LLM_API_KEY in .env after init");
|
|
106
111
|
}
|
|
107
|
-
if (!nonInteractive) {
|
|
108
|
-
const nameOverride = await prompt(` Agent name [${config.agentName}]: `);
|
|
109
|
-
if (nameOverride) config.agentName = nameOverride;
|
|
110
|
-
}
|
|
111
112
|
console.log("\n\u2192 Writing configuration...");
|
|
112
113
|
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
113
114
|
mkdirSync(WORKSPACE_DIR, { recursive: true });
|
|
115
|
+
const defaultToml = resolve(CONFIG_DIR, "default.toml");
|
|
116
|
+
if (!existsSync(defaultToml)) {
|
|
117
|
+
const realBin = realpathSync(process.argv[1]);
|
|
118
|
+
const packageConfigDir = resolve(dirname(realBin), "..", "config");
|
|
119
|
+
const packageDefault = resolve(packageConfigDir, "default.toml");
|
|
120
|
+
if (existsSync(packageDefault)) {
|
|
121
|
+
copyFileSync(packageDefault, defaultToml);
|
|
122
|
+
console.log(` \u2713 ${defaultToml}`);
|
|
123
|
+
const packageCharter = resolve(packageConfigDir, "TEAM-CHARTER.md");
|
|
124
|
+
const localCharter = resolve(CONFIG_DIR, "TEAM-CHARTER.md");
|
|
125
|
+
if (existsSync(packageCharter) && !existsSync(localCharter)) {
|
|
126
|
+
copyFileSync(packageCharter, localCharter);
|
|
127
|
+
console.log(` \u2713 ${localCharter}`);
|
|
128
|
+
}
|
|
129
|
+
} else {
|
|
130
|
+
console.log(` ! default.toml not found in package \u2014 you may need to copy it manually`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
114
133
|
const soulPath = resolve(WORKSPACE_DIR, "SOUL.md");
|
|
115
134
|
if (!existsSync(soulPath)) {
|
|
116
135
|
const personality = config.personality || "A helpful, capable agent.";
|
|
@@ -145,6 +164,9 @@ workspace = "workspace"
|
|
|
145
164
|
${config.llmModel ? `[llm]
|
|
146
165
|
model = "${config.llmModel}"` : "# [llm] using defaults"}
|
|
147
166
|
${config.llmBaseUrl ? `# base_url = "${config.llmBaseUrl}"` : ""}
|
|
167
|
+
|
|
168
|
+
[sesame]
|
|
169
|
+
api_key = "${sesameApiKey}"
|
|
148
170
|
`;
|
|
149
171
|
writeFileSync(LOCAL_TOML, localToml);
|
|
150
172
|
console.log(` \u2713 ${LOCAL_TOML}`);
|
|
@@ -156,20 +178,107 @@ AGENT_NAME=${config.agentName}
|
|
|
156
178
|
`;
|
|
157
179
|
writeFileSync(ENV_FILE, envContent, { mode: 384 });
|
|
158
180
|
console.log(` \u2713 ${ENV_FILE} (chmod 600)`);
|
|
181
|
+
console.log("\n\u2192 Setting up memory system...");
|
|
182
|
+
mkdirSync(BIN_DIR, { recursive: true });
|
|
183
|
+
mkdirSync(DATA_DIR, { recursive: true });
|
|
184
|
+
await installOllama();
|
|
185
|
+
await pullEmbeddingModel();
|
|
186
|
+
await downloadMemoryDaemon();
|
|
159
187
|
console.log(`
|
|
160
188
|
\u2713 Hivemind initialized for ${config.agentName}!
|
|
161
189
|
|
|
162
190
|
To start the agent:
|
|
163
|
-
|
|
191
|
+
hivemind start
|
|
164
192
|
|
|
165
|
-
To
|
|
166
|
-
|
|
193
|
+
To install as a service:
|
|
194
|
+
hivemind service install
|
|
167
195
|
|
|
168
196
|
Agent ID: ${config.agentId}
|
|
169
197
|
Channels: ${config.channels.map((c) => c.name || c.id).join(", ")}
|
|
170
198
|
Fleet role: ${config.fleetRole || "standalone"}
|
|
171
199
|
`);
|
|
172
200
|
}
|
|
201
|
+
async function installOllama() {
|
|
202
|
+
try {
|
|
203
|
+
execSync("which ollama", { stdio: "ignore" });
|
|
204
|
+
const version = execSync("ollama --version", { encoding: "utf-8" }).trim();
|
|
205
|
+
console.log(` \u2713 Ollama already installed (${version})`);
|
|
206
|
+
return;
|
|
207
|
+
} catch {
|
|
208
|
+
}
|
|
209
|
+
console.log(" \u2192 Installing Ollama...");
|
|
210
|
+
try {
|
|
211
|
+
execSync("which brew", { stdio: "ignore" });
|
|
212
|
+
execSync("brew install ollama", { stdio: "inherit" });
|
|
213
|
+
console.log(" \u2713 Ollama installed via Homebrew");
|
|
214
|
+
} catch {
|
|
215
|
+
try {
|
|
216
|
+
execSync("curl -fsSL https://ollama.com/install.sh | sh", { stdio: "inherit" });
|
|
217
|
+
console.log(" \u2713 Ollama installed via installer script");
|
|
218
|
+
} catch (err) {
|
|
219
|
+
console.error(` \u2717 Failed to install Ollama: ${err.message}`);
|
|
220
|
+
console.error(" ! Install manually: https://ollama.com/download");
|
|
221
|
+
console.error(" ! Memory system will not work without Ollama");
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
async function pullEmbeddingModel() {
|
|
226
|
+
console.log(` \u2192 Pulling embedding model (${EMBEDDING_MODEL})...`);
|
|
227
|
+
try {
|
|
228
|
+
try {
|
|
229
|
+
execSync("curl -sf http://localhost:11434/api/tags > /dev/null", { stdio: "ignore" });
|
|
230
|
+
} catch {
|
|
231
|
+
console.log(" \u2192 Starting Ollama server...");
|
|
232
|
+
execSync("ollama serve &", { stdio: "ignore", shell: "/bin/sh" });
|
|
233
|
+
for (let i = 0; i < 15; i++) {
|
|
234
|
+
try {
|
|
235
|
+
execSync("curl -sf http://localhost:11434/api/tags > /dev/null", { stdio: "ignore" });
|
|
236
|
+
break;
|
|
237
|
+
} catch {
|
|
238
|
+
execSync("sleep 1");
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
execSync(`ollama pull ${EMBEDDING_MODEL}`, { stdio: "inherit" });
|
|
243
|
+
console.log(` \u2713 ${EMBEDDING_MODEL} model ready`);
|
|
244
|
+
} catch (err) {
|
|
245
|
+
console.error(` \u2717 Failed to pull model: ${err.message}`);
|
|
246
|
+
console.error(` ! Run manually: ollama pull ${EMBEDDING_MODEL}`);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
async function downloadMemoryDaemon() {
|
|
250
|
+
if (existsSync(MEMORY_BIN)) {
|
|
251
|
+
console.log(` \u2713 Memory daemon already installed at ${MEMORY_BIN}`);
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
const osArch = arch();
|
|
255
|
+
const osPlatform = platform();
|
|
256
|
+
if (osPlatform !== "darwin") {
|
|
257
|
+
console.log(` ! Memory daemon pre-built binaries only available for macOS currently`);
|
|
258
|
+
console.log(` ! Build from source: cd packages/memory && cargo build --release`);
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
const artifactName = osArch === "arm64" ? "hivemind-memory-darwin-arm64" : "hivemind-memory-darwin-x64";
|
|
262
|
+
console.log(` \u2192 Downloading memory daemon (${artifactName})...`);
|
|
263
|
+
try {
|
|
264
|
+
const latestJson = execSync(
|
|
265
|
+
`curl -sf "${RELEASES_BASE_URL}/latest.json"`,
|
|
266
|
+
{ encoding: "utf-8" }
|
|
267
|
+
);
|
|
268
|
+
const { version } = JSON.parse(latestJson);
|
|
269
|
+
const url = `${RELEASES_BASE_URL}/v${version}/${artifactName}`;
|
|
270
|
+
execSync(
|
|
271
|
+
`curl -fSL -o "${MEMORY_BIN}" "${url}"`,
|
|
272
|
+
{ stdio: "inherit" }
|
|
273
|
+
);
|
|
274
|
+
chmodSync(MEMORY_BIN, 493);
|
|
275
|
+
console.log(` \u2713 Memory daemon installed at ${MEMORY_BIN} (v${version})`);
|
|
276
|
+
} catch (err) {
|
|
277
|
+
console.error(` \u2717 Failed to download memory daemon: ${err.message}`);
|
|
278
|
+
console.error(" ! Build from source: cd packages/memory && cargo build --release");
|
|
279
|
+
console.error(` ! Then copy to: ${MEMORY_BIN}`);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
173
282
|
function printHelp() {
|
|
174
283
|
console.log(`hivemind init \u2014 Initialize a Hivemind agent from Sesame
|
|
175
284
|
|
|
@@ -180,8 +289,9 @@ The API key can also be passed as the first argument.
|
|
|
180
289
|
What it does:
|
|
181
290
|
1. Connects to Sesame and fetches agent identity
|
|
182
291
|
2. Reads provisioning config from Sesame vault (if available)
|
|
183
|
-
3.
|
|
184
|
-
4.
|
|
292
|
+
3. Writes config/local.toml and .env
|
|
293
|
+
4. Installs Ollama + embedding model for memory
|
|
294
|
+
5. Downloads pre-built memory daemon binary
|
|
185
295
|
|
|
186
296
|
Options:
|
|
187
297
|
-h, --help Show this help
|
|
@@ -191,4 +301,4 @@ Options:
|
|
|
191
301
|
export {
|
|
192
302
|
runInitCommand
|
|
193
303
|
};
|
|
194
|
-
//# sourceMappingURL=chunk-
|
|
304
|
+
//# sourceMappingURL=chunk-GIRXRVRQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../packages/cli/src/commands/init.ts"],"sourcesContent":["import { resolve, dirname } from \"path\";\nimport { existsSync, writeFileSync, mkdirSync, readFileSync, copyFileSync, realpathSync, chmodSync } from \"fs\";\nimport { createInterface } from \"readline\";\nimport { fileURLToPath } from \"url\";\nimport { execSync } from \"child_process\";\nimport { SesameClient } from \"@sesamespace/sdk\";\nimport { homedir, arch, platform } from \"os\";\n\nconst HIVEMIND_DIR = resolve(process.env.HIVEMIND_HOME || resolve(homedir(), \"hivemind\"));\nconst CONFIG_DIR = resolve(HIVEMIND_DIR, \"config\");\nconst WORKSPACE_DIR = resolve(HIVEMIND_DIR, \"workspace\");\nconst BIN_DIR = resolve(HIVEMIND_DIR, \"bin\");\nconst DATA_DIR = resolve(HIVEMIND_DIR, \"data\");\nconst ENV_FILE = resolve(HIVEMIND_DIR, \".env\");\nconst LOCAL_TOML = resolve(CONFIG_DIR, \"local.toml\");\nconst MEMORY_BIN = resolve(BIN_DIR, \"hivemind-memory\");\n\nconst RELEASES_BASE_URL = \"https://sesame-hivemind-releases.s3.amazonaws.com\";\nconst EMBEDDING_MODEL = \"nomic-embed-text\";\n\nconst VAULT_CONFIG_NAME = \"hivemind-config\";\n\ninterface ProvisioningConfig {\n agentName: string;\n agentHandle: string;\n agentId: string;\n personality?: string;\n llmApiKey?: string;\n llmBaseUrl?: string;\n llmModel?: string;\n fleetRole?: string;\n channels: Array<{ id: string; name: string | null; kind: string }>;\n}\n\nasync function prompt(question: string): Promise<string> {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n return new Promise((resolve) => {\n rl.question(question, (answer) => {\n rl.close();\n resolve(answer.trim());\n });\n });\n}\n\nexport async function runInitCommand(args: string[]): Promise<void> {\n const nonInteractive = args.includes(\"--yes\") || args.includes(\"-y\") || args.includes(\"--non-interactive\");\n const filteredArgs = args.filter((a) => ![\"--yes\", \"-y\", \"--non-interactive\", \"--help\", \"-h\"].includes(a));\n let sesameApiKey = filteredArgs[0];\n\n if (args.includes(\"--help\") || args.includes(\"-h\")) {\n printHelp();\n return;\n }\n\n console.log(`\n ╦ ╦╦╦ ╦╔═╗╔╦╗╦╔╗╔╔╦╗\n ╠═╣║╚╗╔╝║╣ ║║║║║║║ ║║\n ╩ ╩╩ ╚╝ ╚═╝╩ ╩╩╝╚╝═╩╝\n Agent Initialization\n`);\n\n // --- Step 1: Get Sesame API key ---\n if (!sesameApiKey) {\n sesameApiKey = await prompt(\" Sesame API key: \");\n }\n if (!sesameApiKey) {\n console.error(\"Error: Sesame API key is required\");\n process.exit(1);\n }\n\n // --- Step 2: Connect to Sesame and fetch manifest ---\n console.log(\"\\n→ Connecting to Sesame...\");\n const sdk = new SesameClient({\n apiUrl: \"https://api.sesame.space\",\n wsUrl: \"wss://ws.sesame.space\",\n apiKey: sesameApiKey,\n });\n\n let config: ProvisioningConfig;\n try {\n const manifest = await sdk.getManifest();\n console.log(` ✓ Authenticated as ${manifest.agent.handle} (${manifest.agent.id})`);\n console.log(` ✓ Workspace: ${manifest.workspace.name}`);\n console.log(` ✓ Channels: ${manifest.channels.length}`);\n for (const ch of manifest.channels) {\n console.log(` - ${ch.name || ch.id} (${ch.kind})`);\n }\n\n config = {\n agentName: manifest.agent.handle,\n agentHandle: manifest.agent.handle,\n agentId: manifest.agent.id,\n channels: manifest.channels.map((ch) => ({\n id: ch.id,\n name: ch.name,\n kind: ch.kind,\n })),\n };\n\n // --- Step 3: Check vault for config ---\n console.log(\"\\n→ Checking vault for provisioning config...\");\n try {\n const vaultResp = await sdk.listVaultItems() as any;\n const items = vaultResp.items || vaultResp.data || [];\n const configItem = items.find((i: any) => i.name === VAULT_CONFIG_NAME);\n\n if (configItem) {\n console.log(` ✓ Found ${VAULT_CONFIG_NAME} vault item`);\n const revealResp = await sdk.revealItem(configItem.id) as any;\n const fields = revealResp.fields || revealResp.data || {};\n\n config.llmApiKey = fields.llm_api_key || fields.openrouter_api_key;\n config.llmBaseUrl = fields.llm_base_url;\n config.llmModel = fields.llm_model;\n config.personality = fields.agent_personality || fields.personality;\n config.fleetRole = fields.fleet_role;\n\n if (config.llmApiKey) console.log(\" ✓ LLM API key loaded from vault\");\n if (config.personality) console.log(` ✓ Personality: ${config.personality.slice(0, 60)}...`);\n if (config.fleetRole) console.log(` ✓ Fleet role: ${config.fleetRole}`);\n } else {\n console.log(\" ! No hivemind-config vault item found\");\n console.log(\" ! Will prompt for LLM API key instead\");\n }\n } catch (err) {\n console.log(` ! Could not read vault: ${(err as Error).message}`);\n }\n } catch (err) {\n console.error(`\\n ✗ Failed to connect to Sesame: ${(err as Error).message}`);\n console.error(\" Check your API key and try again.\");\n process.exit(1);\n } finally {\n sdk.disconnect();\n }\n\n // --- Step 4: Prompt for anything missing ---\n if (!config.llmApiKey) {\n console.log(\" ! No LLM API key found in vault — set LLM_API_KEY in .env after init\");\n }\n\n // --- Step 5: Write config files ---\n console.log(\"\\n→ Writing configuration...\");\n\n mkdirSync(CONFIG_DIR, { recursive: true });\n mkdirSync(WORKSPACE_DIR, { recursive: true });\n\n // Copy default.toml from installed package if not present\n const defaultToml = resolve(CONFIG_DIR, \"default.toml\");\n if (!existsSync(defaultToml)) {\n // Resolve from the hivemind binary location\n // process.argv[1] may be a symlink, so resolve it first\n const realBin = realpathSync(process.argv[1]);\n // realBin is <pkg>/dist/main.js, so ../config/ gets us to <pkg>/config/\n const packageConfigDir = resolve(dirname(realBin), \"..\", \"config\");\n const packageDefault = resolve(packageConfigDir, \"default.toml\");\n if (existsSync(packageDefault)) {\n copyFileSync(packageDefault, defaultToml);\n console.log(` ✓ ${defaultToml}`);\n // Also copy team charter if available\n const packageCharter = resolve(packageConfigDir, \"TEAM-CHARTER.md\");\n const localCharter = resolve(CONFIG_DIR, \"TEAM-CHARTER.md\");\n if (existsSync(packageCharter) && !existsSync(localCharter)) {\n copyFileSync(packageCharter, localCharter);\n console.log(` ✓ ${localCharter}`);\n }\n } else {\n console.log(` ! default.toml not found in package — you may need to copy it manually`);\n }\n }\n\n // Write workspace identity files\n const soulPath = resolve(WORKSPACE_DIR, \"SOUL.md\");\n if (!existsSync(soulPath)) {\n const personality = config.personality || \"A helpful, capable agent.\";\n writeFileSync(soulPath, `# SOUL.md — Who You Are\n\n${personality}\n\n---\n\n_This file defines your personality and values. Edit it to evolve who you are._\n`);\n console.log(` ✓ ${soulPath}`);\n }\n\n const identityPath = resolve(WORKSPACE_DIR, \"IDENTITY.md\");\n if (!existsSync(identityPath)) {\n writeFileSync(identityPath, `# IDENTITY.md\n\n- **Name:** ${config.agentName}\n- **Handle:** ${config.agentHandle}\n- **Agent ID:** ${config.agentId}\n`);\n console.log(` ✓ ${identityPath}`);\n }\n\n // Write local.toml (overrides)\n const localToml = `# Generated by hivemind init — ${new Date().toISOString()}\n# Overrides config/default.toml with agent-specific settings\n\n[agent]\nname = \"${config.agentName}\"\n${config.personality ? `personality = \"${config.personality.replace(/\"/g, '\\\\\"')}\"` : \"# personality = (using default)\"}\nworkspace = \"workspace\"\n\n${config.llmModel ? `[llm]\\nmodel = \"${config.llmModel}\"` : \"# [llm] using defaults\"}\n${config.llmBaseUrl ? `# base_url = \"${config.llmBaseUrl}\"` : \"\"}\n\n[sesame]\napi_key = \"${sesameApiKey}\"\n`;\n\n writeFileSync(LOCAL_TOML, localToml);\n console.log(` ✓ ${LOCAL_TOML}`);\n\n // Write .env\n const envContent = `# Hivemind Agent — ${config.agentName}\n# Generated by hivemind init — ${new Date().toISOString()}\nSESAME_API_KEY=${sesameApiKey}\nLLM_API_KEY=${config.llmApiKey || \"\"}\nAGENT_NAME=${config.agentName}\n`;\n\n writeFileSync(ENV_FILE, envContent, { mode: 0o600 });\n console.log(` ✓ ${ENV_FILE} (chmod 600)`);\n\n // --- Step 6: Install memory infrastructure ---\n console.log(\"\\n→ Setting up memory system...\");\n mkdirSync(BIN_DIR, { recursive: true });\n mkdirSync(DATA_DIR, { recursive: true });\n\n await installOllama();\n await pullEmbeddingModel();\n await downloadMemoryDaemon();\n\n // --- Done ---\n console.log(`\n ✓ Hivemind initialized for ${config.agentName}!\n\n To start the agent:\n hivemind start\n\n To install as a service:\n hivemind service install\n\n Agent ID: ${config.agentId}\n Channels: ${config.channels.map((c) => c.name || c.id).join(\", \")}\n Fleet role: ${config.fleetRole || \"standalone\"}\n`);\n}\n\n// --- Memory infrastructure helpers ---\n\nasync function installOllama(): Promise<void> {\n try {\n execSync(\"which ollama\", { stdio: \"ignore\" });\n const version = execSync(\"ollama --version\", { encoding: \"utf-8\" }).trim();\n console.log(` ✓ Ollama already installed (${version})`);\n return;\n } catch {}\n\n console.log(\" → Installing Ollama...\");\n try {\n // Try Homebrew first (macOS)\n execSync(\"which brew\", { stdio: \"ignore\" });\n execSync(\"brew install ollama\", { stdio: \"inherit\" });\n console.log(\" ✓ Ollama installed via Homebrew\");\n } catch {\n // Fall back to official installer\n try {\n execSync(\"curl -fsSL https://ollama.com/install.sh | sh\", { stdio: \"inherit\" });\n console.log(\" ✓ Ollama installed via installer script\");\n } catch (err) {\n console.error(` ✗ Failed to install Ollama: ${(err as Error).message}`);\n console.error(\" ! Install manually: https://ollama.com/download\");\n console.error(\" ! Memory system will not work without Ollama\");\n }\n }\n}\n\nasync function pullEmbeddingModel(): Promise<void> {\n console.log(` → Pulling embedding model (${EMBEDDING_MODEL})...`);\n try {\n // Ensure ollama is running\n try {\n execSync(\"curl -sf http://localhost:11434/api/tags > /dev/null\", { stdio: \"ignore\" });\n } catch {\n // Start ollama serve in background\n console.log(\" → Starting Ollama server...\");\n execSync(\"ollama serve &\", { stdio: \"ignore\", shell: \"/bin/sh\" });\n // Wait for it to be ready\n for (let i = 0; i < 15; i++) {\n try {\n execSync(\"curl -sf http://localhost:11434/api/tags > /dev/null\", { stdio: \"ignore\" });\n break;\n } catch {\n execSync(\"sleep 1\");\n }\n }\n }\n\n execSync(`ollama pull ${EMBEDDING_MODEL}`, { stdio: \"inherit\" });\n console.log(` ✓ ${EMBEDDING_MODEL} model ready`);\n } catch (err) {\n console.error(` ✗ Failed to pull model: ${(err as Error).message}`);\n console.error(` ! Run manually: ollama pull ${EMBEDDING_MODEL}`);\n }\n}\n\nasync function downloadMemoryDaemon(): Promise<void> {\n if (existsSync(MEMORY_BIN)) {\n console.log(` ✓ Memory daemon already installed at ${MEMORY_BIN}`);\n return;\n }\n\n const osArch = arch();\n const osPlatform = platform();\n\n if (osPlatform !== \"darwin\") {\n console.log(` ! Memory daemon pre-built binaries only available for macOS currently`);\n console.log(` ! Build from source: cd packages/memory && cargo build --release`);\n return;\n }\n\n const artifactName = osArch === \"arm64\"\n ? \"hivemind-memory-darwin-arm64\"\n : \"hivemind-memory-darwin-x64\";\n\n console.log(` → Downloading memory daemon (${artifactName})...`);\n try {\n // Get latest version from S3\n const latestJson = execSync(\n `curl -sf \"${RELEASES_BASE_URL}/latest.json\"`,\n { encoding: \"utf-8\" },\n );\n const { version } = JSON.parse(latestJson);\n const url = `${RELEASES_BASE_URL}/v${version}/${artifactName}`;\n\n execSync(\n `curl -fSL -o \"${MEMORY_BIN}\" \"${url}\"`,\n { stdio: \"inherit\" },\n );\n chmodSync(MEMORY_BIN, 0o755);\n console.log(` ✓ Memory daemon installed at ${MEMORY_BIN} (v${version})`);\n } catch (err) {\n console.error(` ✗ Failed to download memory daemon: ${(err as Error).message}`);\n console.error(\" ! Build from source: cd packages/memory && cargo build --release\");\n console.error(` ! Then copy to: ${MEMORY_BIN}`);\n }\n}\n\nfunction printHelp(): void {\n console.log(`hivemind init — Initialize a Hivemind agent from Sesame\n\nUsage: hivemind init [sesame-api-key]\n\nThe API key can also be passed as the first argument.\n\nWhat it does:\n 1. Connects to Sesame and fetches agent identity\n 2. Reads provisioning config from Sesame vault (if available)\n 3. Writes config/local.toml and .env\n 4. Installs Ollama + embedding model for memory\n 5. Downloads pre-built memory daemon binary\n\nOptions:\n -h, --help Show this help\n`);\n}\n"],"mappings":"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","names":["resolve"]}
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
// packages/cli/src/commands/service.ts
|
|
2
|
+
import { resolve } from "path";
|
|
3
|
+
import { writeFileSync, existsSync, unlinkSync, mkdirSync } from "fs";
|
|
4
|
+
import { execSync } from "child_process";
|
|
5
|
+
import { homedir } from "os";
|
|
6
|
+
var LAUNCH_AGENTS_DIR = resolve(homedir(), "Library/LaunchAgents");
|
|
7
|
+
var AGENT_LABEL = "com.hivemind.agent";
|
|
8
|
+
var WATCHDOG_LABEL = "com.hivemind.watchdog";
|
|
9
|
+
var MEMORY_LABEL = "com.hivemind.memory";
|
|
10
|
+
var STOP_FLAG_FILE = "/tmp/hivemind-agent.stopped";
|
|
11
|
+
function getHivemindHome() {
|
|
12
|
+
return process.env.HIVEMIND_HOME || resolve(homedir(), "hivemind");
|
|
13
|
+
}
|
|
14
|
+
function getHivemindBin() {
|
|
15
|
+
try {
|
|
16
|
+
const which = execSync("which hivemind", { encoding: "utf-8" }).trim();
|
|
17
|
+
if (which) return which;
|
|
18
|
+
} catch {
|
|
19
|
+
}
|
|
20
|
+
return process.argv[1] || "hivemind";
|
|
21
|
+
}
|
|
22
|
+
function generateMemoryPlist(hivemindHome) {
|
|
23
|
+
const memoryBin = resolve(hivemindHome, "bin", "hivemind-memory");
|
|
24
|
+
const dbPath = resolve(hivemindHome, "data", "lancedb");
|
|
25
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
26
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
27
|
+
<plist version="1.0">
|
|
28
|
+
<dict>
|
|
29
|
+
<key>Label</key>
|
|
30
|
+
<string>${MEMORY_LABEL}</string>
|
|
31
|
+
<key>ProgramArguments</key>
|
|
32
|
+
<array>
|
|
33
|
+
<string>${memoryBin}</string>
|
|
34
|
+
</array>
|
|
35
|
+
<key>WorkingDirectory</key>
|
|
36
|
+
<string>${hivemindHome}</string>
|
|
37
|
+
<key>EnvironmentVariables</key>
|
|
38
|
+
<dict>
|
|
39
|
+
<key>PORT</key>
|
|
40
|
+
<string>3434</string>
|
|
41
|
+
<key>DB_PATH</key>
|
|
42
|
+
<string>${dbPath}</string>
|
|
43
|
+
<key>OLLAMA_URL</key>
|
|
44
|
+
<string>http://localhost:11434</string>
|
|
45
|
+
<key>EMBEDDING_MODEL</key>
|
|
46
|
+
<string>nomic-embed-text</string>
|
|
47
|
+
</dict>
|
|
48
|
+
<key>RunAtLoad</key>
|
|
49
|
+
<true/>
|
|
50
|
+
<key>KeepAlive</key>
|
|
51
|
+
<true/>
|
|
52
|
+
<key>StandardOutPath</key>
|
|
53
|
+
<string>/tmp/hivemind-memory.log</string>
|
|
54
|
+
<key>StandardErrorPath</key>
|
|
55
|
+
<string>/tmp/hivemind-memory-error.log</string>
|
|
56
|
+
<key>ThrottleInterval</key>
|
|
57
|
+
<integer>5</integer>
|
|
58
|
+
</dict>
|
|
59
|
+
</plist>`;
|
|
60
|
+
}
|
|
61
|
+
function generateWatchdogPlist(hivemindHome, hivemindBin) {
|
|
62
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
63
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
64
|
+
<plist version="1.0">
|
|
65
|
+
<dict>
|
|
66
|
+
<key>Label</key>
|
|
67
|
+
<string>${WATCHDOG_LABEL}</string>
|
|
68
|
+
<key>ProgramArguments</key>
|
|
69
|
+
<array>
|
|
70
|
+
<string>${hivemindBin}</string>
|
|
71
|
+
<string>watchdog</string>
|
|
72
|
+
</array>
|
|
73
|
+
<key>WorkingDirectory</key>
|
|
74
|
+
<string>${hivemindHome}</string>
|
|
75
|
+
<key>EnvironmentVariables</key>
|
|
76
|
+
<dict>
|
|
77
|
+
<key>PATH</key>
|
|
78
|
+
<string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>
|
|
79
|
+
<key>HIVEMIND_HOME</key>
|
|
80
|
+
<string>${hivemindHome}</string>
|
|
81
|
+
</dict>
|
|
82
|
+
<key>RunAtLoad</key>
|
|
83
|
+
<true/>
|
|
84
|
+
<key>KeepAlive</key>
|
|
85
|
+
<true/>
|
|
86
|
+
<key>StandardOutPath</key>
|
|
87
|
+
<string>/tmp/hivemind-watchdog.log</string>
|
|
88
|
+
<key>StandardErrorPath</key>
|
|
89
|
+
<string>/tmp/hivemind-watchdog-error.log</string>
|
|
90
|
+
<key>ThrottleInterval</key>
|
|
91
|
+
<integer>5</integer>
|
|
92
|
+
</dict>
|
|
93
|
+
</plist>`;
|
|
94
|
+
}
|
|
95
|
+
function generatePlist(hivemindHome, hivemindBin) {
|
|
96
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
97
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
98
|
+
<plist version="1.0">
|
|
99
|
+
<dict>
|
|
100
|
+
<key>Label</key>
|
|
101
|
+
<string>${AGENT_LABEL}</string>
|
|
102
|
+
<key>ProgramArguments</key>
|
|
103
|
+
<array>
|
|
104
|
+
<string>${hivemindBin}</string>
|
|
105
|
+
<string>start</string>
|
|
106
|
+
</array>
|
|
107
|
+
<key>WorkingDirectory</key>
|
|
108
|
+
<string>${hivemindHome}</string>
|
|
109
|
+
<key>EnvironmentVariables</key>
|
|
110
|
+
<dict>
|
|
111
|
+
<key>PATH</key>
|
|
112
|
+
<string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>
|
|
113
|
+
<key>HIVEMIND_HOME</key>
|
|
114
|
+
<string>${hivemindHome}</string>
|
|
115
|
+
</dict>
|
|
116
|
+
<key>RunAtLoad</key>
|
|
117
|
+
<true/>
|
|
118
|
+
<key>KeepAlive</key>
|
|
119
|
+
<false/>
|
|
120
|
+
<key>StandardOutPath</key>
|
|
121
|
+
<string>/tmp/hivemind-agent.log</string>
|
|
122
|
+
<key>StandardErrorPath</key>
|
|
123
|
+
<string>/tmp/hivemind-error.log</string>
|
|
124
|
+
<key>ThrottleInterval</key>
|
|
125
|
+
<integer>5</integer>
|
|
126
|
+
</dict>
|
|
127
|
+
</plist>`;
|
|
128
|
+
}
|
|
129
|
+
async function runServiceCommand(args) {
|
|
130
|
+
const subcommand = args[0];
|
|
131
|
+
switch (subcommand) {
|
|
132
|
+
case "install":
|
|
133
|
+
await installService();
|
|
134
|
+
break;
|
|
135
|
+
case "uninstall":
|
|
136
|
+
await uninstallService();
|
|
137
|
+
break;
|
|
138
|
+
case "stop":
|
|
139
|
+
stopService();
|
|
140
|
+
break;
|
|
141
|
+
case "start":
|
|
142
|
+
startService();
|
|
143
|
+
break;
|
|
144
|
+
case "status":
|
|
145
|
+
showStatus();
|
|
146
|
+
break;
|
|
147
|
+
case "logs":
|
|
148
|
+
showLogs(args[1]);
|
|
149
|
+
break;
|
|
150
|
+
default:
|
|
151
|
+
printHelp();
|
|
152
|
+
if (subcommand) {
|
|
153
|
+
console.error(`Unknown subcommand: ${subcommand}`);
|
|
154
|
+
process.exit(1);
|
|
155
|
+
}
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
async function installService() {
|
|
160
|
+
const hivemindHome = getHivemindHome();
|
|
161
|
+
const hivemindBin = getHivemindBin();
|
|
162
|
+
const memoryBin = resolve(hivemindHome, "bin", "hivemind-memory");
|
|
163
|
+
console.log(`
|
|
164
|
+
\u2192 Installing launchd services for ${hivemindHome}
|
|
165
|
+
`);
|
|
166
|
+
console.log(` Agent binary: ${hivemindBin}`);
|
|
167
|
+
console.log(` Memory binary: ${memoryBin}`);
|
|
168
|
+
mkdirSync(LAUNCH_AGENTS_DIR, { recursive: true });
|
|
169
|
+
if (existsSync(memoryBin)) {
|
|
170
|
+
const memoryPlist = generateMemoryPlist(hivemindHome);
|
|
171
|
+
const memoryDest = resolve(LAUNCH_AGENTS_DIR, `${MEMORY_LABEL}.plist`);
|
|
172
|
+
try {
|
|
173
|
+
execSync(`launchctl unload ${memoryDest} 2>/dev/null`);
|
|
174
|
+
} catch {
|
|
175
|
+
}
|
|
176
|
+
writeFileSync(memoryDest, memoryPlist);
|
|
177
|
+
execSync(`launchctl load ${memoryDest}`);
|
|
178
|
+
console.log(` \u2713 ${MEMORY_LABEL} installed and started`);
|
|
179
|
+
} else {
|
|
180
|
+
console.log(` ! Memory daemon not found at ${memoryBin} \u2014 skipping`);
|
|
181
|
+
console.log(` ! Run 'hivemind init' to download it`);
|
|
182
|
+
}
|
|
183
|
+
try {
|
|
184
|
+
execSync("curl -sf http://localhost:11434/api/tags > /dev/null", { stdio: "ignore" });
|
|
185
|
+
console.log(" \u2713 Ollama already running");
|
|
186
|
+
} catch {
|
|
187
|
+
try {
|
|
188
|
+
execSync("brew services start ollama 2>/dev/null", { stdio: "ignore" });
|
|
189
|
+
console.log(" \u2713 Ollama started via brew services");
|
|
190
|
+
} catch {
|
|
191
|
+
console.log(" ! Ollama not running \u2014 start manually: ollama serve");
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
const watchdogPlist = generateWatchdogPlist(hivemindHome, hivemindBin);
|
|
195
|
+
const watchdogDest = resolve(LAUNCH_AGENTS_DIR, `${WATCHDOG_LABEL}.plist`);
|
|
196
|
+
try {
|
|
197
|
+
execSync(`launchctl unload ${watchdogDest} 2>/dev/null`);
|
|
198
|
+
} catch {
|
|
199
|
+
}
|
|
200
|
+
writeFileSync(watchdogDest, watchdogPlist);
|
|
201
|
+
execSync(`launchctl load ${watchdogDest}`);
|
|
202
|
+
console.log(` \u2713 ${WATCHDOG_LABEL} installed and started`);
|
|
203
|
+
const plistContent = generatePlist(hivemindHome, hivemindBin);
|
|
204
|
+
const destPath = resolve(LAUNCH_AGENTS_DIR, `${AGENT_LABEL}.plist`);
|
|
205
|
+
try {
|
|
206
|
+
execSync(`launchctl unload ${destPath} 2>/dev/null`);
|
|
207
|
+
} catch {
|
|
208
|
+
}
|
|
209
|
+
writeFileSync(destPath, plistContent);
|
|
210
|
+
execSync(`launchctl load ${destPath}`);
|
|
211
|
+
console.log(` \u2713 ${AGENT_LABEL} installed and started`);
|
|
212
|
+
console.log("\n Services will auto-start on boot.");
|
|
213
|
+
console.log(" Logs:");
|
|
214
|
+
console.log(" Agent: /tmp/hivemind-agent.log");
|
|
215
|
+
console.log(" Watchdog: /tmp/hivemind-watchdog.log");
|
|
216
|
+
console.log(" Memory: /tmp/hivemind-memory.log\n");
|
|
217
|
+
}
|
|
218
|
+
async function uninstallService() {
|
|
219
|
+
console.log("\n\u2192 Uninstalling launchd services\n");
|
|
220
|
+
for (const label of [AGENT_LABEL, WATCHDOG_LABEL, MEMORY_LABEL]) {
|
|
221
|
+
const plistPath = resolve(LAUNCH_AGENTS_DIR, `${label}.plist`);
|
|
222
|
+
if (existsSync(plistPath)) {
|
|
223
|
+
try {
|
|
224
|
+
execSync(`launchctl unload ${plistPath} 2>/dev/null`);
|
|
225
|
+
} catch {
|
|
226
|
+
}
|
|
227
|
+
unlinkSync(plistPath);
|
|
228
|
+
console.log(` \u2713 ${label} uninstalled`);
|
|
229
|
+
} else {
|
|
230
|
+
console.log(` - ${label} not installed`);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
try {
|
|
234
|
+
unlinkSync(STOP_FLAG_FILE);
|
|
235
|
+
} catch {
|
|
236
|
+
}
|
|
237
|
+
console.log("");
|
|
238
|
+
}
|
|
239
|
+
function stopService() {
|
|
240
|
+
console.log("\n\u2192 Stopping agent\n");
|
|
241
|
+
writeFileSync(STOP_FLAG_FILE, String(Date.now()));
|
|
242
|
+
console.log(` \u2713 Stop flag written (${STOP_FLAG_FILE})`);
|
|
243
|
+
try {
|
|
244
|
+
const uid = execSync("id -u", { encoding: "utf-8" }).trim();
|
|
245
|
+
execSync(`launchctl kill SIGTERM gui/${uid}/${AGENT_LABEL} 2>/dev/null`);
|
|
246
|
+
console.log(` \u2713 ${AGENT_LABEL} stopped`);
|
|
247
|
+
} catch {
|
|
248
|
+
console.log(` - ${AGENT_LABEL} was not running`);
|
|
249
|
+
}
|
|
250
|
+
console.log(" Watchdog will NOT restart the agent while stop flag exists.");
|
|
251
|
+
console.log(" Use 'hivemind service start' to resume.\n");
|
|
252
|
+
}
|
|
253
|
+
function startService() {
|
|
254
|
+
console.log("\n\u2192 Starting agent\n");
|
|
255
|
+
try {
|
|
256
|
+
unlinkSync(STOP_FLAG_FILE);
|
|
257
|
+
console.log(` \u2713 Stop flag removed (${STOP_FLAG_FILE})`);
|
|
258
|
+
} catch {
|
|
259
|
+
console.log(" - No stop flag present");
|
|
260
|
+
}
|
|
261
|
+
try {
|
|
262
|
+
const uid = execSync("id -u", { encoding: "utf-8" }).trim();
|
|
263
|
+
execSync(`launchctl kickstart gui/${uid}/${AGENT_LABEL}`);
|
|
264
|
+
console.log(` \u2713 ${AGENT_LABEL} started`);
|
|
265
|
+
} catch (err) {
|
|
266
|
+
console.error(` ! Failed to start agent: ${err.message}`);
|
|
267
|
+
}
|
|
268
|
+
console.log("");
|
|
269
|
+
}
|
|
270
|
+
function showStatus() {
|
|
271
|
+
console.log("\n\u2192 Service status\n");
|
|
272
|
+
for (const label of [AGENT_LABEL, WATCHDOG_LABEL, MEMORY_LABEL]) {
|
|
273
|
+
try {
|
|
274
|
+
const out = execSync(`launchctl list ${label} 2>/dev/null`, { encoding: "utf-8" });
|
|
275
|
+
const pidMatch = out.match(/"PID"\s*=\s*(\d+)/);
|
|
276
|
+
const pid = pidMatch ? pidMatch[1] : "unknown";
|
|
277
|
+
console.log(` \u2713 ${label}: running (PID ${pid})`);
|
|
278
|
+
} catch {
|
|
279
|
+
console.log(` - ${label}: not running`);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
try {
|
|
283
|
+
execSync("curl -sf http://localhost:11434/api/tags > /dev/null", { stdio: "ignore" });
|
|
284
|
+
console.log(" \u2713 ollama: running");
|
|
285
|
+
} catch {
|
|
286
|
+
console.log(" - ollama: not running");
|
|
287
|
+
}
|
|
288
|
+
console.log("");
|
|
289
|
+
}
|
|
290
|
+
function showLogs(which) {
|
|
291
|
+
const logMap = {
|
|
292
|
+
agent: "/tmp/hivemind-agent.log",
|
|
293
|
+
error: "/tmp/hivemind-error.log",
|
|
294
|
+
watchdog: "/tmp/hivemind-watchdog.log",
|
|
295
|
+
memory: "/tmp/hivemind-memory.log"
|
|
296
|
+
};
|
|
297
|
+
const logFile = logMap[which || "agent"] || logMap.agent;
|
|
298
|
+
try {
|
|
299
|
+
execSync(`tail -30 ${logFile}`, { stdio: "inherit" });
|
|
300
|
+
} catch {
|
|
301
|
+
console.error(`No log file at ${logFile}`);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
function printHelp() {
|
|
305
|
+
console.log(`hivemind service \u2014 Manage launchd services
|
|
306
|
+
|
|
307
|
+
Usage: hivemind service <subcommand>
|
|
308
|
+
|
|
309
|
+
Subcommands:
|
|
310
|
+
install Install and start all launchd services (survives reboots)
|
|
311
|
+
uninstall Stop and remove all launchd services
|
|
312
|
+
stop Stop agent (watchdog will not restart it)
|
|
313
|
+
start Start agent (removes stop flag)
|
|
314
|
+
status Show service status
|
|
315
|
+
logs [agent|watchdog|memory|error] Show recent logs
|
|
316
|
+
|
|
317
|
+
Services:
|
|
318
|
+
com.hivemind.watchdog \u2014 Watchdog daemon (health monitoring, restart/upgrade orchestration)
|
|
319
|
+
com.hivemind.agent \u2014 Agent runtime (Node.js, Sesame) \u2014 managed by watchdog
|
|
320
|
+
com.hivemind.memory \u2014 Memory daemon (LanceDB + Ollama embeddings)
|
|
321
|
+
`);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
export {
|
|
325
|
+
runServiceCommand
|
|
326
|
+
};
|
|
327
|
+
//# sourceMappingURL=chunk-IJRAVHQC.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../packages/cli/src/commands/service.ts"],"sourcesContent":["import { resolve } from \"path\";\nimport { writeFileSync, existsSync, unlinkSync, mkdirSync } from \"fs\";\nimport { execSync } from \"child_process\";\nimport { homedir } from \"os\";\n\nconst LAUNCH_AGENTS_DIR = resolve(homedir(), \"Library/LaunchAgents\");\nconst AGENT_LABEL = \"com.hivemind.agent\";\nconst WATCHDOG_LABEL = \"com.hivemind.watchdog\";\nconst MEMORY_LABEL = \"com.hivemind.memory\";\nconst STOP_FLAG_FILE = \"/tmp/hivemind-agent.stopped\";\n\nfunction getHivemindHome(): string {\n return process.env.HIVEMIND_HOME || resolve(homedir(), \"hivemind\");\n}\n\nfunction getHivemindBin(): string {\n // Try to find the hivemind binary\n try {\n const which = execSync(\"which hivemind\", { encoding: \"utf-8\" }).trim();\n if (which) return which;\n } catch {}\n // Fallback to process.argv[1] (the script being run)\n return process.argv[1] || \"hivemind\";\n}\n\nfunction generateMemoryPlist(hivemindHome: string): string {\n const memoryBin = resolve(hivemindHome, \"bin\", \"hivemind-memory\");\n const dbPath = resolve(hivemindHome, \"data\", \"lancedb\");\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>${MEMORY_LABEL}</string>\n <key>ProgramArguments</key>\n <array>\n <string>${memoryBin}</string>\n </array>\n <key>WorkingDirectory</key>\n <string>${hivemindHome}</string>\n <key>EnvironmentVariables</key>\n <dict>\n <key>PORT</key>\n <string>3434</string>\n <key>DB_PATH</key>\n <string>${dbPath}</string>\n <key>OLLAMA_URL</key>\n <string>http://localhost:11434</string>\n <key>EMBEDDING_MODEL</key>\n <string>nomic-embed-text</string>\n </dict>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <true/>\n <key>StandardOutPath</key>\n <string>/tmp/hivemind-memory.log</string>\n <key>StandardErrorPath</key>\n <string>/tmp/hivemind-memory-error.log</string>\n <key>ThrottleInterval</key>\n <integer>5</integer>\n</dict>\n</plist>`;\n}\n\nfunction generateWatchdogPlist(hivemindHome: string, hivemindBin: string): string {\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>${WATCHDOG_LABEL}</string>\n <key>ProgramArguments</key>\n <array>\n <string>${hivemindBin}</string>\n <string>watchdog</string>\n </array>\n <key>WorkingDirectory</key>\n <string>${hivemindHome}</string>\n <key>EnvironmentVariables</key>\n <dict>\n <key>PATH</key>\n <string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>\n <key>HIVEMIND_HOME</key>\n <string>${hivemindHome}</string>\n </dict>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <true/>\n <key>StandardOutPath</key>\n <string>/tmp/hivemind-watchdog.log</string>\n <key>StandardErrorPath</key>\n <string>/tmp/hivemind-watchdog-error.log</string>\n <key>ThrottleInterval</key>\n <integer>5</integer>\n</dict>\n</plist>`;\n}\n\nfunction generatePlist(hivemindHome: string, hivemindBin: string): string {\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>${AGENT_LABEL}</string>\n <key>ProgramArguments</key>\n <array>\n <string>${hivemindBin}</string>\n <string>start</string>\n </array>\n <key>WorkingDirectory</key>\n <string>${hivemindHome}</string>\n <key>EnvironmentVariables</key>\n <dict>\n <key>PATH</key>\n <string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>\n <key>HIVEMIND_HOME</key>\n <string>${hivemindHome}</string>\n </dict>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <false/>\n <key>StandardOutPath</key>\n <string>/tmp/hivemind-agent.log</string>\n <key>StandardErrorPath</key>\n <string>/tmp/hivemind-error.log</string>\n <key>ThrottleInterval</key>\n <integer>5</integer>\n</dict>\n</plist>`;\n}\n\nexport async function runServiceCommand(args: string[]): Promise<void> {\n const subcommand = args[0];\n\n switch (subcommand) {\n case \"install\":\n await installService();\n break;\n case \"uninstall\":\n await uninstallService();\n break;\n case \"stop\":\n stopService();\n break;\n case \"start\":\n startService();\n break;\n case \"status\":\n showStatus();\n break;\n case \"logs\":\n showLogs(args[1]);\n break;\n default:\n printHelp();\n if (subcommand) {\n console.error(`Unknown subcommand: ${subcommand}`);\n process.exit(1);\n }\n break;\n }\n}\n\nasync function installService(): Promise<void> {\n const hivemindHome = getHivemindHome();\n const hivemindBin = getHivemindBin();\n const memoryBin = resolve(hivemindHome, \"bin\", \"hivemind-memory\");\n\n console.log(`\\n→ Installing launchd services for ${hivemindHome}\\n`);\n console.log(` Agent binary: ${hivemindBin}`);\n console.log(` Memory binary: ${memoryBin}`);\n\n mkdirSync(LAUNCH_AGENTS_DIR, { recursive: true });\n\n // --- Memory daemon service ---\n if (existsSync(memoryBin)) {\n const memoryPlist = generateMemoryPlist(hivemindHome);\n const memoryDest = resolve(LAUNCH_AGENTS_DIR, `${MEMORY_LABEL}.plist`);\n try { execSync(`launchctl unload ${memoryDest} 2>/dev/null`); } catch {}\n writeFileSync(memoryDest, memoryPlist);\n execSync(`launchctl load ${memoryDest}`);\n console.log(` ✓ ${MEMORY_LABEL} installed and started`);\n } else {\n console.log(` ! Memory daemon not found at ${memoryBin} — skipping`);\n console.log(` ! Run 'hivemind init' to download it`);\n }\n\n // --- Ollama service (ensure running) ---\n try {\n execSync(\"curl -sf http://localhost:11434/api/tags > /dev/null\", { stdio: \"ignore\" });\n console.log(\" ✓ Ollama already running\");\n } catch {\n try {\n execSync(\"brew services start ollama 2>/dev/null\", { stdio: \"ignore\" });\n console.log(\" ✓ Ollama started via brew services\");\n } catch {\n console.log(\" ! Ollama not running — start manually: ollama serve\");\n }\n }\n\n // --- Watchdog service ---\n const watchdogPlist = generateWatchdogPlist(hivemindHome, hivemindBin);\n const watchdogDest = resolve(LAUNCH_AGENTS_DIR, `${WATCHDOG_LABEL}.plist`);\n try { execSync(`launchctl unload ${watchdogDest} 2>/dev/null`); } catch {}\n writeFileSync(watchdogDest, watchdogPlist);\n execSync(`launchctl load ${watchdogDest}`);\n console.log(` ✓ ${WATCHDOG_LABEL} installed and started`);\n\n // --- Agent service (KeepAlive: false — watchdog manages restarts) ---\n const plistContent = generatePlist(hivemindHome, hivemindBin);\n const destPath = resolve(LAUNCH_AGENTS_DIR, `${AGENT_LABEL}.plist`);\n try { execSync(`launchctl unload ${destPath} 2>/dev/null`); } catch {}\n writeFileSync(destPath, plistContent);\n execSync(`launchctl load ${destPath}`);\n console.log(` ✓ ${AGENT_LABEL} installed and started`);\n\n console.log(\"\\n Services will auto-start on boot.\");\n console.log(\" Logs:\");\n console.log(\" Agent: /tmp/hivemind-agent.log\");\n console.log(\" Watchdog: /tmp/hivemind-watchdog.log\");\n console.log(\" Memory: /tmp/hivemind-memory.log\\n\");\n}\n\nasync function uninstallService(): Promise<void> {\n console.log(\"\\n→ Uninstalling launchd services\\n\");\n\n for (const label of [AGENT_LABEL, WATCHDOG_LABEL, MEMORY_LABEL]) {\n const plistPath = resolve(LAUNCH_AGENTS_DIR, `${label}.plist`);\n if (existsSync(plistPath)) {\n try { execSync(`launchctl unload ${plistPath} 2>/dev/null`); } catch {}\n unlinkSync(plistPath);\n console.log(` ✓ ${label} uninstalled`);\n } else {\n console.log(` - ${label} not installed`);\n }\n }\n\n // Clean up stop flag if present\n try { unlinkSync(STOP_FLAG_FILE); } catch {}\n console.log(\"\");\n}\n\nfunction stopService(): void {\n console.log(\"\\n→ Stopping agent\\n\");\n\n // Write stop flag so watchdog doesn't restart\n writeFileSync(STOP_FLAG_FILE, String(Date.now()));\n console.log(` ✓ Stop flag written (${STOP_FLAG_FILE})`);\n\n // Stop agent via launchctl\n try {\n const uid = execSync(\"id -u\", { encoding: \"utf-8\" }).trim();\n execSync(`launchctl kill SIGTERM gui/${uid}/${AGENT_LABEL} 2>/dev/null`);\n console.log(` ✓ ${AGENT_LABEL} stopped`);\n } catch {\n console.log(` - ${AGENT_LABEL} was not running`);\n }\n\n console.log(\" Watchdog will NOT restart the agent while stop flag exists.\");\n console.log(\" Use 'hivemind service start' to resume.\\n\");\n}\n\nfunction startService(): void {\n console.log(\"\\n→ Starting agent\\n\");\n\n // Remove stop flag\n try {\n unlinkSync(STOP_FLAG_FILE);\n console.log(` ✓ Stop flag removed (${STOP_FLAG_FILE})`);\n } catch {\n console.log(\" - No stop flag present\");\n }\n\n // Start agent via launchctl\n try {\n const uid = execSync(\"id -u\", { encoding: \"utf-8\" }).trim();\n execSync(`launchctl kickstart gui/${uid}/${AGENT_LABEL}`);\n console.log(` ✓ ${AGENT_LABEL} started`);\n } catch (err) {\n console.error(` ! Failed to start agent: ${(err as Error).message}`);\n }\n console.log(\"\");\n}\n\nfunction showStatus(): void {\n console.log(\"\\n→ Service status\\n\");\n for (const label of [AGENT_LABEL, WATCHDOG_LABEL, MEMORY_LABEL]) {\n try {\n const out = execSync(`launchctl list ${label} 2>/dev/null`, { encoding: \"utf-8\" });\n const pidMatch = out.match(/\"PID\"\\s*=\\s*(\\d+)/);\n const pid = pidMatch ? pidMatch[1] : \"unknown\";\n console.log(` ✓ ${label}: running (PID ${pid})`);\n } catch {\n console.log(` - ${label}: not running`);\n }\n }\n\n // Check Ollama\n try {\n execSync(\"curl -sf http://localhost:11434/api/tags > /dev/null\", { stdio: \"ignore\" });\n console.log(\" ✓ ollama: running\");\n } catch {\n console.log(\" - ollama: not running\");\n }\n console.log(\"\");\n}\n\nfunction showLogs(which?: string): void {\n const logMap: Record<string, string> = {\n agent: \"/tmp/hivemind-agent.log\",\n error: \"/tmp/hivemind-error.log\",\n watchdog: \"/tmp/hivemind-watchdog.log\",\n memory: \"/tmp/hivemind-memory.log\",\n };\n const logFile = logMap[which || \"agent\"] || logMap.agent;\n try {\n execSync(`tail -30 ${logFile}`, { stdio: \"inherit\" });\n } catch {\n console.error(`No log file at ${logFile}`);\n }\n}\n\nfunction printHelp(): void {\n console.log(`hivemind service — Manage launchd services\n\nUsage: hivemind service <subcommand>\n\nSubcommands:\n install Install and start all launchd services (survives reboots)\n uninstall Stop and remove all launchd services\n stop Stop agent (watchdog will not restart it)\n start Start agent (removes stop flag)\n status Show service status\n logs [agent|watchdog|memory|error] Show recent logs\n\nServices:\n com.hivemind.watchdog — Watchdog daemon (health monitoring, restart/upgrade orchestration)\n com.hivemind.agent — Agent runtime (Node.js, Sesame) — managed by watchdog\n com.hivemind.memory — Memory daemon (LanceDB + Ollama embeddings)\n`);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
// packages/cli/src/commands/upgrade.ts
|
|
2
2
|
import { execSync } from "child_process";
|
|
3
3
|
import { resolve } from "path";
|
|
4
|
-
import { existsSync, readFileSync } from "fs";
|
|
4
|
+
import { existsSync, readFileSync, writeFileSync, unlinkSync } from "fs";
|
|
5
5
|
var PACKAGE_NAME = "@sesamespace/hivemind";
|
|
6
|
+
var STOP_FLAG_FILE = "/tmp/hivemind-agent.stopped";
|
|
6
7
|
function getCurrentVersion() {
|
|
7
8
|
try {
|
|
8
9
|
const output = execSync(`npm ls -g ${PACKAGE_NAME} --json 2>/dev/null`, { encoding: "utf-8" });
|
|
@@ -85,6 +86,7 @@ async function runUpgradeCommand(args) {
|
|
|
85
86
|
console.error(` \u2717 npm install failed: ${err.message}`);
|
|
86
87
|
process.exit(1);
|
|
87
88
|
}
|
|
89
|
+
writeFileSync(STOP_FLAG_FILE, String(Date.now()));
|
|
88
90
|
console.log("\n\u2192 Restarting agent...");
|
|
89
91
|
try {
|
|
90
92
|
const plistName = "com.hivemind.agent";
|
|
@@ -100,6 +102,10 @@ async function runUpgradeCommand(args) {
|
|
|
100
102
|
console.log(" ! No running agent found \u2014 start manually: hivemind start");
|
|
101
103
|
}
|
|
102
104
|
}
|
|
105
|
+
try {
|
|
106
|
+
unlinkSync(STOP_FLAG_FILE);
|
|
107
|
+
} catch {
|
|
108
|
+
}
|
|
103
109
|
const newVersion = getCurrentVersion();
|
|
104
110
|
console.log(`
|
|
105
111
|
\u2713 Upgrade complete: ${info.current} \u2192 ${newVersion}`);
|
|
@@ -128,4 +134,4 @@ Examples:
|
|
|
128
134
|
export {
|
|
129
135
|
runUpgradeCommand
|
|
130
136
|
};
|
|
131
|
-
//# sourceMappingURL=chunk-
|
|
137
|
+
//# sourceMappingURL=chunk-LJHJGDKY.js.map
|