@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
|
@@ -1,1050 +1,24 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
// src/lib/secure-files.ts
|
|
26
|
-
import { chmodSync, existsSync, mkdirSync } from "fs";
|
|
27
|
-
import { chmod, mkdir } from "fs/promises";
|
|
28
|
-
function ensurePrivateDirSync(dirPath) {
|
|
29
|
-
mkdirSync(dirPath, { recursive: true, mode: PRIVATE_DIR_MODE });
|
|
30
|
-
try {
|
|
31
|
-
chmodSync(dirPath, PRIVATE_DIR_MODE);
|
|
32
|
-
} catch {
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
function enforcePrivateFileSync(filePath) {
|
|
36
|
-
try {
|
|
37
|
-
if (existsSync(filePath)) chmodSync(filePath, PRIVATE_FILE_MODE);
|
|
38
|
-
} catch {
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
var PRIVATE_DIR_MODE, PRIVATE_FILE_MODE;
|
|
42
|
-
var init_secure_files = __esm({
|
|
43
|
-
"src/lib/secure-files.ts"() {
|
|
44
|
-
"use strict";
|
|
45
|
-
PRIVATE_DIR_MODE = 448;
|
|
46
|
-
PRIVATE_FILE_MODE = 384;
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
// src/lib/config.ts
|
|
51
|
-
import { readFile, writeFile } from "fs/promises";
|
|
52
|
-
import { readFileSync, existsSync as existsSync2, renameSync } from "fs";
|
|
53
|
-
import path from "path";
|
|
54
|
-
import os from "os";
|
|
55
|
-
function resolveDataDir() {
|
|
56
|
-
if (process.env.EXE_OS_DIR) return process.env.EXE_OS_DIR;
|
|
57
|
-
if (process.env.EXE_MEM_DIR) return process.env.EXE_MEM_DIR;
|
|
58
|
-
const newDir = path.join(os.homedir(), ".exe-os");
|
|
59
|
-
const legacyDir = path.join(os.homedir(), ".exe-mem");
|
|
60
|
-
if (!existsSync2(newDir) && existsSync2(legacyDir)) {
|
|
61
|
-
try {
|
|
62
|
-
renameSync(legacyDir, newDir);
|
|
63
|
-
process.stderr.write(`[exe-os] Migrated data directory: ~/.exe-mem \u2192 ~/.exe-os
|
|
64
|
-
`);
|
|
65
|
-
} catch {
|
|
66
|
-
return legacyDir;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
return newDir;
|
|
70
|
-
}
|
|
71
|
-
var EXE_AI_DIR, DB_PATH, MODELS_DIR, CONFIG_PATH, LEGACY_LANCE_PATH, CURRENT_CONFIG_VERSION, DEFAULT_CONFIG;
|
|
72
|
-
var init_config = __esm({
|
|
73
|
-
"src/lib/config.ts"() {
|
|
74
|
-
"use strict";
|
|
75
|
-
init_secure_files();
|
|
76
|
-
EXE_AI_DIR = resolveDataDir();
|
|
77
|
-
DB_PATH = path.join(EXE_AI_DIR, "memories.db");
|
|
78
|
-
MODELS_DIR = path.join(EXE_AI_DIR, "models");
|
|
79
|
-
CONFIG_PATH = path.join(EXE_AI_DIR, "config.json");
|
|
80
|
-
LEGACY_LANCE_PATH = path.join(EXE_AI_DIR, "local.lance");
|
|
81
|
-
CURRENT_CONFIG_VERSION = 1;
|
|
82
|
-
DEFAULT_CONFIG = {
|
|
83
|
-
config_version: CURRENT_CONFIG_VERSION,
|
|
84
|
-
dbPath: DB_PATH,
|
|
85
|
-
modelFile: "jina-embeddings-v5-small-q4_k_m.gguf",
|
|
86
|
-
embeddingDim: 1024,
|
|
87
|
-
batchSize: 20,
|
|
88
|
-
flushIntervalMs: 1e4,
|
|
89
|
-
autoIngestion: true,
|
|
90
|
-
autoRetrieval: true,
|
|
91
|
-
searchMode: "hybrid",
|
|
92
|
-
hookSearchMode: "hybrid",
|
|
93
|
-
fileGrepEnabled: true,
|
|
94
|
-
splashEffect: true,
|
|
95
|
-
consolidationEnabled: true,
|
|
96
|
-
consolidationIntervalMs: 6 * 60 * 60 * 1e3,
|
|
97
|
-
consolidationModel: "claude-haiku-4-5-20251001",
|
|
98
|
-
consolidationMaxCallsPerRun: 20,
|
|
99
|
-
selfQueryRouter: true,
|
|
100
|
-
selfQueryModel: "claude-haiku-4-5-20251001",
|
|
101
|
-
rerankerEnabled: true,
|
|
102
|
-
scalingRoadmap: {
|
|
103
|
-
rerankerAutoTrigger: {
|
|
104
|
-
enabled: true,
|
|
105
|
-
broadQueryMinCardinality: 5e4,
|
|
106
|
-
fetchTopK: 150,
|
|
107
|
-
returnTopK: 5
|
|
108
|
-
}
|
|
109
|
-
},
|
|
110
|
-
graphRagEnabled: true,
|
|
111
|
-
wikiEnabled: false,
|
|
112
|
-
wikiUrl: "",
|
|
113
|
-
wikiApiKey: "",
|
|
114
|
-
wikiSyncIntervalMs: 30 * 60 * 1e3,
|
|
115
|
-
wikiWorkspaceMapping: {},
|
|
116
|
-
wikiAutoUpdate: true,
|
|
117
|
-
wikiAutoUpdateThreshold: 0.5,
|
|
118
|
-
wikiAutoUpdateCreateNew: true,
|
|
119
|
-
skillLearning: true,
|
|
120
|
-
skillThreshold: 3,
|
|
121
|
-
skillModel: "claude-haiku-4-5-20251001",
|
|
122
|
-
exeHeartbeat: {
|
|
123
|
-
enabled: true,
|
|
124
|
-
intervalSeconds: 60,
|
|
125
|
-
staleInProgressThresholdHours: 2
|
|
126
|
-
},
|
|
127
|
-
sessionLifecycle: {
|
|
128
|
-
idleKillEnabled: true,
|
|
129
|
-
idleKillTicksRequired: 3,
|
|
130
|
-
idleKillIntercomAckWindowMs: 1e4,
|
|
131
|
-
maxAutoInstances: 10
|
|
132
|
-
},
|
|
133
|
-
autoUpdate: {
|
|
134
|
-
checkOnBoot: true,
|
|
135
|
-
autoInstall: false,
|
|
136
|
-
checkIntervalMs: 24 * 60 * 60 * 1e3
|
|
137
|
-
},
|
|
138
|
-
support: {
|
|
139
|
-
bugReportEndpoint: "https://askexe.com/v1/support/bug-reports"
|
|
140
|
-
},
|
|
141
|
-
orchestration: {
|
|
142
|
-
phase: "phase_1_coo",
|
|
143
|
-
phaseSetBy: "default"
|
|
144
|
-
}
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
// src/lib/runtime-table.ts
|
|
150
|
-
var RUNTIME_TABLE, DEFAULT_RUNTIME;
|
|
151
|
-
var init_runtime_table = __esm({
|
|
152
|
-
"src/lib/runtime-table.ts"() {
|
|
153
|
-
"use strict";
|
|
154
|
-
RUNTIME_TABLE = {
|
|
155
|
-
codex: {
|
|
156
|
-
binary: "codex",
|
|
157
|
-
launchMode: "interactive",
|
|
158
|
-
autoApproveFlag: "--dangerously-bypass-approvals-and-sandbox",
|
|
159
|
-
inlineFlag: "--no-alt-screen",
|
|
160
|
-
apiKeyEnv: "OPENAI_API_KEY",
|
|
161
|
-
defaultModel: "gpt-5.5"
|
|
162
|
-
},
|
|
163
|
-
opencode: {
|
|
164
|
-
binary: "opencode",
|
|
165
|
-
launchMode: "exec",
|
|
166
|
-
autoApproveFlag: "--dangerously-skip-permissions",
|
|
167
|
-
inlineFlag: "",
|
|
168
|
-
apiKeyEnv: "ANTHROPIC_API_KEY",
|
|
169
|
-
defaultModel: "anthropic/claude-sonnet-4-6"
|
|
170
|
-
}
|
|
171
|
-
};
|
|
172
|
-
DEFAULT_RUNTIME = "claude";
|
|
173
|
-
}
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
// src/lib/agent-config.ts
|
|
177
|
-
var agent_config_exports = {};
|
|
178
|
-
__export(agent_config_exports, {
|
|
179
|
-
AGENT_CONFIG_PATH: () => AGENT_CONFIG_PATH,
|
|
180
|
-
DEFAULT_MODELS: () => DEFAULT_MODELS,
|
|
181
|
-
KNOWN_RUNTIMES: () => KNOWN_RUNTIMES,
|
|
182
|
-
RUNTIME_LABELS: () => RUNTIME_LABELS,
|
|
183
|
-
clearAgentRuntime: () => clearAgentRuntime,
|
|
184
|
-
getAgentRuntime: () => getAgentRuntime,
|
|
185
|
-
loadAgentConfig: () => loadAgentConfig,
|
|
186
|
-
normalizeCcModelName: () => normalizeCcModelName,
|
|
187
|
-
saveAgentConfig: () => saveAgentConfig,
|
|
188
|
-
setAgentMcps: () => setAgentMcps,
|
|
189
|
-
setAgentRuntime: () => setAgentRuntime
|
|
190
|
-
});
|
|
191
|
-
import { readFileSync as readFileSync2, writeFileSync, existsSync as existsSync3 } from "fs";
|
|
192
|
-
import path2 from "path";
|
|
193
|
-
function loadAgentConfig() {
|
|
194
|
-
if (!existsSync3(AGENT_CONFIG_PATH)) return {};
|
|
195
|
-
try {
|
|
196
|
-
return JSON.parse(readFileSync2(AGENT_CONFIG_PATH, "utf-8"));
|
|
197
|
-
} catch {
|
|
198
|
-
return {};
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
function saveAgentConfig(config) {
|
|
202
|
-
const dir = path2.dirname(AGENT_CONFIG_PATH);
|
|
203
|
-
ensurePrivateDirSync(dir);
|
|
204
|
-
writeFileSync(AGENT_CONFIG_PATH, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
205
|
-
enforcePrivateFileSync(AGENT_CONFIG_PATH);
|
|
206
|
-
}
|
|
207
|
-
function getAgentRuntime(agentId) {
|
|
208
|
-
const config = loadAgentConfig();
|
|
209
|
-
const entry = config[agentId];
|
|
210
|
-
if (entry) return entry;
|
|
211
|
-
const orgDefault = config["default"];
|
|
212
|
-
if (orgDefault) return orgDefault;
|
|
213
|
-
return { runtime: DEFAULT_RUNTIME, model: DEFAULT_MODELS[DEFAULT_RUNTIME] };
|
|
214
|
-
}
|
|
215
|
-
function normalizeCcModelName(model) {
|
|
216
|
-
let ccModel = model.replace(/(\d+)\.(\d+)/g, "$1-$2");
|
|
217
|
-
if (/claude-(opus|sonnet)-4-[6-9]/.test(ccModel) && !ccModel.includes("[1m]")) {
|
|
218
|
-
ccModel += "[1m]";
|
|
219
|
-
}
|
|
220
|
-
return ccModel;
|
|
221
|
-
}
|
|
222
|
-
function setAgentRuntime(agentId, runtime, model, reasoning_effort, mcps) {
|
|
223
|
-
const knownModels = KNOWN_RUNTIMES[runtime];
|
|
224
|
-
if (!knownModels) {
|
|
225
|
-
return {
|
|
226
|
-
ok: false,
|
|
227
|
-
error: `Unknown runtime "${runtime}". Valid: ${Object.keys(KNOWN_RUNTIMES).join(", ")}`
|
|
228
|
-
};
|
|
229
|
-
}
|
|
230
|
-
if (!knownModels.includes(model)) {
|
|
231
|
-
return {
|
|
232
|
-
ok: false,
|
|
233
|
-
error: `Unknown model "${model}" for runtime "${runtime}". Valid: ${knownModels.join(", ")}`
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
|
-
const config = loadAgentConfig();
|
|
237
|
-
const existing = config[agentId];
|
|
238
|
-
const entry = { runtime, model };
|
|
239
|
-
if (reasoning_effort) entry.reasoning_effort = reasoning_effort;
|
|
240
|
-
if (mcps !== void 0) {
|
|
241
|
-
entry.mcps = mcps.includes("exe-os") ? mcps : ["exe-os", ...mcps];
|
|
242
|
-
} else if (existing?.mcps) {
|
|
243
|
-
entry.mcps = existing.mcps;
|
|
244
|
-
}
|
|
245
|
-
config[agentId] = entry;
|
|
246
|
-
saveAgentConfig(config);
|
|
247
|
-
return { ok: true };
|
|
248
|
-
}
|
|
249
|
-
function setAgentMcps(agentId, mcps) {
|
|
250
|
-
const config = loadAgentConfig();
|
|
251
|
-
const existing = config[agentId] ?? getAgentRuntime(agentId);
|
|
252
|
-
existing.mcps = mcps.includes("exe-os") ? mcps : ["exe-os", ...mcps];
|
|
253
|
-
config[agentId] = existing;
|
|
254
|
-
saveAgentConfig(config);
|
|
255
|
-
return { ok: true };
|
|
256
|
-
}
|
|
257
|
-
function clearAgentRuntime(agentId) {
|
|
258
|
-
const config = loadAgentConfig();
|
|
259
|
-
delete config[agentId];
|
|
260
|
-
saveAgentConfig(config);
|
|
261
|
-
}
|
|
262
|
-
var AGENT_CONFIG_PATH, KNOWN_RUNTIMES, RUNTIME_LABELS, DEFAULT_MODELS;
|
|
263
|
-
var init_agent_config = __esm({
|
|
264
|
-
"src/lib/agent-config.ts"() {
|
|
265
|
-
"use strict";
|
|
266
|
-
init_config();
|
|
267
|
-
init_runtime_table();
|
|
268
|
-
init_secure_files();
|
|
269
|
-
AGENT_CONFIG_PATH = path2.join(EXE_AI_DIR, "agent-config.json");
|
|
270
|
-
KNOWN_RUNTIMES = {
|
|
271
|
-
claude: ["claude-opus-4.6", "claude-opus-4", "claude-sonnet-4.6", "claude-sonnet-4", "claude-haiku-4.5"],
|
|
272
|
-
codex: ["gpt-5.4", "gpt-5.5", "gpt-5.3-codex-spark", "o3", "o4-mini"],
|
|
273
|
-
opencode: ["anthropic/claude-sonnet-4-6", "openai/gpt-5.4", "google/gemini-2.5-pro", "deepseek/deepseek-r3", "minimax/minimax-m2.5"]
|
|
274
|
-
};
|
|
275
|
-
RUNTIME_LABELS = {
|
|
276
|
-
claude: "Claude Code (Anthropic)",
|
|
277
|
-
codex: "Codex (OpenAI)",
|
|
278
|
-
opencode: "OpenCode (open source)"
|
|
279
|
-
};
|
|
280
|
-
DEFAULT_MODELS = {
|
|
281
|
-
claude: "claude-opus-4.6",
|
|
282
|
-
codex: RUNTIME_TABLE.codex?.defaultModel ?? "gpt-5.4",
|
|
283
|
-
opencode: RUNTIME_TABLE.opencode?.defaultModel ?? "anthropic/claude-sonnet-4-6"
|
|
284
|
-
};
|
|
285
|
-
}
|
|
286
|
-
});
|
|
287
|
-
|
|
288
|
-
// src/lib/employees.ts
|
|
289
|
-
var employees_exports = {};
|
|
290
|
-
__export(employees_exports, {
|
|
291
|
-
COORDINATOR_ROLE: () => COORDINATOR_ROLE,
|
|
292
|
-
DEFAULT_COORDINATOR_TEMPLATE_NAME: () => DEFAULT_COORDINATOR_TEMPLATE_NAME,
|
|
293
|
-
EMPLOYEES_PATH: () => EMPLOYEES_PATH,
|
|
294
|
-
addEmployee: () => addEmployee,
|
|
295
|
-
baseAgentName: () => baseAgentName,
|
|
296
|
-
canCoordinate: () => canCoordinate,
|
|
297
|
-
getCoordinatorEmployee: () => getCoordinatorEmployee,
|
|
298
|
-
getCoordinatorName: () => getCoordinatorName,
|
|
299
|
-
getEmployee: () => getEmployee,
|
|
300
|
-
getEmployeeByRole: () => getEmployeeByRole,
|
|
301
|
-
getEmployeeNamesByRole: () => getEmployeeNamesByRole,
|
|
302
|
-
hasRole: () => hasRole,
|
|
303
|
-
hireEmployee: () => hireEmployee,
|
|
304
|
-
isCoordinatorName: () => isCoordinatorName,
|
|
305
|
-
isCoordinatorRole: () => isCoordinatorRole,
|
|
306
|
-
isMultiInstance: () => isMultiInstance,
|
|
307
|
-
loadEmployees: () => loadEmployees,
|
|
308
|
-
loadEmployeesSync: () => loadEmployeesSync,
|
|
309
|
-
normalizeRole: () => normalizeRole,
|
|
310
|
-
normalizeRosterCase: () => normalizeRosterCase,
|
|
311
|
-
registerBinSymlinks: () => registerBinSymlinks,
|
|
312
|
-
saveEmployees: () => saveEmployees,
|
|
313
|
-
validateEmployeeName: () => validateEmployeeName
|
|
314
|
-
});
|
|
315
|
-
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
316
|
-
import { existsSync as existsSync4, symlinkSync, readlinkSync, readFileSync as readFileSync3, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
|
|
317
|
-
import { execSync } from "child_process";
|
|
318
|
-
import path3 from "path";
|
|
319
|
-
import os2 from "os";
|
|
320
|
-
function normalizeRole(role) {
|
|
321
|
-
return (role ?? "").trim().toLowerCase();
|
|
322
|
-
}
|
|
323
|
-
function isCoordinatorRole(role) {
|
|
324
|
-
return normalizeRole(role) === normalizeRole(COORDINATOR_ROLE);
|
|
325
|
-
}
|
|
326
|
-
function getCoordinatorEmployee(employees) {
|
|
327
|
-
return employees.find((e) => isCoordinatorRole(e.role));
|
|
328
|
-
}
|
|
329
|
-
function getCoordinatorName(employees = loadEmployeesSync()) {
|
|
330
|
-
return getCoordinatorEmployee(employees)?.name ?? DEFAULT_COORDINATOR_TEMPLATE_NAME;
|
|
331
|
-
}
|
|
332
|
-
function isCoordinatorName(agentName, employees = loadEmployeesSync()) {
|
|
333
|
-
if (!agentName) return false;
|
|
334
|
-
return agentName.toLowerCase() === getCoordinatorName(employees).toLowerCase();
|
|
335
|
-
}
|
|
336
|
-
function canCoordinate(agentName, agentRole, employees = loadEmployeesSync()) {
|
|
337
|
-
return agentName === "default" || isCoordinatorRole(agentRole) || isCoordinatorName(agentName, employees);
|
|
338
|
-
}
|
|
339
|
-
function validateEmployeeName(name) {
|
|
340
|
-
if (!name) {
|
|
341
|
-
return { valid: false, error: "Name is required" };
|
|
342
|
-
}
|
|
343
|
-
if (name.length > 32) {
|
|
344
|
-
return { valid: false, error: "Name must be 32 characters or fewer" };
|
|
345
|
-
}
|
|
346
|
-
if (!/^[a-z][a-z0-9]*$/.test(name)) {
|
|
347
|
-
return {
|
|
348
|
-
valid: false,
|
|
349
|
-
error: "Name must start with a letter and contain only lowercase alphanumeric characters"
|
|
350
|
-
};
|
|
351
|
-
}
|
|
352
|
-
return { valid: true };
|
|
353
|
-
}
|
|
354
|
-
async function loadEmployees(employeesPath = EMPLOYEES_PATH) {
|
|
355
|
-
if (!existsSync4(employeesPath)) {
|
|
356
|
-
return [];
|
|
357
|
-
}
|
|
358
|
-
const raw = await readFile2(employeesPath, "utf-8");
|
|
359
|
-
try {
|
|
360
|
-
return JSON.parse(raw);
|
|
361
|
-
} catch {
|
|
362
|
-
return [];
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
async function saveEmployees(employees, employeesPath = EMPLOYEES_PATH) {
|
|
366
|
-
await mkdir2(path3.dirname(employeesPath), { recursive: true });
|
|
367
|
-
await writeFile2(employeesPath, JSON.stringify(employees, null, 2) + "\n", "utf-8");
|
|
368
|
-
}
|
|
369
|
-
function loadEmployeesSync(employeesPath = EMPLOYEES_PATH) {
|
|
370
|
-
if (!existsSync4(employeesPath)) return [];
|
|
371
|
-
try {
|
|
372
|
-
return JSON.parse(readFileSync3(employeesPath, "utf-8"));
|
|
373
|
-
} catch {
|
|
374
|
-
return [];
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
function getEmployee(employees, name) {
|
|
378
|
-
return employees.find((e) => e.name.toLowerCase() === name.toLowerCase());
|
|
379
|
-
}
|
|
380
|
-
function getEmployeeByRole(employees, role) {
|
|
381
|
-
const lower = role.toLowerCase();
|
|
382
|
-
return employees.find((e) => e.role.toLowerCase() === lower);
|
|
383
|
-
}
|
|
384
|
-
function getEmployeeNamesByRole(employees, role) {
|
|
385
|
-
const lower = role.toLowerCase();
|
|
386
|
-
return employees.filter((e) => e.role.toLowerCase() === lower).map((e) => e.name);
|
|
387
|
-
}
|
|
388
|
-
function hasRole(agentName, role) {
|
|
389
|
-
const employees = loadEmployeesSync();
|
|
390
|
-
const emp = getEmployee(employees, agentName);
|
|
391
|
-
return emp ? emp.role.toLowerCase() === role.toLowerCase() : false;
|
|
392
|
-
}
|
|
393
|
-
function baseAgentName(name, employees) {
|
|
394
|
-
const match = name.match(/^([a-zA-Z]+)\d+$/);
|
|
395
|
-
if (!match) return name;
|
|
396
|
-
const base = match[1];
|
|
397
|
-
const roster = employees ?? loadEmployeesSync();
|
|
398
|
-
if (getEmployee(roster, base)) return base;
|
|
399
|
-
return name;
|
|
400
|
-
}
|
|
401
|
-
function isMultiInstance(agentName, employees) {
|
|
402
|
-
const roster = employees ?? loadEmployeesSync();
|
|
403
|
-
const emp = getEmployee(roster, agentName);
|
|
404
|
-
if (!emp) return false;
|
|
405
|
-
return MULTI_INSTANCE_ROLES.has(emp.role.toLowerCase());
|
|
406
|
-
}
|
|
407
|
-
function addEmployee(employees, employee) {
|
|
408
|
-
const { systemPrompt: _legacyPrompt, ...rest } = employee;
|
|
409
|
-
const normalized = { ...rest, name: employee.name.toLowerCase() };
|
|
410
|
-
if (employees.some((e) => e.name.toLowerCase() === normalized.name)) {
|
|
411
|
-
throw new Error(`Employee '${normalized.name}' already exists`);
|
|
412
|
-
}
|
|
413
|
-
return [...employees, normalized];
|
|
414
|
-
}
|
|
415
|
-
function appendToCoordinatorTeam(employee) {
|
|
416
|
-
const coordinator = getCoordinatorEmployee(loadEmployeesSync());
|
|
417
|
-
if (!coordinator) return;
|
|
418
|
-
const idPath = path3.join(IDENTITY_DIR, `${coordinator.name}.md`);
|
|
419
|
-
if (!existsSync4(idPath)) return;
|
|
420
|
-
const content = readFileSync3(idPath, "utf-8");
|
|
421
|
-
if (content.includes(`**${capitalize(employee.name)}`)) return;
|
|
422
|
-
const teamMatch = content.match(TEAM_SECTION_RE);
|
|
423
|
-
if (!teamMatch || teamMatch.index === void 0) return;
|
|
424
|
-
const afterTeam = content.slice(teamMatch.index + teamMatch[0].length);
|
|
425
|
-
const nextHeading = afterTeam.match(/\n## /);
|
|
426
|
-
const entry = `
|
|
427
|
-
**${capitalize(employee.name)} (${employee.role}):** Newly hired. Update this description as the role develops.
|
|
428
|
-
`;
|
|
429
|
-
let updated;
|
|
430
|
-
if (nextHeading && nextHeading.index !== void 0) {
|
|
431
|
-
const insertAt = teamMatch.index + teamMatch[0].length + nextHeading.index;
|
|
432
|
-
updated = content.slice(0, insertAt) + entry + content.slice(insertAt);
|
|
433
|
-
} else {
|
|
434
|
-
updated = content.trimEnd() + "\n" + entry;
|
|
435
|
-
}
|
|
436
|
-
writeFileSync2(idPath, updated, "utf-8");
|
|
437
|
-
}
|
|
438
|
-
function capitalize(s) {
|
|
439
|
-
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
440
|
-
}
|
|
441
|
-
async function hireEmployee(employee) {
|
|
442
|
-
const employees = await loadEmployees();
|
|
443
|
-
const updated = addEmployee(employees, employee);
|
|
444
|
-
await saveEmployees(updated);
|
|
445
|
-
try {
|
|
446
|
-
appendToCoordinatorTeam(employee);
|
|
447
|
-
} catch {
|
|
448
|
-
}
|
|
449
|
-
try {
|
|
450
|
-
const { loadAgentConfig: loadAgentConfig2, saveAgentConfig: saveAgentConfig2 } = await Promise.resolve().then(() => (init_agent_config(), agent_config_exports));
|
|
451
|
-
const config = loadAgentConfig2();
|
|
452
|
-
const name = employee.name.toLowerCase();
|
|
453
|
-
if (!config[name] && config["default"]) {
|
|
454
|
-
config[name] = { ...config["default"] };
|
|
455
|
-
saveAgentConfig2(config);
|
|
456
|
-
}
|
|
457
|
-
} catch {
|
|
458
|
-
}
|
|
459
|
-
return updated;
|
|
460
|
-
}
|
|
461
|
-
async function normalizeRosterCase(rosterPath) {
|
|
462
|
-
const employees = await loadEmployees(rosterPath);
|
|
463
|
-
let changed = false;
|
|
464
|
-
for (const emp of employees) {
|
|
465
|
-
if (emp.name !== emp.name.toLowerCase()) {
|
|
466
|
-
const oldName = emp.name;
|
|
467
|
-
emp.name = emp.name.toLowerCase();
|
|
468
|
-
changed = true;
|
|
469
|
-
try {
|
|
470
|
-
const identityDir = path3.join(os2.homedir(), ".exe-os", "identity");
|
|
471
|
-
const oldPath = path3.join(identityDir, `${oldName}.md`);
|
|
472
|
-
const newPath = path3.join(identityDir, `${emp.name}.md`);
|
|
473
|
-
if (existsSync4(oldPath) && !existsSync4(newPath)) {
|
|
474
|
-
renameSync2(oldPath, newPath);
|
|
475
|
-
} else if (existsSync4(oldPath) && oldPath !== newPath) {
|
|
476
|
-
const content = readFileSync3(oldPath, "utf-8");
|
|
477
|
-
writeFileSync2(newPath, content, "utf-8");
|
|
478
|
-
if (oldPath.toLowerCase() !== newPath.toLowerCase()) {
|
|
479
|
-
unlinkSync(oldPath);
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
} catch {
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
if (changed) {
|
|
487
|
-
await saveEmployees(employees, rosterPath);
|
|
488
|
-
}
|
|
489
|
-
return changed;
|
|
490
|
-
}
|
|
491
|
-
function findExeBin() {
|
|
492
|
-
try {
|
|
493
|
-
return execSync(process.platform === "win32" ? "where exe-os" : "which exe-os", { encoding: "utf8" }).trim();
|
|
494
|
-
} catch {
|
|
495
|
-
return null;
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
function registerBinSymlinks(name) {
|
|
499
|
-
const created = [];
|
|
500
|
-
const skipped = [];
|
|
501
|
-
const errors = [];
|
|
502
|
-
const exeBinPath = findExeBin();
|
|
503
|
-
if (!exeBinPath) {
|
|
504
|
-
errors.push("Could not find 'exe-os' in PATH");
|
|
505
|
-
return { created, skipped, errors };
|
|
506
|
-
}
|
|
507
|
-
const binDir = path3.dirname(exeBinPath);
|
|
508
|
-
let target;
|
|
509
|
-
try {
|
|
510
|
-
target = readlinkSync(exeBinPath);
|
|
511
|
-
} catch {
|
|
512
|
-
errors.push("Could not read 'exe' symlink");
|
|
513
|
-
return { created, skipped, errors };
|
|
514
|
-
}
|
|
515
|
-
for (const suffix of ["", "-opencode"]) {
|
|
516
|
-
const linkName = `${name}${suffix}`;
|
|
517
|
-
const linkPath = path3.join(binDir, linkName);
|
|
518
|
-
if (existsSync4(linkPath)) {
|
|
519
|
-
skipped.push(linkName);
|
|
520
|
-
continue;
|
|
521
|
-
}
|
|
522
|
-
try {
|
|
523
|
-
symlinkSync(target, linkPath);
|
|
524
|
-
created.push(linkName);
|
|
525
|
-
} catch (err) {
|
|
526
|
-
errors.push(`${linkName}: ${err instanceof Error ? err.message : String(err)}`);
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
return { created, skipped, errors };
|
|
530
|
-
}
|
|
531
|
-
var EMPLOYEES_PATH, DEFAULT_COORDINATOR_TEMPLATE_NAME, COORDINATOR_ROLE, MULTI_INSTANCE_ROLES, IDENTITY_DIR, TEAM_SECTION_RE;
|
|
532
|
-
var init_employees = __esm({
|
|
533
|
-
"src/lib/employees.ts"() {
|
|
534
|
-
"use strict";
|
|
535
|
-
init_config();
|
|
536
|
-
EMPLOYEES_PATH = path3.join(EXE_AI_DIR, "exe-employees.json");
|
|
537
|
-
DEFAULT_COORDINATOR_TEMPLATE_NAME = "exe";
|
|
538
|
-
COORDINATOR_ROLE = "COO";
|
|
539
|
-
MULTI_INSTANCE_ROLES = /* @__PURE__ */ new Set(["principal engineer", "content production specialist", "staff code reviewer"]);
|
|
540
|
-
IDENTITY_DIR = path3.join(EXE_AI_DIR, "identity");
|
|
541
|
-
TEAM_SECTION_RE = /^## Team\b.*$/m;
|
|
542
|
-
}
|
|
543
|
-
});
|
|
544
|
-
|
|
545
|
-
// src/lib/database-adapter.ts
|
|
546
|
-
import os3 from "os";
|
|
547
|
-
import path4 from "path";
|
|
548
|
-
import { createRequire } from "module";
|
|
549
|
-
import { pathToFileURL } from "url";
|
|
550
|
-
var BOOLEAN_COLUMNS_BY_TABLE, BOOLEAN_COLUMN_NAMES;
|
|
551
|
-
var init_database_adapter = __esm({
|
|
552
|
-
"src/lib/database-adapter.ts"() {
|
|
553
|
-
"use strict";
|
|
554
|
-
BOOLEAN_COLUMNS_BY_TABLE = {
|
|
555
|
-
memories: /* @__PURE__ */ new Set(["has_error", "draft"]),
|
|
556
|
-
behaviors: /* @__PURE__ */ new Set(["active"]),
|
|
557
|
-
notifications: /* @__PURE__ */ new Set(["read"]),
|
|
558
|
-
users: /* @__PURE__ */ new Set(["has_personal_memory"])
|
|
559
|
-
};
|
|
560
|
-
BOOLEAN_COLUMN_NAMES = new Set(
|
|
561
|
-
Object.values(BOOLEAN_COLUMNS_BY_TABLE).flatMap((cols) => [...cols])
|
|
562
|
-
);
|
|
563
|
-
}
|
|
564
|
-
});
|
|
565
|
-
|
|
566
|
-
// src/lib/database.ts
|
|
567
|
-
import { chmodSync as chmodSync2, existsSync as existsSync5, statSync, copyFileSync, unlinkSync as unlinkSync2, openSync, closeSync, mkdirSync as mkdirSync2 } from "fs";
|
|
568
|
-
import { createClient } from "@libsql/client";
|
|
569
|
-
import { homedir } from "os";
|
|
570
|
-
import { join } from "path";
|
|
571
|
-
var _debugDb, DB_LOCK_PATH;
|
|
572
|
-
var init_database = __esm({
|
|
573
|
-
"src/lib/database.ts"() {
|
|
574
|
-
"use strict";
|
|
575
|
-
init_db_retry();
|
|
576
|
-
init_employees();
|
|
577
|
-
init_database_adapter();
|
|
578
|
-
init_memory();
|
|
579
|
-
_debugDb = process.env.EXE_DEBUG === "1";
|
|
580
|
-
DB_LOCK_PATH = join(homedir(), ".exe-os", "db.lock");
|
|
581
|
-
}
|
|
582
|
-
});
|
|
583
|
-
|
|
584
|
-
// src/lib/consolidation.ts
|
|
585
|
-
import { randomUUID } from "crypto";
|
|
586
|
-
|
|
587
|
-
// src/lib/store.ts
|
|
588
|
-
init_memory();
|
|
589
|
-
init_database();
|
|
590
|
-
|
|
591
|
-
// src/lib/keychain.ts
|
|
592
|
-
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2, rename, copyFile } from "fs/promises";
|
|
593
|
-
import { existsSync as existsSync6, statSync as statSync2 } from "fs";
|
|
594
|
-
import { execSync as execSync2 } from "child_process";
|
|
595
|
-
import path5 from "path";
|
|
596
|
-
import os4 from "os";
|
|
597
|
-
|
|
598
|
-
// src/lib/store.ts
|
|
599
|
-
init_config();
|
|
600
|
-
|
|
601
|
-
// src/lib/state-bus.ts
|
|
602
|
-
var StateBus = class {
|
|
603
|
-
handlers = /* @__PURE__ */ new Map();
|
|
604
|
-
globalHandlers = /* @__PURE__ */ new Set();
|
|
605
|
-
/** Emit an event to all subscribers */
|
|
606
|
-
emit(event) {
|
|
607
|
-
const typeHandlers = this.handlers.get(event.type);
|
|
608
|
-
if (typeHandlers) {
|
|
609
|
-
for (const handler of typeHandlers) {
|
|
610
|
-
try {
|
|
611
|
-
handler(event);
|
|
612
|
-
} catch {
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
for (const handler of this.globalHandlers) {
|
|
617
|
-
try {
|
|
618
|
-
handler(event);
|
|
619
|
-
} catch {
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
|
-
}
|
|
623
|
-
/** Subscribe to a specific event type */
|
|
624
|
-
on(type, handler) {
|
|
625
|
-
if (!this.handlers.has(type)) {
|
|
626
|
-
this.handlers.set(type, /* @__PURE__ */ new Set());
|
|
627
|
-
}
|
|
628
|
-
this.handlers.get(type).add(handler);
|
|
629
|
-
}
|
|
630
|
-
/** Subscribe to ALL events */
|
|
631
|
-
onAny(handler) {
|
|
632
|
-
this.globalHandlers.add(handler);
|
|
633
|
-
}
|
|
634
|
-
/** Unsubscribe from a specific event type */
|
|
635
|
-
off(type, handler) {
|
|
636
|
-
this.handlers.get(type)?.delete(handler);
|
|
637
|
-
}
|
|
638
|
-
/** Unsubscribe from ALL events */
|
|
639
|
-
offAny(handler) {
|
|
640
|
-
this.globalHandlers.delete(handler);
|
|
641
|
-
}
|
|
642
|
-
/** Remove all listeners */
|
|
643
|
-
clear() {
|
|
644
|
-
this.handlers.clear();
|
|
645
|
-
this.globalHandlers.clear();
|
|
646
|
-
}
|
|
647
|
-
};
|
|
648
|
-
var orgBus = new StateBus();
|
|
649
|
-
|
|
650
|
-
// src/lib/memory-write-governor.ts
|
|
651
|
-
import { createHash } from "crypto";
|
|
652
|
-
|
|
653
|
-
// src/lib/store.ts
|
|
654
|
-
var _debugStore = process.env.EXE_DEBUG === "1";
|
|
655
|
-
function vectorToBlob(vector) {
|
|
656
|
-
const f32 = vector instanceof Float32Array ? vector : new Float32Array(vector);
|
|
657
|
-
return JSON.stringify(Array.from(f32));
|
|
658
|
-
}
|
|
659
|
-
|
|
660
|
-
// src/lib/consolidation.ts
|
|
661
|
-
init_employees();
|
|
662
|
-
async function selectUnconsolidated(client, limit = 200) {
|
|
663
|
-
const result = await client.execute({
|
|
664
|
-
sql: `SELECT id, agent_id, project_name, tool_name, raw_text, timestamp
|
|
665
|
-
FROM memories
|
|
666
|
-
WHERE consolidated = 0
|
|
667
|
-
AND COALESCE(memory_type, 'raw') != 'procedure'
|
|
668
|
-
ORDER BY timestamp DESC
|
|
669
|
-
LIMIT ?`,
|
|
670
|
-
args: [limit]
|
|
671
|
-
});
|
|
672
|
-
return result.rows.map((row) => ({
|
|
673
|
-
id: row.id,
|
|
674
|
-
agent_id: row.agent_id,
|
|
675
|
-
project_name: row.project_name,
|
|
676
|
-
tool_name: row.tool_name,
|
|
677
|
-
raw_text: row.raw_text,
|
|
678
|
-
timestamp: row.timestamp
|
|
679
|
-
}));
|
|
680
|
-
}
|
|
681
|
-
function groupMemories(memories) {
|
|
682
|
-
const byProject = /* @__PURE__ */ new Map();
|
|
683
|
-
for (const mem of memories) {
|
|
684
|
-
const key = `${mem.agent_id}::${mem.project_name}`;
|
|
685
|
-
const list = byProject.get(key) ?? [];
|
|
686
|
-
list.push(mem);
|
|
687
|
-
byProject.set(key, list);
|
|
688
|
-
}
|
|
689
|
-
const clusters = [];
|
|
690
|
-
for (const [key, projectMemories] of byProject) {
|
|
691
|
-
const [agentId, projectName] = key.split("::");
|
|
692
|
-
const byDay = /* @__PURE__ */ new Map();
|
|
693
|
-
for (const mem of projectMemories) {
|
|
694
|
-
const day = mem.timestamp.slice(0, 10);
|
|
695
|
-
const list = byDay.get(day) ?? [];
|
|
696
|
-
list.push(mem);
|
|
697
|
-
byDay.set(day, list);
|
|
698
|
-
}
|
|
699
|
-
for (const [day, dayMemories] of byDay) {
|
|
700
|
-
if (dayMemories.length <= 15) {
|
|
701
|
-
clusters.push({
|
|
702
|
-
agentId,
|
|
703
|
-
projectName,
|
|
704
|
-
dateRange: day,
|
|
705
|
-
memories: dayMemories
|
|
706
|
-
});
|
|
707
|
-
} else {
|
|
708
|
-
for (let i = 0; i < dayMemories.length; i += 12) {
|
|
709
|
-
const chunk = dayMemories.slice(i, i + 12);
|
|
710
|
-
clusters.push({
|
|
711
|
-
agentId,
|
|
712
|
-
projectName,
|
|
713
|
-
dateRange: day,
|
|
714
|
-
memories: chunk
|
|
715
|
-
});
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
|
-
}
|
|
720
|
-
return clusters;
|
|
721
|
-
}
|
|
722
|
-
var ROLE_PROMPTS = {
|
|
723
|
-
"COO": `Extract EXACTLY THREE types of insights:
|
|
724
|
-
1. KEY DECISIONS \u2014 choices that were made and why (at most 3)
|
|
725
|
-
2. RECURRING PATTERNS \u2014 actions or approaches that repeated (at most 3)
|
|
726
|
-
3. OPEN QUESTIONS \u2014 things that seem unresolved or risky (at most 2)`,
|
|
727
|
-
"CTO": `Extract EXACTLY THREE types of insights:
|
|
728
|
-
1. ARCHITECTURE DECISIONS \u2014 design choices, tradeoffs, delegation patterns (at most 3)
|
|
729
|
-
2. REVIEW OUTCOMES \u2014 what was approved, rejected, or flagged during code review (at most 3)
|
|
730
|
-
3. TECHNICAL DEBT \u2014 unresolved issues, deferred work, risks identified (at most 2)`,
|
|
731
|
-
"Principal Engineer": `Extract EXACTLY THREE types of insights:
|
|
732
|
-
1. CODE DECISIONS \u2014 implementation choices, patterns used, bugs fixed (at most 3)
|
|
733
|
-
2. FILE CHANGES \u2014 key files modified and why (at most 3)
|
|
734
|
-
3. BLOCKERS \u2014 things that slowed down or prevented progress (at most 2)`,
|
|
735
|
-
"Staff Code Reviewer": `Extract EXACTLY THREE types of insights:
|
|
736
|
-
1. AUDIT FINDINGS \u2014 issues found, severity, fix status (at most 3)
|
|
737
|
-
2. RECURRING ISSUES \u2014 patterns that keep appearing across reviews (at most 3)
|
|
738
|
-
3. QUALITY SIGNALS \u2014 areas of the codebase that are strong or weak (at most 2)`,
|
|
739
|
-
"CMO": `Extract EXACTLY THREE types of insights:
|
|
740
|
-
1. DESIGN DECISIONS \u2014 brand, layout, typography, or content choices made (at most 3)
|
|
741
|
-
2. CONTENT STRATEGY \u2014 messaging, SEO, platform-specific decisions (at most 3)
|
|
742
|
-
3. BRAND ALIGNMENT \u2014 consistency issues or guidelines established (at most 2)`,
|
|
743
|
-
"AI Product Lead": `Extract EXACTLY THREE types of insights:
|
|
744
|
-
1. RESEARCH FINDINGS \u2014 tools, repos, or models evaluated with conclusions (at most 3)
|
|
745
|
-
2. COMPETITIVE GAPS \u2014 features or patterns worth adopting from competitors (at most 3)
|
|
746
|
-
3. BUILD RECOMMENDATIONS \u2014 what to build, skip, or watch (at most 2)`
|
|
747
|
-
};
|
|
748
|
-
var DEFAULT_ROLE_PROMPT = `Extract EXACTLY THREE types of insights:
|
|
749
|
-
1. KEY DECISIONS \u2014 choices that were made and why (at most 3)
|
|
750
|
-
2. RECURRING PATTERNS \u2014 actions or approaches that repeated (at most 3)
|
|
751
|
-
3. OPEN QUESTIONS \u2014 things that seem unresolved or risky (at most 2)`;
|
|
752
|
-
function buildConsolidationPrompt(cluster, agentRole) {
|
|
753
|
-
const snippets = cluster.memories.map((m, i) => {
|
|
754
|
-
const text = m.raw_text.length > 200 ? m.raw_text.slice(0, 200) + "..." : m.raw_text;
|
|
755
|
-
return `${i + 1}. [${m.tool_name}] ${text}`;
|
|
756
|
-
}).join("\n");
|
|
757
|
-
const rolePrompt = agentRole && ROLE_PROMPTS[agentRole] || DEFAULT_ROLE_PROMPT;
|
|
758
|
-
return `You are reviewing a set of work memories from an AI coding agent.
|
|
759
|
-
These are raw tool call records from ${cluster.dateRange}.
|
|
760
|
-
|
|
761
|
-
Agent: ${cluster.agentId} | Project: ${cluster.projectName} | Date: ${cluster.dateRange}
|
|
762
|
-
|
|
763
|
-
MEMORIES:
|
|
764
|
-
${snippets}
|
|
765
|
-
|
|
766
|
-
${rolePrompt}
|
|
767
|
-
|
|
768
|
-
Format each as a single sentence. Be specific \u2014 include file names,
|
|
769
|
-
function names, and concrete details. Skip if no insight for a category.`;
|
|
770
|
-
}
|
|
771
|
-
async function consolidateCluster(cluster, model, agentRole) {
|
|
772
|
-
const Anthropic = (await import("@anthropic-ai/sdk")).default;
|
|
773
|
-
const client = new Anthropic();
|
|
774
|
-
const prompt = buildConsolidationPrompt(cluster, agentRole);
|
|
775
|
-
const response = await client.messages.create({
|
|
776
|
-
model,
|
|
777
|
-
max_tokens: 300,
|
|
778
|
-
messages: [{ role: "user", content: prompt }]
|
|
779
|
-
});
|
|
780
|
-
const textBlock = response.content.find((b) => b.type === "text");
|
|
781
|
-
return textBlock?.text ?? "";
|
|
782
|
-
}
|
|
783
|
-
async function storeConsolidation(client, cluster, synthesisText, embedFn) {
|
|
784
|
-
const consolidatedId = randomUUID();
|
|
785
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
786
|
-
const rawText = `CONSOLIDATION [${cluster.dateRange}, ${cluster.projectName}]:
|
|
787
|
-
|
|
788
|
-
${synthesisText}`;
|
|
789
|
-
let vector = null;
|
|
790
|
-
if (embedFn) {
|
|
791
|
-
try {
|
|
792
|
-
vector = await embedFn(rawText);
|
|
793
|
-
} catch {
|
|
794
|
-
}
|
|
795
|
-
}
|
|
796
|
-
const insertSql = vector ? `INSERT INTO memories
|
|
797
|
-
(id, agent_id, agent_role, session_id, timestamp,
|
|
798
|
-
tool_name, project_name, has_error, raw_text, vector, version, consolidated, importance)
|
|
799
|
-
VALUES (?, ?, 'consolidation', 'daemon-consolidation', ?, 'consolidation', ?, 0, ?, vector32(?), 0, 1, 9)` : `INSERT INTO memories
|
|
800
|
-
(id, agent_id, agent_role, session_id, timestamp,
|
|
801
|
-
tool_name, project_name, has_error, raw_text, vector, version, consolidated, importance)
|
|
802
|
-
VALUES (?, ?, 'consolidation', 'daemon-consolidation', ?, 'consolidation', ?, 0, ?, NULL, 0, 1, 9)`;
|
|
803
|
-
const insertArgs = vector ? [consolidatedId, cluster.agentId, now, cluster.projectName, rawText, vectorToBlob(vector)] : [consolidatedId, cluster.agentId, now, cluster.projectName, rawText];
|
|
804
|
-
await client.execute({ sql: insertSql, args: insertArgs });
|
|
805
|
-
const sourceIds = cluster.memories.map((m) => m.id);
|
|
806
|
-
const linkStmts = sourceIds.map((sourceId) => ({
|
|
807
|
-
sql: `INSERT INTO consolidations (id, consolidated_memory_id, source_memory_id, created_at)
|
|
808
|
-
VALUES (?, ?, ?, ?)`,
|
|
809
|
-
args: [randomUUID(), consolidatedId, sourceId, now]
|
|
810
|
-
}));
|
|
811
|
-
const placeholders = sourceIds.map(() => "?").join(",");
|
|
812
|
-
const markStmt = {
|
|
813
|
-
sql: `UPDATE memories SET consolidated = 1 WHERE id IN (${placeholders})`,
|
|
814
|
-
args: sourceIds
|
|
815
|
-
};
|
|
816
|
-
await client.batch([...linkStmts, markStmt], "write");
|
|
817
|
-
return { consolidatedMemoryId: consolidatedId, sourceIds, rawText };
|
|
818
|
-
}
|
|
819
|
-
var WIKI_FETCH_TIMEOUT_MS = 1e4;
|
|
820
|
-
async function pushToWiki(consolidation, config) {
|
|
821
|
-
if (!config.wikiEnabled || !config.wikiAutoUpdate) {
|
|
822
|
-
return { updated: false };
|
|
823
|
-
}
|
|
824
|
-
const apiUrl = config.wikiUrl || process.env.EXE_WIKI_API_URL;
|
|
825
|
-
const apiKey = config.wikiApiKey || process.env.EXE_WIKI_API_KEY;
|
|
826
|
-
if (!apiUrl || !apiKey) {
|
|
827
|
-
return { updated: false };
|
|
828
|
-
}
|
|
829
|
-
const workspace = config.wikiWorkspaceMapping[consolidation.projectName] ?? consolidation.projectName;
|
|
830
|
-
try {
|
|
831
|
-
const listRes = await fetch(
|
|
832
|
-
`${apiUrl}/v1/workspace/${encodeURIComponent(workspace)}/documents`,
|
|
833
|
-
{
|
|
834
|
-
headers: { Authorization: `Bearer ${apiKey}` },
|
|
835
|
-
signal: AbortSignal.timeout(WIKI_FETCH_TIMEOUT_MS)
|
|
836
|
-
}
|
|
837
|
-
);
|
|
838
|
-
if (!listRes.ok) {
|
|
839
|
-
return { updated: false, error: `Workspace "${workspace}" not accessible (${listRes.status})` };
|
|
840
|
-
}
|
|
841
|
-
const listJson = await listRes.json();
|
|
842
|
-
const docs = listJson.documents ?? listJson.localFiles?.items ?? [];
|
|
843
|
-
const contentLines = consolidation.rawText.split("\n").filter((l) => l.trim() && !l.startsWith("CONSOLIDATION") && !l.match(/^[A-Z\s]+:$/)).join(" ");
|
|
844
|
-
const keywords = contentLines.toLowerCase().replace(/[^a-z0-9\s]/g, "").split(/\s+/).filter((w) => w.length > 3);
|
|
845
|
-
let bestMatch = null;
|
|
846
|
-
for (const doc of docs) {
|
|
847
|
-
if (!doc.id || !doc.title) continue;
|
|
848
|
-
const titleWords = doc.title.toLowerCase().replace(/[^a-z0-9\s]/g, "").split(/\s+/).filter((w) => w.length > 3);
|
|
849
|
-
if (titleWords.length === 0) continue;
|
|
850
|
-
const matchCount = titleWords.filter(
|
|
851
|
-
(tw) => keywords.some((k) => k.includes(tw) || tw.includes(k))
|
|
852
|
-
).length;
|
|
853
|
-
const score = matchCount / titleWords.length;
|
|
854
|
-
if (score > (bestMatch?.score ?? 0)) {
|
|
855
|
-
bestMatch = { id: doc.id, title: doc.title, score };
|
|
856
|
-
}
|
|
857
|
-
}
|
|
858
|
-
if (bestMatch && bestMatch.score >= config.wikiAutoUpdateThreshold) {
|
|
859
|
-
const updateRes = await fetch(`${apiUrl}/v1/document/raw-text`, {
|
|
860
|
-
method: "POST",
|
|
861
|
-
headers: {
|
|
862
|
-
"Content-Type": "application/json",
|
|
863
|
-
Authorization: `Bearer ${apiKey}`
|
|
864
|
-
},
|
|
865
|
-
body: JSON.stringify({
|
|
866
|
-
textContent: consolidation.rawText,
|
|
867
|
-
metadata: { title: bestMatch.title, appendTo: bestMatch.id },
|
|
868
|
-
workspaceSlugs: [workspace]
|
|
869
|
-
}),
|
|
870
|
-
signal: AbortSignal.timeout(WIKI_FETCH_TIMEOUT_MS)
|
|
871
|
-
});
|
|
872
|
-
if (updateRes.ok) {
|
|
873
|
-
process.stderr.write(
|
|
874
|
-
`[consolidation] Wiki auto-updated: ${workspace}/${bestMatch.title}
|
|
875
|
-
`
|
|
876
|
-
);
|
|
877
|
-
return { updated: true, action: "updated", page: bestMatch.title };
|
|
878
|
-
}
|
|
879
|
-
return { updated: false, error: `Update failed (${updateRes.status})` };
|
|
880
|
-
}
|
|
881
|
-
if (config.wikiAutoUpdateCreateNew) {
|
|
882
|
-
const title = `Consolidated Insights \u2014 ${consolidation.projectName} (${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)})`;
|
|
883
|
-
const createRes = await fetch(`${apiUrl}/v1/document/raw-text`, {
|
|
884
|
-
method: "POST",
|
|
885
|
-
headers: {
|
|
886
|
-
"Content-Type": "application/json",
|
|
887
|
-
Authorization: `Bearer ${apiKey}`
|
|
888
|
-
},
|
|
889
|
-
body: JSON.stringify({
|
|
890
|
-
textContent: consolidation.rawText,
|
|
891
|
-
metadata: { title },
|
|
892
|
-
workspaceSlugs: [workspace]
|
|
893
|
-
}),
|
|
894
|
-
signal: AbortSignal.timeout(WIKI_FETCH_TIMEOUT_MS)
|
|
895
|
-
});
|
|
896
|
-
if (createRes.ok) {
|
|
897
|
-
process.stderr.write(
|
|
898
|
-
`[consolidation] Wiki page created: ${workspace}/${title}
|
|
899
|
-
`
|
|
900
|
-
);
|
|
901
|
-
return { updated: true, action: "created", page: title };
|
|
902
|
-
}
|
|
903
|
-
return { updated: false, error: `Create failed (${createRes.status})` };
|
|
904
|
-
}
|
|
905
|
-
return { updated: false };
|
|
906
|
-
} catch (err) {
|
|
907
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
908
|
-
process.stderr.write(`[consolidation] Wiki push failed: ${msg}
|
|
909
|
-
`);
|
|
910
|
-
return { updated: false, error: msg };
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
|
-
async function runConsolidation(client, options) {
|
|
914
|
-
const memories = await selectUnconsolidated(client);
|
|
915
|
-
if (memories.length < 20) {
|
|
916
|
-
return { clustersProcessed: 0, memoriesConsolidated: 0 };
|
|
917
|
-
}
|
|
918
|
-
let roleMap = {};
|
|
919
|
-
try {
|
|
920
|
-
const { loadEmployeesSync: loadEmployeesSync2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
921
|
-
const employees = loadEmployeesSync2();
|
|
922
|
-
for (const e of employees) {
|
|
923
|
-
roleMap[e.name] = e.role;
|
|
924
|
-
}
|
|
925
|
-
} catch {
|
|
926
|
-
}
|
|
927
|
-
const clusters = groupMemories(memories);
|
|
928
|
-
let clustersProcessed = 0;
|
|
929
|
-
let memoriesConsolidated = 0;
|
|
930
|
-
for (const cluster of clusters) {
|
|
931
|
-
if (clustersProcessed >= options.maxCalls) break;
|
|
932
|
-
if (cluster.memories.length < 3) continue;
|
|
933
|
-
try {
|
|
934
|
-
const isCoordinator = isCoordinatorName(cluster.agentId);
|
|
935
|
-
const agentRole = roleMap[cluster.agentId];
|
|
936
|
-
const dedupCount = await dedupCluster(client, cluster, options.embedFn);
|
|
937
|
-
memoriesConsolidated += dedupCount;
|
|
938
|
-
const synthesis = await consolidateCluster(cluster, options.model, agentRole);
|
|
939
|
-
if (!synthesis.trim()) {
|
|
940
|
-
if (dedupCount > 0) clustersProcessed++;
|
|
941
|
-
continue;
|
|
942
|
-
}
|
|
943
|
-
const result = await storeConsolidation(client, cluster, synthesis, options.embedFn);
|
|
944
|
-
if (isCoordinator && options.wikiConfig) {
|
|
945
|
-
await pushToWiki(
|
|
946
|
-
{ ...result, projectName: cluster.projectName },
|
|
947
|
-
options.wikiConfig
|
|
948
|
-
).catch((err) => {
|
|
949
|
-
process.stderr.write(
|
|
950
|
-
`[consolidation] Wiki push error (non-fatal): ${err instanceof Error ? err.message : String(err)}
|
|
951
|
-
`
|
|
952
|
-
);
|
|
953
|
-
});
|
|
954
|
-
}
|
|
955
|
-
if (isCoordinator) {
|
|
956
|
-
const sourceIds = result.sourceIds;
|
|
957
|
-
if (sourceIds.length > 0) {
|
|
958
|
-
const placeholders = sourceIds.map(() => "?").join(",");
|
|
959
|
-
await client.execute({
|
|
960
|
-
sql: `UPDATE memories SET status = 'archived' WHERE id IN (${placeholders})`,
|
|
961
|
-
args: sourceIds
|
|
962
|
-
});
|
|
963
|
-
}
|
|
964
|
-
}
|
|
965
|
-
clustersProcessed++;
|
|
966
|
-
memoriesConsolidated += cluster.memories.length;
|
|
967
|
-
} catch (err) {
|
|
968
|
-
process.stderr.write(
|
|
969
|
-
`[consolidation] Cluster failed (${cluster.projectName}/${cluster.dateRange}): ${err instanceof Error ? err.message : String(err)}
|
|
970
|
-
`
|
|
971
|
-
);
|
|
972
|
-
}
|
|
973
|
-
}
|
|
974
|
-
return { clustersProcessed, memoriesConsolidated };
|
|
975
|
-
}
|
|
976
|
-
async function dedupCluster(client, cluster, embedFn) {
|
|
977
|
-
if (!embedFn || cluster.memories.length < 2) return 0;
|
|
978
|
-
const vectors = [];
|
|
979
|
-
for (const mem of cluster.memories) {
|
|
980
|
-
try {
|
|
981
|
-
const v = await embedFn(mem.raw_text);
|
|
982
|
-
vectors.push({ id: mem.id, vector: v });
|
|
983
|
-
} catch {
|
|
984
|
-
}
|
|
985
|
-
}
|
|
986
|
-
if (vectors.length < 2) return 0;
|
|
987
|
-
const toArchive = /* @__PURE__ */ new Set();
|
|
988
|
-
for (let i = 0; i < vectors.length; i++) {
|
|
989
|
-
if (toArchive.has(vectors[i].id)) continue;
|
|
990
|
-
for (let j = i + 1; j < vectors.length; j++) {
|
|
991
|
-
if (toArchive.has(vectors[j].id)) continue;
|
|
992
|
-
const sim = cosineSimilarity(vectors[i].vector, vectors[j].vector);
|
|
993
|
-
if (sim > 0.95) {
|
|
994
|
-
toArchive.add(vectors[j].id);
|
|
995
|
-
}
|
|
996
|
-
}
|
|
997
|
-
}
|
|
998
|
-
if (toArchive.size === 0) return 0;
|
|
999
|
-
const ids = [...toArchive];
|
|
1000
|
-
const placeholders = ids.map(() => "?").join(",");
|
|
1001
|
-
await client.execute({
|
|
1002
|
-
sql: `UPDATE memories SET status = 'archived', consolidated = 1 WHERE id IN (${placeholders})`,
|
|
1003
|
-
args: ids
|
|
1004
|
-
});
|
|
1005
|
-
const survivors = vectors.filter((v) => !toArchive.has(v.id)).map((v) => v.id);
|
|
1006
|
-
if (survivors.length > 0) {
|
|
1007
|
-
const survivorPlaceholders = survivors.map(() => "?").join(",");
|
|
1008
|
-
await client.execute({
|
|
1009
|
-
sql: `UPDATE memories SET confidence = MIN(1.0, COALESCE(confidence, 0.7) + 0.1) WHERE id IN (${survivorPlaceholders})`,
|
|
1010
|
-
args: survivors
|
|
1011
|
-
});
|
|
1012
|
-
}
|
|
1013
|
-
return ids.length;
|
|
1014
|
-
}
|
|
1015
|
-
function cosineSimilarity(a, b) {
|
|
1016
|
-
let dot = 0, normA = 0, normB = 0;
|
|
1017
|
-
for (let i = 0; i < a.length; i++) {
|
|
1018
|
-
dot += a[i] * b[i];
|
|
1019
|
-
normA += a[i] * a[i];
|
|
1020
|
-
normB += b[i] * b[i];
|
|
1021
|
-
}
|
|
1022
|
-
const denom = Math.sqrt(normA) * Math.sqrt(normB);
|
|
1023
|
-
return denom === 0 ? 0 : dot / denom;
|
|
1024
|
-
}
|
|
1025
|
-
async function isUserIdle(client, idleMinutes = 30) {
|
|
1026
|
-
const result = await client.execute({
|
|
1027
|
-
sql: `SELECT MAX(timestamp) as last_activity
|
|
1028
|
-
FROM memories
|
|
1029
|
-
WHERE tool_name != 'consolidation'
|
|
1030
|
-
AND timestamp >= datetime('now', '-1 day')`,
|
|
1031
|
-
args: []
|
|
1032
|
-
});
|
|
1033
|
-
const lastActivity = result.rows[0]?.last_activity;
|
|
1034
|
-
if (!lastActivity) return true;
|
|
1035
|
-
const lastMs = new Date(lastActivity).getTime();
|
|
1036
|
-
const now = Date.now();
|
|
1037
|
-
return now - lastMs >= idleMinutes * 60 * 1e3;
|
|
1038
|
-
}
|
|
1039
|
-
async function countUnconsolidated(client) {
|
|
1040
|
-
const result = await client.execute({
|
|
1041
|
-
sql: `SELECT COUNT(*) as cnt FROM memories
|
|
1042
|
-
WHERE consolidated = 0
|
|
1043
|
-
AND COALESCE(memory_type, 'raw') != 'procedure'`,
|
|
1044
|
-
args: []
|
|
1045
|
-
});
|
|
1046
|
-
return Number(result.rows[0]?.cnt ?? 0);
|
|
1047
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
buildConsolidationPrompt,
|
|
3
|
+
consolidateCluster,
|
|
4
|
+
countUnconsolidated,
|
|
5
|
+
groupMemories,
|
|
6
|
+
isUserIdle,
|
|
7
|
+
pushToWiki,
|
|
8
|
+
runConsolidation,
|
|
9
|
+
selectUnconsolidated,
|
|
10
|
+
storeConsolidation
|
|
11
|
+
} from "../chunk-IJ73YE73.js";
|
|
12
|
+
import "../chunk-HSRM6PNM.js";
|
|
13
|
+
import "../chunk-NHK5KW6Y.js";
|
|
14
|
+
import "../chunk-WZQ4CPRG.js";
|
|
15
|
+
import "../chunk-A2NZP64U.js";
|
|
16
|
+
import "../chunk-4NYQAS33.js";
|
|
17
|
+
import "../chunk-RUG3N6P4.js";
|
|
18
|
+
import "../chunk-XUHFQHGZ.js";
|
|
19
|
+
import "../chunk-KVPG5UT6.js";
|
|
20
|
+
import "../chunk-X2IMCCM5.js";
|
|
21
|
+
import "../chunk-KFQGP6VL.js";
|
|
1048
22
|
export {
|
|
1049
23
|
buildConsolidationPrompt,
|
|
1050
24
|
consolidateCluster,
|