@sesamespace/hivemind 0.11.5 → 0.12.1

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.
@@ -7,7 +7,7 @@ import {
7
7
  SesameClient2 as SesameClient,
8
8
  WORKER_ROUTES,
9
9
  createLogger
10
- } from "./chunk-EKZ3IZU6.js";
10
+ } from "./chunk-7XXV5FKN.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-MWQZTAYA.js.map
1098
+ //# sourceMappingURL=chunk-6IAV6YAV.js.map
@@ -4225,12 +4225,12 @@ var LogWatcher = class extends BackgroundProcess {
4225
4225
  }
4226
4226
  savePositions() {
4227
4227
  try {
4228
- const { mkdirSync: mkdirSync15, writeFileSync: writeFileSync9 } = __require("fs");
4228
+ const { mkdirSync: mkdirSync16, writeFileSync: writeFileSync10 } = __require("fs");
4229
4229
  const { dirname: dirname9 } = __require("path");
4230
4230
  const dir = dirname9(this.positionsFile);
4231
- if (!existsSync7(dir)) mkdirSync15(dir, { recursive: true });
4231
+ if (!existsSync7(dir)) mkdirSync16(dir, { recursive: true });
4232
4232
  const data = Object.fromEntries(this.tailPositions);
4233
- writeFileSync9(this.positionsFile, JSON.stringify(data));
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
@@ -7806,10 +7806,10 @@ function truncate2(text) {
7806
7806
  }
7807
7807
 
7808
7808
  // packages/runtime/src/tools/coding-agent.ts
7809
- import { execSync as execSync9 } from "child_process";
7809
+ import { exec as exec2, execSync as execSync9 } from "child_process";
7810
7810
  import { resolve as resolve17 } from "path";
7811
7811
  var MAX_OUTPUT6 = 5e4;
7812
- function registerCodingAgentTools(registry, workspaceDir) {
7812
+ function registerCodingAgentTools(registry, workspaceDir, contextBridge) {
7813
7813
  registry.register(
7814
7814
  "coding_agent",
7815
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.",
@@ -7827,6 +7827,31 @@ function registerCodingAgentTools(registry, workspaceDir) {
7827
7827
  timeout: {
7828
7828
  type: "number",
7829
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"
7830
7855
  }
7831
7856
  },
7832
7857
  required: ["task"]
@@ -7835,8 +7860,24 @@ function registerCodingAgentTools(registry, workspaceDir) {
7835
7860
  const task = params.task;
7836
7861
  const timeoutSeconds = params.timeout || 300;
7837
7862
  const cwd = params.workdir ? resolve17(workspaceDir, params.workdir) : workspaceDir;
7838
- const homedir = process.env.HOME || "/root";
7839
- const extendedPath = `${homedir}/.local/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:${process.env.PATH}`;
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}`;
7840
7881
  try {
7841
7882
  execSync9("which claude", { stdio: "ignore", env: { ...process.env, PATH: extendedPath } });
7842
7883
  } catch {
@@ -7845,17 +7886,28 @@ function registerCodingAgentTools(registry, workspaceDir) {
7845
7886
  const escapedTask = task.replace(/'/g, "'\\''");
7846
7887
  const command = `claude --dangerously-skip-permissions -p '${escapedTask}'`;
7847
7888
  try {
7848
- const output = execSync9(command, {
7849
- cwd,
7850
- timeout: timeoutSeconds * 1e3,
7851
- encoding: "utf-8",
7852
- maxBuffer: 10 * 1024 * 1024,
7853
- // 10MB
7854
- shell: "/bin/sh",
7855
- env: {
7856
- ...process.env,
7857
- PATH: extendedPath
7858
- }
7889
+ const output = await new Promise((resolve21, reject) => {
7890
+ const child = exec2(command, {
7891
+ cwd,
7892
+ timeout: timeoutSeconds * 1e3,
7893
+ encoding: "utf-8",
7894
+ maxBuffer: 10 * 1024 * 1024,
7895
+ // 10MB
7896
+ shell: "/bin/sh",
7897
+ env: {
7898
+ ...process.env,
7899
+ PATH: extendedPath
7900
+ }
7901
+ }, (error, stdout, stderr) => {
7902
+ if (error) {
7903
+ error.stdout = stdout;
7904
+ error.stderr = stderr;
7905
+ reject(error);
7906
+ } else {
7907
+ resolve21(stdout);
7908
+ }
7909
+ });
7910
+ child.stdin?.end();
7859
7911
  });
7860
7912
  const trimmed = output.length > MAX_OUTPUT6 ? output.slice(0, MAX_OUTPUT6) + `
7861
7913
  ... (truncated, ${output.length} total chars)` : output;
@@ -8328,7 +8380,7 @@ function registerAllTools(hivemindHome, config) {
8328
8380
  registerWatchTools(registry, workspaceDir, dataDir);
8329
8381
  registerMacOSTools(registry, workspaceDir);
8330
8382
  registerDataTools(registry, workspaceDir);
8331
- registerCodingAgentTools(registry, workspaceDir);
8383
+ registerCodingAgentTools(registry, workspaceDir, config?.contextBridge);
8332
8384
  registerLearnTools(registry, {
8333
8385
  llmConfig: config?.llmConfig,
8334
8386
  memoryDaemonUrl: config?.memoryDaemonUrl || "http://localhost:3434",
@@ -8537,9 +8589,218 @@ Path: ${skillDir}`;
8537
8589
  }
8538
8590
 
8539
8591
  // packages/runtime/src/pipeline.ts
8540
- import { readFileSync as readFileSync15, writeFileSync as writeFileSync8, unlinkSync as unlinkSync3 } from "fs";
8592
+ import { readFileSync as readFileSync15, writeFileSync as writeFileSync9, unlinkSync as unlinkSync3 } from "fs";
8541
8593
  import { resolve as resolve20, dirname as dirname8 } from "path";
8542
8594
  import { fileURLToPath as fileURLToPath3 } from "url";
8595
+
8596
+ // packages/runtime/src/tools/context-bridge.ts
8597
+ import { writeFileSync as writeFileSync8, existsSync as existsSync20, mkdirSync as mkdirSync15, watchFile, unwatchFile, openSync, readSync, closeSync } from "fs";
8598
+ import { join as join8 } from "path";
8599
+ import { homedir } from "os";
8600
+ import { EventEmitter as EventEmitter2 } from "events";
8601
+ var ClaudeContextBridge = class extends EventEmitter2 {
8602
+ workspaceDir;
8603
+ memoryClient;
8604
+ logger;
8605
+ sessionLogPath;
8606
+ contextFilePath;
8607
+ constructor(config) {
8608
+ super();
8609
+ this.workspaceDir = config.workspaceDir;
8610
+ this.memoryClient = config.memoryClient;
8611
+ this.logger = config.logger;
8612
+ this.sessionLogPath = join8(homedir(), ".claude", "session.log");
8613
+ this.contextFilePath = join8(this.workspaceDir, "CLAUDE_CONTEXT.md");
8614
+ }
8615
+ /**
8616
+ * Initialize the context bridge
8617
+ */
8618
+ async initialize() {
8619
+ const claudeDir = join8(homedir(), ".claude");
8620
+ if (!existsSync20(claudeDir)) {
8621
+ mkdirSync15(claudeDir, { recursive: true });
8622
+ }
8623
+ await this.setupClaudeSettings();
8624
+ this.startLogMonitoring();
8625
+ this.logger.info("Claude context bridge initialized");
8626
+ }
8627
+ /**
8628
+ * Configure Claude Code to report insights via workspace CLAUDE.md
8629
+ */
8630
+ async setupClaudeSettings() {
8631
+ const instructions = `# Hivemind Context Bridge
8632
+
8633
+ When working on tasks, please report significant findings by writing to the session log:
8634
+
8635
+ - When you discover architecture/patterns: echo "DISCOVERY: [details]" >> ~/.claude/session.log
8636
+ - When you need more context: echo "NEED: [what you need]" >> ~/.claude/session.log
8637
+ - When you complete major steps: echo "COMPLETE: [what you did]" >> ~/.claude/session.log
8638
+ - When you find reusable solutions: echo "PATTERN: [approach]" >> ~/.claude/session.log
8639
+ - When you encounter errors: echo "ERROR: [error details]" >> ~/.claude/session.log
8640
+
8641
+ Always check CLAUDE_CONTEXT.md in the workspace for task context and requirements.`;
8642
+ const claudeMdPath = join8(this.workspaceDir, "CLAUDE.md");
8643
+ writeFileSync8(claudeMdPath, instructions);
8644
+ this.logger.info("Claude workspace CLAUDE.md configured for context bridge");
8645
+ }
8646
+ /**
8647
+ * Prepare context for a Claude Code session
8648
+ */
8649
+ async prepareContext(context) {
8650
+ let content = `# Claude Code Context
8651
+ Generated: ${(/* @__PURE__ */ new Date()).toISOString()}
8652
+
8653
+ ## Current Goal
8654
+ ${context.goal}
8655
+ `;
8656
+ if (context.requirements?.length) {
8657
+ content += `
8658
+ ## Requirements
8659
+ ${context.requirements.map((r) => `- ${r}`).join("\n")}
8660
+ `;
8661
+ }
8662
+ if (context.recentErrors?.length) {
8663
+ content += `
8664
+ ## Recent Errors
8665
+ \`\`\`
8666
+ ${context.recentErrors.join("\n")}
8667
+ \`\`\`
8668
+ `;
8669
+ }
8670
+ if (context.relevantPatterns?.length) {
8671
+ content += `
8672
+ ## Known Patterns
8673
+ ${context.relevantPatterns.map((p) => `- ${p}`).join("\n")}
8674
+ `;
8675
+ }
8676
+ if (context.workingFiles?.length) {
8677
+ content += `
8678
+ ## Working Files
8679
+ ${context.workingFiles.map((f) => `- ${f}`).join("\n")}
8680
+ `;
8681
+ }
8682
+ if (context.knownConstraints?.length) {
8683
+ content += `
8684
+ ## Known Constraints
8685
+ ${context.knownConstraints.map((c) => `- ${c}`).join("\n")}
8686
+ `;
8687
+ }
8688
+ try {
8689
+ const memories = await this.getRelevantMemories(context.goal);
8690
+ if (memories.length > 0) {
8691
+ content += `
8692
+ ## Relevant Knowledge
8693
+ ${memories.join("\n\n")}
8694
+ `;
8695
+ }
8696
+ } catch (err) {
8697
+ this.logger.warn("Failed to fetch memories for context", err);
8698
+ }
8699
+ writeFileSync8(this.contextFilePath, content);
8700
+ this.logger.info("Context prepared for Claude Code", { goal: context.goal });
8701
+ }
8702
+ /**
8703
+ * Fetch relevant memories for the task
8704
+ */
8705
+ async getRelevantMemories(goal) {
8706
+ try {
8707
+ const results = await Promise.race([
8708
+ this.memoryClient.search(goal, "global", 5),
8709
+ new Promise(
8710
+ (_, reject) => setTimeout(() => reject(new Error("Memory search timeout")), 3e3)
8711
+ )
8712
+ ]);
8713
+ return results.map((r) => `- ${r.content}`);
8714
+ } catch {
8715
+ return [];
8716
+ }
8717
+ }
8718
+ /**
8719
+ * Start monitoring Claude's session log for insights
8720
+ */
8721
+ startLogMonitoring() {
8722
+ if (!existsSync20(this.sessionLogPath)) {
8723
+ writeFileSync8(this.sessionLogPath, "");
8724
+ }
8725
+ let lastSize = 0;
8726
+ watchFile(this.sessionLogPath, { interval: 2e3 }, (curr) => {
8727
+ if (curr.size > lastSize) {
8728
+ try {
8729
+ const fd = openSync(this.sessionLogPath, "r");
8730
+ const buf = Buffer.alloc(curr.size - lastSize);
8731
+ readSync(fd, buf, 0, buf.length, lastSize);
8732
+ closeSync(fd);
8733
+ lastSize = curr.size;
8734
+ const lines = buf.toString("utf-8").split("\n").filter((l) => l.trim());
8735
+ for (const line of lines) {
8736
+ this.processLogLine(line);
8737
+ }
8738
+ } catch (err) {
8739
+ this.logger.warn("Failed to read session log", { error: String(err) });
8740
+ }
8741
+ }
8742
+ });
8743
+ this.logger.info("Started monitoring Claude session log");
8744
+ }
8745
+ /**
8746
+ * Process a line from Claude's session log
8747
+ */
8748
+ processLogLine(line) {
8749
+ const patterns = {
8750
+ DISCOVERY: /^DISCOVERY:\s*(.+)$/,
8751
+ NEED: /^NEED:\s*(.+)$/,
8752
+ COMPLETE: /^COMPLETE:\s*(.+)$/,
8753
+ PATTERN: /^PATTERN:\s*(.+)$/,
8754
+ ERROR: /^ERROR:\s*(.+)$/
8755
+ };
8756
+ for (const [type, pattern] of Object.entries(patterns)) {
8757
+ const match = line.match(pattern);
8758
+ if (match) {
8759
+ const content = match[1];
8760
+ this.handleInsight(type, content).catch((err) => {
8761
+ this.logger.warn("Failed to handle insight", { error: String(err) });
8762
+ });
8763
+ break;
8764
+ }
8765
+ }
8766
+ }
8767
+ /**
8768
+ * Handle an insight from Claude Code
8769
+ */
8770
+ async handleInsight(type, content) {
8771
+ this.logger.info(`Claude insight: ${type}`, { content });
8772
+ this.emit("insight", { type, content });
8773
+ if (["DISCOVERY", "PATTERN"].includes(type)) {
8774
+ try {
8775
+ await this.memoryClient.storeEpisode({
8776
+ context_name: "claude-code",
8777
+ role: "system",
8778
+ content: `Claude Code ${type}: ${content}`
8779
+ });
8780
+ } catch (err) {
8781
+ this.logger.warn("Failed to store Claude insight in memory", err);
8782
+ }
8783
+ }
8784
+ if (type === "NEED") {
8785
+ this.emit("context-request", content);
8786
+ }
8787
+ }
8788
+ /**
8789
+ * Clean up resources
8790
+ */
8791
+ destroy() {
8792
+ if (this.sessionLogPath && existsSync20(this.sessionLogPath)) {
8793
+ unwatchFile(this.sessionLogPath);
8794
+ }
8795
+ }
8796
+ };
8797
+ async function createContextBridge(config) {
8798
+ const bridge = new ClaudeContextBridge(config);
8799
+ await bridge.initialize();
8800
+ return bridge;
8801
+ }
8802
+
8803
+ // packages/runtime/src/pipeline.ts
8543
8804
  var PACKAGE_VERSION = "unknown";
8544
8805
  try {
8545
8806
  const __dirname2 = dirname8(fileURLToPath3(import.meta.url));
@@ -8585,7 +8846,7 @@ function startHealthServer(port) {
8585
8846
  return server;
8586
8847
  }
8587
8848
  function writePidFile(path) {
8588
- writeFileSync8(path, String(process.pid));
8849
+ writeFileSync9(path, String(process.pid));
8589
8850
  console.log(`[hivemind] PID file written: ${path}`);
8590
8851
  }
8591
8852
  function cleanupPidFile(path) {
@@ -8631,15 +8892,32 @@ async function startPipeline(configPath) {
8631
8892
  startDashboardServer(requestLogger, config.memory, () => agent.getConversationHistories());
8632
8893
  agent.setRequestLogger(requestLogger);
8633
8894
  const hivemindHome = process.env.HIVEMIND_HOME || resolve20(process.env.HOME || "/root", "hivemind");
8895
+ const workspaceDir = resolve20(hivemindHome, config.agent.workspace || "workspace");
8896
+ let contextBridge;
8897
+ if (memoryConnected) {
8898
+ try {
8899
+ contextBridge = await createContextBridge({
8900
+ workspaceDir,
8901
+ memoryClient: memory,
8902
+ logger: createLogger("claude-bridge")
8903
+ });
8904
+ console.log("[hivemind] Claude context bridge initialized");
8905
+ } catch (err) {
8906
+ console.warn("[hivemind] Failed to create Claude context bridge:", err);
8907
+ }
8908
+ }
8909
+ if (contextBridge) {
8910
+ process.on("exit", () => contextBridge.destroy());
8911
+ }
8634
8912
  const toolRegistry = registerAllTools(hivemindHome, {
8635
8913
  enabled: true,
8636
8914
  workspace: config.agent.workspace || "workspace",
8637
8915
  braveApiKey: process.env.BRAVE_API_KEY,
8638
8916
  memoryDaemonUrl: config.memory.daemon_url,
8639
8917
  configPath,
8640
- llmConfig: config.llm
8918
+ llmConfig: config.llm,
8919
+ contextBridge
8641
8920
  });
8642
- const workspaceDir = resolve20(hivemindHome, config.agent.workspace || "workspace");
8643
8921
  const skillsEngine = new SkillsEngine(workspaceDir, toolRegistry);
8644
8922
  await skillsEngine.loadAll();
8645
8923
  registerSkillsTools(toolRegistry, skillsEngine, workspaceDir);
@@ -8889,7 +9167,7 @@ async function runSpawnTask(config, configPath) {
8889
9167
  const result = response.content;
8890
9168
  console.log(`[spawn] Task completed (context: ${response.context})`);
8891
9169
  if (spawnDir) {
8892
- writeFileSync8(resolve20(spawnDir, "result.txt"), result);
9170
+ writeFileSync9(resolve20(spawnDir, "result.txt"), result);
8893
9171
  }
8894
9172
  if (channelId && config.sesame.api_key) {
8895
9173
  try {
@@ -8906,7 +9184,7 @@ async function runSpawnTask(config, configPath) {
8906
9184
  const errorMsg = `[SPAWN ERROR] ${err.message}`;
8907
9185
  console.error(`[spawn] ${errorMsg}`);
8908
9186
  if (spawnDir) {
8909
- writeFileSync8(resolve20(spawnDir, "result.txt"), errorMsg);
9187
+ writeFileSync9(resolve20(spawnDir, "result.txt"), errorMsg);
8910
9188
  }
8911
9189
  process.exitCode = 1;
8912
9190
  }
@@ -9418,4 +9696,4 @@ smol-toml/dist/index.js:
9418
9696
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
9419
9697
  *)
9420
9698
  */
9421
- //# sourceMappingURL=chunk-EKZ3IZU6.js.map
9699
+ //# sourceMappingURL=chunk-7XXV5FKN.js.map