@askexenow/exe-os 0.9.21 → 0.9.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/backfill-conversations.js +17 -4
- package/dist/bin/backfill-responses.js +17 -4
- package/dist/bin/backfill-vectors.js +2 -2
- package/dist/bin/cleanup-stale-review-tasks.js +17 -4
- package/dist/bin/cli.js +378 -171
- package/dist/bin/exe-assign.js +17 -4
- package/dist/bin/exe-boot.js +2 -2
- package/dist/bin/exe-dispatch.js +17 -4
- package/dist/bin/exe-doctor.js +2 -2
- package/dist/bin/exe-export-behaviors.js +17 -4
- package/dist/bin/exe-forget.js +17 -4
- package/dist/bin/exe-gateway.js +17 -4
- package/dist/bin/exe-heartbeat.js +17 -4
- package/dist/bin/exe-kill.js +17 -4
- package/dist/bin/exe-launch-agent.js +17 -4
- package/dist/bin/exe-pending-messages.js +17 -4
- package/dist/bin/exe-pending-notifications.js +17 -4
- package/dist/bin/exe-pending-reviews.js +17 -4
- package/dist/bin/exe-review.js +17 -4
- package/dist/bin/exe-search.js +23 -8
- package/dist/bin/exe-session-cleanup.js +17 -4
- package/dist/bin/exe-start-codex.js +209 -32
- package/dist/bin/exe-start-opencode.js +17 -4
- package/dist/bin/exe-status.js +17 -4
- package/dist/bin/exe-team.js +17 -4
- package/dist/bin/git-sweep.js +17 -4
- package/dist/bin/graph-backfill.js +17 -4
- package/dist/bin/graph-export.js +17 -4
- package/dist/bin/install.js +42 -0
- package/dist/bin/intercom-check.js +17 -4
- package/dist/bin/scan-tasks.js +17 -4
- package/dist/bin/shard-migrate.js +17 -4
- package/dist/bin/update.js +187 -42
- package/dist/gateway/index.js +17 -4
- package/dist/hooks/bug-report-worker.js +793 -150
- package/dist/hooks/codex-stop-task-finalizer.js +3020 -2375
- package/dist/hooks/commit-complete.js +156 -6
- package/dist/hooks/error-recall.js +23 -8
- package/dist/hooks/ingest.js +17 -4
- package/dist/hooks/instructions-loaded.js +17 -4
- package/dist/hooks/notification.js +17 -4
- package/dist/hooks/post-compact.js +17 -4
- package/dist/hooks/post-tool-combined.js +23 -8
- package/dist/hooks/pre-compact.js +156 -8
- package/dist/hooks/pre-tool-use.js +21 -12
- package/dist/hooks/prompt-submit.js +23 -8
- package/dist/hooks/session-end.js +156 -8
- package/dist/hooks/session-start.js +23 -8
- package/dist/hooks/stop.js +306 -9
- package/dist/hooks/subagent-stop.js +306 -9
- package/dist/hooks/summary-worker.js +2 -2
- package/dist/index.js +17 -4
- package/dist/lib/exe-daemon.js +17 -4
- package/dist/lib/hybrid-search.js +23 -8
- package/dist/lib/schedules.js +2 -2
- package/dist/lib/store.js +17 -4
- package/dist/mcp/server.js +36 -10
- package/dist/runtime/index.js +17 -4
- package/dist/tui/App.js +17 -4
- package/package.json +1 -1
|
@@ -25,15 +25,6 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
25
25
|
};
|
|
26
26
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
27
|
|
|
28
|
-
// src/types/memory.ts
|
|
29
|
-
var EMBEDDING_DIM;
|
|
30
|
-
var init_memory = __esm({
|
|
31
|
-
"src/types/memory.ts"() {
|
|
32
|
-
"use strict";
|
|
33
|
-
EMBEDDING_DIM = 1024;
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
|
|
37
28
|
// src/lib/db-retry.ts
|
|
38
29
|
function isBusyError(err) {
|
|
39
30
|
if (err instanceof Error) {
|
|
@@ -1323,6 +1314,15 @@ var init_database_adapter = __esm({
|
|
|
1323
1314
|
}
|
|
1324
1315
|
});
|
|
1325
1316
|
|
|
1317
|
+
// src/types/memory.ts
|
|
1318
|
+
var EMBEDDING_DIM;
|
|
1319
|
+
var init_memory = __esm({
|
|
1320
|
+
"src/types/memory.ts"() {
|
|
1321
|
+
"use strict";
|
|
1322
|
+
EMBEDDING_DIM = 1024;
|
|
1323
|
+
}
|
|
1324
|
+
});
|
|
1325
|
+
|
|
1326
1326
|
// src/lib/daemon-auth.ts
|
|
1327
1327
|
import crypto from "crypto";
|
|
1328
1328
|
import path5 from "path";
|
|
@@ -1361,6 +1361,17 @@ var init_daemon_auth = __esm({
|
|
|
1361
1361
|
});
|
|
1362
1362
|
|
|
1363
1363
|
// src/lib/exe-daemon-client.ts
|
|
1364
|
+
var exe_daemon_client_exports = {};
|
|
1365
|
+
__export(exe_daemon_client_exports, {
|
|
1366
|
+
connectEmbedDaemon: () => connectEmbedDaemon,
|
|
1367
|
+
disconnectClient: () => disconnectClient,
|
|
1368
|
+
embedBatchViaClient: () => embedBatchViaClient,
|
|
1369
|
+
embedViaClient: () => embedViaClient,
|
|
1370
|
+
isClientConnected: () => isClientConnected,
|
|
1371
|
+
pingDaemon: () => pingDaemon,
|
|
1372
|
+
sendDaemonRequest: () => sendDaemonRequest,
|
|
1373
|
+
sendIngestRequest: () => sendIngestRequest
|
|
1374
|
+
});
|
|
1364
1375
|
import net from "net";
|
|
1365
1376
|
import os4 from "os";
|
|
1366
1377
|
import { spawn } from "child_process";
|
|
@@ -1749,6 +1760,15 @@ async function embedViaClient(text, priority = "high") {
|
|
|
1749
1760
|
);
|
|
1750
1761
|
return !result.error && result.vectors?.[0] ? result.vectors[0] : null;
|
|
1751
1762
|
}
|
|
1763
|
+
async function embedBatchViaClient(texts, priority = "high") {
|
|
1764
|
+
if (!_connected && !await connectEmbedDaemon()) return null;
|
|
1765
|
+
_requestCount++;
|
|
1766
|
+
const result = await retryThenRestart(
|
|
1767
|
+
() => sendRequest(texts, priority),
|
|
1768
|
+
"Batch embed"
|
|
1769
|
+
);
|
|
1770
|
+
return !result.error && result.vectors ? result.vectors : null;
|
|
1771
|
+
}
|
|
1752
1772
|
function disconnectClient() {
|
|
1753
1773
|
if (_socket) {
|
|
1754
1774
|
_socket.destroy();
|
|
@@ -1765,6 +1785,17 @@ function disconnectClient() {
|
|
|
1765
1785
|
function isClientConnected() {
|
|
1766
1786
|
return _connected;
|
|
1767
1787
|
}
|
|
1788
|
+
function sendIngestRequest(payload) {
|
|
1789
|
+
if (!_socket || !_connected) return false;
|
|
1790
|
+
try {
|
|
1791
|
+
const id = randomUUID();
|
|
1792
|
+
const token = process.env[DAEMON_TOKEN_ENV] ?? readDaemonToken();
|
|
1793
|
+
_socket.write(JSON.stringify({ id, token, type: "ingest", ...payload }) + "\n");
|
|
1794
|
+
return true;
|
|
1795
|
+
} catch {
|
|
1796
|
+
return false;
|
|
1797
|
+
}
|
|
1798
|
+
}
|
|
1768
1799
|
var SOCKET_PATH, PID_PATH, SPAWN_LOCK_PATH, SPAWN_LOCK_STALE_MS, CONNECT_TIMEOUT_MS, REQUEST_TIMEOUT_MS, DAEMON_TOKEN_ENV, _socket, _connected, _buffer, _requestCount, _consecutiveFailures, HEALTH_CHECK_INTERVAL, MAX_RETRIES_BEFORE_RESTART, RETRY_DELAYS_MS, MIN_DAEMON_AGE_MS, _pending, MAX_BUFFER;
|
|
1769
1800
|
var init_exe_daemon_client = __esm({
|
|
1770
1801
|
"src/lib/exe-daemon-client.ts"() {
|
|
@@ -1793,6 +1824,15 @@ var init_exe_daemon_client = __esm({
|
|
|
1793
1824
|
});
|
|
1794
1825
|
|
|
1795
1826
|
// src/lib/daemon-protocol.ts
|
|
1827
|
+
var daemon_protocol_exports = {};
|
|
1828
|
+
__export(daemon_protocol_exports, {
|
|
1829
|
+
deserializeArgs: () => deserializeArgs,
|
|
1830
|
+
deserializeResultSet: () => deserializeResultSet,
|
|
1831
|
+
deserializeValue: () => deserializeValue,
|
|
1832
|
+
serializeArgs: () => serializeArgs,
|
|
1833
|
+
serializeResultSet: () => serializeResultSet,
|
|
1834
|
+
serializeValue: () => serializeValue
|
|
1835
|
+
});
|
|
1796
1836
|
function serializeValue(v) {
|
|
1797
1837
|
if (v === null || v === void 0) return null;
|
|
1798
1838
|
if (typeof v === "bigint") return Number(v);
|
|
@@ -1817,6 +1857,32 @@ function deserializeValue(v) {
|
|
|
1817
1857
|
}
|
|
1818
1858
|
return v;
|
|
1819
1859
|
}
|
|
1860
|
+
function serializeArgs(args) {
|
|
1861
|
+
return args.map(serializeValue);
|
|
1862
|
+
}
|
|
1863
|
+
function deserializeArgs(args) {
|
|
1864
|
+
return args.map(deserializeValue);
|
|
1865
|
+
}
|
|
1866
|
+
function serializeResultSet(rs) {
|
|
1867
|
+
const rows = [];
|
|
1868
|
+
for (const row of rs.rows) {
|
|
1869
|
+
const obj = {};
|
|
1870
|
+
for (let i = 0; i < rs.columns.length; i++) {
|
|
1871
|
+
const col = rs.columns[i];
|
|
1872
|
+
if (col !== void 0) {
|
|
1873
|
+
obj[col] = serializeValue(row[i]);
|
|
1874
|
+
}
|
|
1875
|
+
}
|
|
1876
|
+
rows.push(obj);
|
|
1877
|
+
}
|
|
1878
|
+
return {
|
|
1879
|
+
columns: [...rs.columns],
|
|
1880
|
+
columnTypes: [...rs.columnTypes ?? []],
|
|
1881
|
+
rows,
|
|
1882
|
+
rowsAffected: typeof rs.rowsAffected === "bigint" ? Number(rs.rowsAffected) : rs.rowsAffected ?? 0,
|
|
1883
|
+
lastInsertRowid: rs.lastInsertRowid != null ? typeof rs.lastInsertRowid === "bigint" ? Number(rs.lastInsertRowid) : rs.lastInsertRowid : null
|
|
1884
|
+
};
|
|
1885
|
+
}
|
|
1820
1886
|
function deserializeResultSet(srs) {
|
|
1821
1887
|
const rows = srs.rows.map((obj) => {
|
|
1822
1888
|
const values = srs.columns.map(
|
|
@@ -3106,6 +3172,63 @@ var init_database = __esm({
|
|
|
3106
3172
|
}
|
|
3107
3173
|
});
|
|
3108
3174
|
|
|
3175
|
+
// src/lib/keychain.ts
|
|
3176
|
+
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
3177
|
+
import { existsSync as existsSync7 } from "fs";
|
|
3178
|
+
import path7 from "path";
|
|
3179
|
+
import os5 from "os";
|
|
3180
|
+
function getKeyDir() {
|
|
3181
|
+
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path7.join(os5.homedir(), ".exe-os");
|
|
3182
|
+
}
|
|
3183
|
+
function getKeyPath() {
|
|
3184
|
+
return path7.join(getKeyDir(), "master.key");
|
|
3185
|
+
}
|
|
3186
|
+
async function tryKeytar() {
|
|
3187
|
+
try {
|
|
3188
|
+
return await import("keytar");
|
|
3189
|
+
} catch {
|
|
3190
|
+
return null;
|
|
3191
|
+
}
|
|
3192
|
+
}
|
|
3193
|
+
async function getMasterKey() {
|
|
3194
|
+
const keytar = await tryKeytar();
|
|
3195
|
+
if (keytar) {
|
|
3196
|
+
try {
|
|
3197
|
+
const stored = await keytar.getPassword(SERVICE, ACCOUNT);
|
|
3198
|
+
if (stored) {
|
|
3199
|
+
return Buffer.from(stored, "base64");
|
|
3200
|
+
}
|
|
3201
|
+
} catch {
|
|
3202
|
+
}
|
|
3203
|
+
}
|
|
3204
|
+
const keyPath = getKeyPath();
|
|
3205
|
+
if (!existsSync7(keyPath)) {
|
|
3206
|
+
process.stderr.write(
|
|
3207
|
+
`[keychain] Key not found at ${keyPath} (HOME=${os5.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
|
|
3208
|
+
`
|
|
3209
|
+
);
|
|
3210
|
+
return null;
|
|
3211
|
+
}
|
|
3212
|
+
try {
|
|
3213
|
+
const content = await readFile3(keyPath, "utf-8");
|
|
3214
|
+
return Buffer.from(content.trim(), "base64");
|
|
3215
|
+
} catch (err) {
|
|
3216
|
+
process.stderr.write(
|
|
3217
|
+
`[keychain] Key read failed at ${keyPath}: ${err instanceof Error ? err.message : String(err)}
|
|
3218
|
+
`
|
|
3219
|
+
);
|
|
3220
|
+
return null;
|
|
3221
|
+
}
|
|
3222
|
+
}
|
|
3223
|
+
var SERVICE, ACCOUNT;
|
|
3224
|
+
var init_keychain = __esm({
|
|
3225
|
+
"src/lib/keychain.ts"() {
|
|
3226
|
+
"use strict";
|
|
3227
|
+
SERVICE = "exe-mem";
|
|
3228
|
+
ACCOUNT = "master-key";
|
|
3229
|
+
}
|
|
3230
|
+
});
|
|
3231
|
+
|
|
3109
3232
|
// src/lib/state-bus.ts
|
|
3110
3233
|
var StateBus, orgBus;
|
|
3111
3234
|
var init_state_bus = __esm({
|
|
@@ -3199,8 +3322,8 @@ function getShardClient(projectName) {
|
|
|
3199
3322
|
throw new Error("Shard manager not initialized. Call initShardManager() first.");
|
|
3200
3323
|
}
|
|
3201
3324
|
const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
3202
|
-
if (!safeName) {
|
|
3203
|
-
throw new Error(`Invalid project name for shard: "${projectName}"`);
|
|
3325
|
+
if (!safeName || safeName === "unknown") {
|
|
3326
|
+
throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
|
|
3204
3327
|
}
|
|
3205
3328
|
const cached = _shards.get(safeName);
|
|
3206
3329
|
if (cached) {
|
|
@@ -3732,6 +3855,607 @@ ${p.content}`).join("\n\n");
|
|
|
3732
3855
|
}
|
|
3733
3856
|
});
|
|
3734
3857
|
|
|
3858
|
+
// src/lib/store.ts
|
|
3859
|
+
var store_exports = {};
|
|
3860
|
+
__export(store_exports, {
|
|
3861
|
+
attachDocumentMetadata: () => attachDocumentMetadata,
|
|
3862
|
+
buildRawVisibilityFilter: () => buildRawVisibilityFilter,
|
|
3863
|
+
buildWikiScopeFilter: () => buildWikiScopeFilter,
|
|
3864
|
+
classifyTier: () => classifyTier,
|
|
3865
|
+
disposeStore: () => disposeStore,
|
|
3866
|
+
flushBatch: () => flushBatch,
|
|
3867
|
+
flushTier3: () => flushTier3,
|
|
3868
|
+
getMemoryCardinality: () => getMemoryCardinality,
|
|
3869
|
+
initStore: () => initStore,
|
|
3870
|
+
reserveVersions: () => reserveVersions,
|
|
3871
|
+
searchMemories: () => searchMemories,
|
|
3872
|
+
updateMemoryStatus: () => updateMemoryStatus,
|
|
3873
|
+
vectorToBlob: () => vectorToBlob,
|
|
3874
|
+
writeMemory: () => writeMemory
|
|
3875
|
+
});
|
|
3876
|
+
import { createHash } from "crypto";
|
|
3877
|
+
function isBusyError2(err) {
|
|
3878
|
+
if (err instanceof Error) {
|
|
3879
|
+
const msg = err.message.toLowerCase();
|
|
3880
|
+
return msg.includes("sqlite_busy") || msg.includes("database is locked");
|
|
3881
|
+
}
|
|
3882
|
+
return false;
|
|
3883
|
+
}
|
|
3884
|
+
async function retryOnBusy2(fn, label) {
|
|
3885
|
+
for (let attempt = 0; attempt <= INIT_MAX_RETRIES; attempt++) {
|
|
3886
|
+
try {
|
|
3887
|
+
return await fn();
|
|
3888
|
+
} catch (err) {
|
|
3889
|
+
if (!isBusyError2(err) || attempt === INIT_MAX_RETRIES) throw err;
|
|
3890
|
+
process.stderr.write(
|
|
3891
|
+
`[store] SQLITE_BUSY during ${label}, retry ${attempt + 1}/${INIT_MAX_RETRIES}
|
|
3892
|
+
`
|
|
3893
|
+
);
|
|
3894
|
+
await new Promise((r) => setTimeout(r, INIT_RETRY_DELAY_MS * (attempt + 1)));
|
|
3895
|
+
}
|
|
3896
|
+
}
|
|
3897
|
+
throw new Error("unreachable");
|
|
3898
|
+
}
|
|
3899
|
+
async function initStore(options) {
|
|
3900
|
+
if (_flushTimer !== null) {
|
|
3901
|
+
clearInterval(_flushTimer);
|
|
3902
|
+
_flushTimer = null;
|
|
3903
|
+
}
|
|
3904
|
+
_pendingRecords = [];
|
|
3905
|
+
_flushing = false;
|
|
3906
|
+
_batchSize = options?.batchSize ?? 20;
|
|
3907
|
+
_flushIntervalMs = options?.flushIntervalMs ?? 1e4;
|
|
3908
|
+
let dbPath = options?.dbPath;
|
|
3909
|
+
if (!dbPath) {
|
|
3910
|
+
const config = await loadConfig();
|
|
3911
|
+
dbPath = config.dbPath;
|
|
3912
|
+
}
|
|
3913
|
+
let masterKey = options?.masterKey ?? null;
|
|
3914
|
+
if (!masterKey) {
|
|
3915
|
+
masterKey = await getMasterKey();
|
|
3916
|
+
if (!masterKey) {
|
|
3917
|
+
throw new Error(
|
|
3918
|
+
"No encryption key found. Run /exe-setup to generate one."
|
|
3919
|
+
);
|
|
3920
|
+
}
|
|
3921
|
+
}
|
|
3922
|
+
const hexKey = masterKey.toString("hex");
|
|
3923
|
+
await initTurso({
|
|
3924
|
+
dbPath,
|
|
3925
|
+
encryptionKey: hexKey
|
|
3926
|
+
});
|
|
3927
|
+
await retryOnBusy2(() => ensureSchema(), "ensureSchema");
|
|
3928
|
+
try {
|
|
3929
|
+
const { initDaemonClient: initDaemonClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
3930
|
+
await initDaemonClient2();
|
|
3931
|
+
} catch {
|
|
3932
|
+
}
|
|
3933
|
+
if (!options?.lightweight) {
|
|
3934
|
+
try {
|
|
3935
|
+
const { initShardManager: initShardManager2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
|
|
3936
|
+
initShardManager2(hexKey);
|
|
3937
|
+
} catch {
|
|
3938
|
+
}
|
|
3939
|
+
const client = getClient();
|
|
3940
|
+
const vResult = await retryOnBusy2(
|
|
3941
|
+
() => client.execute("SELECT MAX(version) as max_v FROM memories"),
|
|
3942
|
+
"version-query"
|
|
3943
|
+
);
|
|
3944
|
+
_nextVersion = (Number(vResult.rows[0]?.max_v) || 0) + 1;
|
|
3945
|
+
try {
|
|
3946
|
+
const { loadGlobalProcedures: loadGlobalProcedures2 } = await Promise.resolve().then(() => (init_global_procedures(), global_procedures_exports));
|
|
3947
|
+
await loadGlobalProcedures2();
|
|
3948
|
+
} catch {
|
|
3949
|
+
}
|
|
3950
|
+
}
|
|
3951
|
+
}
|
|
3952
|
+
function classifyTier(record) {
|
|
3953
|
+
if (record.tool_name === "commit_to_long_term_memory" && (record.importance ?? 0) >= 8) return 1;
|
|
3954
|
+
if (["store_memory", "manual"].includes(record.tool_name ?? "") && (record.importance ?? 0) >= 5) return 2;
|
|
3955
|
+
return 3;
|
|
3956
|
+
}
|
|
3957
|
+
function inferFilePaths(record) {
|
|
3958
|
+
if (!["Read", "Write", "Edit"].includes(record.tool_name)) return null;
|
|
3959
|
+
const firstLine = record.raw_text.split("\n")[0] ?? "";
|
|
3960
|
+
const match = firstLine.match(/(\/[\w./-]+\.\w+)/);
|
|
3961
|
+
return match ? JSON.stringify([match[1]]) : null;
|
|
3962
|
+
}
|
|
3963
|
+
function inferCommitHash(record) {
|
|
3964
|
+
if (record.tool_name !== "Bash") return null;
|
|
3965
|
+
const match = record.raw_text.match(/\b([a-f0-9]{7,40})\b/);
|
|
3966
|
+
return match ? match[1] : null;
|
|
3967
|
+
}
|
|
3968
|
+
function inferLanguageType(record) {
|
|
3969
|
+
const text = record.raw_text;
|
|
3970
|
+
if (!text || text.length < 10) return null;
|
|
3971
|
+
const trimmed = text.trimStart();
|
|
3972
|
+
if (trimmed.startsWith("{") || trimmed.startsWith("[")) return "json";
|
|
3973
|
+
if (/\b(SELECT|INSERT|UPDATE|DELETE|CREATE TABLE|ALTER TABLE)\b/i.test(text)) return "sql";
|
|
3974
|
+
if (/\b(function |const |import |export |class |def |async |=>)\b/.test(text)) return "code";
|
|
3975
|
+
if (trimmed.startsWith("#") || trimmed.startsWith("*")) return "prose";
|
|
3976
|
+
return "mixed";
|
|
3977
|
+
}
|
|
3978
|
+
function inferDomain(record) {
|
|
3979
|
+
const proj = (record.project_name ?? "").toLowerCase();
|
|
3980
|
+
if (proj.includes("marketing") || proj.includes("content")) return "marketing";
|
|
3981
|
+
if (proj.includes("crm") || proj.includes("customer")) return "customer";
|
|
3982
|
+
return null;
|
|
3983
|
+
}
|
|
3984
|
+
async function writeMemory(record) {
|
|
3985
|
+
if (record.vector !== null && record.vector.length !== EMBEDDING_DIM) {
|
|
3986
|
+
throw new Error(
|
|
3987
|
+
`Expected ${EMBEDDING_DIM}-dim vector, got ${record.vector.length}`
|
|
3988
|
+
);
|
|
3989
|
+
}
|
|
3990
|
+
const contentHash = createHash("md5").update(record.raw_text).digest("hex");
|
|
3991
|
+
if (_pendingRecords.some((r) => r.content_hash === contentHash && r.agent_id === record.agent_id)) {
|
|
3992
|
+
return;
|
|
3993
|
+
}
|
|
3994
|
+
try {
|
|
3995
|
+
const client = getClient();
|
|
3996
|
+
const existing = await client.execute({
|
|
3997
|
+
sql: "SELECT id FROM memories WHERE content_hash = ? AND agent_id = ? LIMIT 1",
|
|
3998
|
+
args: [contentHash, record.agent_id]
|
|
3999
|
+
});
|
|
4000
|
+
if (existing.rows.length > 0) return;
|
|
4001
|
+
} catch {
|
|
4002
|
+
}
|
|
4003
|
+
const dbRow = {
|
|
4004
|
+
id: record.id,
|
|
4005
|
+
agent_id: record.agent_id,
|
|
4006
|
+
agent_role: record.agent_role,
|
|
4007
|
+
session_id: record.session_id,
|
|
4008
|
+
timestamp: record.timestamp,
|
|
4009
|
+
tool_name: record.tool_name,
|
|
4010
|
+
project_name: record.project_name,
|
|
4011
|
+
has_error: record.has_error ? 1 : 0,
|
|
4012
|
+
raw_text: record.raw_text,
|
|
4013
|
+
vector: record.vector,
|
|
4014
|
+
version: 0,
|
|
4015
|
+
// Placeholder — assigned atomically at flush time
|
|
4016
|
+
task_id: record.task_id ?? null,
|
|
4017
|
+
importance: record.importance ?? 5,
|
|
4018
|
+
status: record.status ?? "active",
|
|
4019
|
+
confidence: record.confidence ?? 0.7,
|
|
4020
|
+
last_accessed: record.last_accessed ?? record.timestamp,
|
|
4021
|
+
workspace_id: record.workspace_id ?? null,
|
|
4022
|
+
document_id: record.document_id ?? null,
|
|
4023
|
+
user_id: record.user_id ?? null,
|
|
4024
|
+
char_offset: record.char_offset ?? null,
|
|
4025
|
+
page_number: record.page_number ?? null,
|
|
4026
|
+
source_path: record.source_path ?? null,
|
|
4027
|
+
source_type: record.source_type ?? null,
|
|
4028
|
+
tier: record.tier ?? classifyTier(record),
|
|
4029
|
+
supersedes_id: record.supersedes_id ?? null,
|
|
4030
|
+
draft: record.draft ? 1 : 0,
|
|
4031
|
+
memory_type: record.memory_type ?? "raw",
|
|
4032
|
+
trajectory: record.trajectory ? JSON.stringify(record.trajectory) : null,
|
|
4033
|
+
content_hash: contentHash,
|
|
4034
|
+
intent: record.intent ?? null,
|
|
4035
|
+
outcome: record.outcome ?? null,
|
|
4036
|
+
domain: record.domain ?? inferDomain(record),
|
|
4037
|
+
referenced_entities: record.referenced_entities ?? null,
|
|
4038
|
+
retrieval_count: record.retrieval_count ?? 0,
|
|
4039
|
+
chain_position: record.chain_position ?? null,
|
|
4040
|
+
review_status: record.review_status ?? null,
|
|
4041
|
+
context_window_pct: record.context_window_pct ?? null,
|
|
4042
|
+
file_paths: record.file_paths ?? inferFilePaths(record),
|
|
4043
|
+
commit_hash: record.commit_hash ?? inferCommitHash(record),
|
|
4044
|
+
duration_ms: record.duration_ms ?? null,
|
|
4045
|
+
token_cost: record.token_cost ?? null,
|
|
4046
|
+
audience: record.audience ?? null,
|
|
4047
|
+
language_type: record.language_type ?? inferLanguageType(record),
|
|
4048
|
+
parent_memory_id: record.parent_memory_id ?? null
|
|
4049
|
+
};
|
|
4050
|
+
_pendingRecords.push(dbRow);
|
|
4051
|
+
orgBus.emit({
|
|
4052
|
+
type: "memory_stored",
|
|
4053
|
+
agentId: record.agent_id,
|
|
4054
|
+
project: record.project_name,
|
|
4055
|
+
timestamp: record.timestamp
|
|
4056
|
+
});
|
|
4057
|
+
const MAX_PENDING = 1e3;
|
|
4058
|
+
if (_pendingRecords.length > MAX_PENDING) {
|
|
4059
|
+
const dropped = _pendingRecords.length - MAX_PENDING;
|
|
4060
|
+
_pendingRecords = _pendingRecords.slice(-MAX_PENDING);
|
|
4061
|
+
console.warn(`[store] Dropped ${dropped} oldest pending records (overflow)`);
|
|
4062
|
+
}
|
|
4063
|
+
if (_flushTimer === null) {
|
|
4064
|
+
_flushTimer = setInterval(() => {
|
|
4065
|
+
void flushBatch();
|
|
4066
|
+
}, _flushIntervalMs);
|
|
4067
|
+
if (_flushTimer && typeof _flushTimer === "object" && "unref" in _flushTimer) {
|
|
4068
|
+
_flushTimer.unref();
|
|
4069
|
+
}
|
|
4070
|
+
}
|
|
4071
|
+
if (_pendingRecords.length >= _batchSize) {
|
|
4072
|
+
await flushBatch();
|
|
4073
|
+
}
|
|
4074
|
+
}
|
|
4075
|
+
async function flushBatch() {
|
|
4076
|
+
if (_flushing || _pendingRecords.length === 0) return 0;
|
|
4077
|
+
_flushing = true;
|
|
4078
|
+
try {
|
|
4079
|
+
const batch = _pendingRecords.slice(0);
|
|
4080
|
+
const client = getClient();
|
|
4081
|
+
const vResult = await client.execute("SELECT MAX(version) as max_v FROM memories");
|
|
4082
|
+
let baseVersion = (Number(vResult.rows[0]?.max_v) || 0) + 1;
|
|
4083
|
+
for (const row of batch) {
|
|
4084
|
+
row.version = baseVersion++;
|
|
4085
|
+
}
|
|
4086
|
+
_nextVersion = baseVersion;
|
|
4087
|
+
const buildStmt = (row) => {
|
|
4088
|
+
const hasVector = row.vector !== null;
|
|
4089
|
+
const taskId = row.task_id ?? null;
|
|
4090
|
+
const importance = row.importance ?? 5;
|
|
4091
|
+
const status = row.status ?? "active";
|
|
4092
|
+
const confidence = row.confidence ?? 0.7;
|
|
4093
|
+
const lastAccessed = row.last_accessed ?? row.timestamp;
|
|
4094
|
+
const workspaceId = row.workspace_id ?? null;
|
|
4095
|
+
const documentId = row.document_id ?? null;
|
|
4096
|
+
const userId = row.user_id ?? null;
|
|
4097
|
+
const charOffset = row.char_offset ?? null;
|
|
4098
|
+
const pageNumber = row.page_number ?? null;
|
|
4099
|
+
const sourcePath = row.source_path ?? null;
|
|
4100
|
+
const sourceType = row.source_type ?? null;
|
|
4101
|
+
const tier = row.tier ?? 3;
|
|
4102
|
+
const supersedesId = row.supersedes_id ?? null;
|
|
4103
|
+
const draft = row.draft ? 1 : 0;
|
|
4104
|
+
const memoryType = row.memory_type ?? "raw";
|
|
4105
|
+
const trajectory = row.trajectory ?? null;
|
|
4106
|
+
const contentHash = row.content_hash ?? null;
|
|
4107
|
+
const intent = row.intent ?? null;
|
|
4108
|
+
const outcome = row.outcome ?? null;
|
|
4109
|
+
const domain = row.domain ?? null;
|
|
4110
|
+
const referencedEntities = row.referenced_entities ?? null;
|
|
4111
|
+
const retrievalCount = row.retrieval_count ?? 0;
|
|
4112
|
+
const chainPosition = row.chain_position ?? null;
|
|
4113
|
+
const reviewStatus = row.review_status ?? null;
|
|
4114
|
+
const contextWindowPct = row.context_window_pct ?? null;
|
|
4115
|
+
const filePaths = row.file_paths ?? null;
|
|
4116
|
+
const commitHash = row.commit_hash ?? null;
|
|
4117
|
+
const durationMs = row.duration_ms ?? null;
|
|
4118
|
+
const tokenCost = row.token_cost ?? null;
|
|
4119
|
+
const audience = row.audience ?? null;
|
|
4120
|
+
const languageType = row.language_type ?? null;
|
|
4121
|
+
const parentMemoryId = row.parent_memory_id ?? null;
|
|
4122
|
+
const cols = `id, agent_id, agent_role, session_id, timestamp,
|
|
4123
|
+
tool_name, project_name,
|
|
4124
|
+
has_error, raw_text, vector, version, task_id, importance, status,
|
|
4125
|
+
confidence, last_accessed,
|
|
4126
|
+
workspace_id, document_id, user_id, char_offset, page_number,
|
|
4127
|
+
source_path, source_type, tier, supersedes_id, draft, memory_type, trajectory, content_hash,
|
|
4128
|
+
intent, outcome, domain, referenced_entities, retrieval_count,
|
|
4129
|
+
chain_position, review_status, context_window_pct, file_paths, commit_hash,
|
|
4130
|
+
duration_ms, token_cost, audience, language_type, parent_memory_id`;
|
|
4131
|
+
const metaArgs = [
|
|
4132
|
+
intent,
|
|
4133
|
+
outcome,
|
|
4134
|
+
domain,
|
|
4135
|
+
referencedEntities,
|
|
4136
|
+
retrievalCount,
|
|
4137
|
+
chainPosition,
|
|
4138
|
+
reviewStatus,
|
|
4139
|
+
contextWindowPct,
|
|
4140
|
+
filePaths,
|
|
4141
|
+
commitHash,
|
|
4142
|
+
durationMs,
|
|
4143
|
+
tokenCost,
|
|
4144
|
+
audience,
|
|
4145
|
+
languageType,
|
|
4146
|
+
parentMemoryId
|
|
4147
|
+
];
|
|
4148
|
+
const baseArgs = [
|
|
4149
|
+
row.id,
|
|
4150
|
+
row.agent_id,
|
|
4151
|
+
row.agent_role,
|
|
4152
|
+
row.session_id,
|
|
4153
|
+
row.timestamp,
|
|
4154
|
+
row.tool_name,
|
|
4155
|
+
row.project_name,
|
|
4156
|
+
row.has_error,
|
|
4157
|
+
row.raw_text
|
|
4158
|
+
];
|
|
4159
|
+
const sharedArgs = [
|
|
4160
|
+
row.version,
|
|
4161
|
+
taskId,
|
|
4162
|
+
importance,
|
|
4163
|
+
status,
|
|
4164
|
+
confidence,
|
|
4165
|
+
lastAccessed,
|
|
4166
|
+
workspaceId,
|
|
4167
|
+
documentId,
|
|
4168
|
+
userId,
|
|
4169
|
+
charOffset,
|
|
4170
|
+
pageNumber,
|
|
4171
|
+
sourcePath,
|
|
4172
|
+
sourceType,
|
|
4173
|
+
tier,
|
|
4174
|
+
supersedesId,
|
|
4175
|
+
draft,
|
|
4176
|
+
memoryType,
|
|
4177
|
+
trajectory,
|
|
4178
|
+
contentHash
|
|
4179
|
+
];
|
|
4180
|
+
return {
|
|
4181
|
+
sql: hasVector ? `INSERT OR IGNORE INTO memories (${cols})
|
|
4182
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
|
|
4183
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
4184
|
+
args: hasVector ? [...baseArgs, vectorToBlob(row.vector), ...sharedArgs, ...metaArgs] : [...baseArgs, ...sharedArgs, ...metaArgs]
|
|
4185
|
+
};
|
|
4186
|
+
};
|
|
4187
|
+
const globalClient = getClient();
|
|
4188
|
+
const globalStmts = batch.map(buildStmt);
|
|
4189
|
+
await globalClient.batch(globalStmts, "write");
|
|
4190
|
+
_pendingRecords.splice(0, batch.length);
|
|
4191
|
+
try {
|
|
4192
|
+
const { isShardingEnabled: isShardingEnabled2, getReadyShardClient: getReadyShardClient2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
|
|
4193
|
+
if (isShardingEnabled2()) {
|
|
4194
|
+
const byProject = /* @__PURE__ */ new Map();
|
|
4195
|
+
let skippedUnknown = 0;
|
|
4196
|
+
for (const row of batch) {
|
|
4197
|
+
const proj = row.project_name?.trim();
|
|
4198
|
+
if (!proj) {
|
|
4199
|
+
skippedUnknown++;
|
|
4200
|
+
continue;
|
|
4201
|
+
}
|
|
4202
|
+
if (!byProject.has(proj)) byProject.set(proj, []);
|
|
4203
|
+
byProject.get(proj).push(row);
|
|
4204
|
+
}
|
|
4205
|
+
if (skippedUnknown > 0) {
|
|
4206
|
+
process.stderr.write(
|
|
4207
|
+
`[store] Shard skip: ${skippedUnknown} record(s) with empty project_name (kept in main DB only)
|
|
4208
|
+
`
|
|
4209
|
+
);
|
|
4210
|
+
}
|
|
4211
|
+
for (const [project, rows] of byProject) {
|
|
4212
|
+
try {
|
|
4213
|
+
const shardClient = await getReadyShardClient2(project);
|
|
4214
|
+
const shardStmts = rows.map(buildStmt);
|
|
4215
|
+
await shardClient.batch(shardStmts, "write");
|
|
4216
|
+
} catch (err) {
|
|
4217
|
+
const fullError = err instanceof Error ? `${err.name}: ${err.message}${err.stack ? `
|
|
4218
|
+
${err.stack.split("\n").slice(1, 3).join("\n")}` : ""}` : String(err);
|
|
4219
|
+
process.stderr.write(
|
|
4220
|
+
`[store] Shard write failed for ${project} (${rows.length} records): ${fullError}
|
|
4221
|
+
`
|
|
4222
|
+
);
|
|
4223
|
+
}
|
|
4224
|
+
}
|
|
4225
|
+
}
|
|
4226
|
+
} catch {
|
|
4227
|
+
}
|
|
4228
|
+
return batch.length;
|
|
4229
|
+
} finally {
|
|
4230
|
+
_flushing = false;
|
|
4231
|
+
}
|
|
4232
|
+
}
|
|
4233
|
+
function buildWikiScopeFilter(options, columnPrefix) {
|
|
4234
|
+
const args = [];
|
|
4235
|
+
let clause = "";
|
|
4236
|
+
if (options?.workspaceId !== void 0) {
|
|
4237
|
+
clause += ` AND ${columnPrefix}workspace_id = ?`;
|
|
4238
|
+
args.push(options.workspaceId);
|
|
4239
|
+
}
|
|
4240
|
+
if (options?.userId === void 0) {
|
|
4241
|
+
clause += ` AND ${columnPrefix}user_id IS NULL`;
|
|
4242
|
+
} else if (options.userId === null) {
|
|
4243
|
+
clause += ` AND ${columnPrefix}user_id IS NULL`;
|
|
4244
|
+
} else {
|
|
4245
|
+
clause += ` AND (${columnPrefix}user_id = ? OR ${columnPrefix}user_id IS NULL)`;
|
|
4246
|
+
args.push(options.userId);
|
|
4247
|
+
}
|
|
4248
|
+
return { clause, args };
|
|
4249
|
+
}
|
|
4250
|
+
function buildRawVisibilityFilter(options, columnPrefix) {
|
|
4251
|
+
if (options?.includeRaw === false) {
|
|
4252
|
+
return {
|
|
4253
|
+
clause: ` AND COALESCE(${columnPrefix}memory_type, 'raw') != 'raw'`,
|
|
4254
|
+
args: []
|
|
4255
|
+
};
|
|
4256
|
+
}
|
|
4257
|
+
return { clause: "", args: [] };
|
|
4258
|
+
}
|
|
4259
|
+
async function searchMemories(queryVector, agentId, options) {
|
|
4260
|
+
let client;
|
|
4261
|
+
try {
|
|
4262
|
+
const { isShardingEnabled: isShardingEnabled2, shardExists: shardExists2, getReadyShardClient: getReadyShardClient2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
|
|
4263
|
+
if (isShardingEnabled2() && options?.projectName && shardExists2(options.projectName)) {
|
|
4264
|
+
client = await getReadyShardClient2(options.projectName);
|
|
4265
|
+
} else {
|
|
4266
|
+
client = getClient();
|
|
4267
|
+
}
|
|
4268
|
+
} catch {
|
|
4269
|
+
client = getClient();
|
|
4270
|
+
}
|
|
4271
|
+
const limit = options?.limit ?? 10;
|
|
4272
|
+
const statusFilter = options?.includeArchived ? "" : `
|
|
4273
|
+
AND COALESCE(status, 'active') = 'active'`;
|
|
4274
|
+
const draftFilter = options?.includeDrafts ? "" : `
|
|
4275
|
+
AND (draft = 0 OR draft IS NULL)`;
|
|
4276
|
+
let sql = `SELECT id, agent_id, agent_role, session_id, timestamp,
|
|
4277
|
+
tool_name, project_name,
|
|
4278
|
+
has_error, raw_text, vector, importance, status,
|
|
4279
|
+
confidence, last_accessed,
|
|
4280
|
+
workspace_id, document_id, user_id,
|
|
4281
|
+
char_offset, page_number,
|
|
4282
|
+
source_path, source_type
|
|
4283
|
+
FROM memories
|
|
4284
|
+
WHERE agent_id = ?
|
|
4285
|
+
AND vector IS NOT NULL${statusFilter}${draftFilter}
|
|
4286
|
+
AND COALESCE(confidence, 0.7) >= 0.3`;
|
|
4287
|
+
const args = [agentId];
|
|
4288
|
+
const scope = buildWikiScopeFilter(options, "");
|
|
4289
|
+
sql += scope.clause;
|
|
4290
|
+
args.push(...scope.args);
|
|
4291
|
+
const rawVisibility = buildRawVisibilityFilter(options, "");
|
|
4292
|
+
sql += rawVisibility.clause;
|
|
4293
|
+
args.push(...rawVisibility.args);
|
|
4294
|
+
if (options?.projectName) {
|
|
4295
|
+
sql += ` AND project_name = ?`;
|
|
4296
|
+
args.push(options.projectName);
|
|
4297
|
+
}
|
|
4298
|
+
if (options?.toolName) {
|
|
4299
|
+
sql += ` AND tool_name = ?`;
|
|
4300
|
+
args.push(options.toolName);
|
|
4301
|
+
}
|
|
4302
|
+
if (options?.hasError !== void 0) {
|
|
4303
|
+
sql += ` AND has_error = ?`;
|
|
4304
|
+
args.push(options.hasError ? 1 : 0);
|
|
4305
|
+
}
|
|
4306
|
+
if (options?.since) {
|
|
4307
|
+
sql += ` AND timestamp >= ?`;
|
|
4308
|
+
args.push(options.since);
|
|
4309
|
+
}
|
|
4310
|
+
if (options?.memoryType) {
|
|
4311
|
+
sql += ` AND memory_type = ?`;
|
|
4312
|
+
args.push(options.memoryType);
|
|
4313
|
+
}
|
|
4314
|
+
sql += ` ORDER BY vector_distance_cos(vector, vector32(?))`;
|
|
4315
|
+
args.push(vectorToBlob(queryVector));
|
|
4316
|
+
sql += ` LIMIT ?`;
|
|
4317
|
+
args.push(limit);
|
|
4318
|
+
const result = await client.execute({ sql, args });
|
|
4319
|
+
return result.rows.map((row) => ({
|
|
4320
|
+
id: row.id,
|
|
4321
|
+
agent_id: row.agent_id,
|
|
4322
|
+
agent_role: row.agent_role,
|
|
4323
|
+
session_id: row.session_id,
|
|
4324
|
+
timestamp: row.timestamp,
|
|
4325
|
+
tool_name: row.tool_name,
|
|
4326
|
+
project_name: row.project_name,
|
|
4327
|
+
has_error: row.has_error === 1,
|
|
4328
|
+
raw_text: row.raw_text,
|
|
4329
|
+
vector: row.vector == null ? [] : Array.isArray(row.vector) ? row.vector : Array.from(row.vector),
|
|
4330
|
+
importance: row.importance ?? 5,
|
|
4331
|
+
status: row.status ?? "active",
|
|
4332
|
+
confidence: row.confidence ?? 0.7,
|
|
4333
|
+
last_accessed: row.last_accessed ?? row.timestamp,
|
|
4334
|
+
workspace_id: row.workspace_id ?? null,
|
|
4335
|
+
document_id: row.document_id ?? null,
|
|
4336
|
+
user_id: row.user_id ?? null,
|
|
4337
|
+
char_offset: row.char_offset ?? null,
|
|
4338
|
+
page_number: row.page_number ?? null,
|
|
4339
|
+
source_path: row.source_path ?? null,
|
|
4340
|
+
source_type: row.source_type ?? null
|
|
4341
|
+
}));
|
|
4342
|
+
}
|
|
4343
|
+
async function attachDocumentMetadata(records) {
|
|
4344
|
+
const docIds = [
|
|
4345
|
+
...new Set(
|
|
4346
|
+
records.map((r) => r.document_id).filter((id) => typeof id === "string" && id.length > 0)
|
|
4347
|
+
)
|
|
4348
|
+
];
|
|
4349
|
+
if (docIds.length === 0) return records;
|
|
4350
|
+
try {
|
|
4351
|
+
const client = getClient();
|
|
4352
|
+
const placeholders = docIds.map(() => "?").join(",");
|
|
4353
|
+
const result = await client.execute({
|
|
4354
|
+
sql: `SELECT id, filename, mime, source_type, uploaded_at
|
|
4355
|
+
FROM documents
|
|
4356
|
+
WHERE id IN (${placeholders})`,
|
|
4357
|
+
args: docIds
|
|
4358
|
+
});
|
|
4359
|
+
const byId = /* @__PURE__ */ new Map();
|
|
4360
|
+
for (const row of result.rows) {
|
|
4361
|
+
const id = row.id;
|
|
4362
|
+
byId.set(id, {
|
|
4363
|
+
document_id: id,
|
|
4364
|
+
filename: row.filename,
|
|
4365
|
+
mime: row.mime ?? null,
|
|
4366
|
+
source_type: row.source_type ?? null,
|
|
4367
|
+
uploaded_at: row.uploaded_at
|
|
4368
|
+
});
|
|
4369
|
+
}
|
|
4370
|
+
for (const record of records) {
|
|
4371
|
+
if (!record.document_id) continue;
|
|
4372
|
+
record.document_metadata = byId.get(record.document_id) ?? null;
|
|
4373
|
+
}
|
|
4374
|
+
} catch {
|
|
4375
|
+
}
|
|
4376
|
+
return records;
|
|
4377
|
+
}
|
|
4378
|
+
async function flushTier3(agentId, options) {
|
|
4379
|
+
const client = getClient();
|
|
4380
|
+
const maxAge = options?.maxAgeHours ?? 72;
|
|
4381
|
+
const cutoff = new Date(Date.now() - maxAge * 36e5).toISOString();
|
|
4382
|
+
if (options?.dryRun) {
|
|
4383
|
+
const result2 = await client.execute({
|
|
4384
|
+
sql: `SELECT COUNT(*) as cnt FROM memories
|
|
4385
|
+
WHERE agent_id = ? AND tier = 3 AND status = 'active' AND timestamp < ?`,
|
|
4386
|
+
args: [agentId, cutoff]
|
|
4387
|
+
});
|
|
4388
|
+
return { archived: Number(result2.rows[0]?.cnt ?? 0) };
|
|
4389
|
+
}
|
|
4390
|
+
const result = await client.execute({
|
|
4391
|
+
sql: `UPDATE memories SET status = 'archived'
|
|
4392
|
+
WHERE agent_id = ? AND tier = 3 AND status = 'active' AND timestamp < ?`,
|
|
4393
|
+
args: [agentId, cutoff]
|
|
4394
|
+
});
|
|
4395
|
+
return { archived: result.rowsAffected };
|
|
4396
|
+
}
|
|
4397
|
+
async function disposeStore() {
|
|
4398
|
+
if (_flushTimer !== null) {
|
|
4399
|
+
clearInterval(_flushTimer);
|
|
4400
|
+
_flushTimer = null;
|
|
4401
|
+
}
|
|
4402
|
+
if (_pendingRecords.length > 0) {
|
|
4403
|
+
await flushBatch();
|
|
4404
|
+
}
|
|
4405
|
+
await disposeTurso();
|
|
4406
|
+
_pendingRecords = [];
|
|
4407
|
+
_nextVersion = 1;
|
|
4408
|
+
}
|
|
4409
|
+
function vectorToBlob(vector) {
|
|
4410
|
+
const f32 = vector instanceof Float32Array ? vector : new Float32Array(vector);
|
|
4411
|
+
return JSON.stringify(Array.from(f32));
|
|
4412
|
+
}
|
|
4413
|
+
async function updateMemoryStatus(id, status) {
|
|
4414
|
+
const client = getClient();
|
|
4415
|
+
await client.execute({
|
|
4416
|
+
sql: `UPDATE memories SET status = ? WHERE id = ?`,
|
|
4417
|
+
args: [status, id]
|
|
4418
|
+
});
|
|
4419
|
+
}
|
|
4420
|
+
function reserveVersions(count) {
|
|
4421
|
+
const reserved = [];
|
|
4422
|
+
for (let i = 0; i < count; i++) {
|
|
4423
|
+
reserved.push(_nextVersion++);
|
|
4424
|
+
}
|
|
4425
|
+
return reserved;
|
|
4426
|
+
}
|
|
4427
|
+
async function getMemoryCardinality(agentId) {
|
|
4428
|
+
try {
|
|
4429
|
+
const client = getClient();
|
|
4430
|
+
const result = await client.execute({
|
|
4431
|
+
sql: `SELECT COUNT(*) as cnt FROM memories WHERE agent_id = ? AND COALESCE(status, 'active') = 'active'`,
|
|
4432
|
+
args: [agentId]
|
|
4433
|
+
});
|
|
4434
|
+
return Number(result.rows[0]?.cnt) || 0;
|
|
4435
|
+
} catch {
|
|
4436
|
+
return 0;
|
|
4437
|
+
}
|
|
4438
|
+
}
|
|
4439
|
+
var INIT_MAX_RETRIES, INIT_RETRY_DELAY_MS, _pendingRecords, _batchSize, _flushIntervalMs, _flushTimer, _flushing, _nextVersion;
|
|
4440
|
+
var init_store = __esm({
|
|
4441
|
+
"src/lib/store.ts"() {
|
|
4442
|
+
"use strict";
|
|
4443
|
+
init_memory();
|
|
4444
|
+
init_database();
|
|
4445
|
+
init_keychain();
|
|
4446
|
+
init_config();
|
|
4447
|
+
init_state_bus();
|
|
4448
|
+
INIT_MAX_RETRIES = 3;
|
|
4449
|
+
INIT_RETRY_DELAY_MS = 1e3;
|
|
4450
|
+
_pendingRecords = [];
|
|
4451
|
+
_batchSize = 20;
|
|
4452
|
+
_flushIntervalMs = 1e4;
|
|
4453
|
+
_flushTimer = null;
|
|
4454
|
+
_flushing = false;
|
|
4455
|
+
_nextVersion = 1;
|
|
4456
|
+
}
|
|
4457
|
+
});
|
|
4458
|
+
|
|
3735
4459
|
// src/lib/session-registry.ts
|
|
3736
4460
|
import { readFileSync as readFileSync6, writeFileSync as writeFileSync4, mkdirSync as mkdirSync3, existsSync as existsSync9 } from "fs";
|
|
3737
4461
|
import path9 from "path";
|
|
@@ -7251,147 +7975,66 @@ var init_tasks = __esm({
|
|
|
7251
7975
|
}
|
|
7252
7976
|
});
|
|
7253
7977
|
|
|
7254
|
-
// src/
|
|
7255
|
-
|
|
7256
|
-
init_database();
|
|
7257
|
-
|
|
7258
|
-
|
|
7259
|
-
|
|
7260
|
-
|
|
7261
|
-
|
|
7262
|
-
|
|
7263
|
-
|
|
7264
|
-
|
|
7265
|
-
|
|
7266
|
-
|
|
7267
|
-
|
|
7268
|
-
|
|
7269
|
-
|
|
7270
|
-
|
|
7271
|
-
|
|
7272
|
-
|
|
7273
|
-
|
|
7274
|
-
|
|
7275
|
-
|
|
7276
|
-
|
|
7277
|
-
|
|
7278
|
-
}
|
|
7279
|
-
|
|
7280
|
-
|
|
7281
|
-
|
|
7282
|
-
|
|
7283
|
-
|
|
7284
|
-
|
|
7285
|
-
|
|
7286
|
-
|
|
7287
|
-
|
|
7288
|
-
|
|
7289
|
-
|
|
7290
|
-
|
|
7291
|
-
|
|
7292
|
-
|
|
7293
|
-
|
|
7294
|
-
|
|
7295
|
-
|
|
7296
|
-
|
|
7297
|
-
|
|
7298
|
-
|
|
7299
|
-
|
|
7300
|
-
|
|
7301
|
-
|
|
7302
|
-
|
|
7303
|
-
|
|
7304
|
-
|
|
7305
|
-
|
|
7306
|
-
|
|
7307
|
-
|
|
7308
|
-
}
|
|
7309
|
-
|
|
7310
|
-
// src/lib/store.ts
|
|
7311
|
-
init_config();
|
|
7312
|
-
init_state_bus();
|
|
7313
|
-
var INIT_MAX_RETRIES = 3;
|
|
7314
|
-
var INIT_RETRY_DELAY_MS = 1e3;
|
|
7315
|
-
function isBusyError2(err) {
|
|
7316
|
-
if (err instanceof Error) {
|
|
7317
|
-
const msg = err.message.toLowerCase();
|
|
7318
|
-
return msg.includes("sqlite_busy") || msg.includes("database is locked");
|
|
7319
|
-
}
|
|
7320
|
-
return false;
|
|
7321
|
-
}
|
|
7322
|
-
async function retryOnBusy2(fn, label) {
|
|
7323
|
-
for (let attempt = 0; attempt <= INIT_MAX_RETRIES; attempt++) {
|
|
7324
|
-
try {
|
|
7325
|
-
return await fn();
|
|
7326
|
-
} catch (err) {
|
|
7327
|
-
if (!isBusyError2(err) || attempt === INIT_MAX_RETRIES) throw err;
|
|
7328
|
-
process.stderr.write(
|
|
7329
|
-
`[store] SQLITE_BUSY during ${label}, retry ${attempt + 1}/${INIT_MAX_RETRIES}
|
|
7330
|
-
`
|
|
7331
|
-
);
|
|
7332
|
-
await new Promise((r) => setTimeout(r, INIT_RETRY_DELAY_MS * (attempt + 1)));
|
|
7333
|
-
}
|
|
7334
|
-
}
|
|
7335
|
-
throw new Error("unreachable");
|
|
7336
|
-
}
|
|
7337
|
-
var _pendingRecords = [];
|
|
7338
|
-
var _batchSize = 20;
|
|
7339
|
-
var _flushIntervalMs = 1e4;
|
|
7340
|
-
var _flushTimer = null;
|
|
7341
|
-
var _flushing = false;
|
|
7342
|
-
var _nextVersion = 1;
|
|
7343
|
-
async function initStore(options) {
|
|
7344
|
-
if (_flushTimer !== null) {
|
|
7345
|
-
clearInterval(_flushTimer);
|
|
7346
|
-
_flushTimer = null;
|
|
7347
|
-
}
|
|
7348
|
-
_pendingRecords = [];
|
|
7349
|
-
_flushing = false;
|
|
7350
|
-
_batchSize = options?.batchSize ?? 20;
|
|
7351
|
-
_flushIntervalMs = options?.flushIntervalMs ?? 1e4;
|
|
7352
|
-
let dbPath = options?.dbPath;
|
|
7353
|
-
if (!dbPath) {
|
|
7354
|
-
const config = await loadConfig();
|
|
7355
|
-
dbPath = config.dbPath;
|
|
7356
|
-
}
|
|
7357
|
-
let masterKey = options?.masterKey ?? null;
|
|
7358
|
-
if (!masterKey) {
|
|
7359
|
-
masterKey = await getMasterKey();
|
|
7360
|
-
if (!masterKey) {
|
|
7361
|
-
throw new Error(
|
|
7362
|
-
"No encryption key found. Run /exe-setup to generate one."
|
|
7363
|
-
);
|
|
7978
|
+
// src/bin/fast-db-init.ts
|
|
7979
|
+
async function fastDbInit() {
|
|
7980
|
+
const { isInitialized: isInitialized2, getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
7981
|
+
if (isInitialized2()) {
|
|
7982
|
+
return getClient2();
|
|
7983
|
+
}
|
|
7984
|
+
try {
|
|
7985
|
+
const { connectEmbedDaemon: connectEmbedDaemon2, sendDaemonRequest: sendDaemonRequest2, isClientConnected: isClientConnected2 } = await Promise.resolve().then(() => (init_exe_daemon_client(), exe_daemon_client_exports));
|
|
7986
|
+
const { deserializeResultSet: deserializeResultSet2 } = await Promise.resolve().then(() => (init_daemon_protocol(), daemon_protocol_exports));
|
|
7987
|
+
await connectEmbedDaemon2();
|
|
7988
|
+
if (isClientConnected2()) {
|
|
7989
|
+
const daemonClient = {
|
|
7990
|
+
async execute(stmt) {
|
|
7991
|
+
const sql = typeof stmt === "string" ? stmt : stmt.sql;
|
|
7992
|
+
const args = typeof stmt === "string" ? [] : Array.isArray(stmt.args) ? stmt.args : [];
|
|
7993
|
+
const resp = await sendDaemonRequest2({ type: "db-execute", sql, args });
|
|
7994
|
+
if (resp.error) throw new Error(String(resp.error));
|
|
7995
|
+
if (resp.db) return deserializeResultSet2(resp.db);
|
|
7996
|
+
throw new Error("Unexpected daemon response");
|
|
7997
|
+
},
|
|
7998
|
+
async batch(stmts, mode) {
|
|
7999
|
+
const statements = stmts.map((s) => {
|
|
8000
|
+
const sql = typeof s === "string" ? s : s.sql;
|
|
8001
|
+
const args = typeof s === "string" ? [] : Array.isArray(s.args) ? s.args : [];
|
|
8002
|
+
return { sql, args };
|
|
8003
|
+
});
|
|
8004
|
+
const resp = await sendDaemonRequest2({ type: "db-batch", statements, mode: mode ?? "deferred" });
|
|
8005
|
+
if (resp.error) throw new Error(String(resp.error));
|
|
8006
|
+
const batchResults = resp["db-batch"];
|
|
8007
|
+
if (batchResults) return batchResults.map(deserializeResultSet2);
|
|
8008
|
+
throw new Error("Unexpected daemon batch response");
|
|
8009
|
+
},
|
|
8010
|
+
async transaction(_mode) {
|
|
8011
|
+
throw new Error("Transactions not supported via daemon socket");
|
|
8012
|
+
},
|
|
8013
|
+
async executeMultiple(_sql) {
|
|
8014
|
+
throw new Error("executeMultiple not supported via daemon socket");
|
|
8015
|
+
},
|
|
8016
|
+
async migrate(_stmts) {
|
|
8017
|
+
throw new Error("migrate not supported via daemon socket");
|
|
8018
|
+
},
|
|
8019
|
+
sync() {
|
|
8020
|
+
return Promise.resolve(void 0);
|
|
8021
|
+
},
|
|
8022
|
+
close() {
|
|
8023
|
+
},
|
|
8024
|
+
get closed() {
|
|
8025
|
+
return false;
|
|
8026
|
+
},
|
|
8027
|
+
get protocol() {
|
|
8028
|
+
return "file";
|
|
8029
|
+
}
|
|
8030
|
+
};
|
|
8031
|
+
return daemonClient;
|
|
7364
8032
|
}
|
|
7365
|
-
}
|
|
7366
|
-
const hexKey = masterKey.toString("hex");
|
|
7367
|
-
await initTurso({
|
|
7368
|
-
dbPath,
|
|
7369
|
-
encryptionKey: hexKey
|
|
7370
|
-
});
|
|
7371
|
-
await retryOnBusy2(() => ensureSchema(), "ensureSchema");
|
|
7372
|
-
try {
|
|
7373
|
-
const { initDaemonClient: initDaemonClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
7374
|
-
await initDaemonClient2();
|
|
7375
8033
|
} catch {
|
|
7376
8034
|
}
|
|
7377
|
-
|
|
7378
|
-
|
|
7379
|
-
|
|
7380
|
-
initShardManager2(hexKey);
|
|
7381
|
-
} catch {
|
|
7382
|
-
}
|
|
7383
|
-
const client = getClient();
|
|
7384
|
-
const vResult = await retryOnBusy2(
|
|
7385
|
-
() => client.execute("SELECT MAX(version) as max_v FROM memories"),
|
|
7386
|
-
"version-query"
|
|
7387
|
-
);
|
|
7388
|
-
_nextVersion = (Number(vResult.rows[0]?.max_v) || 0) + 1;
|
|
7389
|
-
try {
|
|
7390
|
-
const { loadGlobalProcedures: loadGlobalProcedures2 } = await Promise.resolve().then(() => (init_global_procedures(), global_procedures_exports));
|
|
7391
|
-
await loadGlobalProcedures2();
|
|
7392
|
-
} catch {
|
|
7393
|
-
}
|
|
7394
|
-
}
|
|
8035
|
+
const { initStore: initStore2 } = await Promise.resolve().then(() => (init_store(), store_exports));
|
|
8036
|
+
await initStore2({ lightweight: true });
|
|
8037
|
+
return getClient2();
|
|
7395
8038
|
}
|
|
7396
8039
|
|
|
7397
8040
|
// src/adapters/claude/hooks/bug-report-worker.ts
|
|
@@ -7405,7 +8048,7 @@ async function main() {
|
|
|
7405
8048
|
const agentId = process.env.BUG_AGENT_ID ?? "unknown";
|
|
7406
8049
|
const agentRole = process.env.BUG_AGENT_ROLE ?? "employee";
|
|
7407
8050
|
const projectName = process.env.BUG_PROJECT_NAME ?? "unknown";
|
|
7408
|
-
await
|
|
8051
|
+
await fastDbInit();
|
|
7409
8052
|
const fpPrefix = fingerprint.slice(0, 8);
|
|
7410
8053
|
const client = getClient();
|
|
7411
8054
|
const { loadEmployeesSync: loadEmployeesSync2, getEmployeeByRole: getEmployeeByRole2, getCoordinatorName: getCoordinatorName2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|