@sesamespace/hivemind 0.11.4 → 0.12.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/dist/{chunk-ZA4NWNS6.js → chunk-3EB4T7D4.js} +2 -2
- package/dist/{chunk-LYL5GG2F.js → chunk-6JB4OAB6.js} +3 -3
- package/dist/{chunk-4C6B2AMB.js → chunk-G5LF3BSN.js} +2 -2
- package/dist/{chunk-4YXOQGQC.js → chunk-JP3ZHMPE.js} +2 -2
- package/dist/{chunk-K6KL2VD6.js → chunk-YJW6OOEJ.js} +2 -2
- package/dist/{chunk-OB6OXLPC.js → chunk-ZQ26EOYD.js} +323 -54
- package/dist/chunk-ZQ26EOYD.js.map +1 -0
- package/dist/commands/fleet.js +3 -3
- package/dist/commands/init.js +3 -3
- package/dist/commands/start.js +3 -3
- package/dist/commands/watchdog.js +3 -3
- package/dist/index.js +2 -2
- package/dist/main.js +6 -6
- package/dist/start.js +1 -1
- package/package.json +5 -4
- package/dist/chunk-OB6OXLPC.js.map +0 -1
- /package/dist/{chunk-ZA4NWNS6.js.map → chunk-3EB4T7D4.js.map} +0 -0
- /package/dist/{chunk-LYL5GG2F.js.map → chunk-6JB4OAB6.js.map} +0 -0
- /package/dist/{chunk-4C6B2AMB.js.map → chunk-G5LF3BSN.js.map} +0 -0
- /package/dist/{chunk-4YXOQGQC.js.map → chunk-JP3ZHMPE.js.map} +0 -0
- /package/dist/{chunk-K6KL2VD6.js.map → chunk-YJW6OOEJ.js.map} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
startPipeline
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-ZQ26EOYD.js";
|
|
4
4
|
|
|
5
5
|
// packages/cli/src/commands/start.ts
|
|
6
6
|
import { resolve } from "path";
|
|
@@ -66,4 +66,4 @@ Options:
|
|
|
66
66
|
export {
|
|
67
67
|
runStartCommand
|
|
68
68
|
};
|
|
69
|
-
//# sourceMappingURL=chunk-
|
|
69
|
+
//# sourceMappingURL=chunk-3EB4T7D4.js.map
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Watchdog
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-YJW6OOEJ.js";
|
|
4
4
|
import {
|
|
5
5
|
defaultSentinelConfig,
|
|
6
6
|
loadConfig
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-ZQ26EOYD.js";
|
|
8
8
|
|
|
9
9
|
// packages/cli/src/commands/watchdog.ts
|
|
10
10
|
import { resolve } from "path";
|
|
@@ -76,4 +76,4 @@ Options:
|
|
|
76
76
|
export {
|
|
77
77
|
runWatchdogCommand
|
|
78
78
|
};
|
|
79
|
-
//# sourceMappingURL=chunk-
|
|
79
|
+
//# sourceMappingURL=chunk-6JB4OAB6.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
FleetManager
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-YJW6OOEJ.js";
|
|
4
4
|
|
|
5
5
|
// packages/cli/src/commands/fleet.ts
|
|
6
6
|
function formatUptime(seconds) {
|
|
@@ -183,4 +183,4 @@ Commands:
|
|
|
183
183
|
export {
|
|
184
184
|
runFleetCommand
|
|
185
185
|
};
|
|
186
|
-
//# sourceMappingURL=chunk-
|
|
186
|
+
//# sourceMappingURL=chunk-G5LF3BSN.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SesameClient,
|
|
3
3
|
getClaudeCodeOAuthToken
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ZQ26EOYD.js";
|
|
5
5
|
|
|
6
6
|
// packages/cli/src/commands/init.ts
|
|
7
7
|
import { resolve, dirname } from "path";
|
|
@@ -436,4 +436,4 @@ Options:
|
|
|
436
436
|
export {
|
|
437
437
|
runInitCommand
|
|
438
438
|
};
|
|
439
|
-
//# sourceMappingURL=chunk-
|
|
439
|
+
//# sourceMappingURL=chunk-JP3ZHMPE.js.map
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
SesameClient2 as SesameClient,
|
|
8
8
|
WORKER_ROUTES,
|
|
9
9
|
createLogger
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-ZQ26EOYD.js";
|
|
11
11
|
|
|
12
12
|
// packages/runtime/src/watchdog.ts
|
|
13
13
|
import { execSync } from "child_process";
|
|
@@ -1095,4 +1095,4 @@ export {
|
|
|
1095
1095
|
WorkerMemorySync,
|
|
1096
1096
|
PrimaryMemorySync
|
|
1097
1097
|
};
|
|
1098
|
-
//# sourceMappingURL=chunk-
|
|
1098
|
+
//# sourceMappingURL=chunk-YJW6OOEJ.js.map
|
|
@@ -4225,12 +4225,12 @@ var LogWatcher = class extends BackgroundProcess {
|
|
|
4225
4225
|
}
|
|
4226
4226
|
savePositions() {
|
|
4227
4227
|
try {
|
|
4228
|
-
const { mkdirSync:
|
|
4229
|
-
const { dirname:
|
|
4230
|
-
const dir =
|
|
4231
|
-
if (!existsSync7(dir))
|
|
4228
|
+
const { mkdirSync: mkdirSync16, writeFileSync: writeFileSync10 } = __require("fs");
|
|
4229
|
+
const { dirname: dirname10 } = __require("path");
|
|
4230
|
+
const dir = dirname10(this.positionsFile);
|
|
4231
|
+
if (!existsSync7(dir)) mkdirSync16(dir, { recursive: true });
|
|
4232
4232
|
const data = Object.fromEntries(this.tailPositions);
|
|
4233
|
-
|
|
4233
|
+
writeFileSync10(this.positionsFile, JSON.stringify(data));
|
|
4234
4234
|
} catch (err) {
|
|
4235
4235
|
log2.warn("failed to save tail positions", {
|
|
4236
4236
|
error: err.message
|
|
@@ -5335,15 +5335,12 @@ function registerMemoryTools(registry, daemonUrl) {
|
|
|
5335
5335
|
const context = params.context || "global";
|
|
5336
5336
|
const topK = params.top_k || 10;
|
|
5337
5337
|
try {
|
|
5338
|
-
const
|
|
5339
|
-
|
|
5340
|
-
headers: { "Content-Type": "application/json" },
|
|
5341
|
-
body: JSON.stringify({ query, context_name: context, top_k: topK })
|
|
5342
|
-
});
|
|
5338
|
+
const searchParams = new URLSearchParams({ q: query, context, limit: String(topK) });
|
|
5339
|
+
const resp = await fetch(`${daemonUrl}/search?${searchParams}`);
|
|
5343
5340
|
if (!resp.ok) return `Memory search failed: ${resp.status}`;
|
|
5344
5341
|
const data = await resp.json();
|
|
5345
|
-
if (!data.
|
|
5346
|
-
return data.
|
|
5342
|
+
if (!data.episodes?.length) return `No memories found for "${query}" in context "${context}".`;
|
|
5343
|
+
return data.episodes.map((r, i) => `${i + 1}. [score: ${r.score.toFixed(3)}] [${r.context_name}] [${r.role}] ${r.content.slice(0, 200)}`).join("\n");
|
|
5347
5344
|
} catch (err) {
|
|
5348
5345
|
return `Memory daemon unreachable: ${err.message}`;
|
|
5349
5346
|
}
|
|
@@ -5361,12 +5358,12 @@ function registerMemoryTools(registry, daemonUrl) {
|
|
|
5361
5358
|
try {
|
|
5362
5359
|
const healthResp = await fetch(`${daemonUrl}/health`);
|
|
5363
5360
|
const health = healthResp.ok ? await healthResp.json() : { status: "unreachable" };
|
|
5364
|
-
const ctxResp = await fetch(`${daemonUrl}/
|
|
5361
|
+
const ctxResp = await fetch(`${daemonUrl}/contexts`);
|
|
5365
5362
|
const contexts = ctxResp.ok ? (await ctxResp.json()).contexts : [];
|
|
5366
5363
|
const l3Counts = {};
|
|
5367
5364
|
for (const ctx of contexts) {
|
|
5368
5365
|
try {
|
|
5369
|
-
const l3Resp = await fetch(`${daemonUrl}/
|
|
5366
|
+
const l3Resp = await fetch(`${daemonUrl}/promotion/l3?context=${encodeURIComponent(ctx.name)}`);
|
|
5370
5367
|
if (l3Resp.ok) {
|
|
5371
5368
|
const l3Data = await l3Resp.json();
|
|
5372
5369
|
l3Counts[ctx.name] = l3Data.entries?.length ?? 0;
|
|
@@ -5411,7 +5408,7 @@ Contexts:
|
|
|
5411
5408
|
async (params) => {
|
|
5412
5409
|
const context = params.context || "global";
|
|
5413
5410
|
try {
|
|
5414
|
-
const resp = await fetch(`${daemonUrl}/
|
|
5411
|
+
const resp = await fetch(`${daemonUrl}/promotion/l3?context=${encodeURIComponent(context)}`);
|
|
5415
5412
|
if (!resp.ok) return `L3 query failed: ${resp.status}`;
|
|
5416
5413
|
const data = await resp.json();
|
|
5417
5414
|
if (!data.entries?.length) return `No L3 knowledge in context "${context}".`;
|
|
@@ -5442,15 +5439,19 @@ Contexts:
|
|
|
5442
5439
|
const query = params.query;
|
|
5443
5440
|
const topK = params.top_k || 10;
|
|
5444
5441
|
try {
|
|
5445
|
-
const
|
|
5446
|
-
|
|
5447
|
-
headers: { "Content-Type": "application/json" },
|
|
5448
|
-
body: JSON.stringify({ query, top_k: topK })
|
|
5449
|
-
});
|
|
5442
|
+
const crossParams = new URLSearchParams({ q: query, limit: String(topK) });
|
|
5443
|
+
const resp = await fetch(`${daemonUrl}/search/cross-context?${crossParams}`);
|
|
5450
5444
|
if (!resp.ok) return `Cross-context search failed: ${resp.status}`;
|
|
5451
5445
|
const data = await resp.json();
|
|
5452
|
-
|
|
5453
|
-
|
|
5446
|
+
const flat = [];
|
|
5447
|
+
for (const group of data.results || []) {
|
|
5448
|
+
for (const ep of group.episodes) {
|
|
5449
|
+
flat.push({ ...ep, context_name: group.context });
|
|
5450
|
+
}
|
|
5451
|
+
}
|
|
5452
|
+
if (!flat.length) return `No memories found across any context for "${query}".`;
|
|
5453
|
+
flat.sort((a, b) => b.score - a.score);
|
|
5454
|
+
return flat.map((r, i) => `${i + 1}. [${r.score.toFixed(3)}] [${r.context_name}] ${r.content.slice(0, 200)}`).join("\n");
|
|
5454
5455
|
} catch (err) {
|
|
5455
5456
|
return `Memory daemon unreachable: ${err.message}`;
|
|
5456
5457
|
}
|
|
@@ -7808,7 +7809,7 @@ function truncate2(text) {
|
|
|
7808
7809
|
import { execSync as execSync9 } from "child_process";
|
|
7809
7810
|
import { resolve as resolve17 } from "path";
|
|
7810
7811
|
var MAX_OUTPUT6 = 5e4;
|
|
7811
|
-
function registerCodingAgentTools(registry, workspaceDir) {
|
|
7812
|
+
function registerCodingAgentTools(registry, workspaceDir, contextBridge) {
|
|
7812
7813
|
registry.register(
|
|
7813
7814
|
"coding_agent",
|
|
7814
7815
|
"Spawn Claude Code CLI to perform a coding task. Use for writing code, debugging, refactoring, or any task that benefits from an AI coding assistant with full filesystem access. Requires the 'claude' CLI to be installed.",
|
|
@@ -7826,6 +7827,31 @@ function registerCodingAgentTools(registry, workspaceDir) {
|
|
|
7826
7827
|
timeout: {
|
|
7827
7828
|
type: "number",
|
|
7828
7829
|
description: "Timeout in seconds. Default: 300"
|
|
7830
|
+
},
|
|
7831
|
+
requirements: {
|
|
7832
|
+
type: "array",
|
|
7833
|
+
items: { type: "string" },
|
|
7834
|
+
description: "Key requirements or constraints for the task"
|
|
7835
|
+
},
|
|
7836
|
+
recentErrors: {
|
|
7837
|
+
type: "array",
|
|
7838
|
+
items: { type: "string" },
|
|
7839
|
+
description: "Recent errors encountered that may be relevant"
|
|
7840
|
+
},
|
|
7841
|
+
relevantPatterns: {
|
|
7842
|
+
type: "array",
|
|
7843
|
+
items: { type: "string" },
|
|
7844
|
+
description: "Known patterns or approaches that might help"
|
|
7845
|
+
},
|
|
7846
|
+
workingFiles: {
|
|
7847
|
+
type: "array",
|
|
7848
|
+
items: { type: "string" },
|
|
7849
|
+
description: "Files currently being worked on"
|
|
7850
|
+
},
|
|
7851
|
+
knownConstraints: {
|
|
7852
|
+
type: "array",
|
|
7853
|
+
items: { type: "string" },
|
|
7854
|
+
description: "Known constraints or limitations to consider"
|
|
7829
7855
|
}
|
|
7830
7856
|
},
|
|
7831
7857
|
required: ["task"]
|
|
@@ -7834,8 +7860,24 @@ function registerCodingAgentTools(registry, workspaceDir) {
|
|
|
7834
7860
|
const task = params.task;
|
|
7835
7861
|
const timeoutSeconds = params.timeout || 300;
|
|
7836
7862
|
const cwd = params.workdir ? resolve17(workspaceDir, params.workdir) : workspaceDir;
|
|
7837
|
-
|
|
7838
|
-
|
|
7863
|
+
if (contextBridge) {
|
|
7864
|
+
const context = {
|
|
7865
|
+
goal: task,
|
|
7866
|
+
// Extract additional context from params if provided
|
|
7867
|
+
requirements: params.requirements || [],
|
|
7868
|
+
recentErrors: params.recentErrors || [],
|
|
7869
|
+
relevantPatterns: params.relevantPatterns || [],
|
|
7870
|
+
workingFiles: params.workingFiles || [],
|
|
7871
|
+
knownConstraints: params.knownConstraints || []
|
|
7872
|
+
};
|
|
7873
|
+
try {
|
|
7874
|
+
await contextBridge.prepareContext(context);
|
|
7875
|
+
} catch (err) {
|
|
7876
|
+
console.warn("Failed to prepare context for Claude Code:", err);
|
|
7877
|
+
}
|
|
7878
|
+
}
|
|
7879
|
+
const homedir2 = process.env.HOME || "/root";
|
|
7880
|
+
const extendedPath = `${homedir2}/.local/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:${process.env.PATH}`;
|
|
7839
7881
|
try {
|
|
7840
7882
|
execSync9("which claude", { stdio: "ignore", env: { ...process.env, PATH: extendedPath } });
|
|
7841
7883
|
} catch {
|
|
@@ -8070,7 +8112,7 @@ ${findingText}`
|
|
|
8070
8112
|
async function storeInMemory(contextName, topic, findings, synthesis, daemonUrl) {
|
|
8071
8113
|
const storedIds = [];
|
|
8072
8114
|
try {
|
|
8073
|
-
await fetch(`${daemonUrl}/
|
|
8115
|
+
await fetch(`${daemonUrl}/contexts`, {
|
|
8074
8116
|
method: "POST",
|
|
8075
8117
|
headers: { "Content-Type": "application/json" },
|
|
8076
8118
|
body: JSON.stringify({
|
|
@@ -8084,7 +8126,7 @@ async function storeInMemory(contextName, topic, findings, synthesis, daemonUrl)
|
|
|
8084
8126
|
const content = `[Source: ${finding.source}]
|
|
8085
8127
|
${finding.keyPoints.join("\n")}`;
|
|
8086
8128
|
try {
|
|
8087
|
-
const resp = await fetch(`${daemonUrl}/
|
|
8129
|
+
const resp = await fetch(`${daemonUrl}/episodes`, {
|
|
8088
8130
|
method: "POST",
|
|
8089
8131
|
headers: { "Content-Type": "application/json" },
|
|
8090
8132
|
body: JSON.stringify({
|
|
@@ -8101,7 +8143,7 @@ ${finding.keyPoints.join("\n")}`;
|
|
|
8101
8143
|
}
|
|
8102
8144
|
}
|
|
8103
8145
|
try {
|
|
8104
|
-
const resp = await fetch(`${daemonUrl}/
|
|
8146
|
+
const resp = await fetch(`${daemonUrl}/episodes`, {
|
|
8105
8147
|
method: "POST",
|
|
8106
8148
|
headers: { "Content-Type": "application/json" },
|
|
8107
8149
|
body: JSON.stringify({
|
|
@@ -8118,7 +8160,7 @@ ${synthesis}`
|
|
|
8118
8160
|
} catch {
|
|
8119
8161
|
}
|
|
8120
8162
|
try {
|
|
8121
|
-
await fetch(`${daemonUrl}/
|
|
8163
|
+
await fetch(`${daemonUrl}/promotion/run?context=${encodeURIComponent(contextName)}`, {
|
|
8122
8164
|
method: "POST"
|
|
8123
8165
|
});
|
|
8124
8166
|
} catch {
|
|
@@ -8265,28 +8307,30 @@ ${synthesis}${storageNote}`;
|
|
|
8265
8307
|
const daemonUrl = config.memoryDaemonUrl;
|
|
8266
8308
|
try {
|
|
8267
8309
|
if (context) {
|
|
8268
|
-
const
|
|
8269
|
-
|
|
8270
|
-
headers: { "Content-Type": "application/json" },
|
|
8271
|
-
body: JSON.stringify({ query: topic, context_name: context, top_k: 10 })
|
|
8272
|
-
});
|
|
8310
|
+
const searchParams = new URLSearchParams({ q: topic, context, limit: "10" });
|
|
8311
|
+
const resp2 = await fetch(`${daemonUrl}/search?${searchParams}`);
|
|
8273
8312
|
if (!resp2.ok) return `Memory search failed: ${resp2.status}`;
|
|
8274
8313
|
const data2 = await resp2.json();
|
|
8275
|
-
if (!data2.
|
|
8276
|
-
return data2.
|
|
8314
|
+
if (!data2.episodes?.length) return `No learned knowledge found for "${topic}" in context "${context}".`;
|
|
8315
|
+
return data2.episodes.map((r, i) => `${i + 1}. [score: ${r.score.toFixed(3)}] [${r.role}]
|
|
8277
8316
|
${r.content.slice(0, 500)}`).join("\n\n");
|
|
8278
8317
|
}
|
|
8279
|
-
const
|
|
8280
|
-
|
|
8281
|
-
headers: { "Content-Type": "application/json" },
|
|
8282
|
-
body: JSON.stringify({ query: topic, top_k: 15 })
|
|
8283
|
-
});
|
|
8318
|
+
const crossParams = new URLSearchParams({ q: topic, limit: "15" });
|
|
8319
|
+
const resp = await fetch(`${daemonUrl}/search/cross-context?${crossParams}`);
|
|
8284
8320
|
if (!resp.ok) return `Memory cross-search failed: ${resp.status}`;
|
|
8285
8321
|
const data = await resp.json();
|
|
8286
|
-
const learnResults =
|
|
8322
|
+
const learnResults = [];
|
|
8323
|
+
for (const group of data.results || []) {
|
|
8324
|
+
if (group.context.startsWith("learn-")) {
|
|
8325
|
+
for (const ep of group.episodes) {
|
|
8326
|
+
learnResults.push({ ...ep, context_name: group.context });
|
|
8327
|
+
}
|
|
8328
|
+
}
|
|
8329
|
+
}
|
|
8287
8330
|
if (learnResults.length === 0) {
|
|
8288
8331
|
return `No previously learned knowledge found for "${topic}". Use the learn tool first.`;
|
|
8289
8332
|
}
|
|
8333
|
+
learnResults.sort((a, b) => b.score - a.score);
|
|
8290
8334
|
return learnResults.map((r, i) => `${i + 1}. [score: ${r.score.toFixed(3)}] [${r.context_name}] [${r.role}]
|
|
8291
8335
|
${r.content.slice(0, 500)}`).join("\n\n");
|
|
8292
8336
|
} catch (err) {
|
|
@@ -8325,7 +8369,7 @@ function registerAllTools(hivemindHome, config) {
|
|
|
8325
8369
|
registerWatchTools(registry, workspaceDir, dataDir);
|
|
8326
8370
|
registerMacOSTools(registry, workspaceDir);
|
|
8327
8371
|
registerDataTools(registry, workspaceDir);
|
|
8328
|
-
registerCodingAgentTools(registry, workspaceDir);
|
|
8372
|
+
registerCodingAgentTools(registry, workspaceDir, config?.contextBridge);
|
|
8329
8373
|
registerLearnTools(registry, {
|
|
8330
8374
|
llmConfig: config?.llmConfig,
|
|
8331
8375
|
memoryDaemonUrl: config?.memoryDaemonUrl || "http://localhost:3434",
|
|
@@ -8534,13 +8578,224 @@ Path: ${skillDir}`;
|
|
|
8534
8578
|
}
|
|
8535
8579
|
|
|
8536
8580
|
// packages/runtime/src/pipeline.ts
|
|
8537
|
-
import { readFileSync as
|
|
8538
|
-
import { resolve as resolve20, dirname as
|
|
8581
|
+
import { readFileSync as readFileSync16, writeFileSync as writeFileSync9, unlinkSync as unlinkSync3 } from "fs";
|
|
8582
|
+
import { resolve as resolve20, dirname as dirname9 } from "path";
|
|
8539
8583
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
8584
|
+
|
|
8585
|
+
// packages/runtime/src/tools/context-bridge.ts
|
|
8586
|
+
import { writeFileSync as writeFileSync8, readFileSync as readFileSync15, existsSync as existsSync20, mkdirSync as mkdirSync15, watchFile, unwatchFile } from "fs";
|
|
8587
|
+
import { join as join8, dirname as dirname8 } from "path";
|
|
8588
|
+
import { homedir } from "os";
|
|
8589
|
+
import { EventEmitter as EventEmitter2 } from "events";
|
|
8590
|
+
var ClaudeContextBridge = class extends EventEmitter2 {
|
|
8591
|
+
workspaceDir;
|
|
8592
|
+
memoryClient;
|
|
8593
|
+
logger;
|
|
8594
|
+
sessionLogPath;
|
|
8595
|
+
contextFilePath;
|
|
8596
|
+
claudeSettingsPath;
|
|
8597
|
+
logWatcher;
|
|
8598
|
+
constructor(config) {
|
|
8599
|
+
super();
|
|
8600
|
+
this.workspaceDir = config.workspaceDir;
|
|
8601
|
+
this.memoryClient = config.memoryClient;
|
|
8602
|
+
this.logger = config.logger;
|
|
8603
|
+
this.sessionLogPath = join8(homedir(), ".claude", "session.log");
|
|
8604
|
+
this.contextFilePath = join8(this.workspaceDir, "CLAUDE_CONTEXT.md");
|
|
8605
|
+
this.claudeSettingsPath = join8(homedir(), ".claude", "settings.json");
|
|
8606
|
+
}
|
|
8607
|
+
/**
|
|
8608
|
+
* Initialize the context bridge
|
|
8609
|
+
*/
|
|
8610
|
+
async initialize() {
|
|
8611
|
+
const claudeDir = dirname8(this.claudeSettingsPath);
|
|
8612
|
+
if (!existsSync20(claudeDir)) {
|
|
8613
|
+
mkdirSync15(claudeDir, { recursive: true });
|
|
8614
|
+
}
|
|
8615
|
+
await this.setupClaudeSettings();
|
|
8616
|
+
this.startLogMonitoring();
|
|
8617
|
+
this.logger.info("Claude context bridge initialized");
|
|
8618
|
+
}
|
|
8619
|
+
/**
|
|
8620
|
+
* Configure Claude Code to report insights
|
|
8621
|
+
*/
|
|
8622
|
+
async setupClaudeSettings() {
|
|
8623
|
+
const customInstructions = `# Hivemind Context Bridge
|
|
8624
|
+
|
|
8625
|
+
When working on tasks, please report significant findings by writing to the session log:
|
|
8626
|
+
|
|
8627
|
+
- When you discover architecture/patterns: echo "DISCOVERY: [details]" >> ~/.claude/session.log
|
|
8628
|
+
- When you need more context: echo "NEED: [what you need]" >> ~/.claude/session.log
|
|
8629
|
+
- When you complete major steps: echo "COMPLETE: [what you did]" >> ~/.claude/session.log
|
|
8630
|
+
- When you find reusable solutions: echo "PATTERN: [approach]" >> ~/.claude/session.log
|
|
8631
|
+
- When you encounter errors: echo "ERROR: [error details]" >> ~/.claude/session.log
|
|
8632
|
+
|
|
8633
|
+
Always check ~/hivemind/workspace/CLAUDE_CONTEXT.md for task context and requirements.`;
|
|
8634
|
+
const settings = {
|
|
8635
|
+
customInstructions,
|
|
8636
|
+
alwaysIncludeFiles: [
|
|
8637
|
+
this.contextFilePath,
|
|
8638
|
+
join8(this.workspaceDir, "ARCHITECTURE.md"),
|
|
8639
|
+
join8(this.workspaceDir, "TOOLS.md")
|
|
8640
|
+
],
|
|
8641
|
+
// Enable verbose logging for better insights
|
|
8642
|
+
verboseLogging: true
|
|
8643
|
+
};
|
|
8644
|
+
writeFileSync8(this.claudeSettingsPath, JSON.stringify(settings, null, 2));
|
|
8645
|
+
this.logger.info("Claude settings configured for context bridge");
|
|
8646
|
+
}
|
|
8647
|
+
/**
|
|
8648
|
+
* Prepare context for a Claude Code session
|
|
8649
|
+
*/
|
|
8650
|
+
async prepareContext(context) {
|
|
8651
|
+
let content = `# Claude Code Context
|
|
8652
|
+
Generated: ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
8653
|
+
|
|
8654
|
+
## Current Goal
|
|
8655
|
+
${context.goal}
|
|
8656
|
+
`;
|
|
8657
|
+
if (context.requirements?.length) {
|
|
8658
|
+
content += `
|
|
8659
|
+
## Requirements
|
|
8660
|
+
${context.requirements.map((r) => `- ${r}`).join("\n")}
|
|
8661
|
+
`;
|
|
8662
|
+
}
|
|
8663
|
+
if (context.recentErrors?.length) {
|
|
8664
|
+
content += `
|
|
8665
|
+
## Recent Errors
|
|
8666
|
+
\`\`\`
|
|
8667
|
+
${context.recentErrors.join("\n")}
|
|
8668
|
+
\`\`\`
|
|
8669
|
+
`;
|
|
8670
|
+
}
|
|
8671
|
+
if (context.relevantPatterns?.length) {
|
|
8672
|
+
content += `
|
|
8673
|
+
## Known Patterns
|
|
8674
|
+
${context.relevantPatterns.map((p) => `- ${p}`).join("\n")}
|
|
8675
|
+
`;
|
|
8676
|
+
}
|
|
8677
|
+
if (context.workingFiles?.length) {
|
|
8678
|
+
content += `
|
|
8679
|
+
## Working Files
|
|
8680
|
+
${context.workingFiles.map((f) => `- ${f}`).join("\n")}
|
|
8681
|
+
`;
|
|
8682
|
+
}
|
|
8683
|
+
if (context.knownConstraints?.length) {
|
|
8684
|
+
content += `
|
|
8685
|
+
## Known Constraints
|
|
8686
|
+
${context.knownConstraints.map((c) => `- ${c}`).join("\n")}
|
|
8687
|
+
`;
|
|
8688
|
+
}
|
|
8689
|
+
try {
|
|
8690
|
+
const memories = await this.getRelevantMemories(context.goal);
|
|
8691
|
+
if (memories.length > 0) {
|
|
8692
|
+
content += `
|
|
8693
|
+
## Relevant Knowledge
|
|
8694
|
+
${memories.join("\n\n")}
|
|
8695
|
+
`;
|
|
8696
|
+
}
|
|
8697
|
+
} catch (err) {
|
|
8698
|
+
this.logger.warn("Failed to fetch memories for context", err);
|
|
8699
|
+
}
|
|
8700
|
+
writeFileSync8(this.contextFilePath, content);
|
|
8701
|
+
this.logger.info("Context prepared for Claude Code", { goal: context.goal });
|
|
8702
|
+
}
|
|
8703
|
+
/**
|
|
8704
|
+
* Fetch relevant memories for the task
|
|
8705
|
+
*/
|
|
8706
|
+
async getRelevantMemories(goal) {
|
|
8707
|
+
try {
|
|
8708
|
+
const results = await this.memoryClient.search(goal, "global", 5);
|
|
8709
|
+
return results.map((r) => `- ${r.content}`);
|
|
8710
|
+
} catch (err) {
|
|
8711
|
+
return [];
|
|
8712
|
+
}
|
|
8713
|
+
}
|
|
8714
|
+
/**
|
|
8715
|
+
* Start monitoring Claude's session log for insights
|
|
8716
|
+
*/
|
|
8717
|
+
startLogMonitoring() {
|
|
8718
|
+
if (!existsSync20(this.sessionLogPath)) {
|
|
8719
|
+
writeFileSync8(this.sessionLogPath, "");
|
|
8720
|
+
}
|
|
8721
|
+
let lastSize = 0;
|
|
8722
|
+
watchFile(this.sessionLogPath, { interval: 1e3 }, (curr, prev) => {
|
|
8723
|
+
if (curr.size > lastSize) {
|
|
8724
|
+
const content = readFileSync15(this.sessionLogPath, "utf-8");
|
|
8725
|
+
const newContent = content.slice(lastSize);
|
|
8726
|
+
lastSize = curr.size;
|
|
8727
|
+
const lines = newContent.split("\n").filter((line) => line.trim());
|
|
8728
|
+
for (const line of lines) {
|
|
8729
|
+
this.processLogLine(line);
|
|
8730
|
+
}
|
|
8731
|
+
}
|
|
8732
|
+
});
|
|
8733
|
+
this.logger.info("Started monitoring Claude session log");
|
|
8734
|
+
}
|
|
8735
|
+
/**
|
|
8736
|
+
* Process a line from Claude's session log
|
|
8737
|
+
*/
|
|
8738
|
+
processLogLine(line) {
|
|
8739
|
+
const patterns = {
|
|
8740
|
+
DISCOVERY: /^DISCOVERY:\s*(.+)$/,
|
|
8741
|
+
NEED: /^NEED:\s*(.+)$/,
|
|
8742
|
+
COMPLETE: /^COMPLETE:\s*(.+)$/,
|
|
8743
|
+
PATTERN: /^PATTERN:\s*(.+)$/,
|
|
8744
|
+
ERROR: /^ERROR:\s*(.+)$/
|
|
8745
|
+
};
|
|
8746
|
+
for (const [type, pattern] of Object.entries(patterns)) {
|
|
8747
|
+
const match = line.match(pattern);
|
|
8748
|
+
if (match) {
|
|
8749
|
+
const content = match[1];
|
|
8750
|
+
this.handleInsight(type, content);
|
|
8751
|
+
break;
|
|
8752
|
+
}
|
|
8753
|
+
}
|
|
8754
|
+
}
|
|
8755
|
+
/**
|
|
8756
|
+
* Handle an insight from Claude Code
|
|
8757
|
+
*/
|
|
8758
|
+
async handleInsight(type, content) {
|
|
8759
|
+
this.logger.info(`Claude insight: ${type}`, { content });
|
|
8760
|
+
this.emit("insight", { type, content });
|
|
8761
|
+
if (["DISCOVERY", "PATTERN"].includes(type)) {
|
|
8762
|
+
try {
|
|
8763
|
+
await this.memoryClient.store({
|
|
8764
|
+
content: `Claude Code ${type}: ${content}`,
|
|
8765
|
+
metadata: {
|
|
8766
|
+
source: "claude-code",
|
|
8767
|
+
type: type.toLowerCase(),
|
|
8768
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
8769
|
+
}
|
|
8770
|
+
});
|
|
8771
|
+
} catch (err) {
|
|
8772
|
+
this.logger.warn("Failed to store Claude insight in memory", err);
|
|
8773
|
+
}
|
|
8774
|
+
}
|
|
8775
|
+
if (type === "NEED") {
|
|
8776
|
+
this.emit("context-request", content);
|
|
8777
|
+
}
|
|
8778
|
+
}
|
|
8779
|
+
/**
|
|
8780
|
+
* Clean up resources
|
|
8781
|
+
*/
|
|
8782
|
+
destroy() {
|
|
8783
|
+
if (this.sessionLogPath && existsSync20(this.sessionLogPath)) {
|
|
8784
|
+
unwatchFile(this.sessionLogPath);
|
|
8785
|
+
}
|
|
8786
|
+
}
|
|
8787
|
+
};
|
|
8788
|
+
async function createContextBridge(config) {
|
|
8789
|
+
const bridge = new ClaudeContextBridge(config);
|
|
8790
|
+
await bridge.initialize();
|
|
8791
|
+
return bridge;
|
|
8792
|
+
}
|
|
8793
|
+
|
|
8794
|
+
// packages/runtime/src/pipeline.ts
|
|
8540
8795
|
var PACKAGE_VERSION = "unknown";
|
|
8541
8796
|
try {
|
|
8542
|
-
const __dirname2 =
|
|
8543
|
-
const pkg = JSON.parse(
|
|
8797
|
+
const __dirname2 = dirname9(fileURLToPath3(import.meta.url));
|
|
8798
|
+
const pkg = JSON.parse(readFileSync16(resolve20(__dirname2, "../package.json"), "utf-8"));
|
|
8544
8799
|
PACKAGE_VERSION = pkg.version ?? "unknown";
|
|
8545
8800
|
} catch {
|
|
8546
8801
|
}
|
|
@@ -8582,7 +8837,7 @@ function startHealthServer(port) {
|
|
|
8582
8837
|
return server;
|
|
8583
8838
|
}
|
|
8584
8839
|
function writePidFile(path) {
|
|
8585
|
-
|
|
8840
|
+
writeFileSync9(path, String(process.pid));
|
|
8586
8841
|
console.log(`[hivemind] PID file written: ${path}`);
|
|
8587
8842
|
}
|
|
8588
8843
|
function cleanupPidFile(path) {
|
|
@@ -8623,20 +8878,34 @@ async function startPipeline(configPath) {
|
|
|
8623
8878
|
console.log("[hivemind] Global context already exists in memory daemon");
|
|
8624
8879
|
}
|
|
8625
8880
|
}
|
|
8626
|
-
const requestLogger = new RequestLogger(resolve20(
|
|
8881
|
+
const requestLogger = new RequestLogger(resolve20(dirname9(configPath), "data", "dashboard.db"));
|
|
8627
8882
|
const agent = new Agent(config);
|
|
8628
8883
|
startDashboardServer(requestLogger, config.memory, () => agent.getConversationHistories());
|
|
8629
8884
|
agent.setRequestLogger(requestLogger);
|
|
8630
8885
|
const hivemindHome = process.env.HIVEMIND_HOME || resolve20(process.env.HOME || "/root", "hivemind");
|
|
8886
|
+
const workspaceDir = resolve20(hivemindHome, config.agent.workspace || "workspace");
|
|
8887
|
+
let contextBridge;
|
|
8888
|
+
if (memoryConnected) {
|
|
8889
|
+
try {
|
|
8890
|
+
contextBridge = await createContextBridge({
|
|
8891
|
+
workspaceDir,
|
|
8892
|
+
memoryClient: memory,
|
|
8893
|
+
logger: createLogger("claude-bridge")
|
|
8894
|
+
});
|
|
8895
|
+
console.log("[hivemind] Claude context bridge initialized");
|
|
8896
|
+
} catch (err) {
|
|
8897
|
+
console.warn("[hivemind] Failed to create Claude context bridge:", err);
|
|
8898
|
+
}
|
|
8899
|
+
}
|
|
8631
8900
|
const toolRegistry = registerAllTools(hivemindHome, {
|
|
8632
8901
|
enabled: true,
|
|
8633
8902
|
workspace: config.agent.workspace || "workspace",
|
|
8634
8903
|
braveApiKey: process.env.BRAVE_API_KEY,
|
|
8635
8904
|
memoryDaemonUrl: config.memory.daemon_url,
|
|
8636
8905
|
configPath,
|
|
8637
|
-
llmConfig: config.llm
|
|
8906
|
+
llmConfig: config.llm,
|
|
8907
|
+
contextBridge
|
|
8638
8908
|
});
|
|
8639
|
-
const workspaceDir = resolve20(hivemindHome, config.agent.workspace || "workspace");
|
|
8640
8909
|
const skillsEngine = new SkillsEngine(workspaceDir, toolRegistry);
|
|
8641
8910
|
await skillsEngine.loadAll();
|
|
8642
8911
|
registerSkillsTools(toolRegistry, skillsEngine, workspaceDir);
|
|
@@ -8886,7 +9155,7 @@ async function runSpawnTask(config, configPath) {
|
|
|
8886
9155
|
const result = response.content;
|
|
8887
9156
|
console.log(`[spawn] Task completed (context: ${response.context})`);
|
|
8888
9157
|
if (spawnDir) {
|
|
8889
|
-
|
|
9158
|
+
writeFileSync9(resolve20(spawnDir, "result.txt"), result);
|
|
8890
9159
|
}
|
|
8891
9160
|
if (channelId && config.sesame.api_key) {
|
|
8892
9161
|
try {
|
|
@@ -8903,7 +9172,7 @@ async function runSpawnTask(config, configPath) {
|
|
|
8903
9172
|
const errorMsg = `[SPAWN ERROR] ${err.message}`;
|
|
8904
9173
|
console.error(`[spawn] ${errorMsg}`);
|
|
8905
9174
|
if (spawnDir) {
|
|
8906
|
-
|
|
9175
|
+
writeFileSync9(resolve20(spawnDir, "result.txt"), errorMsg);
|
|
8907
9176
|
}
|
|
8908
9177
|
process.exitCode = 1;
|
|
8909
9178
|
}
|
|
@@ -9415,4 +9684,4 @@ smol-toml/dist/index.js:
|
|
|
9415
9684
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
9416
9685
|
*)
|
|
9417
9686
|
*/
|
|
9418
|
-
//# sourceMappingURL=chunk-
|
|
9687
|
+
//# sourceMappingURL=chunk-ZQ26EOYD.js.map
|