@askexenow/exe-os 0.9.227 → 0.9.229
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-GJDG4CAW.js +24 -0
- package/dist/active-agent-WOP3ZHLN.js +25 -0
- package/dist/agent-context-ZPDQOAD2.js +9 -0
- package/dist/agent-heartbeat-AWTVGE4C.js +60 -0
- package/dist/agent-loop-7UM2ENGU.js +10 -0
- package/dist/agentic-ontology-ASORFII6.js +25 -0
- package/dist/asana-JN2UF47A.js +129 -0
- package/dist/assets/ghostty.conf +83 -0
- package/dist/assets/statusline-command.sh +44 -0
- package/dist/assets/tmux.conf +56 -0
- package/dist/assets/wezterm.lua +68 -0
- package/dist/backfill-metadata-JRWUECUS.js +596 -0
- package/dist/background-jobs-VTOMOTNA.js +25 -0
- package/dist/bash-XA65M6T6.js +8 -0
- package/dist/behaviors-36T3O2DC.js +24 -0
- package/dist/bin/age-ontology-load.js +85 -0
- package/dist/bin/agentic-ontology-backfill.js +84 -0
- package/dist/bin/agentic-reflection-backfill.js +45 -0
- package/dist/bin/agentic-semantic-label.js +193 -0
- package/dist/bin/backfill-conversations.js +399 -0
- package/dist/bin/backfill-responses.js +227 -0
- package/dist/bin/backfill-vectors.js +149 -0
- package/dist/bin/bulk-sync-postgres.js +92 -0
- package/dist/bin/cc-doctor.js +51 -0
- package/dist/bin/cleanup-stale-review-tasks.js +139 -0
- package/dist/bin/cli.js +1076 -0
- package/dist/bin/customer-readiness.js +389 -0
- package/dist/bin/deferred-daemon-restart.js +123 -0
- package/dist/bin/exe-agent-config.js +87 -0
- package/dist/bin/exe-agent.js +190 -0
- package/dist/bin/exe-assign.js +93 -0
- package/dist/bin/exe-boot.js +1114 -0
- package/dist/bin/exe-call.js +127 -0
- package/dist/bin/exe-cloud.js +484 -0
- package/dist/bin/exe-dispatch.js +72 -0
- package/dist/bin/exe-doctor.js +48 -0
- package/dist/bin/exe-export-behaviors.js +48 -0
- package/dist/bin/exe-forget.js +204 -0
- package/dist/bin/exe-gateway.js +1137 -0
- package/dist/bin/exe-healthcheck.js +14 -0
- package/dist/bin/exe-heartbeat.js +233 -0
- package/dist/bin/exe-kill.js +126 -0
- package/dist/bin/exe-launch-agent.js +678 -0
- package/dist/bin/exe-new-employee.js +160 -0
- package/dist/bin/exe-pending-messages.js +60 -0
- package/dist/bin/exe-pending-notifications.js +107 -0
- package/dist/bin/exe-pending-reviews.js +81 -0
- package/dist/bin/exe-rename.js +219 -0
- package/dist/bin/exe-repo-drift.js +95 -0
- package/dist/bin/exe-review.js +251 -0
- package/dist/bin/exe-search.js +65 -0
- package/dist/bin/exe-session-cleanup.js +331 -0
- package/dist/bin/exe-settings.js +364 -0
- package/dist/bin/exe-start-codex.js +404 -0
- package/dist/bin/exe-start-opencode.js +233 -0
- package/dist/bin/exe-start.sh +194 -0
- package/dist/bin/exe-status.js +34 -0
- package/dist/bin/exe-support.js +17 -0
- package/dist/bin/exe-team.js +83 -0
- package/dist/bin/generate-hook-manifest.js +30 -0
- package/dist/bin/git-sweep.js +74 -0
- package/dist/bin/graph-backfill.js +78 -0
- package/dist/bin/graph-export.js +66 -0
- package/dist/bin/graph-layer-benchmark.js +113 -0
- package/dist/bin/import-history.js +84 -0
- package/dist/bin/install-launchd.js +41 -0
- package/dist/bin/install.js +422 -0
- package/dist/bin/intercom-check.js +137 -0
- package/dist/bin/list-providers.js +128 -0
- package/dist/bin/mcp-sessions.js +194 -0
- package/dist/bin/orchestration-metrics.js +61 -0
- package/dist/bin/postgres-agentic-reflection-backfill.js +123 -0
- package/dist/bin/postgres-agentic-semantic-backfill.js +126 -0
- package/dist/bin/pre-build-guard.js +98 -0
- package/dist/bin/pre-publish.js +224 -0
- package/dist/bin/registry-proxy.js +44 -0
- package/dist/bin/scan-tasks.js +265 -0
- package/dist/bin/setup.js +19 -0
- package/dist/bin/shard-migrate.js +162 -0
- package/dist/bin/stack-update.js +372 -0
- package/dist/bin/update.js +354 -0
- package/dist/bin/verify-stack.js +389 -0
- package/dist/bin/vps-backup.js +170 -0
- package/dist/bin/vps-health-gate.js +232 -0
- package/dist/branding-I2TDZFUH.js +97 -0
- package/dist/browser-sanitizer-MRSSEJZE.js +229 -0
- package/dist/browser-session-store-RF45DSJR.js +232 -0
- package/dist/capacity-monitor-HZPAFQZH.js +48 -0
- package/dist/catchup-brief-CDG4KD5Y.js +150 -0
- package/dist/chunk-26PUEPOY.js +290 -0
- package/dist/chunk-2VZ6SY2R.js +142 -0
- package/dist/chunk-36DAY227.js +297 -0
- package/dist/chunk-3A5BZETG.js +463 -0
- package/dist/chunk-3DQ3IPPO.js +50 -0
- package/dist/chunk-3JP3FY33.js +258 -0
- package/dist/chunk-3MK3R5E6.js +85 -0
- package/dist/chunk-46SQTBQW.js +207 -0
- package/dist/chunk-4JERP7NT.js +132 -0
- package/dist/chunk-557C2IGL.js +0 -0
- package/dist/chunk-5BS5ELMC.js +85 -0
- package/dist/chunk-5NFBE376.js +391 -0
- package/dist/chunk-6A7P74QV.js +53 -0
- package/dist/chunk-6KFICEAT.js +20 -0
- package/dist/chunk-6MP5NOOR.js +151 -0
- package/dist/chunk-6Y4B3QF6.js +19 -0
- package/dist/chunk-7BPKHR4O.js +171 -0
- package/dist/chunk-7DNX45WB.js +244 -0
- package/dist/chunk-7EZCYO76.js +128 -0
- package/dist/chunk-7NNXBDOO.js +541 -0
- package/dist/chunk-ADJXHBEU.js +667 -0
- package/dist/chunk-AHMUF6RO.js +147 -0
- package/dist/chunk-AJWFPKQS.js +573 -0
- package/dist/chunk-AVE2B4DQ.js +140 -0
- package/dist/chunk-AZSCW64F.js +190 -0
- package/dist/chunk-BZAQ4UG7.js +614 -0
- package/dist/chunk-CHCA3ZM2.js +167 -0
- package/dist/chunk-CHT3THVG.js +240 -0
- package/dist/chunk-CLGB3FGL.js +48 -0
- package/dist/chunk-CQDSTBKT.js +1919 -0
- package/dist/chunk-CTFKTUYN.js +627 -0
- package/dist/chunk-CVYC6DUW.js +78 -0
- package/dist/chunk-CX6GL3ZJ.js +274 -0
- package/dist/chunk-D4IVTUNN.js +377 -0
- package/dist/chunk-DGOGCPYU.js +390 -0
- package/dist/chunk-DKRTWILB.js +81 -0
- package/dist/chunk-DLXTKVBO.js +183 -0
- package/dist/chunk-E6ORBQHP.js +225 -0
- package/dist/chunk-ECGTESAP.js +236 -0
- package/dist/chunk-ECQBG62Y.js +363 -0
- package/dist/chunk-ECSNSHZ7.js +431 -0
- package/dist/chunk-EEAKFEEA.js +221 -0
- package/dist/chunk-EGWPJQRQ.js +159 -0
- package/dist/chunk-EHKIJPVX.js +30 -0
- package/dist/chunk-EIT6J37V.js +119 -0
- package/dist/chunk-EQSQ4HBW.js +9 -0
- package/dist/chunk-ETSREHYC.js +55 -0
- package/dist/chunk-F2GUJW5O.js +1090 -0
- package/dist/chunk-F7LU65PQ.js +33 -0
- package/dist/chunk-FF62UWIJ.js +90 -0
- package/dist/chunk-FIPU4BDF.js +123 -0
- package/dist/chunk-FLSASUV3.js +177 -0
- package/dist/chunk-FWFFZGSC.js +94 -0
- package/dist/chunk-FXU7JOXK.js +6 -0
- package/dist/chunk-G4LLKD4Z.js +147 -0
- package/dist/chunk-GFCQJZTO.js +1051 -0
- package/dist/chunk-GGV3PFUW.js +41 -0
- package/dist/chunk-GJV3WDWM.js +14 -0
- package/dist/chunk-GKM7RYN3.js +1020 -0
- package/dist/chunk-GNHN5HRQ.js +40 -0
- package/dist/chunk-GP6G6EQI.js +632 -0
- package/dist/chunk-GUMRIUI5.js +63 -0
- package/dist/chunk-GVP5U4WL.js +113 -0
- package/dist/chunk-HF25XPZE.js +83 -0
- package/dist/chunk-HFJNYSTQ.js +1088 -0
- package/dist/chunk-HO5SBL4B.js +97 -0
- package/dist/chunk-HOKOOBDL.js +52 -0
- package/dist/chunk-HQMEOIUJ.js +69 -0
- package/dist/chunk-HTCBLSIB.js +813 -0
- package/dist/chunk-HYZV25LY.js +34 -0
- package/dist/chunk-I2CDSGQW.js +280 -0
- package/dist/chunk-I7AW4237.js +251 -0
- package/dist/chunk-IKTMX6N7.js +495 -0
- package/dist/chunk-IQT43SDJ.js +357 -0
- package/dist/chunk-IW53DAYO.js +210 -0
- package/dist/chunk-JBKA7F5V.js +2017 -0
- package/dist/chunk-JJNXFW7M.js +330 -0
- package/dist/chunk-JKGAJAM7.js +214 -0
- package/dist/chunk-JQ6TLNIV.js +133 -0
- package/dist/chunk-JSH5MAMM.js +284 -0
- package/dist/chunk-KCUYRZSX.js +72 -0
- package/dist/chunk-KH5Y6RR4.js +360 -0
- package/dist/chunk-L24HYX62.js +498 -0
- package/dist/chunk-L3TB7CC3.js +170 -0
- package/dist/chunk-LHOIY5LQ.js +58 -0
- package/dist/chunk-LWVZLTMD.js +412 -0
- package/dist/chunk-LYH5HE24.js +73 -0
- package/dist/chunk-M37HYGAG.js +346 -0
- package/dist/chunk-MJXEOKIW.js +54 -0
- package/dist/chunk-MKVFPQH2.js +1051 -0
- package/dist/chunk-MLXJ5EZG.js +90 -0
- package/dist/chunk-MP2AFCGL.js +53 -0
- package/dist/chunk-MSCB4ACU.js +356 -0
- package/dist/chunk-MVW62NIZ.js +20 -0
- package/dist/chunk-MZIGUUDQ.js +42 -0
- package/dist/chunk-N5RRQOAC.js +134 -0
- package/dist/chunk-NFB4N53K.js +159 -0
- package/dist/chunk-NGP6LSV2.js +25 -0
- package/dist/chunk-NGVOA6ZQ.js +84 -0
- package/dist/chunk-NRFVWJHP.js +575 -0
- package/dist/chunk-NUVDSQNY.js +1345 -0
- package/dist/chunk-O377P7GM.js +100 -0
- package/dist/chunk-OE6SYHTC.js +157 -0
- package/dist/chunk-OHPRXEUA.js +75 -0
- package/dist/chunk-OI6MVDSY.js +33 -0
- package/dist/chunk-ONKIWA3R.js +249 -0
- package/dist/chunk-OPU3NYOO.js +55 -0
- package/dist/chunk-ORCCI2VV.js +140 -0
- package/dist/chunk-OSMMWGJ2.js +204 -0
- package/dist/chunk-OYNKIAVW.js +181 -0
- package/dist/chunk-PRKVT4KN.js +90 -0
- package/dist/chunk-PW2YH2ZR.js +403 -0
- package/dist/chunk-PWMMIGVQ.js +332 -0
- package/dist/chunk-Q3V7K4ME.js +149 -0
- package/dist/chunk-Q5GUJUDW.js +348 -0
- package/dist/chunk-Q7RGLXQO.js +574 -0
- package/dist/chunk-Q7XA3SQ4.js +13097 -0
- package/dist/chunk-QGGH7LOU.js +93 -0
- package/dist/chunk-QHIGMP2M.js +237 -0
- package/dist/chunk-QI4IXJN7.js +132 -0
- package/dist/chunk-R2E4TV5V.js +56 -0
- package/dist/chunk-R4WMF32C.js +81 -0
- package/dist/chunk-R5U7XKVJ.js +16 -0
- package/dist/chunk-RJT7H2KR.js +349 -0
- package/dist/chunk-RMPAMMYW.js +70 -0
- package/dist/chunk-RTXGUKY3.js +731 -0
- package/dist/chunk-SH45SJQW.js +0 -0
- package/dist/chunk-SUNYJ6YE.js +204 -0
- package/dist/chunk-SVXDCELZ.js +163 -0
- package/dist/chunk-TMEE7AT7.js +72 -0
- package/dist/chunk-TNTFEWU5.js +361 -0
- package/dist/chunk-TOQZO2XX.js +76 -0
- package/dist/chunk-UBMGUX6T.js +3753 -0
- package/dist/chunk-UJOSFVWG.js +3511 -0
- package/dist/chunk-UPSZ2VKV.js +197 -0
- package/dist/chunk-UV4ZHXUP.js +38 -0
- package/dist/chunk-UWISNP4U.js +1073 -0
- package/dist/chunk-V3QAAU2U.js +129 -0
- package/dist/chunk-V4TZI6EO.js +60 -0
- package/dist/chunk-W6TC6A73.js +77 -0
- package/dist/chunk-WA67SFFZ.js +227 -0
- package/dist/chunk-WWPX2LLP.js +262 -0
- package/dist/chunk-WZ2RVKRO.js +121 -0
- package/dist/chunk-X2Z5GT3V.js +118 -0
- package/dist/chunk-X3AVWFWW.js +294 -0
- package/dist/chunk-XEKO37NM.js +43 -0
- package/dist/chunk-YADYM2DE.js +42 -0
- package/dist/chunk-YCTCKUZE.js +128 -0
- package/dist/chunk-YGAAZN3E.js +47 -0
- package/dist/chunk-YKIPAQZG.js +333 -0
- package/dist/chunk-YSU7JB7H.js +0 -0
- package/dist/chunk-YZFZDJWZ.js +107 -0
- package/dist/chunk-YZKJLGWL.js +169 -0
- package/dist/chunk-Z3TT2SVJ.js +135 -0
- package/dist/chunk-Z3ZCLTP7.js +382 -0
- package/dist/chunk-ZVSG2KKG.js +106 -0
- package/dist/co-activation-AJZTQHI3.js +71 -0
- package/dist/co-occurrence-FGEJIMMV.js +73 -0
- package/dist/code-context-index-KHUYATRB.js +29 -0
- package/dist/content-extractor-CUJOBFBU.js +9 -0
- package/dist/conversation-entity-extractor-TW4W57K4.js +114 -0
- package/dist/conversation-wiki-populator-GNFRTS7X.js +105 -0
- package/dist/core-memory-R7QBLN4C.js +110 -0
- package/dist/crdt-sync-K25AKQAD.js +33 -0
- package/dist/crm-bridge-NG5WJMGF.js +19 -0
- package/dist/crm-webhook-3ODT32F7.js +10 -0
- package/dist/cto-delegation-gate-4XDMTK6H.js +205 -0
- package/dist/daemon-auth-WFQMMNSD.js +13 -0
- package/dist/daemon-orchestration-5I7RLXCP.js +133 -0
- package/dist/daemon-protocol-4FUHT5NH.js +17 -0
- package/dist/db-backup-MSQKO6M5.js +25 -0
- package/dist/devtools-J4QYYO7U.js +8 -0
- package/dist/discord-7UHIZNJ3.js +7 -0
- package/dist/dispatch-ack-RMVFHO4I.js +13 -0
- package/dist/dreaming-UL7T5ZXA.js +12 -0
- package/dist/email-T6PQUUY6.js +137 -0
- package/dist/entity-boost-7MB2IYAE.js +332 -0
- package/dist/exe-drift-2KHRPBUK.js +67 -0
- package/dist/exe-export-UZN6EFOR.js +72 -0
- package/dist/exe-import-OSM3U36A.js +75 -0
- package/dist/exe-key-OG35WPBA.js +573 -0
- package/dist/exe-org-JRBBON5H.js +73 -0
- package/dist/exe-snapshot-7TQIN7XI.js +145 -0
- package/dist/factory-UQSRMKJW.js +67 -0
- package/dist/fast-db-init-4VXDSFUY.js +7 -0
- package/dist/file-edit-YORRFENG.js +8 -0
- package/dist/file-read-RMQFDE5L.js +8 -0
- package/dist/file-write-VO4MQW5Y.js +8 -0
- package/dist/founder-context-3N6BMG7B.js +96 -0
- package/dist/gateway/index.js +148 -0
- package/dist/gateway-client-V7NH35Q2.js +11 -0
- package/dist/git-staleness-JW57ZGEJ.js +109 -0
- package/dist/git-task-sweep-HYAPIM44.js +39 -0
- package/dist/glob-2LXRC3F5.js +7 -0
- package/dist/global-procedures-NY3W7L5Q.js +19 -0
- package/dist/graph-auto-extract-5GZ34NXS.js +161 -0
- package/dist/graph-query-YZ4RZEIL.js +26 -0
- package/dist/graph-rag-S5SBJW5J.js +29 -0
- package/dist/grep-OY7KCRLQ.js +7 -0
- package/dist/hook-integrity-OKSYTGVP.js +89 -0
- package/dist/hooks/bug-report-worker.js +179 -0
- package/dist/hooks/codex-stop-task-finalizer.js +258 -0
- package/dist/hooks/commit-complete.js +162 -0
- package/dist/hooks/error-recall.js +129 -0
- package/dist/hooks/exe-heartbeat-hook.js +78 -0
- package/dist/hooks/ingest-worker.js +51 -0
- package/dist/hooks/ingest.js +491 -0
- package/dist/hooks/instructions-loaded.js +119 -0
- package/dist/hooks/manifest.json +25 -0
- package/dist/hooks/notification.js +67 -0
- package/dist/hooks/post-compact.js +138 -0
- package/dist/hooks/post-tool-combined.js +152 -0
- package/dist/hooks/pre-compact.js +159 -0
- package/dist/hooks/pre-tool-use.js +512 -0
- package/dist/hooks/prompt-submit.js +699 -0
- package/dist/hooks/session-end.js +482 -0
- package/dist/hooks/session-start.js +362 -0
- package/dist/hooks/stop.js +332 -0
- package/dist/hooks/subagent-stop.js +85 -0
- package/dist/hooks/summary-worker.js +298 -0
- package/dist/hooks-RPTZV5KX.js +9 -0
- package/dist/imessage-CE5USLTI.js +7 -0
- package/dist/index.js +60 -0
- package/dist/installer-GMIVB2JS.js +341 -0
- package/dist/installer-OBYQ6O3C.js +295 -0
- package/dist/installer-UAMA6ZVH.js +37 -0
- package/dist/intercom-queue-USIXVVJQ.js +17 -0
- package/dist/key-backup-status-TVFMMWTT.js +39 -0
- package/dist/keyword-extractor-OGQRRVTB.js +11 -0
- package/dist/lib/agent-config.js +30 -0
- package/dist/lib/cloud-sync.js +103 -0
- package/dist/lib/cloudflare-dns.js +13 -0
- package/dist/lib/config.js +32 -0
- package/dist/lib/consolidation.js +38 -0
- package/dist/lib/crypto.js +13 -0
- package/dist/lib/database.js +31 -0
- package/dist/lib/db-daemon-client.js +141 -0
- package/dist/lib/db.js +31 -0
- package/dist/lib/device-registry.js +70 -0
- package/dist/lib/embed-worker.js +165 -0
- package/dist/lib/embedder.js +19 -0
- package/dist/lib/employee-templates.js +34 -0
- package/dist/lib/employees.js +63 -0
- package/dist/lib/error-detector.js +16 -0
- package/dist/lib/exe-daemon-client.js +25 -0
- package/dist/lib/exe-daemon.js +4454 -0
- package/dist/lib/file-grep.js +242 -0
- package/dist/lib/hybrid-search.js +28 -0
- package/dist/lib/identity-templates.js +650 -0
- package/dist/lib/identity.js +19 -0
- package/dist/lib/keychain.js +17 -0
- package/dist/lib/license.js +35 -0
- package/dist/lib/messaging.js +59 -0
- package/dist/lib/post-tool-memory.js +13 -0
- package/dist/lib/registry-proxy.js +15 -0
- package/dist/lib/reminders.js +16 -0
- package/dist/lib/runtime-table.js +9 -0
- package/dist/lib/schedules.js +24 -0
- package/dist/lib/session-registry.js +21 -0
- package/dist/lib/session-wrappers.js +7 -0
- package/dist/lib/skill-learning.js +29 -0
- package/dist/lib/status-brief.js +7 -0
- package/dist/lib/store.js +43 -0
- package/dist/lib/task-router.js +22 -0
- package/dist/lib/tasks.js +66 -0
- package/dist/lib/tmux-routing.js +70 -0
- package/dist/lib/tmux-status.js +29 -0
- package/dist/lib/tmux-transport.js +7 -0
- package/dist/lib/token-spend.js +12 -0
- package/dist/lib/transport.js +10 -0
- package/dist/lib/ws-auth.js +11 -0
- package/dist/lib/ws-client.js +190 -0
- package/dist/license-gate-7QVCYARF.js +14 -0
- package/dist/mcp/register-tools.js +102 -0
- package/dist/mcp/server.js +370 -0
- package/dist/mcp/tools/complete-reminder.js +13 -0
- package/dist/mcp/tools/create-reminder.js +13 -0
- package/dist/mcp/tools/create-task.js +34 -0
- package/dist/mcp/tools/deactivate-behavior.js +16 -0
- package/dist/mcp/tools/list-reminders.js +13 -0
- package/dist/mcp/tools/list-tasks.js +33 -0
- package/dist/mcp/tools/send-message.js +33 -0
- package/dist/mcp/tools/update-task.js +32 -0
- package/dist/mcp-diagnostics-5T5OZ52S.js +200 -0
- package/dist/mcp-disconnect-tracker-VINUVEZJ.js +79 -0
- package/dist/mcp-http-config-YPF4WGU5.js +26 -0
- package/dist/memory-cards-XHZEOX7Q.js +173 -0
- package/dist/memory-graph-extractor-J3K7B4GC.js +16 -0
- package/dist/memory-poisoning-defense-I76FGNHK.js +224 -0
- package/dist/memory-queue-WEVFXPZO.js +19 -0
- package/dist/memory-queue-client-5XBHYAQR.js +15 -0
- package/dist/memory-reflection-YJGI6IDI.js +237 -0
- package/dist/message-queue-client-FUKX43JD.js +92 -0
- package/dist/notifications-H4F77BYT.js +44 -0
- package/dist/oauth-server-CCZPDTZJ.js +437 -0
- package/dist/orchestration-events-LXVPJL6S.js +24 -0
- package/dist/orchestration-phase-HXRKMZXM.js +23 -0
- package/dist/orchestrator-HXUZ6LYM.js +32 -0
- package/dist/permission-presets-UPVLJWZD.js +25 -0
- package/dist/permissions-C4EMHPDD.js +14 -0
- package/dist/pg-ssl-GD3332YS.js +7 -0
- package/dist/pipeline-router-QRJQWMFF.js +12 -0
- package/dist/plan-limits-NFQVRHS5.js +25 -0
- package/dist/prediction-log-C2BD3AHR.js +120 -0
- package/dist/preferences-5ARPMYE7.js +10 -0
- package/dist/preflight-TZOGLBZU.js +287 -0
- package/dist/project-boot-JIGOSGCN.js +254 -0
- package/dist/project-name-4SKOH2UO.js +10 -0
- package/dist/projection-worker-JZQTL4NU.js +877 -0
- package/dist/push-notifications-3GNJ5SZS.js +15 -0
- package/dist/reranker-U6DEAT4S.js +19 -0
- package/dist/review-gate-I66GDXNR.js +120 -0
- package/dist/review-polling-W2S3XAAU.js +123 -0
- package/dist/runtime/index.js +129 -0
- package/dist/self-query-router-QMK5ZSZR.js +188 -0
- package/dist/session-events-MNWHGZY5.js +35 -0
- package/dist/session-kill-telemetry-JHSI7D3F.js +28 -0
- package/dist/session-scope-SMT225X3.js +85 -0
- package/dist/setup-wizard-RBUTEZB2.js +12 -0
- package/dist/shard-manager-ON2WWCRM.js +29 -0
- package/dist/signal-KF2LIO7Y.js +7 -0
- package/dist/signal-paths-5ZTWCBUX.js +19 -0
- package/dist/skill-refinement-LKJHUW2U.js +156 -0
- package/dist/slack-JRDUD5Z7.js +7 -0
- package/dist/stack-update-ZIMV4OEQ.js +50 -0
- package/dist/steward-gate-6IKH335D.js +12 -0
- package/dist/support-outbox-HIJVUDA2.js +206 -0
- package/dist/task-enforcement-UIEWTA6H.js +292 -0
- package/dist/task-scanner-5OQBNC2N.js +11 -0
- package/dist/task-scope-DNQURKOQ.js +34 -0
- package/dist/tasks-crud-CLAYZZ4O.js +76 -0
- package/dist/tasks-review-OHR2P4QE.js +46 -0
- package/dist/telegram-COCYUCT7.js +7 -0
- package/dist/telemetry-QKWQKAUC.js +9 -0
- package/dist/telemetry-upload-APVDPCEV.js +609 -0
- package/dist/token-budget-6IQNYKLR.js +83 -0
- package/dist/tool-capability-index-UUNF7VPA.js +10 -0
- package/dist/tool-gates-6A6LE4DZ.js +14 -0
- package/dist/tool-gates-RNWEH5IK.js +13 -0
- package/dist/tool-registry-KL24CAFR.js +11 -0
- package/dist/tool-telemetry-SJSIL5M5.js +17 -0
- package/dist/tui/App.js +10223 -0
- package/dist/tui-data-L6XG4Z52.js +161 -0
- package/dist/typed-messages-53Q7L3LB.js +17 -0
- package/dist/update-check-5IL5I3E2.js +11 -0
- package/dist/webhook-VXGIH7PN.js +96 -0
- package/dist/webhook-pipe-4WPFGGFD.js +114 -0
- package/dist/whatsapp-PSMKCDS7.js +9 -0
- package/dist/whatsapp-accounts-4OKWFRWL.js +15 -0
- package/dist/whatsapp-config-ZG5LX4O4.js +125 -0
- package/dist/wiki-acl-XCT6QQGP.js +111 -0
- package/dist/wiki-client-KE622HKY.js +157 -0
- package/dist/worker-gate-GFKXZ6V5.js +21 -0
- package/dist/workflow-engine-6HTKI2ZE.js +28 -0
- package/dist/working-memory-Z3EB3FW6.js +77 -0
- package/dist/worktree-BO7QQ32T.js +25 -0
- package/package.json +1 -1
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
// src/lib/tool-telemetry.ts
|
|
2
|
+
var _toolCalls = /* @__PURE__ */ new Map();
|
|
3
|
+
var _sessionStartedAt = Date.now();
|
|
4
|
+
var _flushTimer = null;
|
|
5
|
+
function recordCall(toolName, action, isError) {
|
|
6
|
+
let record = _toolCalls.get(toolName);
|
|
7
|
+
if (!record) {
|
|
8
|
+
record = { count: 0, actions: /* @__PURE__ */ new Map(), lastCalledAt: 0, errors: 0 };
|
|
9
|
+
_toolCalls.set(toolName, record);
|
|
10
|
+
}
|
|
11
|
+
record.count++;
|
|
12
|
+
record.lastCalledAt = Date.now();
|
|
13
|
+
if (isError) record.errors++;
|
|
14
|
+
if (action) {
|
|
15
|
+
record.actions.set(action, (record.actions.get(action) ?? 0) + 1);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function wrapServerWithTelemetry(server) {
|
|
19
|
+
const originalRegisterTool = server.registerTool.bind(server);
|
|
20
|
+
server.registerTool = (name, config, handler) => {
|
|
21
|
+
const wrappedHandler = async (input, extra) => {
|
|
22
|
+
const action = input.action;
|
|
23
|
+
try {
|
|
24
|
+
const result = await handler(input, extra);
|
|
25
|
+
const isError = result?.isError === true;
|
|
26
|
+
recordCall(name, action, isError);
|
|
27
|
+
return result;
|
|
28
|
+
} catch (err) {
|
|
29
|
+
recordCall(name, action, true);
|
|
30
|
+
throw err;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
return originalRegisterTool(name, config, wrappedHandler);
|
|
34
|
+
};
|
|
35
|
+
return server;
|
|
36
|
+
}
|
|
37
|
+
function getToolUsageStats() {
|
|
38
|
+
let totalCalls = 0;
|
|
39
|
+
let totalErrors = 0;
|
|
40
|
+
const tools = {};
|
|
41
|
+
for (const [name, record] of _toolCalls) {
|
|
42
|
+
totalCalls += record.count;
|
|
43
|
+
totalErrors += record.errors;
|
|
44
|
+
const entry = {
|
|
45
|
+
calls: record.count,
|
|
46
|
+
errors: record.errors,
|
|
47
|
+
lastCalledAt: new Date(record.lastCalledAt).toISOString()
|
|
48
|
+
};
|
|
49
|
+
if (record.actions.size > 0) {
|
|
50
|
+
entry.actions = Object.fromEntries(record.actions);
|
|
51
|
+
}
|
|
52
|
+
tools[name] = entry;
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
sessionStartedAt: new Date(_sessionStartedAt).toISOString(),
|
|
56
|
+
uptimeMs: Date.now() - _sessionStartedAt,
|
|
57
|
+
totalCalls,
|
|
58
|
+
totalErrors,
|
|
59
|
+
tools
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function resetToolUsageStats() {
|
|
63
|
+
_toolCalls.clear();
|
|
64
|
+
_sessionStartedAt = Date.now();
|
|
65
|
+
}
|
|
66
|
+
var FLUSH_INTERVAL_MS = 5 * 60 * 1e3;
|
|
67
|
+
var _lastFlushedAt = 0;
|
|
68
|
+
async function flushToMemory() {
|
|
69
|
+
const stats = getToolUsageStats();
|
|
70
|
+
if (stats.totalCalls === 0) return;
|
|
71
|
+
if (stats.totalCalls === _lastFlushedAt) return;
|
|
72
|
+
try {
|
|
73
|
+
const { getClient, isInitialized } = await import("./lib/database.js");
|
|
74
|
+
if (!isInitialized()) return;
|
|
75
|
+
const client = getClient();
|
|
76
|
+
const toolSummary = Object.entries(stats.tools).sort((a, b) => b[1].calls - a[1].calls).map(([name, t]) => {
|
|
77
|
+
const actionStr = t.actions ? ` (${Object.entries(t.actions).sort((a, b) => b[1] - a[1]).map(([a, c]) => `${a}:${c}`).join(", ")})` : "";
|
|
78
|
+
return `${name}: ${t.calls} calls${t.errors > 0 ? ` (${t.errors} errors)` : ""}${actionStr}`;
|
|
79
|
+
}).join("\n");
|
|
80
|
+
const raw_text = `Tool usage since ${stats.sessionStartedAt} (${Math.round(stats.uptimeMs / 6e4)}min):
|
|
81
|
+
Total: ${stats.totalCalls} calls, ${stats.totalErrors} errors
|
|
82
|
+
|
|
83
|
+
${toolSummary}`;
|
|
84
|
+
await client.execute({
|
|
85
|
+
sql: `INSERT INTO memories (id, agent_id, raw_text, memory_type, project_name, importance, created_at, updated_at, session_scope)
|
|
86
|
+
VALUES (?, 'system', ?, 'telemetry', 'exe-os', 2, datetime('now'), datetime('now'), NULL)`,
|
|
87
|
+
args: [
|
|
88
|
+
`telemetry-tools-${Date.now()}`,
|
|
89
|
+
raw_text
|
|
90
|
+
]
|
|
91
|
+
});
|
|
92
|
+
_lastFlushedAt = stats.totalCalls;
|
|
93
|
+
} catch {
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function startToolTelemetryFlush() {
|
|
97
|
+
if (_flushTimer) return;
|
|
98
|
+
_sessionStartedAt = Date.now();
|
|
99
|
+
_flushTimer = setInterval(() => void flushToMemory(), FLUSH_INTERVAL_MS);
|
|
100
|
+
_flushTimer.unref();
|
|
101
|
+
}
|
|
102
|
+
async function stopToolTelemetryFlush() {
|
|
103
|
+
if (_flushTimer) {
|
|
104
|
+
clearInterval(_flushTimer);
|
|
105
|
+
_flushTimer = null;
|
|
106
|
+
}
|
|
107
|
+
await flushToMemory();
|
|
108
|
+
}
|
|
109
|
+
function getToolUsageSummary() {
|
|
110
|
+
const summary = {};
|
|
111
|
+
for (const [tool, record] of _toolCalls) {
|
|
112
|
+
summary[tool] = {
|
|
113
|
+
count: record.count,
|
|
114
|
+
errors: record.errors,
|
|
115
|
+
actions: Object.fromEntries(record.actions)
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
return summary;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export {
|
|
122
|
+
wrapServerWithTelemetry,
|
|
123
|
+
getToolUsageStats,
|
|
124
|
+
resetToolUsageStats,
|
|
125
|
+
startToolTelemetryFlush,
|
|
126
|
+
stopToolTelemetryFlush,
|
|
127
|
+
getToolUsageSummary
|
|
128
|
+
};
|
|
@@ -0,0 +1,541 @@
|
|
|
1
|
+
// src/lib/keychain.ts
|
|
2
|
+
import { readFile, writeFile, unlink, mkdir, chmod, rename, copyFile } from "fs/promises";
|
|
3
|
+
import { existsSync, statSync, writeFileSync, readFileSync } from "fs";
|
|
4
|
+
import { execSync } from "child_process";
|
|
5
|
+
import crypto from "crypto";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import os from "os";
|
|
8
|
+
var SERVICE = "exe-os";
|
|
9
|
+
var _plaintextWarningShown = false;
|
|
10
|
+
function warnPlaintextFallback() {
|
|
11
|
+
if (_plaintextWarningShown) return;
|
|
12
|
+
_plaintextWarningShown = true;
|
|
13
|
+
process.stderr.write(
|
|
14
|
+
"[exe-os] \u26A0 Native keychain unavailable \u2014 encryption key stored in plaintext file.\n[exe-os] For production security, install: apt install libsecret-tools gnome-keyring\n"
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
var LEGACY_SERVICE = "exe-mem";
|
|
18
|
+
var ACCOUNT = "master-key";
|
|
19
|
+
function getKeyDir() {
|
|
20
|
+
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path.join(os.homedir(), ".exe-os");
|
|
21
|
+
}
|
|
22
|
+
function getKeyPath() {
|
|
23
|
+
return path.join(getKeyDir(), "master.key");
|
|
24
|
+
}
|
|
25
|
+
function nativeKeychainAllowed() {
|
|
26
|
+
return process.env.EXE_OS_DISABLE_NATIVE_KEYCHAIN !== "1";
|
|
27
|
+
}
|
|
28
|
+
var linuxSecretAvailability = null;
|
|
29
|
+
function linuxSecretAvailable() {
|
|
30
|
+
if (!nativeKeychainAllowed()) return false;
|
|
31
|
+
if (process.platform !== "linux") return false;
|
|
32
|
+
if (linuxSecretAvailability !== null) return linuxSecretAvailability;
|
|
33
|
+
try {
|
|
34
|
+
execSync("command -v secret-tool >/dev/null 2>&1", { timeout: 1e3 });
|
|
35
|
+
} catch {
|
|
36
|
+
linuxSecretAvailability = false;
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
execSync("secret-tool search --all exe-os probe >/dev/null 2>&1", { timeout: 1e3 });
|
|
41
|
+
linuxSecretAvailability = true;
|
|
42
|
+
} catch {
|
|
43
|
+
linuxSecretAvailability = false;
|
|
44
|
+
}
|
|
45
|
+
return linuxSecretAvailability;
|
|
46
|
+
}
|
|
47
|
+
var SERVER_MODE_MARKER = ".server-mode";
|
|
48
|
+
function getServerModeMarkerPath() {
|
|
49
|
+
return path.join(getKeyDir(), SERVER_MODE_MARKER);
|
|
50
|
+
}
|
|
51
|
+
function isServerModeMarked() {
|
|
52
|
+
try {
|
|
53
|
+
return existsSync(getServerModeMarkerPath());
|
|
54
|
+
} catch {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function writeServerModeMarker() {
|
|
59
|
+
try {
|
|
60
|
+
const markerPath = getServerModeMarkerPath();
|
|
61
|
+
if (!existsSync(markerPath)) {
|
|
62
|
+
writeFileSync(markerPath, `# Server mode \u2014 keychain migration disabled.
|
|
63
|
+
# Created: ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
64
|
+
# Remove this file to re-enable native keychain migration.
|
|
65
|
+
`, { mode: 384 });
|
|
66
|
+
}
|
|
67
|
+
} catch {
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function isRootOnlyTrustedServerKeyFile(keyPath) {
|
|
71
|
+
if (process.platform !== "linux") return false;
|
|
72
|
+
try {
|
|
73
|
+
const st = statSync(keyPath);
|
|
74
|
+
if (!st.isFile() || (st.mode & 63) !== 0) return false;
|
|
75
|
+
if (isServerModeMarked()) return true;
|
|
76
|
+
const uid = typeof os.userInfo().uid === "number" ? os.userInfo().uid : -1;
|
|
77
|
+
if (uid === 0) {
|
|
78
|
+
writeServerModeMarker();
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
const exeOsDir = process.env.EXE_OS_DIR;
|
|
82
|
+
if (exeOsDir && path.resolve(keyPath).startsWith(path.resolve(exeOsDir) + path.sep)) {
|
|
83
|
+
writeServerModeMarker();
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
if (!linuxSecretAvailable()) {
|
|
87
|
+
writeServerModeMarker();
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
return false;
|
|
91
|
+
} catch {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function macKeychainGet(service = SERVICE) {
|
|
96
|
+
if (!nativeKeychainAllowed()) return null;
|
|
97
|
+
if (process.platform !== "darwin") return null;
|
|
98
|
+
try {
|
|
99
|
+
return execSync(
|
|
100
|
+
`security find-generic-password -s "${service}" -a "${ACCOUNT}" -w 2>/dev/null`,
|
|
101
|
+
{ encoding: "utf-8", timeout: 5e3 }
|
|
102
|
+
).trim();
|
|
103
|
+
} catch {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function macKeychainSet(value, service = SERVICE) {
|
|
108
|
+
if (!nativeKeychainAllowed()) return false;
|
|
109
|
+
if (process.platform !== "darwin") return false;
|
|
110
|
+
try {
|
|
111
|
+
try {
|
|
112
|
+
execSync(
|
|
113
|
+
`security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
114
|
+
{ timeout: 5e3 }
|
|
115
|
+
);
|
|
116
|
+
} catch {
|
|
117
|
+
}
|
|
118
|
+
execSync(
|
|
119
|
+
`security add-generic-password -s "${service}" -a "${ACCOUNT}" -w "${value}"`,
|
|
120
|
+
{ timeout: 5e3 }
|
|
121
|
+
);
|
|
122
|
+
return true;
|
|
123
|
+
} catch {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
function macKeychainDelete(service = SERVICE) {
|
|
128
|
+
if (!nativeKeychainAllowed()) return false;
|
|
129
|
+
if (process.platform !== "darwin") return false;
|
|
130
|
+
try {
|
|
131
|
+
execSync(
|
|
132
|
+
`security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
133
|
+
{ timeout: 5e3 }
|
|
134
|
+
);
|
|
135
|
+
return true;
|
|
136
|
+
} catch {
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
function linuxSecretGet(service = SERVICE) {
|
|
141
|
+
if (!linuxSecretAvailable()) return null;
|
|
142
|
+
try {
|
|
143
|
+
return execSync(
|
|
144
|
+
`secret-tool lookup service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
145
|
+
{ encoding: "utf-8", timeout: 5e3 }
|
|
146
|
+
).trim();
|
|
147
|
+
} catch {
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
function linuxSecretSet(value, service = SERVICE) {
|
|
152
|
+
if (!linuxSecretAvailable()) return false;
|
|
153
|
+
try {
|
|
154
|
+
execSync(
|
|
155
|
+
`echo -n "${value}" | secret-tool store --label="exe-os master key" service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
156
|
+
{ timeout: 5e3 }
|
|
157
|
+
);
|
|
158
|
+
return true;
|
|
159
|
+
} catch {
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
function linuxSecretDelete(service = SERVICE) {
|
|
164
|
+
if (!nativeKeychainAllowed()) return false;
|
|
165
|
+
if (process.platform !== "linux") return false;
|
|
166
|
+
try {
|
|
167
|
+
execSync(
|
|
168
|
+
`secret-tool clear service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
169
|
+
{ timeout: 5e3 }
|
|
170
|
+
);
|
|
171
|
+
return true;
|
|
172
|
+
} catch {
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
async function tryKeytar() {
|
|
177
|
+
if (!nativeKeychainAllowed()) return null;
|
|
178
|
+
try {
|
|
179
|
+
return await import("keytar");
|
|
180
|
+
} catch {
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
var ENCRYPTED_PREFIX = "enc:";
|
|
185
|
+
function deriveMachineKey() {
|
|
186
|
+
try {
|
|
187
|
+
const material = [
|
|
188
|
+
os.hostname(),
|
|
189
|
+
os.userInfo().username,
|
|
190
|
+
os.arch(),
|
|
191
|
+
os.platform(),
|
|
192
|
+
// Machine ID on Linux (stable across reboots)
|
|
193
|
+
process.platform === "linux" ? readMachineId() : ""
|
|
194
|
+
].join("|");
|
|
195
|
+
return crypto.createHash("sha256").update(material).digest();
|
|
196
|
+
} catch {
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
function readMachineId() {
|
|
201
|
+
try {
|
|
202
|
+
return readFileSync("/etc/machine-id", "utf-8").trim();
|
|
203
|
+
} catch {
|
|
204
|
+
return "";
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
function encryptWithMachineKey(plaintext, machineKey) {
|
|
208
|
+
const iv = crypto.randomBytes(12);
|
|
209
|
+
const cipher = crypto.createCipheriv("aes-256-gcm", machineKey, iv);
|
|
210
|
+
let encrypted = cipher.update(plaintext, "utf-8", "base64");
|
|
211
|
+
encrypted += cipher.final("base64");
|
|
212
|
+
const authTag = cipher.getAuthTag().toString("base64");
|
|
213
|
+
return `${ENCRYPTED_PREFIX}${iv.toString("base64")}:${authTag}:${encrypted}`;
|
|
214
|
+
}
|
|
215
|
+
function decryptWithMachineKey(encrypted, machineKey) {
|
|
216
|
+
if (!encrypted.startsWith(ENCRYPTED_PREFIX)) return null;
|
|
217
|
+
try {
|
|
218
|
+
const parts = encrypted.slice(ENCRYPTED_PREFIX.length).split(":");
|
|
219
|
+
if (parts.length !== 3) return null;
|
|
220
|
+
const [ivB64, tagB64, cipherB64] = parts;
|
|
221
|
+
const iv = Buffer.from(ivB64, "base64");
|
|
222
|
+
const authTag = Buffer.from(tagB64, "base64");
|
|
223
|
+
const decipher = crypto.createDecipheriv("aes-256-gcm", machineKey, iv);
|
|
224
|
+
decipher.setAuthTag(authTag);
|
|
225
|
+
let decrypted = decipher.update(cipherB64, "base64", "utf-8");
|
|
226
|
+
decrypted += decipher.final("utf-8");
|
|
227
|
+
return decrypted;
|
|
228
|
+
} catch {
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
async function writeMachineBoundFileFallback(b64) {
|
|
233
|
+
const dir = getKeyDir();
|
|
234
|
+
await mkdir(dir, { recursive: true });
|
|
235
|
+
const keyPath = getKeyPath();
|
|
236
|
+
const machineKey = deriveMachineKey();
|
|
237
|
+
const content = machineKey ? encryptWithMachineKey(b64, machineKey) + "\n" : b64 + "\n";
|
|
238
|
+
const result = machineKey ? "encrypted" : "plaintext";
|
|
239
|
+
const tmpPath = keyPath + ".tmp";
|
|
240
|
+
try {
|
|
241
|
+
if (existsSync(keyPath)) {
|
|
242
|
+
await copyFile(keyPath, keyPath + ".bak").catch(() => {
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
await writeFile(tmpPath, content, "utf-8");
|
|
246
|
+
await chmod(tmpPath, 384);
|
|
247
|
+
await rename(tmpPath, keyPath);
|
|
248
|
+
} catch (err) {
|
|
249
|
+
try {
|
|
250
|
+
await unlink(tmpPath);
|
|
251
|
+
} catch {
|
|
252
|
+
}
|
|
253
|
+
throw err;
|
|
254
|
+
}
|
|
255
|
+
return result;
|
|
256
|
+
}
|
|
257
|
+
async function getMasterKey() {
|
|
258
|
+
let nativeValue = macKeychainGet() ?? linuxSecretGet();
|
|
259
|
+
if (!nativeValue) {
|
|
260
|
+
const legacyValue = macKeychainGet(LEGACY_SERVICE) ?? linuxSecretGet(LEGACY_SERVICE);
|
|
261
|
+
if (legacyValue) {
|
|
262
|
+
const migrated = macKeychainSet(legacyValue) || linuxSecretSet(legacyValue);
|
|
263
|
+
if (migrated) {
|
|
264
|
+
macKeychainDelete(LEGACY_SERVICE);
|
|
265
|
+
linuxSecretDelete(LEGACY_SERVICE);
|
|
266
|
+
process.stderr.write("[keychain] Migrated keychain service from exe-mem to exe-os.\n");
|
|
267
|
+
}
|
|
268
|
+
nativeValue = legacyValue;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
if (nativeValue) {
|
|
272
|
+
return Buffer.from(nativeValue, "base64");
|
|
273
|
+
}
|
|
274
|
+
const keytar = await tryKeytar();
|
|
275
|
+
if (keytar) {
|
|
276
|
+
try {
|
|
277
|
+
const keytarValue = await keytar.getPassword(SERVICE, ACCOUNT);
|
|
278
|
+
const legacyKeytarValue = keytarValue ?? await keytar.getPassword(LEGACY_SERVICE, ACCOUNT);
|
|
279
|
+
if (legacyKeytarValue) {
|
|
280
|
+
const migrated = macKeychainSet(legacyKeytarValue) || linuxSecretSet(legacyKeytarValue);
|
|
281
|
+
if (migrated) {
|
|
282
|
+
process.stderr.write("[keychain] Migrated key from keytar to native keychain.\n");
|
|
283
|
+
try {
|
|
284
|
+
await keytar.deletePassword(LEGACY_SERVICE, ACCOUNT);
|
|
285
|
+
} catch {
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
return Buffer.from(legacyKeytarValue, "base64");
|
|
289
|
+
}
|
|
290
|
+
} catch {
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
const keyPath = getKeyPath();
|
|
294
|
+
if (!existsSync(keyPath)) {
|
|
295
|
+
process.stderr.write(
|
|
296
|
+
`[keychain] Key not found at ${keyPath} (HOME=${os.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
|
|
297
|
+
`
|
|
298
|
+
);
|
|
299
|
+
return null;
|
|
300
|
+
}
|
|
301
|
+
try {
|
|
302
|
+
const content = (await readFile(keyPath, "utf-8")).trim();
|
|
303
|
+
let b64Value;
|
|
304
|
+
if (content.startsWith(ENCRYPTED_PREFIX)) {
|
|
305
|
+
const machineKey = deriveMachineKey();
|
|
306
|
+
if (!machineKey) {
|
|
307
|
+
process.stderr.write("[keychain] Cannot derive machine key to decrypt stored key.\n");
|
|
308
|
+
return null;
|
|
309
|
+
}
|
|
310
|
+
const decrypted = decryptWithMachineKey(content, machineKey);
|
|
311
|
+
if (!decrypted) {
|
|
312
|
+
process.stderr.write(
|
|
313
|
+
"[keychain] Key decryption failed \u2014 machine may have changed.\n Use your 24-word recovery phrase during setup: exe-os setup\n"
|
|
314
|
+
);
|
|
315
|
+
return null;
|
|
316
|
+
}
|
|
317
|
+
b64Value = decrypted;
|
|
318
|
+
} else {
|
|
319
|
+
b64Value = content;
|
|
320
|
+
}
|
|
321
|
+
const key = Buffer.from(b64Value, "base64");
|
|
322
|
+
if (isRootOnlyTrustedServerKeyFile(keyPath)) {
|
|
323
|
+
return key;
|
|
324
|
+
}
|
|
325
|
+
const migrated = macKeychainSet(b64Value) || linuxSecretSet(b64Value);
|
|
326
|
+
if (migrated) {
|
|
327
|
+
process.stderr.write("[keychain] Migrated key from file to native keychain.\n");
|
|
328
|
+
try {
|
|
329
|
+
await unlink(keyPath);
|
|
330
|
+
process.stderr.write("[keychain] Removed legacy master.key file after native keychain migration.\n");
|
|
331
|
+
} catch {
|
|
332
|
+
}
|
|
333
|
+
} else if (!content.startsWith(ENCRYPTED_PREFIX)) {
|
|
334
|
+
const fallback = await writeMachineBoundFileFallback(b64Value);
|
|
335
|
+
if (fallback === "encrypted") {
|
|
336
|
+
process.stderr.write("[keychain] Upgraded legacy plaintext master.key to machine-bound encrypted fallback.\n");
|
|
337
|
+
} else {
|
|
338
|
+
process.stderr.write(
|
|
339
|
+
"[keychain] WARNING: Could not encrypt legacy master.key \u2014 plaintext fallback remains.\n"
|
|
340
|
+
);
|
|
341
|
+
warnPlaintextFallback();
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
return key;
|
|
345
|
+
} catch (err) {
|
|
346
|
+
process.stderr.write(
|
|
347
|
+
`[keychain] Key read failed at ${keyPath}: ${err instanceof Error ? err.message : String(err)}
|
|
348
|
+
`
|
|
349
|
+
);
|
|
350
|
+
return null;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
async function getKeyStorageInfo() {
|
|
354
|
+
if (macKeychainGet()) {
|
|
355
|
+
return {
|
|
356
|
+
kind: "macos-keychain",
|
|
357
|
+
secure: true,
|
|
358
|
+
note: "stored in macOS Keychain via built-in security CLI"
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
if (macKeychainGet(LEGACY_SERVICE)) {
|
|
362
|
+
return {
|
|
363
|
+
kind: "macos-keychain",
|
|
364
|
+
secure: true,
|
|
365
|
+
note: "stored in legacy macOS Keychain service exe-mem; next key read migrates it to exe-os"
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
if (linuxSecretGet()) {
|
|
369
|
+
return {
|
|
370
|
+
kind: "linux-secret-service",
|
|
371
|
+
secure: true,
|
|
372
|
+
note: "stored in Linux Secret Service via secret-tool"
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
if (linuxSecretGet(LEGACY_SERVICE)) {
|
|
376
|
+
return {
|
|
377
|
+
kind: "linux-secret-service",
|
|
378
|
+
secure: true,
|
|
379
|
+
note: "stored in legacy Linux Secret Service service exe-mem; next key read migrates it to exe-os"
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
const keytar = await tryKeytar();
|
|
383
|
+
if (keytar) {
|
|
384
|
+
try {
|
|
385
|
+
if (await keytar.getPassword(SERVICE, ACCOUNT)) {
|
|
386
|
+
return {
|
|
387
|
+
kind: "legacy-keytar",
|
|
388
|
+
secure: true,
|
|
389
|
+
note: "stored in legacy keytar backend; will migrate to native keychain when possible"
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
if (await keytar.getPassword(LEGACY_SERVICE, ACCOUNT)) {
|
|
393
|
+
return {
|
|
394
|
+
kind: "legacy-keytar",
|
|
395
|
+
secure: true,
|
|
396
|
+
note: "stored in legacy keytar service exe-mem; will migrate to native exe-os keychain when possible"
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
} catch {
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
const keyPath = getKeyPath();
|
|
403
|
+
if (!existsSync(keyPath)) {
|
|
404
|
+
return {
|
|
405
|
+
kind: "missing",
|
|
406
|
+
secure: false,
|
|
407
|
+
path: keyPath,
|
|
408
|
+
note: "no key found in OS keychain, legacy keytar, or file fallback"
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
try {
|
|
412
|
+
const content = (await readFile(keyPath, "utf-8")).trim();
|
|
413
|
+
if (content.startsWith(ENCRYPTED_PREFIX)) {
|
|
414
|
+
return {
|
|
415
|
+
kind: "encrypted-file",
|
|
416
|
+
secure: true,
|
|
417
|
+
path: keyPath,
|
|
418
|
+
note: "stored in machine-bound encrypted file fallback"
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
if (isRootOnlyTrustedServerKeyFile(keyPath)) {
|
|
422
|
+
return {
|
|
423
|
+
kind: "server-secret-file",
|
|
424
|
+
secure: true,
|
|
425
|
+
path: keyPath,
|
|
426
|
+
note: "stored as root-only trusted server secret file"
|
|
427
|
+
};
|
|
428
|
+
}
|
|
429
|
+
return {
|
|
430
|
+
kind: "plaintext-file",
|
|
431
|
+
secure: false,
|
|
432
|
+
path: keyPath,
|
|
433
|
+
note: "stored in legacy plaintext file; reading it will migrate or encrypt it"
|
|
434
|
+
};
|
|
435
|
+
} catch {
|
|
436
|
+
return {
|
|
437
|
+
kind: "missing",
|
|
438
|
+
secure: false,
|
|
439
|
+
path: keyPath,
|
|
440
|
+
note: "key file exists but could not be read"
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
async function setMasterKey(key) {
|
|
445
|
+
const b64 = key.toString("base64");
|
|
446
|
+
let keychainOk = false;
|
|
447
|
+
if (macKeychainSet(b64)) {
|
|
448
|
+
const readBack = macKeychainGet();
|
|
449
|
+
if (readBack === b64) {
|
|
450
|
+
keychainOk = true;
|
|
451
|
+
} else {
|
|
452
|
+
process.stderr.write(
|
|
453
|
+
"[keychain] macOS Keychain write appeared to succeed but read-back failed.\n This can happen on macOS Tahoe with new permission patterns.\n"
|
|
454
|
+
);
|
|
455
|
+
}
|
|
456
|
+
} else if (linuxSecretSet(b64)) {
|
|
457
|
+
const readBack = linuxSecretGet();
|
|
458
|
+
if (readBack === b64) {
|
|
459
|
+
keychainOk = true;
|
|
460
|
+
} else {
|
|
461
|
+
process.stderr.write("[keychain] Linux secret-tool write appeared to succeed but read-back failed.\n");
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
if (!keychainOk) {
|
|
465
|
+
const keytar = await tryKeytar();
|
|
466
|
+
if (keytar) {
|
|
467
|
+
try {
|
|
468
|
+
await keytar.setPassword(SERVICE, ACCOUNT, b64);
|
|
469
|
+
keychainOk = true;
|
|
470
|
+
} catch {
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
const fallback = await writeMachineBoundFileFallback(b64);
|
|
475
|
+
if (keychainOk) {
|
|
476
|
+
process.stderr.write("[keychain] Key stored in OS keychain (file backup also written).\n");
|
|
477
|
+
} else if (fallback === "encrypted") {
|
|
478
|
+
process.stderr.write("[keychain] Key stored encrypted (machine-bound file fallback).\n");
|
|
479
|
+
} else {
|
|
480
|
+
process.stderr.write(
|
|
481
|
+
"[keychain] WARNING: Key stored in plaintext file \u2014 no OS keychain available.\n"
|
|
482
|
+
);
|
|
483
|
+
warnPlaintextFallback();
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
async function deleteMasterKey() {
|
|
487
|
+
macKeychainDelete();
|
|
488
|
+
linuxSecretDelete();
|
|
489
|
+
macKeychainDelete(LEGACY_SERVICE);
|
|
490
|
+
linuxSecretDelete(LEGACY_SERVICE);
|
|
491
|
+
const keytar = await tryKeytar();
|
|
492
|
+
if (keytar) {
|
|
493
|
+
try {
|
|
494
|
+
await keytar.deletePassword(SERVICE, ACCOUNT);
|
|
495
|
+
await keytar.deletePassword(LEGACY_SERVICE, ACCOUNT);
|
|
496
|
+
} catch {
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
const keyPath = getKeyPath();
|
|
500
|
+
if (existsSync(keyPath)) {
|
|
501
|
+
await unlink(keyPath);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
async function loadBip39() {
|
|
505
|
+
try {
|
|
506
|
+
return await import("bip39");
|
|
507
|
+
} catch {
|
|
508
|
+
throw new Error(
|
|
509
|
+
"bip39 package not found. Run: npm install -g bip39\nOr reinstall exe-os: npm install -g @askexenow/exe-os"
|
|
510
|
+
);
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
async function exportMnemonic(key) {
|
|
514
|
+
if (key.length !== 32) {
|
|
515
|
+
throw new Error(`Key must be 32 bytes, got ${key.length}`);
|
|
516
|
+
}
|
|
517
|
+
const { entropyToMnemonic } = await loadBip39();
|
|
518
|
+
return entropyToMnemonic(key.toString("hex"));
|
|
519
|
+
}
|
|
520
|
+
async function importMnemonic(mnemonic) {
|
|
521
|
+
const trimmed = mnemonic.trim();
|
|
522
|
+
const words = trimmed.split(/\s+/);
|
|
523
|
+
if (words.length !== 24) {
|
|
524
|
+
throw new Error(`Expected 24 words, got ${words.length}`);
|
|
525
|
+
}
|
|
526
|
+
const { validateMnemonic, mnemonicToEntropy } = await loadBip39();
|
|
527
|
+
if (!validateMnemonic(trimmed)) {
|
|
528
|
+
throw new Error("Invalid mnemonic \u2014 check for typos or missing words");
|
|
529
|
+
}
|
|
530
|
+
const entropy = mnemonicToEntropy(trimmed);
|
|
531
|
+
return Buffer.from(entropy, "hex");
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
export {
|
|
535
|
+
getMasterKey,
|
|
536
|
+
getKeyStorageInfo,
|
|
537
|
+
setMasterKey,
|
|
538
|
+
deleteMasterKey,
|
|
539
|
+
exportMnemonic,
|
|
540
|
+
importMnemonic
|
|
541
|
+
};
|