@askexenow/exe-os 0.9.342 → 0.9.343
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-TNIO6IY3.js → active-agent-MDGDKGCL.js} +4 -4
- package/dist/{active-agent-PVGE57FY.js → active-agent-SNVSJFI5.js} +4 -4
- package/dist/{agentic-ontology-3FXYMHKW.js → agentic-ontology-SCG6UUHK.js} +1 -1
- package/dist/{backfill-gate-65LSYVE5.js → backfill-gate-HARARX5F.js} +2 -2
- package/dist/{backfill-metadata-ZSMZC45J.js → backfill-metadata-SCQ5FPDR.js} +5 -5
- package/dist/{background-jobs-EXR5RVGG.js → background-jobs-KKRO3QRO.js} +2 -2
- package/dist/{backup-verify-3Y2FHGZU.js → backup-verify-KDLOT4RP.js} +3 -3
- package/dist/{behaviors-KYRB3NGJ.js → behaviors-MICGF3H3.js} +6 -6
- package/dist/bin/age-ontology-load.js +2 -2
- package/dist/bin/agentic-ontology-backfill.js +7 -7
- package/dist/bin/agentic-reflection-backfill.js +8 -8
- package/dist/bin/agentic-semantic-label.js +7 -7
- package/dist/bin/backfill-conversations.js +7 -7
- package/dist/bin/backfill-responses.js +7 -7
- package/dist/bin/backfill-vectors.js +16 -16
- package/dist/bin/bulk-sync-postgres.js +15 -15
- package/dist/bin/cc-doctor.js +8 -8
- package/dist/bin/cleanup-stale-review-tasks.js +20 -19
- package/dist/bin/cli.js +23 -23
- package/dist/bin/daemon-restart-handoff.js +27 -0
- package/dist/bin/deferred-daemon-restart.js +116 -89
- package/dist/bin/exe-agent-config.js +4 -4
- package/dist/bin/exe-agent.js +13 -13
- package/dist/bin/exe-assign.js +9 -9
- package/dist/bin/exe-boot.js +34 -33
- package/dist/bin/exe-call.js +6 -6
- package/dist/bin/exe-cloud.js +16 -16
- package/dist/bin/exe-config-dump.js +4 -4
- package/dist/bin/exe-dispatch.js +20 -19
- package/dist/bin/exe-doctor.js +6 -6
- package/dist/bin/exe-export-behaviors.js +10 -10
- package/dist/bin/exe-forget.js +9 -9
- package/dist/bin/exe-gateway.js +8 -8
- package/dist/bin/exe-grant.js +4 -4
- package/dist/bin/exe-healthcheck.js +8 -8
- package/dist/bin/exe-heartbeat.js +20 -19
- package/dist/bin/exe-kill.js +25 -24
- package/dist/bin/exe-launch-agent.js +46 -31
- package/dist/bin/exe-memory-reads.js +5 -5
- package/dist/bin/exe-new-employee.js +10 -10
- package/dist/bin/exe-os-mcp-proxy.js +365 -0
- package/dist/bin/exe-pending-messages.js +21 -20
- package/dist/bin/exe-pending-notifications.js +20 -19
- package/dist/bin/exe-pending-reviews.js +20 -19
- package/dist/bin/exe-rename.js +6 -6
- package/dist/bin/exe-review.js +24 -23
- package/dist/bin/exe-search.js +6 -6
- package/dist/bin/exe-session-cleanup.js +23 -22
- package/dist/bin/exe-settings.js +16 -16
- package/dist/bin/exe-start-codex.js +17 -17
- package/dist/bin/exe-start-opencode.js +9 -9
- package/dist/bin/exe-status.js +21 -20
- package/dist/bin/exe-support.js +4 -4
- package/dist/bin/exe-team.js +4 -4
- package/dist/bin/git-sweep.js +21 -20
- package/dist/bin/graph-backfill.js +6 -6
- package/dist/bin/graph-export.js +8 -8
- package/dist/bin/import-history.js +8 -8
- package/dist/bin/install.js +87 -86
- package/dist/bin/intercom-check.js +4 -4
- package/dist/bin/mcp-sessions.js +2 -2
- package/dist/bin/orchestration-metrics.js +5 -5
- package/dist/bin/postgres-agentic-reflection-backfill.js +4 -4
- package/dist/bin/postgres-agentic-semantic-backfill.js +3 -3
- package/dist/bin/pre-publish.js +1 -1
- package/dist/bin/reconcile-backlog.js +2 -2
- package/dist/bin/registry-proxy.js +1 -1
- package/dist/bin/scan-tasks.js +20 -19
- package/dist/bin/setup.js +3 -3
- package/dist/bin/shard-migrate.js +6 -6
- package/dist/bin/stack-update.js +5 -5
- package/dist/bin/vps-health-gate.js +1 -1
- package/dist/{boot-generation-BL2ISK4U.js → boot-generation-CFA5NKSK.js} +4 -4
- package/dist/{boot-review-sections-DBMQJT5N.js → boot-review-sections-FX2FYZJQ.js} +19 -18
- package/dist/{branch-hygiene-TZWK6QCF.js → branch-hygiene-PILXQQDF.js} +1 -1
- package/dist/{branding-DVXBGVDH.js → branding-ZSC6YN63.js} +2 -2
- package/dist/{capability-cards-DN5UIKVN.js → capability-cards-O27UB3J5.js} +3 -3
- package/dist/{capacity-monitor-ZG5GGFR2.js → capacity-monitor-5DVZY3SM.js} +21 -20
- package/dist/{catchup-brief-D6HH6DWS.js → catchup-brief-3GYI6AKV.js} +23 -22
- package/dist/{chunk-YTCFACP4.js → chunk-25ORSHR7.js} +137 -137
- package/dist/{chunk-PDWS3E22.js → chunk-2F7WGH5K.js} +6 -6
- package/dist/{chunk-JLZ4RYSD.js → chunk-2VZMLKNS.js} +2 -2
- package/dist/{chunk-CNVBKDEY.js → chunk-2YPCD2UH.js} +12 -12
- package/dist/{chunk-HAF2DJYV.js → chunk-34RULPS2.js} +3 -3
- package/dist/{chunk-JPUZPAAF.js → chunk-3MLSM77R.js} +3 -3
- package/dist/{chunk-JTBIS4R5.js → chunk-3OO34BOT.js} +1 -1
- package/dist/{chunk-L4A5DL6Z.js → chunk-3OR54BBE.js} +3 -3
- package/dist/{chunk-USSB56WK.js → chunk-3PFP7GV2.js} +1 -1
- package/dist/{chunk-TLT7NZCW.js → chunk-4AA2HRIM.js} +3 -3
- package/dist/{chunk-PQIDGXSG.js → chunk-4E3SZEEI.js} +2 -2
- package/dist/chunk-4EI5AHHR.js +37 -0
- package/dist/{chunk-6XWTQUO4.js → chunk-4MLSFZLY.js} +19 -8
- package/dist/{chunk-AJYCFKJR.js → chunk-4UIYLTA3.js} +1 -1
- package/dist/{chunk-I26FWCSP.js → chunk-4VUAG6DN.js} +1 -1
- package/dist/{chunk-V3EEVY4L.js → chunk-54O2FWRM.js} +1 -1
- package/dist/{chunk-TTCUG2CF.js → chunk-5DSVWSL5.js} +2 -2
- package/dist/{chunk-4J4PMPXZ.js → chunk-5ERB3AWT.js} +1 -1
- package/dist/{chunk-SQKXKV2Y.js → chunk-5GDTZOVS.js} +2 -2
- package/dist/{chunk-BUCXNV32.js → chunk-5HQHHQUR.js} +1 -1
- package/dist/chunk-5MLYU6I2.js +76 -0
- package/dist/{chunk-X2Q5NLUL.js → chunk-5VV2YMMB.js} +1 -1
- package/dist/{chunk-XZXBB3TN.js → chunk-62MYX7G4.js} +2 -2
- package/dist/{chunk-X33NYQYJ.js → chunk-6CYVBLZW.js} +2 -2
- package/dist/{chunk-GJ26DULE.js → chunk-6IK2ME5X.js} +2 -2
- package/dist/{chunk-4ZCD2UWW.js → chunk-6JMRRJD6.js} +3 -3
- package/dist/{chunk-EQHQF5IM.js → chunk-6L6SXVTP.js} +32 -16
- package/dist/{chunk-MR6LHP4F.js → chunk-6ST7ZWTV.js} +1 -1
- package/dist/{chunk-WMESXBJM.js → chunk-6TJLBXR5.js} +30 -5
- package/dist/{chunk-PPCDBE6Z.js → chunk-6XKIMGHA.js} +1 -1
- package/dist/{chunk-5ERDIOV3.js → chunk-7M5AWCR3.js} +2 -2
- package/dist/{chunk-MKYFAKDW.js → chunk-7MESPFOK.js} +4 -4
- package/dist/{chunk-RACAOE2Z.js → chunk-7S3A4TOL.js} +15 -15
- package/dist/{chunk-LU2FALL6.js → chunk-7UNIYLGV.js} +28 -4
- package/dist/{chunk-N7QJKQMX.js → chunk-AGHKOBA6.js} +10 -10
- package/dist/{chunk-OZEBAGKR.js → chunk-B4LOFZLB.js} +10 -10
- package/dist/{chunk-GDIJE6D7.js → chunk-BUI2CHLQ.js} +1 -1
- package/dist/{chunk-JMYHW3AL.js → chunk-BVURFD5R.js} +2 -2
- package/dist/{chunk-7V4JADD6.js → chunk-BXSC34Y2.js} +2 -2
- package/dist/{chunk-YCANDMI2.js → chunk-BZA4N43B.js} +1 -1
- package/dist/{chunk-QDGZJ653.js → chunk-C24F7SOO.js} +4 -4
- package/dist/{chunk-5TY4FPH6.js → chunk-CBD64QQG.js} +1 -1
- package/dist/{chunk-QRYVCDWS.js → chunk-DHW4DIGK.js} +2 -2
- package/dist/{chunk-2KZNGDSW.js → chunk-DLGEQJ6E.js} +1 -1
- package/dist/{chunk-GBTTBXAF.js → chunk-DT6LX4SV.js} +4 -4
- package/dist/{chunk-R2NN3JKH.js → chunk-E4FGXPHB.js} +5 -5
- package/dist/{chunk-UEA3LXOB.js → chunk-FCKYJSVY.js} +1 -1
- package/dist/{chunk-FPFPLPUY.js → chunk-FQEBVYVE.js} +5 -5
- package/dist/{chunk-AOHXREB7.js → chunk-GD7FA6IP.js} +70 -66
- package/dist/{chunk-6WQ3NNCE.js → chunk-GGQMX4IU.js} +3 -3
- package/dist/{chunk-H6BV5TKD.js → chunk-H6BVQIAF.js} +6 -6
- package/dist/{chunk-CWXVH7WV.js → chunk-H6WLWIPN.js} +1 -1
- package/dist/{chunk-UP75Z5X7.js → chunk-HDL7CXQ4.js} +73 -67
- package/dist/{chunk-RHWZUUS4.js → chunk-HENPNYGY.js} +11 -11
- package/dist/{chunk-C5QAPURN.js → chunk-HRBTW62M.js} +1 -1
- package/dist/{chunk-OLMQ4UOF.js → chunk-IKAGAKAI.js} +209 -20
- package/dist/{chunk-UUEKJDK6.js → chunk-IPB5QM4S.js} +2 -2
- package/dist/{chunk-NXUSDL37.js → chunk-IRUWKANS.js} +1 -1
- package/dist/{chunk-EUS4QUKP.js → chunk-JBMIIBPS.js} +1 -1
- package/dist/{chunk-VPZHJCKW.js → chunk-JLLJ3ER3.js} +2 -2
- package/dist/{chunk-F27XXN6C.js → chunk-JMMF3PPQ.js} +1 -1
- package/dist/{chunk-UNXQBELK.js → chunk-K2G3VDCV.js} +1 -1
- package/dist/{chunk-3SW4OEHB.js → chunk-KIUNO3JP.js} +1 -1
- package/dist/{chunk-KW2SD2FL.js → chunk-KRRZNASS.js} +2 -2
- package/dist/{chunk-HV4KESRY.js → chunk-LSAH73QD.js} +1 -1
- package/dist/chunk-LUQ57SRM.js +127 -0
- package/dist/{sweep-budget-WB2FKPYN.js → chunk-M6DZYWZH.js} +8 -3
- package/dist/{chunk-JGIPOUIK.js → chunk-MNIA3IOU.js} +3 -3
- package/dist/{chunk-XHK3FS3W.js → chunk-MTFSD6DH.js} +1 -1
- package/dist/{chunk-2ZYO73KO.js → chunk-MVWFY7IO.js} +1 -1
- package/dist/{chunk-ASAFVDVR.js → chunk-NDJASAXP.js} +1 -1
- package/dist/{chunk-K7KFGDWF.js → chunk-NG2ABIDX.js} +1 -1
- package/dist/{chunk-O5V57XYE.js → chunk-NPFU2NPG.js} +1 -1
- package/dist/{chunk-UUQBZPJJ.js → chunk-NUVP4CCD.js} +1 -1
- package/dist/{chunk-NX5INHHG.js → chunk-O5VMAZZH.js} +1 -1
- package/dist/{chunk-WZHZCDDO.js → chunk-OL4JFQ2T.js} +1 -0
- package/dist/{chunk-Z6RSN7KS.js → chunk-OZUQJZYO.js} +4 -4
- package/dist/{chunk-P5HIWY2E.js → chunk-PAYVSTF2.js} +1 -1
- package/dist/chunk-PWRC5XZO.js +161 -0
- package/dist/{chunk-MZM6EJCU.js → chunk-PXPBF2JZ.js} +4 -4
- package/dist/{chunk-L2R3LN2P.js → chunk-QFBT7CJH.js} +1 -1
- package/dist/{chunk-2WAVZ5UJ.js → chunk-QTKDGDR5.js} +1 -1
- package/dist/{chunk-G4RGKBCA.js → chunk-R3QDXB55.js} +13 -3
- package/dist/{chunk-QQ4E2RYW.js → chunk-RZZ66LSS.js} +12 -12
- package/dist/{chunk-HJ447YER.js → chunk-S3FIQCSM.js} +14 -6
- package/dist/{chunk-G5T6KDG4.js → chunk-SA7GZU3U.js} +1 -1
- package/dist/{chunk-7CTRGNLW.js → chunk-SIGS6D5R.js} +2 -2
- package/dist/{chunk-VRAQTFD6.js → chunk-SJN5ZEDI.js} +1 -1
- package/dist/{chunk-QOO5RW3K.js → chunk-SLK3DPYU.js} +3 -3
- package/dist/{chunk-F5O7V7UK.js → chunk-SXKMH4JX.js} +1 -1
- package/dist/{chunk-6CH3TPHR.js → chunk-T3EJIMDX.js} +3 -3
- package/dist/{chunk-KWZMQACA.js → chunk-TI2XFHRQ.js} +3 -3
- package/dist/{chunk-OTF44GXL.js → chunk-TR73G4GH.js} +2 -2
- package/dist/{chunk-4CMVFVFC.js → chunk-UC37QPSR.js} +4 -4
- package/dist/{chunk-KGWRTRKC.js → chunk-UZ2LYBY5.js} +1 -1
- package/dist/{chunk-EV46QTD3.js → chunk-V7AGCRLI.js} +1 -1
- package/dist/{chunk-H7I47RS5.js → chunk-VIIHBYIP.js} +115 -3
- package/dist/{chunk-HA5R6USD.js → chunk-WYRZEMRU.js} +1 -1
- package/dist/{chunk-CE7F6RHG.js → chunk-WZTWA4G4.js} +11 -11
- package/dist/{chunk-IBYL4DHM.js → chunk-X4Z5DPOC.js} +22 -2
- package/dist/{chunk-4VSV5P4D.js → chunk-XZTTLTPG.js} +4 -4
- package/dist/{chunk-S7QUM2UK.js → chunk-YCPZTX7V.js} +2 -2
- package/dist/{chunk-GG5NDQNN.js → chunk-YYCKKORY.js} +13 -20
- package/dist/{chunk-NN2B2QKU.js → chunk-Z5VL7YBR.js} +1 -1
- package/dist/{chunk-QYZJHTNE.js → chunk-ZCLVPTZU.js} +9 -9
- package/dist/{chunk-RAXVPNMR.js → chunk-ZUBUP66T.js} +1 -1
- package/dist/{chunk-VSRPS3J7.js → chunk-ZYLKX3KB.js} +13 -13
- package/dist/{cleanup-graph-garbage-XWUFAMFO.js → cleanup-graph-garbage-DDVPSPI4.js} +5 -5
- package/dist/{co-activation-ZCHPLLP6.js → co-activation-HLCAD44L.js} +3 -3
- package/dist/{co-occurrence-KG3LKALN.js → co-occurrence-I5U2PCPX.js} +3 -3
- package/dist/{code-context-index-WSOJQ72R.js → code-context-index-FSYP5VF2.js} +4 -4
- package/dist/{conversation-wiki-populator-WQN3IUU6.js → conversation-wiki-populator-YVT5AYSK.js} +1 -1
- package/dist/{crdt-sync-4PFGPZXV.js → crdt-sync-EMV5EZ4J.js} +1 -1
- package/dist/{crm-webhook-II7Z45Q6.js → crm-webhook-XJ6UOBHR.js} +2 -2
- package/dist/{cto-delegation-gate-JWWOJPNC.js → cto-delegation-gate-5NNZWP2M.js} +19 -18
- package/dist/{daemon-auth-3FEAHFWC.js → daemon-auth-TIE7HSWF.js} +2 -2
- package/dist/{daemon-orchestration-FX4XZDR5.js → daemon-orchestration-GGSRCXR3.js} +24 -23
- package/dist/{daemon-ready-4JTSFKAY.js → daemon-ready-A7R6XZRF.js} +1 -1
- package/dist/{daemon-restart-circuit-breaker-PEGEIP6H.js → daemon-restart-circuit-breaker-5V6B6NLS.js} +1 -1
- package/dist/{db-restore-events-MQ2DBGEQ.js → db-restore-events-GQGQSYHV.js} +1 -1
- package/dist/{doc-graph-extractor-F6ODFIID.js → doc-graph-extractor-3OXUTEKS.js} +3 -3
- package/dist/{documents-23WX2FPQ.js → documents-M7UI6SZ6.js} +9 -9
- package/dist/{dreaming-NWD22UQ5.js → dreaming-CYQWRJA5.js} +20 -19
- package/dist/{exe-drift-CW72FBGE.js → exe-drift-DPDRG3OM.js} +4 -4
- package/dist/{exe-export-AUJ7CV7G.js → exe-export-SZVIC6KI.js} +8 -8
- package/dist/{exe-import-JX4I52VE.js → exe-import-Q6TCHQ6P.js} +8 -8
- package/dist/{exe-key-2N6LY2BU.js → exe-key-EVMVLB3Y.js} +86 -85
- package/dist/{exe-org-X4CSNCKS.js → exe-org-3Y3RWGIU.js} +2 -2
- package/dist/{exe-snapshot-XZ7FVCYZ.js → exe-snapshot-UX5CFSDX.js} +23 -22
- package/dist/{fast-db-init-4CWHSOOR.js → fast-db-init-O62SMAQL.js} +1 -1
- package/dist/{founder-context-7L3CFPYN.js → founder-context-FCVTBCWI.js} +3 -3
- package/dist/gateway/index.js +18 -18
- package/dist/{git-staleness-CI2R4QOJ.js → git-staleness-AFBXWNTZ.js} +3 -3
- package/dist/{global-procedures-XQX3LUH6.js → global-procedures-BDREAJSZ.js} +5 -5
- package/dist/{graph-auto-extract-OURWMGBS.js → graph-auto-extract-JJ5OGNGJ.js} +3 -3
- package/dist/{hook-integrity-XY47IM7G.js → hook-integrity-IKKZ6HBC.js} +1 -1
- package/dist/{hook-prefetch-PHRRKY4C.js → hook-prefetch-HLCCAOSZ.js} +20 -19
- package/dist/hooks/bug-report-worker.js +24 -23
- package/dist/hooks/codex-stop-task-finalizer.js +24 -23
- package/dist/hooks/commit-complete.js +23 -22
- package/dist/hooks/error-recall.js +12 -12
- package/dist/hooks/exe-heartbeat-hook.js +5 -5
- package/dist/hooks/ingest-worker.js +7 -7
- package/dist/hooks/ingest.js +19 -19
- package/dist/hooks/instructions-loaded.js +6 -6
- package/dist/hooks/manifest.json +20 -20
- package/dist/hooks/notification.js +6 -6
- package/dist/hooks/post-compact.js +22 -21
- package/dist/hooks/post-tool-combined.js +23 -10
- package/dist/hooks/pre-compact.js +23 -22
- package/dist/hooks/pre-tool-use.js +28 -27
- package/dist/hooks/prompt-submit.js +53 -40
- package/dist/hooks/session-end.js +28 -27
- package/dist/hooks/session-start.js +17 -17
- package/dist/hooks/stop.js +29 -28
- package/dist/hooks/subagent-stop.js +22 -21
- package/dist/hooks/summary-worker.js +28 -27
- package/dist/index.js +33 -32
- package/dist/{installer-L7EVH5U5.js → installer-BZ3QV7DJ.js} +7 -7
- package/dist/{installer-JND3RJ6Q.js → installer-HADQQZIU.js} +7 -7
- package/dist/{installer-G3JAO3NT.js → installer-OJ7XKSAR.js} +7 -7
- package/dist/{intercom-queue-ZFEQALR3.js → intercom-queue-NFOLOBTT.js} +19 -18
- package/dist/{key-backup-status-LOSMVATJ.js → key-backup-status-TTO2UUYP.js} +1 -1
- package/dist/lib/agent-config.js +2 -2
- package/dist/lib/cloud-sync.js +15 -15
- package/dist/lib/config.js +1 -1
- package/dist/lib/consolidation.js +6 -6
- package/dist/lib/database.js +3 -3
- package/dist/{db-backup-W2QFSYQC.js → lib/db-backup.js} +16 -4
- package/dist/lib/db-checkpoint-worker.js +57 -0
- package/dist/lib/db-daemon-client.js +4 -4
- package/dist/lib/db-write-worker-client.js +17 -0
- package/dist/lib/db-write-worker.js +216 -0
- package/dist/lib/db.js +3 -3
- package/dist/lib/device-registry.js +2 -2
- package/dist/lib/embed-worker.js +1 -1
- package/dist/lib/embedder.js +4 -4
- package/dist/lib/employee-templates.js +6 -6
- package/dist/lib/employees.js +3 -3
- package/dist/lib/exe-daemon-client.js +3 -3
- package/dist/lib/exe-daemon.js +781 -276
- package/dist/lib/hybrid-search.js +6 -6
- package/dist/lib/identity.js +3 -3
- package/dist/lib/license.js +3 -3
- package/dist/lib/messaging.js +20 -19
- package/dist/lib/registry-proxy.js +1 -1
- package/dist/lib/reminders.js +4 -4
- package/dist/lib/schedules.js +6 -6
- package/dist/lib/session-registry.js +5 -5
- package/dist/lib/skill-learning.js +7 -7
- package/dist/lib/status-brief.js +3 -3
- package/dist/lib/store.js +5 -5
- package/dist/lib/task-router.js +4 -4
- package/dist/lib/tasks.js +21 -20
- package/dist/lib/tmux-routing.js +19 -18
- package/dist/lib/token-spend.js +4 -4
- package/dist/{license-gate-QTRQHV4F.js → license-gate-3KPSNYVA.js} +4 -4
- package/dist/{license-sync-N3UJFWAW.js → license-sync-CQ42HDBA.js} +3 -3
- package/dist/mcp/register-tools.js +83 -82
- package/dist/mcp/server.js +85 -84
- package/dist/mcp/tools/complete-reminder.js +5 -5
- package/dist/mcp/tools/create-reminder.js +5 -5
- package/dist/mcp/tools/create-task.js +23 -22
- package/dist/mcp/tools/deactivate-behavior.js +8 -8
- package/dist/mcp/tools/list-reminders.js +5 -5
- package/dist/mcp/tools/list-tasks.js +23 -22
- package/dist/mcp/tools/send-message.js +22 -21
- package/dist/mcp/tools/update-task.js +22 -21
- package/dist/{mcp-http-config-BDL36JZ3.js → mcp-http-config-BHAM376G.js} +8 -6
- package/dist/{mcp-port-config-6HYY6J7K.js → mcp-port-config-PA3W3BJK.js} +7 -1
- package/dist/{mcp-session-identity-T7H2EKFQ.js → mcp-session-identity-S7GSVRR6.js} +19 -18
- package/dist/mcp-session-persist-PS7BIG44.js +62 -0
- package/dist/mcp-stale-flag-ZM23XRSJ.js +11 -0
- package/dist/{memory-cards-ZRDW7QBX.js → memory-cards-47NYPFC3.js} +5 -5
- package/dist/{memory-graph-extractor-QLXDMHRS.js → memory-graph-extractor-IH7YBZ6U.js} +4 -4
- package/dist/{memory-poisoning-defense-HJTXYCWH.js → memory-poisoning-defense-MZQFCQ2G.js} +3 -3
- package/dist/{memory-pressure-watchdog-HN5X7AVN.js → memory-pressure-watchdog-PSVJ5BCF.js} +20 -19
- package/dist/{memory-queue-2UOOF27L.js → memory-queue-ZI7DX44D.js} +2 -2
- package/dist/{memory-queue-client-O5U6F6XP.js → memory-queue-client-6IPZTWZA.js} +5 -5
- package/dist/{memory-reflection-WVNFBJAA.js → memory-reflection-3VPYJS2G.js} +3 -3
- package/dist/{monitor-grants-E3ELDEWD.js → monitor-grants-OXKZ75TH.js} +2 -2
- package/dist/{notification-ledger-SZEPGJQ7.js → notification-ledger-A6MYLQAN.js} +20 -19
- package/dist/{notifications-4UT53CDG.js → notifications-6XCSUTJW.js} +19 -18
- package/dist/{orchestration-events-WV4NWKZH.js → orchestration-events-5XDNVNR2.js} +4 -4
- package/dist/{orchestration-phase-AWBXPO52.js → orchestration-phase-6DJUSFMV.js} +2 -2
- package/dist/{orchestrator-UAC3RW2T.js → orchestrator-2RQBNMZL.js} +21 -20
- package/dist/{pipeline-router-LM53NMWJ.js → pipeline-router-N2LDNFJ5.js} +4 -4
- package/dist/{plan-limits-2FEY2GOS.js → plan-limits-7BUMNQOI.js} +6 -6
- package/dist/{platform-procedures-X5DFJFV7.js → platform-procedures-VDW2R65H.js} +1 -1
- package/dist/{project-boot-4NUH5FRU.js → project-boot-RXCHF3S7.js} +1 -1
- package/dist/{projection-worker-FZ7YSN3G.js → projection-worker-CKC2E22U.js} +4 -4
- package/dist/{prospective-memory-6D2ASWM3.js → prospective-memory-Q7ZUCAS4.js} +3 -3
- package/dist/{push-notifications-U6FIBQRW.js → push-notifications-VCSZYVD5.js} +2 -2
- package/dist/{reranker-GYYRPANK.js → reranker-L3GLRUDY.js} +2 -2
- package/dist/{retrieval-health-4Z242P3B.js → retrieval-health-DPLY6O6P.js} +1 -1
- package/dist/{review-polling-HXAFJZDA.js → review-polling-DLPMK3QW.js} +20 -19
- package/dist/runtime/index.js +31 -30
- package/dist/{session-events-O3BV56ZX.js → session-events-N5VRC6IT.js} +20 -19
- package/dist/{session-kill-telemetry-AELE4JDK.js → session-kill-telemetry-76ZVQ525.js} +20 -19
- package/dist/{session-scope-5EAPUT45.js → session-scope-B3BEHGHO.js} +19 -18
- package/dist/{setup-wizard-NB6R4QVS.js → setup-wizard-5SIRITVN.js} +3 -3
- package/dist/{shard-manager-35PWFR3B.js → shard-manager-OETALPDW.js} +2 -2
- package/dist/{skill-refinement-DVSYXBBP.js → skill-refinement-ACXLAK2G.js} +4 -4
- package/dist/{stack-update-ATCJFOEK.js → stack-update-YVFP65NY.js} +4 -4
- package/dist/{steward-gate-3GQ5XKMJ.js → steward-gate-2M66UU6A.js} +4 -4
- package/dist/{support-inbox-4L62P4EP.js → support-inbox-5W2GMJGV.js} +4 -4
- package/dist/sweep-budget-LQYBMDTK.js +15 -0
- package/dist/{task-enforcement-IPIZX2MM.js → task-enforcement-C7MMJTKX.js} +20 -19
- package/dist/{task-scope-FOIW25HR.js → task-scope-DK666AKV.js} +19 -18
- package/dist/{tasks-crud-HBDKE6C5.js → tasks-crud-DFPIAAEC.js} +21 -18
- package/dist/{tasks-notify-G2U2U2YA.js → tasks-notify-4R5YIPZN.js} +20 -19
- package/dist/{tasks-review-27SFX5XN.js → tasks-review-GOYSZEZA.js} +19 -18
- package/dist/{telemetry-upload-ZOXHRWR5.js → telemetry-upload-Y5F6WYLD.js} +8 -8
- package/dist/{token-budget-5Y4YPDO3.js → token-budget-BAM5QDFV.js} +4 -4
- package/dist/{tool-capability-index-VYF5GNJ2.js → tool-capability-index-QOFFCWDS.js} +1 -1
- package/dist/{tool-telemetry-KBXSBDTK.js → tool-telemetry-4MF2HIWR.js} +1 -1
- package/dist/tui/App.js +33 -32
- package/dist/{tui-data-NLFMBIQI.js → tui-data-WMYZNTBR.js} +19 -18
- package/dist/{update-support-UVUSZG7R.js → update-support-44SGQUA4.js} +12 -12
- package/dist/{worker-gate-3KUBAU32.js → worker-gate-7OK7ZRJL.js} +2 -2
- package/dist/{workflow-engine-YITHXZR5.js → workflow-engine-EDZGGHAI.js} +2 -2
- package/dist/{worktree-LL62PLQB.js → worktree-VDCY44ZP.js} +5 -5
- package/dist/{worktree-sweep-WTK3MTKH.js → worktree-sweep-VSL7TRQK.js} +6 -6
- package/package.json +3 -2
- package/release-notes.json +12 -12
- package/dist/chunk-GIBYNT6W.js +0 -23
- /package/dist/{chunk-NBZL5CGA.js → chunk-735SUAT4.js} +0 -0
- /package/dist/{chunk-MGGOSFCR.js → chunk-CIG7FSD5.js} +0 -0
- /package/dist/{chunk-JRM4TAGS.js → chunk-DFCSGPNZ.js} +0 -0
- /package/dist/{chunk-QIFYLIUF.js → chunk-EBTWNNAS.js} +0 -0
- /package/dist/{chunk-KP3U5QGJ.js → chunk-L5GFREAH.js} +0 -0
- /package/dist/{chunk-PWUFMX75.js → chunk-UU4FHMON.js} +0 -0
- /package/dist/{core-memory-GAC6EWOQ.js → core-memory-VOBMIFRX.js} +0 -0
- /package/dist/{entity-boost-NT6UO2Z3.js → entity-boost-N4NAK4WA.js} +0 -0
- /package/dist/{message-queue-client-4EOQRUXW.js → message-queue-client-WMIO5FL5.js} +0 -0
- /package/dist/{oauth-server-67YBDP32.js → oauth-server-HPQCBLZQ.js} +0 -0
- /package/dist/{webhook-pipe-LEXMUQ5B.js → webhook-pipe-HH7XXXYC.js} +0 -0
- /package/dist/{wiki-acl-74BLWG6J.js → wiki-acl-NEM3L4LK.js} +0 -0
- /package/dist/{wiki-client-EAN7F5LV.js → wiki-client-WREIYJLY.js} +0 -0
package/dist/lib/exe-daemon.js
CHANGED
|
@@ -4,10 +4,20 @@ import {
|
|
|
4
4
|
restartBootsInWindow,
|
|
5
5
|
restartBreakerAlertPath,
|
|
6
6
|
writeDaemonExitBreadcrumb
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-S3FIQCSM.js";
|
|
8
8
|
import {
|
|
9
9
|
pushNotifyAsync
|
|
10
|
-
} from "../chunk-
|
|
10
|
+
} from "../chunk-KIUNO3JP.js";
|
|
11
|
+
import {
|
|
12
|
+
disposeDbWriteWorker,
|
|
13
|
+
isDbWriteWorkerReady,
|
|
14
|
+
isWriteWorkerEnabled,
|
|
15
|
+
spawnDbWriteWorker,
|
|
16
|
+
writeMemoryInWorker
|
|
17
|
+
} from "../chunk-LUQ57SRM.js";
|
|
18
|
+
import {
|
|
19
|
+
shouldScheduleDaemonRestartHandoff
|
|
20
|
+
} from "../chunk-PWRC5XZO.js";
|
|
11
21
|
import {
|
|
12
22
|
clearDaemonReady,
|
|
13
23
|
eventLoopHeartbeatPath,
|
|
@@ -17,7 +27,7 @@ import {
|
|
|
17
27
|
getMcpToolFamily,
|
|
18
28
|
inferMcpRuntime,
|
|
19
29
|
recordMcpHttpEvent
|
|
20
|
-
} from "../chunk-
|
|
30
|
+
} from "../chunk-ZUBUP66T.js";
|
|
21
31
|
import {
|
|
22
32
|
deserializeArgs,
|
|
23
33
|
serializeResultSet
|
|
@@ -29,11 +39,14 @@ import {
|
|
|
29
39
|
findScopedDuplicate,
|
|
30
40
|
governMemoryRecord,
|
|
31
41
|
schedulePostWriteMemoryHygiene
|
|
32
|
-
} from "../chunk-
|
|
42
|
+
} from "../chunk-4MLSFZLY.js";
|
|
33
43
|
import "../chunk-4QCFFW2H.js";
|
|
34
44
|
import {
|
|
35
45
|
BUSY_PATTERN
|
|
36
46
|
} from "../chunk-GWDSB25T.js";
|
|
47
|
+
import {
|
|
48
|
+
sweepPauseTotalMs
|
|
49
|
+
} from "../chunk-M6DZYWZH.js";
|
|
37
50
|
import {
|
|
38
51
|
attributeSignalSource,
|
|
39
52
|
consumeRestartIntentDetail,
|
|
@@ -45,7 +58,7 @@ import {
|
|
|
45
58
|
ensureDaemonToken,
|
|
46
59
|
reconcileSessionAgentIdentity,
|
|
47
60
|
shouldEnforceSessionIdentity
|
|
48
|
-
} from "../chunk-
|
|
61
|
+
} from "../chunk-5VV2YMMB.js";
|
|
49
62
|
import {
|
|
50
63
|
DAEMON_RSS_RESTART_DEBOUNCE,
|
|
51
64
|
DAEMON_RSS_STARTUP_GRACE_MS,
|
|
@@ -82,7 +95,7 @@ import {
|
|
|
82
95
|
EXE_AI_DIR,
|
|
83
96
|
MODELS_DIR,
|
|
84
97
|
resolveEmbedModelFile
|
|
85
|
-
} from "../chunk-
|
|
98
|
+
} from "../chunk-OL4JFQ2T.js";
|
|
86
99
|
import "../chunk-BYTDMAGB.js";
|
|
87
100
|
import "../chunk-MLKGABMK.js";
|
|
88
101
|
|
|
@@ -92,7 +105,7 @@ import net from "net";
|
|
|
92
105
|
import v8 from "v8";
|
|
93
106
|
import { createServer as createHttpServer, request as httpRequest } from "http";
|
|
94
107
|
import { randomUUID, timingSafeEqual } from "crypto";
|
|
95
|
-
import { writeFileSync as
|
|
108
|
+
import { writeFileSync as writeFileSync4, unlinkSync as unlinkSync3, mkdirSync as mkdirSync3, existsSync as existsSync5, readFileSync as readFileSync5, chmodSync, readdirSync, renameSync, statSync as statSync2 } from "fs";
|
|
96
109
|
import { writeFile } from "fs/promises";
|
|
97
110
|
import { execSync as execSyncNode, execFile as execFileNode } from "child_process";
|
|
98
111
|
import { promisify } from "util";
|
|
@@ -322,6 +335,11 @@ function initMetrics() {
|
|
|
322
335
|
});
|
|
323
336
|
}
|
|
324
337
|
|
|
338
|
+
// src/lib/daemon-timer-warnings.ts
|
|
339
|
+
function shouldWarnSlowTimer(durationMs, slept, thresholdMs) {
|
|
340
|
+
return !slept && durationMs >= thresholdMs;
|
|
341
|
+
}
|
|
342
|
+
|
|
325
343
|
// src/lib/mcp-init-grace.ts
|
|
326
344
|
var defaultSleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
327
345
|
async function awaitPendingMcpInit(ownerKey, requestSessionId, deps, transientMatch) {
|
|
@@ -376,6 +394,176 @@ async function awaitPendingMcpInit(ownerKey, requestSessionId, deps, transientMa
|
|
|
376
394
|
return null;
|
|
377
395
|
}
|
|
378
396
|
|
|
397
|
+
// src/lib/daemon-coverage-gap.ts
|
|
398
|
+
import { closeSync, existsSync as existsSync2, mkdirSync, openSync, readFileSync as readFileSync2, readSync, statSync, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
|
|
399
|
+
import { homedir } from "os";
|
|
400
|
+
import { dirname, join } from "path";
|
|
401
|
+
var HEALTH_LOG_TAIL_BYTES = 512 * 1024;
|
|
402
|
+
var DEFAULT_COVERAGE_GAP_THRESHOLD_MS = 30 * 60 * 1e3;
|
|
403
|
+
var DEFAULT_COVERAGE_GAP_ALERT_THRESHOLD_MS = 60 * 60 * 1e3;
|
|
404
|
+
function resolveCoverageGapAlertThresholdMs() {
|
|
405
|
+
const raw = Number(process.env.EXE_HEARTBEAT_GAP_ALERT_MS);
|
|
406
|
+
return Number.isFinite(raw) && raw > 0 ? Math.floor(raw) : DEFAULT_COVERAGE_GAP_ALERT_THRESHOLD_MS;
|
|
407
|
+
}
|
|
408
|
+
var COVERAGE_GAP_ALERT_THRESHOLD_MS = resolveCoverageGapAlertThresholdMs();
|
|
409
|
+
function shouldAlertCoverageGap(a, alertThresholdMs) {
|
|
410
|
+
return Number.isFinite(a.gapMs) && a.gapMs > 0 && a.gapMs > alertThresholdMs;
|
|
411
|
+
}
|
|
412
|
+
function shouldWriteCoverageGapAlert(bootClass, a, alertThresholdMs) {
|
|
413
|
+
return bootClass === "coverage_gap" && a !== void 0 && shouldAlertCoverageGap(a, alertThresholdMs);
|
|
414
|
+
}
|
|
415
|
+
var COVERAGE_GAP_ALERT_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
416
|
+
function clearCoverageGapAlertIfExpired(maxAgeMs = COVERAGE_GAP_ALERT_MAX_AGE_MS) {
|
|
417
|
+
try {
|
|
418
|
+
const alert = readCoverageGapAlert();
|
|
419
|
+
if (!alert) return;
|
|
420
|
+
const detectedAt = typeof alert.detectedAt === "string" ? Date.parse(alert.detectedAt) : NaN;
|
|
421
|
+
if (!Number.isFinite(detectedAt) || Date.now() - detectedAt > maxAgeMs) {
|
|
422
|
+
clearCoverageGapAlert();
|
|
423
|
+
}
|
|
424
|
+
} catch {
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
function coverageGapAlertPath() {
|
|
428
|
+
const home = process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? join(homedir(), ".exe-os");
|
|
429
|
+
return join(home, "daemon-coverage-gap.ALERT.json");
|
|
430
|
+
}
|
|
431
|
+
function isoOrNull(ts) {
|
|
432
|
+
return ts !== null && Number.isFinite(ts) ? new Date(ts).toISOString() : null;
|
|
433
|
+
}
|
|
434
|
+
function writeCoverageGapAlert(a, ctx) {
|
|
435
|
+
try {
|
|
436
|
+
const hours = a.gapMs / (60 * 60 * 1e3);
|
|
437
|
+
const lastHeartbeatAt = isoOrNull(ctx.lastHeartbeatTs);
|
|
438
|
+
const hostRebootAt = a.rebootSpansGap ? isoOrNull(ctx.hostBootTs) : null;
|
|
439
|
+
const rebootClause = a.rebootSpansGap && hostRebootAt ? `, host rebooted ${hostRebootAt}` : ", no host reboot was detected";
|
|
440
|
+
const payload = {
|
|
441
|
+
detectedAt: new Date(ctx.nowMs).toISOString(),
|
|
442
|
+
gapMs: a.gapMs,
|
|
443
|
+
gapHours: Number(hours.toFixed(1)),
|
|
444
|
+
lastHeartbeatAt,
|
|
445
|
+
rebootSpansGap: a.rebootSpansGap,
|
|
446
|
+
reason: `Daemon was down ~${hours.toFixed(1)}h: last heartbeat ${lastHeartbeatAt ?? "unknown"}${rebootClause}, daemon only starts at GUI login (LaunchAgent) - this was a coverage gap, not a crash.`,
|
|
447
|
+
limitation: "Root cause: the daemon is a GUI LaunchAgent and does not run pre-login after reboot."
|
|
448
|
+
};
|
|
449
|
+
if (a.rebootSpansGap) payload.hostRebootAt = hostRebootAt;
|
|
450
|
+
const p = coverageGapAlertPath();
|
|
451
|
+
mkdirSync(dirname(p), { recursive: true });
|
|
452
|
+
writeFileSync2(p, JSON.stringify(payload, null, 2), { mode: 384 });
|
|
453
|
+
} catch {
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
function clearCoverageGapAlert() {
|
|
457
|
+
try {
|
|
458
|
+
const p = coverageGapAlertPath();
|
|
459
|
+
if (existsSync2(p)) unlinkSync(p);
|
|
460
|
+
} catch {
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
function readCoverageGapAlert() {
|
|
464
|
+
try {
|
|
465
|
+
const p = coverageGapAlertPath();
|
|
466
|
+
if (!existsSync2(p)) return null;
|
|
467
|
+
return JSON.parse(readFileSync2(p, "utf8"));
|
|
468
|
+
} catch {
|
|
469
|
+
return null;
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
function hostBootTimeMs(nowMs, uptimeSec) {
|
|
473
|
+
return nowMs - uptimeSec * 1e3;
|
|
474
|
+
}
|
|
475
|
+
function readTail(p, maxBytes = HEALTH_LOG_TAIL_BYTES) {
|
|
476
|
+
let fd = null;
|
|
477
|
+
try {
|
|
478
|
+
const st = statSync(p);
|
|
479
|
+
const size = Math.max(0, Math.floor(st.size));
|
|
480
|
+
const len = Math.min(size, maxBytes);
|
|
481
|
+
const start = Math.max(0, size - len);
|
|
482
|
+
const buf = Buffer.alloc(len);
|
|
483
|
+
fd = openSync(p, "r");
|
|
484
|
+
const bytesRead = readSync(fd, buf, 0, len, start);
|
|
485
|
+
return buf.subarray(0, bytesRead).toString("utf8");
|
|
486
|
+
} catch {
|
|
487
|
+
return null;
|
|
488
|
+
} finally {
|
|
489
|
+
if (fd !== null) {
|
|
490
|
+
try {
|
|
491
|
+
closeSync(fd);
|
|
492
|
+
} catch {
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
var PROOF_OF_LIFE_EVENTS = /* @__PURE__ */ new Set(["heartbeat", "boot"]);
|
|
498
|
+
function lastHeartbeatFromHealthLog(p, excludePid) {
|
|
499
|
+
try {
|
|
500
|
+
const tail = readTail(p);
|
|
501
|
+
if (!tail) return null;
|
|
502
|
+
const lines = tail.split(/\r?\n/);
|
|
503
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
504
|
+
const line = lines[i]?.trim();
|
|
505
|
+
if (!line || !line.includes('"event"')) continue;
|
|
506
|
+
if (!line.includes('"heartbeat"') && !line.includes('"boot"')) continue;
|
|
507
|
+
try {
|
|
508
|
+
const parsed = JSON.parse(line);
|
|
509
|
+
if (typeof parsed.event !== "string" || !PROOF_OF_LIFE_EVENTS.has(parsed.event)) continue;
|
|
510
|
+
if (excludePid !== null && typeof parsed.pid === "number" && parsed.pid === excludePid) continue;
|
|
511
|
+
if (typeof parsed.ts !== "string") continue;
|
|
512
|
+
const ts = Date.parse(parsed.ts);
|
|
513
|
+
if (Number.isFinite(ts)) return ts;
|
|
514
|
+
} catch {
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
return null;
|
|
518
|
+
} catch {
|
|
519
|
+
return null;
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
function readLastHeartbeatTsMs(paths) {
|
|
523
|
+
try {
|
|
524
|
+
const signals = [];
|
|
525
|
+
const excludePid = paths?.excludePid === void 0 ? process.pid : paths.excludePid;
|
|
526
|
+
const logDir = join(homedir(), ".exe-os", "logs");
|
|
527
|
+
const mainLog = paths?.logPath ?? join(logDir, "daemon-health.log");
|
|
528
|
+
const rotatedLog = paths?.rotatedLogPath ?? join(logDir, "daemon-health.log.1");
|
|
529
|
+
const mainHeartbeat = lastHeartbeatFromHealthLog(mainLog, excludePid);
|
|
530
|
+
if (mainHeartbeat !== null) signals.push(mainHeartbeat);
|
|
531
|
+
else {
|
|
532
|
+
const rotatedHeartbeat = lastHeartbeatFromHealthLog(rotatedLog, excludePid);
|
|
533
|
+
if (rotatedHeartbeat !== null) signals.push(rotatedHeartbeat);
|
|
534
|
+
}
|
|
535
|
+
try {
|
|
536
|
+
const heartbeatPath = paths?.heartbeatFilePath ?? eventLoopHeartbeatPath();
|
|
537
|
+
if (existsSync2(heartbeatPath)) {
|
|
538
|
+
const mtimeMs = statSync(heartbeatPath).mtimeMs;
|
|
539
|
+
if (Number.isFinite(mtimeMs)) signals.push(mtimeMs);
|
|
540
|
+
}
|
|
541
|
+
} catch {
|
|
542
|
+
}
|
|
543
|
+
return signals.length ? Math.max(...signals) : null;
|
|
544
|
+
} catch {
|
|
545
|
+
return null;
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
function assessCoverageGap(ctx) {
|
|
549
|
+
const gapThresholdMs = ctx.gapThresholdMs ?? DEFAULT_COVERAGE_GAP_THRESHOLD_MS;
|
|
550
|
+
const lastHeartbeatTs = ctx.lastHeartbeatTs;
|
|
551
|
+
if (lastHeartbeatTs === null) {
|
|
552
|
+
return {
|
|
553
|
+
isCoverageGap: false,
|
|
554
|
+
gapMs: 0,
|
|
555
|
+
rebootSpansGap: false,
|
|
556
|
+
label: "no coverage-gap evidence"
|
|
557
|
+
};
|
|
558
|
+
}
|
|
559
|
+
const gapMs = ctx.nowMs - lastHeartbeatTs;
|
|
560
|
+
const rebootSpansGap = ctx.hostBootTs !== null && ctx.hostBootTs > lastHeartbeatTs;
|
|
561
|
+
const isCoverageGap = gapMs > gapThresholdMs;
|
|
562
|
+
const hours = (gapMs / (60 * 60 * 1e3)).toFixed(1);
|
|
563
|
+
const label = rebootSpansGap ? `coverage-gap (died ~${hours}h ago; host reboot at ${new Date(ctx.hostBootTs).toISOString()})` : `coverage-gap (died ~${hours}h ago; no reboot detected)`;
|
|
564
|
+
return { isCoverageGap, gapMs, rebootSpansGap, label };
|
|
565
|
+
}
|
|
566
|
+
|
|
379
567
|
// src/lib/daemon-self-heal-dispatch.ts
|
|
380
568
|
function dispatchSelfHealRestart(lagMs, trigger, deps) {
|
|
381
569
|
deps.writeBreadcrumb(lagMs, trigger);
|
|
@@ -391,7 +579,7 @@ function resolveSelfHealThresholds(env = process.env) {
|
|
|
391
579
|
}
|
|
392
580
|
|
|
393
581
|
// src/lib/daemon-restart-backoff.ts
|
|
394
|
-
import { existsSync as
|
|
582
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3, unlinkSync as unlinkSync2, mkdirSync as mkdirSync2 } from "fs";
|
|
395
583
|
import { createHash } from "crypto";
|
|
396
584
|
import path2 from "path";
|
|
397
585
|
import os from "os";
|
|
@@ -437,8 +625,8 @@ function stateFile(workerKey) {
|
|
|
437
625
|
function loadBackoffState(workerKey) {
|
|
438
626
|
try {
|
|
439
627
|
const f = stateFile(workerKey);
|
|
440
|
-
if (!
|
|
441
|
-
const parsed = JSON.parse(
|
|
628
|
+
if (!existsSync3(f)) return null;
|
|
629
|
+
const parsed = JSON.parse(readFileSync3(f, "utf8"));
|
|
442
630
|
if (typeof parsed.consecutiveFailures !== "number" || typeof parsed.lastFailureAt !== "number") {
|
|
443
631
|
return null;
|
|
444
632
|
}
|
|
@@ -453,15 +641,15 @@ function loadBackoffState(workerKey) {
|
|
|
453
641
|
}
|
|
454
642
|
function saveBackoffState(workerKey, state) {
|
|
455
643
|
try {
|
|
456
|
-
if (!
|
|
457
|
-
|
|
644
|
+
if (!existsSync3(STATE_DIR)) mkdirSync2(STATE_DIR, { recursive: true });
|
|
645
|
+
writeFileSync3(stateFile(workerKey), JSON.stringify(state), { mode: 384 });
|
|
458
646
|
} catch {
|
|
459
647
|
}
|
|
460
648
|
}
|
|
461
649
|
function resetBackoffState(workerKey) {
|
|
462
650
|
try {
|
|
463
651
|
const f = stateFile(workerKey);
|
|
464
|
-
if (
|
|
652
|
+
if (existsSync3(f)) unlinkSync2(f);
|
|
465
653
|
} catch {
|
|
466
654
|
}
|
|
467
655
|
}
|
|
@@ -525,6 +713,31 @@ function isHostCpuStarved(load1m, cpuCount, ratio) {
|
|
|
525
713
|
const cores = Number.isFinite(cpuCount) && cpuCount > 0 ? cpuCount : 1;
|
|
526
714
|
return load1m > cores * ratio;
|
|
527
715
|
}
|
|
716
|
+
function pruneLoadSamples(samples, keepSinceMs) {
|
|
717
|
+
return samples.filter((sample) => Number.isFinite(sample.ts) && sample.ts >= keepSinceMs);
|
|
718
|
+
}
|
|
719
|
+
function maxLoadOverWindow(samples, windowStartMs, currentLoad1m) {
|
|
720
|
+
const candidates = [currentLoad1m];
|
|
721
|
+
for (const sample of samples) {
|
|
722
|
+
if (sample.ts >= windowStartMs && Number.isFinite(sample.load1m)) {
|
|
723
|
+
candidates.push(sample.load1m);
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
const finite = candidates.filter((load) => Number.isFinite(load));
|
|
727
|
+
return finite.length > 0 ? Math.max(...finite) : currentLoad1m;
|
|
728
|
+
}
|
|
729
|
+
function updateLoadWindow(samples, nowMs, load1m, wallElapsedMs, keepMs) {
|
|
730
|
+
const blockStartMs = nowMs - wallElapsedMs - 2500;
|
|
731
|
+
const next = pruneLoadSamples(
|
|
732
|
+
[...samples, { ts: nowMs, load1m }],
|
|
733
|
+
Math.min(nowMs - keepMs, blockStartMs)
|
|
734
|
+
);
|
|
735
|
+
return {
|
|
736
|
+
samples: next,
|
|
737
|
+
maxLoad1mOverWindow: maxLoadOverWindow(next, blockStartMs, load1m),
|
|
738
|
+
blockStartMs
|
|
739
|
+
};
|
|
740
|
+
}
|
|
528
741
|
function decideDaemonSelfHeal(s) {
|
|
529
742
|
const alive = s.processAlive ?? true;
|
|
530
743
|
if (!alive) {
|
|
@@ -543,7 +756,11 @@ function decideDaemonSelfHeal(s) {
|
|
|
543
756
|
selfInflictedSuppressedMsAfter: sumOf(prunedWindow)
|
|
544
757
|
};
|
|
545
758
|
const cleared = { selfInflictedWindowAfter: [], selfInflictedStreakAfter: 0, selfInflictedSuppressedMsAfter: 0 };
|
|
546
|
-
|
|
759
|
+
const loadCandidates = [s.load1m, s.maxLoad1mOverWindow].filter(
|
|
760
|
+
(load) => typeof load === "number" && Number.isFinite(load) && load > 0
|
|
761
|
+
);
|
|
762
|
+
const effectiveLoad1m = loadCandidates.length > 0 ? Math.max(...loadCandidates) : s.load1m;
|
|
763
|
+
if (isHostCpuStarved(effectiveLoad1m, s.cpuCount, s.starvationRatio)) {
|
|
547
764
|
return { restart: false, reason: "starved_backoff", consecutiveSevereAfter: 0, ...carry };
|
|
548
765
|
}
|
|
549
766
|
if (s.catchUpActive) {
|
|
@@ -589,22 +806,68 @@ function decideBootBackoff(s) {
|
|
|
589
806
|
if (!isHostCpuStarved(s.load1m, s.cpuCount, s.starvationRatio)) {
|
|
590
807
|
return { wait: false, delayMs: 0, reason: "not_starved" };
|
|
591
808
|
}
|
|
592
|
-
|
|
809
|
+
const clientsWaiting = s.clientsWaiting === true;
|
|
810
|
+
const baseDelayMs = clientsWaiting ? s.baseDelayMs / 2 : s.baseDelayMs;
|
|
811
|
+
const maxDelayMs = clientsWaiting ? s.maxDelayMs / 2 : s.maxDelayMs;
|
|
812
|
+
const maxAttempts = clientsWaiting ? Math.min(s.maxAttempts, 2) : s.maxAttempts;
|
|
813
|
+
if (s.attempt >= maxAttempts) {
|
|
593
814
|
return { wait: false, delayMs: 0, reason: "max_attempts_proceed" };
|
|
594
815
|
}
|
|
595
|
-
const base = Number.isFinite(
|
|
596
|
-
const cap = Number.isFinite(
|
|
816
|
+
const base = Number.isFinite(baseDelayMs) && baseDelayMs > 0 ? baseDelayMs : 0;
|
|
817
|
+
const cap = Number.isFinite(maxDelayMs) && maxDelayMs > 0 ? maxDelayMs : base;
|
|
597
818
|
const exp = base * Math.pow(2, Math.max(0, s.attempt));
|
|
598
819
|
const delayMs = Math.min(cap, exp);
|
|
599
820
|
return { wait: true, delayMs, reason: "backoff" };
|
|
600
821
|
}
|
|
822
|
+
function computeBootRetryAfterSeconds(nowMs, readyEtaMs, opts = {}) {
|
|
823
|
+
const defaultS = opts.defaultS ?? 3;
|
|
824
|
+
if (readyEtaMs === null) return defaultS;
|
|
825
|
+
const minS = opts.minS ?? 1;
|
|
826
|
+
const maxS = opts.maxS ?? 60;
|
|
827
|
+
return Math.min(maxS, Math.max(minS, Math.ceil((readyEtaMs - nowMs) / 1e3)));
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
// src/lib/bootstrap-response.ts
|
|
831
|
+
function buildBootstrapResponse(input) {
|
|
832
|
+
const headers = { "Content-Type": "application/json" };
|
|
833
|
+
if (input.method === "GET" && input.path === "/health") {
|
|
834
|
+
return {
|
|
835
|
+
statusCode: 200,
|
|
836
|
+
headers,
|
|
837
|
+
body: JSON.stringify(input.failedReason === null ? { status: "starting", version: input.version } : { status: "failed", reason: input.failedReason, version: input.version, recovery: "exe-os setup" })
|
|
838
|
+
};
|
|
839
|
+
}
|
|
840
|
+
if (input.failedReason !== null) {
|
|
841
|
+
return {
|
|
842
|
+
statusCode: 503,
|
|
843
|
+
headers: { ...headers, "Retry-After": "300" },
|
|
844
|
+
body: JSON.stringify({
|
|
845
|
+
jsonrpc: "2.0",
|
|
846
|
+
error: {
|
|
847
|
+
code: -32002,
|
|
848
|
+
message: `Terminal DB init failure (${input.failedReason}) - MCP will not start. Recover: 'exe-os setup'.`
|
|
849
|
+
},
|
|
850
|
+
id: null
|
|
851
|
+
})
|
|
852
|
+
};
|
|
853
|
+
}
|
|
854
|
+
return {
|
|
855
|
+
statusCode: 503,
|
|
856
|
+
headers: { ...headers, "Retry-After": String(input.retryAfterSeconds) },
|
|
857
|
+
body: JSON.stringify({
|
|
858
|
+
jsonrpc: "2.0",
|
|
859
|
+
error: { code: -32001, message: "Daemon initializing \u2014 MCP not ready yet. Retry in a few seconds." },
|
|
860
|
+
id: null
|
|
861
|
+
})
|
|
862
|
+
};
|
|
863
|
+
}
|
|
601
864
|
|
|
602
865
|
// src/lib/daemon-env.ts
|
|
603
|
-
import { readFileSync as
|
|
604
|
-
import { homedir } from "os";
|
|
605
|
-
import { join } from "path";
|
|
866
|
+
import { readFileSync as readFileSync4, existsSync as existsSync4 } from "fs";
|
|
867
|
+
import { homedir as homedir2 } from "os";
|
|
868
|
+
import { join as join2 } from "path";
|
|
606
869
|
function daemonEnvPath() {
|
|
607
|
-
return
|
|
870
|
+
return join2(homedir2(), ".exe-os", "daemon.env");
|
|
608
871
|
}
|
|
609
872
|
function parseDaemonEnv(contents) {
|
|
610
873
|
const out = {};
|
|
@@ -639,8 +902,8 @@ function applyDaemonEnv(parsed, env = process.env) {
|
|
|
639
902
|
function loadDaemonEnv(path4 = daemonEnvPath()) {
|
|
640
903
|
let contents;
|
|
641
904
|
try {
|
|
642
|
-
if (!
|
|
643
|
-
contents =
|
|
905
|
+
if (!existsSync4(path4)) return 0;
|
|
906
|
+
contents = readFileSync4(path4, "utf8");
|
|
644
907
|
} catch {
|
|
645
908
|
return 0;
|
|
646
909
|
}
|
|
@@ -661,7 +924,7 @@ function stabilizeDaemonCwd() {
|
|
|
661
924
|
} catch (err) {
|
|
662
925
|
const moduleDir = path3.dirname(fileURLToPath(import.meta.url));
|
|
663
926
|
const packageRoot = path3.resolve(moduleDir, "../..");
|
|
664
|
-
const fallback =
|
|
927
|
+
const fallback = existsSync5(path3.join(packageRoot, "package.json")) ? packageRoot : os2.homedir();
|
|
665
928
|
try {
|
|
666
929
|
process.chdir(fallback);
|
|
667
930
|
process.stderr.write(
|
|
@@ -686,7 +949,7 @@ var REVIEW_POLL_INTERVAL_MS = 60 * 1e3;
|
|
|
686
949
|
var DAEMON_TOKEN_ENV = "EXE_DAEMON_TOKEN";
|
|
687
950
|
var PACKAGE_VERSION = (() => {
|
|
688
951
|
try {
|
|
689
|
-
const pkg = JSON.parse(
|
|
952
|
+
const pkg = JSON.parse(readFileSync5(new URL("../../package.json", import.meta.url), "utf8"));
|
|
690
953
|
return typeof pkg.version === "string" ? pkg.version : "unknown";
|
|
691
954
|
} catch {
|
|
692
955
|
return "unknown";
|
|
@@ -702,6 +965,7 @@ var _rerankPendingCallbacks = /* @__PURE__ */ new Map();
|
|
|
702
965
|
var _shuttingDown = false;
|
|
703
966
|
var _drainingWrites = false;
|
|
704
967
|
var _mcpSessionDetailsRef = null;
|
|
968
|
+
var _mcpSessionLastSeenRef = null;
|
|
705
969
|
var _activeWrites = 0;
|
|
706
970
|
var _mcpHttpReady = Promise.resolve();
|
|
707
971
|
var _daemonToken = "";
|
|
@@ -1029,6 +1293,7 @@ function setBootPhase(phase) {
|
|
|
1029
1293
|
var TIMER_TRACE_BOOT_WINDOW_MS = Number(process.env.EXE_TIMER_TRACE_BOOT_WINDOW_MS) || 10 * 60 * 1e3;
|
|
1030
1294
|
var TIMER_TRACE_SLOW_MS = Number(process.env.EXE_TIMER_TRACE_SLOW_MS) || 500;
|
|
1031
1295
|
var TIMER_TIMEOUT_MS = Number(process.env.EXE_TIMER_TIMEOUT_MS) || 1e4;
|
|
1296
|
+
var TIMER_SLOW_WARN_MS = Number(process.env.EXE_TIMER_SLOW_WARN_MS) || 1e3;
|
|
1032
1297
|
var _timerInFlight = /* @__PURE__ */ new Set();
|
|
1033
1298
|
function shouldTraceDaemonTimer(durationMs = 0) {
|
|
1034
1299
|
return Date.now() - _startedAt2 < TIMER_TRACE_BOOT_WINDOW_MS || durationMs >= TIMER_TRACE_SLOW_MS;
|
|
@@ -1082,12 +1347,17 @@ async function traceDaemonTimer(name, fn) {
|
|
|
1082
1347
|
}
|
|
1083
1348
|
_timerInFlight.add(name);
|
|
1084
1349
|
const probe = captureClockProbe();
|
|
1350
|
+
const pauseSnapshot = sweepPauseTotalMs();
|
|
1085
1351
|
const traceStart = shouldTraceDaemonTimer();
|
|
1086
1352
|
if (traceStart) {
|
|
1087
1353
|
process.stderr.write(`[exed] Timer start: ${name}
|
|
1088
1354
|
`);
|
|
1089
1355
|
}
|
|
1356
|
+
const watchdogStart = Date.now();
|
|
1090
1357
|
const timeoutHandle = setTimeout(() => {
|
|
1358
|
+
const pausedMs = sweepPauseTotalMs() - pauseSnapshot;
|
|
1359
|
+
const busyMs = Date.now() - watchdogStart - pausedMs;
|
|
1360
|
+
if (busyMs < TIMER_TIMEOUT_MS) return;
|
|
1091
1361
|
_lastBlockingTimer = { name, durationMs: TIMER_TIMEOUT_MS, ts: Date.now() };
|
|
1092
1362
|
process.stderr.write(
|
|
1093
1363
|
`[exed] Timer TIMEOUT WARNING: ${name} has been running for >${TIMER_TIMEOUT_MS / 1e3}s \u2014 likely blocking the event loop
|
|
@@ -1109,8 +1379,31 @@ async function traceDaemonTimer(name, fn) {
|
|
|
1109
1379
|
const span = measureSpan(probe);
|
|
1110
1380
|
const durationMs = Math.round(span.monoMs);
|
|
1111
1381
|
const slept = span.sleptMs > 1e3;
|
|
1112
|
-
|
|
1113
|
-
|
|
1382
|
+
const sweepPausedMs = Math.max(0, sweepPauseTotalMs() - pauseSnapshot);
|
|
1383
|
+
const busyMs = Math.max(0, durationMs - sweepPausedMs);
|
|
1384
|
+
if (!slept && busyMs >= TIMER_TIMEOUT_MS) {
|
|
1385
|
+
_lastBlockingTimer = { name, durationMs: busyMs, ts: Date.now() };
|
|
1386
|
+
}
|
|
1387
|
+
if (shouldWarnSlowTimer(busyMs, slept, TIMER_SLOW_WARN_MS)) {
|
|
1388
|
+
const msg = `[exed] Timer SLOW: ${name} busy ${busyMs}ms (wall ${durationMs}ms, sweep-paused ${sweepPausedMs}ms) \u2014 exceeded ${TIMER_SLOW_WARN_MS}ms per-tick budget (event loop was held)`;
|
|
1389
|
+
process.stderr.write(`${msg}
|
|
1390
|
+
`);
|
|
1391
|
+
logDaemonHealth({
|
|
1392
|
+
event: "process_stats",
|
|
1393
|
+
pid: process.pid,
|
|
1394
|
+
message: msg,
|
|
1395
|
+
data: {
|
|
1396
|
+
type: "timer_slow",
|
|
1397
|
+
timer: name,
|
|
1398
|
+
durationMs,
|
|
1399
|
+
busyMs,
|
|
1400
|
+
sweepPausedMs,
|
|
1401
|
+
thresholdMs: TIMER_SLOW_WARN_MS,
|
|
1402
|
+
wallMs: Math.round(span.wallMs),
|
|
1403
|
+
sleptMs: Math.round(span.sleptMs),
|
|
1404
|
+
uptimeMs: Date.now() - _startedAt2
|
|
1405
|
+
}
|
|
1406
|
+
});
|
|
1114
1407
|
}
|
|
1115
1408
|
if (shouldTraceDaemonTimer(durationMs)) {
|
|
1116
1409
|
const sleepNote = slept ? ` (wall ${Math.round(span.wallMs)}ms \u2014 host slept/clock-stepped ${Math.round(span.sleptMs)}ms; not an event-loop block)` : "";
|
|
@@ -1178,18 +1471,18 @@ function recordDaemonCrash() {
|
|
|
1178
1471
|
const now = Date.now();
|
|
1179
1472
|
let counter = { crashes: [] };
|
|
1180
1473
|
try {
|
|
1181
|
-
counter = JSON.parse(
|
|
1474
|
+
counter = JSON.parse(readFileSync5(CRASH_LOOP_COUNTER_PATH, "utf8"));
|
|
1182
1475
|
} catch {
|
|
1183
1476
|
}
|
|
1184
1477
|
counter.crashes = counter.crashes.filter((t) => now - t < CRASH_LOOP_WINDOW_MS);
|
|
1185
1478
|
counter.crashes.push(now);
|
|
1186
1479
|
try {
|
|
1187
|
-
|
|
1480
|
+
writeFileSync4(CRASH_LOOP_COUNTER_PATH, JSON.stringify(counter), "utf8");
|
|
1188
1481
|
} catch {
|
|
1189
1482
|
}
|
|
1190
1483
|
if (counter.crashes.length >= CRASH_LOOP_THRESHOLD) {
|
|
1191
1484
|
try {
|
|
1192
|
-
|
|
1485
|
+
writeFileSync4(CRASH_LOOP_BREAKER_PATH, JSON.stringify({
|
|
1193
1486
|
trippedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1194
1487
|
crashCount: counter.crashes.length,
|
|
1195
1488
|
windowMs: CRASH_LOOP_WINDOW_MS
|
|
@@ -1206,10 +1499,10 @@ function recordDaemonCrash() {
|
|
|
1206
1499
|
}
|
|
1207
1500
|
function isCrashLoopBreakerActive() {
|
|
1208
1501
|
try {
|
|
1209
|
-
if (!
|
|
1210
|
-
const ageMs = Date.now() -
|
|
1502
|
+
if (!existsSync5(CRASH_LOOP_BREAKER_PATH)) return false;
|
|
1503
|
+
const ageMs = Date.now() - statSync2(CRASH_LOOP_BREAKER_PATH).mtimeMs;
|
|
1211
1504
|
if (ageMs > CRASH_LOOP_BREAKER_TTL_MS) {
|
|
1212
|
-
|
|
1505
|
+
unlinkSync3(CRASH_LOOP_BREAKER_PATH);
|
|
1213
1506
|
process.stderr.write(`[exed] Crash-loop breaker expired after ${Math.round(ageMs / 6e4)}min \u2014 cleared.
|
|
1214
1507
|
`);
|
|
1215
1508
|
return false;
|
|
@@ -1221,7 +1514,7 @@ function isCrashLoopBreakerActive() {
|
|
|
1221
1514
|
}
|
|
1222
1515
|
function resetCrashCounterOnHealthy() {
|
|
1223
1516
|
try {
|
|
1224
|
-
|
|
1517
|
+
unlinkSync3(CRASH_LOOP_COUNTER_PATH);
|
|
1225
1518
|
} catch {
|
|
1226
1519
|
}
|
|
1227
1520
|
}
|
|
@@ -1247,10 +1540,10 @@ function currentEmbedConfigFingerprint() {
|
|
|
1247
1540
|
}
|
|
1248
1541
|
function clearStaleOomMarker() {
|
|
1249
1542
|
try {
|
|
1250
|
-
if (!
|
|
1251
|
-
const ageMs = Date.now() -
|
|
1543
|
+
if (!existsSync5(OOM_MARKER_PATH)) return false;
|
|
1544
|
+
const ageMs = Date.now() - statSync2(OOM_MARKER_PATH).mtimeMs;
|
|
1252
1545
|
if (ageMs < OOM_MARKER_TTL_MS) return false;
|
|
1253
|
-
|
|
1546
|
+
unlinkSync3(OOM_MARKER_PATH);
|
|
1254
1547
|
process.stderr.write(`[exed] Cleared stale embedding OOM marker after ${Math.round(ageMs / 36e5)}h.
|
|
1255
1548
|
`);
|
|
1256
1549
|
return true;
|
|
@@ -1264,7 +1557,7 @@ function eventLoopBlockedMarkerPath() {
|
|
|
1264
1557
|
}
|
|
1265
1558
|
function isEventLoopBlockedNow(freshMs = EVENT_LOOP_BLOCKED_FRESH_MS) {
|
|
1266
1559
|
try {
|
|
1267
|
-
const ageMs = Date.now() -
|
|
1560
|
+
const ageMs = Date.now() - statSync2(eventLoopBlockedMarkerPath()).mtimeMs;
|
|
1268
1561
|
return ageMs < freshMs && ageMs > -freshMs;
|
|
1269
1562
|
} catch {
|
|
1270
1563
|
return false;
|
|
@@ -1273,8 +1566,8 @@ function isEventLoopBlockedNow(freshMs = EVENT_LOOP_BLOCKED_FRESH_MS) {
|
|
|
1273
1566
|
function touchEventLoopHeartbeat() {
|
|
1274
1567
|
try {
|
|
1275
1568
|
const p = eventLoopHeartbeatPath();
|
|
1276
|
-
|
|
1277
|
-
|
|
1569
|
+
mkdirSync3(path3.dirname(p), { recursive: true });
|
|
1570
|
+
writeFileSync4(p, String(Date.now()));
|
|
1278
1571
|
} catch {
|
|
1279
1572
|
}
|
|
1280
1573
|
}
|
|
@@ -1282,8 +1575,8 @@ function checkLaunchdPlistHealth() {
|
|
|
1282
1575
|
try {
|
|
1283
1576
|
if (process.platform !== "darwin") return;
|
|
1284
1577
|
const plistPath = path3.join(os2.homedir(), "Library", "LaunchAgents", "com.askexe.exed.plist");
|
|
1285
|
-
if (!
|
|
1286
|
-
const plist =
|
|
1578
|
+
if (!existsSync5(plistPath)) return;
|
|
1579
|
+
const plist = readFileSync5(plistPath, "utf8");
|
|
1287
1580
|
const expectedHeap = computeDaemonHeapCapMb();
|
|
1288
1581
|
const heapMatch = plist.match(/--max-old-space-size=(\d+)/);
|
|
1289
1582
|
const heap = heapMatch?.[1] ? parseInt(heapMatch[1], 10) : null;
|
|
@@ -1354,7 +1647,7 @@ async function loadModel() {
|
|
|
1354
1647
|
} catch {
|
|
1355
1648
|
}
|
|
1356
1649
|
const modelPath = path3.join(MODELS_DIR, MODEL_FILE);
|
|
1357
|
-
if (!
|
|
1650
|
+
if (!existsSync5(modelPath)) {
|
|
1358
1651
|
process.stderr.write(`[exed] No model at ${modelPath} \u2014 running without embeddings (VPS mode).
|
|
1359
1652
|
`);
|
|
1360
1653
|
_embeddingsDisabledByDesign = true;
|
|
@@ -1365,19 +1658,19 @@ async function loadModel() {
|
|
|
1365
1658
|
process.stderr.write(`[exed] Embedding config changed \u2014 cleared stale embed-worker backoff (one prompt retry under new config).
|
|
1366
1659
|
`);
|
|
1367
1660
|
try {
|
|
1368
|
-
if (
|
|
1661
|
+
if (existsSync5(EMBED_TIMEOUT_MARKER_PATH)) unlinkSync3(EMBED_TIMEOUT_MARKER_PATH);
|
|
1369
1662
|
} catch {
|
|
1370
1663
|
}
|
|
1371
1664
|
_embedConsecutiveTimeouts = 0;
|
|
1372
1665
|
}
|
|
1373
1666
|
clearStaleOomMarker();
|
|
1374
|
-
if (
|
|
1667
|
+
if (existsSync5(OOM_MARKER_PATH)) {
|
|
1375
1668
|
process.stderr.write(`[exed] Skipping embeddings \u2014 OOM marker exists. Delete ${OOM_MARKER_PATH} to retry.
|
|
1376
1669
|
`);
|
|
1377
1670
|
_embeddingsDisabledByDesign = true;
|
|
1378
1671
|
return;
|
|
1379
1672
|
}
|
|
1380
|
-
if (
|
|
1673
|
+
if (existsSync5(EMBED_TIMEOUT_MARKER_PATH)) {
|
|
1381
1674
|
process.stderr.write(`[exed] Skipping embeddings \u2014 inference-timeout marker exists (local embeddings non-functional on this host). Set EXE_EMBEDDINGS=0 or delete ${EMBED_TIMEOUT_MARKER_PATH} to retry.
|
|
1382
1675
|
`);
|
|
1383
1676
|
_embeddingsDisabledByDesign = true;
|
|
@@ -1432,7 +1725,7 @@ async function loadModel() {
|
|
|
1432
1725
|
process.stderr.write("[exed] Spawning embed worker process...\n");
|
|
1433
1726
|
try {
|
|
1434
1727
|
const workerPath = path3.join(path3.dirname(new URL(import.meta.url).pathname), "embed-worker.js");
|
|
1435
|
-
if (!
|
|
1728
|
+
if (!existsSync5(workerPath)) {
|
|
1436
1729
|
process.stderr.write(`[exed] Embed worker not found at ${workerPath} \u2014 running without embeddings.
|
|
1437
1730
|
`);
|
|
1438
1731
|
return;
|
|
@@ -1518,8 +1811,8 @@ async function loadModel() {
|
|
|
1518
1811
|
const oomShaped = code === 134 || signal === "SIGKILL" || signal === "SIGABRT";
|
|
1519
1812
|
if (oomShaped) {
|
|
1520
1813
|
try {
|
|
1521
|
-
|
|
1522
|
-
|
|
1814
|
+
mkdirSync3(path3.dirname(OOM_MARKER_PATH), { recursive: true });
|
|
1815
|
+
writeFileSync4(OOM_MARKER_PATH, `embed-worker OOM exit (code=${code}, signal=${signal ?? "none"}) at ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
1523
1816
|
`);
|
|
1524
1817
|
process.stderr.write(`[exed] Embed worker OOM-shaped exit \u2014 wrote OOM marker; respawns will skip model load until it TTL-clears.
|
|
1525
1818
|
`);
|
|
@@ -1539,7 +1832,7 @@ async function loadModel() {
|
|
|
1539
1832
|
void (async () => {
|
|
1540
1833
|
try {
|
|
1541
1834
|
if (_storeInitialized) {
|
|
1542
|
-
const { writeNotification } = await import("../notifications-
|
|
1835
|
+
const { writeNotification } = await import("../notifications-6XCSUTJW.js");
|
|
1543
1836
|
await writeNotification({
|
|
1544
1837
|
agentId: "exe",
|
|
1545
1838
|
agentRole: "system",
|
|
@@ -1620,8 +1913,8 @@ function disableEmbeddingsForInferenceTimeouts() {
|
|
|
1620
1913
|
if (_embeddingsDisabledByDesign) return;
|
|
1621
1914
|
_embeddingsDisabledByDesign = true;
|
|
1622
1915
|
try {
|
|
1623
|
-
|
|
1624
|
-
|
|
1916
|
+
mkdirSync3(path3.dirname(EMBED_TIMEOUT_MARKER_PATH), { recursive: true });
|
|
1917
|
+
writeFileSync4(
|
|
1625
1918
|
EMBED_TIMEOUT_MARKER_PATH,
|
|
1626
1919
|
`embed inference timed out ${_embedConsecutiveTimeouts}x consecutively at ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
1627
1920
|
`
|
|
@@ -1655,7 +1948,7 @@ function disableEmbeddingsForInferenceTimeouts() {
|
|
|
1655
1948
|
void (async () => {
|
|
1656
1949
|
try {
|
|
1657
1950
|
if (_storeInitialized) {
|
|
1658
|
-
const { writeNotification } = await import("../notifications-
|
|
1951
|
+
const { writeNotification } = await import("../notifications-6XCSUTJW.js");
|
|
1659
1952
|
await writeNotification({
|
|
1660
1953
|
agentId: "exe",
|
|
1661
1954
|
agentRole: "system",
|
|
@@ -1843,11 +2136,11 @@ async function shutdown(exitCode = 0, reason = null) {
|
|
|
1843
2136
|
`
|
|
1844
2137
|
);
|
|
1845
2138
|
try {
|
|
1846
|
-
|
|
2139
|
+
unlinkSync3(SOCKET_PATH);
|
|
1847
2140
|
} catch {
|
|
1848
2141
|
}
|
|
1849
2142
|
try {
|
|
1850
|
-
|
|
2143
|
+
unlinkSync3(PID_PATH);
|
|
1851
2144
|
} catch {
|
|
1852
2145
|
}
|
|
1853
2146
|
process.kill(process.pid, "SIGKILL");
|
|
@@ -1875,7 +2168,7 @@ async function shutdown(exitCode = 0, reason = null) {
|
|
|
1875
2168
|
preRestartDedupWindowMs,
|
|
1876
2169
|
findActiveDb,
|
|
1877
2170
|
shouldSkipBackupUnderMemoryPressure
|
|
1878
|
-
} = await import("
|
|
2171
|
+
} = await import("./db-backup.js");
|
|
1879
2172
|
const PRE_RESTART_DEDUP_MS = preRestartDedupWindowMs();
|
|
1880
2173
|
const PRE_RESTART_STORM_CAP = (() => {
|
|
1881
2174
|
const v = Number(process.env.EXE_PRE_RESTART_STORM_CAP);
|
|
@@ -1898,10 +2191,10 @@ async function shutdown(exitCode = 0, reason = null) {
|
|
|
1898
2191
|
const dbPath = findActiveDb();
|
|
1899
2192
|
let dbBytes = 0;
|
|
1900
2193
|
try {
|
|
1901
|
-
dbBytes = dbPath ?
|
|
2194
|
+
dbBytes = dbPath ? statSync2(dbPath).size : 0;
|
|
1902
2195
|
} catch {
|
|
1903
2196
|
}
|
|
1904
|
-
const { getAvailableMemoryBytesSync } = await import("../memory-pressure-watchdog-
|
|
2197
|
+
const { getAvailableMemoryBytesSync } = await import("../memory-pressure-watchdog-PSVJ5BCF.js");
|
|
1905
2198
|
const freeBytes = getAvailableMemoryBytesSync();
|
|
1906
2199
|
if (shouldSkipBackupUnderMemoryPressure(freeBytes, dbBytes)) {
|
|
1907
2200
|
memoryGateSkip = true;
|
|
@@ -1932,6 +2225,7 @@ async function shutdown(exitCode = 0, reason = null) {
|
|
|
1932
2225
|
process.stderr.write(`[exed] Pre-restart backup failed (non-fatal): ${e instanceof Error ? e.message : String(e)}
|
|
1933
2226
|
`);
|
|
1934
2227
|
}
|
|
2228
|
+
const restartHandoff = shouldScheduleDaemonRestartHandoff(exitCode, reason);
|
|
1935
2229
|
try {
|
|
1936
2230
|
const { getClient } = await import("./database.js");
|
|
1937
2231
|
const client = getClient();
|
|
@@ -1945,12 +2239,20 @@ async function shutdown(exitCode = 0, reason = null) {
|
|
|
1945
2239
|
`);
|
|
1946
2240
|
}
|
|
1947
2241
|
try {
|
|
1948
|
-
const {
|
|
2242
|
+
const { disposeDatabase } = await import("./database.js");
|
|
2243
|
+
await disposeDatabase();
|
|
2244
|
+
process.stderr.write("[exed] Database disposed before restart handoff.\n");
|
|
2245
|
+
} catch (e) {
|
|
2246
|
+
process.stderr.write(`[exed] Database dispose failed during shutdown: ${e instanceof Error ? e.message : String(e)}
|
|
2247
|
+
`);
|
|
2248
|
+
}
|
|
2249
|
+
try {
|
|
2250
|
+
const { stopProjectionWorker } = await import("../projection-worker-CKC2E22U.js");
|
|
1949
2251
|
stopProjectionWorker();
|
|
1950
2252
|
} catch {
|
|
1951
2253
|
}
|
|
1952
2254
|
try {
|
|
1953
|
-
const { disposeShards } = await import("../shard-manager-
|
|
2255
|
+
const { disposeShards } = await import("../shard-manager-OETALPDW.js");
|
|
1954
2256
|
disposeShards();
|
|
1955
2257
|
} catch {
|
|
1956
2258
|
}
|
|
@@ -1968,18 +2270,15 @@ async function shutdown(exitCode = 0, reason = null) {
|
|
|
1968
2270
|
} catch {
|
|
1969
2271
|
}
|
|
1970
2272
|
try {
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
const sessPath = path3.join(EXE_AI_DIR, "mcp-sessions-persist.json");
|
|
1981
|
-
writeFileSync3(sessPath, JSON.stringify(sessionsToSave) + "\n", { mode: 384 });
|
|
1982
|
-
process.stderr.write(`[exed] Persisted ${sessionsToSave.length} MCP session(s) for next daemon.
|
|
2273
|
+
disposeDbWriteWorker();
|
|
2274
|
+
} catch {
|
|
2275
|
+
}
|
|
2276
|
+
try {
|
|
2277
|
+
const { persistMcpSessions, buildPersistedSessions } = await import("../mcp-session-persist-PS7BIG44.js");
|
|
2278
|
+
const sessionsToSave = _mcpSessionDetailsRef ? buildPersistedSessions(_mcpSessionDetailsRef.entries(), _mcpSessionLastSeenRef ?? /* @__PURE__ */ new Map(), Date.now()) : [];
|
|
2279
|
+
const persisted = persistMcpSessions(sessionsToSave, EXE_AI_DIR);
|
|
2280
|
+
if (persisted > 0) {
|
|
2281
|
+
process.stderr.write(`[exed] Persisted ${persisted} MCP session(s) for next daemon.
|
|
1983
2282
|
`);
|
|
1984
2283
|
}
|
|
1985
2284
|
} catch (e) {
|
|
@@ -1987,17 +2286,50 @@ async function shutdown(exitCode = 0, reason = null) {
|
|
|
1987
2286
|
`);
|
|
1988
2287
|
}
|
|
1989
2288
|
try {
|
|
1990
|
-
|
|
2289
|
+
unlinkSync3(SOCKET_PATH);
|
|
1991
2290
|
} catch (e) {
|
|
1992
2291
|
process.stderr.write(`[exed] socket cleanup: ${e.message}
|
|
1993
2292
|
`);
|
|
1994
2293
|
}
|
|
1995
2294
|
try {
|
|
1996
|
-
|
|
2295
|
+
unlinkSync3(PID_PATH);
|
|
1997
2296
|
} catch (e) {
|
|
1998
2297
|
process.stderr.write(`[exed] pid cleanup: ${e.message}
|
|
1999
2298
|
`);
|
|
2000
2299
|
}
|
|
2300
|
+
if (restartHandoff) {
|
|
2301
|
+
try {
|
|
2302
|
+
const moduleDir = path3.dirname(fileURLToPath(import.meta.url));
|
|
2303
|
+
const helperPath = path3.resolve(moduleDir, "../bin/daemon-restart-handoff.js");
|
|
2304
|
+
const daemonPath = fileURLToPath(import.meta.url);
|
|
2305
|
+
const logPath = path3.join(EXE_AI_DIR, "logs", "exed.log");
|
|
2306
|
+
const lockPath = path3.join(EXE_AI_DIR, "exed-spawn.lock");
|
|
2307
|
+
const heapCapMb = computeDaemonHeapCapMb(os2.totalmem() / (1024 * 1024 * 1024));
|
|
2308
|
+
const config = {
|
|
2309
|
+
oldPid: process.pid,
|
|
2310
|
+
daemonPath,
|
|
2311
|
+
pidPath: PID_PATH,
|
|
2312
|
+
socketPath: SOCKET_PATH,
|
|
2313
|
+
lockPath,
|
|
2314
|
+
logPath,
|
|
2315
|
+
heapCapMb
|
|
2316
|
+
};
|
|
2317
|
+
const child = spawn(process.execPath, [helperPath], {
|
|
2318
|
+
detached: true,
|
|
2319
|
+
stdio: "ignore",
|
|
2320
|
+
env: {
|
|
2321
|
+
...process.env,
|
|
2322
|
+
EXE_DAEMON_HANDOFF_CONFIG: JSON.stringify(config)
|
|
2323
|
+
}
|
|
2324
|
+
});
|
|
2325
|
+
child.unref();
|
|
2326
|
+
process.stderr.write(`[exed] Restart handoff helper scheduled (pid ${child.pid ?? "unknown"}).
|
|
2327
|
+
`);
|
|
2328
|
+
} catch (e) {
|
|
2329
|
+
process.stderr.write(`[exed] Restart handoff helper schedule failed: ${e instanceof Error ? e.message : String(e)}
|
|
2330
|
+
`);
|
|
2331
|
+
}
|
|
2332
|
+
}
|
|
2001
2333
|
process.stderr.write(`[exed] Shutdown complete (exit ${exitCode}${exitCode === 0 ? "" : " \u2014 restart-intent, launchd will relaunch"}).
|
|
2002
2334
|
`);
|
|
2003
2335
|
process.exit(exitCode);
|
|
@@ -2011,7 +2343,7 @@ async function handleHealthCheck(socket, requestId) {
|
|
|
2011
2343
|
let pipelineStatus = "unknown";
|
|
2012
2344
|
if (dbConnected) {
|
|
2013
2345
|
try {
|
|
2014
|
-
await import("../pipeline-router-
|
|
2346
|
+
await import("../pipeline-router-N2LDNFJ5.js");
|
|
2015
2347
|
pipelineStatus = "ok";
|
|
2016
2348
|
} catch {
|
|
2017
2349
|
pipelineStatus = "unavailable";
|
|
@@ -2196,11 +2528,11 @@ var _ingestCount = 0;
|
|
|
2196
2528
|
var INGEST_OUTBOX_DIR = path3.join(EXE_AI_DIR, "ingest-outbox");
|
|
2197
2529
|
function persistIngestOutbox(req) {
|
|
2198
2530
|
try {
|
|
2199
|
-
|
|
2531
|
+
mkdirSync3(INGEST_OUTBOX_DIR, { recursive: true });
|
|
2200
2532
|
const id = randomUUID();
|
|
2201
2533
|
const finalPath = path3.join(INGEST_OUTBOX_DIR, `${Date.now()}-${id}.json`);
|
|
2202
2534
|
const tmpPath = `${finalPath}.tmp`;
|
|
2203
|
-
|
|
2535
|
+
writeFileSync4(tmpPath, JSON.stringify(req) + "\n", { mode: 384 });
|
|
2204
2536
|
renameSync(tmpPath, finalPath);
|
|
2205
2537
|
return finalPath;
|
|
2206
2538
|
} catch (err) {
|
|
@@ -2211,12 +2543,12 @@ function persistIngestOutbox(req) {
|
|
|
2211
2543
|
}
|
|
2212
2544
|
async function drainIngestOutbox() {
|
|
2213
2545
|
try {
|
|
2214
|
-
if (!
|
|
2546
|
+
if (!existsSync5(INGEST_OUTBOX_DIR)) return;
|
|
2215
2547
|
const files = readdirSync(INGEST_OUTBOX_DIR).filter((f) => f.endsWith(".json")).sort().slice(0, 500);
|
|
2216
2548
|
for (const file of files) {
|
|
2217
2549
|
const fullPath = path3.join(INGEST_OUTBOX_DIR, file);
|
|
2218
2550
|
try {
|
|
2219
|
-
const req = JSON.parse(
|
|
2551
|
+
const req = JSON.parse(readFileSync5(fullPath, "utf8"));
|
|
2220
2552
|
await handleIngest(req, fullPath);
|
|
2221
2553
|
} catch (err) {
|
|
2222
2554
|
process.stderr.write(`[exed] Ingest outbox drain failed for ${file}: ${err instanceof Error ? err.message : String(err)}
|
|
@@ -2235,7 +2567,7 @@ async function handleIngest(req, outboxPath) {
|
|
|
2235
2567
|
if (!req.rawText || req.rawText.length < 50) {
|
|
2236
2568
|
if (persistedPath) {
|
|
2237
2569
|
try {
|
|
2238
|
-
|
|
2570
|
+
unlinkSync3(persistedPath);
|
|
2239
2571
|
} catch {
|
|
2240
2572
|
}
|
|
2241
2573
|
}
|
|
@@ -2258,7 +2590,7 @@ async function handleIngest(req, outboxPath) {
|
|
|
2258
2590
|
_ingestCount++;
|
|
2259
2591
|
if (persistedPath) {
|
|
2260
2592
|
try {
|
|
2261
|
-
|
|
2593
|
+
unlinkSync3(persistedPath);
|
|
2262
2594
|
} catch {
|
|
2263
2595
|
}
|
|
2264
2596
|
}
|
|
@@ -2306,16 +2638,16 @@ async function handleBatchWriteMemory(socket, requestId, entries) {
|
|
|
2306
2638
|
});
|
|
2307
2639
|
}
|
|
2308
2640
|
}
|
|
2309
|
-
async function writeMemoryRecord(entry) {
|
|
2641
|
+
async function writeMemoryRecord(entry, opts = {}) {
|
|
2310
2642
|
if (_drainingWrites) throw new Error("Server shutting down \u2014 writes paused");
|
|
2311
2643
|
_activeWrites++;
|
|
2312
2644
|
try {
|
|
2313
|
-
return await _writeMemoryRecordInner(entry);
|
|
2645
|
+
return await _writeMemoryRecordInner(entry, opts.syncOnly === true);
|
|
2314
2646
|
} finally {
|
|
2315
2647
|
_activeWrites--;
|
|
2316
2648
|
}
|
|
2317
2649
|
}
|
|
2318
|
-
async function _writeMemoryRecordInner(entry) {
|
|
2650
|
+
async function _writeMemoryRecordInner(entry, syncOnly = false) {
|
|
2319
2651
|
const id = randomUUID();
|
|
2320
2652
|
const now = entry.timestamp || (/* @__PURE__ */ new Date()).toISOString();
|
|
2321
2653
|
const governed = governMemoryRecord({
|
|
@@ -2337,15 +2669,8 @@ async function _writeMemoryRecordInner(entry) {
|
|
|
2337
2669
|
});
|
|
2338
2670
|
if (governed.shouldDrop) return id;
|
|
2339
2671
|
const record = governed.record;
|
|
2340
|
-
const duplicate = await findScopedDuplicate({
|
|
2341
|
-
contentHash: governed.contentHash,
|
|
2342
|
-
agentId: record.agent_id,
|
|
2343
|
-
projectName: record.project_name,
|
|
2344
|
-
memoryType: record.memory_type ?? "raw"
|
|
2345
|
-
});
|
|
2346
|
-
if (duplicate) return duplicate;
|
|
2347
2672
|
let vectorBlob = null;
|
|
2348
|
-
if (_embedWorkerReady && !governed.skipEmbedding) {
|
|
2673
|
+
if (!syncOnly && _embedWorkerReady && !governed.skipEmbedding) {
|
|
2349
2674
|
try {
|
|
2350
2675
|
const vectors = await embedTexts([record.raw_text]);
|
|
2351
2676
|
if (vectors.length > 0 && vectors[0].length === EMBEDDING_DIM) {
|
|
@@ -2357,11 +2682,33 @@ async function _writeMemoryRecordInner(entry) {
|
|
|
2357
2682
|
`);
|
|
2358
2683
|
}
|
|
2359
2684
|
}
|
|
2360
|
-
const { getClient } = await import("./database.js");
|
|
2361
|
-
const client = getClient();
|
|
2362
2685
|
const hasVector = vectorBlob !== null;
|
|
2363
2686
|
const embeddingModel = hasVector ? activeEmbeddingModelName() : null;
|
|
2364
|
-
|
|
2687
|
+
if (!syncOnly && isWriteWorkerEnabled() && isDbWriteWorkerReady()) {
|
|
2688
|
+
try {
|
|
2689
|
+
const result = await writeMemoryInWorker({
|
|
2690
|
+
record,
|
|
2691
|
+
contentHash: governed.contentHash,
|
|
2692
|
+
vectorBlob,
|
|
2693
|
+
embeddingModel,
|
|
2694
|
+
trajectory: entry.trajectory ?? null
|
|
2695
|
+
});
|
|
2696
|
+
return result.memoryId;
|
|
2697
|
+
} catch (e) {
|
|
2698
|
+
process.stderr.write(`[exed] write worker failed (${e instanceof Error ? e.message : String(e)}) - falling back to main-thread write
|
|
2699
|
+
`);
|
|
2700
|
+
}
|
|
2701
|
+
}
|
|
2702
|
+
const duplicate = await findScopedDuplicate({
|
|
2703
|
+
contentHash: governed.contentHash,
|
|
2704
|
+
agentId: record.agent_id,
|
|
2705
|
+
projectName: record.project_name,
|
|
2706
|
+
memoryType: record.memory_type ?? "raw"
|
|
2707
|
+
});
|
|
2708
|
+
if (duplicate) return duplicate;
|
|
2709
|
+
const { getClient } = await import("./database.js");
|
|
2710
|
+
const client = getClient();
|
|
2711
|
+
const insertResult = await client.execute({
|
|
2365
2712
|
sql: hasVector ? `INSERT OR IGNORE INTO memories
|
|
2366
2713
|
(id, agent_id, agent_role, session_id, timestamp, tool_name, project_name,
|
|
2367
2714
|
has_error, raw_text, vector, version, task_id, importance, status,
|
|
@@ -2416,10 +2763,19 @@ async function _writeMemoryRecordInner(entry) {
|
|
|
2416
2763
|
embeddingModel
|
|
2417
2764
|
]
|
|
2418
2765
|
});
|
|
2766
|
+
if (Number(insertResult.rowsAffected) === 0) {
|
|
2767
|
+
const winner = await findScopedDuplicate({
|
|
2768
|
+
contentHash: governed.contentHash,
|
|
2769
|
+
agentId: record.agent_id,
|
|
2770
|
+
projectName: record.project_name,
|
|
2771
|
+
memoryType: record.memory_type ?? "raw"
|
|
2772
|
+
});
|
|
2773
|
+
return winner ?? id;
|
|
2774
|
+
}
|
|
2419
2775
|
const vRow = await client.execute({ sql: "SELECT version FROM memories WHERE id = ?", args: [id] });
|
|
2420
2776
|
const version = Number(vRow.rows[0]?.version) || 0;
|
|
2421
2777
|
try {
|
|
2422
|
-
const { insertOntologyForMemory } = await import("../agentic-ontology-
|
|
2778
|
+
const { insertOntologyForMemory } = await import("../agentic-ontology-SCG6UUHK.js");
|
|
2423
2779
|
await insertOntologyForMemory({
|
|
2424
2780
|
id,
|
|
2425
2781
|
agent_id: record.agent_id,
|
|
@@ -2443,20 +2799,33 @@ async function _writeMemoryRecordInner(entry) {
|
|
|
2443
2799
|
}
|
|
2444
2800
|
var MEMORY_DRAIN_INTERVAL_MS = 30 * 1e3;
|
|
2445
2801
|
var MEMORY_DRAIN_BATCH = Math.max(1, Number(process.env.EXE_MEMORY_DRAIN_BATCH) || 1);
|
|
2802
|
+
var MEMORY_DRAIN_TX_BATCH = Math.max(1, Number(process.env.EXE_MEMORY_DRAIN_TX_BATCH) || 25);
|
|
2446
2803
|
function startMemoryQueueDrain() {
|
|
2447
2804
|
const drain = async () => traceDaemonTimer("memory_queue_drain", async () => {
|
|
2448
2805
|
fired("memory_queue_drain");
|
|
2449
2806
|
if (!await ensureStoreForPolling()) return;
|
|
2450
2807
|
try {
|
|
2451
|
-
const { ackQueue, claimQueue, retryQueueEntries, processQueueEntries } = await import("../memory-queue-
|
|
2808
|
+
const { ackQueue, claimQueue, retryQueueEntries, processQueueEntries } = await import("../memory-queue-ZI7DX44D.js");
|
|
2452
2809
|
const lease = claimQueue();
|
|
2453
2810
|
if (!lease || lease.entries.length === 0) return;
|
|
2454
2811
|
acted("memory_queue_drain");
|
|
2455
2812
|
const entries = lease.entries;
|
|
2456
|
-
const
|
|
2813
|
+
const useTxBatch = !_embedWorkerReady && !(isWriteWorkerEnabled() && isDbWriteWorkerReady());
|
|
2814
|
+
const txClient = useTxBatch ? (await import("./database.js")).getClient() : null;
|
|
2815
|
+
const drainSyncOnly = useTxBatch;
|
|
2816
|
+
const result = await processQueueEntries(entries, (entry) => writeMemoryRecord(entry, { syncOnly: drainSyncOnly }), {
|
|
2457
2817
|
isDraining: () => _drainingWrites,
|
|
2458
|
-
batchSize: MEMORY_DRAIN_BATCH,
|
|
2818
|
+
batchSize: useTxBatch ? MEMORY_DRAIN_TX_BATCH : MEMORY_DRAIN_BATCH,
|
|
2459
2819
|
yieldFn: yieldToEventLoop,
|
|
2820
|
+
beginBatch: txClient ? async () => {
|
|
2821
|
+
await txClient.execute("BEGIN IMMEDIATE");
|
|
2822
|
+
} : void 0,
|
|
2823
|
+
commitBatch: txClient ? async () => {
|
|
2824
|
+
await txClient.execute("COMMIT");
|
|
2825
|
+
} : void 0,
|
|
2826
|
+
rollbackBatch: txClient ? async () => {
|
|
2827
|
+
await txClient.execute("ROLLBACK");
|
|
2828
|
+
} : void 0,
|
|
2460
2829
|
onWriteError: (_entry, err) => {
|
|
2461
2830
|
process.stderr.write(
|
|
2462
2831
|
`[exed] Queue drain write error: ${err instanceof Error ? err.message : String(err)}
|
|
@@ -2484,7 +2853,24 @@ function startMemoryQueueDrain() {
|
|
|
2484
2853
|
);
|
|
2485
2854
|
}
|
|
2486
2855
|
});
|
|
2487
|
-
void
|
|
2856
|
+
void (async () => {
|
|
2857
|
+
const holdStartedAt = Date.now();
|
|
2858
|
+
const HOLD_CAP_MS = Number(process.env.EXE_STARTUP_DRAIN_GRACE_CAP_MS) || 30 * 60 * 1e3;
|
|
2859
|
+
const hold = setInterval(() => {
|
|
2860
|
+
if (Date.now() - holdStartedAt >= HOLD_CAP_MS) {
|
|
2861
|
+
clearInterval(hold);
|
|
2862
|
+
return;
|
|
2863
|
+
}
|
|
2864
|
+
extendBootCatchUp(6e4);
|
|
2865
|
+
}, 3e4);
|
|
2866
|
+
hold.unref();
|
|
2867
|
+
extendBootCatchUp(6e4);
|
|
2868
|
+
try {
|
|
2869
|
+
await drain();
|
|
2870
|
+
} finally {
|
|
2871
|
+
clearInterval(hold);
|
|
2872
|
+
}
|
|
2873
|
+
})();
|
|
2488
2874
|
const timer = setInterval(() => void drain(), MEMORY_DRAIN_INTERVAL_MS);
|
|
2489
2875
|
timer.unref();
|
|
2490
2876
|
process.stderr.write(`[exed] Memory queue drain started (every ${MEMORY_DRAIN_INTERVAL_MS / 1e3}s)
|
|
@@ -2494,19 +2880,19 @@ var MESSAGE_DRAIN_INTERVAL_MS = 3e4;
|
|
|
2494
2880
|
function retryMessageQueueEntries(leasePath, entries) {
|
|
2495
2881
|
if (entries.length === 0) {
|
|
2496
2882
|
try {
|
|
2497
|
-
|
|
2883
|
+
unlinkSync3(leasePath);
|
|
2498
2884
|
} catch {
|
|
2499
2885
|
}
|
|
2500
2886
|
return;
|
|
2501
2887
|
}
|
|
2502
|
-
|
|
2888
|
+
writeFileSync4(leasePath, entries.map((entry) => JSON.stringify(entry)).join("\n") + "\n");
|
|
2503
2889
|
}
|
|
2504
2890
|
function startMessageQueueDrain() {
|
|
2505
2891
|
const drain = async () => traceDaemonTimer("message_queue_drain", async () => {
|
|
2506
2892
|
fired("message_queue_drain");
|
|
2507
2893
|
if (!await ensureStoreForPolling()) return;
|
|
2508
2894
|
try {
|
|
2509
|
-
const { claimMessageQueue, ackMessageQueue } = await import("../message-queue-client-
|
|
2895
|
+
const { claimMessageQueue, ackMessageQueue } = await import("../message-queue-client-WMIO5FL5.js");
|
|
2510
2896
|
const lease = claimMessageQueue();
|
|
2511
2897
|
if (!lease || lease.entries.length === 0) return;
|
|
2512
2898
|
acted("message_queue_drain");
|
|
@@ -2610,7 +2996,7 @@ async function retryPendingMessages() {
|
|
|
2610
2996
|
}
|
|
2611
2997
|
}
|
|
2612
2998
|
function startServer() {
|
|
2613
|
-
|
|
2999
|
+
mkdirSync3(path3.dirname(SOCKET_PATH), { recursive: true });
|
|
2614
3000
|
try {
|
|
2615
3001
|
chmodSync(path3.dirname(SOCKET_PATH), 448);
|
|
2616
3002
|
} catch {
|
|
@@ -2620,18 +3006,18 @@ function startServer() {
|
|
|
2620
3006
|
const oldPath = path3.join(path3.dirname(SOCKET_PATH), oldFile);
|
|
2621
3007
|
try {
|
|
2622
3008
|
if (oldFile.endsWith(".pid")) {
|
|
2623
|
-
const pid = parseInt(
|
|
3009
|
+
const pid = parseInt(readFileSync5(oldPath, "utf8").trim(), 10);
|
|
2624
3010
|
if (pid > 0) try {
|
|
2625
3011
|
process.kill(pid, "SIGKILL");
|
|
2626
3012
|
} catch {
|
|
2627
3013
|
}
|
|
2628
3014
|
}
|
|
2629
|
-
|
|
3015
|
+
unlinkSync3(oldPath);
|
|
2630
3016
|
} catch {
|
|
2631
3017
|
}
|
|
2632
3018
|
}
|
|
2633
3019
|
try {
|
|
2634
|
-
|
|
3020
|
+
unlinkSync3(SOCKET_PATH);
|
|
2635
3021
|
} catch {
|
|
2636
3022
|
}
|
|
2637
3023
|
const server = net.createServer((socket) => {
|
|
@@ -2845,6 +3231,8 @@ async function resolveAndClaimPort() {
|
|
|
2845
3231
|
async function startMcpHttpServer() {
|
|
2846
3232
|
process.stderr.write("[exed] MCP HTTP: starting setup...\n");
|
|
2847
3233
|
let _bootstrapServerRef = null;
|
|
3234
|
+
let _bootstrapFailedReason = null;
|
|
3235
|
+
let _bootReadyEtaMs = null;
|
|
2848
3236
|
try {
|
|
2849
3237
|
let parseDurationMs2 = function(value, fallback, options = {}) {
|
|
2850
3238
|
if (!value) return fallback;
|
|
@@ -3020,6 +3408,18 @@ async function startMcpHttpServer() {
|
|
|
3020
3408
|
}
|
|
3021
3409
|
global.gc?.();
|
|
3022
3410
|
}
|
|
3411
|
+
try {
|
|
3412
|
+
void import("../mcp-session-persist-PS7BIG44.js").then(({ persistMcpSessions, buildPersistedSessions }) => {
|
|
3413
|
+
const sessionsToSave = buildPersistedSessions(sessionDetails.entries(), sessionLastSeen, Date.now());
|
|
3414
|
+
persistMcpSessions(sessionsToSave, EXE_AI_DIR);
|
|
3415
|
+
}).catch((e) => {
|
|
3416
|
+
process.stderr.write(`[exed] Session persist failed (non-fatal): ${e instanceof Error ? e.message : String(e)}
|
|
3417
|
+
`);
|
|
3418
|
+
});
|
|
3419
|
+
} catch (e) {
|
|
3420
|
+
process.stderr.write(`[exed] Session persist failed (non-fatal): ${e instanceof Error ? e.message : String(e)}
|
|
3421
|
+
`);
|
|
3422
|
+
}
|
|
3023
3423
|
}, getJsonRpcId2 = function(body) {
|
|
3024
3424
|
if (body && typeof body === "object" && !Array.isArray(body) && "id" in body) {
|
|
3025
3425
|
const id = body.id;
|
|
@@ -3055,21 +3455,21 @@ async function startMcpHttpServer() {
|
|
|
3055
3455
|
const _earlyAllowRemote = /^(1|true|yes|on)$/i.test(process.env.EXE_MCP_ALLOW_REMOTE ?? "");
|
|
3056
3456
|
const RESOLVED_MCP_HOST = _earlyIsRemoteHost && !_earlyAllowRemote ? "127.0.0.1" : _earlyRequestedHost;
|
|
3057
3457
|
const RESOLVED_MCP_PORT = await resolveAndClaimPort();
|
|
3458
|
+
const DB_INIT_ETA_MS = 2e4;
|
|
3058
3459
|
_bootstrapServerRef = createHttpServer((req, res) => {
|
|
3059
3460
|
try {
|
|
3060
3461
|
res.setHeader("Access-Control-Allow-Origin", "http://127.0.0.1");
|
|
3061
|
-
const path4 = (req.url || "/").split("?")[0];
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
}));
|
|
3462
|
+
const path4 = (req.url || "/").split("?")[0] ?? "/";
|
|
3463
|
+
const retryAfterSeconds = computeBootRetryAfterSeconds(Date.now(), _bootReadyEtaMs);
|
|
3464
|
+
const response = buildBootstrapResponse({
|
|
3465
|
+
failedReason: _bootstrapFailedReason,
|
|
3466
|
+
method: req.method ?? "",
|
|
3467
|
+
path: path4,
|
|
3468
|
+
retryAfterSeconds,
|
|
3469
|
+
version: PACKAGE_VERSION
|
|
3470
|
+
});
|
|
3471
|
+
res.writeHead(response.statusCode, response.headers);
|
|
3472
|
+
res.end(response.body);
|
|
3073
3473
|
} catch {
|
|
3074
3474
|
}
|
|
3075
3475
|
});
|
|
@@ -3096,33 +3496,62 @@ async function startMcpHttpServer() {
|
|
|
3096
3496
|
const BOOT_BACKOFF_MAX_MS = parseInt(process.env.EXE_BOOT_BACKOFF_MAX_MS ?? "") || 15e3;
|
|
3097
3497
|
const BOOT_BACKOFF_MAX_ATTEMPTS = parseInt(process.env.EXE_BOOT_BACKOFF_MAX_ATTEMPTS ?? "") || 5;
|
|
3098
3498
|
const starvationRatio = parseFloat(process.env.EXE_STARVATION_LOAD_RATIO ?? "1.5");
|
|
3499
|
+
let clientsWaiting = false;
|
|
3500
|
+
try {
|
|
3501
|
+
const sessPath = path3.join(EXE_AI_DIR, "mcp-sessions-persist.json");
|
|
3502
|
+
if (existsSync5(sessPath)) {
|
|
3503
|
+
const saved = JSON.parse(readFileSync5(sessPath, "utf-8"));
|
|
3504
|
+
const { hasRecentWaitingClients, mcpSessionRestoreMaxAgeMs } = await import("../mcp-session-persist-PS7BIG44.js");
|
|
3505
|
+
clientsWaiting = hasRecentWaitingClients(saved, Date.now(), mcpSessionRestoreMaxAgeMs());
|
|
3506
|
+
}
|
|
3507
|
+
} catch {
|
|
3508
|
+
clientsWaiting = false;
|
|
3509
|
+
}
|
|
3510
|
+
let loggedClientsWaitingBackoff = false;
|
|
3099
3511
|
for (let attempt = 0; ; attempt++) {
|
|
3512
|
+
const load1m = os2.loadavg()[0] ?? 0;
|
|
3513
|
+
const cpuCount = os2.cpus().length || 1;
|
|
3100
3514
|
const decision = decideBootBackoff({
|
|
3101
|
-
load1m
|
|
3102
|
-
cpuCount
|
|
3515
|
+
load1m,
|
|
3516
|
+
cpuCount,
|
|
3103
3517
|
starvationRatio,
|
|
3104
3518
|
attempt,
|
|
3105
3519
|
baseDelayMs: BOOT_BACKOFF_BASE_MS,
|
|
3106
3520
|
maxDelayMs: BOOT_BACKOFF_MAX_MS,
|
|
3107
|
-
maxAttempts: BOOT_BACKOFF_MAX_ATTEMPTS
|
|
3521
|
+
maxAttempts: BOOT_BACKOFF_MAX_ATTEMPTS,
|
|
3522
|
+
clientsWaiting
|
|
3108
3523
|
});
|
|
3524
|
+
if (clientsWaiting && !loggedClientsWaitingBackoff) {
|
|
3525
|
+
const normalDecision = decideBootBackoff({
|
|
3526
|
+
load1m,
|
|
3527
|
+
cpuCount,
|
|
3528
|
+
starvationRatio,
|
|
3529
|
+
attempt,
|
|
3530
|
+
baseDelayMs: BOOT_BACKOFF_BASE_MS,
|
|
3531
|
+
maxDelayMs: BOOT_BACKOFF_MAX_MS,
|
|
3532
|
+
maxAttempts: BOOT_BACKOFF_MAX_ATTEMPTS
|
|
3533
|
+
});
|
|
3534
|
+
if (normalDecision.wait !== decision.wait || normalDecision.delayMs !== decision.delayMs || normalDecision.reason !== decision.reason) {
|
|
3535
|
+
process.stderr.write("[exed] Boot backoff: shortened because persisted MCP clients are waiting.\n");
|
|
3536
|
+
loggedClientsWaitingBackoff = true;
|
|
3537
|
+
}
|
|
3538
|
+
}
|
|
3109
3539
|
if (!decision.wait) {
|
|
3540
|
+
_bootReadyEtaMs = Date.now() + DB_INIT_ETA_MS;
|
|
3110
3541
|
if (decision.reason === "max_attempts_proceed") {
|
|
3111
3542
|
process.stderr.write(
|
|
3112
|
-
`[exed] Boot backoff: still starved after ${
|
|
3543
|
+
`[exed] Boot backoff: still starved after ${attempt} attempts \u2014 proceeding with DB init anyway.
|
|
3113
3544
|
`
|
|
3114
3545
|
);
|
|
3115
3546
|
logDaemonHealth({
|
|
3116
3547
|
event: "boot_backoff_starvation",
|
|
3117
3548
|
pid: process.pid,
|
|
3118
|
-
message: `boot backoff exhausted (${
|
|
3119
|
-
data: { load1m
|
|
3549
|
+
message: `boot backoff exhausted (${attempt} attempts) \u2014 proceeding`,
|
|
3550
|
+
data: { load1m, cpuCount, attempts: attempt }
|
|
3120
3551
|
});
|
|
3121
3552
|
}
|
|
3122
3553
|
break;
|
|
3123
3554
|
}
|
|
3124
|
-
const load1m = os2.loadavg()[0] ?? 0;
|
|
3125
|
-
const cpuCount = os2.cpus().length || 1;
|
|
3126
3555
|
process.stderr.write(
|
|
3127
3556
|
`[exed] Boot backoff: CPU starved (load=${load1m.toFixed(2)} cpus=${cpuCount}) \u2014 delaying DB init ${Math.round(decision.delayMs / 1e3)}s (attempt ${attempt + 1}/${BOOT_BACKOFF_MAX_ATTEMPTS}).
|
|
3128
3557
|
`
|
|
@@ -3133,6 +3562,7 @@ async function startMcpHttpServer() {
|
|
|
3133
3562
|
message: `boot delayed ${Math.round(decision.delayMs / 1e3)}s before DB init \u2014 CPU starved (load=${load1m.toFixed(2)} / cpus=${cpuCount})`,
|
|
3134
3563
|
data: { load1m, cpuCount, loadPerCore: load1m / cpuCount, delayMs: decision.delayMs, attempt }
|
|
3135
3564
|
});
|
|
3565
|
+
_bootReadyEtaMs = Date.now() + decision.delayMs + DB_INIT_ETA_MS;
|
|
3136
3566
|
await new Promise((resolve) => setTimeout(resolve, decision.delayMs));
|
|
3137
3567
|
}
|
|
3138
3568
|
}
|
|
@@ -3143,16 +3573,17 @@ async function startMcpHttpServer() {
|
|
|
3143
3573
|
"[exed] MCP HTTP: DB init failed \u2014 MCP HTTP endpoint will NOT start. Run 'exe-os setup' to fix keychain/encryption.\n"
|
|
3144
3574
|
);
|
|
3145
3575
|
if (_bootstrapServerRef) {
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3576
|
+
_bootstrapFailedReason = "db_init";
|
|
3577
|
+
process.stderr.write(
|
|
3578
|
+
"[exed] MCP HTTP: failed-health responder remains alive on the port so tooling can distinguish terminal DB init failure from startup.\n"
|
|
3579
|
+
);
|
|
3149
3580
|
}
|
|
3150
3581
|
return;
|
|
3151
3582
|
}
|
|
3152
3583
|
process.stderr.write("[exed] MCP HTTP: DB ready\n");
|
|
3153
3584
|
setBootPhase("db_ready");
|
|
3154
3585
|
_storeInitialized = true;
|
|
3155
|
-
const { initLicenseGate, getCachedLicenseGate } = await import("../license-gate-
|
|
3586
|
+
const { initLicenseGate, getCachedLicenseGate } = await import("../license-gate-3KPSNYVA.js");
|
|
3156
3587
|
const gateResult = await initLicenseGate();
|
|
3157
3588
|
if (!gateResult.hasKey) {
|
|
3158
3589
|
process.stderr.write(
|
|
@@ -3167,13 +3598,13 @@ async function startMcpHttpServer() {
|
|
|
3167
3598
|
let _cachedWrapTelemetry = null;
|
|
3168
3599
|
async function getWrapTelemetry() {
|
|
3169
3600
|
if (!_cachedWrapTelemetry) {
|
|
3170
|
-
const { wrapServerWithTelemetry } = await import("../tool-telemetry-
|
|
3601
|
+
const { wrapServerWithTelemetry } = await import("../tool-telemetry-4MF2HIWR.js");
|
|
3171
3602
|
_cachedWrapTelemetry = wrapServerWithTelemetry;
|
|
3172
3603
|
}
|
|
3173
3604
|
return _cachedWrapTelemetry;
|
|
3174
3605
|
}
|
|
3175
3606
|
Promise.all([
|
|
3176
|
-
import("../tool-capability-index-
|
|
3607
|
+
import("../tool-capability-index-QOFFCWDS.js"),
|
|
3177
3608
|
import("../tool-gates-3IC7DK4R.js")
|
|
3178
3609
|
]).then(async ([{ getToolCapabilityIndex }, { TOOL_CATEGORIES }]) => {
|
|
3179
3610
|
const gateState = getCachedLicenseGate();
|
|
@@ -3239,7 +3670,7 @@ async function startMcpHttpServer() {
|
|
|
3239
3670
|
const expectedBuf = Buffer.from(_daemonToken);
|
|
3240
3671
|
if (tokenBuf.length === expectedBuf.length && timingSafeEqual(tokenBuf, expectedBuf)) return true;
|
|
3241
3672
|
try {
|
|
3242
|
-
const { verifyAccessToken } = await import("../oauth-server-
|
|
3673
|
+
const { verifyAccessToken } = await import("../oauth-server-HPQCBLZQ.js");
|
|
3243
3674
|
const result = verifyAccessToken(token);
|
|
3244
3675
|
return result.valid;
|
|
3245
3676
|
} catch {
|
|
@@ -3248,28 +3679,28 @@ async function startMcpHttpServer() {
|
|
|
3248
3679
|
}
|
|
3249
3680
|
const pendingStaleSessionRecoveries = /* @__PURE__ */ new Map();
|
|
3250
3681
|
_mcpSessionDetailsRef = sessionDetails;
|
|
3682
|
+
_mcpSessionLastSeenRef = sessionLastSeen;
|
|
3251
3683
|
try {
|
|
3684
|
+
const { filterRestorableSessions, mcpSessionRestoreMaxAgeMs } = await import("../mcp-session-persist-PS7BIG44.js");
|
|
3252
3685
|
const sessPath = path3.join(EXE_AI_DIR, "mcp-sessions-persist.json");
|
|
3253
|
-
if (
|
|
3254
|
-
const raw =
|
|
3686
|
+
if (existsSync5(sessPath)) {
|
|
3687
|
+
const raw = readFileSync5(sessPath, "utf-8");
|
|
3255
3688
|
const saved = JSON.parse(raw);
|
|
3256
|
-
const MAX_AGE_MS =
|
|
3689
|
+
const MAX_AGE_MS = mcpSessionRestoreMaxAgeMs();
|
|
3257
3690
|
const now = Date.now();
|
|
3258
3691
|
let restored = 0;
|
|
3259
|
-
for (const s of saved) {
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
restored++;
|
|
3269
|
-
}
|
|
3692
|
+
for (const s of filterRestorableSessions(saved, now, MAX_AGE_MS)) {
|
|
3693
|
+
sessionLastSeen.set(s.sessionId, s.savedAt);
|
|
3694
|
+
sessionDetails.set(s.sessionId, {
|
|
3695
|
+
agentId: s.agentId,
|
|
3696
|
+
agentRole: s.agentRole,
|
|
3697
|
+
runtime: s.runtime,
|
|
3698
|
+
sessionHint: s.sessionHint
|
|
3699
|
+
});
|
|
3700
|
+
restored++;
|
|
3270
3701
|
}
|
|
3271
3702
|
try {
|
|
3272
|
-
|
|
3703
|
+
unlinkSync3(sessPath);
|
|
3273
3704
|
} catch {
|
|
3274
3705
|
}
|
|
3275
3706
|
if (restored > 0) {
|
|
@@ -3492,7 +3923,7 @@ async function startMcpHttpServer() {
|
|
|
3492
3923
|
return;
|
|
3493
3924
|
}
|
|
3494
3925
|
try {
|
|
3495
|
-
const { handleOAuthRoute } = await import("../oauth-server-
|
|
3926
|
+
const { handleOAuthRoute } = await import("../oauth-server-HPQCBLZQ.js");
|
|
3496
3927
|
const handled = await handleOAuthRoute(req, res, url, MCP_HTTP_PORT);
|
|
3497
3928
|
if (handled) return;
|
|
3498
3929
|
} catch (err) {
|
|
@@ -3524,7 +3955,7 @@ async function startMcpHttpServer() {
|
|
|
3524
3955
|
for await (const chunk of req) chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
|
|
3525
3956
|
const rawBody = Buffer.concat(chunks);
|
|
3526
3957
|
try {
|
|
3527
|
-
const { loadWebhookConfig, verifyHmac, processWebhook } = await import("../webhook-pipe-
|
|
3958
|
+
const { loadWebhookConfig, verifyHmac, processWebhook } = await import("../webhook-pipe-HH7XXXYC.js");
|
|
3528
3959
|
const webhookConfig = await loadWebhookConfig();
|
|
3529
3960
|
const serviceConfig = webhookConfig[serviceName];
|
|
3530
3961
|
if (!serviceConfig) {
|
|
@@ -3620,7 +4051,7 @@ async function startMcpHttpServer() {
|
|
|
3620
4051
|
contextPct: body.context_pct
|
|
3621
4052
|
});
|
|
3622
4053
|
if (body.context_pct !== void 0 && body.context_pct > 70) {
|
|
3623
|
-
void import("../orchestration-events-
|
|
4054
|
+
void import("../orchestration-events-5XDNVNR2.js").then(({ recordOrchestrationEventBestEffort: recordOE }) => {
|
|
3624
4055
|
recordOE({
|
|
3625
4056
|
eventType: "context.pressure",
|
|
3626
4057
|
source: "exe-daemon.heartbeat",
|
|
@@ -3705,7 +4136,7 @@ async function startMcpHttpServer() {
|
|
|
3705
4136
|
let sessionHint = req.headers["x-exe-session-name"] || req.headers["x-exe-session"] || "";
|
|
3706
4137
|
if (sessionHint) {
|
|
3707
4138
|
try {
|
|
3708
|
-
const { sanitizeSessionHintHeader, rejectForgedSessionHint } = await import("../mcp-session-identity-
|
|
4139
|
+
const { sanitizeSessionHintHeader, rejectForgedSessionHint } = await import("../mcp-session-identity-S7GSVRR6.js");
|
|
3709
4140
|
const rawHint = sessionHint;
|
|
3710
4141
|
sessionHint = sanitizeSessionHintHeader(sessionHint);
|
|
3711
4142
|
if (!sessionHint) {
|
|
@@ -3740,7 +4171,7 @@ async function startMcpHttpServer() {
|
|
|
3740
4171
|
try {
|
|
3741
4172
|
const liveSessions = await getTmuxSessionsAsync();
|
|
3742
4173
|
const paneCommands = await getPaneCommandsAsync();
|
|
3743
|
-
const { resolveMcpSessionHint } = await import("../mcp-session-identity-
|
|
4174
|
+
const { resolveMcpSessionHint } = await import("../mcp-session-identity-S7GSVRR6.js");
|
|
3744
4175
|
let registrySessions = [];
|
|
3745
4176
|
try {
|
|
3746
4177
|
const { listSessions: listRegistrySessions } = await import("./session-registry.js");
|
|
@@ -3876,7 +4307,7 @@ async function startMcpHttpServer() {
|
|
|
3876
4307
|
bindLive = await getTmuxSessionsAsync();
|
|
3877
4308
|
} catch {
|
|
3878
4309
|
}
|
|
3879
|
-
const { isLauncherCorroboratedIdentity } = await import("../mcp-session-identity-
|
|
4310
|
+
const { isLauncherCorroboratedIdentity } = await import("../mcp-session-identity-S7GSVRR6.js");
|
|
3880
4311
|
const corroborated = isLauncherCorroboratedIdentity({
|
|
3881
4312
|
agentId,
|
|
3882
4313
|
registrySessions: bindRegistry,
|
|
@@ -4119,7 +4550,7 @@ async function startMcpHttpServer() {
|
|
|
4119
4550
|
}
|
|
4120
4551
|
}
|
|
4121
4552
|
try {
|
|
4122
|
-
const { reconcileHintWithRegistryIdentity } = await import("../mcp-session-identity-
|
|
4553
|
+
const { reconcileHintWithRegistryIdentity } = await import("../mcp-session-identity-S7GSVRR6.js");
|
|
4123
4554
|
const { listSessions: listRegistrySessions } = await import("./session-registry.js");
|
|
4124
4555
|
const recon = reconcileHintWithRegistryIdentity({
|
|
4125
4556
|
agentId,
|
|
@@ -4257,7 +4688,7 @@ async function startMcpHttpServer() {
|
|
|
4257
4688
|
`);
|
|
4258
4689
|
_boundMcpPort = MCP_HTTP_PORT;
|
|
4259
4690
|
writeDaemonReady({ pid: process.pid, port: MCP_HTTP_PORT });
|
|
4260
|
-
void import("../mcp-port-config-
|
|
4691
|
+
void import("../mcp-port-config-PA3W3BJK.js").then(({ persistMcpPortToConfig }) => persistMcpPortToConfig(String(MCP_HTTP_PORT))).catch(() => {
|
|
4261
4692
|
});
|
|
4262
4693
|
recordMcpHttpEvent({
|
|
4263
4694
|
level: "info",
|
|
@@ -4316,9 +4747,9 @@ async function ensureStoreForPolling() {
|
|
|
4316
4747
|
await initDatabase({ dbPath: config.dbPath, encryptionKey: masterKey.toString("hex") });
|
|
4317
4748
|
await ensureSchema();
|
|
4318
4749
|
try {
|
|
4319
|
-
const { isLedgerEnabled } = await import("../notification-ledger-
|
|
4750
|
+
const { isLedgerEnabled } = await import("../notification-ledger-A6MYLQAN.js");
|
|
4320
4751
|
if (isLedgerEnabled()) {
|
|
4321
|
-
const { bumpBootGeneration } = await import("../boot-generation-
|
|
4752
|
+
const { bumpBootGeneration } = await import("../boot-generation-CFA5NKSK.js");
|
|
4322
4753
|
const { setDaemonReadyGeneration } = await import("../daemon-ready-signal-LPAZWQOV.js");
|
|
4323
4754
|
const generation = await bumpBootGeneration();
|
|
4324
4755
|
setDaemonReadyGeneration(generation);
|
|
@@ -4332,8 +4763,18 @@ async function ensureStoreForPolling() {
|
|
|
4332
4763
|
try {
|
|
4333
4764
|
const { spawnDbReadWorker } = await import("./db-read-worker-client.js");
|
|
4334
4765
|
spawnDbReadWorker(config.dbPath, masterKey.toString("hex"));
|
|
4766
|
+
const { registerBackupOffload } = await import("./db-backup.js");
|
|
4767
|
+
registerBackupOffload({ dbPath: config.dbPath, encryptionKeyHex: masterKey.toString("hex") });
|
|
4335
4768
|
} catch (e) {
|
|
4336
4769
|
process.stderr.write(`[exed] DB read worker spawn failed (non-fatal): ${e instanceof Error ? e.message : String(e)}
|
|
4770
|
+
`);
|
|
4771
|
+
}
|
|
4772
|
+
try {
|
|
4773
|
+
if (isWriteWorkerEnabled()) {
|
|
4774
|
+
spawnDbWriteWorker(config.dbPath, masterKey.toString("hex"));
|
|
4775
|
+
}
|
|
4776
|
+
} catch (e) {
|
|
4777
|
+
process.stderr.write(`[exed] DB write worker spawn failed (non-fatal): ${e instanceof Error ? e.message : String(e)}
|
|
4337
4778
|
`);
|
|
4338
4779
|
}
|
|
4339
4780
|
}
|
|
@@ -4348,13 +4789,13 @@ async function ensureStoreForPolling() {
|
|
|
4348
4789
|
}
|
|
4349
4790
|
}
|
|
4350
4791
|
async function startReviewPolling() {
|
|
4351
|
-
const polling = await import("../review-polling-
|
|
4792
|
+
const polling = await import("../review-polling-DLPMK3QW.js");
|
|
4352
4793
|
const state = {
|
|
4353
4794
|
lastIntercomSent: /* @__PURE__ */ new Map(),
|
|
4354
4795
|
lastNudgeSent: /* @__PURE__ */ new Map(),
|
|
4355
4796
|
intervalMs: REVIEW_POLL_INTERVAL_MS
|
|
4356
4797
|
};
|
|
4357
|
-
const { pollReviewNudge, createReviewNudgeRealDeps, loadNudgeState } = await import("../daemon-orchestration-
|
|
4798
|
+
const { pollReviewNudge, createReviewNudgeRealDeps, loadNudgeState } = await import("../daemon-orchestration-GGSRCXR3.js");
|
|
4358
4799
|
const nudgeState = loadNudgeState();
|
|
4359
4800
|
const tick = async () => traceDaemonTimer("review_polling", async () => {
|
|
4360
4801
|
fired("review_polling");
|
|
@@ -4400,7 +4841,7 @@ function startSessionTTL() {
|
|
|
4400
4841
|
if (!await ensureStoreForPolling()) return;
|
|
4401
4842
|
if (inPostRestartDestructiveGrace("session_ttl")) return;
|
|
4402
4843
|
const { getClient } = await import("./database.js");
|
|
4403
|
-
const { checkSessionTTL, createSessionTTLRealDeps } = await import("../daemon-orchestration-
|
|
4844
|
+
const { checkSessionTTL, createSessionTTLRealDeps } = await import("../daemon-orchestration-GGSRCXR3.js");
|
|
4404
4845
|
const deps = createSessionTTLRealDeps(getClient);
|
|
4405
4846
|
const killed = await checkSessionTTL(deps, _wedgeObservations);
|
|
4406
4847
|
if (killed.length > 0) acted("session_ttl");
|
|
@@ -4426,7 +4867,7 @@ function startIdleKill() {
|
|
|
4426
4867
|
if (inPostRestartDestructiveGrace("idle_kill")) return;
|
|
4427
4868
|
try {
|
|
4428
4869
|
const signalDir = path3.join(os2.homedir(), ".exe-os", "task-signals");
|
|
4429
|
-
if (
|
|
4870
|
+
if (existsSync5(signalDir)) {
|
|
4430
4871
|
const files = (await import("fs")).readdirSync(signalDir).filter((f) => f.endsWith(".terminate"));
|
|
4431
4872
|
for (const file of files) {
|
|
4432
4873
|
const agentId = file.replace(".terminate", "");
|
|
@@ -4440,9 +4881,9 @@ function startIdleKill() {
|
|
|
4440
4881
|
`);
|
|
4441
4882
|
acted("idle_kill");
|
|
4442
4883
|
}
|
|
4443
|
-
|
|
4884
|
+
unlinkSync3(signalPath);
|
|
4444
4885
|
} catch {
|
|
4445
|
-
|
|
4886
|
+
unlinkSync3(signalPath);
|
|
4446
4887
|
}
|
|
4447
4888
|
}
|
|
4448
4889
|
}
|
|
@@ -4452,7 +4893,7 @@ function startIdleKill() {
|
|
|
4452
4893
|
const cfg = await getCachedConfig();
|
|
4453
4894
|
if (!cfg) return;
|
|
4454
4895
|
const { getClient } = await import("./database.js");
|
|
4455
|
-
const { pollIdleKill, createIdleKillRealDeps } = await import("../daemon-orchestration-
|
|
4896
|
+
const { pollIdleKill, createIdleKillRealDeps } = await import("../daemon-orchestration-GGSRCXR3.js");
|
|
4456
4897
|
const { sessions: liveSessions, paneCache, aliveSessions } = await getSharedOrchestrationCaches();
|
|
4457
4898
|
const realDeps = createIdleKillRealDeps(
|
|
4458
4899
|
getClient,
|
|
@@ -4525,7 +4966,7 @@ function startConsolidation() {
|
|
|
4525
4966
|
`);
|
|
4526
4967
|
}
|
|
4527
4968
|
try {
|
|
4528
|
-
const { createBackupAsync, enforceRetention } = await import("
|
|
4969
|
+
const { createBackupAsync, enforceRetention } = await import("./db-backup.js");
|
|
4529
4970
|
const p = await createBackupAsync("pre-consolidation");
|
|
4530
4971
|
if (p) enforceRetention("pre-consolidation");
|
|
4531
4972
|
} catch (e) {
|
|
@@ -4758,7 +5199,7 @@ function startSkillRefinement() {
|
|
|
4758
5199
|
if (!shouldRunHeavyJob("skill_refinement")) return;
|
|
4759
5200
|
try {
|
|
4760
5201
|
if (!await ensureStoreForPolling()) return;
|
|
4761
|
-
const { runSkillRefinement } = await import("../skill-refinement-
|
|
5202
|
+
const { runSkillRefinement } = await import("../skill-refinement-ACXLAK2G.js");
|
|
4762
5203
|
const result = await runSkillRefinement();
|
|
4763
5204
|
if (result.reviewed > 0) {
|
|
4764
5205
|
acted("skill_refinement");
|
|
@@ -4784,8 +5225,8 @@ function startStaleBranchSweep() {
|
|
|
4784
5225
|
const tick = async () => {
|
|
4785
5226
|
fired("stale_branch_sweep");
|
|
4786
5227
|
try {
|
|
4787
|
-
const { discoverRepoPaths } = await import("../worktree-sweep-
|
|
4788
|
-
const { scanUnmergedBranchesCached } = await import("../branch-hygiene-
|
|
5228
|
+
const { discoverRepoPaths } = await import("../worktree-sweep-VSL7TRQK.js");
|
|
5229
|
+
const { scanUnmergedBranchesCached } = await import("../branch-hygiene-PILXQQDF.js");
|
|
4789
5230
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
4790
5231
|
for (const k of _staleBranchAlertedToday) {
|
|
4791
5232
|
if (!k.endsWith(today)) _staleBranchAlertedToday.delete(k);
|
|
@@ -4816,7 +5257,7 @@ function startStaleBranchSweep() {
|
|
|
4816
5257
|
if (!_storeInitialized) continue;
|
|
4817
5258
|
const stale = scan.branches.filter((b) => b.ageHours >= STALE_BRANCH_HOURS).slice(0, 5).map((b) => `${b.name} (+${b.ahead} commits, ${(b.ageHours / 24).toFixed(1)}d)`).join("; ");
|
|
4818
5259
|
try {
|
|
4819
|
-
const { writeNotification } = await import("../notifications-
|
|
5260
|
+
const { writeNotification } = await import("../notifications-6XCSUTJW.js");
|
|
4820
5261
|
await writeNotification({
|
|
4821
5262
|
agentId: "exe",
|
|
4822
5263
|
agentRole: "system",
|
|
@@ -5273,14 +5714,14 @@ function startReflectionSweep() {
|
|
|
5273
5714
|
);
|
|
5274
5715
|
let runReflection;
|
|
5275
5716
|
try {
|
|
5276
|
-
({ runReflection } = await import("../memory-reflection-
|
|
5717
|
+
({ runReflection } = await import("../memory-reflection-3VPYJS2G.js"));
|
|
5277
5718
|
} catch (importErr) {
|
|
5278
5719
|
_reflectionImportFailed = true;
|
|
5279
5720
|
process.stderr.write(`[exed] Reflection module unavailable (stale chunk hash?) \u2014 disabled until daemon restart: ${importErr instanceof Error ? importErr.message : String(importErr)}
|
|
5280
5721
|
`);
|
|
5281
5722
|
return;
|
|
5282
5723
|
}
|
|
5283
|
-
const { runBudgetedSweep } = await import("../sweep-budget-
|
|
5724
|
+
const { runBudgetedSweep } = await import("../sweep-budget-LQYBMDTK.js");
|
|
5284
5725
|
let totalInsights = 0;
|
|
5285
5726
|
await runBudgetedSweep(
|
|
5286
5727
|
agents.rows,
|
|
@@ -5314,7 +5755,7 @@ function startReflectionSweep() {
|
|
|
5314
5755
|
if (memories > 100 && cards < memories * 0.1) {
|
|
5315
5756
|
process.stderr.write(`[exed] Memory cards sparse (${cards} cards / ${memories} memories) \u2014 running backfill...
|
|
5316
5757
|
`);
|
|
5317
|
-
const { insertMemoryCardsForBatch } = await import("../memory-cards-
|
|
5758
|
+
const { insertMemoryCardsForBatch } = await import("../memory-cards-47NYPFC3.js");
|
|
5318
5759
|
const batchSize = 500;
|
|
5319
5760
|
let offset = 0;
|
|
5320
5761
|
let totalCards = 0;
|
|
@@ -5359,7 +5800,7 @@ function startDatabaseBackup() {
|
|
|
5359
5800
|
const tick = async () => {
|
|
5360
5801
|
fired("db_backup");
|
|
5361
5802
|
try {
|
|
5362
|
-
const { createBackupAsync, enforceRetention, hasBackupToday, hasRecentBackup } = await import("
|
|
5803
|
+
const { createBackupAsync, enforceRetention, hasBackupToday, hasRecentBackup } = await import("./db-backup.js");
|
|
5363
5804
|
if (!hasRecentBackup("guaranteed", DB_BACKUP_TARGET_WINDOW_MS)) {
|
|
5364
5805
|
const guaranteedPath = await createBackupAsync("guaranteed");
|
|
5365
5806
|
if (guaranteedPath) {
|
|
@@ -5382,7 +5823,7 @@ function startDatabaseBackup() {
|
|
|
5382
5823
|
`
|
|
5383
5824
|
);
|
|
5384
5825
|
try {
|
|
5385
|
-
const { maybeVerifyDailyBackup } = await import("../backup-verify-
|
|
5826
|
+
const { maybeVerifyDailyBackup } = await import("../backup-verify-KDLOT4RP.js");
|
|
5386
5827
|
const verdict = await maybeVerifyDailyBackup(backupPath);
|
|
5387
5828
|
if (verdict && !verdict.ok) {
|
|
5388
5829
|
process.stderr.write(
|
|
@@ -5459,7 +5900,7 @@ function startSessionEventsRetention() {
|
|
|
5459
5900
|
if (!await ensureStoreForPolling()) return;
|
|
5460
5901
|
try {
|
|
5461
5902
|
const { getClient } = await import("./database.js");
|
|
5462
|
-
const { sweepExpiredSessionEvents, DEFAULT_SESSION_EVENTS_RETENTION_DAYS } = await import("../session-events-
|
|
5903
|
+
const { sweepExpiredSessionEvents, DEFAULT_SESSION_EVENTS_RETENTION_DAYS } = await import("../session-events-N5VRC6IT.js");
|
|
5463
5904
|
const days = SESSION_EVENTS_RETENTION_DAYS ?? DEFAULT_SESSION_EVENTS_RETENTION_DAYS;
|
|
5464
5905
|
const count = await sweepExpiredSessionEvents(getClient(), days);
|
|
5465
5906
|
if (count > 0) {
|
|
@@ -5490,7 +5931,7 @@ function startIntercomQueueDrain() {
|
|
|
5490
5931
|
const tick = async () => traceDaemonTimer("intercom_queue_drain", async () => {
|
|
5491
5932
|
fired("intercom_queue_drain");
|
|
5492
5933
|
try {
|
|
5493
|
-
const { drainQueueAsync, readQueue } = await import("../intercom-queue-
|
|
5934
|
+
const { drainQueueAsync, readQueue } = await import("../intercom-queue-NFOLOBTT.js");
|
|
5494
5935
|
const {
|
|
5495
5936
|
sendIntercomAsync: centralSendIntercomAsync,
|
|
5496
5937
|
countScopedPendingReviews,
|
|
@@ -5622,7 +6063,7 @@ function startLedgerDrain() {
|
|
|
5622
6063
|
const tick = async () => traceDaemonTimer("ledger_drain", async () => {
|
|
5623
6064
|
fired("ledger_drain");
|
|
5624
6065
|
try {
|
|
5625
|
-
const { isLedgerEnabled, drainLedger } = await import("../notification-ledger-
|
|
6066
|
+
const { isLedgerEnabled, drainLedger } = await import("../notification-ledger-A6MYLQAN.js");
|
|
5626
6067
|
if (!isLedgerEnabled()) return;
|
|
5627
6068
|
const result = await drainLedger({
|
|
5628
6069
|
// Shadow "would-deliver": idle target = would-deliver, busy = retry.
|
|
@@ -5661,7 +6102,7 @@ function startOrphanReaper() {
|
|
|
5661
6102
|
const tick = async () => traceDaemonTimer("orphan_reaper", async () => {
|
|
5662
6103
|
fired("orphan_reaper");
|
|
5663
6104
|
try {
|
|
5664
|
-
const { reapOrphanedMcpProcesses, createOrphanReaperRealDepsAsync } = await import("../daemon-orchestration-
|
|
6105
|
+
const { reapOrphanedMcpProcesses, createOrphanReaperRealDepsAsync } = await import("../daemon-orchestration-GGSRCXR3.js");
|
|
5665
6106
|
const deps = await createOrphanReaperRealDepsAsync();
|
|
5666
6107
|
const reaped = await reapOrphanedMcpProcesses(deps);
|
|
5667
6108
|
if (reaped.length > 0) acted("orphan_reaper");
|
|
@@ -5686,7 +6127,7 @@ function startZombieAgentReaper() {
|
|
|
5686
6127
|
const tick = async () => traceDaemonTimer("zombie_agent_reaper", async () => {
|
|
5687
6128
|
fired("zombie_agent_reaper");
|
|
5688
6129
|
try {
|
|
5689
|
-
const { reapZombieAgentProcesses, createZombieAgentReaperRealDepsAsync } = await import("../daemon-orchestration-
|
|
6130
|
+
const { reapZombieAgentProcesses, createZombieAgentReaperRealDepsAsync } = await import("../daemon-orchestration-GGSRCXR3.js");
|
|
5690
6131
|
const deps = await createZombieAgentReaperRealDepsAsync();
|
|
5691
6132
|
const reaped = reapZombieAgentProcesses(deps);
|
|
5692
6133
|
if (reaped.length > 0) acted("zombie_agent_reaper");
|
|
@@ -5710,7 +6151,7 @@ async function startDaemonMemoryPressureWatchdog() {
|
|
|
5710
6151
|
try {
|
|
5711
6152
|
const cfg = await getCachedConfig();
|
|
5712
6153
|
if (!cfg) return;
|
|
5713
|
-
const { startMemoryPressureWatchdog: startWatchdog, MEMORY_PRESSURE_WATCHDOG_DEFAULTS } = await import("../memory-pressure-watchdog-
|
|
6154
|
+
const { startMemoryPressureWatchdog: startWatchdog, MEMORY_PRESSURE_WATCHDOG_DEFAULTS } = await import("../memory-pressure-watchdog-PSVJ5BCF.js");
|
|
5714
6155
|
const watchdogCfg = {
|
|
5715
6156
|
...MEMORY_PRESSURE_WATCHDOG_DEFAULTS,
|
|
5716
6157
|
...cfg.memoryPressureWatchdog ?? {}
|
|
@@ -5741,7 +6182,7 @@ function startWorktreeReaper() {
|
|
|
5741
6182
|
const tick = async () => traceDaemonTimer("worktree_reaper", async () => {
|
|
5742
6183
|
fired("worktree_reaper");
|
|
5743
6184
|
try {
|
|
5744
|
-
const { reapOrphanedWorktrees, createWorktreeReaperRealDeps } = await import("../daemon-orchestration-
|
|
6185
|
+
const { reapOrphanedWorktrees, createWorktreeReaperRealDeps } = await import("../daemon-orchestration-GGSRCXR3.js");
|
|
5745
6186
|
const deps = await createWorktreeReaperRealDeps();
|
|
5746
6187
|
const result = await reapOrphanedWorktrees(deps);
|
|
5747
6188
|
if (result.pruned.length > 0) {
|
|
@@ -5781,8 +6222,8 @@ function startWorktreeReaper() {
|
|
|
5781
6222
|
}
|
|
5782
6223
|
continue;
|
|
5783
6224
|
}
|
|
5784
|
-
const { cleanupAgentWorktree } = await import("../worktree-sweep-
|
|
5785
|
-
const { getMainRepoRootAsync } = await import("../worktree-
|
|
6225
|
+
const { cleanupAgentWorktree } = await import("../worktree-sweep-VSL7TRQK.js");
|
|
6226
|
+
const { getMainRepoRootAsync } = await import("../worktree-VDCY44ZP.js");
|
|
5786
6227
|
const repoRoot = await getMainRepoRootAsync(signal.worktreePath);
|
|
5787
6228
|
if (repoRoot && signal.agentId) {
|
|
5788
6229
|
const notes = await cleanupAgentWorktree(repoRoot, signal.agentId);
|
|
@@ -5815,7 +6256,7 @@ function startAutoWake() {
|
|
|
5815
6256
|
if (!await ensureStoreForPolling()) return;
|
|
5816
6257
|
try {
|
|
5817
6258
|
const { getClient } = await import("./database.js");
|
|
5818
|
-
const { pollOrphanedTasks, createAutoWakeRealDeps } = await import("../daemon-orchestration-
|
|
6259
|
+
const { pollOrphanedTasks, createAutoWakeRealDeps } = await import("../daemon-orchestration-GGSRCXR3.js");
|
|
5819
6260
|
const deps = createAutoWakeRealDeps(getClient, process.cwd(), getTmuxSessionsAsync);
|
|
5820
6261
|
const woken = await pollOrphanedTasks(deps);
|
|
5821
6262
|
if (woken.length > 0) acted("auto_wake");
|
|
@@ -5825,7 +6266,7 @@ function startAutoWake() {
|
|
|
5825
6266
|
}
|
|
5826
6267
|
try {
|
|
5827
6268
|
const signalBase = path3.join(os2.homedir(), ".exe-os", "task-signals");
|
|
5828
|
-
if (
|
|
6269
|
+
if (existsSync5(signalBase)) {
|
|
5829
6270
|
const { readdirSync: readdirSync2, statSync: statSyncFs } = await import("fs");
|
|
5830
6271
|
const { sendIntercomAsync, extractRootExe } = await import("./tmux-routing.js");
|
|
5831
6272
|
const sessionCache = path3.join(os2.homedir(), ".exe-os", "session-cache");
|
|
@@ -5841,11 +6282,11 @@ function startAutoWake() {
|
|
|
5841
6282
|
if (cached && Date.now() - cached.ts < 3e4) return cached.runtime;
|
|
5842
6283
|
try {
|
|
5843
6284
|
const dispatchInfoPath = path3.join(sessionCache, `dispatch-info-${sessionName}.json`);
|
|
5844
|
-
if (!
|
|
6285
|
+
if (!existsSync5(dispatchInfoPath)) {
|
|
5845
6286
|
_runtimeCache.set(sessionName, { runtime: "claude", ts: Date.now() });
|
|
5846
6287
|
return "claude";
|
|
5847
6288
|
}
|
|
5848
|
-
const raw = JSON.parse(
|
|
6289
|
+
const raw = JSON.parse(readFileSync5(dispatchInfoPath, "utf8"));
|
|
5849
6290
|
const rt = raw.runtime ?? "claude";
|
|
5850
6291
|
_runtimeCache.set(sessionName, { runtime: rt, ts: Date.now() });
|
|
5851
6292
|
return rt;
|
|
@@ -5865,8 +6306,8 @@ function startAutoWake() {
|
|
|
5865
6306
|
const age = Date.now() - statSyncFs(signalPath).mtimeMs;
|
|
5866
6307
|
if (age > 60 * 60 * 1e3) {
|
|
5867
6308
|
try {
|
|
5868
|
-
|
|
5869
|
-
void import("../orchestration-events-
|
|
6309
|
+
unlinkSync3(signalPath);
|
|
6310
|
+
void import("../orchestration-events-5XDNVNR2.js").then(({ recordOrchestrationEventBestEffort: recordOE }) => {
|
|
5870
6311
|
recordOE({ eventType: "signal.stale", source: "exe-daemon.autoWake", severity: "warn", payload: { file, ageMinutes: Math.round(age / 6e4) } });
|
|
5871
6312
|
}).catch(() => {
|
|
5872
6313
|
});
|
|
@@ -5934,7 +6375,7 @@ function startWalCheckpoint() {
|
|
|
5934
6375
|
try {
|
|
5935
6376
|
const { getClient, runWalCheckpoint } = await import("./database.js");
|
|
5936
6377
|
const client = getClient();
|
|
5937
|
-
const { findActiveDb } = await import("
|
|
6378
|
+
const { findActiveDb } = await import("./db-backup.js");
|
|
5938
6379
|
const dbPath = findActiveDb();
|
|
5939
6380
|
const started = Date.now();
|
|
5940
6381
|
const result = await runWalCheckpoint(client, dbPath, true);
|
|
@@ -6012,7 +6453,7 @@ function startStuckTaskRelease() {
|
|
|
6012
6453
|
createStuckTaskRealDeps,
|
|
6013
6454
|
escalateStuckBlockedTasks,
|
|
6014
6455
|
createStuckBlockedRealDeps
|
|
6015
|
-
} = await import("../daemon-orchestration-
|
|
6456
|
+
} = await import("../daemon-orchestration-GGSRCXR3.js");
|
|
6016
6457
|
const deps = createStuckTaskRealDeps(getClient);
|
|
6017
6458
|
const released = await releaseStuckTasks(deps);
|
|
6018
6459
|
if (released.length > 0) {
|
|
@@ -6207,12 +6648,12 @@ function startTaskEnforcementScanner() {
|
|
|
6207
6648
|
const tick = async () => traceDaemonTimer("task_enforcement", async () => {
|
|
6208
6649
|
fired("task_enforcement");
|
|
6209
6650
|
try {
|
|
6210
|
-
const { runTaskEnforcementTick } = await import("../task-enforcement-
|
|
6651
|
+
const { runTaskEnforcementTick } = await import("../task-enforcement-C7MMJTKX.js");
|
|
6211
6652
|
const { getTransport } = await import("./transport.js");
|
|
6212
6653
|
const { loadAgentConfig } = await import("./agent-config.js");
|
|
6213
6654
|
const { getClient } = await import("./database.js");
|
|
6214
6655
|
const { loadEmployeesSync } = await import("./employees.js");
|
|
6215
|
-
const { sessionScopeFilter } = await import("../task-scope-
|
|
6656
|
+
const { sessionScopeFilter } = await import("../task-scope-DK666AKV.js");
|
|
6216
6657
|
const transport = getTransport();
|
|
6217
6658
|
const { sessions: allSessions, paneCache, aliveSessions } = await getSharedOrchestrationCaches();
|
|
6218
6659
|
await yieldToEventLoop();
|
|
@@ -6223,10 +6664,10 @@ function startTaskEnforcementScanner() {
|
|
|
6223
6664
|
sendKeysLiteral: transport.sendKeysLiteral?.bind(transport),
|
|
6224
6665
|
isAlive: (session) => aliveSessions.has(session)
|
|
6225
6666
|
};
|
|
6226
|
-
const { checkAutoWakeGates } = await import("../daemon-orchestration-
|
|
6667
|
+
const { checkAutoWakeGates } = await import("../daemon-orchestration-GGSRCXR3.js");
|
|
6227
6668
|
const { ensureEmployeeAsync, employeeSessionName, sendIntercomAsync } = await import("./tmux-routing.js");
|
|
6228
6669
|
const { shouldAutoInstance } = await import("./employees.js");
|
|
6229
|
-
const { recordOrchestrationEventBestEffort } = await import("../orchestration-events-
|
|
6670
|
+
const { recordOrchestrationEventBestEffort } = await import("../orchestration-events-5XDNVNR2.js");
|
|
6230
6671
|
const projectDir = process.cwd();
|
|
6231
6672
|
await runTaskEnforcementTick({
|
|
6232
6673
|
transport: enforcementTransport,
|
|
@@ -6360,8 +6801,8 @@ function startRssWatchdog() {
|
|
|
6360
6801
|
`
|
|
6361
6802
|
);
|
|
6362
6803
|
try {
|
|
6363
|
-
|
|
6364
|
-
|
|
6804
|
+
mkdirSync3(path3.dirname(OOM_MARKER_PATH), { recursive: true });
|
|
6805
|
+
writeFileSync4(OOM_MARKER_PATH, `RSS=${(effectiveRss / 1024 / 1024).toFixed(0)}MB at ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
6365
6806
|
`);
|
|
6366
6807
|
process.stderr.write(`[exed] Wrote OOM marker at ${OOM_MARKER_PATH}
|
|
6367
6808
|
`);
|
|
@@ -6475,14 +6916,14 @@ function startApiWatchdog() {
|
|
|
6475
6916
|
process.stderr.write(`[exed] API watchdog nudged ${session} (attempt ${nudgeCount}/3, matched: ${matchedPattern.source})
|
|
6476
6917
|
`);
|
|
6477
6918
|
try {
|
|
6478
|
-
const { appendFileSync, mkdirSync:
|
|
6479
|
-
const { join:
|
|
6480
|
-
const logDir =
|
|
6919
|
+
const { appendFileSync, mkdirSync: mkdirSync4, statSync: statSyncFs, renameSync: renameSyncFs } = await import("fs");
|
|
6920
|
+
const { join: join3 } = await import("path");
|
|
6921
|
+
const logDir = join3(process.env.EXE_OS_DIR ?? join3(process.env.HOME ?? "", ".exe-os"), "logs");
|
|
6481
6922
|
try {
|
|
6482
|
-
|
|
6923
|
+
mkdirSync4(logDir, { recursive: true });
|
|
6483
6924
|
} catch {
|
|
6484
6925
|
}
|
|
6485
|
-
const watchdogLogPath =
|
|
6926
|
+
const watchdogLogPath = join3(logDir, "api-watchdog.jsonl");
|
|
6486
6927
|
try {
|
|
6487
6928
|
const wStat = statSyncFs(watchdogLogPath);
|
|
6488
6929
|
if (wStat.size > 5 * 1024 * 1024) renameSyncFs(watchdogLogPath, watchdogLogPath + ".1");
|
|
@@ -6518,7 +6959,7 @@ function startBackgroundJobGuardrails() {
|
|
|
6518
6959
|
const tick = async () => traceDaemonTimer("background_job_guardrails", async () => {
|
|
6519
6960
|
fired("background_job_guardrails");
|
|
6520
6961
|
try {
|
|
6521
|
-
const { enforceBackgroundJobGuardrailsAsync } = await import("../background-jobs-
|
|
6962
|
+
const { enforceBackgroundJobGuardrailsAsync } = await import("../background-jobs-KKRO3QRO.js");
|
|
6522
6963
|
const actions = await enforceBackgroundJobGuardrailsAsync();
|
|
6523
6964
|
if (actions.length > 0) {
|
|
6524
6965
|
acted("background_job_guardrails");
|
|
@@ -6709,18 +7150,18 @@ process.on("uncaughtException", (err) => {
|
|
|
6709
7150
|
} catch {
|
|
6710
7151
|
}
|
|
6711
7152
|
try {
|
|
6712
|
-
|
|
7153
|
+
unlinkSync3(SOCKET_PATH);
|
|
6713
7154
|
} catch (_) {
|
|
6714
7155
|
}
|
|
6715
7156
|
try {
|
|
6716
|
-
|
|
7157
|
+
unlinkSync3(PID_PATH);
|
|
6717
7158
|
} catch (_) {
|
|
6718
7159
|
}
|
|
6719
7160
|
setTimeout(() => process.exit(1), 3e3);
|
|
6720
7161
|
});
|
|
6721
7162
|
function readProcEnviron(pid) {
|
|
6722
7163
|
try {
|
|
6723
|
-
const raw =
|
|
7164
|
+
const raw = readFileSync5(`/proc/${pid}/environ`, "utf8");
|
|
6724
7165
|
const env = {};
|
|
6725
7166
|
for (const part of raw.split("\0")) {
|
|
6726
7167
|
const idx = part.indexOf("=");
|
|
@@ -6773,18 +7214,18 @@ function killOrphanDaemons() {
|
|
|
6773
7214
|
}
|
|
6774
7215
|
function checkExistingDaemon() {
|
|
6775
7216
|
try {
|
|
6776
|
-
if (!
|
|
7217
|
+
if (!existsSync5(PID_PATH)) {
|
|
6777
7218
|
killOrphanDaemons();
|
|
6778
7219
|
return false;
|
|
6779
7220
|
}
|
|
6780
|
-
const pid = parseInt(
|
|
7221
|
+
const pid = parseInt(readFileSync5(PID_PATH, "utf8").trim(), 10);
|
|
6781
7222
|
if (!pid || isNaN(pid)) {
|
|
6782
7223
|
killOrphanDaemons();
|
|
6783
7224
|
return false;
|
|
6784
7225
|
}
|
|
6785
7226
|
if (pid === process.pid) {
|
|
6786
7227
|
try {
|
|
6787
|
-
|
|
7228
|
+
unlinkSync3(PID_PATH);
|
|
6788
7229
|
} catch {
|
|
6789
7230
|
}
|
|
6790
7231
|
return false;
|
|
@@ -6795,11 +7236,11 @@ function checkExistingDaemon() {
|
|
|
6795
7236
|
process.stderr.write(`[exed] PID ${pid} is a zombie \u2014 cleaning up and proceeding.
|
|
6796
7237
|
`);
|
|
6797
7238
|
try {
|
|
6798
|
-
|
|
7239
|
+
unlinkSync3(PID_PATH);
|
|
6799
7240
|
} catch {
|
|
6800
7241
|
}
|
|
6801
7242
|
try {
|
|
6802
|
-
|
|
7243
|
+
unlinkSync3(SOCKET_PATH);
|
|
6803
7244
|
} catch {
|
|
6804
7245
|
}
|
|
6805
7246
|
killOrphanDaemons();
|
|
@@ -6809,11 +7250,11 @@ function checkExistingDaemon() {
|
|
|
6809
7250
|
process.stderr.write(`[exed] PID ${pid} no longer exists \u2014 cleaning stale PID file.
|
|
6810
7251
|
`);
|
|
6811
7252
|
try {
|
|
6812
|
-
|
|
7253
|
+
unlinkSync3(PID_PATH);
|
|
6813
7254
|
} catch {
|
|
6814
7255
|
}
|
|
6815
7256
|
try {
|
|
6816
|
-
|
|
7257
|
+
unlinkSync3(SOCKET_PATH);
|
|
6817
7258
|
} catch {
|
|
6818
7259
|
}
|
|
6819
7260
|
killOrphanDaemons();
|
|
@@ -6835,7 +7276,7 @@ function checkExistingDaemon() {
|
|
|
6835
7276
|
return true;
|
|
6836
7277
|
}
|
|
6837
7278
|
try {
|
|
6838
|
-
|
|
7279
|
+
unlinkSync3(PID_PATH);
|
|
6839
7280
|
} catch {
|
|
6840
7281
|
}
|
|
6841
7282
|
killOrphanDaemons();
|
|
@@ -6908,21 +7349,21 @@ function startAutoUpdateCheck() {
|
|
|
6908
7349
|
if (checkExistingDaemon()) {
|
|
6909
7350
|
process.exit(0);
|
|
6910
7351
|
}
|
|
6911
|
-
|
|
7352
|
+
writeFileSync4(PID_PATH, String(process.pid));
|
|
6912
7353
|
try {
|
|
6913
7354
|
chmodSync(PID_PATH, 384);
|
|
6914
7355
|
} catch {
|
|
6915
7356
|
}
|
|
6916
7357
|
markAsDaemonProcess();
|
|
6917
7358
|
var DAEMON_BOOT_PATH = path3.join(EXE_AI_DIR, "daemon-boot-ts");
|
|
6918
|
-
|
|
7359
|
+
writeFileSync4(DAEMON_BOOT_PATH, (/* @__PURE__ */ new Date()).toISOString());
|
|
6919
7360
|
try {
|
|
6920
7361
|
chmodSync(DAEMON_BOOT_PATH, 420);
|
|
6921
7362
|
} catch {
|
|
6922
7363
|
}
|
|
6923
7364
|
await new Promise((r) => setTimeout(r, 500));
|
|
6924
7365
|
try {
|
|
6925
|
-
const claimedPid = parseInt(
|
|
7366
|
+
const claimedPid = parseInt(readFileSync5(PID_PATH, "utf8").trim(), 10);
|
|
6926
7367
|
if (claimedPid !== process.pid) {
|
|
6927
7368
|
process.stderr.write(
|
|
6928
7369
|
`[exed] Race detected \u2014 PID ${claimedPid} claimed the lock. Exiting cleanly.
|
|
@@ -6941,12 +7382,12 @@ process.env.EXE_IS_DAEMON = "1";
|
|
|
6941
7382
|
if (process.platform === "darwin") {
|
|
6942
7383
|
try {
|
|
6943
7384
|
const oldPlist = path3.join(os2.homedir(), "Library", "LaunchAgents", "com.askexe.exed-keepalive.plist");
|
|
6944
|
-
if (
|
|
7385
|
+
if (existsSync5(oldPlist)) {
|
|
6945
7386
|
try {
|
|
6946
7387
|
execSyncNode(`launchctl unload "${oldPlist}" 2>/dev/null`, { timeout: 5e3 });
|
|
6947
7388
|
} catch {
|
|
6948
7389
|
}
|
|
6949
|
-
|
|
7390
|
+
unlinkSync3(oldPlist);
|
|
6950
7391
|
process.stderr.write("[exed] Removed old keepalive plist (replaced by launchd KeepAlive).\n");
|
|
6951
7392
|
}
|
|
6952
7393
|
} catch {
|
|
@@ -6955,7 +7396,7 @@ if (process.platform === "darwin") {
|
|
|
6955
7396
|
logBoot({ socketPath: SOCKET_PATH, pidPath: PID_PATH });
|
|
6956
7397
|
void (async () => {
|
|
6957
7398
|
try {
|
|
6958
|
-
const { cleanupCrashDebris } = await import("
|
|
7399
|
+
const { cleanupCrashDebris } = await import("./db-backup.js");
|
|
6959
7400
|
const removed = cleanupCrashDebris();
|
|
6960
7401
|
if (removed > 0) {
|
|
6961
7402
|
process.stderr.write(`[exed] Startup cleanup: pruned ${removed} crash-debris file(s) (backups/quarantine).
|
|
@@ -7104,11 +7545,16 @@ function startEventLoopLagDetector() {
|
|
|
7104
7545
|
const { singleMs: SELF_HEAL_SINGLE_MS, consecutive: SELF_HEAL_CONSECUTIVE, thresholdMs: SELF_HEAL_THRESHOLD_MS } = resolveSelfHealThresholds();
|
|
7105
7546
|
let consecutiveSevereBlocks = 0;
|
|
7106
7547
|
let selfInflictedWindow = [];
|
|
7548
|
+
const LOAD_SAMPLE_KEEP_MS = Math.max(12e4, SELF_HEAL_SINGLE_MS + 6e4);
|
|
7549
|
+
let loadSamples = [];
|
|
7107
7550
|
touchEventLoopHeartbeat();
|
|
7108
7551
|
const lagTimer = setInterval(() => {
|
|
7109
7552
|
touchEventLoopHeartbeat();
|
|
7110
7553
|
const wallElapsedMs = monotonicElapsedMs(lastTick);
|
|
7111
7554
|
const lag = wallElapsedMs - 2e3;
|
|
7555
|
+
const sampledLoad1m = os2.loadavg()[0] ?? 0;
|
|
7556
|
+
const loadWindow = updateLoadWindow(loadSamples, Date.now(), sampledLoad1m, wallElapsedMs, LOAD_SAMPLE_KEEP_MS);
|
|
7557
|
+
loadSamples = loadWindow.samples;
|
|
7112
7558
|
const cpuDelta = process.cpuUsage(lastCpu);
|
|
7113
7559
|
lastCpu = process.cpuUsage();
|
|
7114
7560
|
const selfCpuBusyFraction = wallElapsedMs > 0 ? (cpuDelta.user + cpuDelta.system) / 1e3 / wallElapsedMs : 0;
|
|
@@ -7119,7 +7565,7 @@ function startEventLoopLagDetector() {
|
|
|
7119
7565
|
if (clockJump) {
|
|
7120
7566
|
consecutiveSevereBlocks = 0;
|
|
7121
7567
|
try {
|
|
7122
|
-
|
|
7568
|
+
unlinkSync3(path3.join(os2.homedir(), ".exe-os", "session-cache", "event-loop-blocked.marker"));
|
|
7123
7569
|
} catch {
|
|
7124
7570
|
}
|
|
7125
7571
|
process.stderr.write("[exed] Event loop lag detector: wall-clock jump/sleep detected; reset without self-heal.\n");
|
|
@@ -7129,12 +7575,12 @@ function startEventLoopLagDetector() {
|
|
|
7129
7575
|
const msg = `[exed] EVENT LOOP BLOCKED ${(lag / 1e3).toFixed(1)}s \u2014 MCP UNRESPONSIVE. Sessions will die.`;
|
|
7130
7576
|
process.stderr.write(msg + "\n");
|
|
7131
7577
|
logDaemonHealth({ event: "event_loop_blocked", pid: process.pid, message: msg, data: { lagMs: lag } });
|
|
7132
|
-
void import("../orchestration-events-
|
|
7578
|
+
void import("../orchestration-events-5XDNVNR2.js").then(({ recordOrchestrationEventBestEffort: recordOE }) => {
|
|
7133
7579
|
recordOE({ eventType: "daemon.event_loop_blocked", source: "exe-daemon.lagDetector", severity: "error", durationMs: lag });
|
|
7134
7580
|
}).catch(() => {
|
|
7135
7581
|
});
|
|
7136
7582
|
try {
|
|
7137
|
-
|
|
7583
|
+
writeFileSync4(path3.join(os2.homedir(), ".exe-os", "session-cache", "event-loop-blocked.marker"), `lag=${lag}ms at ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
7138
7584
|
`);
|
|
7139
7585
|
} catch {
|
|
7140
7586
|
}
|
|
@@ -7150,13 +7596,15 @@ function startEventLoopLagDetector() {
|
|
|
7150
7596
|
});
|
|
7151
7597
|
} catch {
|
|
7152
7598
|
}
|
|
7153
|
-
const load1m =
|
|
7599
|
+
const load1m = sampledLoad1m;
|
|
7600
|
+
const maxLoad1mOverWindow = loadWindow.maxLoad1mOverWindow;
|
|
7154
7601
|
const cpuCount = os2.cpus().length || 1;
|
|
7155
7602
|
const starvationRatio = resolveSelfHealThresholds().starvationRatio;
|
|
7156
7603
|
const catchUpActive = inBootCatchUpGrace();
|
|
7157
7604
|
const decision = decideDaemonSelfHeal({
|
|
7158
7605
|
lagMs: lag,
|
|
7159
7606
|
load1m,
|
|
7607
|
+
maxLoad1mOverWindow,
|
|
7160
7608
|
cpuCount,
|
|
7161
7609
|
starvationRatio,
|
|
7162
7610
|
singleBlockMs: SELF_HEAL_SINGLE_MS,
|
|
@@ -7180,14 +7628,14 @@ function startEventLoopLagDetector() {
|
|
|
7180
7628
|
selfInflictedWindow = decision.selfInflictedWindowAfter;
|
|
7181
7629
|
if (decision.reason === "starved_backoff") {
|
|
7182
7630
|
process.stderr.write(
|
|
7183
|
-
`[exed] SELF-HEAL SUPPRESSED: load=${load1m.toFixed(2)} cpus=${cpuCount} \u2014 lag is CPU starvation, not internal hang. Skipping restart.
|
|
7631
|
+
`[exed] SELF-HEAL SUPPRESSED: load=${load1m.toFixed(2)} maxOverWindow=${maxLoad1mOverWindow.toFixed(2)} cpus=${cpuCount} \u2014 lag is CPU starvation, not internal hang. Skipping restart.
|
|
7184
7632
|
`
|
|
7185
7633
|
);
|
|
7186
7634
|
logDaemonHealth({
|
|
7187
7635
|
event: "self_heal_suppressed_starvation",
|
|
7188
7636
|
pid: process.pid,
|
|
7189
|
-
message: `CPU starved (load=${load1m.toFixed(2)} / cpus=${cpuCount}) \u2014 restart skipped`,
|
|
7190
|
-
data: { lagMs: lag, load1m, cpuCount }
|
|
7637
|
+
message: `CPU starved (load=${load1m.toFixed(2)} maxOverWindow=${maxLoad1mOverWindow.toFixed(2)} / cpus=${cpuCount}) \u2014 restart skipped`,
|
|
7638
|
+
data: { lagMs: lag, load1m, maxLoad1mOverWindow, cpuCount }
|
|
7191
7639
|
});
|
|
7192
7640
|
return;
|
|
7193
7641
|
}
|
|
@@ -7274,9 +7722,11 @@ function startTaskFileResync() {
|
|
|
7274
7722
|
if (!await ensureStoreForPolling()) return;
|
|
7275
7723
|
const { readdir, readFile } = await import("fs/promises");
|
|
7276
7724
|
const { getClient } = await import("./database.js");
|
|
7725
|
+
const { runBudgetedSweep } = await import("../sweep-budget-LQYBMDTK.js");
|
|
7277
7726
|
const client = getClient();
|
|
7278
7727
|
const tasksRoot = path3.join(os2.homedir(), ".exe-os", "tasks");
|
|
7279
7728
|
let synced = 0;
|
|
7729
|
+
const paths = [];
|
|
7280
7730
|
let fileCount = 0;
|
|
7281
7731
|
const walkAsync = async (dir) => {
|
|
7282
7732
|
let entries;
|
|
@@ -7292,47 +7742,50 @@ function startTaskFileResync() {
|
|
|
7292
7742
|
continue;
|
|
7293
7743
|
}
|
|
7294
7744
|
if (!e.name.endsWith(".md")) continue;
|
|
7295
|
-
|
|
7296
|
-
|
|
7297
|
-
|
|
7298
|
-
|
|
7299
|
-
|
|
7300
|
-
|
|
7301
|
-
|
|
7302
|
-
|
|
7303
|
-
|
|
7304
|
-
|
|
7305
|
-
|
|
7306
|
-
|
|
7307
|
-
|
|
7308
|
-
|
|
7745
|
+
paths.push(full);
|
|
7746
|
+
if (++fileCount % 10 === 0) await yieldToEventLoop();
|
|
7747
|
+
}
|
|
7748
|
+
};
|
|
7749
|
+
await walkAsync(tasksRoot);
|
|
7750
|
+
await runBudgetedSweep(paths, async (full) => {
|
|
7751
|
+
try {
|
|
7752
|
+
const content = await readFile(full, "utf8");
|
|
7753
|
+
const id = content.match(/\*\*ID:\*\*\s*([a-f0-9-]+)/)?.[1];
|
|
7754
|
+
const title = content.split("\n")[0]?.replace(/^# /, "") || "";
|
|
7755
|
+
const assignedTo = content.match(/\*\*Assigned to:\*\*\s*(\w+)/)?.[1];
|
|
7756
|
+
const assignedBy = content.match(/\*\*Assigned by:\*\*\s*(\w+)/)?.[1] || "exe";
|
|
7757
|
+
const project = content.match(/\*\*Project:\*\*\s*([\w-]+)/)?.[1] || "exe-os";
|
|
7758
|
+
const status = content.match(/\*\*Status:\*\*\s*(\w+)/)?.[1] || "open";
|
|
7759
|
+
const priority = content.match(/\*\*Priority:\*\*\s*(\w+)/)?.[1] || "p1";
|
|
7760
|
+
const scope = full.match(/tasks\/([^/]+)\//)?.[1] || null;
|
|
7761
|
+
if (id && assignedTo) {
|
|
7762
|
+
try {
|
|
7763
|
+
const res = await client.execute({
|
|
7764
|
+
sql: `INSERT OR IGNORE INTO tasks (id, title, assigned_to, assigned_by, project_name, status, priority, task_file, session_scope, created_at, updated_at)
|
|
7309
7765
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
7310
|
-
|
|
7311
|
-
|
|
7312
|
-
|
|
7313
|
-
|
|
7314
|
-
|
|
7315
|
-
|
|
7316
|
-
|
|
7317
|
-
|
|
7318
|
-
|
|
7319
|
-
|
|
7320
|
-
|
|
7321
|
-
|
|
7322
|
-
|
|
7323
|
-
});
|
|
7324
|
-
}).catch(() => {
|
|
7766
|
+
args: [id, title, assignedTo, assignedBy, project, status, priority, full, scope, (/* @__PURE__ */ new Date()).toISOString(), (/* @__PURE__ */ new Date()).toISOString()]
|
|
7767
|
+
});
|
|
7768
|
+
if (Number(res.rowsAffected ?? 0) > 0) {
|
|
7769
|
+
synced++;
|
|
7770
|
+
void import("../orchestration-events-5XDNVNR2.js").then(({ recordOrchestrationEventBestEffort: recordOE }) => {
|
|
7771
|
+
recordOE({
|
|
7772
|
+
eventType: "task_file.resynced",
|
|
7773
|
+
source: "exe-daemon.taskFileResync",
|
|
7774
|
+
taskId: id,
|
|
7775
|
+
agentId: assignedTo,
|
|
7776
|
+
sessionScope: scope,
|
|
7777
|
+
projectName: project,
|
|
7778
|
+
payload: { status, priority }
|
|
7325
7779
|
});
|
|
7326
|
-
}
|
|
7327
|
-
|
|
7780
|
+
}).catch(() => {
|
|
7781
|
+
});
|
|
7328
7782
|
}
|
|
7783
|
+
} catch {
|
|
7329
7784
|
}
|
|
7330
|
-
} catch {
|
|
7331
7785
|
}
|
|
7332
|
-
|
|
7786
|
+
} catch {
|
|
7333
7787
|
}
|
|
7334
|
-
};
|
|
7335
|
-
await walkAsync(tasksRoot);
|
|
7788
|
+
}, { label: "task_file_resync" });
|
|
7336
7789
|
if (synced > 0) process.stderr.write(`[exed] Task re-sync: ${synced} missing DB rows restored from disk.
|
|
7337
7790
|
`);
|
|
7338
7791
|
} catch (e) {
|
|
@@ -7348,7 +7801,7 @@ function startTaskGroupBarriers() {
|
|
|
7348
7801
|
fired("task_group_barriers");
|
|
7349
7802
|
if (!await ensureStoreForPolling()) return;
|
|
7350
7803
|
try {
|
|
7351
|
-
const { pollTaskGroupBarriers } = await import("../daemon-orchestration-
|
|
7804
|
+
const { pollTaskGroupBarriers } = await import("../daemon-orchestration-GGSRCXR3.js");
|
|
7352
7805
|
const firedCount = await pollTaskGroupBarriers();
|
|
7353
7806
|
if (firedCount > 0) {
|
|
7354
7807
|
acted("task_group_barriers");
|
|
@@ -7370,7 +7823,7 @@ function startCheckpointGc() {
|
|
|
7370
7823
|
fired("checkpoint_gc");
|
|
7371
7824
|
if (!await ensureStoreForPolling()) return;
|
|
7372
7825
|
try {
|
|
7373
|
-
const { gcStaleCheckpoints } = await import("../daemon-orchestration-
|
|
7826
|
+
const { gcStaleCheckpoints } = await import("../daemon-orchestration-GGSRCXR3.js");
|
|
7374
7827
|
const cleared = await gcStaleCheckpoints();
|
|
7375
7828
|
if (cleared > 0) {
|
|
7376
7829
|
acted("checkpoint_gc");
|
|
@@ -7410,14 +7863,14 @@ function startDispatchAckCleanup() {
|
|
|
7410
7863
|
function startProjectionWorkerDeferred() {
|
|
7411
7864
|
setTimeout(async () => {
|
|
7412
7865
|
try {
|
|
7413
|
-
const { startProjectionWorker } = await import("../projection-worker-
|
|
7866
|
+
const { startProjectionWorker } = await import("../projection-worker-CKC2E22U.js");
|
|
7414
7867
|
startProjectionWorker();
|
|
7415
7868
|
} catch {
|
|
7416
7869
|
}
|
|
7417
7870
|
}, 2e4);
|
|
7418
7871
|
}
|
|
7419
7872
|
async function startToolTelemetry() {
|
|
7420
|
-
const { startToolTelemetryFlush } = await import("../tool-telemetry-
|
|
7873
|
+
const { startToolTelemetryFlush } = await import("../tool-telemetry-4MF2HIWR.js");
|
|
7421
7874
|
startToolTelemetryFlush();
|
|
7422
7875
|
process.stderr.write("[exed] Tool telemetry started (flush every 5m)\n");
|
|
7423
7876
|
}
|
|
@@ -7553,8 +8006,8 @@ function startLocalFirstTimers() {
|
|
|
7553
8006
|
}
|
|
7554
8007
|
_intercomDedupCompleted = true;
|
|
7555
8008
|
try {
|
|
7556
|
-
const { writeFileSync:
|
|
7557
|
-
|
|
8009
|
+
const { writeFileSync: writeFileSync5 } = await import("fs");
|
|
8010
|
+
writeFileSync5(markerPath, (/* @__PURE__ */ new Date()).toISOString(), "utf8");
|
|
7558
8011
|
} catch {
|
|
7559
8012
|
}
|
|
7560
8013
|
} catch (err) {
|
|
@@ -7583,7 +8036,7 @@ function startLocalFirstTimers() {
|
|
|
7583
8036
|
fired("orphan_task_cleanup");
|
|
7584
8037
|
try {
|
|
7585
8038
|
if (!await ensureStoreForPolling()) return;
|
|
7586
|
-
const { cleanOrphanedTaskFiles } = await import("../tasks-crud-
|
|
8039
|
+
const { cleanOrphanedTaskFiles } = await import("../tasks-crud-DFPIAAEC.js");
|
|
7587
8040
|
const count = await cleanOrphanedTaskFiles();
|
|
7588
8041
|
if (count > 0) {
|
|
7589
8042
|
acted("orphan_task_cleanup");
|
|
@@ -7599,7 +8052,7 @@ function startLocalFirstTimers() {
|
|
|
7599
8052
|
fired("task_file_consistency");
|
|
7600
8053
|
try {
|
|
7601
8054
|
if (!await ensureStoreForPolling()) return;
|
|
7602
|
-
const { checkTaskFileConsistency } = await import("../tasks-crud-
|
|
8055
|
+
const { checkTaskFileConsistency } = await import("../tasks-crud-DFPIAAEC.js");
|
|
7603
8056
|
const mismatches = await checkTaskFileConsistency();
|
|
7604
8057
|
if (mismatches > 0) {
|
|
7605
8058
|
acted("task_file_consistency");
|
|
@@ -7618,7 +8071,7 @@ function startLocalFirstTimers() {
|
|
|
7618
8071
|
const TELEMETRY_DAILY_MS = 24 * 60 * 60 * 1e3;
|
|
7619
8072
|
const telemetryDaily = async () => {
|
|
7620
8073
|
try {
|
|
7621
|
-
const { sendTelemetry, isTelemetryEnabled } = await import("../telemetry-upload-
|
|
8074
|
+
const { sendTelemetry, isTelemetryEnabled } = await import("../telemetry-upload-Y5F6WYLD.js");
|
|
7622
8075
|
if (!isTelemetryEnabled()) return;
|
|
7623
8076
|
const { upstream } = await sendTelemetry(24);
|
|
7624
8077
|
if (upstream.startsWith("sent")) {
|
|
@@ -7789,11 +8242,63 @@ async function enterDegradedBreakerMode(crashCount) {
|
|
|
7789
8242
|
}, 5 * 60 * 1e3);
|
|
7790
8243
|
}
|
|
7791
8244
|
try {
|
|
7792
|
-
|
|
8245
|
+
let coverageGap;
|
|
8246
|
+
let coverageGapLastHeartbeatTs = null;
|
|
8247
|
+
let coverageGapHostBootTs = null;
|
|
8248
|
+
let coverageGapNowMs = Date.now();
|
|
8249
|
+
try {
|
|
8250
|
+
coverageGapNowMs = Date.now();
|
|
8251
|
+
coverageGapLastHeartbeatTs = readLastHeartbeatTsMs();
|
|
8252
|
+
coverageGapHostBootTs = hostBootTimeMs(coverageGapNowMs, os2.uptime());
|
|
8253
|
+
const rawThreshold = Number(process.env.EXE_COVERAGE_GAP_THRESHOLD_MS);
|
|
8254
|
+
coverageGap = assessCoverageGap({
|
|
8255
|
+
lastHeartbeatTs: coverageGapLastHeartbeatTs,
|
|
8256
|
+
hostBootTs: coverageGapHostBootTs,
|
|
8257
|
+
nowMs: coverageGapNowMs,
|
|
8258
|
+
...Number.isFinite(rawThreshold) && rawThreshold > 0 ? { gapThresholdMs: Math.floor(rawThreshold) } : {}
|
|
8259
|
+
});
|
|
8260
|
+
} catch {
|
|
8261
|
+
coverageGap = void 0;
|
|
8262
|
+
}
|
|
8263
|
+
const breaker = recordDaemonRestart(void 0, coverageGap);
|
|
7793
8264
|
process.stderr.write(
|
|
7794
8265
|
`[exed] Boot classified as ${breaker.bootClass} (${breaker.reasonLabel}); crashes=${breaker.crashInWindow}/${5}, restarts=${breaker.restartsInWindow} in window.
|
|
7795
8266
|
`
|
|
7796
8267
|
);
|
|
8268
|
+
try {
|
|
8269
|
+
touchEventLoopHeartbeat();
|
|
8270
|
+
} catch {
|
|
8271
|
+
}
|
|
8272
|
+
try {
|
|
8273
|
+
if (coverageGap && shouldWriteCoverageGapAlert(breaker.bootClass, coverageGap, COVERAGE_GAP_ALERT_THRESHOLD_MS)) {
|
|
8274
|
+
const gapHours = (coverageGap.gapMs / (60 * 60 * 1e3)).toFixed(1);
|
|
8275
|
+
const lastHeartbeatIso = coverageGapLastHeartbeatTs !== null ? new Date(coverageGapLastHeartbeatTs).toISOString() : "unknown";
|
|
8276
|
+
const rebootIso = coverageGap.rebootSpansGap && coverageGapHostBootTs !== null ? `, reboot=${new Date(coverageGapHostBootTs).toISOString()}` : "";
|
|
8277
|
+
process.stderr.write(
|
|
8278
|
+
`[exed] COVERAGE GAP: daemon was down ~${gapHours}h; lastHeartbeat=${lastHeartbeatIso}${rebootIso}; GUI LaunchAgent does not run pre-login.
|
|
8279
|
+
`
|
|
8280
|
+
);
|
|
8281
|
+
logDaemonHealth({
|
|
8282
|
+
event: "coverage_gap",
|
|
8283
|
+
pid: process.pid,
|
|
8284
|
+
message: `Daemon coverage gap detected (~${gapHours}h)`,
|
|
8285
|
+
data: {
|
|
8286
|
+
gapMs: coverageGap.gapMs,
|
|
8287
|
+
lastHeartbeatTs: coverageGapLastHeartbeatTs,
|
|
8288
|
+
hostBootTs: coverageGapHostBootTs,
|
|
8289
|
+
rebootSpansGap: coverageGap.rebootSpansGap
|
|
8290
|
+
}
|
|
8291
|
+
});
|
|
8292
|
+
writeCoverageGapAlert(coverageGap, {
|
|
8293
|
+
lastHeartbeatTs: coverageGapLastHeartbeatTs,
|
|
8294
|
+
hostBootTs: coverageGapHostBootTs,
|
|
8295
|
+
nowMs: coverageGapNowMs
|
|
8296
|
+
});
|
|
8297
|
+
} else if (coverageGap) {
|
|
8298
|
+
clearCoverageGapAlertIfExpired();
|
|
8299
|
+
}
|
|
8300
|
+
} catch {
|
|
8301
|
+
}
|
|
7797
8302
|
if (breaker.trip) {
|
|
7798
8303
|
logRestartEvent("daemon_restart_breaker_tripped", { crash_in_window: breaker.crashInWindow, restarts_in_window: breaker.restartsInWindow });
|
|
7799
8304
|
await enterDegradedBreakerMode(breaker.crashInWindow);
|
|
@@ -7831,11 +8336,11 @@ try {
|
|
|
7831
8336
|
process.stderr.write(`[exed] FATAL: ${err instanceof Error ? err.message : String(err)}
|
|
7832
8337
|
`);
|
|
7833
8338
|
try {
|
|
7834
|
-
|
|
8339
|
+
unlinkSync3(SOCKET_PATH);
|
|
7835
8340
|
} catch {
|
|
7836
8341
|
}
|
|
7837
8342
|
try {
|
|
7838
|
-
|
|
8343
|
+
unlinkSync3(PID_PATH);
|
|
7839
8344
|
} catch {
|
|
7840
8345
|
}
|
|
7841
8346
|
process.exit(1);
|