mcp-agents-memory 0.9.16 → 0.9.18
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/build/index.js +121 -21
- package/build/migrations/028_raw_message.js +26000 -0
- package/package.json +3 -2
package/build/index.js
CHANGED
|
@@ -47034,6 +47034,88 @@ import * as os3 from "node:os";
|
|
|
47034
47034
|
|
|
47035
47035
|
// src/hot_path.ts
|
|
47036
47036
|
init_db();
|
|
47037
|
+
|
|
47038
|
+
// src/auto_save/buzz_envelope.ts
|
|
47039
|
+
var PREAMBLE_BLOCKS = ["agent-instructions", "core-memory"];
|
|
47040
|
+
var HISTORY_OPEN = /^\s*<((?:thread|conversation)-context)(?:\s[^>]*)?>/;
|
|
47041
|
+
var TURN_OPEN = /^\s*<(?:what-you-were-working-on|buzz-events?|new-message-arrived-while-you-were-working)[\s>]/;
|
|
47042
|
+
var TURN_IN_DROPPED = /(?:^|>)[ \t]*<(?:what-you-were-working-on|buzz-events?|new-message-arrived-while-you-were-working)[\s>]/m;
|
|
47043
|
+
var CONTEXT_OPEN = /^<context>\r?\n/;
|
|
47044
|
+
var CONTEXT_CLOSE = "\n</context>";
|
|
47045
|
+
function isNostrMetaLine(line) {
|
|
47046
|
+
return /^Tags: \[\[".*\]\]\s*$/.test(line) && /[0-9a-f]{64}/.test(line) || /^Parsed: (?:root=[0-9a-f]{64}|mentions=\[.*\([0-9a-f]{64}\))/.test(line);
|
|
47047
|
+
}
|
|
47048
|
+
function skipWhitespace(s, i) {
|
|
47049
|
+
while (i < s.length && /\s/.test(s[i])) i++;
|
|
47050
|
+
return i;
|
|
47051
|
+
}
|
|
47052
|
+
function cleanBuzzEnvelope(message) {
|
|
47053
|
+
try {
|
|
47054
|
+
const text = message.trimStart();
|
|
47055
|
+
if (!text.startsWith("<base>")) return null;
|
|
47056
|
+
const baseEnd = text.indexOf("</base>");
|
|
47057
|
+
if (baseEnd < 0) return null;
|
|
47058
|
+
const rest = text.slice(baseEnd + "</base>".length);
|
|
47059
|
+
let pos = skipWhitespace(rest, 0);
|
|
47060
|
+
for (; ; ) {
|
|
47061
|
+
const name = PREAMBLE_BLOCKS.find((b) => rest.startsWith(`<${b}>`, pos));
|
|
47062
|
+
if (!name) break;
|
|
47063
|
+
const close = rest.indexOf(`</${name}>`, pos);
|
|
47064
|
+
if (close < 0) return null;
|
|
47065
|
+
pos = skipWhitespace(rest, close + name.length + 3);
|
|
47066
|
+
}
|
|
47067
|
+
if (!CONTEXT_OPEN.test(rest.slice(pos, pos + 12))) return null;
|
|
47068
|
+
const bodyStart = rest.indexOf("\n", pos) + 1;
|
|
47069
|
+
const contextClose = rest.indexOf(CONTEXT_CLOSE, bodyStart - 1);
|
|
47070
|
+
if (contextClose < 0) return null;
|
|
47071
|
+
const contextBody = rest.slice(bodyStart, contextClose).replace(/\r$/, "");
|
|
47072
|
+
const tail = rest.slice(contextClose + CONTEXT_CLOSE.length);
|
|
47073
|
+
let turnStart = 0;
|
|
47074
|
+
const history = HISTORY_OPEN.exec(tail);
|
|
47075
|
+
if (history) {
|
|
47076
|
+
const closeTag = `</${history[1]}>`;
|
|
47077
|
+
const close = tail.indexOf(closeTag, history[0].length);
|
|
47078
|
+
if (close < 0) return null;
|
|
47079
|
+
turnStart = close + closeTag.length;
|
|
47080
|
+
}
|
|
47081
|
+
if (TURN_IN_DROPPED.test(rest.slice(0, pos)) || TURN_IN_DROPPED.test(tail.slice(0, turnStart))) return null;
|
|
47082
|
+
const turn = tail.slice(turnStart);
|
|
47083
|
+
if (!TURN_OPEN.test(turn)) return null;
|
|
47084
|
+
const turnText = turn.split("\n").filter((line) => !isNostrMetaLine(line)).join("\n").trim();
|
|
47085
|
+
if (!turnText) return null;
|
|
47086
|
+
const cleaned = `<context>
|
|
47087
|
+
${contextBody}
|
|
47088
|
+
</context>
|
|
47089
|
+
|
|
47090
|
+
${turnText}`;
|
|
47091
|
+
if (cleaned.length >= message.length) return null;
|
|
47092
|
+
return cleaned;
|
|
47093
|
+
} catch {
|
|
47094
|
+
return null;
|
|
47095
|
+
}
|
|
47096
|
+
}
|
|
47097
|
+
var EVENT_HEADER = /^(?:Event ID: [0-9a-f]{64}|Kind: \d+|Time: \d{4}-\d{2}-\d{2}T\S+|--- Event \d+ \(.*\) ---|Note: A new message arrived while you were working\..*)\s*$/;
|
|
47098
|
+
function buzzEmbeddingText(message) {
|
|
47099
|
+
try {
|
|
47100
|
+
if (!message.startsWith("<context>\n")) return message;
|
|
47101
|
+
const close = message.indexOf(CONTEXT_CLOSE);
|
|
47102
|
+
if (close < 0) return message;
|
|
47103
|
+
const turn = message.slice(close + CONTEXT_CLOSE.length);
|
|
47104
|
+
if (!TURN_OPEN.test(turn)) return message;
|
|
47105
|
+
const text = turn.split("\n").filter((line) => !EVENT_HEADER.test(line) && !isNostrMetaLine(line)).map(
|
|
47106
|
+
(line) => (
|
|
47107
|
+
// `$` 없이: 끝까지 되짚는 역추적을 막는다 (긴 줄에서 제곱 시간)
|
|
47108
|
+
line.replace(/^From: (.*?) \(npub:.*/, "From: $1").replace(/^Channel: (\S+) \(#[0-9a-f-]+\)/, "Channel: $1")
|
|
47109
|
+
)
|
|
47110
|
+
).join("\n").trim();
|
|
47111
|
+
return text || message;
|
|
47112
|
+
} catch {
|
|
47113
|
+
return message;
|
|
47114
|
+
}
|
|
47115
|
+
}
|
|
47116
|
+
|
|
47117
|
+
// src/hot_path.ts
|
|
47118
|
+
var rawMessageColumnMissing = false;
|
|
47037
47119
|
async function insertRawMemory(params) {
|
|
47038
47120
|
const {
|
|
47039
47121
|
user_id,
|
|
@@ -47053,25 +47135,26 @@ async function insertRawMemory(params) {
|
|
|
47053
47135
|
} = params;
|
|
47054
47136
|
const embeddingSql = embedding && embedding.length > 0 ? `[${embedding.join(",")}]` : null;
|
|
47055
47137
|
const tagProcessed = p_tag_id !== null;
|
|
47056
|
-
const
|
|
47138
|
+
const cleaned = role === "user" && !is_pinned && p_tag_id === null && embeddingSql === null ? cleanBuzzEnvelope(message) : null;
|
|
47139
|
+
const insert = (text, raw) => db.query(
|
|
47057
47140
|
`INSERT INTO memory (
|
|
47058
|
-
|
|
47059
|
-
|
|
47060
|
-
|
|
47061
|
-
|
|
47062
|
-
|
|
47063
|
-
|
|
47064
|
-
|
|
47065
|
-
|
|
47066
|
-
|
|
47067
|
-
|
|
47068
|
-
|
|
47069
|
-
|
|
47070
|
-
|
|
47071
|
-
|
|
47072
|
-
|
|
47073
|
-
|
|
47074
|
-
|
|
47141
|
+
user_id, agent_platform, agent_model,
|
|
47142
|
+
subagent, subagent_model, subagent_role,
|
|
47143
|
+
role, message,
|
|
47144
|
+
p_tag_id, d_tag, embedding,
|
|
47145
|
+
is_pinned, tag_processed, external_uuid,
|
|
47146
|
+
device_name${raw !== null ? ", raw_message" : ""}
|
|
47147
|
+
) VALUES (
|
|
47148
|
+
$1, $2, $3,
|
|
47149
|
+
$4, $5, $6,
|
|
47150
|
+
$7, $8,
|
|
47151
|
+
$9, $10::text[], $11::halfvec,
|
|
47152
|
+
$12, $13, $14,
|
|
47153
|
+
$15${raw !== null ? ", $16" : ""}
|
|
47154
|
+
)
|
|
47155
|
+
ON CONFLICT (external_uuid) WHERE external_uuid IS NOT NULL
|
|
47156
|
+
DO NOTHING
|
|
47157
|
+
RETURNING id, created_at`,
|
|
47075
47158
|
[
|
|
47076
47159
|
user_id,
|
|
47077
47160
|
agent_platform,
|
|
@@ -47080,16 +47163,33 @@ async function insertRawMemory(params) {
|
|
|
47080
47163
|
subagent_model,
|
|
47081
47164
|
subagent_role,
|
|
47082
47165
|
role,
|
|
47083
|
-
|
|
47166
|
+
text,
|
|
47084
47167
|
p_tag_id,
|
|
47085
47168
|
d_tag,
|
|
47086
47169
|
embeddingSql,
|
|
47087
47170
|
is_pinned,
|
|
47088
47171
|
tagProcessed,
|
|
47089
47172
|
external_uuid,
|
|
47090
|
-
device_name
|
|
47173
|
+
device_name,
|
|
47174
|
+
...raw !== null ? [raw] : []
|
|
47091
47175
|
]
|
|
47092
47176
|
);
|
|
47177
|
+
let result;
|
|
47178
|
+
if (cleaned !== null && !rawMessageColumnMissing) {
|
|
47179
|
+
try {
|
|
47180
|
+
result = await insert(cleaned, message);
|
|
47181
|
+
} catch (err3) {
|
|
47182
|
+
const e = err3;
|
|
47183
|
+
if (e.code !== "42703" || !e.message?.includes("raw_message")) throw err3;
|
|
47184
|
+
rawMessageColumnMissing = true;
|
|
47185
|
+
console.error(
|
|
47186
|
+
"\u26A0\uFE0F [HotPath] memory.raw_message \uCE78\uC774 \uC5C6\uC2B5\uB2C8\uB2E4 \u2014 `mcp-agents-memory migrate` \uC2E4\uD589 \uD6C4 \uC774 \uD504\uB85C\uC138\uC2A4\uB97C \uC7AC\uC2DC\uC791\uD574\uC57C Buzz \uBD09\uD22C \uC815\uB9AC\uAC00 \uC2DC\uC791\uB429\uB2C8\uB2E4. \uADF8 \uC804\uAE4C\uC9C0\uB294 \uC6D0\uBB38 \uADF8\uB300\uB85C \uC800\uC7A5\uD569\uB2C8\uB2E4."
|
|
47187
|
+
);
|
|
47188
|
+
result = await insert(message, null);
|
|
47189
|
+
}
|
|
47190
|
+
} else {
|
|
47191
|
+
result = await insert(message, null);
|
|
47192
|
+
}
|
|
47093
47193
|
if (result.rows.length === 0) {
|
|
47094
47194
|
const existing = await db.query(
|
|
47095
47195
|
`SELECT id, created_at FROM memory WHERE external_uuid = $1 LIMIT 1`,
|
|
@@ -60397,7 +60497,7 @@ async function processOne(client2, row) {
|
|
|
60397
60497
|
promises.push(
|
|
60398
60498
|
(async () => {
|
|
60399
60499
|
try {
|
|
60400
|
-
embedding = await embedMessage(row.message);
|
|
60500
|
+
embedding = await embedMessage(buzzEmbeddingText(row.message));
|
|
60401
60501
|
} catch (err3) {
|
|
60402
60502
|
embedError = err3;
|
|
60403
60503
|
}
|