@sesamespace/hivemind 0.12.4 → 0.12.6
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-XW4AQDZA.js → chunk-DOFNPWS6.js} +2 -2
- package/dist/{chunk-TJBUZUVY.js → chunk-LNLALGT6.js} +3 -3
- package/dist/{chunk-FIHSUSBJ.js → chunk-SRGR3JYL.js} +2 -2
- package/dist/{chunk-YDK3Z5IW.js → chunk-T6YWTMGJ.js} +2 -2
- package/dist/{chunk-PGLO6WA5.js → chunk-TETVPYWD.js} +680 -44
- package/dist/chunk-TETVPYWD.js.map +1 -0
- package/dist/{chunk-J3WGHS5W.js → chunk-XWEHMSUL.js} +2 -2
- 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 +1 -1
- package/dist/chunk-PGLO6WA5.js.map +0 -1
- /package/dist/{chunk-XW4AQDZA.js.map → chunk-DOFNPWS6.js.map} +0 -0
- /package/dist/{chunk-TJBUZUVY.js.map → chunk-LNLALGT6.js.map} +0 -0
- /package/dist/{chunk-FIHSUSBJ.js.map → chunk-SRGR3JYL.js.map} +0 -0
- /package/dist/{chunk-YDK3Z5IW.js.map → chunk-T6YWTMGJ.js.map} +0 -0
- /package/dist/{chunk-J3WGHS5W.js.map → chunk-XWEHMSUL.js.map} +0 -0
|
@@ -3049,7 +3049,7 @@ var SesameClient = class {
|
|
|
3049
3049
|
* Connect to the real-time WebSocket gateway.
|
|
3050
3050
|
*/
|
|
3051
3051
|
connect() {
|
|
3052
|
-
return new Promise((
|
|
3052
|
+
return new Promise((resolve22, reject) => {
|
|
3053
3053
|
try {
|
|
3054
3054
|
this.ws = new WebSocket(`${this.config.wsUrl}/v1/connect`);
|
|
3055
3055
|
this.ws.on("open", () => {
|
|
@@ -3063,7 +3063,7 @@ var SesameClient = class {
|
|
|
3063
3063
|
this.authenticated = true;
|
|
3064
3064
|
this.startHeartbeat(event.heartbeatIntervalMs ?? 3e4);
|
|
3065
3065
|
this.sendReplay();
|
|
3066
|
-
|
|
3066
|
+
resolve22();
|
|
3067
3067
|
return;
|
|
3068
3068
|
}
|
|
3069
3069
|
if (event.type === "pong")
|
|
@@ -3249,6 +3249,10 @@ var SesameClient2 = class {
|
|
|
3249
3249
|
agentId = null;
|
|
3250
3250
|
channels = /* @__PURE__ */ new Map();
|
|
3251
3251
|
typingIntervals = /* @__PURE__ */ new Map();
|
|
3252
|
+
/** Messages held briefly to allow streaming edits to replace initial fragments */
|
|
3253
|
+
pendingMessages = /* @__PURE__ */ new Map();
|
|
3254
|
+
/** How long to wait for streaming edits before delivering (ms) */
|
|
3255
|
+
MESSAGE_HOLD_MS = 3e3;
|
|
3252
3256
|
constructor(config) {
|
|
3253
3257
|
this.config = config;
|
|
3254
3258
|
this.sdk = new SesameClient({
|
|
@@ -3305,8 +3309,9 @@ var SesameClient2 = class {
|
|
|
3305
3309
|
if (senderId === this.agentId) return;
|
|
3306
3310
|
if (!this.messageHandler || !msg.content) return;
|
|
3307
3311
|
const channelInfo = this.channels.get(msg.channelId);
|
|
3308
|
-
|
|
3309
|
-
|
|
3312
|
+
const messageId = msg.id || "unknown";
|
|
3313
|
+
const sesameMsg = {
|
|
3314
|
+
id: messageId,
|
|
3310
3315
|
channelId: msg.channelId || "unknown",
|
|
3311
3316
|
channelKind: channelInfo?.kind || "dm",
|
|
3312
3317
|
content: msg.content,
|
|
@@ -3315,7 +3320,52 @@ var SesameClient2 = class {
|
|
|
3315
3320
|
handle: msg.senderHandle || msg.metadata?.senderHandle || "unknown"
|
|
3316
3321
|
},
|
|
3317
3322
|
timestamp: msg.createdAt || (/* @__PURE__ */ new Date()).toISOString()
|
|
3318
|
-
}
|
|
3323
|
+
};
|
|
3324
|
+
const existing = this.pendingMessages.get(messageId);
|
|
3325
|
+
if (existing && !existing.delivered) {
|
|
3326
|
+
existing.message = sesameMsg;
|
|
3327
|
+
return;
|
|
3328
|
+
}
|
|
3329
|
+
const pending = {
|
|
3330
|
+
message: sesameMsg,
|
|
3331
|
+
delivered: false,
|
|
3332
|
+
timer: setTimeout(() => {
|
|
3333
|
+
const p = this.pendingMessages.get(messageId);
|
|
3334
|
+
if (p && !p.delivered && this.messageHandler) {
|
|
3335
|
+
p.delivered = true;
|
|
3336
|
+
this.messageHandler(p.message);
|
|
3337
|
+
}
|
|
3338
|
+
this.pendingMessages.delete(messageId);
|
|
3339
|
+
}, this.MESSAGE_HOLD_MS)
|
|
3340
|
+
};
|
|
3341
|
+
this.pendingMessages.set(messageId, pending);
|
|
3342
|
+
});
|
|
3343
|
+
this.sdk.on("message.edited", (event) => {
|
|
3344
|
+
const msg = event.data || event.message || event;
|
|
3345
|
+
const senderId = msg.senderId || msg.sender?.id;
|
|
3346
|
+
if (senderId === this.agentId) return;
|
|
3347
|
+
if (event.streaming) return;
|
|
3348
|
+
const messageId = msg.id || "unknown";
|
|
3349
|
+
const channelInfo = this.channels.get(msg.channelId);
|
|
3350
|
+
const updatedMsg = {
|
|
3351
|
+
id: messageId,
|
|
3352
|
+
channelId: msg.channelId || "unknown",
|
|
3353
|
+
channelKind: channelInfo?.kind || "dm",
|
|
3354
|
+
content: msg.content,
|
|
3355
|
+
author: {
|
|
3356
|
+
id: senderId || "unknown",
|
|
3357
|
+
handle: msg.senderHandle || msg.metadata?.senderHandle || "unknown"
|
|
3358
|
+
},
|
|
3359
|
+
timestamp: msg.updatedAt || msg.createdAt || (/* @__PURE__ */ new Date()).toISOString()
|
|
3360
|
+
};
|
|
3361
|
+
const pending = this.pendingMessages.get(messageId);
|
|
3362
|
+
if (pending && !pending.delivered) {
|
|
3363
|
+
pending.message = updatedMsg;
|
|
3364
|
+
return;
|
|
3365
|
+
}
|
|
3366
|
+
if (this.messageHandler && msg.content) {
|
|
3367
|
+
this.messageHandler(updatedMsg);
|
|
3368
|
+
}
|
|
3319
3369
|
});
|
|
3320
3370
|
await this.sdk.connect();
|
|
3321
3371
|
console.log("[sesame] WebSocket connected");
|
|
@@ -4225,12 +4275,12 @@ var LogWatcher = class extends BackgroundProcess {
|
|
|
4225
4275
|
}
|
|
4226
4276
|
savePositions() {
|
|
4227
4277
|
try {
|
|
4228
|
-
const { mkdirSync:
|
|
4229
|
-
const { dirname:
|
|
4230
|
-
const dir =
|
|
4231
|
-
if (!existsSync7(dir))
|
|
4278
|
+
const { mkdirSync: mkdirSync17, writeFileSync: writeFileSync11 } = __require("fs");
|
|
4279
|
+
const { dirname: dirname10 } = __require("path");
|
|
4280
|
+
const dir = dirname10(this.positionsFile);
|
|
4281
|
+
if (!existsSync7(dir)) mkdirSync17(dir, { recursive: true });
|
|
4232
4282
|
const data = Object.fromEntries(this.tailPositions);
|
|
4233
|
-
|
|
4283
|
+
writeFileSync11(this.positionsFile, JSON.stringify(data));
|
|
4234
4284
|
} catch (err) {
|
|
4235
4285
|
log2.warn("failed to save tail positions", {
|
|
4236
4286
|
error: err.message
|
|
@@ -4750,10 +4800,10 @@ function parseQuery(url) {
|
|
|
4750
4800
|
return params;
|
|
4751
4801
|
}
|
|
4752
4802
|
function readBody(req) {
|
|
4753
|
-
return new Promise((
|
|
4803
|
+
return new Promise((resolve22, reject) => {
|
|
4754
4804
|
const chunks = [];
|
|
4755
4805
|
req.on("data", (chunk) => chunks.push(chunk));
|
|
4756
|
-
req.on("end", () =>
|
|
4806
|
+
req.on("end", () => resolve22(Buffer.concat(chunks).toString()));
|
|
4757
4807
|
req.on("error", reject);
|
|
4758
4808
|
});
|
|
4759
4809
|
}
|
|
@@ -5178,13 +5228,13 @@ function registerFileTools(registry, workspaceDir) {
|
|
|
5178
5228
|
required: []
|
|
5179
5229
|
},
|
|
5180
5230
|
async (params) => {
|
|
5181
|
-
const { readdirSync:
|
|
5231
|
+
const { readdirSync: readdirSync6, statSync: statSync5 } = await import("fs");
|
|
5182
5232
|
const dirPath = params.path ? resolvePath(workspaceDir, params.path) : workspaceDir;
|
|
5183
5233
|
if (!existsSync10(dirPath)) {
|
|
5184
5234
|
return `Error: Directory not found: ${dirPath}`;
|
|
5185
5235
|
}
|
|
5186
5236
|
try {
|
|
5187
|
-
const entries =
|
|
5237
|
+
const entries = readdirSync6(dirPath);
|
|
5188
5238
|
const results = [];
|
|
5189
5239
|
for (const entry of entries) {
|
|
5190
5240
|
if (entry.startsWith(".")) continue;
|
|
@@ -7898,7 +7948,7 @@ function registerCodingAgentTools(registry, workspaceDir, contextBridge) {
|
|
|
7898
7948
|
contextBridge.on("error-encountered", errorHandler);
|
|
7899
7949
|
}
|
|
7900
7950
|
try {
|
|
7901
|
-
const output = await new Promise((
|
|
7951
|
+
const output = await new Promise((resolve22, reject) => {
|
|
7902
7952
|
const child = exec2(command, {
|
|
7903
7953
|
cwd,
|
|
7904
7954
|
timeout: timeoutSeconds * 1e3,
|
|
@@ -7915,7 +7965,7 @@ function registerCodingAgentTools(registry, workspaceDir, contextBridge) {
|
|
|
7915
7965
|
error.stderr = stderr;
|
|
7916
7966
|
reject(error);
|
|
7917
7967
|
} else {
|
|
7918
|
-
|
|
7968
|
+
resolve22(stdout);
|
|
7919
7969
|
}
|
|
7920
7970
|
});
|
|
7921
7971
|
child.stdin?.end();
|
|
@@ -7966,6 +8016,9 @@ ${output || err.message}`;
|
|
|
7966
8016
|
if (contextBridge && errorHandler) {
|
|
7967
8017
|
contextBridge.off("error-encountered", errorHandler);
|
|
7968
8018
|
}
|
|
8019
|
+
if (contextBridge) {
|
|
8020
|
+
contextBridge.cleanupContextFile();
|
|
8021
|
+
}
|
|
7969
8022
|
}
|
|
7970
8023
|
}
|
|
7971
8024
|
);
|
|
@@ -8633,12 +8686,12 @@ Path: ${skillDir}`;
|
|
|
8633
8686
|
}
|
|
8634
8687
|
|
|
8635
8688
|
// packages/runtime/src/pipeline.ts
|
|
8636
|
-
import { readFileSync as
|
|
8637
|
-
import { resolve as
|
|
8689
|
+
import { readFileSync as readFileSync17, writeFileSync as writeFileSync10, unlinkSync as unlinkSync4 } from "fs";
|
|
8690
|
+
import { resolve as resolve21, dirname as dirname9 } from "path";
|
|
8638
8691
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
8639
8692
|
|
|
8640
8693
|
// packages/runtime/src/tools/context-bridge.ts
|
|
8641
|
-
import { writeFileSync as writeFileSync8, readFileSync as readFileSync15, statSync as statSync4, existsSync as existsSync20, mkdirSync as mkdirSync15, openSync, readSync, closeSync } from "fs";
|
|
8694
|
+
import { writeFileSync as writeFileSync8, readFileSync as readFileSync15, statSync as statSync4, existsSync as existsSync20, mkdirSync as mkdirSync15, openSync, readSync, closeSync, readdirSync as readdirSync5, unlinkSync as unlinkSync3 } from "fs";
|
|
8642
8695
|
import { createHash as createHash2 } from "crypto";
|
|
8643
8696
|
import { join as join8 } from "path";
|
|
8644
8697
|
import { homedir } from "os";
|
|
@@ -8649,16 +8702,20 @@ var ClaudeContextBridge = class extends EventEmitter2 {
|
|
|
8649
8702
|
logger;
|
|
8650
8703
|
sessionLogPath;
|
|
8651
8704
|
contextFilePath;
|
|
8705
|
+
sessionArchiveDir;
|
|
8652
8706
|
watchInterval = null;
|
|
8653
8707
|
lastLogSize = 0;
|
|
8654
8708
|
seenPatterns = /* @__PURE__ */ new Set();
|
|
8709
|
+
currentSessionId;
|
|
8655
8710
|
constructor(config) {
|
|
8656
8711
|
super();
|
|
8657
8712
|
this.workspaceDir = config.workspaceDir;
|
|
8658
8713
|
this.memoryClient = config.memoryClient;
|
|
8659
8714
|
this.logger = config.logger;
|
|
8660
8715
|
this.sessionLogPath = join8(homedir(), ".claude", "session.log");
|
|
8661
|
-
this.
|
|
8716
|
+
this.sessionArchiveDir = join8(homedir(), ".claude", "sessions");
|
|
8717
|
+
this.contextFilePath = join8(this.workspaceDir, ".claude-context-current.md");
|
|
8718
|
+
this.currentSessionId = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
8662
8719
|
}
|
|
8663
8720
|
/**
|
|
8664
8721
|
* Initialize the context bridge
|
|
@@ -8668,10 +8725,49 @@ var ClaudeContextBridge = class extends EventEmitter2 {
|
|
|
8668
8725
|
if (!existsSync20(claudeDir)) {
|
|
8669
8726
|
mkdirSync15(claudeDir, { recursive: true });
|
|
8670
8727
|
}
|
|
8728
|
+
if (!existsSync20(this.sessionArchiveDir)) {
|
|
8729
|
+
mkdirSync15(this.sessionArchiveDir, { recursive: true });
|
|
8730
|
+
}
|
|
8731
|
+
await this.archiveSessionLog();
|
|
8671
8732
|
await this.setupClaudeSettings();
|
|
8672
8733
|
this.startLogMonitoring();
|
|
8673
8734
|
this.logger.info("Claude context bridge initialized");
|
|
8674
8735
|
}
|
|
8736
|
+
/**
|
|
8737
|
+
* Archive previous session log if it exists
|
|
8738
|
+
*/
|
|
8739
|
+
async archiveSessionLog() {
|
|
8740
|
+
if (existsSync20(this.sessionLogPath)) {
|
|
8741
|
+
const stats = statSync4(this.sessionLogPath);
|
|
8742
|
+
if (stats.size > 0) {
|
|
8743
|
+
const archivePath = join8(this.sessionArchiveDir, `${this.currentSessionId}.log`);
|
|
8744
|
+
const content = readFileSync15(this.sessionLogPath, "utf-8");
|
|
8745
|
+
writeFileSync8(archivePath, content);
|
|
8746
|
+
writeFileSync8(this.sessionLogPath, "");
|
|
8747
|
+
this.logger.info("Archived previous session log", { path: archivePath });
|
|
8748
|
+
this.cleanupOldArchives();
|
|
8749
|
+
}
|
|
8750
|
+
}
|
|
8751
|
+
}
|
|
8752
|
+
/**
|
|
8753
|
+
* Clean up old session archives, keeping only the most recent ones
|
|
8754
|
+
*/
|
|
8755
|
+
cleanupOldArchives() {
|
|
8756
|
+
try {
|
|
8757
|
+
const files = readdirSync5(this.sessionArchiveDir).filter((f) => f.endsWith(".log")).map((f) => ({
|
|
8758
|
+
name: f,
|
|
8759
|
+
path: join8(this.sessionArchiveDir, f),
|
|
8760
|
+
mtime: statSync4(join8(this.sessionArchiveDir, f)).mtime
|
|
8761
|
+
})).sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
|
|
8762
|
+
const toDelete = files.slice(10);
|
|
8763
|
+
for (const file of toDelete) {
|
|
8764
|
+
unlinkSync3(file.path);
|
|
8765
|
+
this.logger.debug("Deleted old session archive", { file: file.name });
|
|
8766
|
+
}
|
|
8767
|
+
} catch (err) {
|
|
8768
|
+
this.logger.warn("Failed to cleanup old archives", { error: String(err) });
|
|
8769
|
+
}
|
|
8770
|
+
}
|
|
8675
8771
|
/**
|
|
8676
8772
|
* Configure Claude Code to report insights via workspace CLAUDE.md
|
|
8677
8773
|
*/
|
|
@@ -8686,7 +8782,7 @@ When working on tasks, please report significant findings by writing to the sess
|
|
|
8686
8782
|
- When you find reusable solutions: echo "PATTERN: [approach]" >> ~/.claude/session.log
|
|
8687
8783
|
- When you encounter errors: echo "ERROR: [error details]" >> ~/.claude/session.log
|
|
8688
8784
|
|
|
8689
|
-
Always check
|
|
8785
|
+
Always check .claude-context-current.md in the workspace for task context and requirements.`;
|
|
8690
8786
|
const claudeMdPath = join8(this.workspaceDir, "CLAUDE.md");
|
|
8691
8787
|
writeFileSync8(claudeMdPath, instructions);
|
|
8692
8788
|
this.logger.info("Claude workspace CLAUDE.md configured for context bridge");
|
|
@@ -8940,6 +9036,15 @@ ${memories.join("\n\n")}
|
|
|
8940
9036
|
};
|
|
8941
9037
|
}
|
|
8942
9038
|
}
|
|
9039
|
+
/**
|
|
9040
|
+
* Clean up just the context file (for use after a session)
|
|
9041
|
+
*/
|
|
9042
|
+
cleanupContextFile() {
|
|
9043
|
+
if (existsSync20(this.contextFilePath)) {
|
|
9044
|
+
unlinkSync3(this.contextFilePath);
|
|
9045
|
+
this.logger.info("Cleaned up context file");
|
|
9046
|
+
}
|
|
9047
|
+
}
|
|
8943
9048
|
/**
|
|
8944
9049
|
* Clean up resources
|
|
8945
9050
|
*/
|
|
@@ -8950,6 +9055,7 @@ ${memories.join("\n\n")}
|
|
|
8950
9055
|
}
|
|
8951
9056
|
this.seenPatterns.clear();
|
|
8952
9057
|
this.removeAllListeners();
|
|
9058
|
+
this.cleanupContextFile();
|
|
8953
9059
|
}
|
|
8954
9060
|
};
|
|
8955
9061
|
async function createContextBridge(config) {
|
|
@@ -8958,11 +9064,516 @@ async function createContextBridge(config) {
|
|
|
8958
9064
|
return bridge;
|
|
8959
9065
|
}
|
|
8960
9066
|
|
|
9067
|
+
// packages/runtime/src/sesame-sync.ts
|
|
9068
|
+
import { readFileSync as readFileSync16, writeFileSync as writeFileSync9, existsSync as existsSync21, mkdirSync as mkdirSync16 } from "fs";
|
|
9069
|
+
import { resolve as resolve20, dirname as dirname8 } from "path";
|
|
9070
|
+
|
|
9071
|
+
// packages/runtime/src/sesame-api.ts
|
|
9072
|
+
var SesameAPI = class {
|
|
9073
|
+
baseUrl;
|
|
9074
|
+
apiKey;
|
|
9075
|
+
rateLimitRemaining = 120;
|
|
9076
|
+
rateLimitResetAt = 0;
|
|
9077
|
+
constructor(config) {
|
|
9078
|
+
this.baseUrl = config.api_url.endsWith("/api/v1") ? config.api_url : `${config.api_url}/api/v1`;
|
|
9079
|
+
this.apiKey = config.api_key;
|
|
9080
|
+
}
|
|
9081
|
+
// ── Internal helpers ──
|
|
9082
|
+
async request(method, path, body) {
|
|
9083
|
+
if (this.rateLimitRemaining <= 5 && Date.now() < this.rateLimitResetAt) {
|
|
9084
|
+
const waitMs = this.rateLimitResetAt - Date.now();
|
|
9085
|
+
console.warn(`[sesame-api] Rate limit low (${this.rateLimitRemaining}), waiting ${waitMs}ms`);
|
|
9086
|
+
await new Promise((r) => setTimeout(r, Math.min(waitMs, 5e3)));
|
|
9087
|
+
}
|
|
9088
|
+
const url = `${this.baseUrl}${path}`;
|
|
9089
|
+
const headers = {
|
|
9090
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
9091
|
+
"Content-Type": "application/json"
|
|
9092
|
+
};
|
|
9093
|
+
const options = { method, headers };
|
|
9094
|
+
if (body && method !== "GET") {
|
|
9095
|
+
options.body = JSON.stringify(body);
|
|
9096
|
+
}
|
|
9097
|
+
try {
|
|
9098
|
+
const response = await fetch(url, options);
|
|
9099
|
+
const remaining = response.headers.get("x-ratelimit-remaining");
|
|
9100
|
+
const reset = response.headers.get("x-ratelimit-reset");
|
|
9101
|
+
if (remaining) this.rateLimitRemaining = parseInt(remaining, 10);
|
|
9102
|
+
if (reset) this.rateLimitResetAt = parseInt(reset, 10) * 1e3;
|
|
9103
|
+
if (!response.ok) {
|
|
9104
|
+
const errorBody = await response.text();
|
|
9105
|
+
let parsed;
|
|
9106
|
+
try {
|
|
9107
|
+
parsed = JSON.parse(errorBody);
|
|
9108
|
+
} catch {
|
|
9109
|
+
parsed = { error: errorBody };
|
|
9110
|
+
}
|
|
9111
|
+
const err = new Error(`Sesame API ${method} ${path}: ${response.status} ${parsed.error || errorBody}`);
|
|
9112
|
+
err.status = response.status;
|
|
9113
|
+
err.details = parsed;
|
|
9114
|
+
throw err;
|
|
9115
|
+
}
|
|
9116
|
+
const data = await response.json();
|
|
9117
|
+
return data.data ?? data;
|
|
9118
|
+
} catch (err) {
|
|
9119
|
+
if (err.status) throw err;
|
|
9120
|
+
console.error(`[sesame-api] Network error on ${method} ${path}:`, err.message);
|
|
9121
|
+
throw err;
|
|
9122
|
+
}
|
|
9123
|
+
}
|
|
9124
|
+
// ── Wake ──
|
|
9125
|
+
async wake(agentId) {
|
|
9126
|
+
return this.request("GET", `/agents/${agentId}/wake`);
|
|
9127
|
+
}
|
|
9128
|
+
// ── Agent State ──
|
|
9129
|
+
async getState(agentId, namespace = "default") {
|
|
9130
|
+
try {
|
|
9131
|
+
return await this.request("GET", `/agents/${agentId}/state?namespace=${namespace}`);
|
|
9132
|
+
} catch (err) {
|
|
9133
|
+
if (err.status === 404) return null;
|
|
9134
|
+
throw err;
|
|
9135
|
+
}
|
|
9136
|
+
}
|
|
9137
|
+
async setState(agentId, state, namespace = "default", ttlSeconds = 86400) {
|
|
9138
|
+
return this.request("PUT", `/agents/${agentId}/state`, {
|
|
9139
|
+
namespace,
|
|
9140
|
+
state,
|
|
9141
|
+
ttlSeconds
|
|
9142
|
+
});
|
|
9143
|
+
}
|
|
9144
|
+
// ── Agent Memory ──
|
|
9145
|
+
async getMemory(agentId, category, limit = 50) {
|
|
9146
|
+
const params = new URLSearchParams({ limit: String(limit) });
|
|
9147
|
+
if (category) params.set("category", category);
|
|
9148
|
+
return this.request("GET", `/agents/${agentId}/memory?${params}`);
|
|
9149
|
+
}
|
|
9150
|
+
async setMemory(agentId, category, key, content, metadata) {
|
|
9151
|
+
return this.request("PUT", `/agents/${agentId}/memory`, {
|
|
9152
|
+
category,
|
|
9153
|
+
key,
|
|
9154
|
+
content,
|
|
9155
|
+
metadata
|
|
9156
|
+
});
|
|
9157
|
+
}
|
|
9158
|
+
async deleteMemory(agentId, memoryId) {
|
|
9159
|
+
await this.request("DELETE", `/agents/${agentId}/memory/${memoryId}`);
|
|
9160
|
+
}
|
|
9161
|
+
// ── Agent Focus ──
|
|
9162
|
+
async setFocus(agentId, taskId) {
|
|
9163
|
+
await this.request("PUT", `/agents/${agentId}/focus`, { taskId });
|
|
9164
|
+
}
|
|
9165
|
+
async clearFocus(agentId) {
|
|
9166
|
+
await this.request("DELETE", `/agents/${agentId}/focus`);
|
|
9167
|
+
}
|
|
9168
|
+
// ── Tasks ──
|
|
9169
|
+
async createTask(task) {
|
|
9170
|
+
return this.request("POST", "/tasks", task);
|
|
9171
|
+
}
|
|
9172
|
+
async getTask(taskId) {
|
|
9173
|
+
return this.request("GET", `/tasks/${taskId}`);
|
|
9174
|
+
}
|
|
9175
|
+
async updateTask(taskId, updates) {
|
|
9176
|
+
return this.request("PATCH", `/tasks/${taskId}`, updates);
|
|
9177
|
+
}
|
|
9178
|
+
async getMyTasks(status) {
|
|
9179
|
+
const params = status ? `?status=${status}` : "";
|
|
9180
|
+
return this.request("GET", `/tasks/mine${params}`);
|
|
9181
|
+
}
|
|
9182
|
+
async getNextTask() {
|
|
9183
|
+
try {
|
|
9184
|
+
return await this.request("GET", "/tasks/next");
|
|
9185
|
+
} catch (err) {
|
|
9186
|
+
if (err.status === 404) return null;
|
|
9187
|
+
throw err;
|
|
9188
|
+
}
|
|
9189
|
+
}
|
|
9190
|
+
async logActivity(taskId, type, message, metadata) {
|
|
9191
|
+
return this.request("POST", `/tasks/${taskId}/activity`, {
|
|
9192
|
+
type,
|
|
9193
|
+
message,
|
|
9194
|
+
metadata
|
|
9195
|
+
});
|
|
9196
|
+
}
|
|
9197
|
+
async getTaskContext(taskId) {
|
|
9198
|
+
try {
|
|
9199
|
+
return await this.request("GET", `/tasks/${taskId}/context`);
|
|
9200
|
+
} catch (err) {
|
|
9201
|
+
if (err.status === 404) return null;
|
|
9202
|
+
throw err;
|
|
9203
|
+
}
|
|
9204
|
+
}
|
|
9205
|
+
async updateTaskContext(taskId, context) {
|
|
9206
|
+
return this.request("PATCH", `/tasks/${taskId}/context`, context);
|
|
9207
|
+
}
|
|
9208
|
+
async appendTaskContext(taskId, field, values) {
|
|
9209
|
+
const current = await this.getTaskContext(taskId);
|
|
9210
|
+
const existing = current?.[field] ?? [];
|
|
9211
|
+
const merged = [...existing, ...values.filter((v) => !existing.includes(v))];
|
|
9212
|
+
return this.request("PATCH", `/tasks/${taskId}/context`, {
|
|
9213
|
+
[field]: merged
|
|
9214
|
+
});
|
|
9215
|
+
}
|
|
9216
|
+
async searchTasks(query, scope = "all") {
|
|
9217
|
+
return this.request("GET", `/tasks/search?q=${encodeURIComponent(query)}&scope=${scope}`);
|
|
9218
|
+
}
|
|
9219
|
+
async handoffTask(taskId, toHandle, summary, instructions, reason, state) {
|
|
9220
|
+
return this.request("POST", `/tasks/${taskId}/handoff`, {
|
|
9221
|
+
toHandle,
|
|
9222
|
+
reason: reason || "Handoff",
|
|
9223
|
+
summary,
|
|
9224
|
+
instructions,
|
|
9225
|
+
state
|
|
9226
|
+
});
|
|
9227
|
+
}
|
|
9228
|
+
// ── Projects ──
|
|
9229
|
+
async createProject(project) {
|
|
9230
|
+
return this.request("POST", "/projects", project);
|
|
9231
|
+
}
|
|
9232
|
+
async getProject(projectId) {
|
|
9233
|
+
return this.request("GET", `/projects/${projectId}`);
|
|
9234
|
+
}
|
|
9235
|
+
async getProjectContext(projectId) {
|
|
9236
|
+
try {
|
|
9237
|
+
return await this.request("GET", `/projects/${projectId}/context`);
|
|
9238
|
+
} catch (err) {
|
|
9239
|
+
if (err.status === 404) return null;
|
|
9240
|
+
throw err;
|
|
9241
|
+
}
|
|
9242
|
+
}
|
|
9243
|
+
async updateProjectContext(projectId, context) {
|
|
9244
|
+
return this.request("PUT", `/projects/${projectId}/context`, context);
|
|
9245
|
+
}
|
|
9246
|
+
// ── Schedule ──
|
|
9247
|
+
async syncSchedule(events) {
|
|
9248
|
+
return this.request("PUT", "/schedule/sync", { events });
|
|
9249
|
+
}
|
|
9250
|
+
async recordOccurrence(eventId, scheduledAt, status, result) {
|
|
9251
|
+
return this.request("POST", `/schedule/${eventId}/occurrences`, {
|
|
9252
|
+
scheduledAt,
|
|
9253
|
+
status,
|
|
9254
|
+
result
|
|
9255
|
+
});
|
|
9256
|
+
}
|
|
9257
|
+
// ── Utility ──
|
|
9258
|
+
getRateLimitRemaining() {
|
|
9259
|
+
return this.rateLimitRemaining;
|
|
9260
|
+
}
|
|
9261
|
+
};
|
|
9262
|
+
|
|
9263
|
+
// packages/runtime/src/sesame-sync.ts
|
|
9264
|
+
function defaultSyncState() {
|
|
9265
|
+
return {
|
|
9266
|
+
lastStatePush: null,
|
|
9267
|
+
lastL3Sync: null,
|
|
9268
|
+
syncedL3Keys: [],
|
|
9269
|
+
lastMemoryMdHash: null,
|
|
9270
|
+
lastWake: null
|
|
9271
|
+
};
|
|
9272
|
+
}
|
|
9273
|
+
function simpleHash(str) {
|
|
9274
|
+
let hash = 0;
|
|
9275
|
+
for (let i = 0; i < str.length; i++) {
|
|
9276
|
+
const char = str.charCodeAt(i);
|
|
9277
|
+
hash = (hash << 5) - hash + char;
|
|
9278
|
+
hash = hash & hash;
|
|
9279
|
+
}
|
|
9280
|
+
return hash.toString(36);
|
|
9281
|
+
}
|
|
9282
|
+
var SesameSync = class {
|
|
9283
|
+
api;
|
|
9284
|
+
agentId;
|
|
9285
|
+
workspaceDir;
|
|
9286
|
+
dataDir;
|
|
9287
|
+
syncState;
|
|
9288
|
+
syncStatePath;
|
|
9289
|
+
syncInterval = null;
|
|
9290
|
+
constructor(config, agentId, workspaceDir, dataDir) {
|
|
9291
|
+
this.api = new SesameAPI(config);
|
|
9292
|
+
this.agentId = agentId;
|
|
9293
|
+
this.workspaceDir = workspaceDir;
|
|
9294
|
+
this.dataDir = dataDir;
|
|
9295
|
+
this.syncStatePath = resolve20(dataDir, "sesame-sync-state.json");
|
|
9296
|
+
this.syncState = this.loadSyncState();
|
|
9297
|
+
}
|
|
9298
|
+
// ── State Persistence ──
|
|
9299
|
+
loadSyncState() {
|
|
9300
|
+
try {
|
|
9301
|
+
if (existsSync21(this.syncStatePath)) {
|
|
9302
|
+
return JSON.parse(readFileSync16(this.syncStatePath, "utf-8"));
|
|
9303
|
+
}
|
|
9304
|
+
} catch (err) {
|
|
9305
|
+
console.warn("[sesame-sync] Failed to load sync state:", err.message);
|
|
9306
|
+
}
|
|
9307
|
+
return defaultSyncState();
|
|
9308
|
+
}
|
|
9309
|
+
saveSyncState() {
|
|
9310
|
+
try {
|
|
9311
|
+
const dir = dirname8(this.syncStatePath);
|
|
9312
|
+
if (!existsSync21(dir)) mkdirSync16(dir, { recursive: true });
|
|
9313
|
+
writeFileSync9(this.syncStatePath, JSON.stringify(this.syncState, null, 2));
|
|
9314
|
+
} catch (err) {
|
|
9315
|
+
console.warn("[sesame-sync] Failed to save sync state:", err.message);
|
|
9316
|
+
}
|
|
9317
|
+
}
|
|
9318
|
+
// ── Push: MEMORY.md -> Agent State ──
|
|
9319
|
+
/**
|
|
9320
|
+
* Read MEMORY.md from workspace and push to Sesame agent state.
|
|
9321
|
+
* Only pushes if content has changed since last push.
|
|
9322
|
+
*/
|
|
9323
|
+
async pushState() {
|
|
9324
|
+
const memoryMdPath = resolve20(this.workspaceDir, "MEMORY.md");
|
|
9325
|
+
if (!existsSync21(memoryMdPath)) {
|
|
9326
|
+
console.log("[sesame-sync] No MEMORY.md found, skipping state push");
|
|
9327
|
+
return false;
|
|
9328
|
+
}
|
|
9329
|
+
const content = readFileSync16(memoryMdPath, "utf-8");
|
|
9330
|
+
const hash = simpleHash(content);
|
|
9331
|
+
if (hash === this.syncState.lastMemoryMdHash) {
|
|
9332
|
+
return false;
|
|
9333
|
+
}
|
|
9334
|
+
try {
|
|
9335
|
+
await this.api.setState(this.agentId, {
|
|
9336
|
+
memoryMd: content,
|
|
9337
|
+
memoryMdHash: hash,
|
|
9338
|
+
lastSync: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9339
|
+
source: "hivemind-sync"
|
|
9340
|
+
}, "memory", 172800);
|
|
9341
|
+
this.syncState.lastMemoryMdHash = hash;
|
|
9342
|
+
this.syncState.lastStatePush = (/* @__PURE__ */ new Date()).toISOString();
|
|
9343
|
+
this.saveSyncState();
|
|
9344
|
+
console.log("[sesame-sync] Pushed MEMORY.md to agent state");
|
|
9345
|
+
return true;
|
|
9346
|
+
} catch (err) {
|
|
9347
|
+
console.error("[sesame-sync] Failed to push state:", err.message);
|
|
9348
|
+
return false;
|
|
9349
|
+
}
|
|
9350
|
+
}
|
|
9351
|
+
// ── Push: Working Context -> Agent State ──
|
|
9352
|
+
/**
|
|
9353
|
+
* Push current working context (focus, active work, etc.) to agent state.
|
|
9354
|
+
* This is the "default" namespace for quick session recovery.
|
|
9355
|
+
*/
|
|
9356
|
+
async pushWorkingContext(context) {
|
|
9357
|
+
try {
|
|
9358
|
+
await this.api.setState(this.agentId, {
|
|
9359
|
+
...context,
|
|
9360
|
+
lastSync: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9361
|
+
source: "hivemind-sync"
|
|
9362
|
+
}, "default", 86400);
|
|
9363
|
+
console.log("[sesame-sync] Pushed working context to agent state");
|
|
9364
|
+
return true;
|
|
9365
|
+
} catch (err) {
|
|
9366
|
+
console.error("[sesame-sync] Failed to push working context:", err.message);
|
|
9367
|
+
return false;
|
|
9368
|
+
}
|
|
9369
|
+
}
|
|
9370
|
+
// ── Push: L3 Knowledge -> Agent Memory ──
|
|
9371
|
+
/**
|
|
9372
|
+
* Sync L3 promoted knowledge to Sesame agent memory.
|
|
9373
|
+
* Only pushes entries that haven't been synced yet.
|
|
9374
|
+
*
|
|
9375
|
+
* @param memoryDaemonUrl - URL of the local memory daemon
|
|
9376
|
+
*/
|
|
9377
|
+
async syncL3ToMemory(memoryDaemonUrl) {
|
|
9378
|
+
let l3Entries;
|
|
9379
|
+
try {
|
|
9380
|
+
const response = await fetch(`${memoryDaemonUrl}/promotion/l3?context=global`);
|
|
9381
|
+
if (!response.ok) {
|
|
9382
|
+
console.warn("[sesame-sync] Failed to fetch L3 knowledge:", response.status);
|
|
9383
|
+
return 0;
|
|
9384
|
+
}
|
|
9385
|
+
const data = await response.json();
|
|
9386
|
+
l3Entries = data.entries || data || [];
|
|
9387
|
+
} catch (err) {
|
|
9388
|
+
console.error("[sesame-sync] Failed to fetch L3 knowledge:", err.message);
|
|
9389
|
+
return 0;
|
|
9390
|
+
}
|
|
9391
|
+
if (!Array.isArray(l3Entries) || l3Entries.length === 0) return 0;
|
|
9392
|
+
let synced = 0;
|
|
9393
|
+
const syncedKeys = new Set(this.syncState.syncedL3Keys);
|
|
9394
|
+
for (const entry of l3Entries) {
|
|
9395
|
+
const key = entry.key || `l3-${simpleHash(entry.content)}`;
|
|
9396
|
+
if (syncedKeys.has(key)) continue;
|
|
9397
|
+
try {
|
|
9398
|
+
await this.api.setMemory(
|
|
9399
|
+
this.agentId,
|
|
9400
|
+
"lessons",
|
|
9401
|
+
key,
|
|
9402
|
+
entry.content,
|
|
9403
|
+
{
|
|
9404
|
+
source: "hivemind-l3-promotion",
|
|
9405
|
+
l3Score: entry.score,
|
|
9406
|
+
l3Context: entry.context || "global",
|
|
9407
|
+
syncedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
9408
|
+
}
|
|
9409
|
+
);
|
|
9410
|
+
syncedKeys.add(key);
|
|
9411
|
+
synced++;
|
|
9412
|
+
} catch (err) {
|
|
9413
|
+
console.warn(`[sesame-sync] Failed to sync L3 entry "${key}":`, err.message);
|
|
9414
|
+
}
|
|
9415
|
+
}
|
|
9416
|
+
if (synced > 0) {
|
|
9417
|
+
this.syncState.syncedL3Keys = Array.from(syncedKeys);
|
|
9418
|
+
this.syncState.lastL3Sync = (/* @__PURE__ */ new Date()).toISOString();
|
|
9419
|
+
this.saveSyncState();
|
|
9420
|
+
console.log(`[sesame-sync] Synced ${synced} L3 entries to Sesame agent memory`);
|
|
9421
|
+
}
|
|
9422
|
+
return synced;
|
|
9423
|
+
}
|
|
9424
|
+
// ── Pull: Wake -> Rebuild Context ──
|
|
9425
|
+
/**
|
|
9426
|
+
* Call the wake endpoint and return structured data for context rebuilding.
|
|
9427
|
+
* This is the primary recovery mechanism after restart/compaction.
|
|
9428
|
+
*/
|
|
9429
|
+
async pullOnWake() {
|
|
9430
|
+
try {
|
|
9431
|
+
const wake = await this.api.wake(this.agentId);
|
|
9432
|
+
this.syncState.lastWake = (/* @__PURE__ */ new Date()).toISOString();
|
|
9433
|
+
this.saveSyncState();
|
|
9434
|
+
console.log("[sesame-sync] Wake data retrieved successfully");
|
|
9435
|
+
return wake;
|
|
9436
|
+
} catch (err) {
|
|
9437
|
+
console.error("[sesame-sync] Wake failed:", err.message);
|
|
9438
|
+
return null;
|
|
9439
|
+
}
|
|
9440
|
+
}
|
|
9441
|
+
// ── Pull: Agent State -> MEMORY.md Recovery ──
|
|
9442
|
+
/**
|
|
9443
|
+
* Pull agent state and restore MEMORY.md if local copy is missing or empty.
|
|
9444
|
+
*/
|
|
9445
|
+
async pullStateToMemoryMd() {
|
|
9446
|
+
const memoryMdPath = resolve20(this.workspaceDir, "MEMORY.md");
|
|
9447
|
+
if (existsSync21(memoryMdPath)) {
|
|
9448
|
+
const content = readFileSync16(memoryMdPath, "utf-8").trim();
|
|
9449
|
+
if (content.length > 0) {
|
|
9450
|
+
return false;
|
|
9451
|
+
}
|
|
9452
|
+
}
|
|
9453
|
+
try {
|
|
9454
|
+
const state = await this.api.getState(this.agentId, "memory");
|
|
9455
|
+
if (!state || !state.state.memoryMd) {
|
|
9456
|
+
console.log("[sesame-sync] No MEMORY.md found in agent state");
|
|
9457
|
+
return false;
|
|
9458
|
+
}
|
|
9459
|
+
writeFileSync9(memoryMdPath, state.state.memoryMd);
|
|
9460
|
+
console.log("[sesame-sync] Restored MEMORY.md from agent state");
|
|
9461
|
+
return true;
|
|
9462
|
+
} catch (err) {
|
|
9463
|
+
console.error("[sesame-sync] Failed to pull state:", err.message);
|
|
9464
|
+
return false;
|
|
9465
|
+
}
|
|
9466
|
+
}
|
|
9467
|
+
// ── Pre-Compaction Flush ──
|
|
9468
|
+
/**
|
|
9469
|
+
* Safety flush before compaction risk.
|
|
9470
|
+
* Pushes MEMORY.md to agent state and updates focused task context.
|
|
9471
|
+
*/
|
|
9472
|
+
async flushBeforeCompaction(focusedTaskId, contextSummary) {
|
|
9473
|
+
console.log("[sesame-sync] Pre-compaction flush starting...");
|
|
9474
|
+
await this.pushState();
|
|
9475
|
+
if (contextSummary) {
|
|
9476
|
+
await this.pushWorkingContext({
|
|
9477
|
+
preCompactionFlush: true,
|
|
9478
|
+
contextSummary,
|
|
9479
|
+
focusedTaskId,
|
|
9480
|
+
flushedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
9481
|
+
});
|
|
9482
|
+
}
|
|
9483
|
+
if (focusedTaskId && contextSummary) {
|
|
9484
|
+
try {
|
|
9485
|
+
await this.api.updateTaskContext(focusedTaskId, {
|
|
9486
|
+
notes: `[Pre-compaction flush ${(/* @__PURE__ */ new Date()).toISOString()}] ${contextSummary}`
|
|
9487
|
+
});
|
|
9488
|
+
console.log("[sesame-sync] Updated focused task context");
|
|
9489
|
+
} catch (err) {
|
|
9490
|
+
console.warn("[sesame-sync] Failed to update task context:", err.message);
|
|
9491
|
+
}
|
|
9492
|
+
}
|
|
9493
|
+
console.log("[sesame-sync] Pre-compaction flush complete");
|
|
9494
|
+
}
|
|
9495
|
+
// ── Task Helpers ──
|
|
9496
|
+
/**
|
|
9497
|
+
* Log progress on a Sesame task.
|
|
9498
|
+
*/
|
|
9499
|
+
async logTaskProgress(taskId, message) {
|
|
9500
|
+
try {
|
|
9501
|
+
await this.api.logActivity(taskId, "progress", message);
|
|
9502
|
+
} catch (err) {
|
|
9503
|
+
console.warn("[sesame-sync] Failed to log task progress:", err.message);
|
|
9504
|
+
}
|
|
9505
|
+
}
|
|
9506
|
+
/**
|
|
9507
|
+
* Log a decision on a Sesame task.
|
|
9508
|
+
*/
|
|
9509
|
+
async logTaskDecision(taskId, message) {
|
|
9510
|
+
try {
|
|
9511
|
+
await this.api.logActivity(taskId, "decision", message);
|
|
9512
|
+
} catch (err) {
|
|
9513
|
+
console.warn("[sesame-sync] Failed to log task decision:", err.message);
|
|
9514
|
+
}
|
|
9515
|
+
}
|
|
9516
|
+
/**
|
|
9517
|
+
* Update a task's context block.
|
|
9518
|
+
*/
|
|
9519
|
+
async updateTaskContext(taskId, context) {
|
|
9520
|
+
try {
|
|
9521
|
+
await this.api.updateTaskContext(taskId, context);
|
|
9522
|
+
} catch (err) {
|
|
9523
|
+
console.warn("[sesame-sync] Failed to update task context:", err.message);
|
|
9524
|
+
}
|
|
9525
|
+
}
|
|
9526
|
+
// ── Periodic Sync ──
|
|
9527
|
+
/**
|
|
9528
|
+
* Start periodic background sync.
|
|
9529
|
+
* Pushes state every intervalMs (default: 5 minutes).
|
|
9530
|
+
* Syncs L3 every l3IntervalMs (default: 30 minutes).
|
|
9531
|
+
*/
|
|
9532
|
+
startPeriodicSync(memoryDaemonUrl, intervalMs = 5 * 60 * 1e3, l3IntervalMs = 30 * 60 * 1e3) {
|
|
9533
|
+
if (this.syncInterval) return;
|
|
9534
|
+
let l3Counter = 0;
|
|
9535
|
+
const l3Every = Math.max(1, Math.floor(l3IntervalMs / intervalMs));
|
|
9536
|
+
this.syncInterval = setInterval(async () => {
|
|
9537
|
+
try {
|
|
9538
|
+
await this.pushState();
|
|
9539
|
+
l3Counter++;
|
|
9540
|
+
if (l3Counter >= l3Every) {
|
|
9541
|
+
l3Counter = 0;
|
|
9542
|
+
await this.syncL3ToMemory(memoryDaemonUrl);
|
|
9543
|
+
}
|
|
9544
|
+
} catch (err) {
|
|
9545
|
+
console.error("[sesame-sync] Periodic sync error:", err.message);
|
|
9546
|
+
}
|
|
9547
|
+
}, intervalMs);
|
|
9548
|
+
console.log(`[sesame-sync] Periodic sync started (state: ${intervalMs / 1e3}s, L3: ${l3IntervalMs / 1e3}s)`);
|
|
9549
|
+
}
|
|
9550
|
+
/**
|
|
9551
|
+
* Stop periodic sync.
|
|
9552
|
+
*/
|
|
9553
|
+
stopPeriodicSync() {
|
|
9554
|
+
if (this.syncInterval) {
|
|
9555
|
+
clearInterval(this.syncInterval);
|
|
9556
|
+
this.syncInterval = null;
|
|
9557
|
+
console.log("[sesame-sync] Periodic sync stopped");
|
|
9558
|
+
}
|
|
9559
|
+
}
|
|
9560
|
+
// ── Accessors ──
|
|
9561
|
+
getApi() {
|
|
9562
|
+
return this.api;
|
|
9563
|
+
}
|
|
9564
|
+
getSyncState() {
|
|
9565
|
+
return { ...this.syncState };
|
|
9566
|
+
}
|
|
9567
|
+
getAgentId() {
|
|
9568
|
+
return this.agentId;
|
|
9569
|
+
}
|
|
9570
|
+
};
|
|
9571
|
+
|
|
8961
9572
|
// packages/runtime/src/pipeline.ts
|
|
8962
9573
|
var PACKAGE_VERSION = "unknown";
|
|
8963
9574
|
try {
|
|
8964
|
-
const __dirname2 =
|
|
8965
|
-
const pkg = JSON.parse(
|
|
9575
|
+
const __dirname2 = dirname9(fileURLToPath3(import.meta.url));
|
|
9576
|
+
const pkg = JSON.parse(readFileSync17(resolve21(__dirname2, "../package.json"), "utf-8"));
|
|
8966
9577
|
PACKAGE_VERSION = pkg.version ?? "unknown";
|
|
8967
9578
|
} catch {
|
|
8968
9579
|
}
|
|
@@ -9004,12 +9615,12 @@ function startHealthServer(port) {
|
|
|
9004
9615
|
return server;
|
|
9005
9616
|
}
|
|
9006
9617
|
function writePidFile(path) {
|
|
9007
|
-
|
|
9618
|
+
writeFileSync10(path, String(process.pid));
|
|
9008
9619
|
console.log(`[hivemind] PID file written: ${path}`);
|
|
9009
9620
|
}
|
|
9010
9621
|
function cleanupPidFile(path) {
|
|
9011
9622
|
try {
|
|
9012
|
-
|
|
9623
|
+
unlinkSync4(path);
|
|
9013
9624
|
} catch {
|
|
9014
9625
|
}
|
|
9015
9626
|
}
|
|
@@ -9045,12 +9656,12 @@ async function startPipeline(configPath) {
|
|
|
9045
9656
|
console.log("[hivemind] Global context already exists in memory daemon");
|
|
9046
9657
|
}
|
|
9047
9658
|
}
|
|
9048
|
-
const requestLogger = new RequestLogger(
|
|
9659
|
+
const requestLogger = new RequestLogger(resolve21(dirname9(configPath), "data", "dashboard.db"));
|
|
9049
9660
|
const agent = new Agent(config);
|
|
9050
9661
|
startDashboardServer(requestLogger, config.memory, () => agent.getConversationHistories());
|
|
9051
9662
|
agent.setRequestLogger(requestLogger);
|
|
9052
|
-
const hivemindHome = process.env.HIVEMIND_HOME ||
|
|
9053
|
-
const workspaceDir =
|
|
9663
|
+
const hivemindHome = process.env.HIVEMIND_HOME || resolve21(process.env.HOME || "/root", "hivemind");
|
|
9664
|
+
const workspaceDir = resolve21(hivemindHome, config.agent.workspace || "workspace");
|
|
9054
9665
|
let contextBridge;
|
|
9055
9666
|
if (memoryConnected) {
|
|
9056
9667
|
try {
|
|
@@ -9084,7 +9695,7 @@ async function startPipeline(configPath) {
|
|
|
9084
9695
|
agent.setToolRegistry(toolRegistry);
|
|
9085
9696
|
console.log(`[hivemind] Context manager initialized (active: ${agent.getActiveContext()})`);
|
|
9086
9697
|
if (config.auto_debug?.enabled) {
|
|
9087
|
-
const dataDir2 =
|
|
9698
|
+
const dataDir2 = resolve21(hivemindHome, "data");
|
|
9088
9699
|
const autoDebugConfig = config.auto_debug;
|
|
9089
9700
|
const logWatcher = new LogWatcher(
|
|
9090
9701
|
{
|
|
@@ -9126,7 +9737,7 @@ async function startPipeline(configPath) {
|
|
|
9126
9737
|
process.on("exit", () => processManager.stop());
|
|
9127
9738
|
console.log("[hivemind] Auto-debug processors started");
|
|
9128
9739
|
}
|
|
9129
|
-
const dataDir =
|
|
9740
|
+
const dataDir = resolve21(hivemindHome, "data");
|
|
9130
9741
|
if (config.sesame.api_key) {
|
|
9131
9742
|
await startSesameLoop(config, agent, toolRegistry, dataDir);
|
|
9132
9743
|
} else {
|
|
@@ -9137,6 +9748,7 @@ async function startPipeline(configPath) {
|
|
|
9137
9748
|
async function startSesameLoop(config, agent, toolRegistry, dataDir) {
|
|
9138
9749
|
const sesame = new SesameClient2(config.sesame);
|
|
9139
9750
|
registerMessagingTools(toolRegistry, sesame);
|
|
9751
|
+
let sesameSync = null;
|
|
9140
9752
|
let eventsWatcher = null;
|
|
9141
9753
|
if (dataDir) {
|
|
9142
9754
|
eventsWatcher = new EventsWatcher(dataDir, async (channelId, text, filename, eventType) => {
|
|
@@ -9159,11 +9771,20 @@ async function startSesameLoop(config, agent, toolRegistry, dataDir) {
|
|
|
9159
9771
|
eventsWatcher.start();
|
|
9160
9772
|
}
|
|
9161
9773
|
let shuttingDown = false;
|
|
9162
|
-
const shutdown = (signal) => {
|
|
9774
|
+
const shutdown = async (signal) => {
|
|
9163
9775
|
if (shuttingDown) return;
|
|
9164
9776
|
shuttingDown = true;
|
|
9165
9777
|
console.log(`
|
|
9166
9778
|
[hivemind] Received ${signal}, shutting down...`);
|
|
9779
|
+
if (sesameSync) {
|
|
9780
|
+
try {
|
|
9781
|
+
await sesameSync.flushBeforeCompaction(void 0, `Shutdown via ${signal}`);
|
|
9782
|
+
sesameSync.stopPeriodicSync();
|
|
9783
|
+
console.log("[hivemind] Sesame state flushed before shutdown");
|
|
9784
|
+
} catch (err) {
|
|
9785
|
+
console.warn("[hivemind] Sesame flush failed:", err.message);
|
|
9786
|
+
}
|
|
9787
|
+
}
|
|
9167
9788
|
try {
|
|
9168
9789
|
sesame.updatePresence("offline", { emoji: "\u2B58" });
|
|
9169
9790
|
sesame.disconnect();
|
|
@@ -9253,6 +9874,21 @@ async function startSesameLoop(config, agent, toolRegistry, dataDir) {
|
|
|
9253
9874
|
await sesame.connect();
|
|
9254
9875
|
sesameConnected = true;
|
|
9255
9876
|
console.log("[hivemind] Listening for Sesame messages");
|
|
9877
|
+
const agentId = sesame.getAgentId();
|
|
9878
|
+
if (agentId && dataDir) {
|
|
9879
|
+
const hivemindHome = process.env.HIVEMIND_HOME || resolve21(process.env.HOME || "/root", "hivemind");
|
|
9880
|
+
const workspaceDir = resolve21(hivemindHome, config.agent.workspace || "workspace");
|
|
9881
|
+
sesameSync = new SesameSync(config.sesame, agentId, workspaceDir, dataDir);
|
|
9882
|
+
try {
|
|
9883
|
+
await sesameSync.pushState();
|
|
9884
|
+
console.log("[hivemind] Initial Sesame state sync complete");
|
|
9885
|
+
} catch (err) {
|
|
9886
|
+
console.warn("[hivemind] Initial Sesame state sync failed:", err.message);
|
|
9887
|
+
}
|
|
9888
|
+
sesameSync.startPeriodicSync(config.memory.daemon_url, 5 * 60 * 1e3, 30 * 60 * 1e3);
|
|
9889
|
+
process.on("exit", () => sesameSync?.stopPeriodicSync());
|
|
9890
|
+
console.log("[hivemind] Sesame sync module initialized");
|
|
9891
|
+
}
|
|
9256
9892
|
await new Promise(() => {
|
|
9257
9893
|
});
|
|
9258
9894
|
}
|
|
@@ -9300,8 +9936,8 @@ ${response.content}
|
|
|
9300
9936
|
console.error("Error:", err.message);
|
|
9301
9937
|
}
|
|
9302
9938
|
});
|
|
9303
|
-
return new Promise((
|
|
9304
|
-
rl.on("close",
|
|
9939
|
+
return new Promise((resolve22) => {
|
|
9940
|
+
rl.on("close", resolve22);
|
|
9305
9941
|
});
|
|
9306
9942
|
}
|
|
9307
9943
|
async function runSpawnTask(config, configPath) {
|
|
@@ -9312,7 +9948,7 @@ async function runSpawnTask(config, configPath) {
|
|
|
9312
9948
|
const spawnDir = process.env.SPAWN_DIR;
|
|
9313
9949
|
console.log(`[spawn] Sub-agent starting (id: ${spawnId}, context: ${context})`);
|
|
9314
9950
|
const agent = new Agent(config, context);
|
|
9315
|
-
const hivemindHome = process.env.HIVEMIND_HOME ||
|
|
9951
|
+
const hivemindHome = process.env.HIVEMIND_HOME || resolve21(process.env.HOME || "/root", "hivemind");
|
|
9316
9952
|
const toolRegistry = registerAllTools(hivemindHome, {
|
|
9317
9953
|
enabled: true,
|
|
9318
9954
|
workspace: config.agent.workspace || "workspace",
|
|
@@ -9325,7 +9961,7 @@ async function runSpawnTask(config, configPath) {
|
|
|
9325
9961
|
const result = response.content;
|
|
9326
9962
|
console.log(`[spawn] Task completed (context: ${response.context})`);
|
|
9327
9963
|
if (spawnDir) {
|
|
9328
|
-
|
|
9964
|
+
writeFileSync10(resolve21(spawnDir, "result.txt"), result);
|
|
9329
9965
|
}
|
|
9330
9966
|
if (channelId && config.sesame.api_key) {
|
|
9331
9967
|
try {
|
|
@@ -9342,7 +9978,7 @@ async function runSpawnTask(config, configPath) {
|
|
|
9342
9978
|
const errorMsg = `[SPAWN ERROR] ${err.message}`;
|
|
9343
9979
|
console.error(`[spawn] ${errorMsg}`);
|
|
9344
9980
|
if (spawnDir) {
|
|
9345
|
-
|
|
9981
|
+
writeFileSync10(resolve21(spawnDir, "result.txt"), errorMsg);
|
|
9346
9982
|
}
|
|
9347
9983
|
process.exitCode = 1;
|
|
9348
9984
|
}
|
|
@@ -9373,20 +10009,20 @@ var WorkerServer = class {
|
|
|
9373
10009
|
}
|
|
9374
10010
|
/** Start listening. */
|
|
9375
10011
|
async start() {
|
|
9376
|
-
return new Promise((
|
|
10012
|
+
return new Promise((resolve22, reject) => {
|
|
9377
10013
|
this.server = createServer4((req, res) => this.handleRequest(req, res));
|
|
9378
10014
|
this.server.on("error", reject);
|
|
9379
|
-
this.server.listen(this.port, () =>
|
|
10015
|
+
this.server.listen(this.port, () => resolve22());
|
|
9380
10016
|
});
|
|
9381
10017
|
}
|
|
9382
10018
|
/** Stop the server. */
|
|
9383
10019
|
async stop() {
|
|
9384
|
-
return new Promise((
|
|
10020
|
+
return new Promise((resolve22) => {
|
|
9385
10021
|
if (!this.server) {
|
|
9386
|
-
|
|
10022
|
+
resolve22();
|
|
9387
10023
|
return;
|
|
9388
10024
|
}
|
|
9389
|
-
this.server.close(() =>
|
|
10025
|
+
this.server.close(() => resolve22());
|
|
9390
10026
|
});
|
|
9391
10027
|
}
|
|
9392
10028
|
getPort() {
|
|
@@ -9509,10 +10145,10 @@ var WorkerServer = class {
|
|
|
9509
10145
|
}
|
|
9510
10146
|
};
|
|
9511
10147
|
function readBody2(req) {
|
|
9512
|
-
return new Promise((
|
|
10148
|
+
return new Promise((resolve22, reject) => {
|
|
9513
10149
|
const chunks = [];
|
|
9514
10150
|
req.on("data", (chunk) => chunks.push(chunk));
|
|
9515
|
-
req.on("end", () =>
|
|
10151
|
+
req.on("end", () => resolve22(Buffer.concat(chunks).toString("utf-8")));
|
|
9516
10152
|
req.on("error", reject);
|
|
9517
10153
|
});
|
|
9518
10154
|
}
|
|
@@ -9854,4 +10490,4 @@ smol-toml/dist/index.js:
|
|
|
9854
10490
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
9855
10491
|
*)
|
|
9856
10492
|
*/
|
|
9857
|
-
//# sourceMappingURL=chunk-
|
|
10493
|
+
//# sourceMappingURL=chunk-TETVPYWD.js.map
|