@askexenow/exe-os 0.8.83 → 0.8.86
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 +154 -21
- package/dist/bin/cli.js +14678 -12676
- package/dist/bin/exe-agent-config.js +242 -0
- package/dist/bin/exe-agent.js +100 -91
- package/dist/bin/exe-assign.js +1003 -854
- package/dist/bin/exe-boot.js +1420 -485
- package/dist/bin/exe-call.js +10 -0
- package/dist/bin/exe-cloud.js +29 -6
- package/dist/bin/exe-dispatch.js +572 -271
- package/dist/bin/exe-doctor.js +403 -6
- package/dist/bin/exe-export-behaviors.js +175 -72
- package/dist/bin/exe-forget.js +102 -3
- package/dist/bin/exe-gateway.js +796 -292
- package/dist/bin/exe-healthcheck.js +134 -1
- package/dist/bin/exe-heartbeat.js +172 -36
- package/dist/bin/exe-kill.js +175 -72
- package/dist/bin/exe-launch-agent.js +189 -76
- package/dist/bin/exe-link.js +927 -82
- package/dist/bin/exe-new-employee.js +60 -8
- package/dist/bin/exe-pending-messages.js +151 -19
- package/dist/bin/exe-pending-notifications.js +97 -2
- package/dist/bin/exe-pending-reviews.js +155 -22
- package/dist/bin/exe-rename.js +564 -23
- package/dist/bin/exe-review.js +231 -73
- package/dist/bin/exe-search.js +995 -228
- package/dist/bin/exe-session-cleanup.js +4930 -1664
- package/dist/bin/exe-settings.js +20 -5
- package/dist/bin/exe-start-codex.js +2598 -0
- package/dist/bin/exe-start.sh +15 -3
- package/dist/bin/exe-status.js +154 -21
- package/dist/bin/exe-team.js +97 -2
- package/dist/bin/git-sweep.js +1180 -363
- package/dist/bin/graph-backfill.js +175 -72
- package/dist/bin/graph-export.js +175 -72
- package/dist/bin/install.js +60 -7
- package/dist/bin/list-providers.js +1 -0
- package/dist/bin/scan-tasks.js +1185 -367
- package/dist/bin/setup.js +914 -270
- 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 +792 -285
- package/dist/hooks/bug-report-worker.js +445 -135
- package/dist/hooks/commit-complete.js +1178 -361
- package/dist/hooks/error-recall.js +994 -228
- package/dist/hooks/ingest-worker.js +1799 -1234
- 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 +757 -109
- package/dist/hooks/pre-compact.js +1061 -244
- package/dist/hooks/pre-tool-use.js +787 -130
- package/dist/hooks/prompt-ingest-worker.js +242 -101
- package/dist/hooks/prompt-submit.js +1121 -299
- package/dist/hooks/response-ingest-worker.js +242 -101
- package/dist/hooks/session-end.js +4063 -397
- package/dist/hooks/session-start.js +1071 -254
- package/dist/hooks/stop.js +768 -120
- package/dist/hooks/subagent-stop.js +757 -109
- package/dist/hooks/summary-worker.js +1706 -1011
- package/dist/index.js +1821 -1098
- package/dist/lib/agent-config.js +167 -0
- package/dist/lib/cloud-sync.js +932 -88
- 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 +2733 -1575
- package/dist/lib/hybrid-search.js +995 -228
- package/dist/lib/identity.js +87 -67
- package/dist/lib/keychain.js +9 -1
- package/dist/lib/messaging.js +103 -40
- package/dist/lib/reminders.js +91 -74
- package/dist/lib/runtime-table.js +16 -0
- package/dist/lib/schedules.js +96 -2
- package/dist/lib/session-wrappers.js +22 -0
- package/dist/lib/skill-learning.js +103 -85
- package/dist/lib/store.js +234 -73
- package/dist/lib/tasks.js +348 -134
- package/dist/lib/tmux-routing.js +422 -208
- package/dist/lib/token-spend.js +273 -0
- package/dist/lib/ws-client.js +11 -0
- package/dist/mcp/server.js +5742 -696
- 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 +375 -152
- 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 +99 -31
- package/dist/mcp/tools/send-message.js +108 -45
- package/dist/mcp/tools/update-task.js +162 -77
- package/dist/runtime/index.js +1075 -258
- package/dist/tui/App.js +1333 -506
- package/package.json +6 -1
- package/src/commands/exe/agent-config.md +27 -0
- package/src/commands/exe/cc-doctor.md +10 -0
package/dist/hooks/stop.js
CHANGED
|
@@ -450,17 +450,53 @@ var init_provider_table = __esm({
|
|
|
450
450
|
}
|
|
451
451
|
});
|
|
452
452
|
|
|
453
|
-
// src/lib/
|
|
454
|
-
|
|
453
|
+
// src/lib/runtime-table.ts
|
|
454
|
+
var RUNTIME_TABLE;
|
|
455
|
+
var init_runtime_table = __esm({
|
|
456
|
+
"src/lib/runtime-table.ts"() {
|
|
457
|
+
"use strict";
|
|
458
|
+
RUNTIME_TABLE = {
|
|
459
|
+
codex: {
|
|
460
|
+
binary: "codex",
|
|
461
|
+
launchMode: "exec",
|
|
462
|
+
autoApproveFlag: "--full-auto",
|
|
463
|
+
inlineFlag: "--no-alt-screen",
|
|
464
|
+
apiKeyEnv: "OPENAI_API_KEY",
|
|
465
|
+
defaultModel: "gpt-5.4"
|
|
466
|
+
}
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
// src/lib/agent-config.ts
|
|
472
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync3, mkdirSync as mkdirSync2 } from "fs";
|
|
455
473
|
import path5 from "path";
|
|
474
|
+
var AGENT_CONFIG_PATH, DEFAULT_MODELS;
|
|
475
|
+
var init_agent_config = __esm({
|
|
476
|
+
"src/lib/agent-config.ts"() {
|
|
477
|
+
"use strict";
|
|
478
|
+
init_config();
|
|
479
|
+
init_runtime_table();
|
|
480
|
+
AGENT_CONFIG_PATH = path5.join(EXE_AI_DIR, "agent-config.json");
|
|
481
|
+
DEFAULT_MODELS = {
|
|
482
|
+
claude: "claude-opus-4",
|
|
483
|
+
codex: RUNTIME_TABLE.codex?.defaultModel ?? "gpt-5.4",
|
|
484
|
+
opencode: "minimax-m2.7"
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
// src/lib/intercom-queue.ts
|
|
490
|
+
import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, renameSync as renameSync3, existsSync as existsSync4, mkdirSync as mkdirSync3 } from "fs";
|
|
491
|
+
import path6 from "path";
|
|
456
492
|
import os4 from "os";
|
|
457
493
|
var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
|
|
458
494
|
var init_intercom_queue = __esm({
|
|
459
495
|
"src/lib/intercom-queue.ts"() {
|
|
460
496
|
"use strict";
|
|
461
|
-
QUEUE_PATH =
|
|
497
|
+
QUEUE_PATH = path6.join(os4.homedir(), ".exe-os", "intercom-queue.json");
|
|
462
498
|
TTL_MS = 60 * 60 * 1e3;
|
|
463
|
-
INTERCOM_LOG =
|
|
499
|
+
INTERCOM_LOG = path6.join(os4.homedir(), ".exe-os", "intercom.log");
|
|
464
500
|
}
|
|
465
501
|
});
|
|
466
502
|
|
|
@@ -519,6 +555,443 @@ var init_db_retry = __esm({
|
|
|
519
555
|
}
|
|
520
556
|
});
|
|
521
557
|
|
|
558
|
+
// src/lib/exe-daemon-client.ts
|
|
559
|
+
import net from "net";
|
|
560
|
+
import { spawn } from "child_process";
|
|
561
|
+
import { randomUUID } from "crypto";
|
|
562
|
+
import { existsSync as existsSync5, unlinkSync as unlinkSync3, readFileSync as readFileSync6, openSync, closeSync, statSync } from "fs";
|
|
563
|
+
import path7 from "path";
|
|
564
|
+
import { fileURLToPath } from "url";
|
|
565
|
+
function handleData(chunk) {
|
|
566
|
+
_buffer += chunk.toString();
|
|
567
|
+
if (_buffer.length > MAX_BUFFER) {
|
|
568
|
+
_buffer = "";
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
let newlineIdx;
|
|
572
|
+
while ((newlineIdx = _buffer.indexOf("\n")) !== -1) {
|
|
573
|
+
const line = _buffer.slice(0, newlineIdx).trim();
|
|
574
|
+
_buffer = _buffer.slice(newlineIdx + 1);
|
|
575
|
+
if (!line) continue;
|
|
576
|
+
try {
|
|
577
|
+
const response = JSON.parse(line);
|
|
578
|
+
const id = response.id;
|
|
579
|
+
if (!id) continue;
|
|
580
|
+
const entry = _pending.get(id);
|
|
581
|
+
if (entry) {
|
|
582
|
+
clearTimeout(entry.timer);
|
|
583
|
+
_pending.delete(id);
|
|
584
|
+
entry.resolve(response);
|
|
585
|
+
}
|
|
586
|
+
} catch {
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
function cleanupStaleFiles() {
|
|
591
|
+
if (existsSync5(PID_PATH)) {
|
|
592
|
+
try {
|
|
593
|
+
const pid = parseInt(readFileSync6(PID_PATH, "utf8").trim(), 10);
|
|
594
|
+
if (pid > 0) {
|
|
595
|
+
try {
|
|
596
|
+
process.kill(pid, 0);
|
|
597
|
+
return;
|
|
598
|
+
} catch {
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
} catch {
|
|
602
|
+
}
|
|
603
|
+
try {
|
|
604
|
+
unlinkSync3(PID_PATH);
|
|
605
|
+
} catch {
|
|
606
|
+
}
|
|
607
|
+
try {
|
|
608
|
+
unlinkSync3(SOCKET_PATH);
|
|
609
|
+
} catch {
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
function findPackageRoot() {
|
|
614
|
+
let dir = path7.dirname(fileURLToPath(import.meta.url));
|
|
615
|
+
const { root } = path7.parse(dir);
|
|
616
|
+
while (dir !== root) {
|
|
617
|
+
if (existsSync5(path7.join(dir, "package.json"))) return dir;
|
|
618
|
+
dir = path7.dirname(dir);
|
|
619
|
+
}
|
|
620
|
+
return null;
|
|
621
|
+
}
|
|
622
|
+
function spawnDaemon() {
|
|
623
|
+
const pkgRoot = findPackageRoot();
|
|
624
|
+
if (!pkgRoot) {
|
|
625
|
+
process.stderr.write("[exed-client] WARN: cannot find package root\n");
|
|
626
|
+
return;
|
|
627
|
+
}
|
|
628
|
+
const daemonPath = path7.join(pkgRoot, "dist", "lib", "exe-daemon.js");
|
|
629
|
+
if (!existsSync5(daemonPath)) {
|
|
630
|
+
process.stderr.write(`[exed-client] WARN: daemon script not found at ${daemonPath}
|
|
631
|
+
`);
|
|
632
|
+
return;
|
|
633
|
+
}
|
|
634
|
+
const resolvedPath = daemonPath;
|
|
635
|
+
process.stderr.write(`[exed-client] Spawning daemon: ${resolvedPath}
|
|
636
|
+
`);
|
|
637
|
+
const logPath = path7.join(path7.dirname(SOCKET_PATH), "exed.log");
|
|
638
|
+
let stderrFd = "ignore";
|
|
639
|
+
try {
|
|
640
|
+
stderrFd = openSync(logPath, "a");
|
|
641
|
+
} catch {
|
|
642
|
+
}
|
|
643
|
+
const child = spawn(process.execPath, [resolvedPath], {
|
|
644
|
+
detached: true,
|
|
645
|
+
stdio: ["ignore", "ignore", stderrFd],
|
|
646
|
+
env: {
|
|
647
|
+
...process.env,
|
|
648
|
+
TMUX: void 0,
|
|
649
|
+
// Daemon is global — must not inherit session scope
|
|
650
|
+
TMUX_PANE: void 0,
|
|
651
|
+
// Prevents resolveExeSession() from scoping to one session
|
|
652
|
+
EXE_DAEMON_SOCK: SOCKET_PATH,
|
|
653
|
+
EXE_DAEMON_PID: PID_PATH
|
|
654
|
+
}
|
|
655
|
+
});
|
|
656
|
+
child.unref();
|
|
657
|
+
if (typeof stderrFd === "number") {
|
|
658
|
+
try {
|
|
659
|
+
closeSync(stderrFd);
|
|
660
|
+
} catch {
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
function acquireSpawnLock() {
|
|
665
|
+
try {
|
|
666
|
+
const fd = openSync(SPAWN_LOCK_PATH, "wx");
|
|
667
|
+
closeSync(fd);
|
|
668
|
+
return true;
|
|
669
|
+
} catch {
|
|
670
|
+
try {
|
|
671
|
+
const stat = statSync(SPAWN_LOCK_PATH);
|
|
672
|
+
if (Date.now() - stat.mtimeMs > SPAWN_LOCK_STALE_MS) {
|
|
673
|
+
try {
|
|
674
|
+
unlinkSync3(SPAWN_LOCK_PATH);
|
|
675
|
+
} catch {
|
|
676
|
+
}
|
|
677
|
+
try {
|
|
678
|
+
const fd = openSync(SPAWN_LOCK_PATH, "wx");
|
|
679
|
+
closeSync(fd);
|
|
680
|
+
return true;
|
|
681
|
+
} catch {
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
} catch {
|
|
685
|
+
}
|
|
686
|
+
return false;
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
function releaseSpawnLock() {
|
|
690
|
+
try {
|
|
691
|
+
unlinkSync3(SPAWN_LOCK_PATH);
|
|
692
|
+
} catch {
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
function connectToSocket() {
|
|
696
|
+
return new Promise((resolve) => {
|
|
697
|
+
if (_socket && _connected) {
|
|
698
|
+
resolve(true);
|
|
699
|
+
return;
|
|
700
|
+
}
|
|
701
|
+
const socket = net.createConnection({ path: SOCKET_PATH });
|
|
702
|
+
const connectTimeout = setTimeout(() => {
|
|
703
|
+
socket.destroy();
|
|
704
|
+
resolve(false);
|
|
705
|
+
}, 2e3);
|
|
706
|
+
socket.on("connect", () => {
|
|
707
|
+
clearTimeout(connectTimeout);
|
|
708
|
+
_socket = socket;
|
|
709
|
+
_connected = true;
|
|
710
|
+
_buffer = "";
|
|
711
|
+
socket.on("data", handleData);
|
|
712
|
+
socket.on("close", () => {
|
|
713
|
+
_connected = false;
|
|
714
|
+
_socket = null;
|
|
715
|
+
for (const [id, entry] of _pending) {
|
|
716
|
+
clearTimeout(entry.timer);
|
|
717
|
+
_pending.delete(id);
|
|
718
|
+
entry.resolve({ error: "Connection closed" });
|
|
719
|
+
}
|
|
720
|
+
});
|
|
721
|
+
socket.on("error", () => {
|
|
722
|
+
_connected = false;
|
|
723
|
+
_socket = null;
|
|
724
|
+
});
|
|
725
|
+
resolve(true);
|
|
726
|
+
});
|
|
727
|
+
socket.on("error", () => {
|
|
728
|
+
clearTimeout(connectTimeout);
|
|
729
|
+
resolve(false);
|
|
730
|
+
});
|
|
731
|
+
});
|
|
732
|
+
}
|
|
733
|
+
async function connectEmbedDaemon() {
|
|
734
|
+
if (_socket && _connected) return true;
|
|
735
|
+
if (await connectToSocket()) return true;
|
|
736
|
+
if (acquireSpawnLock()) {
|
|
737
|
+
try {
|
|
738
|
+
cleanupStaleFiles();
|
|
739
|
+
spawnDaemon();
|
|
740
|
+
} finally {
|
|
741
|
+
releaseSpawnLock();
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
const start = Date.now();
|
|
745
|
+
let delay2 = 100;
|
|
746
|
+
while (Date.now() - start < CONNECT_TIMEOUT_MS) {
|
|
747
|
+
await new Promise((r) => setTimeout(r, delay2));
|
|
748
|
+
if (await connectToSocket()) return true;
|
|
749
|
+
delay2 = Math.min(delay2 * 2, 3e3);
|
|
750
|
+
}
|
|
751
|
+
return false;
|
|
752
|
+
}
|
|
753
|
+
function sendDaemonRequest(payload, timeoutMs = REQUEST_TIMEOUT_MS) {
|
|
754
|
+
return new Promise((resolve) => {
|
|
755
|
+
if (!_socket || !_connected) {
|
|
756
|
+
resolve({ error: "Not connected" });
|
|
757
|
+
return;
|
|
758
|
+
}
|
|
759
|
+
const id = randomUUID();
|
|
760
|
+
const timer = setTimeout(() => {
|
|
761
|
+
_pending.delete(id);
|
|
762
|
+
resolve({ error: "Request timeout" });
|
|
763
|
+
}, timeoutMs);
|
|
764
|
+
_pending.set(id, { resolve, timer });
|
|
765
|
+
try {
|
|
766
|
+
_socket.write(JSON.stringify({ id, ...payload }) + "\n");
|
|
767
|
+
} catch {
|
|
768
|
+
clearTimeout(timer);
|
|
769
|
+
_pending.delete(id);
|
|
770
|
+
resolve({ error: "Write failed" });
|
|
771
|
+
}
|
|
772
|
+
});
|
|
773
|
+
}
|
|
774
|
+
function isClientConnected() {
|
|
775
|
+
return _connected;
|
|
776
|
+
}
|
|
777
|
+
var SOCKET_PATH, PID_PATH, SPAWN_LOCK_PATH, SPAWN_LOCK_STALE_MS, CONNECT_TIMEOUT_MS, REQUEST_TIMEOUT_MS, _socket, _connected, _buffer, _pending, MAX_BUFFER;
|
|
778
|
+
var init_exe_daemon_client = __esm({
|
|
779
|
+
"src/lib/exe-daemon-client.ts"() {
|
|
780
|
+
"use strict";
|
|
781
|
+
init_config();
|
|
782
|
+
SOCKET_PATH = process.env.EXE_DAEMON_SOCK ?? process.env.EXE_EMBED_SOCK ?? path7.join(EXE_AI_DIR, "exed.sock");
|
|
783
|
+
PID_PATH = process.env.EXE_DAEMON_PID ?? process.env.EXE_EMBED_PID ?? path7.join(EXE_AI_DIR, "exed.pid");
|
|
784
|
+
SPAWN_LOCK_PATH = path7.join(EXE_AI_DIR, "exed-spawn.lock");
|
|
785
|
+
SPAWN_LOCK_STALE_MS = 3e4;
|
|
786
|
+
CONNECT_TIMEOUT_MS = 15e3;
|
|
787
|
+
REQUEST_TIMEOUT_MS = 3e4;
|
|
788
|
+
_socket = null;
|
|
789
|
+
_connected = false;
|
|
790
|
+
_buffer = "";
|
|
791
|
+
_pending = /* @__PURE__ */ new Map();
|
|
792
|
+
MAX_BUFFER = 1e7;
|
|
793
|
+
}
|
|
794
|
+
});
|
|
795
|
+
|
|
796
|
+
// src/lib/daemon-protocol.ts
|
|
797
|
+
function serializeValue(v) {
|
|
798
|
+
if (v === null || v === void 0) return null;
|
|
799
|
+
if (typeof v === "bigint") return Number(v);
|
|
800
|
+
if (typeof v === "boolean") return v ? 1 : 0;
|
|
801
|
+
if (v instanceof Uint8Array) {
|
|
802
|
+
return { __blob: Buffer.from(v).toString("base64") };
|
|
803
|
+
}
|
|
804
|
+
if (ArrayBuffer.isView(v)) {
|
|
805
|
+
return { __blob: Buffer.from(v.buffer, v.byteOffset, v.byteLength).toString("base64") };
|
|
806
|
+
}
|
|
807
|
+
if (v instanceof ArrayBuffer) {
|
|
808
|
+
return { __blob: Buffer.from(v).toString("base64") };
|
|
809
|
+
}
|
|
810
|
+
if (typeof v === "string" || typeof v === "number") return v;
|
|
811
|
+
return String(v);
|
|
812
|
+
}
|
|
813
|
+
function deserializeValue(v) {
|
|
814
|
+
if (v === null) return null;
|
|
815
|
+
if (typeof v === "object" && v !== null && "__blob" in v) {
|
|
816
|
+
const buf = Buffer.from(v.__blob, "base64");
|
|
817
|
+
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
|
|
818
|
+
}
|
|
819
|
+
return v;
|
|
820
|
+
}
|
|
821
|
+
function deserializeResultSet(srs) {
|
|
822
|
+
const rows = srs.rows.map((obj) => {
|
|
823
|
+
const values = srs.columns.map(
|
|
824
|
+
(col) => deserializeValue(obj[col] ?? null)
|
|
825
|
+
);
|
|
826
|
+
const row = values;
|
|
827
|
+
for (let i = 0; i < srs.columns.length; i++) {
|
|
828
|
+
const col = srs.columns[i];
|
|
829
|
+
if (col !== void 0) {
|
|
830
|
+
row[col] = values[i] ?? null;
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
Object.defineProperty(row, "length", {
|
|
834
|
+
value: values.length,
|
|
835
|
+
enumerable: false
|
|
836
|
+
});
|
|
837
|
+
return row;
|
|
838
|
+
});
|
|
839
|
+
return {
|
|
840
|
+
columns: srs.columns,
|
|
841
|
+
columnTypes: srs.columnTypes ?? [],
|
|
842
|
+
rows,
|
|
843
|
+
rowsAffected: srs.rowsAffected,
|
|
844
|
+
lastInsertRowid: srs.lastInsertRowid != null ? BigInt(srs.lastInsertRowid) : void 0,
|
|
845
|
+
toJSON: () => ({
|
|
846
|
+
columns: srs.columns,
|
|
847
|
+
columnTypes: srs.columnTypes ?? [],
|
|
848
|
+
rows: srs.rows,
|
|
849
|
+
rowsAffected: srs.rowsAffected,
|
|
850
|
+
lastInsertRowid: srs.lastInsertRowid
|
|
851
|
+
})
|
|
852
|
+
};
|
|
853
|
+
}
|
|
854
|
+
var init_daemon_protocol = __esm({
|
|
855
|
+
"src/lib/daemon-protocol.ts"() {
|
|
856
|
+
"use strict";
|
|
857
|
+
}
|
|
858
|
+
});
|
|
859
|
+
|
|
860
|
+
// src/lib/db-daemon-client.ts
|
|
861
|
+
var db_daemon_client_exports = {};
|
|
862
|
+
__export(db_daemon_client_exports, {
|
|
863
|
+
createDaemonDbClient: () => createDaemonDbClient,
|
|
864
|
+
initDaemonDbClient: () => initDaemonDbClient
|
|
865
|
+
});
|
|
866
|
+
function normalizeStatement(stmt) {
|
|
867
|
+
if (typeof stmt === "string") {
|
|
868
|
+
return { sql: stmt, args: [] };
|
|
869
|
+
}
|
|
870
|
+
const sql = stmt.sql;
|
|
871
|
+
let args = [];
|
|
872
|
+
if (Array.isArray(stmt.args)) {
|
|
873
|
+
args = stmt.args.map((v) => serializeValue(v));
|
|
874
|
+
} else if (stmt.args && typeof stmt.args === "object") {
|
|
875
|
+
const named = {};
|
|
876
|
+
for (const [key, val] of Object.entries(stmt.args)) {
|
|
877
|
+
named[key] = serializeValue(val);
|
|
878
|
+
}
|
|
879
|
+
return { sql, args: named };
|
|
880
|
+
}
|
|
881
|
+
return { sql, args };
|
|
882
|
+
}
|
|
883
|
+
function createDaemonDbClient(fallbackClient) {
|
|
884
|
+
let _useDaemon = false;
|
|
885
|
+
const client = {
|
|
886
|
+
async execute(stmt) {
|
|
887
|
+
if (!_useDaemon || !isClientConnected()) {
|
|
888
|
+
return fallbackClient.execute(stmt);
|
|
889
|
+
}
|
|
890
|
+
const { sql, args } = normalizeStatement(stmt);
|
|
891
|
+
const response = await sendDaemonRequest({
|
|
892
|
+
type: "db-execute",
|
|
893
|
+
sql,
|
|
894
|
+
args
|
|
895
|
+
});
|
|
896
|
+
if (response.error) {
|
|
897
|
+
const errMsg = String(response.error);
|
|
898
|
+
if (errMsg === "Not connected" || errMsg === "Request timeout" || errMsg === "Write failed") {
|
|
899
|
+
process.stderr.write(`[db-daemon] Transport error (${errMsg}), falling back to direct
|
|
900
|
+
`);
|
|
901
|
+
return fallbackClient.execute(stmt);
|
|
902
|
+
}
|
|
903
|
+
throw new Error(errMsg);
|
|
904
|
+
}
|
|
905
|
+
if (response.db) {
|
|
906
|
+
return deserializeResultSet(response.db);
|
|
907
|
+
}
|
|
908
|
+
process.stderr.write("[db-daemon] Unexpected response shape, falling back to direct\n");
|
|
909
|
+
return fallbackClient.execute(stmt);
|
|
910
|
+
},
|
|
911
|
+
async batch(stmts, mode) {
|
|
912
|
+
if (!_useDaemon || !isClientConnected()) {
|
|
913
|
+
return fallbackClient.batch(stmts, mode);
|
|
914
|
+
}
|
|
915
|
+
const statements = stmts.map(normalizeStatement);
|
|
916
|
+
const response = await sendDaemonRequest({
|
|
917
|
+
type: "db-batch",
|
|
918
|
+
statements,
|
|
919
|
+
mode: mode ?? "deferred"
|
|
920
|
+
});
|
|
921
|
+
if (response.error) {
|
|
922
|
+
const errMsg = String(response.error);
|
|
923
|
+
if (errMsg === "Not connected" || errMsg === "Request timeout" || errMsg === "Write failed") {
|
|
924
|
+
process.stderr.write(`[db-daemon] Batch transport error (${errMsg}), falling back to direct
|
|
925
|
+
`);
|
|
926
|
+
return fallbackClient.batch(stmts, mode);
|
|
927
|
+
}
|
|
928
|
+
throw new Error(errMsg);
|
|
929
|
+
}
|
|
930
|
+
const batchResults = response["db-batch"];
|
|
931
|
+
if (batchResults) {
|
|
932
|
+
return batchResults.map(deserializeResultSet);
|
|
933
|
+
}
|
|
934
|
+
process.stderr.write("[db-daemon] Unexpected batch response shape, falling back to direct\n");
|
|
935
|
+
return fallbackClient.batch(stmts, mode);
|
|
936
|
+
},
|
|
937
|
+
// Transaction support — delegate to fallback (transactions need direct connection)
|
|
938
|
+
async transaction(mode) {
|
|
939
|
+
return fallbackClient.transaction(mode);
|
|
940
|
+
},
|
|
941
|
+
// executeMultiple — delegate to fallback (used only for schema migrations)
|
|
942
|
+
async executeMultiple(sql) {
|
|
943
|
+
return fallbackClient.executeMultiple(sql);
|
|
944
|
+
},
|
|
945
|
+
// migrate — delegate to fallback
|
|
946
|
+
async migrate(stmts) {
|
|
947
|
+
return fallbackClient.migrate(stmts);
|
|
948
|
+
},
|
|
949
|
+
// Sync mode — delegate to fallback
|
|
950
|
+
sync() {
|
|
951
|
+
return fallbackClient.sync();
|
|
952
|
+
},
|
|
953
|
+
close() {
|
|
954
|
+
_useDaemon = false;
|
|
955
|
+
},
|
|
956
|
+
get closed() {
|
|
957
|
+
return fallbackClient.closed;
|
|
958
|
+
},
|
|
959
|
+
get protocol() {
|
|
960
|
+
return fallbackClient.protocol;
|
|
961
|
+
}
|
|
962
|
+
};
|
|
963
|
+
return {
|
|
964
|
+
...client,
|
|
965
|
+
/** Enable daemon routing (call after confirming daemon is connected) */
|
|
966
|
+
_enableDaemon() {
|
|
967
|
+
_useDaemon = true;
|
|
968
|
+
},
|
|
969
|
+
/** Check if daemon routing is active */
|
|
970
|
+
_isDaemonActive() {
|
|
971
|
+
return _useDaemon && isClientConnected();
|
|
972
|
+
}
|
|
973
|
+
};
|
|
974
|
+
}
|
|
975
|
+
async function initDaemonDbClient(fallbackClient) {
|
|
976
|
+
if (process.env.EXE_IS_DAEMON === "1") return null;
|
|
977
|
+
const connected = await connectEmbedDaemon();
|
|
978
|
+
if (!connected) {
|
|
979
|
+
process.stderr.write("[db-daemon] Daemon unavailable \u2014 using direct SQLite\n");
|
|
980
|
+
return null;
|
|
981
|
+
}
|
|
982
|
+
const client = createDaemonDbClient(fallbackClient);
|
|
983
|
+
client._enableDaemon();
|
|
984
|
+
process.stderr.write("[db-daemon] DB routing through daemon (single-writer)\n");
|
|
985
|
+
return client;
|
|
986
|
+
}
|
|
987
|
+
var init_db_daemon_client = __esm({
|
|
988
|
+
"src/lib/db-daemon-client.ts"() {
|
|
989
|
+
"use strict";
|
|
990
|
+
init_exe_daemon_client();
|
|
991
|
+
init_daemon_protocol();
|
|
992
|
+
}
|
|
993
|
+
});
|
|
994
|
+
|
|
522
995
|
// src/lib/database.ts
|
|
523
996
|
var database_exports = {};
|
|
524
997
|
__export(database_exports, {
|
|
@@ -527,6 +1000,7 @@ __export(database_exports, {
|
|
|
527
1000
|
ensureSchema: () => ensureSchema,
|
|
528
1001
|
getClient: () => getClient,
|
|
529
1002
|
getRawClient: () => getRawClient,
|
|
1003
|
+
initDaemonClient: () => initDaemonClient,
|
|
530
1004
|
initDatabase: () => initDatabase,
|
|
531
1005
|
initTurso: () => initTurso,
|
|
532
1006
|
isInitialized: () => isInitialized
|
|
@@ -554,8 +1028,27 @@ function getClient() {
|
|
|
554
1028
|
if (!_resilientClient) {
|
|
555
1029
|
throw new Error("Database client not initialized. Call initDatabase() first.");
|
|
556
1030
|
}
|
|
1031
|
+
if (process.env.EXE_IS_DAEMON === "1") {
|
|
1032
|
+
return _resilientClient;
|
|
1033
|
+
}
|
|
1034
|
+
if (_daemonClient && _daemonClient._isDaemonActive()) {
|
|
1035
|
+
return _daemonClient;
|
|
1036
|
+
}
|
|
557
1037
|
return _resilientClient;
|
|
558
1038
|
}
|
|
1039
|
+
async function initDaemonClient() {
|
|
1040
|
+
if (process.env.EXE_IS_DAEMON === "1") return;
|
|
1041
|
+
if (!_resilientClient) return;
|
|
1042
|
+
try {
|
|
1043
|
+
const { initDaemonDbClient: initDaemonDbClient2 } = await Promise.resolve().then(() => (init_db_daemon_client(), db_daemon_client_exports));
|
|
1044
|
+
_daemonClient = await initDaemonDbClient2(_resilientClient);
|
|
1045
|
+
} catch (err) {
|
|
1046
|
+
process.stderr.write(
|
|
1047
|
+
`[database] Daemon client init failed (non-fatal): ${err instanceof Error ? err.message : String(err)}
|
|
1048
|
+
`
|
|
1049
|
+
);
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
559
1052
|
function getRawClient() {
|
|
560
1053
|
if (!_client) {
|
|
561
1054
|
throw new Error("Database client not initialized. Call initDatabase() first.");
|
|
@@ -1042,6 +1535,12 @@ async function ensureSchema() {
|
|
|
1042
1535
|
} catch {
|
|
1043
1536
|
}
|
|
1044
1537
|
}
|
|
1538
|
+
try {
|
|
1539
|
+
await client.execute(
|
|
1540
|
+
`CREATE INDEX IF NOT EXISTS idx_memories_content_hash ON memories(content_hash, agent_id)`
|
|
1541
|
+
);
|
|
1542
|
+
} catch {
|
|
1543
|
+
}
|
|
1045
1544
|
await client.executeMultiple(`
|
|
1046
1545
|
CREATE TABLE IF NOT EXISTS entities (
|
|
1047
1546
|
id TEXT PRIMARY KEY,
|
|
@@ -1094,7 +1593,30 @@ async function ensureSchema() {
|
|
|
1094
1593
|
entity_id TEXT NOT NULL,
|
|
1095
1594
|
PRIMARY KEY (hyperedge_id, entity_id)
|
|
1096
1595
|
);
|
|
1596
|
+
|
|
1597
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS entities_fts USING fts5(
|
|
1598
|
+
name,
|
|
1599
|
+
content=entities,
|
|
1600
|
+
content_rowid=rowid
|
|
1601
|
+
);
|
|
1602
|
+
|
|
1603
|
+
CREATE TRIGGER IF NOT EXISTS entities_fts_ai AFTER INSERT ON entities BEGIN
|
|
1604
|
+
INSERT INTO entities_fts(rowid, name) VALUES (new.rowid, new.name);
|
|
1605
|
+
END;
|
|
1606
|
+
|
|
1607
|
+
CREATE TRIGGER IF NOT EXISTS entities_fts_ad AFTER DELETE ON entities BEGIN
|
|
1608
|
+
INSERT INTO entities_fts(entities_fts, rowid, name) VALUES('delete', old.rowid, old.name);
|
|
1609
|
+
END;
|
|
1610
|
+
|
|
1611
|
+
CREATE TRIGGER IF NOT EXISTS entities_fts_au AFTER UPDATE ON entities BEGIN
|
|
1612
|
+
INSERT INTO entities_fts(entities_fts, rowid, name) VALUES('delete', old.rowid, old.name);
|
|
1613
|
+
INSERT INTO entities_fts(rowid, name) VALUES (new.rowid, new.name);
|
|
1614
|
+
END;
|
|
1097
1615
|
`);
|
|
1616
|
+
try {
|
|
1617
|
+
await client.execute("INSERT INTO entities_fts(entities_fts) VALUES('rebuild')");
|
|
1618
|
+
} catch {
|
|
1619
|
+
}
|
|
1098
1620
|
await client.executeMultiple(`
|
|
1099
1621
|
CREATE TABLE IF NOT EXISTS entity_aliases (
|
|
1100
1622
|
alias TEXT NOT NULL PRIMARY KEY,
|
|
@@ -1275,6 +1797,33 @@ async function ensureSchema() {
|
|
|
1275
1797
|
CREATE INDEX IF NOT EXISTS idx_conversations_channel
|
|
1276
1798
|
ON conversations(channel_id);
|
|
1277
1799
|
`);
|
|
1800
|
+
await client.executeMultiple(`
|
|
1801
|
+
CREATE TABLE IF NOT EXISTS session_agent_map (
|
|
1802
|
+
session_uuid TEXT PRIMARY KEY,
|
|
1803
|
+
agent_id TEXT NOT NULL,
|
|
1804
|
+
session_name TEXT,
|
|
1805
|
+
task_id TEXT,
|
|
1806
|
+
project_name TEXT,
|
|
1807
|
+
started_at TEXT NOT NULL
|
|
1808
|
+
);
|
|
1809
|
+
|
|
1810
|
+
CREATE INDEX IF NOT EXISTS idx_session_agent_map_agent
|
|
1811
|
+
ON session_agent_map(agent_id);
|
|
1812
|
+
`);
|
|
1813
|
+
try {
|
|
1814
|
+
const mapCount = await client.execute({ sql: `SELECT COUNT(*) as cnt FROM session_agent_map`, args: [] });
|
|
1815
|
+
if (Number(mapCount.rows[0]?.cnt ?? 0) === 0) {
|
|
1816
|
+
await client.execute({
|
|
1817
|
+
sql: `INSERT OR IGNORE INTO session_agent_map (session_uuid, agent_id, session_name, started_at)
|
|
1818
|
+
SELECT session_id, agent_id, '', MIN(timestamp)
|
|
1819
|
+
FROM memories
|
|
1820
|
+
WHERE session_id IS NOT NULL AND session_id != '' AND agent_id IS NOT NULL AND agent_id != ''
|
|
1821
|
+
GROUP BY session_id, agent_id`,
|
|
1822
|
+
args: []
|
|
1823
|
+
});
|
|
1824
|
+
}
|
|
1825
|
+
} catch {
|
|
1826
|
+
}
|
|
1278
1827
|
try {
|
|
1279
1828
|
await client.execute({
|
|
1280
1829
|
sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
|
|
@@ -1408,15 +1957,41 @@ async function ensureSchema() {
|
|
|
1408
1957
|
});
|
|
1409
1958
|
} catch {
|
|
1410
1959
|
}
|
|
1960
|
+
for (const col of [
|
|
1961
|
+
"ALTER TABLE memories ADD COLUMN intent TEXT",
|
|
1962
|
+
"ALTER TABLE memories ADD COLUMN outcome TEXT",
|
|
1963
|
+
"ALTER TABLE memories ADD COLUMN domain TEXT",
|
|
1964
|
+
"ALTER TABLE memories ADD COLUMN referenced_entities TEXT",
|
|
1965
|
+
"ALTER TABLE memories ADD COLUMN retrieval_count INTEGER DEFAULT 0",
|
|
1966
|
+
"ALTER TABLE memories ADD COLUMN chain_position TEXT",
|
|
1967
|
+
"ALTER TABLE memories ADD COLUMN review_status TEXT",
|
|
1968
|
+
"ALTER TABLE memories ADD COLUMN context_window_pct INTEGER",
|
|
1969
|
+
"ALTER TABLE memories ADD COLUMN file_paths TEXT",
|
|
1970
|
+
"ALTER TABLE memories ADD COLUMN commit_hash TEXT",
|
|
1971
|
+
"ALTER TABLE memories ADD COLUMN duration_ms INTEGER",
|
|
1972
|
+
"ALTER TABLE memories ADD COLUMN token_cost REAL",
|
|
1973
|
+
"ALTER TABLE memories ADD COLUMN audience TEXT",
|
|
1974
|
+
"ALTER TABLE memories ADD COLUMN language_type TEXT",
|
|
1975
|
+
"ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
|
|
1976
|
+
]) {
|
|
1977
|
+
try {
|
|
1978
|
+
await client.execute(col);
|
|
1979
|
+
} catch {
|
|
1980
|
+
}
|
|
1981
|
+
}
|
|
1411
1982
|
}
|
|
1412
1983
|
async function disposeDatabase() {
|
|
1984
|
+
if (_daemonClient) {
|
|
1985
|
+
_daemonClient.close();
|
|
1986
|
+
_daemonClient = null;
|
|
1987
|
+
}
|
|
1413
1988
|
if (_client) {
|
|
1414
1989
|
_client.close();
|
|
1415
1990
|
_client = null;
|
|
1416
1991
|
_resilientClient = null;
|
|
1417
1992
|
}
|
|
1418
1993
|
}
|
|
1419
|
-
var _client, _resilientClient, initTurso, disposeTurso;
|
|
1994
|
+
var _client, _resilientClient, _daemonClient, initTurso, disposeTurso;
|
|
1420
1995
|
var init_database = __esm({
|
|
1421
1996
|
"src/lib/database.ts"() {
|
|
1422
1997
|
"use strict";
|
|
@@ -1424,30 +1999,31 @@ var init_database = __esm({
|
|
|
1424
1999
|
init_employees();
|
|
1425
2000
|
_client = null;
|
|
1426
2001
|
_resilientClient = null;
|
|
2002
|
+
_daemonClient = null;
|
|
1427
2003
|
initTurso = initDatabase;
|
|
1428
2004
|
disposeTurso = disposeDatabase;
|
|
1429
2005
|
}
|
|
1430
2006
|
});
|
|
1431
2007
|
|
|
1432
2008
|
// src/lib/license.ts
|
|
1433
|
-
import { readFileSync as
|
|
1434
|
-
import { randomUUID } from "crypto";
|
|
1435
|
-
import
|
|
2009
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, existsSync as existsSync6, mkdirSync as mkdirSync4 } from "fs";
|
|
2010
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
2011
|
+
import path8 from "path";
|
|
1436
2012
|
import { jwtVerify, importSPKI } from "jose";
|
|
1437
2013
|
var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH;
|
|
1438
2014
|
var init_license = __esm({
|
|
1439
2015
|
"src/lib/license.ts"() {
|
|
1440
2016
|
"use strict";
|
|
1441
2017
|
init_config();
|
|
1442
|
-
LICENSE_PATH =
|
|
1443
|
-
CACHE_PATH =
|
|
1444
|
-
DEVICE_ID_PATH =
|
|
2018
|
+
LICENSE_PATH = path8.join(EXE_AI_DIR, "license.key");
|
|
2019
|
+
CACHE_PATH = path8.join(EXE_AI_DIR, "license-cache.json");
|
|
2020
|
+
DEVICE_ID_PATH = path8.join(EXE_AI_DIR, "device-id");
|
|
1445
2021
|
}
|
|
1446
2022
|
});
|
|
1447
2023
|
|
|
1448
2024
|
// src/lib/plan-limits.ts
|
|
1449
|
-
import { readFileSync as
|
|
1450
|
-
import
|
|
2025
|
+
import { readFileSync as readFileSync8, existsSync as existsSync7 } from "fs";
|
|
2026
|
+
import path9 from "path";
|
|
1451
2027
|
var CACHE_PATH2;
|
|
1452
2028
|
var init_plan_limits = __esm({
|
|
1453
2029
|
"src/lib/plan-limits.ts"() {
|
|
@@ -1456,15 +2032,15 @@ var init_plan_limits = __esm({
|
|
|
1456
2032
|
init_employees();
|
|
1457
2033
|
init_license();
|
|
1458
2034
|
init_config();
|
|
1459
|
-
CACHE_PATH2 =
|
|
2035
|
+
CACHE_PATH2 = path9.join(EXE_AI_DIR, "license-cache.json");
|
|
1460
2036
|
}
|
|
1461
2037
|
});
|
|
1462
2038
|
|
|
1463
2039
|
// src/lib/tmux-routing.ts
|
|
1464
|
-
import { readFileSync as
|
|
1465
|
-
import
|
|
2040
|
+
import { readFileSync as readFileSync9, writeFileSync as writeFileSync6, mkdirSync as mkdirSync5, existsSync as existsSync8, appendFileSync } from "fs";
|
|
2041
|
+
import path10 from "path";
|
|
1466
2042
|
import os5 from "os";
|
|
1467
|
-
import { fileURLToPath } from "url";
|
|
2043
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
1468
2044
|
function getMySession() {
|
|
1469
2045
|
return getTransport().getMySession();
|
|
1470
2046
|
}
|
|
@@ -1476,7 +2052,7 @@ function extractRootExe(name) {
|
|
|
1476
2052
|
}
|
|
1477
2053
|
function getParentExe(sessionKey) {
|
|
1478
2054
|
try {
|
|
1479
|
-
const data = JSON.parse(
|
|
2055
|
+
const data = JSON.parse(readFileSync9(path10.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
|
|
1480
2056
|
return data.parentExe || null;
|
|
1481
2057
|
} catch {
|
|
1482
2058
|
return null;
|
|
@@ -1505,13 +2081,15 @@ var init_tmux_routing = __esm({
|
|
|
1505
2081
|
init_cc_agent_support();
|
|
1506
2082
|
init_mcp_prefix();
|
|
1507
2083
|
init_provider_table();
|
|
2084
|
+
init_agent_config();
|
|
2085
|
+
init_runtime_table();
|
|
1508
2086
|
init_intercom_queue();
|
|
1509
2087
|
init_plan_limits();
|
|
1510
2088
|
init_employees();
|
|
1511
|
-
SPAWN_LOCK_DIR =
|
|
1512
|
-
SESSION_CACHE =
|
|
1513
|
-
INTERCOM_LOG2 =
|
|
1514
|
-
DEBOUNCE_FILE =
|
|
2089
|
+
SPAWN_LOCK_DIR = path10.join(os5.homedir(), ".exe-os", "spawn-locks");
|
|
2090
|
+
SESSION_CACHE = path10.join(os5.homedir(), ".exe-os", "session-cache");
|
|
2091
|
+
INTERCOM_LOG2 = path10.join(os5.homedir(), ".exe-os", "intercom.log");
|
|
2092
|
+
DEBOUNCE_FILE = path10.join(SESSION_CACHE, "intercom-debounce.json");
|
|
1515
2093
|
DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
|
|
1516
2094
|
}
|
|
1517
2095
|
});
|
|
@@ -1551,14 +2129,14 @@ var init_memory = __esm({
|
|
|
1551
2129
|
|
|
1552
2130
|
// src/lib/keychain.ts
|
|
1553
2131
|
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
1554
|
-
import { existsSync as
|
|
1555
|
-
import
|
|
2132
|
+
import { existsSync as existsSync9 } from "fs";
|
|
2133
|
+
import path11 from "path";
|
|
1556
2134
|
import os6 from "os";
|
|
1557
2135
|
function getKeyDir() {
|
|
1558
|
-
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ??
|
|
2136
|
+
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path11.join(os6.homedir(), ".exe-os");
|
|
1559
2137
|
}
|
|
1560
2138
|
function getKeyPath() {
|
|
1561
|
-
return
|
|
2139
|
+
return path11.join(getKeyDir(), "master.key");
|
|
1562
2140
|
}
|
|
1563
2141
|
async function tryKeytar() {
|
|
1564
2142
|
try {
|
|
@@ -1579,13 +2157,21 @@ async function getMasterKey() {
|
|
|
1579
2157
|
}
|
|
1580
2158
|
}
|
|
1581
2159
|
const keyPath = getKeyPath();
|
|
1582
|
-
if (!
|
|
2160
|
+
if (!existsSync9(keyPath)) {
|
|
2161
|
+
process.stderr.write(
|
|
2162
|
+
`[keychain] Key not found at ${keyPath} (HOME=${os6.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
|
|
2163
|
+
`
|
|
2164
|
+
);
|
|
1583
2165
|
return null;
|
|
1584
2166
|
}
|
|
1585
2167
|
try {
|
|
1586
2168
|
const content = await readFile3(keyPath, "utf-8");
|
|
1587
2169
|
return Buffer.from(content.trim(), "base64");
|
|
1588
|
-
} catch {
|
|
2170
|
+
} catch (err) {
|
|
2171
|
+
process.stderr.write(
|
|
2172
|
+
`[keychain] Key read failed at ${keyPath}: ${err instanceof Error ? err.message : String(err)}
|
|
2173
|
+
`
|
|
2174
|
+
);
|
|
1589
2175
|
return null;
|
|
1590
2176
|
}
|
|
1591
2177
|
}
|
|
@@ -1666,13 +2252,13 @@ __export(shard_manager_exports, {
|
|
|
1666
2252
|
listShards: () => listShards,
|
|
1667
2253
|
shardExists: () => shardExists
|
|
1668
2254
|
});
|
|
1669
|
-
import
|
|
1670
|
-
import { existsSync as
|
|
2255
|
+
import path12 from "path";
|
|
2256
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync6, readdirSync as readdirSync2 } from "fs";
|
|
1671
2257
|
import { createClient as createClient2 } from "@libsql/client";
|
|
1672
2258
|
function initShardManager(encryptionKey) {
|
|
1673
2259
|
_encryptionKey = encryptionKey;
|
|
1674
|
-
if (!
|
|
1675
|
-
|
|
2260
|
+
if (!existsSync10(SHARDS_DIR)) {
|
|
2261
|
+
mkdirSync6(SHARDS_DIR, { recursive: true });
|
|
1676
2262
|
}
|
|
1677
2263
|
_shardingEnabled = true;
|
|
1678
2264
|
}
|
|
@@ -1692,7 +2278,7 @@ function getShardClient(projectName) {
|
|
|
1692
2278
|
}
|
|
1693
2279
|
const cached = _shards.get(safeName);
|
|
1694
2280
|
if (cached) return cached;
|
|
1695
|
-
const dbPath =
|
|
2281
|
+
const dbPath = path12.join(SHARDS_DIR, `${safeName}.db`);
|
|
1696
2282
|
const client = createClient2({
|
|
1697
2283
|
url: `file:${dbPath}`,
|
|
1698
2284
|
encryptionKey: _encryptionKey
|
|
@@ -1702,10 +2288,10 @@ function getShardClient(projectName) {
|
|
|
1702
2288
|
}
|
|
1703
2289
|
function shardExists(projectName) {
|
|
1704
2290
|
const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
1705
|
-
return
|
|
2291
|
+
return existsSync10(path12.join(SHARDS_DIR, `${safeName}.db`));
|
|
1706
2292
|
}
|
|
1707
2293
|
function listShards() {
|
|
1708
|
-
if (!
|
|
2294
|
+
if (!existsSync10(SHARDS_DIR)) return [];
|
|
1709
2295
|
return readdirSync2(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
1710
2296
|
}
|
|
1711
2297
|
async function ensureShardSchema(client) {
|
|
@@ -1891,7 +2477,7 @@ var init_shard_manager = __esm({
|
|
|
1891
2477
|
"src/lib/shard-manager.ts"() {
|
|
1892
2478
|
"use strict";
|
|
1893
2479
|
init_config();
|
|
1894
|
-
SHARDS_DIR =
|
|
2480
|
+
SHARDS_DIR = path12.join(EXE_AI_DIR, "shards");
|
|
1895
2481
|
_shards = /* @__PURE__ */ new Map();
|
|
1896
2482
|
_encryptionKey = null;
|
|
1897
2483
|
_shardingEnabled = false;
|
|
@@ -2016,7 +2602,7 @@ __export(global_procedures_exports, {
|
|
|
2016
2602
|
loadGlobalProcedures: () => loadGlobalProcedures,
|
|
2017
2603
|
storeGlobalProcedure: () => storeGlobalProcedure
|
|
2018
2604
|
});
|
|
2019
|
-
import { randomUUID as
|
|
2605
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
2020
2606
|
async function loadGlobalProcedures() {
|
|
2021
2607
|
const client = getClient();
|
|
2022
2608
|
const result = await client.execute({
|
|
@@ -2045,7 +2631,7 @@ ${sections.join("\n\n")}
|
|
|
2045
2631
|
`;
|
|
2046
2632
|
}
|
|
2047
2633
|
async function storeGlobalProcedure(input2) {
|
|
2048
|
-
const id =
|
|
2634
|
+
const id = randomUUID3();
|
|
2049
2635
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2050
2636
|
const client = getClient();
|
|
2051
2637
|
await client.execute({
|
|
@@ -2096,6 +2682,7 @@ __export(store_exports, {
|
|
|
2096
2682
|
vectorToBlob: () => vectorToBlob,
|
|
2097
2683
|
writeMemory: () => writeMemory
|
|
2098
2684
|
});
|
|
2685
|
+
import { createHash } from "crypto";
|
|
2099
2686
|
function isBusyError2(err) {
|
|
2100
2687
|
if (err instanceof Error) {
|
|
2101
2688
|
const msg = err.message.toLowerCase();
|
|
@@ -2169,12 +2756,52 @@ function classifyTier(record) {
|
|
|
2169
2756
|
if (["store_memory", "manual"].includes(record.tool_name ?? "") && (record.importance ?? 0) >= 5) return 2;
|
|
2170
2757
|
return 3;
|
|
2171
2758
|
}
|
|
2759
|
+
function inferFilePaths(record) {
|
|
2760
|
+
if (!["Read", "Write", "Edit"].includes(record.tool_name)) return null;
|
|
2761
|
+
const firstLine = record.raw_text.split("\n")[0] ?? "";
|
|
2762
|
+
const match = firstLine.match(/(\/[\w./-]+\.\w+)/);
|
|
2763
|
+
return match ? JSON.stringify([match[1]]) : null;
|
|
2764
|
+
}
|
|
2765
|
+
function inferCommitHash(record) {
|
|
2766
|
+
if (record.tool_name !== "Bash") return null;
|
|
2767
|
+
const match = record.raw_text.match(/\b([a-f0-9]{7,40})\b/);
|
|
2768
|
+
return match ? match[1] : null;
|
|
2769
|
+
}
|
|
2770
|
+
function inferLanguageType(record) {
|
|
2771
|
+
const text = record.raw_text;
|
|
2772
|
+
if (!text || text.length < 10) return null;
|
|
2773
|
+
const trimmed = text.trimStart();
|
|
2774
|
+
if (trimmed.startsWith("{") || trimmed.startsWith("[")) return "json";
|
|
2775
|
+
if (/\b(SELECT|INSERT|UPDATE|DELETE|CREATE TABLE|ALTER TABLE)\b/i.test(text)) return "sql";
|
|
2776
|
+
if (/\b(function |const |import |export |class |def |async |=>)\b/.test(text)) return "code";
|
|
2777
|
+
if (trimmed.startsWith("#") || trimmed.startsWith("*")) return "prose";
|
|
2778
|
+
return "mixed";
|
|
2779
|
+
}
|
|
2780
|
+
function inferDomain(record) {
|
|
2781
|
+
const proj = (record.project_name ?? "").toLowerCase();
|
|
2782
|
+
if (proj.includes("marketing") || proj.includes("content")) return "marketing";
|
|
2783
|
+
if (proj.includes("crm") || proj.includes("customer")) return "customer";
|
|
2784
|
+
return null;
|
|
2785
|
+
}
|
|
2172
2786
|
async function writeMemory(record) {
|
|
2173
2787
|
if (record.vector !== null && record.vector.length !== EMBEDDING_DIM) {
|
|
2174
2788
|
throw new Error(
|
|
2175
2789
|
`Expected ${EMBEDDING_DIM}-dim vector, got ${record.vector.length}`
|
|
2176
2790
|
);
|
|
2177
2791
|
}
|
|
2792
|
+
const contentHash = createHash("md5").update(record.raw_text).digest("hex");
|
|
2793
|
+
if (_pendingRecords.some((r) => r.content_hash === contentHash && r.agent_id === record.agent_id)) {
|
|
2794
|
+
return;
|
|
2795
|
+
}
|
|
2796
|
+
try {
|
|
2797
|
+
const client = getClient();
|
|
2798
|
+
const existing = await client.execute({
|
|
2799
|
+
sql: "SELECT id FROM memories WHERE content_hash = ? AND agent_id = ? LIMIT 1",
|
|
2800
|
+
args: [contentHash, record.agent_id]
|
|
2801
|
+
});
|
|
2802
|
+
if (existing.rows.length > 0) return;
|
|
2803
|
+
} catch {
|
|
2804
|
+
}
|
|
2178
2805
|
const dbRow = {
|
|
2179
2806
|
id: record.id,
|
|
2180
2807
|
agent_id: record.agent_id,
|
|
@@ -2204,7 +2831,23 @@ async function writeMemory(record) {
|
|
|
2204
2831
|
supersedes_id: record.supersedes_id ?? null,
|
|
2205
2832
|
draft: record.draft ? 1 : 0,
|
|
2206
2833
|
memory_type: record.memory_type ?? "raw",
|
|
2207
|
-
trajectory: record.trajectory ? JSON.stringify(record.trajectory) : null
|
|
2834
|
+
trajectory: record.trajectory ? JSON.stringify(record.trajectory) : null,
|
|
2835
|
+
content_hash: contentHash,
|
|
2836
|
+
intent: record.intent ?? null,
|
|
2837
|
+
outcome: record.outcome ?? null,
|
|
2838
|
+
domain: record.domain ?? inferDomain(record),
|
|
2839
|
+
referenced_entities: record.referenced_entities ?? null,
|
|
2840
|
+
retrieval_count: record.retrieval_count ?? 0,
|
|
2841
|
+
chain_position: record.chain_position ?? null,
|
|
2842
|
+
review_status: record.review_status ?? null,
|
|
2843
|
+
context_window_pct: record.context_window_pct ?? null,
|
|
2844
|
+
file_paths: record.file_paths ?? inferFilePaths(record),
|
|
2845
|
+
commit_hash: record.commit_hash ?? inferCommitHash(record),
|
|
2846
|
+
duration_ms: record.duration_ms ?? null,
|
|
2847
|
+
token_cost: record.token_cost ?? null,
|
|
2848
|
+
audience: record.audience ?? null,
|
|
2849
|
+
language_type: record.language_type ?? inferLanguageType(record),
|
|
2850
|
+
parent_memory_id: record.parent_memory_id ?? null
|
|
2208
2851
|
};
|
|
2209
2852
|
_pendingRecords.push(dbRow);
|
|
2210
2853
|
orgBus.emit({
|
|
@@ -2262,80 +2905,85 @@ async function flushBatch() {
|
|
|
2262
2905
|
const draft = row.draft ? 1 : 0;
|
|
2263
2906
|
const memoryType = row.memory_type ?? "raw";
|
|
2264
2907
|
const trajectory = row.trajectory ?? null;
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2908
|
+
const contentHash = row.content_hash ?? null;
|
|
2909
|
+
const intent = row.intent ?? null;
|
|
2910
|
+
const outcome = row.outcome ?? null;
|
|
2911
|
+
const domain = row.domain ?? null;
|
|
2912
|
+
const referencedEntities = row.referenced_entities ?? null;
|
|
2913
|
+
const retrievalCount = row.retrieval_count ?? 0;
|
|
2914
|
+
const chainPosition = row.chain_position ?? null;
|
|
2915
|
+
const reviewStatus = row.review_status ?? null;
|
|
2916
|
+
const contextWindowPct = row.context_window_pct ?? null;
|
|
2917
|
+
const filePaths = row.file_paths ?? null;
|
|
2918
|
+
const commitHash = row.commit_hash ?? null;
|
|
2919
|
+
const durationMs = row.duration_ms ?? null;
|
|
2920
|
+
const tokenCost = row.token_cost ?? null;
|
|
2921
|
+
const audience = row.audience ?? null;
|
|
2922
|
+
const languageType = row.language_type ?? null;
|
|
2923
|
+
const parentMemoryId = row.parent_memory_id ?? null;
|
|
2924
|
+
const cols = `id, agent_id, agent_role, session_id, timestamp,
|
|
2275
2925
|
tool_name, project_name,
|
|
2276
2926
|
has_error, raw_text, vector, version, task_id, importance, status,
|
|
2277
2927
|
confidence, last_accessed,
|
|
2278
2928
|
workspace_id, document_id, user_id, char_offset, page_number,
|
|
2279
|
-
source_path, source_type, tier, supersedes_id, draft, memory_type, trajectory
|
|
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
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
trajectory
|
|
2338
|
-
]
|
|
2929
|
+
source_path, source_type, tier, supersedes_id, draft, memory_type, trajectory, content_hash,
|
|
2930
|
+
intent, outcome, domain, referenced_entities, retrieval_count,
|
|
2931
|
+
chain_position, review_status, context_window_pct, file_paths, commit_hash,
|
|
2932
|
+
duration_ms, token_cost, audience, language_type, parent_memory_id`;
|
|
2933
|
+
const metaArgs = [
|
|
2934
|
+
intent,
|
|
2935
|
+
outcome,
|
|
2936
|
+
domain,
|
|
2937
|
+
referencedEntities,
|
|
2938
|
+
retrievalCount,
|
|
2939
|
+
chainPosition,
|
|
2940
|
+
reviewStatus,
|
|
2941
|
+
contextWindowPct,
|
|
2942
|
+
filePaths,
|
|
2943
|
+
commitHash,
|
|
2944
|
+
durationMs,
|
|
2945
|
+
tokenCost,
|
|
2946
|
+
audience,
|
|
2947
|
+
languageType,
|
|
2948
|
+
parentMemoryId
|
|
2949
|
+
];
|
|
2950
|
+
const baseArgs = [
|
|
2951
|
+
row.id,
|
|
2952
|
+
row.agent_id,
|
|
2953
|
+
row.agent_role,
|
|
2954
|
+
row.session_id,
|
|
2955
|
+
row.timestamp,
|
|
2956
|
+
row.tool_name,
|
|
2957
|
+
row.project_name,
|
|
2958
|
+
row.has_error,
|
|
2959
|
+
row.raw_text
|
|
2960
|
+
];
|
|
2961
|
+
const sharedArgs = [
|
|
2962
|
+
row.version,
|
|
2963
|
+
taskId,
|
|
2964
|
+
importance,
|
|
2965
|
+
status,
|
|
2966
|
+
confidence,
|
|
2967
|
+
lastAccessed,
|
|
2968
|
+
workspaceId,
|
|
2969
|
+
documentId,
|
|
2970
|
+
userId,
|
|
2971
|
+
charOffset,
|
|
2972
|
+
pageNumber,
|
|
2973
|
+
sourcePath,
|
|
2974
|
+
sourceType,
|
|
2975
|
+
tier,
|
|
2976
|
+
supersedesId,
|
|
2977
|
+
draft,
|
|
2978
|
+
memoryType,
|
|
2979
|
+
trajectory,
|
|
2980
|
+
contentHash
|
|
2981
|
+
];
|
|
2982
|
+
return {
|
|
2983
|
+
sql: hasVector ? `INSERT OR IGNORE INTO memories (${cols})
|
|
2984
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
|
|
2985
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
2986
|
+
args: hasVector ? [...baseArgs, vectorToBlob(row.vector), ...sharedArgs, ...metaArgs] : [...baseArgs, ...sharedArgs, ...metaArgs]
|
|
2339
2987
|
};
|
|
2340
2988
|
};
|
|
2341
2989
|
const globalClient = getClient();
|
|
@@ -2588,10 +3236,10 @@ var init_store = __esm({
|
|
|
2588
3236
|
// src/adapters/claude/hooks/stop.ts
|
|
2589
3237
|
init_config();
|
|
2590
3238
|
init_config();
|
|
2591
|
-
import { spawn } from "child_process";
|
|
2592
|
-
import { existsSync as
|
|
2593
|
-
import
|
|
2594
|
-
import { fileURLToPath as
|
|
3239
|
+
import { spawn as spawn2 } from "child_process";
|
|
3240
|
+
import { existsSync as existsSync11, openSync as openSync2, closeSync as closeSync2 } from "fs";
|
|
3241
|
+
import path13 from "path";
|
|
3242
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
2595
3243
|
|
|
2596
3244
|
// src/adapters/claude/active-agent.ts
|
|
2597
3245
|
init_config();
|
|
@@ -2704,10 +3352,10 @@ if (!process.env.AGENT_ID) {
|
|
|
2704
3352
|
if (!loadConfigSync().autoIngestion) {
|
|
2705
3353
|
process.exit(0);
|
|
2706
3354
|
}
|
|
2707
|
-
var WORKER_LOG_PATH =
|
|
3355
|
+
var WORKER_LOG_PATH = path13.join(EXE_AI_DIR, "workers.log");
|
|
2708
3356
|
function openWorkerLog() {
|
|
2709
3357
|
try {
|
|
2710
|
-
return
|
|
3358
|
+
return openSync2(WORKER_LOG_PATH, "a");
|
|
2711
3359
|
} catch {
|
|
2712
3360
|
return "ignore";
|
|
2713
3361
|
}
|
|
@@ -2796,17 +3444,17 @@ process.stdin.on("end", () => {
|
|
|
2796
3444
|
}).catch(() => {
|
|
2797
3445
|
});
|
|
2798
3446
|
}
|
|
2799
|
-
const workerPath =
|
|
2800
|
-
|
|
3447
|
+
const workerPath = path13.resolve(
|
|
3448
|
+
path13.dirname(fileURLToPath3(import.meta.url)),
|
|
2801
3449
|
"response-ingest-worker.js"
|
|
2802
3450
|
);
|
|
2803
|
-
if (!
|
|
3451
|
+
if (!existsSync11(workerPath)) {
|
|
2804
3452
|
process.stderr.write(`[stop] WARN: response-ingest-worker not found at ${workerPath}
|
|
2805
3453
|
`);
|
|
2806
3454
|
process.exit(0);
|
|
2807
3455
|
}
|
|
2808
3456
|
const stderrFd = openWorkerLog();
|
|
2809
|
-
const worker =
|
|
3457
|
+
const worker = spawn2(process.execPath, [workerPath], {
|
|
2810
3458
|
detached: true,
|
|
2811
3459
|
stdio: ["ignore", "ignore", stderrFd],
|
|
2812
3460
|
env: {
|
|
@@ -2819,7 +3467,7 @@ process.stdin.on("end", () => {
|
|
|
2819
3467
|
});
|
|
2820
3468
|
worker.unref();
|
|
2821
3469
|
if (typeof stderrFd === "number") try {
|
|
2822
|
-
|
|
3470
|
+
closeSync2(stderrFd);
|
|
2823
3471
|
} catch {
|
|
2824
3472
|
}
|
|
2825
3473
|
} catch {
|