mcp-agents-memory 0.9.18 → 0.9.19
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 +387 -154
- package/build/migrations/029_venue.js +26000 -0
- package/package.json +2 -2
package/build/index.js
CHANGED
|
@@ -1675,15 +1675,15 @@ var require_pg_connection_string = __commonJS({
|
|
|
1675
1675
|
if (config2.sslcert || config2.sslkey || config2.sslrootcert || config2.sslmode) {
|
|
1676
1676
|
config2.ssl = {};
|
|
1677
1677
|
}
|
|
1678
|
-
const
|
|
1678
|
+
const fs14 = config2.sslcert || config2.sslkey || config2.sslrootcert ? __require("fs") : null;
|
|
1679
1679
|
if (config2.sslcert) {
|
|
1680
|
-
config2.ssl.cert =
|
|
1680
|
+
config2.ssl.cert = fs14.readFileSync(config2.sslcert).toString();
|
|
1681
1681
|
}
|
|
1682
1682
|
if (config2.sslkey) {
|
|
1683
|
-
config2.ssl.key =
|
|
1683
|
+
config2.ssl.key = fs14.readFileSync(config2.sslkey).toString();
|
|
1684
1684
|
}
|
|
1685
1685
|
if (config2.sslrootcert) {
|
|
1686
|
-
config2.ssl.ca =
|
|
1686
|
+
config2.ssl.ca = fs14.readFileSync(config2.sslrootcert).toString();
|
|
1687
1687
|
}
|
|
1688
1688
|
if (options.useLibpqCompat && config2.uselibpqcompat) {
|
|
1689
1689
|
throw new Error("Both useLibpqCompat and uselibpqcompat are set. Please use only one of them.");
|
|
@@ -3620,15 +3620,15 @@ var require_lib = __commonJS({
|
|
|
3620
3620
|
"../mcp-agents-memory/node_modules/pgpass/lib/index.js"(exports, module) {
|
|
3621
3621
|
"use strict";
|
|
3622
3622
|
var path13 = __require("path");
|
|
3623
|
-
var
|
|
3623
|
+
var fs14 = __require("fs");
|
|
3624
3624
|
var helper = require_helper();
|
|
3625
3625
|
module.exports = function(connInfo, cb) {
|
|
3626
3626
|
var file = helper.getFileName();
|
|
3627
|
-
|
|
3627
|
+
fs14.stat(file, function(err3, stat) {
|
|
3628
3628
|
if (err3 || !helper.usePgPass(stat, file)) {
|
|
3629
3629
|
return cb(void 0);
|
|
3630
3630
|
}
|
|
3631
|
-
var st =
|
|
3631
|
+
var st = fs14.createReadStream(file);
|
|
3632
3632
|
helper.getPassword(connInfo, st, cb);
|
|
3633
3633
|
});
|
|
3634
3634
|
};
|
|
@@ -18203,8 +18203,8 @@ var require_SFTP = __commonJS({
|
|
|
18203
18203
|
"../mcp-agents-memory/node_modules/ssh2/lib/protocol/SFTP.js"(exports, module) {
|
|
18204
18204
|
"use strict";
|
|
18205
18205
|
var EventEmitter = __require("events");
|
|
18206
|
-
var
|
|
18207
|
-
var { constants } =
|
|
18206
|
+
var fs14 = __require("fs");
|
|
18207
|
+
var { constants } = fs14;
|
|
18208
18208
|
var {
|
|
18209
18209
|
Readable: ReadableStream2,
|
|
18210
18210
|
Writable: WritableStream
|
|
@@ -18633,12 +18633,12 @@ var require_SFTP = __commonJS({
|
|
|
18633
18633
|
fastGet(remotePath, localPath, opts, cb) {
|
|
18634
18634
|
if (this.server)
|
|
18635
18635
|
throw new Error("Client-only method called in server mode");
|
|
18636
|
-
fastXfer(this,
|
|
18636
|
+
fastXfer(this, fs14, remotePath, localPath, opts, cb);
|
|
18637
18637
|
}
|
|
18638
18638
|
fastPut(localPath, remotePath, opts, cb) {
|
|
18639
18639
|
if (this.server)
|
|
18640
18640
|
throw new Error("Client-only method called in server mode");
|
|
18641
|
-
fastXfer(
|
|
18641
|
+
fastXfer(fs14, this, localPath, remotePath, opts, cb);
|
|
18642
18642
|
}
|
|
18643
18643
|
readFile(path13, options, callback_) {
|
|
18644
18644
|
if (this.server)
|
|
@@ -19899,13 +19899,13 @@ var require_SFTP = __commonJS({
|
|
|
19899
19899
|
if (--left === 0)
|
|
19900
19900
|
cb(err3);
|
|
19901
19901
|
};
|
|
19902
|
-
if (srcHandle && (src ===
|
|
19902
|
+
if (srcHandle && (src === fs14 || src.outgoing.state === "open"))
|
|
19903
19903
|
++left;
|
|
19904
|
-
if (dstHandle && (dst ===
|
|
19904
|
+
if (dstHandle && (dst === fs14 || dst.outgoing.state === "open"))
|
|
19905
19905
|
++left;
|
|
19906
|
-
if (srcHandle && (src ===
|
|
19906
|
+
if (srcHandle && (src === fs14 || src.outgoing.state === "open"))
|
|
19907
19907
|
src.close(srcHandle, cbfinal);
|
|
19908
|
-
if (dstHandle && (dst ===
|
|
19908
|
+
if (dstHandle && (dst === fs14 || dst.outgoing.state === "open"))
|
|
19909
19909
|
dst.close(dstHandle, cbfinal);
|
|
19910
19910
|
} else {
|
|
19911
19911
|
cb(err3);
|
|
@@ -19921,7 +19921,7 @@ var require_SFTP = __commonJS({
|
|
|
19921
19921
|
tryStat(null, { size: fileSize });
|
|
19922
19922
|
function tryStat(err4, attrs) {
|
|
19923
19923
|
if (err4) {
|
|
19924
|
-
if (src !==
|
|
19924
|
+
if (src !== fs14) {
|
|
19925
19925
|
src.stat(srcPath, (err_, attrs_) => {
|
|
19926
19926
|
if (err_)
|
|
19927
19927
|
return onerror(err4);
|
|
@@ -25485,7 +25485,7 @@ var require_package2 = __commonJS({
|
|
|
25485
25485
|
// ../mcp-agents-memory/node_modules/dotenv/lib/main.js
|
|
25486
25486
|
var require_main = __commonJS({
|
|
25487
25487
|
"../mcp-agents-memory/node_modules/dotenv/lib/main.js"(exports, module) {
|
|
25488
|
-
var
|
|
25488
|
+
var fs14 = __require("fs");
|
|
25489
25489
|
var path13 = __require("path");
|
|
25490
25490
|
var os14 = __require("os");
|
|
25491
25491
|
var crypto3 = __require("crypto");
|
|
@@ -25594,7 +25594,7 @@ var require_main = __commonJS({
|
|
|
25594
25594
|
if (options && options.path && options.path.length > 0) {
|
|
25595
25595
|
if (Array.isArray(options.path)) {
|
|
25596
25596
|
for (const filepath of options.path) {
|
|
25597
|
-
if (
|
|
25597
|
+
if (fs14.existsSync(filepath)) {
|
|
25598
25598
|
possibleVaultPath = filepath.endsWith(".vault") ? filepath : `${filepath}.vault`;
|
|
25599
25599
|
}
|
|
25600
25600
|
}
|
|
@@ -25604,7 +25604,7 @@ var require_main = __commonJS({
|
|
|
25604
25604
|
} else {
|
|
25605
25605
|
possibleVaultPath = path13.resolve(process.cwd(), ".env.vault");
|
|
25606
25606
|
}
|
|
25607
|
-
if (
|
|
25607
|
+
if (fs14.existsSync(possibleVaultPath)) {
|
|
25608
25608
|
return possibleVaultPath;
|
|
25609
25609
|
}
|
|
25610
25610
|
return null;
|
|
@@ -25653,7 +25653,7 @@ var require_main = __commonJS({
|
|
|
25653
25653
|
const parsedAll = {};
|
|
25654
25654
|
for (const path14 of optionPaths) {
|
|
25655
25655
|
try {
|
|
25656
|
-
const parsed = DotenvModule.parse(
|
|
25656
|
+
const parsed = DotenvModule.parse(fs14.readFileSync(path14, { encoding }));
|
|
25657
25657
|
DotenvModule.populate(parsedAll, parsed, options);
|
|
25658
25658
|
} catch (e) {
|
|
25659
25659
|
if (debug) {
|
|
@@ -32726,12 +32726,12 @@ var require_dist2 = __commonJS({
|
|
|
32726
32726
|
throw new Error(`Unknown format "${name}"`);
|
|
32727
32727
|
return f;
|
|
32728
32728
|
};
|
|
32729
|
-
function addFormats(ajv, list,
|
|
32729
|
+
function addFormats(ajv, list, fs14, exportName) {
|
|
32730
32730
|
var _a3;
|
|
32731
32731
|
var _b;
|
|
32732
32732
|
(_a3 = (_b = ajv.opts.code).formats) !== null && _a3 !== void 0 ? _a3 : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
|
|
32733
32733
|
for (const f of list)
|
|
32734
|
-
ajv.addFormat(f,
|
|
32734
|
+
ajv.addFormat(f, fs14[f]);
|
|
32735
32735
|
}
|
|
32736
32736
|
module.exports = exports = formatsPlugin;
|
|
32737
32737
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -32770,12 +32770,12 @@ __export(runner_exports, {
|
|
|
32770
32770
|
runAllMigrations: () => runAllMigrations
|
|
32771
32771
|
});
|
|
32772
32772
|
import { spawn } from "child_process";
|
|
32773
|
-
import
|
|
32773
|
+
import fs12 from "fs";
|
|
32774
32774
|
import path12 from "path";
|
|
32775
32775
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
32776
32776
|
function listMigrationFiles() {
|
|
32777
|
-
if (!
|
|
32778
|
-
return
|
|
32777
|
+
if (!fs12.existsSync(migrationsDir)) return [];
|
|
32778
|
+
return fs12.readdirSync(migrationsDir).filter((f) => MIGRATION_FILE_RE.test(f)).sort();
|
|
32779
32779
|
}
|
|
32780
32780
|
function runOne(file) {
|
|
32781
32781
|
return new Promise((resolve, reject) => {
|
|
@@ -32808,7 +32808,7 @@ var init_runner = __esm({
|
|
|
32808
32808
|
"src/migrations/runner.ts"() {
|
|
32809
32809
|
"use strict";
|
|
32810
32810
|
__dirname4 = path12.dirname(fileURLToPath4(import.meta.url));
|
|
32811
|
-
migrationsDir =
|
|
32811
|
+
migrationsDir = fs12.existsSync(path12.join(__dirname4, "migrations")) ? path12.join(__dirname4, "migrations") : __dirname4;
|
|
32812
32812
|
MIGRATION_FILE_RE = /^\d{3}_.+\.js$/;
|
|
32813
32813
|
}
|
|
32814
32814
|
});
|
|
@@ -47049,22 +47049,28 @@ function skipWhitespace(s, i) {
|
|
|
47049
47049
|
while (i < s.length && /\s/.test(s[i])) i++;
|
|
47050
47050
|
return i;
|
|
47051
47051
|
}
|
|
47052
|
+
function locateBuzzContext(text) {
|
|
47053
|
+
if (!text.startsWith("<base>")) return CONTEXT_OPEN.test(text.slice(0, 12)) ? { rest: text, pos: 0 } : null;
|
|
47054
|
+
const baseEnd = text.indexOf("</base>");
|
|
47055
|
+
if (baseEnd < 0) return null;
|
|
47056
|
+
const rest = text.slice(baseEnd + "</base>".length);
|
|
47057
|
+
let pos = skipWhitespace(rest, 0);
|
|
47058
|
+
for (; ; ) {
|
|
47059
|
+
const name = PREAMBLE_BLOCKS.find((b) => rest.startsWith(`<${b}>`, pos));
|
|
47060
|
+
if (!name) break;
|
|
47061
|
+
const close = rest.indexOf(`</${name}>`, pos);
|
|
47062
|
+
if (close < 0) return null;
|
|
47063
|
+
pos = skipWhitespace(rest, close + name.length + 3);
|
|
47064
|
+
}
|
|
47065
|
+
return CONTEXT_OPEN.test(rest.slice(pos, pos + 12)) ? { rest, pos } : null;
|
|
47066
|
+
}
|
|
47052
47067
|
function cleanBuzzEnvelope(message) {
|
|
47053
47068
|
try {
|
|
47054
47069
|
const text = message.trimStart();
|
|
47055
47070
|
if (!text.startsWith("<base>")) return null;
|
|
47056
|
-
const
|
|
47057
|
-
if (
|
|
47058
|
-
const rest
|
|
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;
|
|
47071
|
+
const loc = locateBuzzContext(text);
|
|
47072
|
+
if (!loc) return null;
|
|
47073
|
+
const { rest, pos } = loc;
|
|
47068
47074
|
const bodyStart = rest.indexOf("\n", pos) + 1;
|
|
47069
47075
|
const contextClose = rest.indexOf(CONTEXT_CLOSE, bodyStart - 1);
|
|
47070
47076
|
if (contextClose < 0) return null;
|
|
@@ -47113,9 +47119,90 @@ function buzzEmbeddingText(message) {
|
|
|
47113
47119
|
return message;
|
|
47114
47120
|
}
|
|
47115
47121
|
}
|
|
47122
|
+
function venueFromBuzzContext(message) {
|
|
47123
|
+
if (!CONTEXT_OPEN.test(message.slice(0, 12))) return null;
|
|
47124
|
+
const end = message.indexOf(CONTEXT_CLOSE);
|
|
47125
|
+
if (end < 0) return null;
|
|
47126
|
+
const lines = message.slice(0, end).split("\n").map((l) => l.replace(/\r$/, ""));
|
|
47127
|
+
const scope = lines.find((l) => l.startsWith("Scope: "))?.slice("Scope: ".length).trim();
|
|
47128
|
+
if (scope !== "thread" && scope !== "channel" && scope !== "dm") return null;
|
|
47129
|
+
if (scope === "dm") return "buzz:dm";
|
|
47130
|
+
const channel = lines.find((l) => l.startsWith("Channel: "))?.trimEnd();
|
|
47131
|
+
const m = channel ? /^Channel: (.+?) \(#[0-9a-f-]{36}\)$/.exec(channel) : null;
|
|
47132
|
+
return m ? `buzz:${m[1]}` : "buzz";
|
|
47133
|
+
}
|
|
47134
|
+
function looksLikeBuzzTurn(message) {
|
|
47135
|
+
const text = message.trimStart();
|
|
47136
|
+
if (text.startsWith("<base>")) return true;
|
|
47137
|
+
if (!CONTEXT_OPEN.test(text.slice(0, 12))) return false;
|
|
47138
|
+
const close = text.indexOf(CONTEXT_CLOSE);
|
|
47139
|
+
return close >= 0 && TURN_OPEN.test(text.slice(close + CONTEXT_CLOSE.length));
|
|
47140
|
+
}
|
|
47141
|
+
function venueFromBuzzMessage(message) {
|
|
47142
|
+
try {
|
|
47143
|
+
const loc = locateBuzzContext(message.trimStart());
|
|
47144
|
+
return loc ? venueFromBuzzContext(loc.rest.slice(loc.pos)) : null;
|
|
47145
|
+
} catch {
|
|
47146
|
+
return null;
|
|
47147
|
+
}
|
|
47148
|
+
}
|
|
47149
|
+
|
|
47150
|
+
// src/auto_save/venue.ts
|
|
47151
|
+
import fs2 from "fs";
|
|
47152
|
+
var INTERACTIVE_ENTRYPOINTS = /* @__PURE__ */ new Set(["cli", "claude-vscode"]);
|
|
47153
|
+
function classifySessionVenue(firstUserText, entrypoint) {
|
|
47154
|
+
if (buzzTurnVenue(firstUserText)) return "buzz";
|
|
47155
|
+
if (entrypoint && INTERACTIVE_ENTRYPOINTS.has(entrypoint)) return "terminal";
|
|
47156
|
+
if (/\bslack\b/i.test(firstUserText.slice(0, 500))) return "slack";
|
|
47157
|
+
if (entrypoint) return "auto";
|
|
47158
|
+
return null;
|
|
47159
|
+
}
|
|
47160
|
+
function buzzTurnVenue(message) {
|
|
47161
|
+
return venueFromBuzzMessage(message) ?? (looksLikeBuzzTurn(message) ? "buzz" : null);
|
|
47162
|
+
}
|
|
47163
|
+
var TAIL_CHUNK = 4 * 1024 * 1024;
|
|
47164
|
+
var TAIL_CAP = 64 * 1024 * 1024;
|
|
47165
|
+
var NEWLINE = 10;
|
|
47166
|
+
function lastBuzzVenueInFile(jsonlPath, uptoBytes, userText) {
|
|
47167
|
+
const fd = fs2.openSync(jsonlPath, "r");
|
|
47168
|
+
try {
|
|
47169
|
+
let end = uptoBytes;
|
|
47170
|
+
let carry = Buffer.alloc(0);
|
|
47171
|
+
while (end > 0 && uptoBytes - end < TAIL_CAP) {
|
|
47172
|
+
const start = Math.max(0, end - TAIL_CHUNK);
|
|
47173
|
+
const chunk = Buffer.allocUnsafe(end - start);
|
|
47174
|
+
fs2.readSync(fd, chunk, 0, chunk.length, start);
|
|
47175
|
+
const buf = carry.length ? Buffer.concat([chunk, carry]) : chunk;
|
|
47176
|
+
const firstNl = start > 0 ? buf.indexOf(NEWLINE) : -1;
|
|
47177
|
+
carry = firstNl >= 0 ? buf.subarray(0, firstNl) : start > 0 ? buf : Buffer.alloc(0);
|
|
47178
|
+
const whole = firstNl >= 0 ? buf.subarray(firstNl + 1) : start > 0 ? Buffer.alloc(0) : buf;
|
|
47179
|
+
const lines = whole.toString("utf-8").split("\n");
|
|
47180
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
47181
|
+
const text = lines[i] ? userText(lines[i]) : null;
|
|
47182
|
+
const venue = text ? buzzTurnVenue(text) : null;
|
|
47183
|
+
if (venue) return venue;
|
|
47184
|
+
}
|
|
47185
|
+
end = start;
|
|
47186
|
+
}
|
|
47187
|
+
return null;
|
|
47188
|
+
} finally {
|
|
47189
|
+
fs2.closeSync(fd);
|
|
47190
|
+
}
|
|
47191
|
+
}
|
|
47116
47192
|
|
|
47117
47193
|
// src/hot_path.ts
|
|
47118
|
-
var
|
|
47194
|
+
var missingColumns = /* @__PURE__ */ new Set();
|
|
47195
|
+
var MISSING_COLUMN_EFFECT = {
|
|
47196
|
+
raw_message: "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.",
|
|
47197
|
+
venue: "\uB300\uD654 \uC790\uB9AC(venue) \uAE30\uB85D\uC774 \uC2DC\uC791\uB429\uB2C8\uB2E4. \uADF8 \uC804\uAE4C\uC9C0\uB294 venue \uC5C6\uC774 \uC800\uC7A5\uD569\uB2C8\uB2E4."
|
|
47198
|
+
};
|
|
47199
|
+
function missingOptionalColumn(err3, sql, cols) {
|
|
47200
|
+
const e = err3;
|
|
47201
|
+
if (e.code !== "42703") return void 0;
|
|
47202
|
+
const at = Number(e.position);
|
|
47203
|
+
const named = at > 0 ? /^[a-z_]+/.exec(sql.slice(at - 1))?.[0] : void 0;
|
|
47204
|
+
return cols.find(([c]) => named ? c === named : !!e.message?.includes(c))?.[0];
|
|
47205
|
+
}
|
|
47119
47206
|
async function insertRawMemory(params) {
|
|
47120
47207
|
const {
|
|
47121
47208
|
user_id,
|
|
@@ -47136,26 +47223,31 @@ async function insertRawMemory(params) {
|
|
|
47136
47223
|
const embeddingSql = embedding && embedding.length > 0 ? `[${embedding.join(",")}]` : null;
|
|
47137
47224
|
const tagProcessed = p_tag_id !== null;
|
|
47138
47225
|
const cleaned = role === "user" && !is_pinned && p_tag_id === null && embeddingSql === null ? cleanBuzzEnvelope(message) : null;
|
|
47139
|
-
const
|
|
47140
|
-
|
|
47226
|
+
const venue = params.venue ?? (role === "user" ? buzzTurnVenue(cleaned ?? message) : null);
|
|
47227
|
+
const optional2 = [];
|
|
47228
|
+
if (cleaned !== null) optional2.push(["raw_message", message]);
|
|
47229
|
+
if (venue) optional2.push(["venue", venue]);
|
|
47230
|
+
const buildInsert = (cols2) => {
|
|
47231
|
+
const text = cols2.some(([c]) => c === "raw_message") ? cleaned : message;
|
|
47232
|
+
const sql = `INSERT INTO memory (
|
|
47141
47233
|
user_id, agent_platform, agent_model,
|
|
47142
47234
|
subagent, subagent_model, subagent_role,
|
|
47143
47235
|
role, message,
|
|
47144
47236
|
p_tag_id, d_tag, embedding,
|
|
47145
47237
|
is_pinned, tag_processed, external_uuid,
|
|
47146
|
-
device_name${
|
|
47238
|
+
device_name${cols2.map(([c]) => `, ${c}`).join("")}
|
|
47147
47239
|
) VALUES (
|
|
47148
47240
|
$1, $2, $3,
|
|
47149
47241
|
$4, $5, $6,
|
|
47150
47242
|
$7, $8,
|
|
47151
47243
|
$9, $10::text[], $11::halfvec,
|
|
47152
47244
|
$12, $13, $14,
|
|
47153
|
-
$15${
|
|
47245
|
+
$15${cols2.map((_, i) => `, $${16 + i}`).join("")}
|
|
47154
47246
|
)
|
|
47155
47247
|
ON CONFLICT (external_uuid) WHERE external_uuid IS NOT NULL
|
|
47156
47248
|
DO NOTHING
|
|
47157
|
-
RETURNING id, created_at
|
|
47158
|
-
[
|
|
47249
|
+
RETURNING id, created_at`;
|
|
47250
|
+
const values = [
|
|
47159
47251
|
user_id,
|
|
47160
47252
|
agent_platform,
|
|
47161
47253
|
agent_model,
|
|
@@ -47171,24 +47263,26 @@ async function insertRawMemory(params) {
|
|
|
47171
47263
|
tagProcessed,
|
|
47172
47264
|
external_uuid,
|
|
47173
47265
|
device_name,
|
|
47174
|
-
...
|
|
47175
|
-
]
|
|
47176
|
-
|
|
47266
|
+
...cols2.map(([, v]) => v)
|
|
47267
|
+
];
|
|
47268
|
+
return { sql, values };
|
|
47269
|
+
};
|
|
47270
|
+
let cols = optional2.filter(([c]) => !missingColumns.has(c));
|
|
47177
47271
|
let result;
|
|
47178
|
-
|
|
47272
|
+
for (; ; ) {
|
|
47273
|
+
const { sql, values } = buildInsert(cols);
|
|
47179
47274
|
try {
|
|
47180
|
-
result = await
|
|
47275
|
+
result = await db.query(sql, values);
|
|
47276
|
+
break;
|
|
47181
47277
|
} catch (err3) {
|
|
47182
|
-
const
|
|
47183
|
-
if (
|
|
47184
|
-
|
|
47278
|
+
const missing = missingOptionalColumn(err3, sql, cols);
|
|
47279
|
+
if (!missing) throw err3;
|
|
47280
|
+
missingColumns.add(missing);
|
|
47185
47281
|
console.error(
|
|
47186
|
-
|
|
47282
|
+
`\u26A0\uFE0F [HotPath] memory.${missing} \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 ${MISSING_COLUMN_EFFECT[missing]}`
|
|
47187
47283
|
);
|
|
47188
|
-
|
|
47284
|
+
cols = cols.filter(([c]) => c !== missing);
|
|
47189
47285
|
}
|
|
47190
|
-
} else {
|
|
47191
|
-
result = await insert(message, null);
|
|
47192
47286
|
}
|
|
47193
47287
|
if (result.rows.length === 0) {
|
|
47194
47288
|
const existing = await db.query(
|
|
@@ -55635,7 +55729,7 @@ async function generateEmbedding(text) {
|
|
|
55635
55729
|
init_db();
|
|
55636
55730
|
|
|
55637
55731
|
// src/cold_path/jev_judge.ts
|
|
55638
|
-
import
|
|
55732
|
+
import fs3 from "fs";
|
|
55639
55733
|
var API_URL = "https://api.typesafe.ai/v1/systemone";
|
|
55640
55734
|
var MODEL = "jev-latest";
|
|
55641
55735
|
var TYPESAFE_KEY_PATH = "/home/admin_3alab/.config/typesafe/api_key";
|
|
@@ -55661,7 +55755,7 @@ function loadJevApiKey() {
|
|
|
55661
55755
|
const fromEnv = process.env.TYPESAFE_API_KEY?.trim();
|
|
55662
55756
|
if (fromEnv) return fromEnv;
|
|
55663
55757
|
try {
|
|
55664
|
-
return
|
|
55758
|
+
return fs3.readFileSync(TYPESAFE_KEY_PATH, "utf8").trim() || null;
|
|
55665
55759
|
} catch {
|
|
55666
55760
|
return null;
|
|
55667
55761
|
}
|
|
@@ -55995,7 +56089,7 @@ async function tagMessage(input) {
|
|
|
55995
56089
|
}
|
|
55996
56090
|
|
|
55997
56091
|
// src/auto_save/opencode_capture.ts
|
|
55998
|
-
import * as
|
|
56092
|
+
import * as fs4 from "node:fs";
|
|
55999
56093
|
import * as path4 from "node:path";
|
|
56000
56094
|
import * as os2 from "node:os";
|
|
56001
56095
|
var DEVICE_NAME = os2.hostname();
|
|
@@ -56191,7 +56285,7 @@ async function captureSessionStart(_cwd) {
|
|
|
56191
56285
|
_state = null;
|
|
56192
56286
|
_consecutiveFailures = 0;
|
|
56193
56287
|
const dbPath = resolveDbPath();
|
|
56194
|
-
if (!dbPath || !
|
|
56288
|
+
if (!dbPath || !fs4.existsSync(dbPath)) return;
|
|
56195
56289
|
const DatabaseSync = await loadSqlite();
|
|
56196
56290
|
if (!DatabaseSync) {
|
|
56197
56291
|
console.error(
|
|
@@ -56590,6 +56684,30 @@ function vectorToHalfvecSql(embedding) {
|
|
|
56590
56684
|
|
|
56591
56685
|
// src/tools/search_memory.ts
|
|
56592
56686
|
import os4 from "node:os";
|
|
56687
|
+
|
|
56688
|
+
// src/memory_columns.ts
|
|
56689
|
+
init_db();
|
|
56690
|
+
var cache2 = /* @__PURE__ */ new Map();
|
|
56691
|
+
async function hasMemoryColumn(column) {
|
|
56692
|
+
const c = cache2.get(column);
|
|
56693
|
+
if (c && (c.exists || Date.now() - c.checkedAt < 5 * 60 * 1e3)) return c.exists;
|
|
56694
|
+
let exists = false;
|
|
56695
|
+
try {
|
|
56696
|
+
const r = await db.query(
|
|
56697
|
+
// 쿼리가 search_path로 찾는 바로 그 memory 테이블 기준
|
|
56698
|
+
`SELECT 1 FROM pg_attribute
|
|
56699
|
+
WHERE attrelid = to_regclass('memory') AND attname = $1 AND NOT attisdropped LIMIT 1`,
|
|
56700
|
+
[column]
|
|
56701
|
+
);
|
|
56702
|
+
exists = r.rows.length > 0;
|
|
56703
|
+
} catch {
|
|
56704
|
+
exists = false;
|
|
56705
|
+
}
|
|
56706
|
+
cache2.set(column, { exists, checkedAt: Date.now() });
|
|
56707
|
+
return exists;
|
|
56708
|
+
}
|
|
56709
|
+
|
|
56710
|
+
// src/tools/search_memory.ts
|
|
56593
56711
|
var DEFAULT_LIMIT = 10;
|
|
56594
56712
|
var DEFAULT_FALLBACK_THRESHOLD = 0.3;
|
|
56595
56713
|
function parseDateRange(s) {
|
|
@@ -56664,7 +56782,10 @@ date_range \uC778\uC2DD \uD615\uC2DD:
|
|
|
56664
56782
|
"\uAE30\uAE30 \uD55C\uC815. 'global'(\uAE30\uBCF8): \uC804 \uAE30\uAE30 \uAC80\uC0C9(\uB113\uAC8C). 'local': \uD604\uC7AC \uAE30\uAE30(hostname)\uB85C \uD55C\uC815(\uC774\uC5B4\uBC1B\uAE30\uC6A9, \uC881\uAC8C). zero-config \u2014 \uC11C\uBC84\uAC00 hostname \uC790\uB3D9 \uD574\uC11D."
|
|
56665
56783
|
),
|
|
56666
56784
|
limit: external_exports.number().int().min(1).max(50).optional().describe(`\uCD5C\uB300 \uACB0\uACFC \uC218 (default ${DEFAULT_LIMIT})`),
|
|
56667
|
-
include_archived: external_exports.boolean().optional().describe("archived \uBA54\uBAA8\uB9AC\uB3C4 \uD3EC\uD568 (default false)")
|
|
56785
|
+
include_archived: external_exports.boolean().optional().describe("archived \uBA54\uBAA8\uB9AC\uB3C4 \uD3EC\uD568 (default false)"),
|
|
56786
|
+
venue: external_exports.string().optional().describe(
|
|
56787
|
+
"\uB300\uD654\uAC00 \uC624\uAC04 \uC790\uB9AC\uB85C \uD55C\uC815. 'buzz'(\uBC84\uC988 \uC804\uCCB4) / 'buzz:<\uCC44\uB110>'(\uADF8 \uCC44\uB110, \uC608: buzz:DevRoom) / 'buzz:dm' / 'terminal'(\uC0AC\uB78C\uACFC 1:1) / 'slack' / 'auto'. \uACB0\uACFC\uB9C8\uB2E4 venue\uAC00 \uBD99\uC5B4 \uB098\uC628\uB2E4."
|
|
56788
|
+
)
|
|
56668
56789
|
}
|
|
56669
56790
|
},
|
|
56670
56791
|
async (args) => {
|
|
@@ -56717,6 +56838,13 @@ date_range \uC778\uC2DD \uD615\uC2DD:
|
|
|
56717
56838
|
filters.push(`(m.device_name = $${p++} OR m.is_pinned = TRUE)`);
|
|
56718
56839
|
params.push(localDevice);
|
|
56719
56840
|
}
|
|
56841
|
+
const withVenue = await hasMemoryColumn("venue");
|
|
56842
|
+
const venueSel = withVenue ? ", m.venue" : "";
|
|
56843
|
+
const venueFilter = (n) => args.venue.includes(":") ? `lower(m.venue) = lower($${n})` : `(lower(m.venue) = lower($${n}) OR lower(m.venue) LIKE lower($${n}) || ':%')`;
|
|
56844
|
+
if (args.venue && withVenue) {
|
|
56845
|
+
filters.push(venueFilter(p++));
|
|
56846
|
+
params.push(args.venue);
|
|
56847
|
+
}
|
|
56720
56848
|
const whereSql = filters.join(" AND ");
|
|
56721
56849
|
let used = "recency";
|
|
56722
56850
|
let topSimilarity = void 0;
|
|
@@ -56731,7 +56859,7 @@ date_range \uC778\uC2DD \uD615\uC2DD:
|
|
|
56731
56859
|
params.push(limit2);
|
|
56732
56860
|
const r = await db.query(
|
|
56733
56861
|
`SELECT m.id, m.role, m.message, m.agent_platform, m.agent_model, m.device_name,
|
|
56734
|
-
pt.name AS p_tag_name, m.d_tag, m.is_pinned, m.created_at,
|
|
56862
|
+
pt.name AS p_tag_name, m.d_tag, m.is_pinned, m.created_at${venueSel},
|
|
56735
56863
|
1 - (m.embedding <=> $${vecParam}::halfvec) AS similarity
|
|
56736
56864
|
FROM memory m
|
|
56737
56865
|
LEFT JOIN project_tags pt ON pt.id = canonical_project_tag_id(m.p_tag_id)
|
|
@@ -56752,6 +56880,7 @@ date_range \uC778\uC2DD \uD615\uC2DD:
|
|
|
56752
56880
|
d_tag: row.d_tag ?? [],
|
|
56753
56881
|
is_pinned: row.is_pinned,
|
|
56754
56882
|
created_at: row.created_at,
|
|
56883
|
+
venue: row.venue ?? null,
|
|
56755
56884
|
similarity: Number(row.similarity)
|
|
56756
56885
|
}));
|
|
56757
56886
|
if (rows.length > 0) {
|
|
@@ -56787,12 +56916,16 @@ date_range \uC778\uC2DD \uD615\uC2DD:
|
|
|
56787
56916
|
ilikeFilters.push(`(m.device_name = $${q++} OR m.is_pinned = TRUE)`);
|
|
56788
56917
|
ilikeParams.push(localDevice);
|
|
56789
56918
|
}
|
|
56919
|
+
if (args.venue && withVenue) {
|
|
56920
|
+
ilikeFilters.push(venueFilter(q++));
|
|
56921
|
+
ilikeParams.push(args.venue);
|
|
56922
|
+
}
|
|
56790
56923
|
ilikeFilters.push(`m.message ILIKE $${q++}`);
|
|
56791
56924
|
ilikeParams.push(`%${args.query}%`);
|
|
56792
56925
|
ilikeParams.push(limit2);
|
|
56793
56926
|
const r = await db.query(
|
|
56794
56927
|
`SELECT m.id, m.role, m.message, m.agent_platform, m.agent_model, m.device_name,
|
|
56795
|
-
pt.name AS p_tag_name, m.d_tag, m.is_pinned, m.created_at
|
|
56928
|
+
pt.name AS p_tag_name, m.d_tag, m.is_pinned, m.created_at${venueSel}
|
|
56796
56929
|
FROM memory m
|
|
56797
56930
|
LEFT JOIN project_tags pt ON pt.id = canonical_project_tag_id(m.p_tag_id)
|
|
56798
56931
|
WHERE ${ilikeFilters.join(" AND ")}
|
|
@@ -56811,7 +56944,8 @@ date_range \uC778\uC2DD \uD615\uC2DD:
|
|
|
56811
56944
|
p_tag_name: row.p_tag_name,
|
|
56812
56945
|
d_tag: row.d_tag ?? [],
|
|
56813
56946
|
is_pinned: row.is_pinned,
|
|
56814
|
-
created_at: row.created_at
|
|
56947
|
+
created_at: row.created_at,
|
|
56948
|
+
venue: row.venue ?? null
|
|
56815
56949
|
}));
|
|
56816
56950
|
used = "ilike";
|
|
56817
56951
|
topSimilarity = void 0;
|
|
@@ -56821,7 +56955,7 @@ date_range \uC778\uC2DD \uD615\uC2DD:
|
|
|
56821
56955
|
params.push(limit2);
|
|
56822
56956
|
const r = await db.query(
|
|
56823
56957
|
`SELECT m.id, m.role, m.message, m.agent_platform, m.agent_model, m.device_name,
|
|
56824
|
-
pt.name AS p_tag_name, m.d_tag, m.is_pinned, m.created_at
|
|
56958
|
+
pt.name AS p_tag_name, m.d_tag, m.is_pinned, m.created_at${venueSel}
|
|
56825
56959
|
FROM memory m
|
|
56826
56960
|
LEFT JOIN project_tags pt ON pt.id = canonical_project_tag_id(m.p_tag_id)
|
|
56827
56961
|
WHERE ${whereSql}
|
|
@@ -56839,7 +56973,8 @@ date_range \uC778\uC2DD \uD615\uC2DD:
|
|
|
56839
56973
|
p_tag_name: row.p_tag_name,
|
|
56840
56974
|
d_tag: row.d_tag ?? [],
|
|
56841
56975
|
is_pinned: row.is_pinned,
|
|
56842
|
-
created_at: row.created_at
|
|
56976
|
+
created_at: row.created_at,
|
|
56977
|
+
venue: row.venue ?? null
|
|
56843
56978
|
}));
|
|
56844
56979
|
used = "recency";
|
|
56845
56980
|
}
|
|
@@ -56851,6 +56986,7 @@ date_range \uC778\uC2DD \uD615\uC2DD:
|
|
|
56851
56986
|
threshold: used === "ilike" ? threshold : void 0,
|
|
56852
56987
|
top_similarity: topSimilarity,
|
|
56853
56988
|
count: rows.length,
|
|
56989
|
+
...args.venue && !withVenue ? { note: "\uC774 DB\uC5D4 \uC544\uC9C1 venue \uCE78\uC774 \uC5C6\uC5B4(migration 029 \uC804) venue \uD544\uD130\uB97C \uC801\uC6A9\uD558\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4." } : {},
|
|
56854
56990
|
results: rows
|
|
56855
56991
|
}, null, 2)
|
|
56856
56992
|
}]
|
|
@@ -58192,6 +58328,7 @@ var PINNED_LIMIT = 10;
|
|
|
58192
58328
|
var INJECT_PINNED_LIMIT = 5;
|
|
58193
58329
|
var BRIEF_MAX_CHARS = Number(process.env.BRIEF_MAX_CHARS ?? 8e3);
|
|
58194
58330
|
async function collectBrief(opts = {}) {
|
|
58331
|
+
const venueSel = await hasMemoryColumn("venue") ? ", venue" : "";
|
|
58195
58332
|
const userId = opts.userId ?? await getDefaultUserId();
|
|
58196
58333
|
const shortTermDays = opts.shortTermDays ?? Number(process.env.SHORT_TERM_DAYS ?? 3);
|
|
58197
58334
|
const currentPlatform = opts.currentPlatform ?? null;
|
|
@@ -58202,7 +58339,7 @@ async function collectBrief(opts = {}) {
|
|
|
58202
58339
|
);
|
|
58203
58340
|
const user = u.rows[0] ?? { user_name: "unknown", core_profile: null, sub_profile: null };
|
|
58204
58341
|
const pinnedMsgs = await db.query(
|
|
58205
|
-
`SELECT role, agent_platform, device_name, message, created_at
|
|
58342
|
+
`SELECT role, agent_platform, device_name, message, created_at${venueSel}
|
|
58206
58343
|
FROM memory
|
|
58207
58344
|
WHERE user_id = $1
|
|
58208
58345
|
AND is_active = TRUE
|
|
@@ -58230,7 +58367,7 @@ async function collectBrief(opts = {}) {
|
|
|
58230
58367
|
let recentOthers = [];
|
|
58231
58368
|
if (currentPlatform) {
|
|
58232
58369
|
const currentMsgs = await db.query(
|
|
58233
|
-
`SELECT role, agent_platform, device_name, message, created_at
|
|
58370
|
+
`SELECT role, agent_platform, device_name, message, created_at${venueSel}
|
|
58234
58371
|
FROM memory
|
|
58235
58372
|
WHERE user_id = $1
|
|
58236
58373
|
AND is_active = TRUE
|
|
@@ -58245,7 +58382,7 @@ async function collectBrief(opts = {}) {
|
|
|
58245
58382
|
);
|
|
58246
58383
|
recentCurrent = currentMsgs.rows.reverse().map(rowToMsg);
|
|
58247
58384
|
const othersMsgs = await db.query(
|
|
58248
|
-
`SELECT role, agent_platform, device_name, message, created_at
|
|
58385
|
+
`SELECT role, agent_platform, device_name, message, created_at${venueSel}
|
|
58249
58386
|
FROM memory
|
|
58250
58387
|
WHERE user_id = $1
|
|
58251
58388
|
AND is_active = TRUE
|
|
@@ -58260,7 +58397,7 @@ async function collectBrief(opts = {}) {
|
|
|
58260
58397
|
recentOthers = othersMsgs.rows.reverse().map(rowToMsg);
|
|
58261
58398
|
} else {
|
|
58262
58399
|
const msgs = await db.query(
|
|
58263
|
-
`SELECT role, agent_platform, device_name, message, created_at
|
|
58400
|
+
`SELECT role, agent_platform, device_name, message, created_at${venueSel}
|
|
58264
58401
|
FROM memory
|
|
58265
58402
|
WHERE user_id = $1
|
|
58266
58403
|
AND is_active = TRUE
|
|
@@ -58307,11 +58444,15 @@ async function collectBrief(opts = {}) {
|
|
|
58307
58444
|
};
|
|
58308
58445
|
}
|
|
58309
58446
|
function rowToMsg(r) {
|
|
58447
|
+
const raw = String(r.message ?? "");
|
|
58448
|
+
const buzz = buzzEmbeddingText(raw);
|
|
58449
|
+
const text = buzz === raw ? raw : buzz.split("\n").filter((l) => !/^<\/?[a-z-]+(\s[^>]*)?>\s*$/.test(l)).join(" ").replace(/\s+/g, " ").trim();
|
|
58310
58450
|
return {
|
|
58311
58451
|
role: r.role,
|
|
58312
58452
|
agent_platform: r.agent_platform,
|
|
58313
58453
|
device_name: r.device_name ?? null,
|
|
58314
|
-
|
|
58454
|
+
venue: r.venue ?? null,
|
|
58455
|
+
preview: text.slice(0, MAX_PREVIEW_STORE),
|
|
58315
58456
|
created_at: r.created_at
|
|
58316
58457
|
};
|
|
58317
58458
|
}
|
|
@@ -58441,7 +58582,8 @@ function fitSection(heading, lines, budget) {
|
|
|
58441
58582
|
function formatMsgLine(m, showPlatform, maxPreview = PREVIEW_COMPACT) {
|
|
58442
58583
|
const dt = m.created_at?.toISOString?.().slice(11, 16) ?? "";
|
|
58443
58584
|
const device = m.device_name ? `@${m.device_name} ` : "";
|
|
58444
|
-
const
|
|
58585
|
+
const venue = m.venue ? `${m.venue} ` : "";
|
|
58586
|
+
const platformTag = (showPlatform ? `${m.agent_platform} ${device}` : device) + venue;
|
|
58445
58587
|
const truncated = m.preview.length > maxPreview;
|
|
58446
58588
|
const text = truncated ? m.preview.slice(0, maxPreview) : m.preview;
|
|
58447
58589
|
return `- [${dt} ${platformTag}${m.role}] ${text}${truncated ? "\u2026" : ""}`;
|
|
@@ -58494,7 +58636,7 @@ agent_platform_filter=false.`,
|
|
|
58494
58636
|
import * as os10 from "node:os";
|
|
58495
58637
|
|
|
58496
58638
|
// src/auto_save/gemini_capture.ts
|
|
58497
|
-
import * as
|
|
58639
|
+
import * as fs5 from "node:fs";
|
|
58498
58640
|
import * as path5 from "node:path";
|
|
58499
58641
|
import * as os6 from "node:os";
|
|
58500
58642
|
import * as crypto2 from "node:crypto";
|
|
@@ -58520,12 +58662,12 @@ function deriveChatsDirCandidates(cwd) {
|
|
|
58520
58662
|
path5.join(GEMINI_TMP_ROOT, cwdHash, "chats"),
|
|
58521
58663
|
path5.join(GEMINI_TMP_ROOT, path5.basename(cwd), "chats")
|
|
58522
58664
|
];
|
|
58523
|
-
return candidates.filter((d) =>
|
|
58665
|
+
return candidates.filter((d) => fs5.existsSync(d));
|
|
58524
58666
|
}
|
|
58525
58667
|
async function readSessionFile(filePath) {
|
|
58526
58668
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
58527
58669
|
try {
|
|
58528
|
-
const raw =
|
|
58670
|
+
const raw = fs5.readFileSync(filePath, "utf-8");
|
|
58529
58671
|
if (!raw.trim()) return null;
|
|
58530
58672
|
return JSON.parse(raw);
|
|
58531
58673
|
} catch {
|
|
@@ -58615,23 +58757,23 @@ async function flushJsonFile(filePath, fileState, contentSeen) {
|
|
|
58615
58757
|
return { inserted, skipped, dedup };
|
|
58616
58758
|
}
|
|
58617
58759
|
async function flushJsonlFile(filePath, fileState, contentSeen) {
|
|
58618
|
-
if (!
|
|
58760
|
+
if (!fs5.existsSync(filePath)) return { inserted: 0, skipped: 0, dedup: 0 };
|
|
58619
58761
|
let stat;
|
|
58620
58762
|
try {
|
|
58621
|
-
stat =
|
|
58763
|
+
stat = fs5.statSync(filePath);
|
|
58622
58764
|
} catch {
|
|
58623
58765
|
return { inserted: 0, skipped: 0, dedup: 0 };
|
|
58624
58766
|
}
|
|
58625
58767
|
if (stat.size <= fileState.cursor) return { inserted: 0, skipped: 0, dedup: 0 };
|
|
58626
58768
|
const length = stat.size - fileState.cursor;
|
|
58627
|
-
const fd =
|
|
58769
|
+
const fd = fs5.openSync(filePath, "r");
|
|
58628
58770
|
let raw;
|
|
58629
58771
|
try {
|
|
58630
58772
|
const buf = Buffer.alloc(length);
|
|
58631
|
-
|
|
58773
|
+
fs5.readSync(fd, buf, 0, length, fileState.cursor);
|
|
58632
58774
|
raw = buf.toString("utf-8");
|
|
58633
58775
|
} finally {
|
|
58634
|
-
|
|
58776
|
+
fs5.closeSync(fd);
|
|
58635
58777
|
}
|
|
58636
58778
|
const lastNl = raw.lastIndexOf("\n");
|
|
58637
58779
|
if (lastNl === -1) return { inserted: 0, skipped: 0, dedup: 0 };
|
|
@@ -58702,10 +58844,10 @@ async function flushAllFiles() {
|
|
|
58702
58844
|
let totalI = 0, totalS = 0, totalD = 0;
|
|
58703
58845
|
const contentSeen = /* @__PURE__ */ new Set();
|
|
58704
58846
|
for (const dir of _state2.chatsDirs) {
|
|
58705
|
-
if (!
|
|
58847
|
+
if (!fs5.existsSync(dir)) continue;
|
|
58706
58848
|
let entries;
|
|
58707
58849
|
try {
|
|
58708
|
-
entries =
|
|
58850
|
+
entries = fs5.readdirSync(dir, { withFileTypes: true });
|
|
58709
58851
|
} catch {
|
|
58710
58852
|
continue;
|
|
58711
58853
|
}
|
|
@@ -58770,7 +58912,7 @@ function captureSessionStart2(cwd) {
|
|
|
58770
58912
|
for (const dir of chatsDirs) {
|
|
58771
58913
|
let entries;
|
|
58772
58914
|
try {
|
|
58773
|
-
entries =
|
|
58915
|
+
entries = fs5.readdirSync(dir, { withFileTypes: true });
|
|
58774
58916
|
} catch {
|
|
58775
58917
|
continue;
|
|
58776
58918
|
}
|
|
@@ -58786,21 +58928,21 @@ function captureSessionStart2(cwd) {
|
|
|
58786
58928
|
if (format === "json") {
|
|
58787
58929
|
let session = null;
|
|
58788
58930
|
try {
|
|
58789
|
-
session = JSON.parse(
|
|
58931
|
+
session = JSON.parse(fs5.readFileSync(filePath, "utf-8"));
|
|
58790
58932
|
} catch {
|
|
58791
58933
|
}
|
|
58792
58934
|
cursor = session && Array.isArray(session.messages) ? session.messages.length : 0;
|
|
58793
58935
|
if (session?.sessionId) realSessionId = session.sessionId;
|
|
58794
58936
|
} else {
|
|
58795
58937
|
try {
|
|
58796
|
-
cursor =
|
|
58938
|
+
cursor = fs5.statSync(filePath).size;
|
|
58797
58939
|
} catch {
|
|
58798
58940
|
}
|
|
58799
58941
|
try {
|
|
58800
|
-
const fd =
|
|
58942
|
+
const fd = fs5.openSync(filePath, "r");
|
|
58801
58943
|
const buf = Buffer.alloc(512);
|
|
58802
|
-
const n =
|
|
58803
|
-
|
|
58944
|
+
const n = fs5.readSync(fd, buf, 0, 512, 0);
|
|
58945
|
+
fs5.closeSync(fd);
|
|
58804
58946
|
const firstLine = buf.slice(0, n).toString("utf-8").split("\n")[0].trim();
|
|
58805
58947
|
const header = JSON.parse(firstLine);
|
|
58806
58948
|
if (typeof header.sessionId === "string" && header.sessionId) {
|
|
@@ -58823,7 +58965,7 @@ function armDirWatchers() {
|
|
|
58823
58965
|
if (_watchers.length > 0) return;
|
|
58824
58966
|
for (const dir of _state2.chatsDirs) {
|
|
58825
58967
|
try {
|
|
58826
|
-
const w =
|
|
58968
|
+
const w = fs5.watch(dir, (_evt, filename) => {
|
|
58827
58969
|
if (filename && !filename.endsWith(".json") && !filename.endsWith(".jsonl")) return;
|
|
58828
58970
|
scheduleFlush();
|
|
58829
58971
|
});
|
|
@@ -58878,7 +59020,7 @@ async function captureSessionEnd2() {
|
|
|
58878
59020
|
}
|
|
58879
59021
|
|
|
58880
59022
|
// src/auto_save/grok_capture.ts
|
|
58881
|
-
import * as
|
|
59023
|
+
import * as fs6 from "node:fs";
|
|
58882
59024
|
import * as path6 from "node:path";
|
|
58883
59025
|
import * as os7 from "node:os";
|
|
58884
59026
|
var DEVICE_NAME4 = os7.hostname();
|
|
@@ -58899,7 +59041,7 @@ function extractSessionId(filePath) {
|
|
|
58899
59041
|
}
|
|
58900
59042
|
function countCompleteLines(filePath) {
|
|
58901
59043
|
try {
|
|
58902
|
-
const content =
|
|
59044
|
+
const content = fs6.readFileSync(filePath, "utf-8");
|
|
58903
59045
|
let n = 0;
|
|
58904
59046
|
for (let i = 0; i < content.length; i++) if (content[i] === "\n") n++;
|
|
58905
59047
|
return n;
|
|
@@ -58908,13 +59050,13 @@ function countCompleteLines(filePath) {
|
|
|
58908
59050
|
}
|
|
58909
59051
|
}
|
|
58910
59052
|
function* walkChatHistories(root) {
|
|
58911
|
-
if (!
|
|
59053
|
+
if (!fs6.existsSync(root)) return;
|
|
58912
59054
|
const stack = [root];
|
|
58913
59055
|
while (stack.length) {
|
|
58914
59056
|
const dir = stack.pop();
|
|
58915
59057
|
let entries;
|
|
58916
59058
|
try {
|
|
58917
|
-
entries =
|
|
59059
|
+
entries = fs6.readdirSync(dir, { withFileTypes: true });
|
|
58918
59060
|
} catch {
|
|
58919
59061
|
continue;
|
|
58920
59062
|
}
|
|
@@ -58929,7 +59071,7 @@ function* walkChatHistories(root) {
|
|
|
58929
59071
|
}
|
|
58930
59072
|
}
|
|
58931
59073
|
function captureSessionStart3(_cwd) {
|
|
58932
|
-
const rootExists =
|
|
59074
|
+
const rootExists = fs6.existsSync(SESSIONS_ROOT);
|
|
58933
59075
|
_state3 = {
|
|
58934
59076
|
rootExists,
|
|
58935
59077
|
files: /* @__PURE__ */ new Map()
|
|
@@ -58941,7 +59083,7 @@ function captureSessionStart3(_cwd) {
|
|
|
58941
59083
|
for (const filePath of walkChatHistories(SESSIONS_ROOT)) {
|
|
58942
59084
|
let stat;
|
|
58943
59085
|
try {
|
|
58944
|
-
stat =
|
|
59086
|
+
stat = fs6.statSync(filePath);
|
|
58945
59087
|
} catch {
|
|
58946
59088
|
continue;
|
|
58947
59089
|
}
|
|
@@ -58992,14 +59134,14 @@ function parseEntry(line, lineIndex) {
|
|
|
58992
59134
|
async function flushDeltaForFile2(filePath, fileState) {
|
|
58993
59135
|
let stat;
|
|
58994
59136
|
try {
|
|
58995
|
-
stat =
|
|
59137
|
+
stat = fs6.statSync(filePath);
|
|
58996
59138
|
} catch {
|
|
58997
59139
|
return { inserted: 0, skipped: 0, dedup: 0 };
|
|
58998
59140
|
}
|
|
58999
59141
|
if (stat.size === fileState.lastSize) return { inserted: 0, skipped: 0, dedup: 0 };
|
|
59000
59142
|
let content;
|
|
59001
59143
|
try {
|
|
59002
|
-
content =
|
|
59144
|
+
content = fs6.readFileSync(filePath, "utf-8");
|
|
59003
59145
|
} catch {
|
|
59004
59146
|
return { inserted: 0, skipped: 0, dedup: 0 };
|
|
59005
59147
|
}
|
|
@@ -59046,7 +59188,7 @@ async function flushAllFiles2() {
|
|
|
59046
59188
|
if (!fileState) {
|
|
59047
59189
|
let stat = null;
|
|
59048
59190
|
try {
|
|
59049
|
-
stat =
|
|
59191
|
+
stat = fs6.statSync(filePath);
|
|
59050
59192
|
} catch {
|
|
59051
59193
|
}
|
|
59052
59194
|
const fileBirthMs = stat ? stat.birthtimeMs || stat.ctimeMs : SERVER_START_MS;
|
|
@@ -59106,7 +59248,7 @@ function armDirWatcher() {
|
|
|
59106
59248
|
if (!_state3 || !_state3.rootExists) return;
|
|
59107
59249
|
if (_watcher) return;
|
|
59108
59250
|
try {
|
|
59109
|
-
_watcher =
|
|
59251
|
+
_watcher = fs6.watch(SESSIONS_ROOT, { recursive: true }, (_evt, filename) => {
|
|
59110
59252
|
if (!filename) return;
|
|
59111
59253
|
if (path6.basename(filename) !== CHAT_FILE) return;
|
|
59112
59254
|
scheduleFlush2();
|
|
@@ -59161,7 +59303,7 @@ function isCaptureArmed3() {
|
|
|
59161
59303
|
}
|
|
59162
59304
|
|
|
59163
59305
|
// src/auto_save/antigravity_capture.ts
|
|
59164
|
-
import * as
|
|
59306
|
+
import * as fs7 from "node:fs";
|
|
59165
59307
|
import * as path7 from "node:path";
|
|
59166
59308
|
import * as os8 from "node:os";
|
|
59167
59309
|
var DEVICE_NAME5 = os8.hostname();
|
|
@@ -59186,7 +59328,7 @@ function extractSid(filePath) {
|
|
|
59186
59328
|
}
|
|
59187
59329
|
function countCompleteLines2(filePath) {
|
|
59188
59330
|
try {
|
|
59189
|
-
const content =
|
|
59331
|
+
const content = fs7.readFileSync(filePath, "utf-8");
|
|
59190
59332
|
let n = 0;
|
|
59191
59333
|
for (let i = 0; i < content.length; i++) if (content[i] === "\n") n++;
|
|
59192
59334
|
return n;
|
|
@@ -59195,13 +59337,13 @@ function countCompleteLines2(filePath) {
|
|
|
59195
59337
|
}
|
|
59196
59338
|
}
|
|
59197
59339
|
function* walkTranscripts(root) {
|
|
59198
|
-
if (!
|
|
59340
|
+
if (!fs7.existsSync(root)) return;
|
|
59199
59341
|
const stack = [root];
|
|
59200
59342
|
while (stack.length) {
|
|
59201
59343
|
const dir = stack.pop();
|
|
59202
59344
|
let entries;
|
|
59203
59345
|
try {
|
|
59204
|
-
entries =
|
|
59346
|
+
entries = fs7.readdirSync(dir, { withFileTypes: true });
|
|
59205
59347
|
} catch {
|
|
59206
59348
|
continue;
|
|
59207
59349
|
}
|
|
@@ -59223,7 +59365,7 @@ function* walkAllTranscripts() {
|
|
|
59223
59365
|
}
|
|
59224
59366
|
}
|
|
59225
59367
|
function captureSessionStart4(_cwd) {
|
|
59226
|
-
const rootExists = ROOTS.some((r) =>
|
|
59368
|
+
const rootExists = ROOTS.some((r) => fs7.existsSync(r.dir));
|
|
59227
59369
|
_state4 = {
|
|
59228
59370
|
rootExists,
|
|
59229
59371
|
files: /* @__PURE__ */ new Map()
|
|
@@ -59235,7 +59377,7 @@ function captureSessionStart4(_cwd) {
|
|
|
59235
59377
|
for (const { filePath, platform } of walkAllTranscripts()) {
|
|
59236
59378
|
let stat;
|
|
59237
59379
|
try {
|
|
59238
|
-
stat =
|
|
59380
|
+
stat = fs7.statSync(filePath);
|
|
59239
59381
|
} catch {
|
|
59240
59382
|
continue;
|
|
59241
59383
|
}
|
|
@@ -59248,7 +59390,7 @@ function captureSessionStart4(_cwd) {
|
|
|
59248
59390
|
});
|
|
59249
59391
|
count++;
|
|
59250
59392
|
}
|
|
59251
|
-
const liveRoots = ROOTS.filter((r) =>
|
|
59393
|
+
const liveRoots = ROOTS.filter((r) => fs7.existsSync(r.dir)).map((r) => r.platform);
|
|
59252
59394
|
console.error(`\u{1F4DD} [Antigravity] capture armed: ${count} transcript(s) across [${liveRoots.join(", ")}]`);
|
|
59253
59395
|
armDirWatcher2();
|
|
59254
59396
|
}
|
|
@@ -59286,14 +59428,14 @@ function parseEntry2(line) {
|
|
|
59286
59428
|
async function flushDeltaForFile3(filePath, fileState) {
|
|
59287
59429
|
let stat;
|
|
59288
59430
|
try {
|
|
59289
|
-
stat =
|
|
59431
|
+
stat = fs7.statSync(filePath);
|
|
59290
59432
|
} catch {
|
|
59291
59433
|
return { inserted: 0, skipped: 0, dedup: 0 };
|
|
59292
59434
|
}
|
|
59293
59435
|
if (stat.size === fileState.lastSize) return { inserted: 0, skipped: 0, dedup: 0 };
|
|
59294
59436
|
let content;
|
|
59295
59437
|
try {
|
|
59296
|
-
content =
|
|
59438
|
+
content = fs7.readFileSync(filePath, "utf-8");
|
|
59297
59439
|
} catch {
|
|
59298
59440
|
return { inserted: 0, skipped: 0, dedup: 0 };
|
|
59299
59441
|
}
|
|
@@ -59342,7 +59484,7 @@ async function flushAllFiles3() {
|
|
|
59342
59484
|
if (!fileState) {
|
|
59343
59485
|
let stat = null;
|
|
59344
59486
|
try {
|
|
59345
|
-
stat =
|
|
59487
|
+
stat = fs7.statSync(filePath);
|
|
59346
59488
|
} catch {
|
|
59347
59489
|
}
|
|
59348
59490
|
const fileBirthMs = stat ? stat.birthtimeMs || stat.ctimeMs : SERVER_START_MS2;
|
|
@@ -59404,9 +59546,9 @@ function armDirWatcher2() {
|
|
|
59404
59546
|
if (!_state4 || !_state4.rootExists) return;
|
|
59405
59547
|
if (_watchers2.length) return;
|
|
59406
59548
|
for (const { dir } of ROOTS) {
|
|
59407
|
-
if (!
|
|
59549
|
+
if (!fs7.existsSync(dir)) continue;
|
|
59408
59550
|
try {
|
|
59409
|
-
const w =
|
|
59551
|
+
const w = fs7.watch(dir, { recursive: true }, (_evt, filename) => {
|
|
59410
59552
|
if (!filename) return;
|
|
59411
59553
|
if (path7.basename(filename) !== CHAT_FILE2) return;
|
|
59412
59554
|
scheduleFlush3();
|
|
@@ -59463,7 +59605,7 @@ function isCaptureArmed4() {
|
|
|
59463
59605
|
}
|
|
59464
59606
|
|
|
59465
59607
|
// src/auto_save/hermes_capture.ts
|
|
59466
|
-
import * as
|
|
59608
|
+
import * as fs8 from "node:fs";
|
|
59467
59609
|
import * as path8 from "node:path";
|
|
59468
59610
|
import * as os9 from "node:os";
|
|
59469
59611
|
var DEVICE_NAME6 = os9.hostname();
|
|
@@ -59519,8 +59661,44 @@ function parseNewRows(db2, afterId) {
|
|
|
59519
59661
|
}
|
|
59520
59662
|
return { rows, maxId };
|
|
59521
59663
|
}
|
|
59522
|
-
function
|
|
59523
|
-
if (
|
|
59664
|
+
function lookupSource(db2, sessionId, cache3) {
|
|
59665
|
+
if (cache3.has(sessionId)) return cache3.get(sessionId);
|
|
59666
|
+
let source = null;
|
|
59667
|
+
try {
|
|
59668
|
+
const row = db2.prepare(`SELECT source FROM sessions WHERE id = ? LIMIT 1`).get(sessionId);
|
|
59669
|
+
source = row?.source ?? null;
|
|
59670
|
+
} catch {
|
|
59671
|
+
source = null;
|
|
59672
|
+
}
|
|
59673
|
+
cache3.set(sessionId, source);
|
|
59674
|
+
return source;
|
|
59675
|
+
}
|
|
59676
|
+
var SOURCE_VENUE = { slack: "slack", cli: "terminal", subagent: "subagent", cron: "auto" };
|
|
59677
|
+
function rowVenue(db2, row, state) {
|
|
59678
|
+
const source = lookupSource(db2, row.sessionId, state.sourceCache);
|
|
59679
|
+
if (source !== "acp") return source ? SOURCE_VENUE[source] ?? null : null;
|
|
59680
|
+
const own = row.role === "user" ? buzzTurnVenue(row.message) : null;
|
|
59681
|
+
if (own) {
|
|
59682
|
+
state.buzzVenue.set(row.sessionId, own);
|
|
59683
|
+
return own;
|
|
59684
|
+
}
|
|
59685
|
+
if (!state.buzzVenue.has(row.sessionId)) {
|
|
59686
|
+
let seeded = null;
|
|
59687
|
+
try {
|
|
59688
|
+
const prev = db2.prepare(`SELECT content FROM messages WHERE session_id = ? AND id < ? AND role = 'user' ORDER BY id DESC LIMIT 20`).all(row.sessionId, row.id);
|
|
59689
|
+
for (const p of prev) {
|
|
59690
|
+
seeded = p.content ? buzzTurnVenue(p.content) : null;
|
|
59691
|
+
if (seeded) break;
|
|
59692
|
+
}
|
|
59693
|
+
} catch {
|
|
59694
|
+
seeded = null;
|
|
59695
|
+
}
|
|
59696
|
+
state.buzzVenue.set(row.sessionId, seeded);
|
|
59697
|
+
}
|
|
59698
|
+
return state.buzzVenue.get(row.sessionId) ?? null;
|
|
59699
|
+
}
|
|
59700
|
+
function lookupModel(db2, sessionId, cache3) {
|
|
59701
|
+
if (cache3.has(sessionId)) return cache3.get(sessionId);
|
|
59524
59702
|
let model = null;
|
|
59525
59703
|
try {
|
|
59526
59704
|
const row = db2.prepare(`SELECT model FROM sessions WHERE id = ? LIMIT 1`).get(sessionId);
|
|
@@ -59528,7 +59706,7 @@ function lookupModel(db2, sessionId, cache2) {
|
|
|
59528
59706
|
} catch {
|
|
59529
59707
|
model = null;
|
|
59530
59708
|
}
|
|
59531
|
-
|
|
59709
|
+
cache3.set(sessionId, model);
|
|
59532
59710
|
return model;
|
|
59533
59711
|
}
|
|
59534
59712
|
function isCaptureArmed5() {
|
|
@@ -59541,7 +59719,7 @@ async function captureSessionStart5(_cwd) {
|
|
|
59541
59719
|
}
|
|
59542
59720
|
_state5 = null;
|
|
59543
59721
|
_consecutiveOpenFailures = 0;
|
|
59544
|
-
if (!
|
|
59722
|
+
if (!fs8.existsSync(STATE_DB)) return;
|
|
59545
59723
|
const DatabaseSync = await loadSqlite2();
|
|
59546
59724
|
if (!DatabaseSync) {
|
|
59547
59725
|
console.error(
|
|
@@ -59573,7 +59751,7 @@ async function captureSessionStart5(_cwd) {
|
|
|
59573
59751
|
db2.close();
|
|
59574
59752
|
} catch {
|
|
59575
59753
|
}
|
|
59576
|
-
_state5 = { cursor: maxId, modelCache: /* @__PURE__ */ new Map() };
|
|
59754
|
+
_state5 = { cursor: maxId, modelCache: /* @__PURE__ */ new Map(), sourceCache: /* @__PURE__ */ new Map(), buzzVenue: /* @__PURE__ */ new Map(), venueByRow: /* @__PURE__ */ new Map() };
|
|
59577
59755
|
console.error(`\u{1F4DD} [Hermes] capture armed: cursor=${maxId} (live-from-now)`);
|
|
59578
59756
|
if (_pollTimer5) clearInterval(_pollTimer5);
|
|
59579
59757
|
_pollTimer5 = setInterval(() => {
|
|
@@ -59612,6 +59790,15 @@ async function flush2() {
|
|
|
59612
59790
|
const userId = await getDefaultUserId();
|
|
59613
59791
|
for (const r of rows) {
|
|
59614
59792
|
const agentModel = r.role === "user" ? null : lookupModel(db2, r.sessionId, _state5.modelCache) ?? "unknown";
|
|
59793
|
+
let venue = _state5.venueByRow.get(r.id);
|
|
59794
|
+
if (venue === void 0) {
|
|
59795
|
+
try {
|
|
59796
|
+
venue = rowVenue(db2, r, _state5);
|
|
59797
|
+
} catch {
|
|
59798
|
+
venue = null;
|
|
59799
|
+
}
|
|
59800
|
+
_state5.venueByRow.set(r.id, venue);
|
|
59801
|
+
}
|
|
59615
59802
|
try {
|
|
59616
59803
|
const res = await insertRawMemory({
|
|
59617
59804
|
user_id: userId,
|
|
@@ -59620,8 +59807,10 @@ async function flush2() {
|
|
|
59620
59807
|
role: r.role,
|
|
59621
59808
|
message: r.message,
|
|
59622
59809
|
external_uuid: `hermes:${r.id}`,
|
|
59623
|
-
device_name: DEVICE_NAME6
|
|
59810
|
+
device_name: DEVICE_NAME6,
|
|
59811
|
+
venue
|
|
59624
59812
|
});
|
|
59813
|
+
_state5.venueByRow.delete(r.id);
|
|
59625
59814
|
if (res.inserted) inserted++;
|
|
59626
59815
|
else dedup++;
|
|
59627
59816
|
} catch (err3) {
|
|
@@ -60704,7 +60893,7 @@ async function drainColdPath(maxTicks = 12) {
|
|
|
60704
60893
|
}
|
|
60705
60894
|
|
|
60706
60895
|
// src/auto_save/jsonl_capture.ts
|
|
60707
|
-
import * as
|
|
60896
|
+
import * as fs9 from "node:fs";
|
|
60708
60897
|
import * as path9 from "node:path";
|
|
60709
60898
|
import * as os12 from "node:os";
|
|
60710
60899
|
var CLIENT_PLATFORM2 = "claude-code";
|
|
@@ -60723,12 +60912,12 @@ function findProjectDir(cwd) {
|
|
|
60723
60912
|
const slug = cwdToSlug(cwd);
|
|
60724
60913
|
const slugPath = path9.join(PROJECTS_ROOT, slug);
|
|
60725
60914
|
try {
|
|
60726
|
-
if (
|
|
60915
|
+
if (fs9.statSync(slugPath).isDirectory()) return slugPath;
|
|
60727
60916
|
} catch {
|
|
60728
60917
|
}
|
|
60729
60918
|
let subdirs;
|
|
60730
60919
|
try {
|
|
60731
|
-
subdirs =
|
|
60920
|
+
subdirs = fs9.readdirSync(PROJECTS_ROOT, { withFileTypes: true });
|
|
60732
60921
|
} catch {
|
|
60733
60922
|
return null;
|
|
60734
60923
|
}
|
|
@@ -60737,7 +60926,7 @@ function findProjectDir(cwd) {
|
|
|
60737
60926
|
const dirPath = path9.join(PROJECTS_ROOT, subdir.name);
|
|
60738
60927
|
let files;
|
|
60739
60928
|
try {
|
|
60740
|
-
files =
|
|
60929
|
+
files = fs9.readdirSync(dirPath, { withFileTypes: true });
|
|
60741
60930
|
} catch {
|
|
60742
60931
|
continue;
|
|
60743
60932
|
}
|
|
@@ -60752,13 +60941,13 @@ function findProjectDir(cwd) {
|
|
|
60752
60941
|
function readCwdFromJsonl(jsonlPath) {
|
|
60753
60942
|
let fd;
|
|
60754
60943
|
try {
|
|
60755
|
-
fd =
|
|
60944
|
+
fd = fs9.openSync(jsonlPath, "r");
|
|
60756
60945
|
} catch {
|
|
60757
60946
|
return null;
|
|
60758
60947
|
}
|
|
60759
60948
|
try {
|
|
60760
60949
|
const buf = Buffer.alloc(2048);
|
|
60761
|
-
const bytesRead =
|
|
60950
|
+
const bytesRead = fs9.readSync(fd, buf, 0, 2048, 0);
|
|
60762
60951
|
const raw = buf.slice(0, bytesRead).toString("utf-8");
|
|
60763
60952
|
for (const line of raw.split("\n")) {
|
|
60764
60953
|
if (!line.trim()) continue;
|
|
@@ -60770,7 +60959,7 @@ function readCwdFromJsonl(jsonlPath) {
|
|
|
60770
60959
|
}
|
|
60771
60960
|
return null;
|
|
60772
60961
|
} finally {
|
|
60773
|
-
|
|
60962
|
+
fs9.closeSync(fd);
|
|
60774
60963
|
}
|
|
60775
60964
|
}
|
|
60776
60965
|
function captureSessionStart6(cwd) {
|
|
@@ -60800,7 +60989,7 @@ function _tryArm(cwd, attempt) {
|
|
|
60800
60989
|
_state6.projectDir = projectDir;
|
|
60801
60990
|
let entries;
|
|
60802
60991
|
try {
|
|
60803
|
-
entries =
|
|
60992
|
+
entries = fs9.readdirSync(projectDir, { withFileTypes: true });
|
|
60804
60993
|
} catch {
|
|
60805
60994
|
return;
|
|
60806
60995
|
}
|
|
@@ -60809,7 +60998,7 @@ function _tryArm(cwd, attempt) {
|
|
|
60809
60998
|
const jsonlPath = path9.join(projectDir, entry.name);
|
|
60810
60999
|
let stat;
|
|
60811
61000
|
try {
|
|
60812
|
-
stat =
|
|
61001
|
+
stat = fs9.statSync(jsonlPath);
|
|
60813
61002
|
} catch {
|
|
60814
61003
|
continue;
|
|
60815
61004
|
}
|
|
@@ -60855,27 +61044,48 @@ function parseEntry3(line) {
|
|
|
60855
61044
|
uuid: entry.uuid ?? `${entry.timestamp ?? ""}-${Math.random()}`,
|
|
60856
61045
|
role: entry.type,
|
|
60857
61046
|
message: messageText,
|
|
60858
|
-
agent_model
|
|
61047
|
+
agent_model,
|
|
61048
|
+
entrypoint: typeof entry.entrypoint === "string" ? entry.entrypoint : void 0
|
|
60859
61049
|
};
|
|
60860
61050
|
}
|
|
61051
|
+
var HEAD_SCAN_BYTES = 2 * 1024 * 1024;
|
|
61052
|
+
function sessionVenueKind(jsonlPath) {
|
|
61053
|
+
const fd = fs9.openSync(jsonlPath, "r");
|
|
61054
|
+
try {
|
|
61055
|
+
const size = fs9.fstatSync(fd).size;
|
|
61056
|
+
const buf = Buffer.allocUnsafe(Math.min(HEAD_SCAN_BYTES, size));
|
|
61057
|
+
fs9.readSync(fd, buf, 0, buf.length, 0);
|
|
61058
|
+
for (const line of buf.toString("utf-8").split("\n")) {
|
|
61059
|
+
const parsed = line.trim() ? parseEntry3(line) : null;
|
|
61060
|
+
if (parsed?.role === "user") return classifySessionVenue(parsed.message, parsed.entrypoint);
|
|
61061
|
+
}
|
|
61062
|
+
return size >= HEAD_SCAN_BYTES ? null : void 0;
|
|
61063
|
+
} finally {
|
|
61064
|
+
fs9.closeSync(fd);
|
|
61065
|
+
}
|
|
61066
|
+
}
|
|
61067
|
+
var userTextOf = (line) => {
|
|
61068
|
+
const parsed = parseEntry3(line);
|
|
61069
|
+
return parsed?.role === "user" ? parsed.message : null;
|
|
61070
|
+
};
|
|
60861
61071
|
async function flushDeltaForFile4(jsonlPath, fileState) {
|
|
60862
|
-
if (!
|
|
61072
|
+
if (!fs9.existsSync(jsonlPath)) return { inserted: 0, skipped: 0, dedup: 0 };
|
|
60863
61073
|
let stat;
|
|
60864
61074
|
try {
|
|
60865
|
-
stat =
|
|
61075
|
+
stat = fs9.statSync(jsonlPath);
|
|
60866
61076
|
} catch {
|
|
60867
61077
|
return { inserted: 0, skipped: 0, dedup: 0 };
|
|
60868
61078
|
}
|
|
60869
61079
|
if (stat.size <= fileState.cursorBytes) return { inserted: 0, skipped: 0, dedup: 0 };
|
|
60870
61080
|
const length = stat.size - fileState.cursorBytes;
|
|
60871
|
-
const fd =
|
|
61081
|
+
const fd = fs9.openSync(jsonlPath, "r");
|
|
60872
61082
|
let raw;
|
|
60873
61083
|
try {
|
|
60874
61084
|
const buf = Buffer.alloc(length);
|
|
60875
|
-
|
|
61085
|
+
fs9.readSync(fd, buf, 0, length, fileState.cursorBytes);
|
|
60876
61086
|
raw = buf.toString("utf-8");
|
|
60877
61087
|
} finally {
|
|
60878
|
-
|
|
61088
|
+
fs9.closeSync(fd);
|
|
60879
61089
|
}
|
|
60880
61090
|
const lastNl = raw.lastIndexOf("\n");
|
|
60881
61091
|
if (lastNl === -1) return { inserted: 0, skipped: 0, dedup: 0 };
|
|
@@ -60884,6 +61094,14 @@ async function flushDeltaForFile4(jsonlPath, fileState) {
|
|
|
60884
61094
|
const newCursor = fileState.cursorBytes + advanceBy;
|
|
60885
61095
|
const lines = parsable.split("\n");
|
|
60886
61096
|
const userId = await getDefaultUserId();
|
|
61097
|
+
if (fileState.venueKind === void 0) {
|
|
61098
|
+
try {
|
|
61099
|
+
fileState.venueKind = sessionVenueKind(jsonlPath);
|
|
61100
|
+
} catch {
|
|
61101
|
+
fileState.venueKind = null;
|
|
61102
|
+
}
|
|
61103
|
+
}
|
|
61104
|
+
const deltaStart = fileState.cursorBytes;
|
|
60887
61105
|
let inserted = 0, skipped = 0, dedup = 0;
|
|
60888
61106
|
for (const line of lines) {
|
|
60889
61107
|
const trimmed = line.trim();
|
|
@@ -60900,6 +61118,20 @@ async function flushDeltaForFile4(jsonlPath, fileState) {
|
|
|
60900
61118
|
}
|
|
60901
61119
|
fileState.contentSeen.add(ck);
|
|
60902
61120
|
const externalUuid = `claude-code:${fileState.sessionId}:${parsed.uuid}`;
|
|
61121
|
+
let venue = fileState.venueKind ?? null;
|
|
61122
|
+
if (fileState.venueKind === "buzz") {
|
|
61123
|
+
const own = parsed.role === "user" ? buzzTurnVenue(parsed.message) : null;
|
|
61124
|
+
if (own) {
|
|
61125
|
+
fileState.buzzVenue = own;
|
|
61126
|
+
} else if (fileState.buzzVenue === void 0) {
|
|
61127
|
+
try {
|
|
61128
|
+
fileState.buzzVenue = lastBuzzVenueInFile(jsonlPath, deltaStart, userTextOf);
|
|
61129
|
+
} catch {
|
|
61130
|
+
fileState.buzzVenue = null;
|
|
61131
|
+
}
|
|
61132
|
+
}
|
|
61133
|
+
venue = own ?? fileState.buzzVenue ?? "buzz";
|
|
61134
|
+
}
|
|
60903
61135
|
const agentModel = parsed.role === "user" ? null : parsed.agent_model ?? "unknown";
|
|
60904
61136
|
try {
|
|
60905
61137
|
const result = await insertRawMemory({
|
|
@@ -60909,7 +61141,8 @@ async function flushDeltaForFile4(jsonlPath, fileState) {
|
|
|
60909
61141
|
role: parsed.role,
|
|
60910
61142
|
message: parsed.message,
|
|
60911
61143
|
external_uuid: externalUuid,
|
|
60912
|
-
device_name: DEVICE_NAME9
|
|
61144
|
+
device_name: DEVICE_NAME9,
|
|
61145
|
+
venue
|
|
60913
61146
|
});
|
|
60914
61147
|
if (result.inserted) inserted++;
|
|
60915
61148
|
else dedup++;
|
|
@@ -60924,10 +61157,10 @@ async function flushDeltaForFile4(jsonlPath, fileState) {
|
|
|
60924
61157
|
async function flushAllFiles4() {
|
|
60925
61158
|
if (!_state6 || !_state6.projectDir) return { inserted: 0, skipped: 0, dedup: 0 };
|
|
60926
61159
|
const projectDir = _state6.projectDir;
|
|
60927
|
-
if (!
|
|
61160
|
+
if (!fs9.existsSync(projectDir)) return { inserted: 0, skipped: 0, dedup: 0 };
|
|
60928
61161
|
let entries;
|
|
60929
61162
|
try {
|
|
60930
|
-
entries =
|
|
61163
|
+
entries = fs9.readdirSync(projectDir, { withFileTypes: true });
|
|
60931
61164
|
} catch {
|
|
60932
61165
|
return { inserted: 0, skipped: 0, dedup: 0 };
|
|
60933
61166
|
}
|
|
@@ -60983,7 +61216,7 @@ function armDirWatcher3() {
|
|
|
60983
61216
|
if (!_state6 || !_state6.projectDir) return;
|
|
60984
61217
|
if (_watcher2) return;
|
|
60985
61218
|
try {
|
|
60986
|
-
_watcher2 =
|
|
61219
|
+
_watcher2 = fs9.watch(_state6.projectDir, (_eventType, filename) => {
|
|
60987
61220
|
if (filename && !filename.endsWith(".jsonl")) return;
|
|
60988
61221
|
scheduleFlush4();
|
|
60989
61222
|
});
|
|
@@ -61027,7 +61260,7 @@ async function captureSessionEnd6() {
|
|
|
61027
61260
|
}
|
|
61028
61261
|
|
|
61029
61262
|
// src/auto_save/codex_capture.ts
|
|
61030
|
-
import * as
|
|
61263
|
+
import * as fs10 from "node:fs";
|
|
61031
61264
|
import * as path10 from "node:path";
|
|
61032
61265
|
import * as os13 from "node:os";
|
|
61033
61266
|
import { spawnSync } from "node:child_process";
|
|
@@ -61075,13 +61308,13 @@ function extractSessionId2(filename) {
|
|
|
61075
61308
|
return m ? m[1] : null;
|
|
61076
61309
|
}
|
|
61077
61310
|
function* walkRollouts(root) {
|
|
61078
|
-
if (!
|
|
61311
|
+
if (!fs10.existsSync(root)) return;
|
|
61079
61312
|
const stack = [root];
|
|
61080
61313
|
while (stack.length) {
|
|
61081
61314
|
const dir = stack.pop();
|
|
61082
61315
|
let entries;
|
|
61083
61316
|
try {
|
|
61084
|
-
entries =
|
|
61317
|
+
entries = fs10.readdirSync(dir, { withFileTypes: true });
|
|
61085
61318
|
} catch {
|
|
61086
61319
|
continue;
|
|
61087
61320
|
}
|
|
@@ -61096,7 +61329,7 @@ function* walkRollouts(root) {
|
|
|
61096
61329
|
}
|
|
61097
61330
|
}
|
|
61098
61331
|
function captureSessionStart7(_cwd) {
|
|
61099
|
-
const rootExists =
|
|
61332
|
+
const rootExists = fs10.existsSync(SESSIONS_ROOT2);
|
|
61100
61333
|
_state7 = {
|
|
61101
61334
|
rootExists,
|
|
61102
61335
|
files: /* @__PURE__ */ new Map()
|
|
@@ -61108,7 +61341,7 @@ function captureSessionStart7(_cwd) {
|
|
|
61108
61341
|
for (const filePath of walkRollouts(SESSIONS_ROOT2)) {
|
|
61109
61342
|
let stat;
|
|
61110
61343
|
try {
|
|
61111
|
-
stat =
|
|
61344
|
+
stat = fs10.statSync(filePath);
|
|
61112
61345
|
} catch {
|
|
61113
61346
|
continue;
|
|
61114
61347
|
}
|
|
@@ -61162,23 +61395,23 @@ function extractModelFromTurnContext(line) {
|
|
|
61162
61395
|
}
|
|
61163
61396
|
}
|
|
61164
61397
|
async function flushDeltaForFile5(filePath, fileState) {
|
|
61165
|
-
if (!
|
|
61398
|
+
if (!fs10.existsSync(filePath)) return { inserted: 0, skipped: 0, dedup: 0 };
|
|
61166
61399
|
let stat;
|
|
61167
61400
|
try {
|
|
61168
|
-
stat =
|
|
61401
|
+
stat = fs10.statSync(filePath);
|
|
61169
61402
|
} catch {
|
|
61170
61403
|
return { inserted: 0, skipped: 0, dedup: 0 };
|
|
61171
61404
|
}
|
|
61172
61405
|
if (stat.size <= fileState.cursorBytes) return { inserted: 0, skipped: 0, dedup: 0 };
|
|
61173
61406
|
const length = stat.size - fileState.cursorBytes;
|
|
61174
|
-
const fd =
|
|
61407
|
+
const fd = fs10.openSync(filePath, "r");
|
|
61175
61408
|
let raw;
|
|
61176
61409
|
try {
|
|
61177
61410
|
const buf = Buffer.alloc(length);
|
|
61178
|
-
|
|
61411
|
+
fs10.readSync(fd, buf, 0, length, fileState.cursorBytes);
|
|
61179
61412
|
raw = buf.toString("utf-8");
|
|
61180
61413
|
} finally {
|
|
61181
|
-
|
|
61414
|
+
fs10.closeSync(fd);
|
|
61182
61415
|
}
|
|
61183
61416
|
const lastNl = raw.lastIndexOf("\n");
|
|
61184
61417
|
if (lastNl === -1) return { inserted: 0, skipped: 0, dedup: 0 };
|
|
@@ -61242,7 +61475,7 @@ async function flushAllFiles5() {
|
|
|
61242
61475
|
if (!sessionId) continue;
|
|
61243
61476
|
let stat = null;
|
|
61244
61477
|
try {
|
|
61245
|
-
stat =
|
|
61478
|
+
stat = fs10.statSync(filePath);
|
|
61246
61479
|
} catch {
|
|
61247
61480
|
}
|
|
61248
61481
|
const fileBirthMs = stat ? stat.birthtimeMs || stat.ctimeMs : SERVER_START_MS3;
|
|
@@ -61302,7 +61535,7 @@ function armDirWatcher4() {
|
|
|
61302
61535
|
if (!_state7 || !_state7.rootExists) return;
|
|
61303
61536
|
if (_watcher3) return;
|
|
61304
61537
|
try {
|
|
61305
|
-
_watcher3 =
|
|
61538
|
+
_watcher3 = fs10.watch(SESSIONS_ROOT2, { recursive: true }, (_evt, filename) => {
|
|
61306
61539
|
if (!filename) return;
|
|
61307
61540
|
const base = path10.basename(filename);
|
|
61308
61541
|
if (!base.startsWith("rollout-") || !base.endsWith(".jsonl")) return;
|
|
@@ -61355,16 +61588,16 @@ async function captureSessionEnd7() {
|
|
|
61355
61588
|
}
|
|
61356
61589
|
|
|
61357
61590
|
// src/version.ts
|
|
61358
|
-
import
|
|
61591
|
+
import fs11 from "fs";
|
|
61359
61592
|
import path11 from "path";
|
|
61360
61593
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
61361
61594
|
var __dirname3 = path11.dirname(fileURLToPath3(import.meta.url));
|
|
61362
61595
|
var packageJsonPath = path11.resolve(__dirname3, "..", "package.json");
|
|
61363
|
-
var packageJson = JSON.parse(
|
|
61596
|
+
var packageJson = JSON.parse(fs11.readFileSync(packageJsonPath, "utf8"));
|
|
61364
61597
|
var PACKAGE_VERSION2 = packageJson.version || "0.0.0";
|
|
61365
61598
|
|
|
61366
61599
|
// src/index.ts
|
|
61367
|
-
import
|
|
61600
|
+
import fs13 from "fs";
|
|
61368
61601
|
var BRIEF_DB_TIMEOUT_MS = 5e3;
|
|
61369
61602
|
var INSTRUCTIONS_MAX_CHARS = Number(process.env.INSTRUCTIONS_MAX_CHARS ?? 1900);
|
|
61370
61603
|
var INSTRUCTIONS_SEP = "\n\n---\n\n";
|
|
@@ -61561,7 +61794,7 @@ async function runMcpServer() {
|
|
|
61561
61794
|
if (process.env.SSH_ENABLED === "true" && !process.env.SSH_KEY_PATH) {
|
|
61562
61795
|
throw new Error("\u274C SSH_KEY_PATH is required when SSH is enabled");
|
|
61563
61796
|
}
|
|
61564
|
-
if (process.env.SSH_KEY_PATH && !
|
|
61797
|
+
if (process.env.SSH_KEY_PATH && !fs13.existsSync(process.env.SSH_KEY_PATH)) {
|
|
61565
61798
|
console.error(`\u26A0\uFE0F [WARNING] SSH key not found at: ${process.env.SSH_KEY_PATH}`);
|
|
61566
61799
|
}
|
|
61567
61800
|
try {
|