@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,862 @@
|
|
|
1
|
+
import {
|
|
2
|
+
init_session_kill_telemetry,
|
|
3
|
+
session_kill_telemetry_exports
|
|
4
|
+
} from "./chunk-IHDHL5ML.js";
|
|
5
|
+
import {
|
|
6
|
+
init_tmux_status,
|
|
7
|
+
tmux_status_exports
|
|
8
|
+
} from "./chunk-DC4ZD76Y.js";
|
|
9
|
+
import {
|
|
10
|
+
init_notifications,
|
|
11
|
+
init_task_scope,
|
|
12
|
+
init_tmux_routing,
|
|
13
|
+
isExeSession,
|
|
14
|
+
notifications_exports,
|
|
15
|
+
sessionScopeFilter,
|
|
16
|
+
tmux_routing_exports
|
|
17
|
+
} from "./chunk-N7L33TED.js";
|
|
18
|
+
import {
|
|
19
|
+
init_intercom_queue,
|
|
20
|
+
intercom_queue_exports
|
|
21
|
+
} from "./chunk-NEAHEC5G.js";
|
|
22
|
+
import {
|
|
23
|
+
init_session_registry,
|
|
24
|
+
session_registry_exports
|
|
25
|
+
} from "./chunk-KRLOFIPI.js";
|
|
26
|
+
import {
|
|
27
|
+
init_transport,
|
|
28
|
+
transport_exports
|
|
29
|
+
} from "./chunk-R4M6XCMU.js";
|
|
30
|
+
import {
|
|
31
|
+
employees_exports,
|
|
32
|
+
init_employees,
|
|
33
|
+
isCoordinatorName
|
|
34
|
+
} from "./chunk-RUG3N6P4.js";
|
|
35
|
+
import {
|
|
36
|
+
__esm,
|
|
37
|
+
__export,
|
|
38
|
+
__require,
|
|
39
|
+
__toCommonJS
|
|
40
|
+
} from "./chunk-KFQGP6VL.js";
|
|
41
|
+
|
|
42
|
+
// src/lib/agent-signals.ts
|
|
43
|
+
var agent_signals_exports = {};
|
|
44
|
+
__export(agent_signals_exports, {
|
|
45
|
+
collectAgentSignals: () => collectAgentSignals,
|
|
46
|
+
hadRecentIntercomAck: () => hadRecentIntercomAck,
|
|
47
|
+
hasNeedsReview: () => hasNeedsReview,
|
|
48
|
+
hasOpenTasks: () => hasOpenTasks,
|
|
49
|
+
hasUnreadInbox: () => hasUnreadInbox
|
|
50
|
+
});
|
|
51
|
+
import { readFileSync, existsSync } from "fs";
|
|
52
|
+
import os from "os";
|
|
53
|
+
import path from "path";
|
|
54
|
+
async function hasOpenTasks(client, agentId) {
|
|
55
|
+
try {
|
|
56
|
+
const scope = sessionScopeFilter(null);
|
|
57
|
+
const result = await client.execute({
|
|
58
|
+
sql: `SELECT 1 FROM tasks
|
|
59
|
+
WHERE assigned_to = ? AND status IN ('open', 'in_progress')${scope.sql}
|
|
60
|
+
LIMIT 1`,
|
|
61
|
+
args: [agentId, ...scope.args]
|
|
62
|
+
});
|
|
63
|
+
return result.rows.length > 0;
|
|
64
|
+
} catch {
|
|
65
|
+
return CONSERVATIVE_ON_ERROR;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async function hasNeedsReview(client, agentId) {
|
|
69
|
+
try {
|
|
70
|
+
const scope = sessionScopeFilter(null);
|
|
71
|
+
const result = await client.execute({
|
|
72
|
+
sql: `SELECT 1 FROM tasks
|
|
73
|
+
WHERE assigned_to = ? AND status = 'needs_review'${scope.sql}
|
|
74
|
+
LIMIT 1`,
|
|
75
|
+
args: [agentId, ...scope.args]
|
|
76
|
+
});
|
|
77
|
+
return result.rows.length > 0;
|
|
78
|
+
} catch {
|
|
79
|
+
return CONSERVATIVE_ON_ERROR;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
async function hasUnreadInbox(client, agentId) {
|
|
83
|
+
try {
|
|
84
|
+
const result = await client.execute({
|
|
85
|
+
sql: `SELECT 1 FROM messages
|
|
86
|
+
WHERE target_agent = ? AND status = 'pending'
|
|
87
|
+
LIMIT 1`,
|
|
88
|
+
args: [agentId]
|
|
89
|
+
});
|
|
90
|
+
return result.rows.length > 0;
|
|
91
|
+
} catch {
|
|
92
|
+
return CONSERVATIVE_ON_ERROR;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function hadRecentIntercomAck(sessionName, windowMs, nowMs = Date.now(), intercomLog = path.join(os.homedir(), ".exe-os", "intercom.log")) {
|
|
96
|
+
if (!existsSync(intercomLog)) return false;
|
|
97
|
+
try {
|
|
98
|
+
const raw = readFileSync(intercomLog, "utf8");
|
|
99
|
+
const lines = raw.split("\n");
|
|
100
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
101
|
+
const line = lines[i];
|
|
102
|
+
if (!line || !line.includes(sessionName)) continue;
|
|
103
|
+
const tsMatch = line.match(/^(\d{4}-\d{2}-\d{2}T[\d:.]+Z)/);
|
|
104
|
+
if (!tsMatch) continue;
|
|
105
|
+
const ts = Date.parse(tsMatch[1]);
|
|
106
|
+
if (!Number.isFinite(ts)) continue;
|
|
107
|
+
if (nowMs - ts <= windowMs) return true;
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
return false;
|
|
111
|
+
} catch {
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
async function collectAgentSignals(client, agentId, sessionName, intercomAckWindowMs, nowMs = Date.now()) {
|
|
116
|
+
const [open, review, inbox] = await Promise.all([
|
|
117
|
+
hasOpenTasks(client, agentId),
|
|
118
|
+
hasNeedsReview(client, agentId),
|
|
119
|
+
hasUnreadInbox(client, agentId)
|
|
120
|
+
]);
|
|
121
|
+
return {
|
|
122
|
+
hasOpenTasks: open,
|
|
123
|
+
hasNeedsReview: review,
|
|
124
|
+
hasUnreadInbox: inbox,
|
|
125
|
+
hadRecentIntercomAck: hadRecentIntercomAck(sessionName, intercomAckWindowMs, nowMs)
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
var CONSERVATIVE_ON_ERROR;
|
|
129
|
+
var init_agent_signals = __esm({
|
|
130
|
+
"src/lib/agent-signals.ts"() {
|
|
131
|
+
"use strict";
|
|
132
|
+
init_task_scope();
|
|
133
|
+
CONSERVATIVE_ON_ERROR = true;
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
// src/lib/daemon-orchestration.ts
|
|
138
|
+
init_tmux_routing();
|
|
139
|
+
init_task_scope();
|
|
140
|
+
init_employees();
|
|
141
|
+
import { execSync } from "child_process";
|
|
142
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync } from "fs";
|
|
143
|
+
import { homedir } from "os";
|
|
144
|
+
import { join } from "path";
|
|
145
|
+
var IDLE_NUDGE_DEDUP_MS = Number(process.env.EXE_NUDGE_INTERVAL_MS) || 6e4;
|
|
146
|
+
var SESSION_TTL_HOURS = Number(process.env.EXE_SESSION_TTL_HOURS) || 4;
|
|
147
|
+
var SESSION_CONTEXT_THRESHOLD_PCT = Number(process.env.EXE_CONTEXT_KILL_PCT) || 50;
|
|
148
|
+
var IDLE_KILL_INTERCOM_ACK_WINDOW_MS = Number(process.env.EXE_INTERCOM_ACK_WINDOW_MS) || 1e4;
|
|
149
|
+
function shouldNudgeEmployee(sessionState, hasOpenTasks2, lastNudgeMs, nowMs, dedupMs) {
|
|
150
|
+
if (sessionState !== "idle") return false;
|
|
151
|
+
if (!hasOpenTasks2) return false;
|
|
152
|
+
if (nowMs - lastNudgeMs < dedupMs) return false;
|
|
153
|
+
return true;
|
|
154
|
+
}
|
|
155
|
+
function shouldKillSession(ageHours, contextPct) {
|
|
156
|
+
return classifyTtlKillReason(ageHours, contextPct) !== null;
|
|
157
|
+
}
|
|
158
|
+
function classifyTtlKillReason(ageHours, contextPct) {
|
|
159
|
+
if (ageHours > SESSION_TTL_HOURS) return "ttl_age";
|
|
160
|
+
if (contextPct !== null && contextPct > SESSION_CONTEXT_THRESHOLD_PCT) return "ttl_context";
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
function shouldKillIdleSession(input) {
|
|
164
|
+
if (!input.enabled) return false;
|
|
165
|
+
if (isExeSession(input.sessionName)) return false;
|
|
166
|
+
if (input.state !== "idle") return false;
|
|
167
|
+
if (input.signals.hasOpenTasks) return false;
|
|
168
|
+
if (input.signals.hasNeedsReview) return false;
|
|
169
|
+
if (input.signals.hasUnreadInbox) return false;
|
|
170
|
+
if (input.signals.hadRecentIntercomAck) return false;
|
|
171
|
+
if (input.idleTicks < input.ticksRequired) return false;
|
|
172
|
+
return true;
|
|
173
|
+
}
|
|
174
|
+
async function pollIdleEmployees(deps, lastNudge) {
|
|
175
|
+
const registered = deps.listRegisteredSessions().filter(
|
|
176
|
+
(s) => !isCoordinatorName(s.agentId)
|
|
177
|
+
);
|
|
178
|
+
if (registered.length === 0) return [];
|
|
179
|
+
let liveSessions;
|
|
180
|
+
try {
|
|
181
|
+
liveSessions = new Set(deps.listTmuxSessions());
|
|
182
|
+
} catch {
|
|
183
|
+
return [];
|
|
184
|
+
}
|
|
185
|
+
const nudged = [];
|
|
186
|
+
const now = Date.now();
|
|
187
|
+
for (const entry of registered) {
|
|
188
|
+
if (!liveSessions.has(entry.windowName)) continue;
|
|
189
|
+
const state = deps.getSessionState(entry.windowName);
|
|
190
|
+
const lastMs = lastNudge.get(entry.windowName) ?? 0;
|
|
191
|
+
if (state !== "idle") continue;
|
|
192
|
+
if (now - lastMs < IDLE_NUDGE_DEDUP_MS) continue;
|
|
193
|
+
const task = await deps.queryOpenTask(entry.agentId);
|
|
194
|
+
if (!task) continue;
|
|
195
|
+
if (shouldNudgeEmployee(state, true, lastMs, now, IDLE_NUDGE_DEDUP_MS)) {
|
|
196
|
+
deps.sendIntercom(entry.windowName);
|
|
197
|
+
lastNudge.set(entry.windowName, now);
|
|
198
|
+
nudged.push(entry.windowName);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return nudged;
|
|
202
|
+
}
|
|
203
|
+
async function checkSessionTTL(deps) {
|
|
204
|
+
const registered = deps.listRegisteredSessions().filter(
|
|
205
|
+
(s) => !isCoordinatorName(s.agentId) && !isExeSession(s.windowName)
|
|
206
|
+
);
|
|
207
|
+
if (registered.length === 0) return [];
|
|
208
|
+
let liveSessions;
|
|
209
|
+
try {
|
|
210
|
+
liveSessions = new Set(deps.listTmuxSessions());
|
|
211
|
+
} catch {
|
|
212
|
+
return [];
|
|
213
|
+
}
|
|
214
|
+
const killed = [];
|
|
215
|
+
for (const entry of registered) {
|
|
216
|
+
if (!liveSessions.has(entry.windowName)) continue;
|
|
217
|
+
if (isCoordinatorName(entry.agentId) || isExeSession(entry.windowName)) continue;
|
|
218
|
+
const createdEpoch = deps.getSessionCreatedEpoch(entry.windowName);
|
|
219
|
+
if (createdEpoch === null) continue;
|
|
220
|
+
const ageHours = (Date.now() / 1e3 - createdEpoch) / 3600;
|
|
221
|
+
const contextPct = deps.parseContextPercentage(entry.windowName);
|
|
222
|
+
const killReason = classifyTtlKillReason(ageHours, contextPct);
|
|
223
|
+
if (killReason !== null) {
|
|
224
|
+
if (deps.hasActiveTasks) {
|
|
225
|
+
try {
|
|
226
|
+
const active = await deps.hasActiveTasks(entry.agentId);
|
|
227
|
+
if (active) {
|
|
228
|
+
process.stderr.write(
|
|
229
|
+
`[exed] Session TTL: SKIPPING ${entry.windowName} (age=${ageHours.toFixed(1)}h, reason=${killReason}) \u2014 agent has active tasks
|
|
230
|
+
`
|
|
231
|
+
);
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
} catch {
|
|
235
|
+
process.stderr.write(
|
|
236
|
+
`[exed] Session TTL: SKIPPING ${entry.windowName} \u2014 hasActiveTasks query failed (conservative)
|
|
237
|
+
`
|
|
238
|
+
);
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
process.stderr.write(
|
|
243
|
+
`[exed] Session TTL: killing ${entry.windowName} (age=${ageHours.toFixed(1)}h, context=${contextPct}%, reason=${killReason})
|
|
244
|
+
`
|
|
245
|
+
);
|
|
246
|
+
deps.recordKill?.({
|
|
247
|
+
sessionName: entry.windowName,
|
|
248
|
+
agentId: entry.agentId,
|
|
249
|
+
reason: killReason
|
|
250
|
+
});
|
|
251
|
+
deps.killSession(entry.windowName);
|
|
252
|
+
killed.push(entry.windowName);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
return killed;
|
|
256
|
+
}
|
|
257
|
+
async function pollIdleKill(deps, idleTickCounts, opts) {
|
|
258
|
+
if (!opts.enabled) return [];
|
|
259
|
+
const registered = deps.listRegisteredSessions().filter(
|
|
260
|
+
(s) => !isCoordinatorName(s.agentId) && !isExeSession(s.windowName)
|
|
261
|
+
);
|
|
262
|
+
if (registered.length === 0) return [];
|
|
263
|
+
let liveSessions;
|
|
264
|
+
try {
|
|
265
|
+
liveSessions = new Set(deps.listTmuxSessions());
|
|
266
|
+
} catch {
|
|
267
|
+
return [];
|
|
268
|
+
}
|
|
269
|
+
const killed = [];
|
|
270
|
+
for (const entry of registered) {
|
|
271
|
+
if (!liveSessions.has(entry.windowName)) {
|
|
272
|
+
idleTickCounts.delete(entry.windowName);
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
275
|
+
const state = deps.getSessionState(entry.windowName);
|
|
276
|
+
if (state !== "idle") {
|
|
277
|
+
idleTickCounts.delete(entry.windowName);
|
|
278
|
+
continue;
|
|
279
|
+
}
|
|
280
|
+
const signals = await deps.collectSignals(entry.agentId, entry.windowName);
|
|
281
|
+
if (signals.hasOpenTasks) {
|
|
282
|
+
const instanceName = entry.windowName.split("-")[0] ?? entry.agentId;
|
|
283
|
+
if (instanceName !== entry.agentId) {
|
|
284
|
+
try {
|
|
285
|
+
const markerPath = __require("path").join(
|
|
286
|
+
__require("os").homedir(),
|
|
287
|
+
".exe-os",
|
|
288
|
+
"session-cache",
|
|
289
|
+
`current-task-${instanceName}.json`
|
|
290
|
+
);
|
|
291
|
+
if (!__require("fs").existsSync(markerPath)) {
|
|
292
|
+
signals.hasOpenTasks = false;
|
|
293
|
+
}
|
|
294
|
+
} catch {
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
if (signals.hasOpenTasks || signals.hasNeedsReview || signals.hasUnreadInbox || signals.hadRecentIntercomAck) {
|
|
299
|
+
idleTickCounts.delete(entry.windowName);
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
const prevTicks = idleTickCounts.get(entry.windowName) ?? 0;
|
|
303
|
+
const nextTicks = prevTicks + 1;
|
|
304
|
+
const shouldKill = shouldKillIdleSession({
|
|
305
|
+
sessionName: entry.windowName,
|
|
306
|
+
state,
|
|
307
|
+
signals,
|
|
308
|
+
idleTicks: nextTicks,
|
|
309
|
+
ticksRequired: opts.ticksRequired,
|
|
310
|
+
enabled: opts.enabled
|
|
311
|
+
});
|
|
312
|
+
if (shouldKill) {
|
|
313
|
+
process.stderr.write(
|
|
314
|
+
`[exed] Idle kill: ${entry.windowName} (agentId=${entry.agentId}, ticks=${nextTicks})
|
|
315
|
+
`
|
|
316
|
+
);
|
|
317
|
+
deps.recordKill?.({
|
|
318
|
+
sessionName: entry.windowName,
|
|
319
|
+
agentId: entry.agentId,
|
|
320
|
+
reason: "idle",
|
|
321
|
+
ticksIdle: nextTicks
|
|
322
|
+
});
|
|
323
|
+
deps.killSession(entry.windowName);
|
|
324
|
+
killed.push(entry.windowName);
|
|
325
|
+
idleTickCounts.delete(entry.windowName);
|
|
326
|
+
} else {
|
|
327
|
+
idleTickCounts.set(entry.windowName, nextTicks);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
return killed;
|
|
331
|
+
}
|
|
332
|
+
var REVIEW_NUDGE_COOLDOWN_MS = 3e5;
|
|
333
|
+
async function pollReviewNudge(deps, state) {
|
|
334
|
+
let sessions;
|
|
335
|
+
try {
|
|
336
|
+
sessions = deps.listTmuxSessions().filter((s) => isExeSession(s));
|
|
337
|
+
} catch {
|
|
338
|
+
return [];
|
|
339
|
+
}
|
|
340
|
+
if (sessions.length === 0) return [];
|
|
341
|
+
const nudged = [];
|
|
342
|
+
const now = Date.now();
|
|
343
|
+
for (const exeSession of sessions) {
|
|
344
|
+
const prev = state.lastNudge.get(exeSession);
|
|
345
|
+
if (prev && now - prev.at < REVIEW_NUDGE_COOLDOWN_MS) continue;
|
|
346
|
+
const sessionState = deps.getSessionState(exeSession);
|
|
347
|
+
if (sessionState !== "idle") continue;
|
|
348
|
+
let count;
|
|
349
|
+
try {
|
|
350
|
+
count = await deps.countReviewsForScope(exeSession);
|
|
351
|
+
} catch {
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
354
|
+
if (count === 0) continue;
|
|
355
|
+
if (prev && prev.count === count) continue;
|
|
356
|
+
try {
|
|
357
|
+
deps.sendNudge(exeSession);
|
|
358
|
+
state.lastNudge.set(exeSession, { at: now, count });
|
|
359
|
+
nudged.push(exeSession);
|
|
360
|
+
} catch {
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
if (nudged.length > 0 && deps.persistState) {
|
|
364
|
+
try {
|
|
365
|
+
deps.persistState(state);
|
|
366
|
+
} catch {
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
return nudged;
|
|
370
|
+
}
|
|
371
|
+
var NUDGE_STATE_PATH = join(homedir(), ".exe-os", "review-nudge-state.json");
|
|
372
|
+
function loadNudgeState() {
|
|
373
|
+
const state = { lastNudge: /* @__PURE__ */ new Map() };
|
|
374
|
+
try {
|
|
375
|
+
if (!existsSync2(NUDGE_STATE_PATH)) return state;
|
|
376
|
+
const raw = JSON.parse(readFileSync2(NUDGE_STATE_PATH, "utf8"));
|
|
377
|
+
if (Array.isArray(raw)) {
|
|
378
|
+
for (const [key, val] of raw) {
|
|
379
|
+
if (key && typeof val?.at === "number" && typeof val?.count === "number") {
|
|
380
|
+
state.lastNudge.set(key, val);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
} catch {
|
|
385
|
+
}
|
|
386
|
+
return state;
|
|
387
|
+
}
|
|
388
|
+
function saveNudgeState(state) {
|
|
389
|
+
const entries = Array.from(state.lastNudge.entries());
|
|
390
|
+
writeFileSync(NUDGE_STATE_PATH, JSON.stringify(entries), "utf8");
|
|
391
|
+
}
|
|
392
|
+
function createReviewNudgeRealDeps(getClient) {
|
|
393
|
+
return {
|
|
394
|
+
listTmuxSessions: () => {
|
|
395
|
+
const { listTmuxSessions } = (init_tmux_status(), __toCommonJS(tmux_status_exports));
|
|
396
|
+
return listTmuxSessions();
|
|
397
|
+
},
|
|
398
|
+
getSessionState: (sessionName) => {
|
|
399
|
+
const { getSessionState } = (init_tmux_routing(), __toCommonJS(tmux_routing_exports));
|
|
400
|
+
return getSessionState(sessionName);
|
|
401
|
+
},
|
|
402
|
+
countReviewsForScope: async (sessionScope) => {
|
|
403
|
+
const client = getClient();
|
|
404
|
+
const result = await client.execute({
|
|
405
|
+
sql: `SELECT COUNT(*) as cnt FROM tasks
|
|
406
|
+
WHERE status = 'needs_review'
|
|
407
|
+
AND (session_scope = ? OR session_scope IS NULL)`,
|
|
408
|
+
args: [sessionScope]
|
|
409
|
+
});
|
|
410
|
+
return Number(result.rows[0]?.cnt ?? 0);
|
|
411
|
+
},
|
|
412
|
+
sendNudge: (sessionName) => {
|
|
413
|
+
const { queueIntercom: qi } = (init_intercom_queue(), __toCommonJS(intercom_queue_exports));
|
|
414
|
+
qi(sessionName, "review nudge: pending reviews");
|
|
415
|
+
},
|
|
416
|
+
persistState: saveNudgeState
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
function createIdleNudgeRealDeps(getClient) {
|
|
420
|
+
return {
|
|
421
|
+
listRegisteredSessions: () => {
|
|
422
|
+
const { listSessions } = (init_session_registry(), __toCommonJS(session_registry_exports));
|
|
423
|
+
return listSessions();
|
|
424
|
+
},
|
|
425
|
+
listTmuxSessions: () => {
|
|
426
|
+
const { listTmuxSessions } = (init_tmux_status(), __toCommonJS(tmux_status_exports));
|
|
427
|
+
return listTmuxSessions();
|
|
428
|
+
},
|
|
429
|
+
getSessionState: (sessionName) => {
|
|
430
|
+
const { getSessionState } = (init_tmux_routing(), __toCommonJS(tmux_routing_exports));
|
|
431
|
+
return getSessionState(sessionName);
|
|
432
|
+
},
|
|
433
|
+
queryOpenTask: async (agentId) => {
|
|
434
|
+
const client = getClient();
|
|
435
|
+
const doScope = sessionScopeFilter(null);
|
|
436
|
+
const result = await client.execute({
|
|
437
|
+
sql: `SELECT id, title, priority FROM tasks
|
|
438
|
+
WHERE assigned_to = ? AND status IN ('open', 'in_progress')${doScope.sql}
|
|
439
|
+
ORDER BY CASE priority WHEN 'p0' THEN 0 WHEN 'p1' THEN 1 ELSE 2 END
|
|
440
|
+
LIMIT 1`,
|
|
441
|
+
args: [agentId, ...doScope.args]
|
|
442
|
+
});
|
|
443
|
+
if (result.rows.length === 0) return null;
|
|
444
|
+
const row = result.rows[0];
|
|
445
|
+
return row;
|
|
446
|
+
},
|
|
447
|
+
sendIntercom: (sessionName) => {
|
|
448
|
+
const { sendIntercom } = (init_tmux_routing(), __toCommonJS(tmux_routing_exports));
|
|
449
|
+
return sendIntercom(sessionName);
|
|
450
|
+
}
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
function createSessionTTLRealDeps(getClient) {
|
|
454
|
+
return {
|
|
455
|
+
listRegisteredSessions: () => {
|
|
456
|
+
const { listSessions } = (init_session_registry(), __toCommonJS(session_registry_exports));
|
|
457
|
+
return listSessions();
|
|
458
|
+
},
|
|
459
|
+
listTmuxSessions: () => {
|
|
460
|
+
const { listTmuxSessions } = (init_tmux_status(), __toCommonJS(tmux_status_exports));
|
|
461
|
+
return listTmuxSessions();
|
|
462
|
+
},
|
|
463
|
+
getSessionCreatedEpoch: (sessionName) => {
|
|
464
|
+
try {
|
|
465
|
+
const out = execSync(
|
|
466
|
+
`tmux display-message -t ${JSON.stringify(sessionName)} -p '#{session_created}' 2>/dev/null`,
|
|
467
|
+
{ encoding: "utf8", timeout: 3e3 }
|
|
468
|
+
).trim();
|
|
469
|
+
const epoch = parseInt(out, 10);
|
|
470
|
+
return isNaN(epoch) ? null : epoch;
|
|
471
|
+
} catch {
|
|
472
|
+
return null;
|
|
473
|
+
}
|
|
474
|
+
},
|
|
475
|
+
parseContextPercentage: (sessionName) => {
|
|
476
|
+
const { parseContextPercentage } = (init_tmux_status(), __toCommonJS(tmux_status_exports));
|
|
477
|
+
return parseContextPercentage(sessionName);
|
|
478
|
+
},
|
|
479
|
+
killSession: (sessionName) => {
|
|
480
|
+
const { getTransport } = (init_transport(), __toCommonJS(transport_exports));
|
|
481
|
+
getTransport().kill(sessionName);
|
|
482
|
+
},
|
|
483
|
+
hasActiveTasks: getClient ? async (agentId) => {
|
|
484
|
+
const client = getClient();
|
|
485
|
+
const scope = sessionScopeFilter(null);
|
|
486
|
+
const result = await client.execute({
|
|
487
|
+
sql: `SELECT 1 FROM tasks
|
|
488
|
+
WHERE assigned_to = ? AND status IN ('open', 'in_progress')${scope.sql}
|
|
489
|
+
LIMIT 1`,
|
|
490
|
+
args: [agentId, ...scope.args]
|
|
491
|
+
});
|
|
492
|
+
return result.rows.length > 0;
|
|
493
|
+
} : void 0,
|
|
494
|
+
recordKill: (input) => {
|
|
495
|
+
const { recordSessionKill } = (init_session_kill_telemetry(), __toCommonJS(session_kill_telemetry_exports));
|
|
496
|
+
void recordSessionKill(input);
|
|
497
|
+
}
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
function createIdleKillRealDeps(getClient, intercomAckWindowMs) {
|
|
501
|
+
return {
|
|
502
|
+
listRegisteredSessions: () => {
|
|
503
|
+
const { listSessions } = (init_session_registry(), __toCommonJS(session_registry_exports));
|
|
504
|
+
return listSessions();
|
|
505
|
+
},
|
|
506
|
+
listTmuxSessions: () => {
|
|
507
|
+
const { listTmuxSessions } = (init_tmux_status(), __toCommonJS(tmux_status_exports));
|
|
508
|
+
return listTmuxSessions();
|
|
509
|
+
},
|
|
510
|
+
getSessionState: (sessionName) => {
|
|
511
|
+
const { getSessionState } = (init_tmux_routing(), __toCommonJS(tmux_routing_exports));
|
|
512
|
+
return getSessionState(sessionName);
|
|
513
|
+
},
|
|
514
|
+
collectSignals: async (agentId, sessionName) => {
|
|
515
|
+
const { collectAgentSignals: collectAgentSignals2 } = (init_agent_signals(), __toCommonJS(agent_signals_exports));
|
|
516
|
+
return collectAgentSignals2(getClient(), agentId, sessionName, intercomAckWindowMs);
|
|
517
|
+
},
|
|
518
|
+
killSession: (sessionName) => {
|
|
519
|
+
const { getTransport } = (init_transport(), __toCommonJS(transport_exports));
|
|
520
|
+
getTransport().kill(sessionName);
|
|
521
|
+
},
|
|
522
|
+
recordKill: (input) => {
|
|
523
|
+
const { recordSessionKill } = (init_session_kill_telemetry(), __toCommonJS(session_kill_telemetry_exports));
|
|
524
|
+
void recordSessionKill(input);
|
|
525
|
+
}
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
var AUTO_WAKE_COOLDOWN_MS = 5 * 60 * 1e3;
|
|
529
|
+
var AUTO_WAKE_MAX_RETRIES = 3;
|
|
530
|
+
var _autoWakeLastSpawn = /* @__PURE__ */ new Map();
|
|
531
|
+
var _autoWakeTaskRetries = /* @__PURE__ */ new Map();
|
|
532
|
+
function _resetAutoWakeState() {
|
|
533
|
+
_autoWakeLastSpawn.clear();
|
|
534
|
+
_autoWakeTaskRetries.clear();
|
|
535
|
+
}
|
|
536
|
+
function shouldAutoWake(input) {
|
|
537
|
+
if (isCoordinatorName(input.agentId)) return false;
|
|
538
|
+
if (input.hasRunningSession) return false;
|
|
539
|
+
if (input.nowMs - input.lastSpawnMs < input.cooldownMs) return false;
|
|
540
|
+
return true;
|
|
541
|
+
}
|
|
542
|
+
async function pollOrphanedTasks(deps, nowMs = Date.now()) {
|
|
543
|
+
let liveSessions;
|
|
544
|
+
try {
|
|
545
|
+
liveSessions = deps.listTmuxSessions();
|
|
546
|
+
} catch {
|
|
547
|
+
return [];
|
|
548
|
+
}
|
|
549
|
+
const liveAgents = /* @__PURE__ */ new Set();
|
|
550
|
+
for (const session of liveSessions) {
|
|
551
|
+
const agent = deps.parseAgentFromSession(session);
|
|
552
|
+
if (agent) liveAgents.add(agent);
|
|
553
|
+
}
|
|
554
|
+
const coordinatorSessions = liveSessions.filter((s) => isExeSession(s));
|
|
555
|
+
let tasksByAgent;
|
|
556
|
+
try {
|
|
557
|
+
tasksByAgent = await deps.queryTasksByAgent();
|
|
558
|
+
} catch {
|
|
559
|
+
return [];
|
|
560
|
+
}
|
|
561
|
+
const coordinatorSet = new Set(coordinatorSessions);
|
|
562
|
+
const agentTasks = /* @__PURE__ */ new Map();
|
|
563
|
+
for (const t of tasksByAgent) {
|
|
564
|
+
const scope = t.sessionScope || coordinatorSessions[0] || null;
|
|
565
|
+
if (!scope) continue;
|
|
566
|
+
if (t.sessionScope && !coordinatorSet.has(t.sessionScope)) {
|
|
567
|
+
process.stderr.write(
|
|
568
|
+
`[auto-wake] Skipping ${t.agentId} task ${t.taskId} \u2014 coordinator session "${t.sessionScope}" is dead
|
|
569
|
+
`
|
|
570
|
+
);
|
|
571
|
+
continue;
|
|
572
|
+
}
|
|
573
|
+
const key = `${t.agentId}::${scope}`;
|
|
574
|
+
const existing = agentTasks.get(key) ?? [];
|
|
575
|
+
existing.push({ taskId: t.taskId, priority: t.priority, sessionScope: scope });
|
|
576
|
+
agentTasks.set(key, existing);
|
|
577
|
+
}
|
|
578
|
+
const woken = [];
|
|
579
|
+
for (const [key, tasks] of agentTasks) {
|
|
580
|
+
const agentId = key.split("::")[0];
|
|
581
|
+
const sessionScope = tasks[0].sessionScope;
|
|
582
|
+
if (!shouldAutoWake({
|
|
583
|
+
agentId,
|
|
584
|
+
hasRunningSession: liveAgents.has(agentId),
|
|
585
|
+
lastSpawnMs: _autoWakeLastSpawn.get(agentId) ?? 0,
|
|
586
|
+
nowMs,
|
|
587
|
+
cooldownMs: AUTO_WAKE_COOLDOWN_MS
|
|
588
|
+
})) {
|
|
589
|
+
continue;
|
|
590
|
+
}
|
|
591
|
+
const topTask = tasks[0];
|
|
592
|
+
const retries = _autoWakeTaskRetries.get(topTask.taskId) ?? 0;
|
|
593
|
+
if (retries >= AUTO_WAKE_MAX_RETRIES) {
|
|
594
|
+
try {
|
|
595
|
+
await deps.markTaskBlocked(
|
|
596
|
+
topTask.taskId,
|
|
597
|
+
`Auto-wake failed ${AUTO_WAKE_MAX_RETRIES} times \u2014 marking blocked for manual intervention`
|
|
598
|
+
);
|
|
599
|
+
process.stderr.write(
|
|
600
|
+
`[auto-wake] ${agentId} task ${topTask.taskId} exceeded ${AUTO_WAKE_MAX_RETRIES} retries \u2014 marked blocked
|
|
601
|
+
`
|
|
602
|
+
);
|
|
603
|
+
} catch {
|
|
604
|
+
}
|
|
605
|
+
continue;
|
|
606
|
+
}
|
|
607
|
+
process.stderr.write(
|
|
608
|
+
`[auto-wake] ${agentId} has ${tasks.length} pending task(s) but no session \u2014 spawning in ${sessionScope} (attempt ${retries + 1} for task ${topTask.taskId})
|
|
609
|
+
`
|
|
610
|
+
);
|
|
611
|
+
try {
|
|
612
|
+
const result = deps.ensureEmployee(agentId, sessionScope);
|
|
613
|
+
if (result.status === "failed") {
|
|
614
|
+
process.stderr.write(
|
|
615
|
+
`[auto-wake] Failed to spawn ${agentId}: ${result.error ?? "unknown"}
|
|
616
|
+
`
|
|
617
|
+
);
|
|
618
|
+
continue;
|
|
619
|
+
}
|
|
620
|
+
_autoWakeLastSpawn.set(agentId, nowMs);
|
|
621
|
+
_autoWakeTaskRetries.set(topTask.taskId, retries + 1);
|
|
622
|
+
woken.push(agentId);
|
|
623
|
+
} catch (err) {
|
|
624
|
+
process.stderr.write(
|
|
625
|
+
`[auto-wake] Error spawning ${agentId}: ${err instanceof Error ? err.message : String(err)}
|
|
626
|
+
`
|
|
627
|
+
);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
return woken;
|
|
631
|
+
}
|
|
632
|
+
var STUCK_TASK_GRACE_MS = 5 * 60 * 1e3;
|
|
633
|
+
async function releaseStuckTasks(deps, nowMs = Date.now()) {
|
|
634
|
+
let liveSessions;
|
|
635
|
+
try {
|
|
636
|
+
liveSessions = deps.listTmuxSessions();
|
|
637
|
+
} catch {
|
|
638
|
+
return [];
|
|
639
|
+
}
|
|
640
|
+
const liveAgents = /* @__PURE__ */ new Set();
|
|
641
|
+
for (const session of liveSessions) {
|
|
642
|
+
const agent = deps.parseAgentFromSession(session);
|
|
643
|
+
if (agent) liveAgents.add(agent);
|
|
644
|
+
}
|
|
645
|
+
for (const session of liveSessions) {
|
|
646
|
+
if (isExeSession(session)) liveAgents.add(session);
|
|
647
|
+
}
|
|
648
|
+
let tasks;
|
|
649
|
+
try {
|
|
650
|
+
tasks = await deps.queryInProgressTasks();
|
|
651
|
+
} catch {
|
|
652
|
+
return [];
|
|
653
|
+
}
|
|
654
|
+
const released = [];
|
|
655
|
+
for (const t of tasks) {
|
|
656
|
+
if (liveAgents.has(t.agentId)) continue;
|
|
657
|
+
const updatedMs = new Date(t.updatedAt).getTime();
|
|
658
|
+
if (isNaN(updatedMs) || nowMs - updatedMs < STUCK_TASK_GRACE_MS) continue;
|
|
659
|
+
const ageMinutes = Math.round((nowMs - updatedMs) / 6e4);
|
|
660
|
+
const reason = `[auto-release] Agent "${t.agentId}" session is dead and task has been in_progress for ${ageMinutes}m with no update. Marked blocked for triage.`;
|
|
661
|
+
try {
|
|
662
|
+
await deps.markTaskBlocked(t.taskId, reason);
|
|
663
|
+
released.push(t.taskId);
|
|
664
|
+
process.stderr.write(
|
|
665
|
+
`[stuck-release] Task ${t.taskId} (${t.agentId}) \u2014 in_progress for ${ageMinutes}m, agent dead \u2192 blocked
|
|
666
|
+
`
|
|
667
|
+
);
|
|
668
|
+
if (deps.notifyOrphan) {
|
|
669
|
+
try {
|
|
670
|
+
await deps.notifyOrphan(t.taskId, t.agentId);
|
|
671
|
+
} catch {
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
} catch (err) {
|
|
675
|
+
process.stderr.write(
|
|
676
|
+
`[stuck-release] Failed to release ${t.taskId}: ${err instanceof Error ? err.message : String(err)}
|
|
677
|
+
`
|
|
678
|
+
);
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
return released;
|
|
682
|
+
}
|
|
683
|
+
function createStuckTaskRealDeps(getClient) {
|
|
684
|
+
return {
|
|
685
|
+
listTmuxSessions: () => {
|
|
686
|
+
const { listTmuxSessions } = (init_tmux_status(), __toCommonJS(tmux_status_exports));
|
|
687
|
+
return listTmuxSessions();
|
|
688
|
+
},
|
|
689
|
+
queryInProgressTasks: async () => {
|
|
690
|
+
const client = getClient();
|
|
691
|
+
const result = await client.execute({
|
|
692
|
+
sql: `SELECT id, assigned_to, session_scope, updated_at FROM tasks
|
|
693
|
+
WHERE status = 'in_progress'
|
|
694
|
+
ORDER BY updated_at ASC`,
|
|
695
|
+
args: []
|
|
696
|
+
});
|
|
697
|
+
return result.rows.map((r) => ({
|
|
698
|
+
taskId: String(r.id),
|
|
699
|
+
agentId: String(r.assigned_to),
|
|
700
|
+
sessionScope: r.session_scope ? String(r.session_scope) : null,
|
|
701
|
+
updatedAt: String(r.updated_at)
|
|
702
|
+
}));
|
|
703
|
+
},
|
|
704
|
+
markTaskBlocked: async (taskId, reason) => {
|
|
705
|
+
const client = getClient();
|
|
706
|
+
await client.execute({
|
|
707
|
+
sql: `UPDATE tasks SET status = 'blocked', result = ?, updated_at = ? WHERE id = ?`,
|
|
708
|
+
args: [reason, (/* @__PURE__ */ new Date()).toISOString(), taskId]
|
|
709
|
+
});
|
|
710
|
+
},
|
|
711
|
+
parseAgentFromSession: (sessionName) => {
|
|
712
|
+
const { baseAgentName } = (init_employees(), __toCommonJS(employees_exports));
|
|
713
|
+
if (!sessionName.includes("-")) return null;
|
|
714
|
+
const agentPart = sessionName.split("-")[0];
|
|
715
|
+
return baseAgentName(agentPart);
|
|
716
|
+
},
|
|
717
|
+
notifyOrphan: async (taskId, agentId) => {
|
|
718
|
+
const { writeNotification } = (init_notifications(), __toCommonJS(notifications_exports));
|
|
719
|
+
await writeNotification({
|
|
720
|
+
agentId,
|
|
721
|
+
agentRole: "employee",
|
|
722
|
+
event: "orphan_task",
|
|
723
|
+
project: "",
|
|
724
|
+
summary: `Agent "${agentId}" session died \u2014 task ${taskId.slice(0, 8)} auto-released to blocked for triage`
|
|
725
|
+
});
|
|
726
|
+
}
|
|
727
|
+
};
|
|
728
|
+
}
|
|
729
|
+
function createAutoWakeRealDeps(getClient, projectDir) {
|
|
730
|
+
return {
|
|
731
|
+
listTmuxSessions: () => {
|
|
732
|
+
const { listTmuxSessions } = (init_tmux_status(), __toCommonJS(tmux_status_exports));
|
|
733
|
+
return listTmuxSessions();
|
|
734
|
+
},
|
|
735
|
+
queryTasksByAgent: async () => {
|
|
736
|
+
const client = getClient();
|
|
737
|
+
const result = await client.execute({
|
|
738
|
+
sql: `SELECT assigned_to, id, priority, session_scope FROM tasks
|
|
739
|
+
WHERE status IN ('open', 'in_progress')
|
|
740
|
+
ORDER BY
|
|
741
|
+
CASE priority WHEN 'p0' THEN 0 WHEN 'p1' THEN 1 WHEN 'p2' THEN 2 ELSE 3 END,
|
|
742
|
+
created_at ASC`,
|
|
743
|
+
args: []
|
|
744
|
+
});
|
|
745
|
+
return result.rows.map((r) => ({
|
|
746
|
+
agentId: String(r.assigned_to),
|
|
747
|
+
taskId: String(r.id),
|
|
748
|
+
priority: String(r.priority),
|
|
749
|
+
sessionScope: r.session_scope ? String(r.session_scope) : null
|
|
750
|
+
}));
|
|
751
|
+
},
|
|
752
|
+
ensureEmployee: (agentName, scope) => {
|
|
753
|
+
const { ensureEmployee } = (init_tmux_routing(), __toCommonJS(tmux_routing_exports));
|
|
754
|
+
return ensureEmployee(agentName, scope, projectDir);
|
|
755
|
+
},
|
|
756
|
+
markTaskBlocked: async (taskId, reason) => {
|
|
757
|
+
const client = getClient();
|
|
758
|
+
await client.execute({
|
|
759
|
+
sql: `UPDATE tasks SET status = 'blocked', result = ?, updated_at = ? WHERE id = ?`,
|
|
760
|
+
args: [reason, (/* @__PURE__ */ new Date()).toISOString(), taskId]
|
|
761
|
+
});
|
|
762
|
+
},
|
|
763
|
+
parseAgentFromSession: (sessionName) => {
|
|
764
|
+
const { baseAgentName } = (init_employees(), __toCommonJS(employees_exports));
|
|
765
|
+
if (!sessionName.includes("-")) return null;
|
|
766
|
+
const agentPart = sessionName.split("-")[0];
|
|
767
|
+
return baseAgentName(agentPart);
|
|
768
|
+
}
|
|
769
|
+
};
|
|
770
|
+
}
|
|
771
|
+
var ORPHAN_SIGKILL_DELAY_MS = 5e3;
|
|
772
|
+
var ORPHAN_PATTERNS = [
|
|
773
|
+
"exe-os/dist/mcp/server.js",
|
|
774
|
+
"exe-mem/dist/mcp/server.js",
|
|
775
|
+
"exe-os/dist/hooks/ingest-worker.js",
|
|
776
|
+
"exe-mem/dist/hooks/ingest-worker.js"
|
|
777
|
+
];
|
|
778
|
+
function reapOrphanedMcpProcesses(deps) {
|
|
779
|
+
const lines = deps.listProcesses();
|
|
780
|
+
const reaped = [];
|
|
781
|
+
for (const line of lines) {
|
|
782
|
+
const trimmed = line.trim();
|
|
783
|
+
const match = trimmed.match(/^(\d+)\s+1\s+(.+)$/);
|
|
784
|
+
if (!match) continue;
|
|
785
|
+
const pid = parseInt(match[1], 10);
|
|
786
|
+
const args = match[2];
|
|
787
|
+
if (pid === deps.selfPid) continue;
|
|
788
|
+
if (!ORPHAN_PATTERNS.some((pat) => args.includes(pat))) continue;
|
|
789
|
+
try {
|
|
790
|
+
deps.killProcess(pid, "SIGTERM");
|
|
791
|
+
} catch {
|
|
792
|
+
continue;
|
|
793
|
+
}
|
|
794
|
+
const desc = `PID ${pid} (${args.slice(0, 100)})`;
|
|
795
|
+
reaped.push(desc);
|
|
796
|
+
deps.scheduleKill(pid, ORPHAN_SIGKILL_DELAY_MS, () => {
|
|
797
|
+
try {
|
|
798
|
+
deps.killProcess(pid, "SIGKILL");
|
|
799
|
+
} catch {
|
|
800
|
+
}
|
|
801
|
+
});
|
|
802
|
+
}
|
|
803
|
+
return reaped;
|
|
804
|
+
}
|
|
805
|
+
function createOrphanReaperRealDeps() {
|
|
806
|
+
return {
|
|
807
|
+
listProcesses: () => {
|
|
808
|
+
const output = execSync("ps -eo pid,ppid,args", {
|
|
809
|
+
encoding: "utf8",
|
|
810
|
+
timeout: 5e3
|
|
811
|
+
});
|
|
812
|
+
return output.split("\n");
|
|
813
|
+
},
|
|
814
|
+
killProcess: (pid, signal) => {
|
|
815
|
+
process.kill(pid, signal);
|
|
816
|
+
},
|
|
817
|
+
scheduleKill: (_pid, delayMs, cb) => {
|
|
818
|
+
setTimeout(() => {
|
|
819
|
+
try {
|
|
820
|
+
cb();
|
|
821
|
+
} catch {
|
|
822
|
+
}
|
|
823
|
+
}, delayMs).unref();
|
|
824
|
+
},
|
|
825
|
+
selfPid: process.pid
|
|
826
|
+
};
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
export {
|
|
830
|
+
IDLE_NUDGE_DEDUP_MS,
|
|
831
|
+
SESSION_TTL_HOURS,
|
|
832
|
+
SESSION_CONTEXT_THRESHOLD_PCT,
|
|
833
|
+
IDLE_KILL_INTERCOM_ACK_WINDOW_MS,
|
|
834
|
+
shouldNudgeEmployee,
|
|
835
|
+
shouldKillSession,
|
|
836
|
+
classifyTtlKillReason,
|
|
837
|
+
shouldKillIdleSession,
|
|
838
|
+
pollIdleEmployees,
|
|
839
|
+
checkSessionTTL,
|
|
840
|
+
pollIdleKill,
|
|
841
|
+
REVIEW_NUDGE_COOLDOWN_MS,
|
|
842
|
+
pollReviewNudge,
|
|
843
|
+
loadNudgeState,
|
|
844
|
+
saveNudgeState,
|
|
845
|
+
createReviewNudgeRealDeps,
|
|
846
|
+
createIdleNudgeRealDeps,
|
|
847
|
+
createSessionTTLRealDeps,
|
|
848
|
+
createIdleKillRealDeps,
|
|
849
|
+
AUTO_WAKE_COOLDOWN_MS,
|
|
850
|
+
AUTO_WAKE_MAX_RETRIES,
|
|
851
|
+
_resetAutoWakeState,
|
|
852
|
+
shouldAutoWake,
|
|
853
|
+
pollOrphanedTasks,
|
|
854
|
+
STUCK_TASK_GRACE_MS,
|
|
855
|
+
releaseStuckTasks,
|
|
856
|
+
createStuckTaskRealDeps,
|
|
857
|
+
createAutoWakeRealDeps,
|
|
858
|
+
ORPHAN_SIGKILL_DELAY_MS,
|
|
859
|
+
ORPHAN_PATTERNS,
|
|
860
|
+
reapOrphanedMcpProcesses,
|
|
861
|
+
createOrphanReaperRealDeps
|
|
862
|
+
};
|