@sesamespace/hivemind 0.5.14 → 0.5.16
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/README.md +30 -0
- package/dist/{chunk-TRXLCIB4.js → chunk-4QICI4U6.js} +2 -2
- package/dist/{chunk-YMQR5I6C.js → chunk-7DZAH77W.js} +3 -3
- package/dist/{chunk-QAOBO4W4.js → chunk-BQCSFDSS.js} +129 -115
- package/dist/chunk-BQCSFDSS.js.map +1 -0
- package/dist/{chunk-7GZ545B5.js → chunk-GVFYI54W.js} +2 -2
- package/dist/{chunk-AGFKYYWT.js → chunk-ZDL7HL6V.js} +2 -2
- package/dist/commands/fleet.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 +5 -5
- package/dist/start.js +1 -1
- package/package.json +1 -2
- package/dist/chunk-QAOBO4W4.js.map +0 -1
- /package/dist/{chunk-TRXLCIB4.js.map → chunk-4QICI4U6.js.map} +0 -0
- /package/dist/{chunk-YMQR5I6C.js.map → chunk-7DZAH77W.js.map} +0 -0
- /package/dist/{chunk-7GZ545B5.js.map → chunk-GVFYI54W.js.map} +0 -0
- /package/dist/{chunk-AGFKYYWT.js.map → chunk-ZDL7HL6V.js.map} +0 -0
package/README.md
CHANGED
|
@@ -67,6 +67,36 @@ cd packages/memory && cargo build --release && cd ../..
|
|
|
67
67
|
| L3 | Semantic Memory | Promoted knowledge (high-access patterns) |
|
|
68
68
|
| L4 | External Memory | Git, files, APIs (on-demand) |
|
|
69
69
|
|
|
70
|
+
## Dashboard
|
|
71
|
+
|
|
72
|
+
Local web UI for debugging memory and LLM request formation.
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
http://localhost:9485
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
- **Request Inspector:** View every LLM call with full prompt breakdown (identity files, L3 knowledge, L2 episodes with scores, L1 history, config snapshot, token estimates)
|
|
79
|
+
- **Memory Browser:** Search L2 episodes, view/delete L3 entries per context
|
|
80
|
+
- **Context Overview:** List contexts with episode counts
|
|
81
|
+
|
|
82
|
+
Bound to localhost only, no auth required. Starts automatically with the agent.
|
|
83
|
+
|
|
84
|
+
## Agent Introspection Commands
|
|
85
|
+
|
|
86
|
+
Use `hm:` prefix in DMs (not group chats — may collide with other agents' platforms):
|
|
87
|
+
|
|
88
|
+
| Command | Description |
|
|
89
|
+
|---------|-------------|
|
|
90
|
+
| `hm:status` | Agent health, memory daemon, model, active context |
|
|
91
|
+
| `hm:config` | Full configuration details |
|
|
92
|
+
| `hm:contexts` | All contexts with L1/L2 info |
|
|
93
|
+
| `hm:memory stats` | Episode counts and L3 entries per context |
|
|
94
|
+
| `hm:memory search <query>` | Search L2 memories with similarity scores |
|
|
95
|
+
| `hm:memory l3 [context]` | View promoted L3 knowledge entries |
|
|
96
|
+
| `hm:help` | List all available commands |
|
|
97
|
+
|
|
98
|
+
These bypass the LLM — deterministic, direct daemon queries.
|
|
99
|
+
|
|
70
100
|
## CLI Commands
|
|
71
101
|
|
|
72
102
|
| Command | Description |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
FleetManager
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-ZDL7HL6V.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-4QICI4U6.js.map
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Watchdog
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-ZDL7HL6V.js";
|
|
4
4
|
import {
|
|
5
5
|
defaultSentinelConfig,
|
|
6
6
|
loadConfig
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-BQCSFDSS.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-7DZAH77W.js.map
|
|
@@ -546,6 +546,7 @@ ${charter}
|
|
|
546
546
|
Messages are prefixed with [sender_handle]: or [sender_handle in group chat]: to tell you who's talking.
|
|
547
547
|
In group chats, multiple people (humans and agents) may be present. Address them by name when relevant.
|
|
548
548
|
Don't repeat or quote these prefixes in your responses \u2014 just respond naturally.
|
|
549
|
+
Keep responses concise \u2014 especially in group chats. A few sentences is usually enough. Don't write essays.
|
|
549
550
|
If you decide not to respond to a group message, reply with exactly: __SKIP__
|
|
550
551
|
`;
|
|
551
552
|
let contextInfo = "";
|
|
@@ -750,7 +751,7 @@ var Agent = class {
|
|
|
750
751
|
let stripped = message.replace(/^\[.+?\s+in\s+group\s+chat\]:\s*/, "");
|
|
751
752
|
stripped = stripped.replace(/^\[.+?\]:\s*/, "");
|
|
752
753
|
const cmdText = stripped;
|
|
753
|
-
if (
|
|
754
|
+
if (/^hm[:\s]status\b/i.test(cmdText)) {
|
|
754
755
|
const memoryOk = await this.memory.healthCheck();
|
|
755
756
|
const contexts = this.contextManager.listContexts();
|
|
756
757
|
let contextStats = "";
|
|
@@ -778,7 +779,7 @@ var Agent = class {
|
|
|
778
779
|
].join("\n");
|
|
779
780
|
return { content: response, model: "system", context: activeCtx };
|
|
780
781
|
}
|
|
781
|
-
if (
|
|
782
|
+
if (/^hm[:\s]memory\s+stats\b/i.test(cmdText)) {
|
|
782
783
|
try {
|
|
783
784
|
const contexts = await this.memory.listContexts();
|
|
784
785
|
let totalEpisodes = 0;
|
|
@@ -810,7 +811,7 @@ var Agent = class {
|
|
|
810
811
|
return { content: `Memory stats failed: ${err.message}`, model: "system", context: activeCtx };
|
|
811
812
|
}
|
|
812
813
|
}
|
|
813
|
-
const memSearchMatch = cmdText.match(
|
|
814
|
+
const memSearchMatch = cmdText.match(/^hm[:\s]memory\s+search\s+(.+)/i);
|
|
814
815
|
if (memSearchMatch) {
|
|
815
816
|
const query = memSearchMatch[1].trim();
|
|
816
817
|
try {
|
|
@@ -831,7 +832,7 @@ var Agent = class {
|
|
|
831
832
|
return { content: `Memory search failed: ${err.message}`, model: "system", context: activeCtx };
|
|
832
833
|
}
|
|
833
834
|
}
|
|
834
|
-
const l3Match = cmdText.match(
|
|
835
|
+
const l3Match = cmdText.match(/^hm[:\s]memory\s+l3(?:\s+(\S+))?/i);
|
|
835
836
|
if (l3Match) {
|
|
836
837
|
const targetCtx = l3Match[1] || activeCtx;
|
|
837
838
|
try {
|
|
@@ -852,7 +853,7 @@ var Agent = class {
|
|
|
852
853
|
return { content: `L3 query failed: ${err.message}`, model: "system", context: activeCtx };
|
|
853
854
|
}
|
|
854
855
|
}
|
|
855
|
-
if (
|
|
856
|
+
if (/^hm[:\s]config\b/i.test(cmdText)) {
|
|
856
857
|
const response = [
|
|
857
858
|
`## Configuration`,
|
|
858
859
|
``,
|
|
@@ -878,7 +879,7 @@ var Agent = class {
|
|
|
878
879
|
].join("\n");
|
|
879
880
|
return { content: response, model: "system", context: activeCtx };
|
|
880
881
|
}
|
|
881
|
-
if (
|
|
882
|
+
if (/^hm[:\s]contexts\b/i.test(cmdText)) {
|
|
882
883
|
const localContexts = this.contextManager.listContexts();
|
|
883
884
|
let daemonInfo = "";
|
|
884
885
|
try {
|
|
@@ -905,17 +906,18 @@ var Agent = class {
|
|
|
905
906
|
].join("\n");
|
|
906
907
|
return { content: response, model: "system", context: activeCtx };
|
|
907
908
|
}
|
|
908
|
-
if (
|
|
909
|
+
if (/^hm[:\s]help\b/i.test(cmdText)) {
|
|
909
910
|
const response = [
|
|
910
911
|
`## Available Commands`,
|
|
911
912
|
``,
|
|
912
913
|
`### Introspection`,
|
|
913
|
-
`-
|
|
914
|
-
`-
|
|
915
|
-
`-
|
|
916
|
-
`-
|
|
917
|
-
`-
|
|
918
|
-
`-
|
|
914
|
+
`- \`hm:status\` \u2014 Agent health, memory status, config summary`,
|
|
915
|
+
`- \`hm:config\` \u2014 Full configuration details`,
|
|
916
|
+
`- \`hm:contexts\` \u2014 List all contexts with L1/L2 info`,
|
|
917
|
+
`- \`hm:memory stats\` \u2014 Episode counts, L3 entries per context`,
|
|
918
|
+
`- \`hm:memory search <query>\` \u2014 Search L2 memories with scores`,
|
|
919
|
+
`- \`hm:memory l3 [context]\` \u2014 Show L3 knowledge entries`,
|
|
920
|
+
`- \`hm:help\` \u2014 This help message`,
|
|
919
921
|
``,
|
|
920
922
|
`### Context Management`,
|
|
921
923
|
`- \`switch to <name>\` \u2014 Switch active context`,
|
|
@@ -1997,58 +1999,42 @@ var HEALTH_PORT = 9484;
|
|
|
1997
1999
|
var HEALTH_PATH = "/health";
|
|
1998
2000
|
|
|
1999
2001
|
// packages/runtime/src/request-logger.ts
|
|
2000
|
-
import Database from "better-sqlite3";
|
|
2001
2002
|
import { randomUUID } from "crypto";
|
|
2002
|
-
import { mkdirSync, existsSync as existsSync3 } from "fs";
|
|
2003
|
+
import { mkdirSync, existsSync as existsSync3, appendFileSync, readFileSync as readFileSync4, writeFileSync } from "fs";
|
|
2003
2004
|
import { dirname as dirname3 } from "path";
|
|
2004
2005
|
var RequestLogger = class {
|
|
2005
|
-
|
|
2006
|
+
logPath;
|
|
2007
|
+
maxAgeDays = 7;
|
|
2006
2008
|
constructor(dbPath) {
|
|
2007
|
-
|
|
2009
|
+
this.logPath = dbPath.replace(/\.db$/, ".jsonl");
|
|
2010
|
+
if (this.logPath === dbPath) this.logPath = dbPath + ".jsonl";
|
|
2011
|
+
const dir = dirname3(this.logPath);
|
|
2008
2012
|
if (!existsSync3(dir)) mkdirSync(dir, { recursive: true });
|
|
2009
|
-
this.db = new Database(dbPath);
|
|
2010
|
-
this.db.pragma("journal_mode = WAL");
|
|
2011
|
-
this.db.pragma("synchronous = NORMAL");
|
|
2012
|
-
this.init();
|
|
2013
2013
|
this.prune();
|
|
2014
2014
|
}
|
|
2015
|
-
init() {
|
|
2016
|
-
this.db.exec(`
|
|
2017
|
-
CREATE TABLE IF NOT EXISTS request_logs (
|
|
2018
|
-
id TEXT PRIMARY KEY,
|
|
2019
|
-
timestamp TEXT NOT NULL,
|
|
2020
|
-
context TEXT NOT NULL,
|
|
2021
|
-
context_switched INTEGER NOT NULL DEFAULT 0,
|
|
2022
|
-
routing_reason TEXT NOT NULL DEFAULT '',
|
|
2023
|
-
channel_id TEXT NOT NULL DEFAULT '',
|
|
2024
|
-
channel_kind TEXT NOT NULL DEFAULT '',
|
|
2025
|
-
sender_handle TEXT NOT NULL DEFAULT '',
|
|
2026
|
-
raw_message TEXT NOT NULL,
|
|
2027
|
-
system_prompt_components TEXT NOT NULL,
|
|
2028
|
-
conversation_history TEXT NOT NULL,
|
|
2029
|
-
user_message TEXT NOT NULL,
|
|
2030
|
-
response_content TEXT NOT NULL,
|
|
2031
|
-
response_model TEXT NOT NULL,
|
|
2032
|
-
response_latency_ms INTEGER NOT NULL,
|
|
2033
|
-
response_skipped INTEGER NOT NULL DEFAULT 0,
|
|
2034
|
-
config_snapshot TEXT NOT NULL,
|
|
2035
|
-
token_est_system INTEGER NOT NULL DEFAULT 0,
|
|
2036
|
-
token_est_history INTEGER NOT NULL DEFAULT 0,
|
|
2037
|
-
token_est_user INTEGER NOT NULL DEFAULT 0,
|
|
2038
|
-
token_est_total INTEGER NOT NULL DEFAULT 0
|
|
2039
|
-
)
|
|
2040
|
-
`);
|
|
2041
|
-
this.db.exec(`
|
|
2042
|
-
CREATE INDEX IF NOT EXISTS idx_request_logs_timestamp ON request_logs(timestamp DESC);
|
|
2043
|
-
CREATE INDEX IF NOT EXISTS idx_request_logs_context ON request_logs(context);
|
|
2044
|
-
CREATE INDEX IF NOT EXISTS idx_request_logs_sender ON request_logs(sender_handle);
|
|
2045
|
-
`);
|
|
2046
|
-
}
|
|
2047
2015
|
prune() {
|
|
2048
|
-
|
|
2049
|
-
const
|
|
2050
|
-
|
|
2051
|
-
|
|
2016
|
+
if (!existsSync3(this.logPath)) return;
|
|
2017
|
+
const cutoff = new Date(Date.now() - this.maxAgeDays * 24 * 60 * 60 * 1e3).toISOString();
|
|
2018
|
+
try {
|
|
2019
|
+
const lines = readFileSync4(this.logPath, "utf-8").split("\n").filter(Boolean);
|
|
2020
|
+
const kept = [];
|
|
2021
|
+
let pruned = 0;
|
|
2022
|
+
for (const line of lines) {
|
|
2023
|
+
try {
|
|
2024
|
+
const entry = JSON.parse(line);
|
|
2025
|
+
if (entry.timestamp >= cutoff) {
|
|
2026
|
+
kept.push(line);
|
|
2027
|
+
} else {
|
|
2028
|
+
pruned++;
|
|
2029
|
+
}
|
|
2030
|
+
} catch {
|
|
2031
|
+
}
|
|
2032
|
+
}
|
|
2033
|
+
if (pruned > 0) {
|
|
2034
|
+
writeFileSync(this.logPath, kept.join("\n") + (kept.length > 0 ? "\n" : ""));
|
|
2035
|
+
console.log(`[dashboard] Pruned ${pruned} old request logs`);
|
|
2036
|
+
}
|
|
2037
|
+
} catch {
|
|
2052
2038
|
}
|
|
2053
2039
|
}
|
|
2054
2040
|
log(entry) {
|
|
@@ -2059,78 +2045,73 @@ var RequestLogger = class {
|
|
|
2059
2045
|
entry.conversationHistory.reduce((sum, m) => sum + m.content.length, 0) / 4
|
|
2060
2046
|
);
|
|
2061
2047
|
const userTokens = Math.ceil(entry.userMessage.length / 4);
|
|
2062
|
-
|
|
2063
|
-
`INSERT INTO request_logs (
|
|
2064
|
-
id, timestamp, context, context_switched, routing_reason,
|
|
2065
|
-
channel_id, channel_kind, sender_handle, raw_message,
|
|
2066
|
-
system_prompt_components, conversation_history, user_message,
|
|
2067
|
-
response_content, response_model, response_latency_ms, response_skipped,
|
|
2068
|
-
config_snapshot,
|
|
2069
|
-
token_est_system, token_est_history, token_est_user, token_est_total
|
|
2070
|
-
) VALUES (
|
|
2071
|
-
?, ?, ?, ?, ?,
|
|
2072
|
-
?, ?, ?, ?,
|
|
2073
|
-
?, ?, ?,
|
|
2074
|
-
?, ?, ?, ?,
|
|
2075
|
-
?,
|
|
2076
|
-
?, ?, ?, ?
|
|
2077
|
-
)`
|
|
2078
|
-
).run(
|
|
2048
|
+
const record = {
|
|
2079
2049
|
id,
|
|
2080
2050
|
timestamp,
|
|
2081
|
-
entry.context,
|
|
2082
|
-
entry.contextSwitched
|
|
2083
|
-
entry.routingReason,
|
|
2084
|
-
entry.channelId ?? "",
|
|
2085
|
-
entry.channelKind ?? "",
|
|
2086
|
-
entry.senderHandle ?? "",
|
|
2087
|
-
entry.rawMessage,
|
|
2088
|
-
JSON.stringify(entry.systemPromptComponents),
|
|
2089
|
-
JSON.stringify(entry.conversationHistory),
|
|
2090
|
-
entry.userMessage,
|
|
2091
|
-
entry.response.content,
|
|
2092
|
-
entry.response.model,
|
|
2093
|
-
entry.response.latencyMs,
|
|
2094
|
-
entry.response.skipped
|
|
2095
|
-
JSON.stringify(entry.config),
|
|
2096
|
-
sysTokens,
|
|
2097
|
-
histTokens,
|
|
2098
|
-
userTokens,
|
|
2099
|
-
sysTokens + histTokens + userTokens
|
|
2100
|
-
|
|
2051
|
+
context: entry.context,
|
|
2052
|
+
context_switched: entry.contextSwitched,
|
|
2053
|
+
routing_reason: entry.routingReason,
|
|
2054
|
+
channel_id: entry.channelId ?? "",
|
|
2055
|
+
channel_kind: entry.channelKind ?? "",
|
|
2056
|
+
sender_handle: entry.senderHandle ?? "",
|
|
2057
|
+
raw_message: entry.rawMessage,
|
|
2058
|
+
system_prompt_components: JSON.stringify(entry.systemPromptComponents),
|
|
2059
|
+
conversation_history: JSON.stringify(entry.conversationHistory),
|
|
2060
|
+
user_message: entry.userMessage,
|
|
2061
|
+
response_content: entry.response.content,
|
|
2062
|
+
response_model: entry.response.model,
|
|
2063
|
+
response_latency_ms: entry.response.latencyMs,
|
|
2064
|
+
response_skipped: entry.response.skipped,
|
|
2065
|
+
config_snapshot: JSON.stringify(entry.config),
|
|
2066
|
+
token_est_system: sysTokens,
|
|
2067
|
+
token_est_history: histTokens,
|
|
2068
|
+
token_est_user: userTokens,
|
|
2069
|
+
token_est_total: sysTokens + histTokens + userTokens
|
|
2070
|
+
};
|
|
2071
|
+
appendFileSync(this.logPath, JSON.stringify(record) + "\n");
|
|
2101
2072
|
return id;
|
|
2102
2073
|
}
|
|
2103
2074
|
getRequests(opts = {}) {
|
|
2104
2075
|
const limit = opts.limit ?? 50;
|
|
2105
2076
|
const offset = opts.offset ?? 0;
|
|
2106
|
-
|
|
2107
|
-
const params = [];
|
|
2077
|
+
let entries = this.readAll();
|
|
2108
2078
|
if (opts.context) {
|
|
2109
|
-
|
|
2110
|
-
params.push(opts.context);
|
|
2079
|
+
entries = entries.filter((e) => e.context === opts.context);
|
|
2111
2080
|
}
|
|
2112
2081
|
if (opts.sender) {
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
const
|
|
2117
|
-
const
|
|
2118
|
-
const requests = this.db.prepare(
|
|
2119
|
-
`SELECT * FROM request_logs ${where} ORDER BY timestamp DESC LIMIT ? OFFSET ?`
|
|
2120
|
-
).all(...params, limit, offset);
|
|
2082
|
+
entries = entries.filter((e) => e.sender_handle === opts.sender);
|
|
2083
|
+
}
|
|
2084
|
+
entries.sort((a, b) => b.timestamp.localeCompare(a.timestamp));
|
|
2085
|
+
const total = entries.length;
|
|
2086
|
+
const requests = entries.slice(offset, offset + limit);
|
|
2121
2087
|
return { requests, total };
|
|
2122
2088
|
}
|
|
2123
2089
|
getRequest(id) {
|
|
2124
|
-
return this.
|
|
2090
|
+
return this.readAll().find((e) => e.id === id);
|
|
2125
2091
|
}
|
|
2126
2092
|
close() {
|
|
2127
|
-
|
|
2093
|
+
}
|
|
2094
|
+
readAll() {
|
|
2095
|
+
if (!existsSync3(this.logPath)) return [];
|
|
2096
|
+
try {
|
|
2097
|
+
const lines = readFileSync4(this.logPath, "utf-8").split("\n").filter(Boolean);
|
|
2098
|
+
const entries = [];
|
|
2099
|
+
for (const line of lines) {
|
|
2100
|
+
try {
|
|
2101
|
+
entries.push(JSON.parse(line));
|
|
2102
|
+
} catch {
|
|
2103
|
+
}
|
|
2104
|
+
}
|
|
2105
|
+
return entries;
|
|
2106
|
+
} catch {
|
|
2107
|
+
return [];
|
|
2108
|
+
}
|
|
2128
2109
|
}
|
|
2129
2110
|
};
|
|
2130
2111
|
|
|
2131
2112
|
// packages/runtime/src/dashboard.ts
|
|
2132
2113
|
import { createServer } from "http";
|
|
2133
|
-
import { readFileSync as
|
|
2114
|
+
import { readFileSync as readFileSync5 } from "fs";
|
|
2134
2115
|
import { resolve as resolve4, dirname as dirname4 } from "path";
|
|
2135
2116
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
2136
2117
|
var __dirname = dirname4(fileURLToPath2(import.meta.url));
|
|
@@ -2140,7 +2121,7 @@ function getSpaHtml() {
|
|
|
2140
2121
|
if (!spaHtml) {
|
|
2141
2122
|
for (const dir of [__dirname, resolve4(__dirname, "../src")]) {
|
|
2142
2123
|
try {
|
|
2143
|
-
spaHtml =
|
|
2124
|
+
spaHtml = readFileSync5(resolve4(dir, "dashboard.html"), "utf-8");
|
|
2144
2125
|
break;
|
|
2145
2126
|
} catch {
|
|
2146
2127
|
}
|
|
@@ -2262,13 +2243,13 @@ function startDashboardServer(requestLogger, memoryConfig) {
|
|
|
2262
2243
|
}
|
|
2263
2244
|
|
|
2264
2245
|
// packages/runtime/src/pipeline.ts
|
|
2265
|
-
import { readFileSync as
|
|
2246
|
+
import { readFileSync as readFileSync6, writeFileSync as writeFileSync2, unlinkSync } from "fs";
|
|
2266
2247
|
import { resolve as resolve5, dirname as dirname5 } from "path";
|
|
2267
2248
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
2268
2249
|
var PACKAGE_VERSION = "unknown";
|
|
2269
2250
|
try {
|
|
2270
2251
|
const __dirname2 = dirname5(fileURLToPath3(import.meta.url));
|
|
2271
|
-
const pkg = JSON.parse(
|
|
2252
|
+
const pkg = JSON.parse(readFileSync6(resolve5(__dirname2, "../package.json"), "utf-8"));
|
|
2272
2253
|
PACKAGE_VERSION = pkg.version ?? "unknown";
|
|
2273
2254
|
} catch {
|
|
2274
2255
|
}
|
|
@@ -2299,7 +2280,7 @@ function startHealthServer(port) {
|
|
|
2299
2280
|
return server;
|
|
2300
2281
|
}
|
|
2301
2282
|
function writePidFile(path) {
|
|
2302
|
-
|
|
2283
|
+
writeFileSync2(path, String(process.pid));
|
|
2303
2284
|
console.log(`[hivemind] PID file written: ${path}`);
|
|
2304
2285
|
}
|
|
2305
2286
|
function cleanupPidFile(path) {
|
|
@@ -2361,8 +2342,41 @@ async function startSesameLoop(config, agent) {
|
|
|
2361
2342
|
};
|
|
2362
2343
|
process.on("SIGTERM", () => shutdown("SIGTERM"));
|
|
2363
2344
|
process.on("SIGINT", () => shutdown("SIGINT"));
|
|
2345
|
+
const processedIds = /* @__PURE__ */ new Set();
|
|
2346
|
+
const MAX_SEEN = 500;
|
|
2347
|
+
let processing = false;
|
|
2348
|
+
const messageQueue = [];
|
|
2349
|
+
async function processQueue() {
|
|
2350
|
+
if (processing || messageQueue.length === 0) return;
|
|
2351
|
+
processing = true;
|
|
2352
|
+
while (messageQueue.length > 0) {
|
|
2353
|
+
const msg = messageQueue.shift();
|
|
2354
|
+
await handleMessage(msg);
|
|
2355
|
+
}
|
|
2356
|
+
processing = false;
|
|
2357
|
+
}
|
|
2364
2358
|
sesame.onMessage(async (msg) => {
|
|
2365
2359
|
if (shuttingDown) return;
|
|
2360
|
+
if (processedIds.has(msg.id)) {
|
|
2361
|
+
console.log(`[sesame] Skipping duplicate message ${msg.id}`);
|
|
2362
|
+
return;
|
|
2363
|
+
}
|
|
2364
|
+
processedIds.add(msg.id);
|
|
2365
|
+
if (processedIds.size > MAX_SEEN) {
|
|
2366
|
+
const iter = processedIds.values();
|
|
2367
|
+
for (let i = 0; i < 100; i++) iter.next();
|
|
2368
|
+
const keep = /* @__PURE__ */ new Set();
|
|
2369
|
+
for (const id of processedIds) {
|
|
2370
|
+
if (keep.size >= MAX_SEEN - 100) break;
|
|
2371
|
+
keep.add(id);
|
|
2372
|
+
}
|
|
2373
|
+
processedIds.clear();
|
|
2374
|
+
for (const id of keep) processedIds.add(id);
|
|
2375
|
+
}
|
|
2376
|
+
messageQueue.push(msg);
|
|
2377
|
+
processQueue();
|
|
2378
|
+
});
|
|
2379
|
+
async function handleMessage(msg) {
|
|
2366
2380
|
console.log(`[sesame] ${msg.author.handle} (${msg.channelKind}): ${msg.content}`);
|
|
2367
2381
|
sesame.startTyping(msg.channelId);
|
|
2368
2382
|
sesame.updatePresence("thinking", { detail: `Replying to ${msg.author.handle}`, emoji: "\u{1F4AD}" });
|
|
@@ -2397,7 +2411,7 @@ async function startSesameLoop(config, agent) {
|
|
|
2397
2411
|
sesame.updatePresence("online", { emoji: "\u{1F7E2}" });
|
|
2398
2412
|
console.error("[sesame] Error processing message:", err.message);
|
|
2399
2413
|
}
|
|
2400
|
-
}
|
|
2414
|
+
}
|
|
2401
2415
|
await sesame.connect();
|
|
2402
2416
|
sesameConnected = true;
|
|
2403
2417
|
console.log("[hivemind] Listening for Sesame messages");
|
|
@@ -2944,4 +2958,4 @@ smol-toml/dist/index.js:
|
|
|
2944
2958
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
2945
2959
|
*)
|
|
2946
2960
|
*/
|
|
2947
|
-
//# sourceMappingURL=chunk-
|
|
2961
|
+
//# sourceMappingURL=chunk-BQCSFDSS.js.map
|