@askexenow/exe-os 0.8.83 → 0.8.85
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 +746 -595
- package/dist/bin/backfill-responses.js +745 -594
- package/dist/bin/backfill-vectors.js +312 -226
- package/dist/bin/cleanup-stale-review-tasks.js +97 -2
- package/dist/bin/cli.js +14350 -12518
- package/dist/bin/exe-agent.js +97 -88
- package/dist/bin/exe-assign.js +1003 -854
- package/dist/bin/exe-boot.js +1257 -320
- package/dist/bin/exe-call.js +10 -0
- package/dist/bin/exe-cloud.js +29 -6
- package/dist/bin/exe-dispatch.js +210 -34
- package/dist/bin/exe-doctor.js +403 -6
- package/dist/bin/exe-export-behaviors.js +175 -72
- package/dist/bin/exe-forget.js +97 -2
- package/dist/bin/exe-gateway.js +550 -171
- package/dist/bin/exe-healthcheck.js +1 -0
- package/dist/bin/exe-heartbeat.js +100 -5
- package/dist/bin/exe-kill.js +175 -72
- package/dist/bin/exe-launch-agent.js +189 -76
- package/dist/bin/exe-link.js +902 -80
- package/dist/bin/exe-new-employee.js +38 -8
- package/dist/bin/exe-pending-messages.js +96 -2
- package/dist/bin/exe-pending-notifications.js +97 -2
- package/dist/bin/exe-pending-reviews.js +98 -3
- package/dist/bin/exe-rename.js +564 -23
- package/dist/bin/exe-review.js +231 -73
- package/dist/bin/exe-search.js +989 -226
- package/dist/bin/exe-session-cleanup.js +4806 -1665
- package/dist/bin/exe-settings.js +20 -5
- package/dist/bin/exe-status.js +97 -2
- package/dist/bin/exe-team.js +97 -2
- package/dist/bin/git-sweep.js +899 -207
- package/dist/bin/graph-backfill.js +175 -72
- package/dist/bin/graph-export.js +175 -72
- package/dist/bin/install.js +38 -7
- package/dist/bin/list-providers.js +1 -0
- package/dist/bin/scan-tasks.js +904 -211
- package/dist/bin/setup.js +867 -268
- package/dist/bin/shard-migrate.js +175 -72
- package/dist/bin/update.js +1 -0
- package/dist/bin/wiki-sync.js +175 -72
- package/dist/gateway/index.js +548 -166
- package/dist/hooks/bug-report-worker.js +208 -23
- package/dist/hooks/commit-complete.js +897 -205
- package/dist/hooks/error-recall.js +988 -226
- package/dist/hooks/ingest-worker.js +1638 -1194
- package/dist/hooks/ingest.js +3 -0
- package/dist/hooks/instructions-loaded.js +707 -97
- package/dist/hooks/notification.js +699 -89
- package/dist/hooks/post-compact.js +714 -104
- package/dist/hooks/pre-compact.js +897 -205
- package/dist/hooks/pre-tool-use.js +742 -123
- package/dist/hooks/prompt-ingest-worker.js +242 -101
- package/dist/hooks/prompt-submit.js +995 -233
- package/dist/hooks/response-ingest-worker.js +242 -101
- package/dist/hooks/session-end.js +3941 -400
- package/dist/hooks/session-start.js +1001 -226
- package/dist/hooks/stop.js +725 -115
- package/dist/hooks/subagent-stop.js +714 -104
- package/dist/hooks/summary-worker.js +1964 -1330
- package/dist/index.js +1651 -1053
- package/dist/lib/cloud-sync.js +907 -86
- package/dist/lib/consolidation.js +2 -1
- package/dist/lib/database.js +642 -87
- package/dist/lib/db-daemon-client.js +503 -0
- package/dist/lib/device-registry.js +547 -7
- package/dist/lib/embedder.js +14 -28
- package/dist/lib/employee-templates.js +84 -74
- package/dist/lib/employees.js +9 -0
- package/dist/lib/exe-daemon-client.js +16 -29
- package/dist/lib/exe-daemon.js +1955 -922
- package/dist/lib/hybrid-search.js +988 -226
- package/dist/lib/identity.js +87 -67
- package/dist/lib/keychain.js +9 -1
- package/dist/lib/messaging.js +8 -1
- package/dist/lib/reminders.js +91 -74
- package/dist/lib/schedules.js +96 -2
- package/dist/lib/skill-learning.js +103 -85
- package/dist/lib/store.js +234 -73
- package/dist/lib/tasks.js +111 -22
- package/dist/lib/tmux-routing.js +120 -31
- package/dist/lib/token-spend.js +273 -0
- package/dist/lib/ws-client.js +11 -0
- package/dist/mcp/server.js +5222 -475
- package/dist/mcp/tools/complete-reminder.js +94 -77
- package/dist/mcp/tools/create-reminder.js +94 -77
- package/dist/mcp/tools/create-task.js +120 -22
- package/dist/mcp/tools/deactivate-behavior.js +95 -77
- package/dist/mcp/tools/list-reminders.js +94 -77
- package/dist/mcp/tools/list-tasks.js +31 -1
- package/dist/mcp/tools/send-message.js +8 -1
- package/dist/mcp/tools/update-task.js +39 -10
- package/dist/runtime/index.js +911 -219
- package/dist/tui/App.js +997 -295
- package/package.json +6 -1
|
@@ -493,6 +493,443 @@ var init_db_retry = __esm({
|
|
|
493
493
|
}
|
|
494
494
|
});
|
|
495
495
|
|
|
496
|
+
// src/lib/exe-daemon-client.ts
|
|
497
|
+
import net from "net";
|
|
498
|
+
import { spawn } from "child_process";
|
|
499
|
+
import { randomUUID } from "crypto";
|
|
500
|
+
import { existsSync as existsSync4, unlinkSync as unlinkSync3, readFileSync as readFileSync5, openSync, closeSync, statSync } from "fs";
|
|
501
|
+
import path6 from "path";
|
|
502
|
+
import { fileURLToPath } from "url";
|
|
503
|
+
function handleData(chunk) {
|
|
504
|
+
_buffer += chunk.toString();
|
|
505
|
+
if (_buffer.length > MAX_BUFFER) {
|
|
506
|
+
_buffer = "";
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
let newlineIdx;
|
|
510
|
+
while ((newlineIdx = _buffer.indexOf("\n")) !== -1) {
|
|
511
|
+
const line = _buffer.slice(0, newlineIdx).trim();
|
|
512
|
+
_buffer = _buffer.slice(newlineIdx + 1);
|
|
513
|
+
if (!line) continue;
|
|
514
|
+
try {
|
|
515
|
+
const response = JSON.parse(line);
|
|
516
|
+
const id = response.id;
|
|
517
|
+
if (!id) continue;
|
|
518
|
+
const entry = _pending.get(id);
|
|
519
|
+
if (entry) {
|
|
520
|
+
clearTimeout(entry.timer);
|
|
521
|
+
_pending.delete(id);
|
|
522
|
+
entry.resolve(response);
|
|
523
|
+
}
|
|
524
|
+
} catch {
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
function cleanupStaleFiles() {
|
|
529
|
+
if (existsSync4(PID_PATH)) {
|
|
530
|
+
try {
|
|
531
|
+
const pid = parseInt(readFileSync5(PID_PATH, "utf8").trim(), 10);
|
|
532
|
+
if (pid > 0) {
|
|
533
|
+
try {
|
|
534
|
+
process.kill(pid, 0);
|
|
535
|
+
return;
|
|
536
|
+
} catch {
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
} catch {
|
|
540
|
+
}
|
|
541
|
+
try {
|
|
542
|
+
unlinkSync3(PID_PATH);
|
|
543
|
+
} catch {
|
|
544
|
+
}
|
|
545
|
+
try {
|
|
546
|
+
unlinkSync3(SOCKET_PATH);
|
|
547
|
+
} catch {
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
function findPackageRoot() {
|
|
552
|
+
let dir = path6.dirname(fileURLToPath(import.meta.url));
|
|
553
|
+
const { root } = path6.parse(dir);
|
|
554
|
+
while (dir !== root) {
|
|
555
|
+
if (existsSync4(path6.join(dir, "package.json"))) return dir;
|
|
556
|
+
dir = path6.dirname(dir);
|
|
557
|
+
}
|
|
558
|
+
return null;
|
|
559
|
+
}
|
|
560
|
+
function spawnDaemon() {
|
|
561
|
+
const pkgRoot = findPackageRoot();
|
|
562
|
+
if (!pkgRoot) {
|
|
563
|
+
process.stderr.write("[exed-client] WARN: cannot find package root\n");
|
|
564
|
+
return;
|
|
565
|
+
}
|
|
566
|
+
const daemonPath = path6.join(pkgRoot, "dist", "lib", "exe-daemon.js");
|
|
567
|
+
if (!existsSync4(daemonPath)) {
|
|
568
|
+
process.stderr.write(`[exed-client] WARN: daemon script not found at ${daemonPath}
|
|
569
|
+
`);
|
|
570
|
+
return;
|
|
571
|
+
}
|
|
572
|
+
const resolvedPath = daemonPath;
|
|
573
|
+
process.stderr.write(`[exed-client] Spawning daemon: ${resolvedPath}
|
|
574
|
+
`);
|
|
575
|
+
const logPath = path6.join(path6.dirname(SOCKET_PATH), "exed.log");
|
|
576
|
+
let stderrFd = "ignore";
|
|
577
|
+
try {
|
|
578
|
+
stderrFd = openSync(logPath, "a");
|
|
579
|
+
} catch {
|
|
580
|
+
}
|
|
581
|
+
const child = spawn(process.execPath, [resolvedPath], {
|
|
582
|
+
detached: true,
|
|
583
|
+
stdio: ["ignore", "ignore", stderrFd],
|
|
584
|
+
env: {
|
|
585
|
+
...process.env,
|
|
586
|
+
TMUX: void 0,
|
|
587
|
+
// Daemon is global — must not inherit session scope
|
|
588
|
+
TMUX_PANE: void 0,
|
|
589
|
+
// Prevents resolveExeSession() from scoping to one session
|
|
590
|
+
EXE_DAEMON_SOCK: SOCKET_PATH,
|
|
591
|
+
EXE_DAEMON_PID: PID_PATH
|
|
592
|
+
}
|
|
593
|
+
});
|
|
594
|
+
child.unref();
|
|
595
|
+
if (typeof stderrFd === "number") {
|
|
596
|
+
try {
|
|
597
|
+
closeSync(stderrFd);
|
|
598
|
+
} catch {
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
function acquireSpawnLock() {
|
|
603
|
+
try {
|
|
604
|
+
const fd = openSync(SPAWN_LOCK_PATH, "wx");
|
|
605
|
+
closeSync(fd);
|
|
606
|
+
return true;
|
|
607
|
+
} catch {
|
|
608
|
+
try {
|
|
609
|
+
const stat = statSync(SPAWN_LOCK_PATH);
|
|
610
|
+
if (Date.now() - stat.mtimeMs > SPAWN_LOCK_STALE_MS) {
|
|
611
|
+
try {
|
|
612
|
+
unlinkSync3(SPAWN_LOCK_PATH);
|
|
613
|
+
} catch {
|
|
614
|
+
}
|
|
615
|
+
try {
|
|
616
|
+
const fd = openSync(SPAWN_LOCK_PATH, "wx");
|
|
617
|
+
closeSync(fd);
|
|
618
|
+
return true;
|
|
619
|
+
} catch {
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
} catch {
|
|
623
|
+
}
|
|
624
|
+
return false;
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
function releaseSpawnLock() {
|
|
628
|
+
try {
|
|
629
|
+
unlinkSync3(SPAWN_LOCK_PATH);
|
|
630
|
+
} catch {
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
function connectToSocket() {
|
|
634
|
+
return new Promise((resolve) => {
|
|
635
|
+
if (_socket && _connected) {
|
|
636
|
+
resolve(true);
|
|
637
|
+
return;
|
|
638
|
+
}
|
|
639
|
+
const socket = net.createConnection({ path: SOCKET_PATH });
|
|
640
|
+
const connectTimeout = setTimeout(() => {
|
|
641
|
+
socket.destroy();
|
|
642
|
+
resolve(false);
|
|
643
|
+
}, 2e3);
|
|
644
|
+
socket.on("connect", () => {
|
|
645
|
+
clearTimeout(connectTimeout);
|
|
646
|
+
_socket = socket;
|
|
647
|
+
_connected = true;
|
|
648
|
+
_buffer = "";
|
|
649
|
+
socket.on("data", handleData);
|
|
650
|
+
socket.on("close", () => {
|
|
651
|
+
_connected = false;
|
|
652
|
+
_socket = null;
|
|
653
|
+
for (const [id, entry] of _pending) {
|
|
654
|
+
clearTimeout(entry.timer);
|
|
655
|
+
_pending.delete(id);
|
|
656
|
+
entry.resolve({ error: "Connection closed" });
|
|
657
|
+
}
|
|
658
|
+
});
|
|
659
|
+
socket.on("error", () => {
|
|
660
|
+
_connected = false;
|
|
661
|
+
_socket = null;
|
|
662
|
+
});
|
|
663
|
+
resolve(true);
|
|
664
|
+
});
|
|
665
|
+
socket.on("error", () => {
|
|
666
|
+
clearTimeout(connectTimeout);
|
|
667
|
+
resolve(false);
|
|
668
|
+
});
|
|
669
|
+
});
|
|
670
|
+
}
|
|
671
|
+
async function connectEmbedDaemon() {
|
|
672
|
+
if (_socket && _connected) return true;
|
|
673
|
+
if (await connectToSocket()) return true;
|
|
674
|
+
if (acquireSpawnLock()) {
|
|
675
|
+
try {
|
|
676
|
+
cleanupStaleFiles();
|
|
677
|
+
spawnDaemon();
|
|
678
|
+
} finally {
|
|
679
|
+
releaseSpawnLock();
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
const start = Date.now();
|
|
683
|
+
let delay2 = 100;
|
|
684
|
+
while (Date.now() - start < CONNECT_TIMEOUT_MS) {
|
|
685
|
+
await new Promise((r) => setTimeout(r, delay2));
|
|
686
|
+
if (await connectToSocket()) return true;
|
|
687
|
+
delay2 = Math.min(delay2 * 2, 3e3);
|
|
688
|
+
}
|
|
689
|
+
return false;
|
|
690
|
+
}
|
|
691
|
+
function sendDaemonRequest(payload, timeoutMs = REQUEST_TIMEOUT_MS) {
|
|
692
|
+
return new Promise((resolve) => {
|
|
693
|
+
if (!_socket || !_connected) {
|
|
694
|
+
resolve({ error: "Not connected" });
|
|
695
|
+
return;
|
|
696
|
+
}
|
|
697
|
+
const id = randomUUID();
|
|
698
|
+
const timer = setTimeout(() => {
|
|
699
|
+
_pending.delete(id);
|
|
700
|
+
resolve({ error: "Request timeout" });
|
|
701
|
+
}, timeoutMs);
|
|
702
|
+
_pending.set(id, { resolve, timer });
|
|
703
|
+
try {
|
|
704
|
+
_socket.write(JSON.stringify({ id, ...payload }) + "\n");
|
|
705
|
+
} catch {
|
|
706
|
+
clearTimeout(timer);
|
|
707
|
+
_pending.delete(id);
|
|
708
|
+
resolve({ error: "Write failed" });
|
|
709
|
+
}
|
|
710
|
+
});
|
|
711
|
+
}
|
|
712
|
+
function isClientConnected() {
|
|
713
|
+
return _connected;
|
|
714
|
+
}
|
|
715
|
+
var SOCKET_PATH, PID_PATH, SPAWN_LOCK_PATH, SPAWN_LOCK_STALE_MS, CONNECT_TIMEOUT_MS, REQUEST_TIMEOUT_MS, _socket, _connected, _buffer, _pending, MAX_BUFFER;
|
|
716
|
+
var init_exe_daemon_client = __esm({
|
|
717
|
+
"src/lib/exe-daemon-client.ts"() {
|
|
718
|
+
"use strict";
|
|
719
|
+
init_config();
|
|
720
|
+
SOCKET_PATH = process.env.EXE_DAEMON_SOCK ?? process.env.EXE_EMBED_SOCK ?? path6.join(EXE_AI_DIR, "exed.sock");
|
|
721
|
+
PID_PATH = process.env.EXE_DAEMON_PID ?? process.env.EXE_EMBED_PID ?? path6.join(EXE_AI_DIR, "exed.pid");
|
|
722
|
+
SPAWN_LOCK_PATH = path6.join(EXE_AI_DIR, "exed-spawn.lock");
|
|
723
|
+
SPAWN_LOCK_STALE_MS = 3e4;
|
|
724
|
+
CONNECT_TIMEOUT_MS = 15e3;
|
|
725
|
+
REQUEST_TIMEOUT_MS = 3e4;
|
|
726
|
+
_socket = null;
|
|
727
|
+
_connected = false;
|
|
728
|
+
_buffer = "";
|
|
729
|
+
_pending = /* @__PURE__ */ new Map();
|
|
730
|
+
MAX_BUFFER = 1e7;
|
|
731
|
+
}
|
|
732
|
+
});
|
|
733
|
+
|
|
734
|
+
// src/lib/daemon-protocol.ts
|
|
735
|
+
function serializeValue(v) {
|
|
736
|
+
if (v === null || v === void 0) return null;
|
|
737
|
+
if (typeof v === "bigint") return Number(v);
|
|
738
|
+
if (typeof v === "boolean") return v ? 1 : 0;
|
|
739
|
+
if (v instanceof Uint8Array) {
|
|
740
|
+
return { __blob: Buffer.from(v).toString("base64") };
|
|
741
|
+
}
|
|
742
|
+
if (ArrayBuffer.isView(v)) {
|
|
743
|
+
return { __blob: Buffer.from(v.buffer, v.byteOffset, v.byteLength).toString("base64") };
|
|
744
|
+
}
|
|
745
|
+
if (v instanceof ArrayBuffer) {
|
|
746
|
+
return { __blob: Buffer.from(v).toString("base64") };
|
|
747
|
+
}
|
|
748
|
+
if (typeof v === "string" || typeof v === "number") return v;
|
|
749
|
+
return String(v);
|
|
750
|
+
}
|
|
751
|
+
function deserializeValue(v) {
|
|
752
|
+
if (v === null) return null;
|
|
753
|
+
if (typeof v === "object" && v !== null && "__blob" in v) {
|
|
754
|
+
const buf = Buffer.from(v.__blob, "base64");
|
|
755
|
+
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
|
|
756
|
+
}
|
|
757
|
+
return v;
|
|
758
|
+
}
|
|
759
|
+
function deserializeResultSet(srs) {
|
|
760
|
+
const rows = srs.rows.map((obj) => {
|
|
761
|
+
const values = srs.columns.map(
|
|
762
|
+
(col) => deserializeValue(obj[col] ?? null)
|
|
763
|
+
);
|
|
764
|
+
const row = values;
|
|
765
|
+
for (let i = 0; i < srs.columns.length; i++) {
|
|
766
|
+
const col = srs.columns[i];
|
|
767
|
+
if (col !== void 0) {
|
|
768
|
+
row[col] = values[i] ?? null;
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
Object.defineProperty(row, "length", {
|
|
772
|
+
value: values.length,
|
|
773
|
+
enumerable: false
|
|
774
|
+
});
|
|
775
|
+
return row;
|
|
776
|
+
});
|
|
777
|
+
return {
|
|
778
|
+
columns: srs.columns,
|
|
779
|
+
columnTypes: srs.columnTypes ?? [],
|
|
780
|
+
rows,
|
|
781
|
+
rowsAffected: srs.rowsAffected,
|
|
782
|
+
lastInsertRowid: srs.lastInsertRowid != null ? BigInt(srs.lastInsertRowid) : void 0,
|
|
783
|
+
toJSON: () => ({
|
|
784
|
+
columns: srs.columns,
|
|
785
|
+
columnTypes: srs.columnTypes ?? [],
|
|
786
|
+
rows: srs.rows,
|
|
787
|
+
rowsAffected: srs.rowsAffected,
|
|
788
|
+
lastInsertRowid: srs.lastInsertRowid
|
|
789
|
+
})
|
|
790
|
+
};
|
|
791
|
+
}
|
|
792
|
+
var init_daemon_protocol = __esm({
|
|
793
|
+
"src/lib/daemon-protocol.ts"() {
|
|
794
|
+
"use strict";
|
|
795
|
+
}
|
|
796
|
+
});
|
|
797
|
+
|
|
798
|
+
// src/lib/db-daemon-client.ts
|
|
799
|
+
var db_daemon_client_exports = {};
|
|
800
|
+
__export(db_daemon_client_exports, {
|
|
801
|
+
createDaemonDbClient: () => createDaemonDbClient,
|
|
802
|
+
initDaemonDbClient: () => initDaemonDbClient
|
|
803
|
+
});
|
|
804
|
+
function normalizeStatement(stmt) {
|
|
805
|
+
if (typeof stmt === "string") {
|
|
806
|
+
return { sql: stmt, args: [] };
|
|
807
|
+
}
|
|
808
|
+
const sql = stmt.sql;
|
|
809
|
+
let args = [];
|
|
810
|
+
if (Array.isArray(stmt.args)) {
|
|
811
|
+
args = stmt.args.map((v) => serializeValue(v));
|
|
812
|
+
} else if (stmt.args && typeof stmt.args === "object") {
|
|
813
|
+
const named = {};
|
|
814
|
+
for (const [key, val] of Object.entries(stmt.args)) {
|
|
815
|
+
named[key] = serializeValue(val);
|
|
816
|
+
}
|
|
817
|
+
return { sql, args: named };
|
|
818
|
+
}
|
|
819
|
+
return { sql, args };
|
|
820
|
+
}
|
|
821
|
+
function createDaemonDbClient(fallbackClient) {
|
|
822
|
+
let _useDaemon = false;
|
|
823
|
+
const client = {
|
|
824
|
+
async execute(stmt) {
|
|
825
|
+
if (!_useDaemon || !isClientConnected()) {
|
|
826
|
+
return fallbackClient.execute(stmt);
|
|
827
|
+
}
|
|
828
|
+
const { sql, args } = normalizeStatement(stmt);
|
|
829
|
+
const response = await sendDaemonRequest({
|
|
830
|
+
type: "db-execute",
|
|
831
|
+
sql,
|
|
832
|
+
args
|
|
833
|
+
});
|
|
834
|
+
if (response.error) {
|
|
835
|
+
const errMsg = String(response.error);
|
|
836
|
+
if (errMsg === "Not connected" || errMsg === "Request timeout" || errMsg === "Write failed") {
|
|
837
|
+
process.stderr.write(`[db-daemon] Transport error (${errMsg}), falling back to direct
|
|
838
|
+
`);
|
|
839
|
+
return fallbackClient.execute(stmt);
|
|
840
|
+
}
|
|
841
|
+
throw new Error(errMsg);
|
|
842
|
+
}
|
|
843
|
+
if (response.db) {
|
|
844
|
+
return deserializeResultSet(response.db);
|
|
845
|
+
}
|
|
846
|
+
process.stderr.write("[db-daemon] Unexpected response shape, falling back to direct\n");
|
|
847
|
+
return fallbackClient.execute(stmt);
|
|
848
|
+
},
|
|
849
|
+
async batch(stmts, mode) {
|
|
850
|
+
if (!_useDaemon || !isClientConnected()) {
|
|
851
|
+
return fallbackClient.batch(stmts, mode);
|
|
852
|
+
}
|
|
853
|
+
const statements = stmts.map(normalizeStatement);
|
|
854
|
+
const response = await sendDaemonRequest({
|
|
855
|
+
type: "db-batch",
|
|
856
|
+
statements,
|
|
857
|
+
mode: mode ?? "deferred"
|
|
858
|
+
});
|
|
859
|
+
if (response.error) {
|
|
860
|
+
const errMsg = String(response.error);
|
|
861
|
+
if (errMsg === "Not connected" || errMsg === "Request timeout" || errMsg === "Write failed") {
|
|
862
|
+
process.stderr.write(`[db-daemon] Batch transport error (${errMsg}), falling back to direct
|
|
863
|
+
`);
|
|
864
|
+
return fallbackClient.batch(stmts, mode);
|
|
865
|
+
}
|
|
866
|
+
throw new Error(errMsg);
|
|
867
|
+
}
|
|
868
|
+
const batchResults = response["db-batch"];
|
|
869
|
+
if (batchResults) {
|
|
870
|
+
return batchResults.map(deserializeResultSet);
|
|
871
|
+
}
|
|
872
|
+
process.stderr.write("[db-daemon] Unexpected batch response shape, falling back to direct\n");
|
|
873
|
+
return fallbackClient.batch(stmts, mode);
|
|
874
|
+
},
|
|
875
|
+
// Transaction support — delegate to fallback (transactions need direct connection)
|
|
876
|
+
async transaction(mode) {
|
|
877
|
+
return fallbackClient.transaction(mode);
|
|
878
|
+
},
|
|
879
|
+
// executeMultiple — delegate to fallback (used only for schema migrations)
|
|
880
|
+
async executeMultiple(sql) {
|
|
881
|
+
return fallbackClient.executeMultiple(sql);
|
|
882
|
+
},
|
|
883
|
+
// migrate — delegate to fallback
|
|
884
|
+
async migrate(stmts) {
|
|
885
|
+
return fallbackClient.migrate(stmts);
|
|
886
|
+
},
|
|
887
|
+
// Sync mode — delegate to fallback
|
|
888
|
+
sync() {
|
|
889
|
+
return fallbackClient.sync();
|
|
890
|
+
},
|
|
891
|
+
close() {
|
|
892
|
+
_useDaemon = false;
|
|
893
|
+
},
|
|
894
|
+
get closed() {
|
|
895
|
+
return fallbackClient.closed;
|
|
896
|
+
},
|
|
897
|
+
get protocol() {
|
|
898
|
+
return fallbackClient.protocol;
|
|
899
|
+
}
|
|
900
|
+
};
|
|
901
|
+
return {
|
|
902
|
+
...client,
|
|
903
|
+
/** Enable daemon routing (call after confirming daemon is connected) */
|
|
904
|
+
_enableDaemon() {
|
|
905
|
+
_useDaemon = true;
|
|
906
|
+
},
|
|
907
|
+
/** Check if daemon routing is active */
|
|
908
|
+
_isDaemonActive() {
|
|
909
|
+
return _useDaemon && isClientConnected();
|
|
910
|
+
}
|
|
911
|
+
};
|
|
912
|
+
}
|
|
913
|
+
async function initDaemonDbClient(fallbackClient) {
|
|
914
|
+
if (process.env.EXE_IS_DAEMON === "1") return null;
|
|
915
|
+
const connected = await connectEmbedDaemon();
|
|
916
|
+
if (!connected) {
|
|
917
|
+
process.stderr.write("[db-daemon] Daemon unavailable \u2014 using direct SQLite\n");
|
|
918
|
+
return null;
|
|
919
|
+
}
|
|
920
|
+
const client = createDaemonDbClient(fallbackClient);
|
|
921
|
+
client._enableDaemon();
|
|
922
|
+
process.stderr.write("[db-daemon] DB routing through daemon (single-writer)\n");
|
|
923
|
+
return client;
|
|
924
|
+
}
|
|
925
|
+
var init_db_daemon_client = __esm({
|
|
926
|
+
"src/lib/db-daemon-client.ts"() {
|
|
927
|
+
"use strict";
|
|
928
|
+
init_exe_daemon_client();
|
|
929
|
+
init_daemon_protocol();
|
|
930
|
+
}
|
|
931
|
+
});
|
|
932
|
+
|
|
496
933
|
// src/lib/database.ts
|
|
497
934
|
var database_exports = {};
|
|
498
935
|
__export(database_exports, {
|
|
@@ -501,6 +938,7 @@ __export(database_exports, {
|
|
|
501
938
|
ensureSchema: () => ensureSchema,
|
|
502
939
|
getClient: () => getClient,
|
|
503
940
|
getRawClient: () => getRawClient,
|
|
941
|
+
initDaemonClient: () => initDaemonClient,
|
|
504
942
|
initDatabase: () => initDatabase,
|
|
505
943
|
initTurso: () => initTurso,
|
|
506
944
|
isInitialized: () => isInitialized
|
|
@@ -528,8 +966,27 @@ function getClient() {
|
|
|
528
966
|
if (!_resilientClient) {
|
|
529
967
|
throw new Error("Database client not initialized. Call initDatabase() first.");
|
|
530
968
|
}
|
|
969
|
+
if (process.env.EXE_IS_DAEMON === "1") {
|
|
970
|
+
return _resilientClient;
|
|
971
|
+
}
|
|
972
|
+
if (_daemonClient && _daemonClient._isDaemonActive()) {
|
|
973
|
+
return _daemonClient;
|
|
974
|
+
}
|
|
531
975
|
return _resilientClient;
|
|
532
976
|
}
|
|
977
|
+
async function initDaemonClient() {
|
|
978
|
+
if (process.env.EXE_IS_DAEMON === "1") return;
|
|
979
|
+
if (!_resilientClient) return;
|
|
980
|
+
try {
|
|
981
|
+
const { initDaemonDbClient: initDaemonDbClient2 } = await Promise.resolve().then(() => (init_db_daemon_client(), db_daemon_client_exports));
|
|
982
|
+
_daemonClient = await initDaemonDbClient2(_resilientClient);
|
|
983
|
+
} catch (err) {
|
|
984
|
+
process.stderr.write(
|
|
985
|
+
`[database] Daemon client init failed (non-fatal): ${err instanceof Error ? err.message : String(err)}
|
|
986
|
+
`
|
|
987
|
+
);
|
|
988
|
+
}
|
|
989
|
+
}
|
|
533
990
|
function getRawClient() {
|
|
534
991
|
if (!_client) {
|
|
535
992
|
throw new Error("Database client not initialized. Call initDatabase() first.");
|
|
@@ -1016,6 +1473,12 @@ async function ensureSchema() {
|
|
|
1016
1473
|
} catch {
|
|
1017
1474
|
}
|
|
1018
1475
|
}
|
|
1476
|
+
try {
|
|
1477
|
+
await client.execute(
|
|
1478
|
+
`CREATE INDEX IF NOT EXISTS idx_memories_content_hash ON memories(content_hash, agent_id)`
|
|
1479
|
+
);
|
|
1480
|
+
} catch {
|
|
1481
|
+
}
|
|
1019
1482
|
await client.executeMultiple(`
|
|
1020
1483
|
CREATE TABLE IF NOT EXISTS entities (
|
|
1021
1484
|
id TEXT PRIMARY KEY,
|
|
@@ -1068,7 +1531,30 @@ async function ensureSchema() {
|
|
|
1068
1531
|
entity_id TEXT NOT NULL,
|
|
1069
1532
|
PRIMARY KEY (hyperedge_id, entity_id)
|
|
1070
1533
|
);
|
|
1534
|
+
|
|
1535
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS entities_fts USING fts5(
|
|
1536
|
+
name,
|
|
1537
|
+
content=entities,
|
|
1538
|
+
content_rowid=rowid
|
|
1539
|
+
);
|
|
1540
|
+
|
|
1541
|
+
CREATE TRIGGER IF NOT EXISTS entities_fts_ai AFTER INSERT ON entities BEGIN
|
|
1542
|
+
INSERT INTO entities_fts(rowid, name) VALUES (new.rowid, new.name);
|
|
1543
|
+
END;
|
|
1544
|
+
|
|
1545
|
+
CREATE TRIGGER IF NOT EXISTS entities_fts_ad AFTER DELETE ON entities BEGIN
|
|
1546
|
+
INSERT INTO entities_fts(entities_fts, rowid, name) VALUES('delete', old.rowid, old.name);
|
|
1547
|
+
END;
|
|
1548
|
+
|
|
1549
|
+
CREATE TRIGGER IF NOT EXISTS entities_fts_au AFTER UPDATE ON entities BEGIN
|
|
1550
|
+
INSERT INTO entities_fts(entities_fts, rowid, name) VALUES('delete', old.rowid, old.name);
|
|
1551
|
+
INSERT INTO entities_fts(rowid, name) VALUES (new.rowid, new.name);
|
|
1552
|
+
END;
|
|
1071
1553
|
`);
|
|
1554
|
+
try {
|
|
1555
|
+
await client.execute("INSERT INTO entities_fts(entities_fts) VALUES('rebuild')");
|
|
1556
|
+
} catch {
|
|
1557
|
+
}
|
|
1072
1558
|
await client.executeMultiple(`
|
|
1073
1559
|
CREATE TABLE IF NOT EXISTS entity_aliases (
|
|
1074
1560
|
alias TEXT NOT NULL PRIMARY KEY,
|
|
@@ -1249,6 +1735,33 @@ async function ensureSchema() {
|
|
|
1249
1735
|
CREATE INDEX IF NOT EXISTS idx_conversations_channel
|
|
1250
1736
|
ON conversations(channel_id);
|
|
1251
1737
|
`);
|
|
1738
|
+
await client.executeMultiple(`
|
|
1739
|
+
CREATE TABLE IF NOT EXISTS session_agent_map (
|
|
1740
|
+
session_uuid TEXT PRIMARY KEY,
|
|
1741
|
+
agent_id TEXT NOT NULL,
|
|
1742
|
+
session_name TEXT,
|
|
1743
|
+
task_id TEXT,
|
|
1744
|
+
project_name TEXT,
|
|
1745
|
+
started_at TEXT NOT NULL
|
|
1746
|
+
);
|
|
1747
|
+
|
|
1748
|
+
CREATE INDEX IF NOT EXISTS idx_session_agent_map_agent
|
|
1749
|
+
ON session_agent_map(agent_id);
|
|
1750
|
+
`);
|
|
1751
|
+
try {
|
|
1752
|
+
const mapCount = await client.execute({ sql: `SELECT COUNT(*) as cnt FROM session_agent_map`, args: [] });
|
|
1753
|
+
if (Number(mapCount.rows[0]?.cnt ?? 0) === 0) {
|
|
1754
|
+
await client.execute({
|
|
1755
|
+
sql: `INSERT OR IGNORE INTO session_agent_map (session_uuid, agent_id, session_name, started_at)
|
|
1756
|
+
SELECT session_id, agent_id, '', MIN(timestamp)
|
|
1757
|
+
FROM memories
|
|
1758
|
+
WHERE session_id IS NOT NULL AND session_id != '' AND agent_id IS NOT NULL AND agent_id != ''
|
|
1759
|
+
GROUP BY session_id, agent_id`,
|
|
1760
|
+
args: []
|
|
1761
|
+
});
|
|
1762
|
+
}
|
|
1763
|
+
} catch {
|
|
1764
|
+
}
|
|
1252
1765
|
try {
|
|
1253
1766
|
await client.execute({
|
|
1254
1767
|
sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
|
|
@@ -1382,15 +1895,41 @@ async function ensureSchema() {
|
|
|
1382
1895
|
});
|
|
1383
1896
|
} catch {
|
|
1384
1897
|
}
|
|
1898
|
+
for (const col of [
|
|
1899
|
+
"ALTER TABLE memories ADD COLUMN intent TEXT",
|
|
1900
|
+
"ALTER TABLE memories ADD COLUMN outcome TEXT",
|
|
1901
|
+
"ALTER TABLE memories ADD COLUMN domain TEXT",
|
|
1902
|
+
"ALTER TABLE memories ADD COLUMN referenced_entities TEXT",
|
|
1903
|
+
"ALTER TABLE memories ADD COLUMN retrieval_count INTEGER DEFAULT 0",
|
|
1904
|
+
"ALTER TABLE memories ADD COLUMN chain_position TEXT",
|
|
1905
|
+
"ALTER TABLE memories ADD COLUMN review_status TEXT",
|
|
1906
|
+
"ALTER TABLE memories ADD COLUMN context_window_pct INTEGER",
|
|
1907
|
+
"ALTER TABLE memories ADD COLUMN file_paths TEXT",
|
|
1908
|
+
"ALTER TABLE memories ADD COLUMN commit_hash TEXT",
|
|
1909
|
+
"ALTER TABLE memories ADD COLUMN duration_ms INTEGER",
|
|
1910
|
+
"ALTER TABLE memories ADD COLUMN token_cost REAL",
|
|
1911
|
+
"ALTER TABLE memories ADD COLUMN audience TEXT",
|
|
1912
|
+
"ALTER TABLE memories ADD COLUMN language_type TEXT",
|
|
1913
|
+
"ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
|
|
1914
|
+
]) {
|
|
1915
|
+
try {
|
|
1916
|
+
await client.execute(col);
|
|
1917
|
+
} catch {
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1385
1920
|
}
|
|
1386
1921
|
async function disposeDatabase() {
|
|
1922
|
+
if (_daemonClient) {
|
|
1923
|
+
_daemonClient.close();
|
|
1924
|
+
_daemonClient = null;
|
|
1925
|
+
}
|
|
1387
1926
|
if (_client) {
|
|
1388
1927
|
_client.close();
|
|
1389
1928
|
_client = null;
|
|
1390
1929
|
_resilientClient = null;
|
|
1391
1930
|
}
|
|
1392
1931
|
}
|
|
1393
|
-
var _client, _resilientClient, initTurso, disposeTurso;
|
|
1932
|
+
var _client, _resilientClient, _daemonClient, initTurso, disposeTurso;
|
|
1394
1933
|
var init_database = __esm({
|
|
1395
1934
|
"src/lib/database.ts"() {
|
|
1396
1935
|
"use strict";
|
|
@@ -1398,30 +1937,31 @@ var init_database = __esm({
|
|
|
1398
1937
|
init_employees();
|
|
1399
1938
|
_client = null;
|
|
1400
1939
|
_resilientClient = null;
|
|
1940
|
+
_daemonClient = null;
|
|
1401
1941
|
initTurso = initDatabase;
|
|
1402
1942
|
disposeTurso = disposeDatabase;
|
|
1403
1943
|
}
|
|
1404
1944
|
});
|
|
1405
1945
|
|
|
1406
1946
|
// src/lib/license.ts
|
|
1407
|
-
import { readFileSync as
|
|
1408
|
-
import { randomUUID } from "crypto";
|
|
1409
|
-
import
|
|
1947
|
+
import { readFileSync as readFileSync6, writeFileSync as writeFileSync4, existsSync as existsSync5, mkdirSync as mkdirSync3 } from "fs";
|
|
1948
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
1949
|
+
import path7 from "path";
|
|
1410
1950
|
import { jwtVerify, importSPKI } from "jose";
|
|
1411
1951
|
var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH;
|
|
1412
1952
|
var init_license = __esm({
|
|
1413
1953
|
"src/lib/license.ts"() {
|
|
1414
1954
|
"use strict";
|
|
1415
1955
|
init_config();
|
|
1416
|
-
LICENSE_PATH =
|
|
1417
|
-
CACHE_PATH =
|
|
1418
|
-
DEVICE_ID_PATH =
|
|
1956
|
+
LICENSE_PATH = path7.join(EXE_AI_DIR, "license.key");
|
|
1957
|
+
CACHE_PATH = path7.join(EXE_AI_DIR, "license-cache.json");
|
|
1958
|
+
DEVICE_ID_PATH = path7.join(EXE_AI_DIR, "device-id");
|
|
1419
1959
|
}
|
|
1420
1960
|
});
|
|
1421
1961
|
|
|
1422
1962
|
// src/lib/plan-limits.ts
|
|
1423
|
-
import { readFileSync as
|
|
1424
|
-
import
|
|
1963
|
+
import { readFileSync as readFileSync7, existsSync as existsSync6 } from "fs";
|
|
1964
|
+
import path8 from "path";
|
|
1425
1965
|
var CACHE_PATH2;
|
|
1426
1966
|
var init_plan_limits = __esm({
|
|
1427
1967
|
"src/lib/plan-limits.ts"() {
|
|
@@ -1430,15 +1970,15 @@ var init_plan_limits = __esm({
|
|
|
1430
1970
|
init_employees();
|
|
1431
1971
|
init_license();
|
|
1432
1972
|
init_config();
|
|
1433
|
-
CACHE_PATH2 =
|
|
1973
|
+
CACHE_PATH2 = path8.join(EXE_AI_DIR, "license-cache.json");
|
|
1434
1974
|
}
|
|
1435
1975
|
});
|
|
1436
1976
|
|
|
1437
1977
|
// src/lib/tmux-routing.ts
|
|
1438
|
-
import { readFileSync as
|
|
1439
|
-
import
|
|
1978
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync5, mkdirSync as mkdirSync4, existsSync as existsSync7, appendFileSync } from "fs";
|
|
1979
|
+
import path9 from "path";
|
|
1440
1980
|
import os5 from "os";
|
|
1441
|
-
import { fileURLToPath } from "url";
|
|
1981
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
1442
1982
|
function getMySession() {
|
|
1443
1983
|
return getTransport().getMySession();
|
|
1444
1984
|
}
|
|
@@ -1450,7 +1990,7 @@ function extractRootExe(name) {
|
|
|
1450
1990
|
}
|
|
1451
1991
|
function getParentExe(sessionKey) {
|
|
1452
1992
|
try {
|
|
1453
|
-
const data = JSON.parse(
|
|
1993
|
+
const data = JSON.parse(readFileSync8(path9.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
|
|
1454
1994
|
return data.parentExe || null;
|
|
1455
1995
|
} catch {
|
|
1456
1996
|
return null;
|
|
@@ -1482,10 +2022,10 @@ var init_tmux_routing = __esm({
|
|
|
1482
2022
|
init_intercom_queue();
|
|
1483
2023
|
init_plan_limits();
|
|
1484
2024
|
init_employees();
|
|
1485
|
-
SPAWN_LOCK_DIR =
|
|
1486
|
-
SESSION_CACHE =
|
|
1487
|
-
INTERCOM_LOG2 =
|
|
1488
|
-
DEBOUNCE_FILE =
|
|
2025
|
+
SPAWN_LOCK_DIR = path9.join(os5.homedir(), ".exe-os", "spawn-locks");
|
|
2026
|
+
SESSION_CACHE = path9.join(os5.homedir(), ".exe-os", "session-cache");
|
|
2027
|
+
INTERCOM_LOG2 = path9.join(os5.homedir(), ".exe-os", "intercom.log");
|
|
2028
|
+
DEBOUNCE_FILE = path9.join(SESSION_CACHE, "intercom-debounce.json");
|
|
1489
2029
|
DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
|
|
1490
2030
|
}
|
|
1491
2031
|
});
|
|
@@ -1525,14 +2065,14 @@ var init_memory = __esm({
|
|
|
1525
2065
|
|
|
1526
2066
|
// src/lib/keychain.ts
|
|
1527
2067
|
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
1528
|
-
import { existsSync as
|
|
1529
|
-
import
|
|
2068
|
+
import { existsSync as existsSync8 } from "fs";
|
|
2069
|
+
import path10 from "path";
|
|
1530
2070
|
import os6 from "os";
|
|
1531
2071
|
function getKeyDir() {
|
|
1532
|
-
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ??
|
|
2072
|
+
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path10.join(os6.homedir(), ".exe-os");
|
|
1533
2073
|
}
|
|
1534
2074
|
function getKeyPath() {
|
|
1535
|
-
return
|
|
2075
|
+
return path10.join(getKeyDir(), "master.key");
|
|
1536
2076
|
}
|
|
1537
2077
|
async function tryKeytar() {
|
|
1538
2078
|
try {
|
|
@@ -1553,13 +2093,21 @@ async function getMasterKey() {
|
|
|
1553
2093
|
}
|
|
1554
2094
|
}
|
|
1555
2095
|
const keyPath = getKeyPath();
|
|
1556
|
-
if (!
|
|
2096
|
+
if (!existsSync8(keyPath)) {
|
|
2097
|
+
process.stderr.write(
|
|
2098
|
+
`[keychain] Key not found at ${keyPath} (HOME=${os6.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
|
|
2099
|
+
`
|
|
2100
|
+
);
|
|
1557
2101
|
return null;
|
|
1558
2102
|
}
|
|
1559
2103
|
try {
|
|
1560
2104
|
const content = await readFile3(keyPath, "utf-8");
|
|
1561
2105
|
return Buffer.from(content.trim(), "base64");
|
|
1562
|
-
} catch {
|
|
2106
|
+
} catch (err) {
|
|
2107
|
+
process.stderr.write(
|
|
2108
|
+
`[keychain] Key read failed at ${keyPath}: ${err instanceof Error ? err.message : String(err)}
|
|
2109
|
+
`
|
|
2110
|
+
);
|
|
1563
2111
|
return null;
|
|
1564
2112
|
}
|
|
1565
2113
|
}
|
|
@@ -1640,12 +2188,12 @@ __export(shard_manager_exports, {
|
|
|
1640
2188
|
listShards: () => listShards,
|
|
1641
2189
|
shardExists: () => shardExists
|
|
1642
2190
|
});
|
|
1643
|
-
import
|
|
1644
|
-
import { existsSync as
|
|
2191
|
+
import path11 from "path";
|
|
2192
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync5, readdirSync as readdirSync2 } from "fs";
|
|
1645
2193
|
import { createClient as createClient2 } from "@libsql/client";
|
|
1646
2194
|
function initShardManager(encryptionKey) {
|
|
1647
2195
|
_encryptionKey = encryptionKey;
|
|
1648
|
-
if (!
|
|
2196
|
+
if (!existsSync9(SHARDS_DIR)) {
|
|
1649
2197
|
mkdirSync5(SHARDS_DIR, { recursive: true });
|
|
1650
2198
|
}
|
|
1651
2199
|
_shardingEnabled = true;
|
|
@@ -1666,7 +2214,7 @@ function getShardClient(projectName) {
|
|
|
1666
2214
|
}
|
|
1667
2215
|
const cached = _shards.get(safeName);
|
|
1668
2216
|
if (cached) return cached;
|
|
1669
|
-
const dbPath =
|
|
2217
|
+
const dbPath = path11.join(SHARDS_DIR, `${safeName}.db`);
|
|
1670
2218
|
const client = createClient2({
|
|
1671
2219
|
url: `file:${dbPath}`,
|
|
1672
2220
|
encryptionKey: _encryptionKey
|
|
@@ -1676,10 +2224,10 @@ function getShardClient(projectName) {
|
|
|
1676
2224
|
}
|
|
1677
2225
|
function shardExists(projectName) {
|
|
1678
2226
|
const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
1679
|
-
return
|
|
2227
|
+
return existsSync9(path11.join(SHARDS_DIR, `${safeName}.db`));
|
|
1680
2228
|
}
|
|
1681
2229
|
function listShards() {
|
|
1682
|
-
if (!
|
|
2230
|
+
if (!existsSync9(SHARDS_DIR)) return [];
|
|
1683
2231
|
return readdirSync2(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
1684
2232
|
}
|
|
1685
2233
|
async function ensureShardSchema(client) {
|
|
@@ -1865,7 +2413,7 @@ var init_shard_manager = __esm({
|
|
|
1865
2413
|
"src/lib/shard-manager.ts"() {
|
|
1866
2414
|
"use strict";
|
|
1867
2415
|
init_config();
|
|
1868
|
-
SHARDS_DIR =
|
|
2416
|
+
SHARDS_DIR = path11.join(EXE_AI_DIR, "shards");
|
|
1869
2417
|
_shards = /* @__PURE__ */ new Map();
|
|
1870
2418
|
_encryptionKey = null;
|
|
1871
2419
|
_shardingEnabled = false;
|
|
@@ -1990,7 +2538,7 @@ __export(global_procedures_exports, {
|
|
|
1990
2538
|
loadGlobalProcedures: () => loadGlobalProcedures,
|
|
1991
2539
|
storeGlobalProcedure: () => storeGlobalProcedure
|
|
1992
2540
|
});
|
|
1993
|
-
import { randomUUID as
|
|
2541
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
1994
2542
|
async function loadGlobalProcedures() {
|
|
1995
2543
|
const client = getClient();
|
|
1996
2544
|
const result = await client.execute({
|
|
@@ -2019,7 +2567,7 @@ ${sections.join("\n\n")}
|
|
|
2019
2567
|
`;
|
|
2020
2568
|
}
|
|
2021
2569
|
async function storeGlobalProcedure(input2) {
|
|
2022
|
-
const id =
|
|
2570
|
+
const id = randomUUID3();
|
|
2023
2571
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2024
2572
|
const client = getClient();
|
|
2025
2573
|
await client.execute({
|
|
@@ -2070,6 +2618,7 @@ __export(store_exports, {
|
|
|
2070
2618
|
vectorToBlob: () => vectorToBlob,
|
|
2071
2619
|
writeMemory: () => writeMemory
|
|
2072
2620
|
});
|
|
2621
|
+
import { createHash } from "crypto";
|
|
2073
2622
|
function isBusyError2(err) {
|
|
2074
2623
|
if (err instanceof Error) {
|
|
2075
2624
|
const msg = err.message.toLowerCase();
|
|
@@ -2143,12 +2692,52 @@ function classifyTier(record) {
|
|
|
2143
2692
|
if (["store_memory", "manual"].includes(record.tool_name ?? "") && (record.importance ?? 0) >= 5) return 2;
|
|
2144
2693
|
return 3;
|
|
2145
2694
|
}
|
|
2695
|
+
function inferFilePaths(record) {
|
|
2696
|
+
if (!["Read", "Write", "Edit"].includes(record.tool_name)) return null;
|
|
2697
|
+
const firstLine = record.raw_text.split("\n")[0] ?? "";
|
|
2698
|
+
const match = firstLine.match(/(\/[\w./-]+\.\w+)/);
|
|
2699
|
+
return match ? JSON.stringify([match[1]]) : null;
|
|
2700
|
+
}
|
|
2701
|
+
function inferCommitHash(record) {
|
|
2702
|
+
if (record.tool_name !== "Bash") return null;
|
|
2703
|
+
const match = record.raw_text.match(/\b([a-f0-9]{7,40})\b/);
|
|
2704
|
+
return match ? match[1] : null;
|
|
2705
|
+
}
|
|
2706
|
+
function inferLanguageType(record) {
|
|
2707
|
+
const text = record.raw_text;
|
|
2708
|
+
if (!text || text.length < 10) return null;
|
|
2709
|
+
const trimmed = text.trimStart();
|
|
2710
|
+
if (trimmed.startsWith("{") || trimmed.startsWith("[")) return "json";
|
|
2711
|
+
if (/\b(SELECT|INSERT|UPDATE|DELETE|CREATE TABLE|ALTER TABLE)\b/i.test(text)) return "sql";
|
|
2712
|
+
if (/\b(function |const |import |export |class |def |async |=>)\b/.test(text)) return "code";
|
|
2713
|
+
if (trimmed.startsWith("#") || trimmed.startsWith("*")) return "prose";
|
|
2714
|
+
return "mixed";
|
|
2715
|
+
}
|
|
2716
|
+
function inferDomain(record) {
|
|
2717
|
+
const proj = (record.project_name ?? "").toLowerCase();
|
|
2718
|
+
if (proj.includes("marketing") || proj.includes("content")) return "marketing";
|
|
2719
|
+
if (proj.includes("crm") || proj.includes("customer")) return "customer";
|
|
2720
|
+
return null;
|
|
2721
|
+
}
|
|
2146
2722
|
async function writeMemory(record) {
|
|
2147
2723
|
if (record.vector !== null && record.vector.length !== EMBEDDING_DIM) {
|
|
2148
2724
|
throw new Error(
|
|
2149
2725
|
`Expected ${EMBEDDING_DIM}-dim vector, got ${record.vector.length}`
|
|
2150
2726
|
);
|
|
2151
2727
|
}
|
|
2728
|
+
const contentHash = createHash("md5").update(record.raw_text).digest("hex");
|
|
2729
|
+
if (_pendingRecords.some((r) => r.content_hash === contentHash && r.agent_id === record.agent_id)) {
|
|
2730
|
+
return;
|
|
2731
|
+
}
|
|
2732
|
+
try {
|
|
2733
|
+
const client = getClient();
|
|
2734
|
+
const existing = await client.execute({
|
|
2735
|
+
sql: "SELECT id FROM memories WHERE content_hash = ? AND agent_id = ? LIMIT 1",
|
|
2736
|
+
args: [contentHash, record.agent_id]
|
|
2737
|
+
});
|
|
2738
|
+
if (existing.rows.length > 0) return;
|
|
2739
|
+
} catch {
|
|
2740
|
+
}
|
|
2152
2741
|
const dbRow = {
|
|
2153
2742
|
id: record.id,
|
|
2154
2743
|
agent_id: record.agent_id,
|
|
@@ -2178,7 +2767,23 @@ async function writeMemory(record) {
|
|
|
2178
2767
|
supersedes_id: record.supersedes_id ?? null,
|
|
2179
2768
|
draft: record.draft ? 1 : 0,
|
|
2180
2769
|
memory_type: record.memory_type ?? "raw",
|
|
2181
|
-
trajectory: record.trajectory ? JSON.stringify(record.trajectory) : null
|
|
2770
|
+
trajectory: record.trajectory ? JSON.stringify(record.trajectory) : null,
|
|
2771
|
+
content_hash: contentHash,
|
|
2772
|
+
intent: record.intent ?? null,
|
|
2773
|
+
outcome: record.outcome ?? null,
|
|
2774
|
+
domain: record.domain ?? inferDomain(record),
|
|
2775
|
+
referenced_entities: record.referenced_entities ?? null,
|
|
2776
|
+
retrieval_count: record.retrieval_count ?? 0,
|
|
2777
|
+
chain_position: record.chain_position ?? null,
|
|
2778
|
+
review_status: record.review_status ?? null,
|
|
2779
|
+
context_window_pct: record.context_window_pct ?? null,
|
|
2780
|
+
file_paths: record.file_paths ?? inferFilePaths(record),
|
|
2781
|
+
commit_hash: record.commit_hash ?? inferCommitHash(record),
|
|
2782
|
+
duration_ms: record.duration_ms ?? null,
|
|
2783
|
+
token_cost: record.token_cost ?? null,
|
|
2784
|
+
audience: record.audience ?? null,
|
|
2785
|
+
language_type: record.language_type ?? inferLanguageType(record),
|
|
2786
|
+
parent_memory_id: record.parent_memory_id ?? null
|
|
2182
2787
|
};
|
|
2183
2788
|
_pendingRecords.push(dbRow);
|
|
2184
2789
|
orgBus.emit({
|
|
@@ -2236,80 +2841,85 @@ async function flushBatch() {
|
|
|
2236
2841
|
const draft = row.draft ? 1 : 0;
|
|
2237
2842
|
const memoryType = row.memory_type ?? "raw";
|
|
2238
2843
|
const trajectory = row.trajectory ?? null;
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2844
|
+
const contentHash = row.content_hash ?? null;
|
|
2845
|
+
const intent = row.intent ?? null;
|
|
2846
|
+
const outcome = row.outcome ?? null;
|
|
2847
|
+
const domain = row.domain ?? null;
|
|
2848
|
+
const referencedEntities = row.referenced_entities ?? null;
|
|
2849
|
+
const retrievalCount = row.retrieval_count ?? 0;
|
|
2850
|
+
const chainPosition = row.chain_position ?? null;
|
|
2851
|
+
const reviewStatus = row.review_status ?? null;
|
|
2852
|
+
const contextWindowPct = row.context_window_pct ?? null;
|
|
2853
|
+
const filePaths = row.file_paths ?? null;
|
|
2854
|
+
const commitHash = row.commit_hash ?? null;
|
|
2855
|
+
const durationMs = row.duration_ms ?? null;
|
|
2856
|
+
const tokenCost = row.token_cost ?? null;
|
|
2857
|
+
const audience = row.audience ?? null;
|
|
2858
|
+
const languageType = row.language_type ?? null;
|
|
2859
|
+
const parentMemoryId = row.parent_memory_id ?? null;
|
|
2860
|
+
const cols = `id, agent_id, agent_role, session_id, timestamp,
|
|
2249
2861
|
tool_name, project_name,
|
|
2250
2862
|
has_error, raw_text, vector, version, task_id, importance, status,
|
|
2251
2863
|
confidence, last_accessed,
|
|
2252
2864
|
workspace_id, document_id, user_id, char_offset, page_number,
|
|
2253
|
-
source_path, source_type, tier, supersedes_id, draft, memory_type, trajectory
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
trajectory
|
|
2312
|
-
]
|
|
2865
|
+
source_path, source_type, tier, supersedes_id, draft, memory_type, trajectory, content_hash,
|
|
2866
|
+
intent, outcome, domain, referenced_entities, retrieval_count,
|
|
2867
|
+
chain_position, review_status, context_window_pct, file_paths, commit_hash,
|
|
2868
|
+
duration_ms, token_cost, audience, language_type, parent_memory_id`;
|
|
2869
|
+
const metaArgs = [
|
|
2870
|
+
intent,
|
|
2871
|
+
outcome,
|
|
2872
|
+
domain,
|
|
2873
|
+
referencedEntities,
|
|
2874
|
+
retrievalCount,
|
|
2875
|
+
chainPosition,
|
|
2876
|
+
reviewStatus,
|
|
2877
|
+
contextWindowPct,
|
|
2878
|
+
filePaths,
|
|
2879
|
+
commitHash,
|
|
2880
|
+
durationMs,
|
|
2881
|
+
tokenCost,
|
|
2882
|
+
audience,
|
|
2883
|
+
languageType,
|
|
2884
|
+
parentMemoryId
|
|
2885
|
+
];
|
|
2886
|
+
const baseArgs = [
|
|
2887
|
+
row.id,
|
|
2888
|
+
row.agent_id,
|
|
2889
|
+
row.agent_role,
|
|
2890
|
+
row.session_id,
|
|
2891
|
+
row.timestamp,
|
|
2892
|
+
row.tool_name,
|
|
2893
|
+
row.project_name,
|
|
2894
|
+
row.has_error,
|
|
2895
|
+
row.raw_text
|
|
2896
|
+
];
|
|
2897
|
+
const sharedArgs = [
|
|
2898
|
+
row.version,
|
|
2899
|
+
taskId,
|
|
2900
|
+
importance,
|
|
2901
|
+
status,
|
|
2902
|
+
confidence,
|
|
2903
|
+
lastAccessed,
|
|
2904
|
+
workspaceId,
|
|
2905
|
+
documentId,
|
|
2906
|
+
userId,
|
|
2907
|
+
charOffset,
|
|
2908
|
+
pageNumber,
|
|
2909
|
+
sourcePath,
|
|
2910
|
+
sourceType,
|
|
2911
|
+
tier,
|
|
2912
|
+
supersedesId,
|
|
2913
|
+
draft,
|
|
2914
|
+
memoryType,
|
|
2915
|
+
trajectory,
|
|
2916
|
+
contentHash
|
|
2917
|
+
];
|
|
2918
|
+
return {
|
|
2919
|
+
sql: hasVector ? `INSERT OR IGNORE INTO memories (${cols})
|
|
2920
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
|
|
2921
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
2922
|
+
args: hasVector ? [...baseArgs, vectorToBlob(row.vector), ...sharedArgs, ...metaArgs] : [...baseArgs, ...sharedArgs, ...metaArgs]
|
|
2313
2923
|
};
|
|
2314
2924
|
};
|
|
2315
2925
|
const globalClient = getClient();
|