@askexenow/exe-os 0.9.127 → 0.9.129
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/active-agent-3FDJYREJ.js +22 -0
- package/dist/active-agent-WC7YK3L5.js +23 -0
- package/dist/agent-context-CDWUZEXY.js +11 -0
- package/dist/agent-loop-G4VUR5ME.js +10 -0
- package/dist/agentic-ontology-2VYNTMNO.js +25 -0
- package/dist/backfill-metadata-OJWOCLSZ.js +601 -0
- package/dist/background-jobs-LGRDXGXC.js +25 -0
- package/dist/bash-Y5PEW5UQ.js +8 -0
- package/dist/behaviors-CSB2YLDT.js +22 -0
- package/dist/bin/age-ontology-load.js +10 -258
- package/dist/bin/agentic-ontology-backfill.js +23 -5296
- package/dist/bin/agentic-reflection-backfill.js +19 -4739
- package/dist/bin/agentic-semantic-label.js +28 -4723
- package/dist/bin/backfill-conversations.js +42 -5543
- package/dist/bin/backfill-responses.js +41 -5542
- package/dist/bin/backfill-vectors.js +43 -4795
- package/dist/bin/bulk-sync-postgres.js +22 -5313
- package/dist/bin/cc-doctor.js +10 -602
- package/dist/bin/cleanup-stale-review-tasks.js +32 -6803
- package/dist/bin/cli.js +169 -38993
- package/dist/bin/exe-agent-config.js +21 -253
- package/dist/bin/exe-agent.js +63 -2429
- package/dist/bin/exe-assign.js +34 -5810
- package/dist/bin/exe-boot.js +180 -12726
- package/dist/bin/exe-call.js +48 -1409
- package/dist/bin/exe-cloud.js +64 -8516
- package/dist/bin/exe-dispatch.js +35 -10818
- package/dist/bin/exe-doctor.js +24 -7537
- package/dist/bin/exe-export-behaviors.js +18 -6122
- package/dist/bin/exe-forget.js +22 -6274
- package/dist/bin/exe-gateway.js +62 -15286
- package/dist/bin/exe-healthcheck.js +9 -602
- package/dist/bin/exe-heartbeat.js +51 -6898
- package/dist/bin/exe-kill.js +30 -5961
- package/dist/bin/exe-launch-agent.js +101 -6788
- package/dist/bin/exe-new-employee.js +42 -3774
- package/dist/bin/exe-pending-messages.js +28 -6833
- package/dist/bin/exe-pending-notifications.js +31 -6869
- package/dist/bin/exe-pending-reviews.js +38 -6910
- package/dist/bin/exe-rename.js +57 -5766
- package/dist/bin/exe-review.js +29 -5948
- package/dist/bin/exe-search.js +22 -7692
- package/dist/bin/exe-session-cleanup.js +52 -11147
- package/dist/bin/exe-settings.js +35 -524
- package/dist/bin/exe-start-codex.js +70 -6641
- package/dist/bin/exe-start-opencode.js +54 -6584
- package/dist/bin/exe-status.js +26 -7081
- package/dist/bin/exe-support.js +10 -546
- package/dist/bin/exe-team.js +18 -5942
- package/dist/bin/git-sweep.js +26 -10909
- package/dist/bin/graph-backfill.js +24 -5979
- package/dist/bin/graph-export.js +31 -6128
- package/dist/bin/graph-layer-benchmark.js +4 -8
- package/dist/bin/install.js +47 -2322
- package/dist/bin/intercom-check.js +25 -11501
- package/dist/bin/list-providers.js +4 -18
- package/dist/bin/postgres-agentic-reflection-backfill.js +14 -357
- package/dist/bin/postgres-agentic-semantic-backfill.js +14 -404
- package/dist/bin/pre-publish.js +4 -298
- package/dist/bin/registry-proxy.js +8 -172
- package/dist/bin/scan-tasks.js +47 -10881
- package/dist/bin/setup.js +6 -9492
- package/dist/bin/shard-migrate.js +30 -5149
- package/dist/bin/stack-update.js +75 -203
- package/dist/bin/update.js +20 -654
- package/dist/capacity-monitor-3GZIHLB4.js +46 -0
- package/dist/catchup-brief-67QDCINS.js +148 -0
- package/dist/chunk-2QD7KBJN.js +664 -0
- package/dist/chunk-2WGSIVI4.js +149 -0
- package/dist/chunk-35TVNLJI.js +57 -0
- package/dist/chunk-3SYV36U5.js +47 -0
- package/dist/chunk-46SQTBQW.js +207 -0
- package/dist/chunk-4CMVLKEI.js +171 -0
- package/dist/chunk-4FLUOZTR.js +116 -0
- package/dist/chunk-4NYQAS33.js +17 -0
- package/dist/chunk-4QNPADWL.js +902 -0
- package/dist/chunk-4Y6QZBEO.js +58 -0
- package/dist/chunk-557C2IGL.js +0 -0
- package/dist/chunk-55S56YDO.js +305 -0
- package/dist/chunk-5BS5ELMC.js +85 -0
- package/dist/chunk-5DHM77JE.js +256 -0
- package/dist/chunk-5QTWQKNF.js +137 -0
- package/dist/chunk-6A7P74QV.js +53 -0
- package/dist/chunk-6BFIFI5F.js +45 -0
- package/dist/chunk-6KFICEAT.js +20 -0
- package/dist/chunk-6LKDJ5WX.js +317 -0
- package/dist/chunk-6M5II4EV.js +148 -0
- package/dist/chunk-6QEFN3DV.js +302 -0
- package/dist/chunk-6WTMJAG3.js +171 -0
- package/dist/chunk-6Y4B3QF6.js +19 -0
- package/dist/chunk-7RK3AYJE.js +163 -0
- package/dist/chunk-7TCP2XTP.js +390 -0
- package/dist/chunk-A2NZP64U.js +2307 -0
- package/dist/chunk-AFYIYM2K.js +322 -0
- package/dist/chunk-AJWFPKQS.js +573 -0
- package/dist/chunk-AVE2B4DQ.js +140 -0
- package/dist/chunk-B4TT2QQA.js +87 -0
- package/dist/chunk-BCMOO4OQ.js +1066 -0
- package/dist/chunk-BU3ID2WT.js +432 -0
- package/dist/chunk-CFIM43JH.js +862 -0
- package/dist/chunk-CURJUF3W.js +66 -0
- package/dist/chunk-DC4ZD76Y.js +288 -0
- package/dist/chunk-DL52JPGF.js +706 -0
- package/dist/chunk-DRSC6ZRA.js +36 -0
- package/dist/chunk-E2Q4Y22A.js +86 -0
- package/dist/chunk-ECGTESAP.js +236 -0
- package/dist/chunk-EHOJUXYG.js +365 -0
- package/dist/chunk-EIT6J37V.js +119 -0
- package/dist/chunk-ELE2C7L4.js +31 -0
- package/dist/chunk-EQSQ4HBW.js +9 -0
- package/dist/chunk-FWFFZGSC.js +94 -0
- package/dist/chunk-GCNWCYJI.js +249 -0
- package/dist/chunk-GGTUUI7J.js +6 -0
- package/dist/chunk-GU56L7OY.js +223 -0
- package/dist/chunk-HF25XPZE.js +83 -0
- package/dist/chunk-HOKOOBDL.js +52 -0
- package/dist/chunk-HP43GLZ6.js +89 -0
- package/dist/chunk-HSRM6PNM.js +682 -0
- package/dist/chunk-HVRTW3OP.js +164 -0
- package/dist/chunk-IHDHL5ML.js +125 -0
- package/dist/chunk-IHF5RXJM.js +168 -0
- package/dist/chunk-IJ73YE73.js +409 -0
- package/dist/chunk-INO4ZD5Y.js +162 -0
- package/dist/chunk-IRQTM7DY.js +475 -0
- package/dist/chunk-JD4FAPYG.js +1208 -0
- package/dist/chunk-JN44LQ53.js +316 -0
- package/dist/chunk-JQ6TLNIV.js +133 -0
- package/dist/chunk-JT76KRZQ.js +35 -0
- package/dist/chunk-K6OEWZTB.js +262 -0
- package/dist/chunk-KCUYRZSX.js +72 -0
- package/dist/chunk-KFQGP6VL.js +33 -0
- package/dist/chunk-KRLOFIPI.js +83 -0
- package/dist/chunk-KVPG5UT6.js +305 -0
- package/dist/chunk-L3TB7CC3.js +170 -0
- package/dist/chunk-L4X5EUHR.js +283 -0
- package/dist/chunk-LAN26C3W.js +655 -0
- package/dist/chunk-LPGBKR4H.js +54 -0
- package/dist/chunk-LVNMOVGD.js +132 -0
- package/dist/chunk-LX5WEEZ7.js +157 -0
- package/dist/chunk-MBH42QNH.js +295 -0
- package/dist/chunk-MFO7MNSD.js +102 -0
- package/dist/chunk-MILTNDZH.js +736 -0
- package/dist/chunk-MJAE4NB7.js +1090 -0
- package/dist/chunk-MLCUPTP7.js +132 -0
- package/dist/chunk-MPURH6JI.js +445 -0
- package/dist/chunk-MVBWW2EO.js +89 -0
- package/dist/chunk-MZIGUUDQ.js +42 -0
- package/dist/chunk-N3DTSVKE.js +157 -0
- package/dist/chunk-N5RRQOAC.js +134 -0
- package/dist/chunk-N7L33TED.js +1664 -0
- package/dist/chunk-NDYSNVI5.js +122 -0
- package/dist/chunk-NEAHEC5G.js +155 -0
- package/dist/chunk-NGVOA6ZQ.js +84 -0
- package/dist/chunk-NHK5KW6Y.js +193 -0
- package/dist/chunk-NMQKGFEP.js +458 -0
- package/dist/chunk-NPT4EHZK.js +352 -0
- package/dist/chunk-NXFJHTED.js +55 -0
- package/dist/chunk-NZLCDI6Y.js +216 -0
- package/dist/chunk-O377P7GM.js +100 -0
- package/dist/chunk-O4VFZRA5.js +33 -0
- package/dist/chunk-O7YD7JYE.js +237 -0
- package/dist/chunk-OFK72LTZ.js +81 -0
- package/dist/chunk-ORCCI2VV.js +140 -0
- package/dist/chunk-OVQR4KMC.js +579 -0
- package/dist/chunk-P3CVUMEH.js +54 -0
- package/dist/chunk-P4HIF72O.js +30 -0
- package/dist/chunk-PEDLSJBL.js +1039 -0
- package/dist/chunk-PFICKZZ5.js +219 -0
- package/dist/chunk-PGW7TIV6.js +142 -0
- package/dist/chunk-PJHHFJAN.js +63 -0
- package/dist/chunk-PP4SNOJ5.js +471 -0
- package/dist/chunk-PRKVT4KN.js +90 -0
- package/dist/chunk-Q2O4VJHH.js +305 -0
- package/dist/chunk-Q36CMZIX.js +38 -0
- package/dist/chunk-Q3V7K4ME.js +149 -0
- package/dist/chunk-QGYPJGHB.js +81 -0
- package/dist/chunk-R23EMFJV.js +198 -0
- package/dist/chunk-R4M6XCMU.js +39 -0
- package/dist/chunk-R4WMF32C.js +81 -0
- package/dist/chunk-RJT7H2KR.js +349 -0
- package/dist/chunk-RJZMRZNV.js +280 -0
- package/dist/chunk-RMFDPCA2.js +72 -0
- package/dist/chunk-RUG3N6P4.js +292 -0
- package/dist/chunk-RWO327FJ.js +84 -0
- package/dist/chunk-SG7EFHQ7.js +108 -0
- package/dist/chunk-SH45SJQW.js +0 -0
- package/dist/chunk-SPKE5ANC.js +42 -0
- package/dist/chunk-SVMFVPBF.js +104 -0
- package/dist/chunk-SVXDCELZ.js +163 -0
- package/dist/chunk-TMEE7AT7.js +72 -0
- package/dist/chunk-TWYEE4FB.js +125 -0
- package/dist/chunk-TYLF4LSW.js +110 -0
- package/dist/chunk-V4TZI6EO.js +60 -0
- package/dist/chunk-VFZTXKQI.js +372 -0
- package/dist/chunk-VQ4K2MLM.js +199 -0
- package/dist/chunk-VU447UAO.js +173 -0
- package/dist/chunk-WMC3TXJF.js +50 -0
- package/dist/chunk-WPOA7XAE.js +84 -0
- package/dist/chunk-WZQ4CPRG.js +64 -0
- package/dist/chunk-X2IMCCM5.js +49 -0
- package/dist/chunk-X2Z5GT3V.js +118 -0
- package/dist/chunk-XEKO37NM.js +43 -0
- package/dist/chunk-XUHFQHGZ.js +505 -0
- package/dist/chunk-YGAAZN3E.js +47 -0
- package/dist/chunk-YKOW7KMK.js +558 -0
- package/dist/chunk-YOQKMB6N.js +145 -0
- package/dist/chunk-YZFZDJWZ.js +107 -0
- package/dist/chunk-ZBY4AUD4.js +10342 -0
- package/dist/chunk-ZOJYPNCM.js +127 -0
- package/dist/chunk-ZS7MGQSD.js +1494 -0
- package/dist/chunk-ZTZQ5A6B.js +191 -0
- package/dist/code-context-index-HXGC4IJL.js +28 -0
- package/dist/content-extractor-UVZXRIPC.js +8 -0
- package/dist/conversation-entity-extractor-HKSNDF4L.js +113 -0
- package/dist/conversation-wiki-populator-NKDAQEZ5.js +105 -0
- package/dist/crdt-sync-T7MHVQCS.js +33 -0
- package/dist/crm-bridge-Q5JBVJ6P.js +19 -0
- package/dist/crm-webhook-OAFTLJYA.js +10 -0
- package/dist/cto-delegation-gate-XWHZCUJH.js +208 -0
- package/dist/daemon-auth-GWUXTUYO.js +15 -0
- package/dist/daemon-orchestration-2C3TVOHO.js +91 -0
- package/dist/daemon-protocol-RLH2XM2K.js +19 -0
- package/dist/db-backup-CH2KG3JY.js +23 -0
- package/dist/devtools-PLJCAU53.js +8 -0
- package/dist/discord-G4BQJ2VX.js +7 -0
- package/dist/email-XMRNMFXR.js +137 -0
- package/dist/entity-boost-IOER4VRR.js +249 -0
- package/dist/exe-drift-2IJFQV43.js +68 -0
- package/dist/exe-export-Y2RFXGNB.js +71 -0
- package/dist/exe-import-LN6PE2YT.js +74 -0
- package/dist/exe-key-DHKBWLIT.js +571 -0
- package/dist/exe-org-F7LZRHFB.js +73 -0
- package/dist/factory-YTD23AW7.js +67 -0
- package/dist/fast-db-init-IIP6EGWT.js +7 -0
- package/dist/file-edit-FJVEO7XZ.js +8 -0
- package/dist/file-read-Q2NH3J35.js +8 -0
- package/dist/file-write-UNSFXNH4.js +8 -0
- package/dist/gateway/index.js +87 -16563
- package/dist/gateway-client-APTYJNCL.js +11 -0
- package/dist/git-staleness-I2BUEDE2.js +111 -0
- package/dist/git-task-sweep-UEOTXRW4.js +35 -0
- package/dist/glob-GRMXLDMB.js +7 -0
- package/dist/global-procedures-MFE5LGRF.js +19 -0
- package/dist/graph-query-657O5JYJ.js +25 -0
- package/dist/graph-rag-ZE5N7C65.js +28 -0
- package/dist/grep-NBV6SKYZ.js +7 -0
- package/dist/hooks/bug-report-worker.js +41 -10823
- package/dist/hooks/codex-stop-task-finalizer.js +38 -9055
- package/dist/hooks/commit-complete.js +32 -10914
- package/dist/hooks/error-recall.js +35 -7955
- package/dist/hooks/exe-heartbeat-hook.js +17 -327
- package/dist/hooks/ingest-worker.js +16 -565
- package/dist/hooks/ingest.js +98 -11436
- package/dist/hooks/instructions-loaded.js +25 -6209
- package/dist/hooks/notification.js +16 -6098
- package/dist/hooks/post-compact.js +34 -7041
- package/dist/hooks/post-tool-combined.js +27 -9751
- package/dist/hooks/pre-compact.js +38 -11130
- package/dist/hooks/pre-tool-use.js +61 -7233
- package/dist/hooks/prompt-submit.js +113 -13358
- package/dist/hooks/session-end.js +57 -11503
- package/dist/hooks/session-start.js +46 -9423
- package/dist/hooks/stop.js +70 -7210
- package/dist/hooks/subagent-stop.js +33 -6897
- package/dist/hooks/summary-worker.js +86 -8629
- package/dist/hooks-KD3N2D7P.js +9 -0
- package/dist/imessage-L7WKA2WD.js +7 -0
- package/dist/index.js +49 -19391
- package/dist/installer-5N24GXFB.js +32 -0
- package/dist/installer-QSD76YRY.js +291 -0
- package/dist/installer-ZPQUKHU5.js +331 -0
- package/dist/intercom-queue-PEEGAJ33.js +19 -0
- package/dist/key-backup-status-57UB74DU.js +41 -0
- package/dist/lib/agent-config.js +19 -224
- package/dist/lib/cloud-sync.js +44 -5398
- package/dist/lib/cloudflare-dns.js +7 -111
- package/dist/lib/config.js +18 -278
- package/dist/lib/consolidation.js +21 -1047
- package/dist/lib/crypto.js +7 -45
- package/dist/lib/database.js +20 -2932
- package/dist/lib/db-daemon-client.js +24 -460
- package/dist/lib/db.js +22 -2932
- package/dist/lib/device-registry.js +20 -2992
- package/dist/lib/embedder.js +14 -822
- package/dist/lib/employee-templates.js +21 -1102
- package/dist/lib/employees.js +30 -497
- package/dist/lib/error-detector.js +9 -149
- package/dist/lib/exe-daemon-client.js +16 -570
- package/dist/lib/exe-daemon.js +509 -18398
- package/dist/lib/file-grep.js +2 -0
- package/dist/lib/hybrid-search.js +18 -7674
- package/dist/lib/identity-templates.js +2 -0
- package/dist/lib/identity.js +13 -309
- package/dist/lib/keychain.js +9 -499
- package/dist/lib/license.js +21 -549
- package/dist/lib/messaging.js +35 -1631
- package/dist/lib/post-tool-memory.js +8 -370
- package/dist/lib/registry-proxy.js +8 -155
- package/dist/lib/reminders.js +11 -231
- package/dist/lib/runtime-table.js +7 -20
- package/dist/lib/schedules.js +16 -4614
- package/dist/lib/session-registry.js +9 -57
- package/dist/lib/session-wrappers.js +3 -127
- package/dist/lib/skill-learning.js +20 -2101
- package/dist/lib/status-brief.js +4 -368
- package/dist/lib/store.js +25 -5593
- package/dist/lib/task-router.js +12 -254
- package/dist/lib/tasks.js +44 -5801
- package/dist/lib/tmux-routing.js +45 -5804
- package/dist/lib/tmux-status.js +16 -248
- package/dist/lib/tmux-transport.js +6 -90
- package/dist/lib/token-spend.js +9 -337
- package/dist/lib/transport.js +8 -134
- package/dist/lib/ws-auth.js +6 -14
- package/dist/lib/ws-client.js +4 -22
- package/dist/license-gate-NXXDOOAQ.js +14 -0
- package/dist/mcp/register-tools.js +90 -32454
- package/dist/mcp/server.js +139 -32625
- package/dist/mcp/tools/complete-reminder.js +10 -237
- package/dist/mcp/tools/create-reminder.js +10 -222
- package/dist/mcp/tools/create-task.js +28 -6730
- package/dist/mcp/tools/deactivate-behavior.js +13 -476
- package/dist/mcp/tools/list-reminders.js +10 -232
- package/dist/mcp/tools/list-tasks.js +28 -1571
- package/dist/mcp/tools/send-message.js +25 -1672
- package/dist/mcp/tools/update-task.js +27 -6123
- package/dist/mcp-diagnostics-OOZ3TDPY.js +200 -0
- package/dist/memory-cards-RIL5BZHK.js +175 -0
- package/dist/memory-queue-JYIJ7TMQ.js +13 -0
- package/dist/memory-queue-client-PE7757HU.js +14 -0
- package/dist/notifications-CJFULBMN.js +42 -0
- package/dist/orchestration-phase-Y2TYNW5H.js +23 -0
- package/dist/orchestrator-RXIPT6PZ.js +29 -0
- package/dist/permission-presets-WI524OSE.js +25 -0
- package/dist/permissions-TYT6YMNZ.js +14 -0
- package/dist/pg-ssl-KFHNJPGO.js +7 -0
- package/dist/plan-limits-5WY5YK6X.js +27 -0
- package/dist/preferences-MW3BYTQ5.js +10 -0
- package/dist/project-name-PL2ZDWNU.js +11 -0
- package/dist/projection-worker-OY4WYZW6.js +661 -0
- package/dist/reranker-LFJ73RRS.js +19 -0
- package/dist/review-gate-E6K7QQE5.js +120 -0
- package/dist/runtime/index.js +82 -13408
- package/dist/self-query-router-IZANO632.js +83 -0
- package/dist/session-events-TQ6S5KQN.js +32 -0
- package/dist/session-kill-telemetry-46YIJWE2.js +30 -0
- package/dist/session-scope-3MYK3YRV.js +34 -0
- package/dist/setup-wizard-ZJ7UCRBP.js +12 -0
- package/dist/shard-manager-RCFZ6RXY.js +29 -0
- package/dist/signal-XN2C7PIG.js +7 -0
- package/dist/slack-Z77TFJCK.js +7 -0
- package/dist/task-enforcement-337DZI3I.js +252 -0
- package/dist/task-scanner-IMIR3T7T.js +11 -0
- package/dist/task-scope-MUU4KXE6.js +32 -0
- package/dist/tasks-crud-PMLK3MM4.js +53 -0
- package/dist/tasks-review-56LVKKNL.js +44 -0
- package/dist/telegram-CRPZO7JT.js +7 -0
- package/dist/telemetry-SPVGPKU7.js +9 -0
- package/dist/tool-capability-index-XNBSDCH3.js +10 -0
- package/dist/tool-gates-LGH6CSY4.js +14 -0
- package/dist/tool-gates-W7SZCYTX.js +13 -0
- package/dist/tool-registry-436LVVLY.js +11 -0
- package/dist/tool-telemetry-L77WNAYT.js +15 -0
- package/dist/tui/App.js +253 -14668
- package/dist/tui-data-SB45REYU.js +161 -0
- package/dist/update-check-LZGZISRJ.js +11 -0
- package/dist/webhook-VVP7KQVC.js +96 -0
- package/dist/whatsapp-J6QNDBGY.js +9 -0
- package/dist/whatsapp-accounts-RTJF3LM6.js +15 -0
- package/dist/wiki-client-EKCIKCVC.js +136 -0
- package/dist/worker-gate-UYNN62GJ.js +19 -0
- package/dist/worktree-4T4BPWPN.js +205 -0
- package/package.json +1 -1
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import {
|
|
2
|
+
EXE_AI_DIR,
|
|
3
|
+
init_config
|
|
4
|
+
} from "./chunk-KVPG5UT6.js";
|
|
5
|
+
import {
|
|
6
|
+
__esm,
|
|
7
|
+
__export
|
|
8
|
+
} from "./chunk-KFQGP6VL.js";
|
|
9
|
+
|
|
10
|
+
// src/lib/db-backup.ts
|
|
11
|
+
var db_backup_exports = {};
|
|
12
|
+
__export(db_backup_exports, {
|
|
13
|
+
createBackup: () => createBackup,
|
|
14
|
+
findActiveDb: () => findActiveDb,
|
|
15
|
+
getBackupDir: () => getBackupDir,
|
|
16
|
+
getLatestBackup: () => getLatestBackup,
|
|
17
|
+
hasBackupToday: () => hasBackupToday,
|
|
18
|
+
listBackups: () => listBackups,
|
|
19
|
+
rotateBackups: () => rotateBackups
|
|
20
|
+
});
|
|
21
|
+
import { copyFileSync, existsSync, mkdirSync, readdirSync, unlinkSync, statSync } from "fs";
|
|
22
|
+
import path from "path";
|
|
23
|
+
function findActiveDb() {
|
|
24
|
+
for (const name of DB_NAMES) {
|
|
25
|
+
const p = path.join(EXE_AI_DIR, name);
|
|
26
|
+
if (existsSync(p)) return p;
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
function createBackup(reason = "manual") {
|
|
31
|
+
const dbPath = findActiveDb();
|
|
32
|
+
if (!dbPath) return null;
|
|
33
|
+
mkdirSync(BACKUP_DIR, { recursive: true });
|
|
34
|
+
const dbName = path.basename(dbPath, ".db");
|
|
35
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
36
|
+
const backupName = `${dbName}-${reason}-${timestamp}.db`;
|
|
37
|
+
const backupPath = path.join(BACKUP_DIR, backupName);
|
|
38
|
+
copyFileSync(dbPath, backupPath);
|
|
39
|
+
const walPath = dbPath + "-wal";
|
|
40
|
+
if (existsSync(walPath)) {
|
|
41
|
+
try {
|
|
42
|
+
copyFileSync(walPath, backupPath + "-wal");
|
|
43
|
+
} catch {
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
const shmPath = dbPath + "-shm";
|
|
47
|
+
if (existsSync(shmPath)) {
|
|
48
|
+
try {
|
|
49
|
+
copyFileSync(shmPath, backupPath + "-shm");
|
|
50
|
+
} catch {
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return backupPath;
|
|
54
|
+
}
|
|
55
|
+
function rotateBackups(keepDays = DEFAULT_KEEP_DAYS) {
|
|
56
|
+
if (!existsSync(BACKUP_DIR)) return 0;
|
|
57
|
+
const cutoff = Date.now() - keepDays * 24 * 60 * 60 * 1e3;
|
|
58
|
+
let deleted = 0;
|
|
59
|
+
try {
|
|
60
|
+
const files = readdirSync(BACKUP_DIR);
|
|
61
|
+
for (const file of files) {
|
|
62
|
+
if (!file.endsWith(".db") && !file.endsWith(".db-wal") && !file.endsWith(".db-shm")) continue;
|
|
63
|
+
const filePath = path.join(BACKUP_DIR, file);
|
|
64
|
+
try {
|
|
65
|
+
const stat = statSync(filePath);
|
|
66
|
+
if (stat.mtimeMs < cutoff) {
|
|
67
|
+
unlinkSync(filePath);
|
|
68
|
+
deleted++;
|
|
69
|
+
}
|
|
70
|
+
} catch {
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
} catch {
|
|
74
|
+
}
|
|
75
|
+
return deleted;
|
|
76
|
+
}
|
|
77
|
+
function listBackups() {
|
|
78
|
+
if (!existsSync(BACKUP_DIR)) return [];
|
|
79
|
+
try {
|
|
80
|
+
const files = readdirSync(BACKUP_DIR).filter((f) => f.endsWith(".db") && !f.endsWith("-wal") && !f.endsWith("-shm"));
|
|
81
|
+
return files.map((name) => {
|
|
82
|
+
const p = path.join(BACKUP_DIR, name);
|
|
83
|
+
const stat = statSync(p);
|
|
84
|
+
return { path: p, name, size: stat.size, date: stat.mtime };
|
|
85
|
+
}).sort((a, b) => b.date.getTime() - a.date.getTime());
|
|
86
|
+
} catch {
|
|
87
|
+
return [];
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function hasBackupToday(reason) {
|
|
91
|
+
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
92
|
+
const backups = listBackups();
|
|
93
|
+
return backups.some((b) => b.name.includes(reason) && b.name.includes(today.replace(/-/g, "-")));
|
|
94
|
+
}
|
|
95
|
+
function getLatestBackup() {
|
|
96
|
+
const backups = listBackups();
|
|
97
|
+
return backups.length > 0 ? backups[0].path : null;
|
|
98
|
+
}
|
|
99
|
+
function getBackupDir() {
|
|
100
|
+
return BACKUP_DIR;
|
|
101
|
+
}
|
|
102
|
+
var BACKUP_DIR, DEFAULT_KEEP_DAYS, DB_NAMES;
|
|
103
|
+
var init_db_backup = __esm({
|
|
104
|
+
"src/lib/db-backup.ts"() {
|
|
105
|
+
init_config();
|
|
106
|
+
BACKUP_DIR = path.join(EXE_AI_DIR, "backups");
|
|
107
|
+
DEFAULT_KEEP_DAYS = 3;
|
|
108
|
+
DB_NAMES = ["memories.db", "exe-mem.db", "exe-os.db", "exe.db"];
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
export {
|
|
113
|
+
findActiveDb,
|
|
114
|
+
createBackup,
|
|
115
|
+
rotateBackups,
|
|
116
|
+
listBackups,
|
|
117
|
+
hasBackupToday,
|
|
118
|
+
getLatestBackup,
|
|
119
|
+
getBackupDir,
|
|
120
|
+
db_backup_exports,
|
|
121
|
+
init_db_backup
|
|
122
|
+
};
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__esm,
|
|
3
|
+
__export,
|
|
4
|
+
__require
|
|
5
|
+
} from "./chunk-KFQGP6VL.js";
|
|
6
|
+
|
|
7
|
+
// src/lib/intercom-queue.ts
|
|
8
|
+
var intercom_queue_exports = {};
|
|
9
|
+
__export(intercom_queue_exports, {
|
|
10
|
+
_resetDrainGuard: () => _resetDrainGuard,
|
|
11
|
+
clearQueueForAgent: () => clearQueueForAgent,
|
|
12
|
+
drainForSession: () => drainForSession,
|
|
13
|
+
drainQueue: () => drainQueue,
|
|
14
|
+
queueIntercom: () => queueIntercom,
|
|
15
|
+
readQueue: () => readQueue
|
|
16
|
+
});
|
|
17
|
+
import { readFileSync, writeFileSync, renameSync, existsSync, mkdirSync } from "fs";
|
|
18
|
+
import path from "path";
|
|
19
|
+
import os from "os";
|
|
20
|
+
function ensureDir() {
|
|
21
|
+
const dir = path.dirname(QUEUE_PATH);
|
|
22
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
23
|
+
}
|
|
24
|
+
function readQueue() {
|
|
25
|
+
try {
|
|
26
|
+
if (!existsSync(QUEUE_PATH)) return [];
|
|
27
|
+
return JSON.parse(readFileSync(QUEUE_PATH, "utf8"));
|
|
28
|
+
} catch {
|
|
29
|
+
return [];
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function writeQueue(queue) {
|
|
33
|
+
ensureDir();
|
|
34
|
+
const tmp = `${QUEUE_PATH}.tmp`;
|
|
35
|
+
writeFileSync(tmp, JSON.stringify(queue, null, 2), { mode: 384 });
|
|
36
|
+
renameSync(tmp, QUEUE_PATH);
|
|
37
|
+
}
|
|
38
|
+
function queueIntercom(targetSession, reason) {
|
|
39
|
+
const queue = readQueue();
|
|
40
|
+
const existing = queue.find((q) => q.targetSession === targetSession);
|
|
41
|
+
if (existing) {
|
|
42
|
+
existing.attempts++;
|
|
43
|
+
existing.queuedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
44
|
+
existing.reason = reason;
|
|
45
|
+
} else {
|
|
46
|
+
queue.push({
|
|
47
|
+
targetSession,
|
|
48
|
+
queuedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
49
|
+
attempts: 0,
|
|
50
|
+
reason
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
writeQueue(queue);
|
|
54
|
+
}
|
|
55
|
+
function drainQueue(isSessionBusy, sendKeys) {
|
|
56
|
+
if (_draining) {
|
|
57
|
+
logQueue("SKIP_DRAIN \u2014 previous drain still running (possible tmux hang)");
|
|
58
|
+
return { drained: 0, failed: 0 };
|
|
59
|
+
}
|
|
60
|
+
const queue = readQueue();
|
|
61
|
+
if (queue.length === 0) return { drained: 0, failed: 0 };
|
|
62
|
+
_draining = true;
|
|
63
|
+
const remaining = [];
|
|
64
|
+
let drained = 0;
|
|
65
|
+
let failed = 0;
|
|
66
|
+
try {
|
|
67
|
+
for (const item of queue) {
|
|
68
|
+
const age = Date.now() - new Date(item.queuedAt).getTime();
|
|
69
|
+
if (age > TTL_MS) {
|
|
70
|
+
logQueue(`EXPIRED \u2192 ${item.targetSession} (${Math.round(age / 6e4)}min old, reason: ${item.reason})`);
|
|
71
|
+
failed++;
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
if (!isSessionBusy(item.targetSession)) {
|
|
76
|
+
const success = sendKeys(item.targetSession);
|
|
77
|
+
if (success) {
|
|
78
|
+
logQueue(`DRAINED \u2192 ${item.targetSession} (after ${item.attempts} retries)`);
|
|
79
|
+
drained++;
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
} catch {
|
|
84
|
+
}
|
|
85
|
+
item.attempts++;
|
|
86
|
+
if (item.attempts >= MAX_RETRIES) {
|
|
87
|
+
logQueue(`FAILED \u2192 ${item.targetSession} (${MAX_RETRIES} retries exhausted, reason: ${item.reason})`);
|
|
88
|
+
failed++;
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
remaining.push(item);
|
|
92
|
+
}
|
|
93
|
+
writeQueue(remaining);
|
|
94
|
+
} finally {
|
|
95
|
+
_draining = false;
|
|
96
|
+
}
|
|
97
|
+
return { drained, failed };
|
|
98
|
+
}
|
|
99
|
+
function drainForSession(targetSession, sendKeys) {
|
|
100
|
+
const queue = readQueue();
|
|
101
|
+
const match = queue.findIndex((q) => q.targetSession === targetSession);
|
|
102
|
+
if (match < 0) return false;
|
|
103
|
+
const success = sendKeys(targetSession);
|
|
104
|
+
if (success) {
|
|
105
|
+
queue.splice(match, 1);
|
|
106
|
+
writeQueue(queue);
|
|
107
|
+
logQueue(`DRAINED \u2192 ${targetSession} (prompt-submit trigger)`);
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
function clearQueueForAgent(agentName) {
|
|
113
|
+
const queue = readQueue();
|
|
114
|
+
const before = queue.length;
|
|
115
|
+
const filtered = queue.filter((q) => !q.targetSession.startsWith(`${agentName}-`));
|
|
116
|
+
if (filtered.length < before) {
|
|
117
|
+
writeQueue(filtered);
|
|
118
|
+
logQueue(`CLEARED ${before - filtered.length} stale item(s) for ${agentName}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function _resetDrainGuard() {
|
|
122
|
+
_draining = false;
|
|
123
|
+
}
|
|
124
|
+
function logQueue(msg) {
|
|
125
|
+
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] [queue] ${msg}
|
|
126
|
+
`;
|
|
127
|
+
process.stderr.write(`[intercom-queue] ${msg}
|
|
128
|
+
`);
|
|
129
|
+
try {
|
|
130
|
+
const { appendFileSync } = __require("fs");
|
|
131
|
+
appendFileSync(INTERCOM_LOG, line);
|
|
132
|
+
} catch {
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
var QUEUE_PATH, MAX_RETRIES, TTL_MS, _draining, INTERCOM_LOG;
|
|
136
|
+
var init_intercom_queue = __esm({
|
|
137
|
+
"src/lib/intercom-queue.ts"() {
|
|
138
|
+
QUEUE_PATH = path.join(os.homedir(), ".exe-os", "intercom-queue.json");
|
|
139
|
+
MAX_RETRIES = 5;
|
|
140
|
+
TTL_MS = 60 * 60 * 1e3;
|
|
141
|
+
_draining = false;
|
|
142
|
+
INTERCOM_LOG = path.join(os.homedir(), ".exe-os", "intercom.log");
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
export {
|
|
147
|
+
readQueue,
|
|
148
|
+
queueIntercom,
|
|
149
|
+
drainQueue,
|
|
150
|
+
drainForSession,
|
|
151
|
+
clearQueueForAgent,
|
|
152
|
+
_resetDrainGuard,
|
|
153
|
+
intercom_queue_exports,
|
|
154
|
+
init_intercom_queue
|
|
155
|
+
};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// src/runtime/safety-checks.ts
|
|
2
|
+
import path from "path";
|
|
3
|
+
import os from "os";
|
|
4
|
+
var HOME = os.homedir();
|
|
5
|
+
var BYPASS_IMMUNE_PATTERNS = [
|
|
6
|
+
{
|
|
7
|
+
pattern: /\/\.git\/hooks\//,
|
|
8
|
+
reason: "Git hooks can execute arbitrary code"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
pattern: /\/\.git\/config$/,
|
|
12
|
+
reason: "Git config can set hooks and command execution"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
pattern: (p) => p.startsWith(path.join(HOME, ".claude")),
|
|
16
|
+
reason: "Claude configuration files are protected"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
pattern: (p) => p.startsWith(path.join(HOME, ".exe-os")),
|
|
20
|
+
reason: "exe-os configuration files are protected"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
pattern: /\/\.env($|\.)/,
|
|
24
|
+
reason: "Environment files may contain secrets"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
pattern: /\/(credentials|secrets|tokens)\.(json|yaml|yml|toml|ini|conf)$/i,
|
|
28
|
+
reason: "Credential files are protected"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
pattern: /(\.pem|\.key|\.p12|\.pfx|\.jks|id_rsa|id_ed25519)$/,
|
|
32
|
+
reason: "Private key files are protected"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
pattern: (p) => {
|
|
36
|
+
const name = path.basename(p);
|
|
37
|
+
return [".bashrc", ".zshrc", ".profile", ".bash_profile", ".zprofile", ".zshenv"].includes(name);
|
|
38
|
+
},
|
|
39
|
+
reason: "Shell configuration files can execute arbitrary code on login"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
pattern: (p) => p.startsWith("/etc/"),
|
|
43
|
+
reason: "System configuration directory is protected"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
pattern: (p) => p.startsWith("/usr/") && !p.startsWith("/usr/local/"),
|
|
47
|
+
reason: "System binary directory is protected"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
pattern: (p) => p === "/" || p === HOME,
|
|
51
|
+
reason: "Root and home directory direct modification is protected"
|
|
52
|
+
}
|
|
53
|
+
];
|
|
54
|
+
function checkPathSafety(filePath) {
|
|
55
|
+
const resolved = path.resolve(filePath);
|
|
56
|
+
for (const { pattern, reason } of BYPASS_IMMUNE_PATTERNS) {
|
|
57
|
+
const matches = typeof pattern === "function" ? pattern(resolved) : pattern.test(resolved);
|
|
58
|
+
if (matches) {
|
|
59
|
+
return { safe: false, reason, bypassImmune: true };
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return { safe: true, bypassImmune: true };
|
|
63
|
+
}
|
|
64
|
+
function containsPathTraversal(filePath) {
|
|
65
|
+
return /(?:^|[\\/])\.\.(?:[\\/]|$)/.test(filePath);
|
|
66
|
+
}
|
|
67
|
+
function checkReadPathSafety(filePath) {
|
|
68
|
+
const resolved = path.resolve(filePath);
|
|
69
|
+
const credPatterns = BYPASS_IMMUNE_PATTERNS.filter(
|
|
70
|
+
(p) => typeof p.pattern !== "function" && (p.reason.includes("secrets") || p.reason.includes("Private key") || p.reason.includes("Credential"))
|
|
71
|
+
);
|
|
72
|
+
for (const { pattern, reason } of credPatterns) {
|
|
73
|
+
if (typeof pattern !== "function" && pattern.test(resolved)) {
|
|
74
|
+
return { safe: false, reason, bypassImmune: true };
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return { safe: true, bypassImmune: true };
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export {
|
|
81
|
+
checkPathSafety,
|
|
82
|
+
containsPathTraversal,
|
|
83
|
+
checkReadPathSafety
|
|
84
|
+
};
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
// src/lib/memory-write-governor.ts
|
|
2
|
+
import { createHash } from "crypto";
|
|
3
|
+
var HIGH_VALUE_SUPERSESSION_TYPES = /* @__PURE__ */ new Set([
|
|
4
|
+
"decision",
|
|
5
|
+
"adr",
|
|
6
|
+
"behavior",
|
|
7
|
+
"procedure"
|
|
8
|
+
]);
|
|
9
|
+
var NOISE_DROP_PATTERNS = [
|
|
10
|
+
/^\s*\[📋\s+\d+\s+reviews?\s+pending\b/im,
|
|
11
|
+
/^\s*<system-reminder>[\s\S]*?<\/system-reminder>\s*$/im,
|
|
12
|
+
/^\s*The UserPromptSubmit hook checks the DB for new tasks/im,
|
|
13
|
+
/^\s*Intercom is a speedup, not delivery/im,
|
|
14
|
+
/^\s*Context bar reads as USAGE not remaining/im
|
|
15
|
+
];
|
|
16
|
+
var SKIP_EMBED_PATTERNS = [
|
|
17
|
+
/tmux capture-pane\b/i,
|
|
18
|
+
/docker ps\b/i,
|
|
19
|
+
/docker images\b/i,
|
|
20
|
+
/git status\b/i,
|
|
21
|
+
/grep .*node_modules/i,
|
|
22
|
+
/npm (install|ci)\b[\s\S]*(added \d+ packages|audited \d+ packages)/i
|
|
23
|
+
];
|
|
24
|
+
function normalizeMemoryText(text) {
|
|
25
|
+
return text.replace(/\r\n/g, "\n").replace(/[ \t]+$/gm, "").replace(/\n{4,}/g, "\n\n\n").trim();
|
|
26
|
+
}
|
|
27
|
+
function classifyMemoryType(input) {
|
|
28
|
+
if (input.memory_type && input.memory_type.trim()) return input.memory_type.trim();
|
|
29
|
+
const tool = input.tool_name.toLowerCase();
|
|
30
|
+
const text = input.raw_text.toLowerCase();
|
|
31
|
+
if (tool.includes("store_decision") || tool.includes("decision")) return "decision";
|
|
32
|
+
if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
|
|
33
|
+
if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
|
|
34
|
+
if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
|
|
35
|
+
if (tool.includes("checkpoint") || text.startsWith("context checkpoint")) return "checkpoint";
|
|
36
|
+
if (tool.includes("sessionsummary") || tool.includes("session-summary")) return "summary";
|
|
37
|
+
if (tool.includes("sessionend") || text.startsWith("session ended")) return "summary";
|
|
38
|
+
if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
|
|
39
|
+
if (tool === "store_memory" || tool === "manual") return "observation";
|
|
40
|
+
return "raw";
|
|
41
|
+
}
|
|
42
|
+
function shouldDropMemory(text) {
|
|
43
|
+
const normalized = normalizeMemoryText(text);
|
|
44
|
+
if (normalized.length < 10) return { drop: true, reason: "too_short" };
|
|
45
|
+
if (NOISE_DROP_PATTERNS.some((pattern) => pattern.test(normalized))) {
|
|
46
|
+
return { drop: true, reason: "known_boilerplate_noise" };
|
|
47
|
+
}
|
|
48
|
+
return { drop: false };
|
|
49
|
+
}
|
|
50
|
+
function shouldSkipEmbedding(input) {
|
|
51
|
+
const type = classifyMemoryType(input);
|
|
52
|
+
if (HIGH_VALUE_SUPERSESSION_TYPES.has(type)) return false;
|
|
53
|
+
if (type === "raw" && input.raw_text.length > 2e4) return true;
|
|
54
|
+
if (SKIP_EMBED_PATTERNS.some((pattern) => pattern.test(input.raw_text))) return true;
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
function hashMemoryContent(text) {
|
|
58
|
+
return createHash("sha256").update(normalizeMemoryText(text)).digest("hex");
|
|
59
|
+
}
|
|
60
|
+
function scopedDedupArgs(input) {
|
|
61
|
+
return [input.contentHash, input.agentId, input.projectName, input.memoryType];
|
|
62
|
+
}
|
|
63
|
+
function governMemoryRecord(record) {
|
|
64
|
+
const normalized = normalizeMemoryText(record.raw_text);
|
|
65
|
+
const memoryType = classifyMemoryType({
|
|
66
|
+
raw_text: normalized,
|
|
67
|
+
agent_id: record.agent_id,
|
|
68
|
+
project_name: record.project_name,
|
|
69
|
+
tool_name: record.tool_name,
|
|
70
|
+
memory_type: record.memory_type
|
|
71
|
+
});
|
|
72
|
+
const drop = shouldDropMemory(normalized);
|
|
73
|
+
const skipEmbedding = shouldSkipEmbedding({
|
|
74
|
+
raw_text: normalized,
|
|
75
|
+
agent_id: record.agent_id,
|
|
76
|
+
project_name: record.project_name,
|
|
77
|
+
tool_name: record.tool_name,
|
|
78
|
+
memory_type: memoryType
|
|
79
|
+
});
|
|
80
|
+
return {
|
|
81
|
+
record: {
|
|
82
|
+
...record,
|
|
83
|
+
raw_text: normalized,
|
|
84
|
+
memory_type: memoryType,
|
|
85
|
+
vector: skipEmbedding ? null : record.vector
|
|
86
|
+
},
|
|
87
|
+
contentHash: hashMemoryContent(normalized),
|
|
88
|
+
shouldDrop: drop.drop,
|
|
89
|
+
dropReason: drop.reason,
|
|
90
|
+
skipEmbedding,
|
|
91
|
+
hygiene: {
|
|
92
|
+
dedup: true,
|
|
93
|
+
supersession: HIGH_VALUE_SUPERSESSION_TYPES.has(memoryType)
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
async function findScopedDuplicate(input) {
|
|
98
|
+
const { getClient } = await import("./lib/database.js");
|
|
99
|
+
const client = getClient();
|
|
100
|
+
const args = scopedDedupArgs(input);
|
|
101
|
+
let sql = `SELECT id FROM memories
|
|
102
|
+
WHERE content_hash = ?
|
|
103
|
+
AND agent_id = ?
|
|
104
|
+
AND project_name = ?
|
|
105
|
+
AND COALESCE(memory_type, 'raw') = ?
|
|
106
|
+
AND COALESCE(status, 'active') != 'deleted'`;
|
|
107
|
+
if (input.excludeId) {
|
|
108
|
+
sql += " AND id != ?";
|
|
109
|
+
args.push(input.excludeId);
|
|
110
|
+
}
|
|
111
|
+
sql += " ORDER BY timestamp DESC LIMIT 1";
|
|
112
|
+
const result = await client.execute({ sql, args });
|
|
113
|
+
return result.rows[0]?.id ? String(result.rows[0].id) : null;
|
|
114
|
+
}
|
|
115
|
+
async function runPostWriteMemoryHygiene(memoryId) {
|
|
116
|
+
try {
|
|
117
|
+
const { getClient } = await import("./lib/database.js");
|
|
118
|
+
const client = getClient();
|
|
119
|
+
const current = await client.execute({
|
|
120
|
+
sql: `SELECT id, agent_id, project_name, memory_type, content_hash, supersedes_id,
|
|
121
|
+
importance, timestamp
|
|
122
|
+
FROM memories
|
|
123
|
+
WHERE id = ?
|
|
124
|
+
LIMIT 1`,
|
|
125
|
+
args: [memoryId]
|
|
126
|
+
});
|
|
127
|
+
const row = current.rows[0];
|
|
128
|
+
if (!row) return;
|
|
129
|
+
const memoryType = String(row.memory_type ?? "raw");
|
|
130
|
+
const contentHash = row.content_hash ? String(row.content_hash) : null;
|
|
131
|
+
const agentId = String(row.agent_id);
|
|
132
|
+
const projectName = String(row.project_name);
|
|
133
|
+
if (contentHash) {
|
|
134
|
+
await client.execute({
|
|
135
|
+
sql: `UPDATE memories
|
|
136
|
+
SET status = 'deleted',
|
|
137
|
+
outcome = COALESCE(outcome, 'superseded')
|
|
138
|
+
WHERE id != ?
|
|
139
|
+
AND content_hash = ?
|
|
140
|
+
AND agent_id = ?
|
|
141
|
+
AND project_name = ?
|
|
142
|
+
AND COALESCE(memory_type, 'raw') = ?
|
|
143
|
+
AND COALESCE(status, 'active') = 'active'`,
|
|
144
|
+
args: [memoryId, contentHash, agentId, projectName, memoryType]
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
const supersedesId = row.supersedes_id ? String(row.supersedes_id) : null;
|
|
148
|
+
if (supersedesId && HIGH_VALUE_SUPERSESSION_TYPES.has(memoryType)) {
|
|
149
|
+
const old = await client.execute({
|
|
150
|
+
sql: `SELECT importance FROM memories WHERE id = ? LIMIT 1`,
|
|
151
|
+
args: [supersedesId]
|
|
152
|
+
});
|
|
153
|
+
const oldImportance = Number(old.rows[0]?.importance ?? 0);
|
|
154
|
+
const newImportance = Number(row.importance ?? 0);
|
|
155
|
+
await client.batch([
|
|
156
|
+
{
|
|
157
|
+
sql: `UPDATE memories
|
|
158
|
+
SET status = 'archived',
|
|
159
|
+
outcome = COALESCE(outcome, 'superseded')
|
|
160
|
+
WHERE id = ?`,
|
|
161
|
+
args: [supersedesId]
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
sql: `UPDATE memories
|
|
165
|
+
SET importance = MAX(COALESCE(importance, 5), ?),
|
|
166
|
+
parent_memory_id = COALESCE(parent_memory_id, ?)
|
|
167
|
+
WHERE id = ?`,
|
|
168
|
+
args: [Math.max(oldImportance, newImportance), supersedesId, memoryId]
|
|
169
|
+
}
|
|
170
|
+
], "write");
|
|
171
|
+
}
|
|
172
|
+
} catch (err) {
|
|
173
|
+
process.stderr.write(
|
|
174
|
+
`[memory-governor] post-write hygiene failed for ${memoryId}: ${err instanceof Error ? err.message : String(err)}
|
|
175
|
+
`
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
function schedulePostWriteMemoryHygiene(memoryIds) {
|
|
180
|
+
if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
|
|
181
|
+
if (memoryIds.length === 0) return;
|
|
182
|
+
const run = () => {
|
|
183
|
+
void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
|
|
184
|
+
};
|
|
185
|
+
if (typeof setImmediate === "function") setImmediate(run);
|
|
186
|
+
else setTimeout(run, 0);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export {
|
|
190
|
+
governMemoryRecord,
|
|
191
|
+
findScopedDuplicate,
|
|
192
|
+
schedulePostWriteMemoryHygiene
|
|
193
|
+
};
|