elanous 0.2.37 → 0.2.38
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/apps/pwa/out/404/index.html +1 -1
- package/apps/pwa/out/404.html +1 -1
- package/apps/pwa/out/_next/static/{8kITumG9GAZ1LwT9POrAR → RrjXTwz-urRAbChP1bX02}/_buildManifest.js +1 -1
- package/apps/pwa/out/_next/static/chunks/{2002-a43a3f380df873ec.js → 1026-44010f405704050c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1118.a8a74ea29aac3e46.js +27 -0
- package/apps/pwa/out/_next/static/chunks/1204-2aa830479adf80f4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1341-43b7d2dc77d45c9d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1440-c3ea8882badfd9bf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7424.c0fe2a595d4232b5.js → 1632.7d87f998e714bede.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1698-9c11cbf97f13717e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1770-3b1fc92253ef9f2f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4937-28d437999b77c9dd.js → 1923-5c1695332240246a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1938.0e6c60ee91c4d7f5.js +148 -0
- package/apps/pwa/out/_next/static/chunks/2104.70e086d5174a4736.js +1 -0
- package/apps/pwa/out/_next/static/chunks/213-20675f20673ba22a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/214.186a430da28338f1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2277.3bd4c0ac7f1b5996.js +93 -0
- package/apps/pwa/out/_next/static/chunks/240.e09f433f71c78ff4.js +104 -0
- package/apps/pwa/out/_next/static/chunks/{3199.6a1a9b0e6cd01dc6.js → 2415.738b777642a02233.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2417.02151393605a7cd0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2463.cd2641a76daaa9ff.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2576.b9e9c629c4b84c52.js +1 -0
- package/apps/pwa/out/_next/static/chunks/265-c021de53f0865bd9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2998-b1cc13956cd6a6e7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2e4782d3.ba2f0ab2b63a53e7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1262.a89bb27a5b2f844e.js → 3086.fb14b60ce98b53d3.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3124-561f7f037943cde2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3130.626b54382b4dc379.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3221-1bb3f99a55088613.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3280.24edb1ffd03a7f3f.js +24 -0
- package/apps/pwa/out/_next/static/chunks/3288-eb3c22a1cbf2ae68.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2283.edd9627b7bdfb546.js → 3291.f6c1005387d514bd.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/33.ef99e8374f96c6c4.js +36 -0
- package/apps/pwa/out/_next/static/chunks/{6877-84d47b7e85d0c41e.js → 3341-f09b9efbd7a82f70.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3389.012c70767a872f9b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3410-d7c0f14b329d6fda.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3421.c87d6313a7d670f7.js +287 -0
- package/apps/pwa/out/_next/static/chunks/3422-83a3953f9bd67e26.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6680.6a693c28aae4cd19.js → 3528.e4b8ab70d339f965.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3587-002e24e368c515a9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3644.f12a7d821ab940af.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3660.d7516588e2d875c3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3695.b82e2610f4cd4ea9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3858.ca1f5bc0f577eac9.js +94 -0
- package/apps/pwa/out/_next/static/chunks/3959-e6ac4a139d9d4bcc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3f0de3de-2340c532c00395db.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4032.53f62176514ec0ea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4199-f7c6eb40cd0322f8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4204-ef8484cbecd5d62f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4259-163129ca79913c4b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/428-eaa77df3d0c85969.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4432-97e400ffa1e161f5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/449-aa427cf2cbb75f50.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4491-39a0fd32bbaf3840.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4588.b7cf06d382953979.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4690.70ec8060825366ab.js +32 -0
- package/apps/pwa/out/_next/static/chunks/{4036.d54e55e1ebf5acdc.js → 4804.6012b5cd33c22792.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/4881.e4d22d730e3b9df5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4937.ce2e340dc29cad3e.js +79 -0
- package/apps/pwa/out/_next/static/chunks/5-bb1c08d84bd71df3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5005.de98df23b37cdf3c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5035.dc64a89cad5573cc.js +74 -0
- package/apps/pwa/out/_next/static/chunks/5041-5aada92ca215ffdd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6819.be5c9c4d67f22922.js → 5203.51e5d8b5f1dcfe53.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/5207.1a224035455790fd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{757-4fbaf50942b8c424.js → 5255-1b60d50eabe9f057.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5269.d0436ee6d773382a.js +286 -0
- package/apps/pwa/out/_next/static/chunks/5300.677c97e0393742e6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7867.e8725745ddd1d940.js → 5307.d7328020227880c2.js} +4 -4
- package/apps/pwa/out/_next/static/chunks/5309.3367c4d50f52b489.js +1 -0
- package/apps/pwa/out/_next/static/chunks/552-689827d49780fa00.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5539.34cc9d60622cb69b.js +8 -0
- package/apps/pwa/out/_next/static/chunks/5568.218dea0c00ca2ec7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5046.7fd5cbd859299448.js → 5638.107314dc479e2f37.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5645.b7e3b055455a04ea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5662.18cc0f30353cbd96.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5671.da24fc9dc5e98325.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5b141171.324c40fd49cb6821.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6142.913b44e260a3f925.js +64 -0
- package/apps/pwa/out/_next/static/chunks/6175-d4621f6a10b0cfab.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6290.3eb53a20746b72ce.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6415-9307f3eafa90837f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6493.27ad77de7aac7966.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6579-3de35d00aacd71b5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/680-2f324c4e039a5b67.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6845-331b3c7481da3ba3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1224.2ceca6c180d5130b.js → 7000.28157393caaf5343.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{6745-5a63492933959dd9.js → 7161-8f22db3ec5ed005e.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/{2479-fe7e188bd9402d14.js → 7311-60a7ea80d23c7521.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7401.525d0a12f7d02c06.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7438.c2cf72b66dca6aa4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5952.294fc574a8625184.js → 7488.966b116789f3d41a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7524.ce973525d30b3d52.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7573.2376e13c9c21f1f8.js +77 -0
- package/apps/pwa/out/_next/static/chunks/7577.ea6e9ac72e035520.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6252.240578f10952e091.js → 7628.6b16863ac3972333.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7657.8d1fb3d2f7ebe273.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7903-1435d5d2f0dd7807.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1746.3563617ea64023a3.js → 7954.4f7a8832663ee979.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7978-30a91192c5dbe3c2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4931.95cc6dbd230774ca.js → 8019.21ca554a821dad01.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/8025-8795821525cf1a07.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8191.3674a00f0b565c23.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8217-604955d8885c5ef2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8298-eed6f5f2585a63f4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2375.bf364c85dbb6f085.js → 8487.291666583bebe640.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8509.3a54d4e61893d7cb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8758.ac421f726a189125.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4383.18e5c54db3a22c88.js → 8879.ac06755bcf3e44a1.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/891.d6c723a51a067b36.js +149 -0
- package/apps/pwa/out/_next/static/chunks/{9151.a2c51e93f9156dae.js → 8911.bf5e712acb25fb6c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{58edce7d.f1b0c72acf13b123.js → 8994d93e.33ba491f95345fc2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{5f6af561-f90b7a67f4f75d13.js → 89d6c04f-6b8ab341748e468a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9223.cbcc88e0e9950426.js +41 -0
- package/apps/pwa/out/_next/static/chunks/9299.24e2a7d9b6d1f91b.js +226 -0
- package/apps/pwa/out/_next/static/chunks/9317.6a9869039c231bb3.js +24 -0
- package/apps/pwa/out/_next/static/chunks/9383.e4755f275b3c11ff.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9581.da63ddf41acfad46.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9715.8c5529a0a5c41a36.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9817.3009d65f0889ef1f.js +2 -0
- package/apps/pwa/out/_next/static/chunks/{de8446d3.31b73eb239fecd7b.js → 9fe1b809.738da85c8b17e3fb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-76873dd80da4f715.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-ed32b6ec5dea8f23.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-fdd40e15babf3d25.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-384efc78e85e400b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-866aac5ff226a7f3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-d91809c5aeed319a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-128f3522f89a81ab.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-595961abf3b43ad1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-f41dccb76d8c0263.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-a3205c2e28b7d0d9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-c39a80277814a3f4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-1ab3f98194513195.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-a5246f7e254d77d0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-0f92287bdb81217d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-5a37131ff63793ef.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-76873dd80da4f715.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-ac4bd14bb2348bfd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/{page-5c112c6d7c33656e.js → page-c348a3959c5b5fc6.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-2addd81c0d3e2906.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-da6b765f58a3eefb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-0661e40f8780c32c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-b89af1b1c8e4875b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-da8aeb82ba751cdb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-cc71317b239439db.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-bde7fc1d64ffe369.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-e2797214f713fa58.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-2a35bcda70defaf6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-3af03deedde45032.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/{page-88a1edbff62eaf1d.js → page-d1d1210f99f620ae.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-46d1b5500885861d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-291ab19fe2acb173.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/{page-b9af2ac1c4737ce8.js → page-7f569e533ddeecba.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-990129c9fee46d8f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-7737f785ebb1cdaf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-9f3c73a4f7ffd2f8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-03be7fb347f01058.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-96b0280625e4df2b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-56855545049eb56d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-76873dd80da4f715.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-79a909c9981f0338.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/{page-fb9e639c107f5f72.js → page-a9d9a3e66459c1e0.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-c383cbf2013f7069.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-f57c6a2e54dbdca4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-6b140f77593576eb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-6b767ae2d9d0adfc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-116d6198d5da0e3d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-b9c9b778c7501370.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-a6c78392ab8f6335.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-455183deb4ed0cfe.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-6a63e99526bd63d0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-31c22caafe788c08.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{709a918c.4fd3b4e2a32cb4e3.js → b7459770.6539b11860eb8a9c.js} +7 -7
- package/apps/pwa/out/_next/static/chunks/{d9815f84.4918f682a45a8502.js → b7478fef.5917716286213fcc.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/{4337e36d.f42c3b391b3d8f20.js → bb6987f9.3647e1a23b0e3217.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/de8b930d.d94c0f42acf807fc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8c58d09b.e8724a299658d86f.js → eaad0cba.771200940c529df7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/framework-4b12a946f352cee2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-941155250ed2644b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-f8b6765abed6d149.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-78432194c85388f9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-cdf7390829512b1b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-d5f0964a9c2e92d2.js +1 -0
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +22 -22
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +22 -22
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +22 -22
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +21 -21
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +21 -21
- package/apps/pwa/out/ceo/index.html +1 -1
- package/apps/pwa/out/ceo/index.txt +22 -22
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +21 -21
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +22 -22
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +22 -22
- package/apps/pwa/out/decisions/index.html +1 -1
- package/apps/pwa/out/decisions/index.txt +21 -21
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +22 -22
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +22 -22
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +22 -22
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +22 -22
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +21 -21
- package/apps/pwa/out/inside/index.html +1 -1
- package/apps/pwa/out/inside/index.txt +21 -21
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +22 -22
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +22 -22
- package/apps/pwa/out/live-run/index.html +1 -1
- package/apps/pwa/out/live-run/index.txt +22 -22
- package/apps/pwa/out/loops/index.html +1 -1
- package/apps/pwa/out/loops/index.txt +21 -21
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +21 -21
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +21 -21
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +22 -22
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +22 -22
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +21 -21
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +21 -21
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +21 -21
- package/apps/pwa/out/outputs/index.html +1 -1
- package/apps/pwa/out/outputs/index.txt +21 -21
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +22 -22
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +22 -22
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +21 -21
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +22 -22
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +22 -22
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +22 -22
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +22 -22
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +22 -22
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +21 -21
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +22 -22
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +22 -22
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +22 -22
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +22 -22
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +22 -22
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +22 -22
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +22 -22
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +22 -22
- package/graphs/release/recipes.yaml +9 -0
- package/graphs/release/release-loop.yaml +26 -18
- package/package.json +1 -1
- package/scripts/ask-op-inbox-once.ts +17 -0
- package/scripts/brand/check.ts +13 -4
- package/scripts/gate-0226-accepted-remaining-90.txt +91 -0
- package/scripts/gate-0226-failure-census.ts +39 -0
- package/scripts/intake-collect-telegram-saved-stage.ts +48 -0
- package/scripts/provision-export-redactions.ts +15 -0
- package/scripts/public-copy-lint.ts +122 -0
- package/scripts/public-export.ts +69 -2
- package/scripts/ratchets/next-tui-entry-budget.ts +124 -0
- package/scripts/ratchets/train-side-invariants.sh +7 -1
- package/scripts/release-loop/cut-branch.ts +61 -12
- package/scripts/release-loop/gate-node.ts +161 -25
- package/scripts/release-loop/gate-partial.ts +82 -3
- package/scripts/release-loop/gate-prewarm-plan.ts +35 -0
- package/scripts/release-loop/gate-radius-live.ts +4 -2
- package/scripts/release-loop/resume-cap.ts +2 -1
- package/scripts/release-loop/resume-release.ts +297 -8
- package/scripts/release-loop/resume.ts +13 -5
- package/scripts/release-loop/traffic-node.ts +12 -4
- package/scripts/release-loop/traffic-transition.ts +53 -13
- package/scripts/release-loop/version-node.ts +29 -4
- package/scripts/ux-sim.ts +1 -1
- package/scripts/video-pipeline.ts +2 -2
- package/src/acp/core-turn-bridge.ts +6 -1
- package/src/agent/run-context.ts +1 -1
- package/src/agent/task-notification.ts +3 -1
- package/src/agent-substrate/review-observation.ts +10 -0
- package/src/agent-substrate/self-review-cli.ts +195 -27
- package/src/auto-research/question-ladder-contract.ts +137 -0
- package/src/auto-research/research-turn.ts +134 -0
- package/src/autopilot/discovery/doc-lint.ts +1 -1
- package/src/bots/screen-probe.ts +1 -1
- package/src/capture/tui-self-report.ts +10 -2
- package/src/chat/index.ts +1 -0
- package/src/chat/tool-render/dispatch.ts +8 -1
- package/src/cli/guardian-cli.ts +3 -1
- package/src/cli/intake-cli.ts +48 -12
- package/src/cli/lesson-cli.ts +69 -9
- package/src/cli/pr-land-overlap-evidence.ts +38 -5
- package/src/cli/pr-land-refusal.ts +1 -1
- package/src/cli/pty-takeover-cli.ts +58 -5
- package/src/cli/release-checklist-read-cli.ts +5 -2
- package/src/cli/release-cli.ts +47 -9
- package/src/cli/review-carry.ts +77 -0
- package/src/cli/self-update.ts +1 -1
- package/src/cli/tasks-card-show.ts +31 -1
- package/src/cli/tasks-cli.ts +62 -23
- package/src/cli/tasks-read-cli.ts +13 -5
- package/src/context-bus/context-now.ts +86 -2
- package/src/core-turn/run-core-turn.ts +9 -2
- package/src/core-turn/types.ts +3 -0
- package/src/dashboard/index.ts +18 -17
- package/src/dashboard/input/terminal-modal-router.ts +8 -159
- package/src/dashboard/side-basic-runtime.ts +61 -0
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +2 -0
- package/src/dashboard/term-slash-runtime.ts +2 -0
- package/src/dashboard/turn-preamble.ts +28 -4
- package/src/domains/guardian-tick.ts +9 -0
- package/src/git-fs/watcher.ts +27 -22
- package/src/git-fs/worktree.ts +19 -3
- package/src/graph-runner/graph-grow.ts +37 -9
- package/src/graph-runner/runner.ts +17 -2
- package/src/grok/credential.ts +107 -36
- package/src/hq/fence-wrapper.ts +1 -1
- package/src/hq/transfer.ts +1 -1
- package/src/index.ts +44 -14
- package/src/intake-plane/collect-telegram-saved.ts +54 -5
- package/src/interactive-terminal-modal.ts +3 -0
- package/src/keybindings.ts +17 -22
- package/src/llm/provider-credentials.ts +1 -1
- package/src/llm-tool-schema.ts +20 -0
- package/src/llm.ts +81 -11
- package/src/loops/orchestrator/inbox-once.ts +28 -0
- package/src/loops/orchestrator/inbox.ts +130 -1
- package/src/loops/orchestrator/tick.ts +6 -3
- package/src/maturity/feature-maturity.ts +1 -0
- package/src/nexus/api/channel-ask-op.ts +96 -0
- package/src/nexus/api/discord-trigger-bot.ts +28 -1
- package/src/nexus/api/telegram-trigger-bot.ts +24 -0
- package/src/nexus/api/terminals.ts +28 -6
- package/src/patents/ledger.ts +18 -1
- package/src/preview/terminal.ts +4 -2
- package/src/prompt-cache/anthropic.ts +2 -0
- package/src/prompt-enhance/enhance.ts +5 -0
- package/src/pty-shell/pty-manifest.ts +16 -2
- package/src/release-loop/gate-shards.ts +61 -0
- package/src/release-loop/light-rc.ts +7 -4
- package/src/release-loop/rehearsal.ts +1 -1
- package/src/repl/index.ts +10 -0
- package/src/research/axis-fanout.ts +133 -0
- package/src/research/edge-decision.ts +88 -0
- package/src/research/output-router.ts +127 -0
- package/src/research-bridge/format.ts +16 -1
- package/src/research-bridge/index.ts +1 -0
- package/src/research-bridge/invoke.ts +41 -5
- package/src/self-dev/decompose.ts +45 -9
- package/src/self-dev/draft-residue.ts +221 -2
- package/src/self-dev/draft-sweep.ts +29 -16
- package/src/self-dev/orchestrate.ts +1 -0
- package/src/self-dev/run-supervisor.ts +22 -7
- package/src/self-dev/shard-run.ts +260 -3
- package/src/self-implement/comment-only-source.ts +54 -0
- package/src/self-implement/doctor-visit.ts +25 -0
- package/src/self-implement/gate-artifacts.ts +2 -2
- package/src/self-implement/gate-baseline.ts +44 -9
- package/src/self-implement/gate-cli.ts +151 -86
- package/src/self-implement/gate-failure-signature.ts +44 -0
- package/src/self-implement/gate-remote.ts +2 -0
- package/src/self-implement/goal-author.ts +74 -3
- package/src/self-implement/goal-doc/section.ts +22 -0
- package/src/self-implement/goal-supervisor-fill.ts +38 -4
- package/src/self-implement/knowhow-pack.ts +120 -7
- package/src/self-implement/l8-merge-queue.ts +198 -32
- package/src/self-implement/off-diff-evidence.ts +23 -0
- package/src/self-implement/orchestrator.ts +55 -12
- package/src/self-implement/pod-inplace-worktree.ts +82 -0
- package/src/self-implement/pod-warm-pool-profile.ts +2 -2
- package/src/self-implement/premise-review.ts +7 -5
- package/src/self-implement/run-ledger.ts +258 -0
- package/src/self-implement/seams.ts +33 -10
- package/src/self-implement/self-implement-cli.ts +26 -2
- package/src/session/channel-ask-op-envelope.ts +36 -0
- package/src/session/channel-op-reply-route.ts +200 -0
- package/src/session/chat.ts +3 -0
- package/src/session/index.ts +2 -0
- package/src/session-runtime/index.ts +9 -22
- package/src/skills/runner.ts +7 -3
- package/src/skills/tools/dev-harness.ts +2 -2
- package/src/skills/tools/schedule-wakeup.ts +1 -6
- package/src/status/bar.ts +3 -3
- package/src/storage/file-lock.ts +17 -4
- package/src/task-agent/adopt-pr.ts +63 -2
- package/src/task-agent/evidence-command-normalize.ts +42 -0
- package/src/task-agent/export-redactions-provision.ts +43 -0
- package/src/task-agent/parent-host.ts +59 -12
- package/src/task-agent/repair-cycle.ts +67 -8
- package/src/task-agent/repair-worker.ts +37 -1
- package/src/task-agent/task-hand.ts +98 -10
- package/src/task-agent/tier-split.ts +37 -3
- package/src/task-orchestrator/surfaces/pod-failure-reason.ts +31 -4
- package/src/task-orchestrator/surfaces/pod-pool.ts +27 -4
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +126 -48
- package/src/task-orchestrator/surfaces/self-implement.ts +33 -2
- package/src/terminal/session-registry.ts +1 -0
- package/src/terminal/terminal-modal-router.ts +156 -0
- package/src/tool-hints/gate.ts +6 -4
- package/src/tool-hints/signals.ts +33 -1
- package/src/tui/chat/background-job-status.ts +8 -2
- package/src/tui/entry.ts +469 -31
- package/src/tui/sidetab/attach.ts +304 -0
- package/src/tui/sidetab/list.ts +176 -0
- package/src/tui/sidetab/nl-tool.ts +136 -0
- package/src/tui/slash/resume-command.ts +23 -0
- package/src/tui/slash/resume.ts +3 -23
- package/src/tui/slash/term-next.ts +2 -1
- package/src/tui-client/local-chat-turn.ts +29 -8
- package/src/user-config.ts +11 -2
- package/src/ux-sim/fake-llm.ts +11 -5
- package/src/ux-sim/next-tui-seat-scenarios.ts +53 -1
- package/src/version/packed-revision.json +1 -1
- package/apps/pwa/out/_next/static/chunks/1041-5841aae848fb6403.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1087.3177e54f672dc526.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1105.efe1e13503ac7a33.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1417-1768233ac92f8a5d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1612.81bbc19af06af16c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1766.728d42053070bb2d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1773.d38e945481e04125.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1974-c12f9600da3d3c26.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1ed5e8af.cf424815c7c0efad.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2061.7232dc9dc058417f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/210.90b2cbd64926cf34.js +0 -32
- package/apps/pwa/out/_next/static/chunks/2318-450e75d07605b8fe.js +0 -1
- package/apps/pwa/out/_next/static/chunks/244-a810d282a20f1783.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2514.03b60f266531a015.js +0 -148
- package/apps/pwa/out/_next/static/chunks/2526-a657538869888604.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2533-6f0341ff075809e9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2676.e7994c695ef0f30d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2734.3ffdf54254fb6f99.js +0 -27
- package/apps/pwa/out/_next/static/chunks/2770-23252bf3a37880b9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2969.66b8b545139d1544.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3128.a9210d08800ea6a8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3212.12179fd3eee8cef1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3578.4e9f9948a9a6f2f4.js +0 -2
- package/apps/pwa/out/_next/static/chunks/3760-2909ddb9279281cd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3825.1921b5901bf33dce.js +0 -36
- package/apps/pwa/out/_next/static/chunks/3994-63eb884ed0547011.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4115.5b438b99f0ae729f.js +0 -226
- package/apps/pwa/out/_next/static/chunks/4269.d8f9f34bb0fc6c43.js +0 -287
- package/apps/pwa/out/_next/static/chunks/431-4eed5bd2c5fe1719.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4313.76f232c304a15bde.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4324.c99ba3e83eb1b691.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4599-96eff3f2a9c242c1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4725-34bed25720cc326b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4825-a9d9d4e9f5892309.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4833-7934c592c5569f00.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4879-68518f547a207aff.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4896.f9b70285363b27b2.js +0 -24
- package/apps/pwa/out/_next/static/chunks/49aa54ab.80f39398e0ed0f30.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5056.482687319b82638e.js +0 -104
- package/apps/pwa/out/_next/static/chunks/506.16b83d56a437a9ee.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5260-20593b0a25d0afbc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5404.cc4e9fec26fd5925.js +0 -1
- package/apps/pwa/out/_next/static/chunks/576.485e83e3f3dec19a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5832-a6be14e663f65726.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5854-56648a9fe646b9a0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5925.3b1f8b135710249b.js +0 -93
- package/apps/pwa/out/_next/static/chunks/6168.17749aa3905fa073.js +0 -74
- package/apps/pwa/out/_next/static/chunks/6416.5d50b8ec9986ca98.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6758.e7fbf532953c0783.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6795.0cb8a59730d99703.js +0 -149
- package/apps/pwa/out/_next/static/chunks/6971-fb5f9dc0a2cb5d2d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/717.522b08685979b814.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7191.e41eb8f455c7f089.js +0 -41
- package/apps/pwa/out/_next/static/chunks/7233.8e744b7513119409.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7238-97c2226f80504bd8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7285.307963afcf7e7660.js +0 -24
- package/apps/pwa/out/_next/static/chunks/7299-fbe4b8c47a87614a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7314.df0d95930b0c3f50.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7406.c0589fdf2ee66629.js +0 -1
- package/apps/pwa/out/_next/static/chunks/752-90e3e7daad3d8e39.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7524-bcd3d9928c6842d9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7549.9a4de3bf231cfc52.js +0 -1
- package/apps/pwa/out/_next/static/chunks/765.76ae970ceb597b5b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7893-e444a1b0809cd1e4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7956-33748cabb3a05562.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7c5ed21f-f286708e57cf88f7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8030-aa66b478b53dbfca.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8051.c88c07dacbbc5f21.js +0 -8
- package/apps/pwa/out/_next/static/chunks/8080-40d781e7704d3671.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8149.80e402d4345e8dae.js +0 -77
- package/apps/pwa/out/_next/static/chunks/8205.50a5268f4e12ba0b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8231.a128feaa6f8b6079.js +0 -1
- package/apps/pwa/out/_next/static/chunks/85.4ddb1dda2ea3ffa2.js +0 -286
- package/apps/pwa/out/_next/static/chunks/8537.26517a09e8247beb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8595-e9b7081ab773a61f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8821-30cc65a61a60951f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8905.b3385aadb7b133e6.js +0 -79
- package/apps/pwa/out/_next/static/chunks/8983.246bb3a1ac38f50f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9072.18342f5941a1f3ec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9123.9df04866b2d6e00f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9175-7d383df15a82e2be.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9181-bf89c07ce5b8f599.js +0 -1
- package/apps/pwa/out/_next/static/chunks/920-429bbc4504b45f71.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9207.625edf45d656151c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9378.d2575c6ffd6dd756.js +0 -94
- package/apps/pwa/out/_next/static/chunks/957.db5b5c4d32a35240.js +0 -1
- package/apps/pwa/out/_next/static/chunks/958.53a8dcf4729e6997.js +0 -64
- package/apps/pwa/out/_next/static/chunks/9647.8f0cd0898c592a29.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9665-26abb02665704c2c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9703.e7d81b6faef1050a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9882-7a9164b3c2dacbe5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9998.b74e033efadecd10.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-c604fb980a634d88.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-ec2d8a4979ca9075.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-cb6add08ad3c7660.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-e2eaa321ec223fe6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-5b8a09c475b5f844.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-91a77daedfbac191.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-f37fc5e974bda39b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-91429a0b78415a94.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-b95798b58263b910.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-763d53e175e17aa1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-d55023204055b12f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-89d2140d78abc810.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-82dc069abfe27f55.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-25d9eee7beb552c0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-770b4594c713ee97.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-c604fb980a634d88.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-ba8e0dcae4f83985.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-09788e1aa9a87db6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-3337c6a1328c2674.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-89acd5d68c0bc560.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-5c13e2c76371d797.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-653a9f18642825c6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-fe986fe79b107546.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-1e5da297557d2354.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-91ea9f5869a40943.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-7824e21b999962e2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-53d00a60cc75a922.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4e931248b3f9574b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-443364c9e4a23b31.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-25ab9c614c14129b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-dbcdcfac0a395a8a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-bf1de6645089ec58.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-c4201761a5e839c9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-c304f469ea5d70e4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-8e5a238cf5e50c9c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-c604fb980a634d88.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-32b526069ee50b3c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-84220c776608cedc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-e475618cbfd5ca2b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-ac2c1e6169cfce57.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-fccd3020af2f8806.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-9c0d7198ff7b5a91.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-d54b1ec9b9c6430d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-8c4bef1791d732ca.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-46fcc0b0bbc6fbfe.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-c1c80e345fa9d6f5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-7dfda00afd172f5b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/f21fd540.63ac75328926ed30.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-77fdcc873519a6cd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-d0d620d2ce235713.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-e0ef79c79337ba90.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-84b1bc71e3f9ce6a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-2acb61f1363128cb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-462ff5727ceb7824.js +0 -1
- package/scripts/migrate-monad-to-elanous.ts +0 -195
- package/scripts/rebrand-elanous.ts +0 -242
- /package/apps/pwa/out/_next/static/{8kITumG9GAZ1LwT9POrAR → RrjXTwz-urRAbChP1bX02}/_ssgManifest.js +0 -0
package/src/llm.ts
CHANGED
|
@@ -62,7 +62,7 @@ import { BUILTIN_CATALOG, reasoningEffortCeiling as reasoningEffortCeilingOf } f
|
|
|
62
62
|
import { inferProviderFromModel as registryInferProviderFromModel } from './registry/normalize.js';
|
|
63
63
|
import { closestMatches } from './tool-name-suggest.js';
|
|
64
64
|
import { createProviderToolNameMap } from './llm-tool-name.js';
|
|
65
|
-
import { isOpenRouterGrokModel, sanitizeToolSchemaForGrok } from './llm-tool-schema.js';
|
|
65
|
+
import { assertNoTopLevelToolSchemaCombinators, isOpenRouterGrokModel, sanitizeToolSchemaForGrok } from './llm-tool-schema.js';
|
|
66
66
|
import { undoTurnRuntime } from './tool-runtime/undo-turn-runtime.js';
|
|
67
67
|
import { listSnapshots } from './undo-turn/index.js';
|
|
68
68
|
// Zero-dep spec module (no tool-runtime registry) — safe for this hot path.
|
|
@@ -403,6 +403,9 @@ export type ToolChoice = 'auto' | 'required' | 'none' | { name: string };
|
|
|
403
403
|
|
|
404
404
|
export interface LLMOpts {
|
|
405
405
|
model?: string;
|
|
406
|
+
/** Explicit research surface verdict from the turn router. Relaxes early
|
|
407
|
+
* exploration guards while retaining a finite tool-loop hard stop. */
|
|
408
|
+
researchTurn?: boolean;
|
|
406
409
|
/** Reports the provider and model actually attempted, including fallbacks. */
|
|
407
410
|
onResolvedProvider?(provider: string, model: string): void;
|
|
408
411
|
temperature?: number;
|
|
@@ -4471,6 +4474,7 @@ function explainAndLogFallbackCandidates(
|
|
|
4471
4474
|
|
|
4472
4475
|
/** 스트림 중 끊김 재시도 상한 — codex `DEFAULT_STREAM_MAX_RETRIES`(5) 와 같은 값. */
|
|
4473
4476
|
const STREAM_DISCONNECT_MAX_RETRIES = 5;
|
|
4477
|
+
const STREAM_IDLE_TIMEOUT_MAX_RETRIES = 1;
|
|
4474
4478
|
let streamDisconnectRetryDelayMs: (attempt: number) => number = backoffMs;
|
|
4475
4479
|
|
|
4476
4480
|
/** @internal 시험 seam — 재시도 대기(기본 `backoffMs`)를 바꾼다. `undefined` 면 원복. */
|
|
@@ -4904,6 +4908,7 @@ export async function streamLLM(
|
|
|
4904
4908
|
);
|
|
4905
4909
|
activeProvider = finalized.provider;
|
|
4906
4910
|
const activeModel = finalized.model;
|
|
4911
|
+
if (getModelFamily(activeModel) === 'claude') assertNoTopLevelToolSchemaCombinators(opts.tools);
|
|
4907
4912
|
opts.onResolvedProvider?.(activeProvider.name, activeModel);
|
|
4908
4913
|
debug.log('llm.router', 'streamLLM', {
|
|
4909
4914
|
provider: activeProvider.name,
|
|
@@ -5118,6 +5123,8 @@ export function resolveDefaultProvider(model?: string): LLMProvider {
|
|
|
5118
5123
|
export interface StreamWithToolsHandlers {
|
|
5119
5124
|
/** Streaming text delta — invoked for every text chunk across all turns. */
|
|
5120
5125
|
onText(delta: string, fullAcrossTurns: string): void;
|
|
5126
|
+
/** Optional status line for hosts that surface transient stream recovery. */
|
|
5127
|
+
onStatus?(line: string): void;
|
|
5121
5128
|
/** Dispatch a tool call. Returning undefined/null throws in the loop so
|
|
5122
5129
|
* callers should always return a JSON-serializable value (can be an
|
|
5123
5130
|
* error object — the model will see it as a tool_result either way).
|
|
@@ -7382,6 +7389,16 @@ function resultText(result: unknown): string {
|
|
|
7382
7389
|
return '';
|
|
7383
7390
|
}
|
|
7384
7391
|
|
|
7392
|
+
/** skill_exec returns structured host metadata, but its model-facing tool result is the answer body. */
|
|
7393
|
+
function toolResultContentForCall(toolName: string, result: unknown): string {
|
|
7394
|
+
if (toolName === 'skill_exec' && result && typeof result === 'object'
|
|
7395
|
+
&& typeof (result as { output?: unknown }).output === 'string') {
|
|
7396
|
+
if ((result as { ok?: unknown }).ok === false) return JSON.stringify(result);
|
|
7397
|
+
return (result as { output: string }).output;
|
|
7398
|
+
}
|
|
7399
|
+
return typeof result === 'string' ? result : JSON.stringify(result);
|
|
7400
|
+
}
|
|
7401
|
+
|
|
7385
7402
|
function detectExecutionFailure(result: unknown): boolean {
|
|
7386
7403
|
if (!result || typeof result !== 'object') return false;
|
|
7387
7404
|
const typed = result as Record<string, unknown>;
|
|
@@ -8409,7 +8426,9 @@ export async function streamLLMWithTools(
|
|
|
8409
8426
|
const familyDefaultMaxTurns = resolved === 0 ? Number.POSITIVE_INFINITY : (resolved || baselineForFamily);
|
|
8410
8427
|
// `let` (not const) — the conditional budget-grant hook (opts.budgetGrant)
|
|
8411
8428
|
// may extend this mid-loop when a designated multi-round tool is called.
|
|
8412
|
-
let maxTurns = opts.maxTurns ??
|
|
8429
|
+
let maxTurns = opts.maxTurns ?? (opts.researchTurn
|
|
8430
|
+
? Math.min(32, Math.max(16, familyDefaultMaxTurns))
|
|
8431
|
+
: familyDefaultMaxTurns);
|
|
8413
8432
|
const budgetGrant = opts.budgetGrant;
|
|
8414
8433
|
// ⭐ Hydration-capable tool list (F2 gap④ · 2026-07-26). The provider tool
|
|
8415
8434
|
// array used to be `opts.tools`, FIXED for the whole loop. That made
|
|
@@ -8428,7 +8447,9 @@ export async function streamLLMWithTools(
|
|
|
8428
8447
|
} catch { /* config unreadable — default 비-면제·hot-path 는 config 손상에 안 막힌다 */ }
|
|
8429
8448
|
const inspectBudgetThreshold = getInspectBudgetThreshold(history, modelFamily, codexInspectExemptFlag);
|
|
8430
8449
|
const inspectFollowupMode = getInspectFollowupMode(history);
|
|
8431
|
-
const explorationThresholdForTurn =
|
|
8450
|
+
const explorationThresholdForTurn = opts.researchTurn
|
|
8451
|
+
? Number.POSITIVE_INFINITY
|
|
8452
|
+
: getExplorationThreshold(history, maxTurns, modelFamily);
|
|
8432
8453
|
const maxTurnsUnbounded = maxTurns === Infinity;
|
|
8433
8454
|
const familyDefaultMaxTurnsUnbounded = familyDefaultMaxTurns === Infinity;
|
|
8434
8455
|
const explorationUnbounded = !Number.isFinite(explorationThresholdForTurn);
|
|
@@ -8443,6 +8464,7 @@ export async function streamLLMWithTools(
|
|
|
8443
8464
|
inspectBudgetThreshold,
|
|
8444
8465
|
inspectFollowupMode,
|
|
8445
8466
|
explorationThresholdForTurn,
|
|
8467
|
+
researchTurn: opts.researchTurn === true,
|
|
8446
8468
|
// ★ Infinity 는 JSON 직렬화 시 null 이 되므로 boolean 으로도 남긴다(관측·제1원칙).
|
|
8447
8469
|
// true = 프론티어 면제로 read/search 스트릭 컷 없음(대표 방침 2026-07-17).
|
|
8448
8470
|
explorationUnbounded,
|
|
@@ -8831,7 +8853,7 @@ export async function streamLLMWithTools(
|
|
|
8831
8853
|
let turnOpts = buildTurnOpts();
|
|
8832
8854
|
// reasoning-heavy family(codex/claude/gemini/grok/local)는 침묵 추론 구간이 길어 idle watchdog 를
|
|
8833
8855
|
// family-aware 로 상향(2026-07-19 goal-exec → 아크4 전-family). fast/mini(gpt·other)만 45s 유지.
|
|
8834
|
-
const streamIdleTimeoutMs = usesLongReasoningIdle(modelFamily, activeProvider.name) ? STREAM_IDLE_TIMEOUT_MS_REASONING : STREAM_IDLE_TIMEOUT_MS;
|
|
8856
|
+
const streamIdleTimeoutMs = opts.streamIdleTimeoutMs ?? (usesLongReasoningIdle(modelFamily, activeProvider.name) ? STREAM_IDLE_TIMEOUT_MS_REASONING : STREAM_IDLE_TIMEOUT_MS);
|
|
8835
8857
|
// ⚠️ hang 진단(2026-07-17) — codex SSE 스트림이 완료 신호 없이 안 끝나는 케이스 확정용.
|
|
8836
8858
|
// consume-start 후 consume-end 가 없으면 = for-await(streamChat SSE) hang. lastEvType 로 어느
|
|
8837
8859
|
// 이벤트 뒤에서 멈추는지(usage/text/tool_call) 특정. 무장할 상한도 남겨 실험 런을 구별한다.
|
|
@@ -8847,6 +8869,7 @@ export async function streamLLMWithTools(
|
|
|
8847
8869
|
// ⭐ TUI-STREAM-RETRY(2026-10-14 실측) — 200 OK 로 흐르던 스트림이 소켓 끊김으로 죽으면 같은 공급자로
|
|
8848
8870
|
// 다시 건다(codex `stream_max_retries` 동형). 이 턴에서 받은 tool_call·image 가 있으면 재시도하지 않는다.
|
|
8849
8871
|
let streamDisconnectRetries = 0;
|
|
8872
|
+
let streamIdleTimeoutRetries = 0;
|
|
8850
8873
|
let streamEmittedImage = false;
|
|
8851
8874
|
// 끊긴 조각을 이력(turnText·fullText)에서 «조용히» 되감는다 — 화면엔 지우라고 알리지 않는다
|
|
8852
8875
|
// (TUI 의 빈 델타는 «커밋»이다). 이미 보인 글과 겹치는 재시도 본문은 `retryDisplay` 가 막는다.
|
|
@@ -8878,6 +8901,9 @@ export async function streamLLMWithTools(
|
|
|
8878
8901
|
while (true) {
|
|
8879
8902
|
let idleTimer: ReturnType<typeof setTimeout> | undefined;
|
|
8880
8903
|
let step: { idle: true } | { idle: false; r: IteratorResult<LLMStreamEvent, void> };
|
|
8904
|
+
// Validate before entering the provider stream's catch/fallback boundary.
|
|
8905
|
+
// An incompatible request is deterministic and must not be retried elsewhere.
|
|
8906
|
+
if (getModelFamily(activeModel) === 'claude') assertNoTopLevelToolSchemaCombinators(turnOpts.tools);
|
|
8881
8907
|
try {
|
|
8882
8908
|
if (!streamIter) {
|
|
8883
8909
|
const finalized = finalizeStreamingProviderModel(activeProvider, activeModel);
|
|
@@ -8918,8 +8944,46 @@ export async function streamLLMWithTools(
|
|
|
8918
8944
|
streamIter.next().then((r) => ({ idle: false as const, r })),
|
|
8919
8945
|
new Promise<{ idle: true }>((res) => { idleTimer = setTimeout(() => res({ idle: true }), streamIdleTimeoutMs); }),
|
|
8920
8946
|
]);
|
|
8947
|
+
if (step.idle) {
|
|
8948
|
+
const error = new Error(`stream idle timeout after ${streamIdleTimeoutMs}ms`);
|
|
8949
|
+
error.name = 'StreamIdleTimeoutError';
|
|
8950
|
+
Object.assign(error, { code: 'ETIMEDOUT' });
|
|
8951
|
+
throw error;
|
|
8952
|
+
}
|
|
8921
8953
|
} catch (err) {
|
|
8922
8954
|
if (idleTimer) clearTimeout(idleTimer);
|
|
8955
|
+
if (err instanceof Error && err.name === 'StreamIdleTimeoutError') {
|
|
8956
|
+
debug.log('llm.stream', 'idle-timeout', {
|
|
8957
|
+
turn, evCount, lastEvType, idleMs: streamIdleTimeoutMs,
|
|
8958
|
+
textChars: turnText.length, pendingCalls: pendingCalls.length,
|
|
8959
|
+
}, { level: 'warn' });
|
|
8960
|
+
// A provider async iterator can queue return() behind the pending next().
|
|
8961
|
+
// Detach cleanup so it cannot keep the user turn busy forever.
|
|
8962
|
+
const timedOutIterator = streamIter;
|
|
8963
|
+
if (timedOutIterator?.return) {
|
|
8964
|
+
try { void Promise.resolve(timedOutIterator.return(undefined)).catch(() => {}); } catch { /* fail-soft cleanup */ }
|
|
8965
|
+
}
|
|
8966
|
+
if (streamIdleTimeoutRetries < STREAM_IDLE_TIMEOUT_MAX_RETRIES
|
|
8967
|
+
&& pendingCalls.length === 0 && !streamEmittedImage && !opts.signal?.aborted) {
|
|
8968
|
+
streamIdleTimeoutRetries++;
|
|
8969
|
+
debug.log('llm.retry', 'idle-timeout-retry', {
|
|
8970
|
+
provider: activeProvider.name, model: activeModel, turn,
|
|
8971
|
+
attempt: streamIdleTimeoutRetries, maxRetries: STREAM_IDLE_TIMEOUT_MAX_RETRIES,
|
|
8972
|
+
delayMs: 0, statusLine: '스트림 무응답 · 재시도',
|
|
8973
|
+
}, { level: 'warn' });
|
|
8974
|
+
handlers.onStatus?.(`스트림 무응답 · 재시도 ${streamIdleTimeoutRetries}/${STREAM_IDLE_TIMEOUT_MAX_RETRIES}`);
|
|
8975
|
+
rewindDisconnectedStream();
|
|
8976
|
+
streamIter = undefined;
|
|
8977
|
+
continue;
|
|
8978
|
+
}
|
|
8979
|
+
// Once a tool call/image escaped, keep the old behavior: finish this
|
|
8980
|
+
// provider turn and never replay or switch providers around side effects.
|
|
8981
|
+
if (pendingCalls.length > 0 || streamEmittedImage || opts.signal?.aborted) break;
|
|
8982
|
+
if (opts.provider) break; // pinned route preserves the prior partial-text result
|
|
8983
|
+
// The retry's text was already sent to the view; drop it from the
|
|
8984
|
+
// logical result before allowing the normal provider fallback path.
|
|
8985
|
+
if (pendingCalls.length === 0 && !streamEmittedImage) rewindDisconnectedStream();
|
|
8986
|
+
}
|
|
8923
8987
|
if (err instanceof OverloadFailoverError && !opts.provider) {
|
|
8924
8988
|
const switched = activeProvider.name === 'openai-codex'
|
|
8925
8989
|
? firstAvailableFallbackProvider(attemptedProviders, opts)
|
|
@@ -8934,6 +8998,7 @@ export async function streamLLMWithTools(
|
|
|
8934
8998
|
status: err.status,
|
|
8935
8999
|
kind: err.kind,
|
|
8936
9000
|
}, { level: 'warn' });
|
|
9001
|
+
handlers.onStatus?.(`⚠ 공급자 전환: ${activeProvider.name} → ${switched.name} (${err.kind ?? err.name ?? 'unknown'})`);
|
|
8937
9002
|
const finalized = finalizeStreamingProviderModel(switched, switched.defaultModel);
|
|
8938
9003
|
activeProvider = finalized.provider;
|
|
8939
9004
|
activeModel = finalized.model;
|
|
@@ -8944,7 +9009,8 @@ export async function streamLLMWithTools(
|
|
|
8944
9009
|
continue;
|
|
8945
9010
|
}
|
|
8946
9011
|
}
|
|
8947
|
-
if (
|
|
9012
|
+
if (!(err instanceof Error && err.name === 'StreamIdleTimeoutError')
|
|
9013
|
+
&& evCount > 0 && isStreamDisconnectRetryable(err, pendingCalls.length, streamEmittedImage) && !opts.signal?.aborted) {
|
|
8948
9014
|
const retryData = {
|
|
8949
9015
|
provider: activeProvider.name,
|
|
8950
9016
|
model: activeModel,
|
|
@@ -9013,6 +9079,7 @@ export async function streamLLMWithTools(
|
|
|
9013
9079
|
tools: activeTools.map((tool) => tool.name),
|
|
9014
9080
|
...(opts.model ? { modelOverrideDropped: opts.model } : {}),
|
|
9015
9081
|
}, { level: 'warn' });
|
|
9082
|
+
handlers.onStatus?.(`⚠ 공급자 전환: ${activeProvider.name} → ${fallback.name} (${verdict.category})`);
|
|
9016
9083
|
const finalized = finalizeStreamingProviderModel(fallback, fallback.defaultModel);
|
|
9017
9084
|
activeProvider = finalized.provider;
|
|
9018
9085
|
activeModel = finalized.model;
|
|
@@ -9025,9 +9092,9 @@ export async function streamLLMWithTools(
|
|
|
9025
9092
|
}
|
|
9026
9093
|
if (idleTimer) clearTimeout(idleTimer);
|
|
9027
9094
|
if (step.idle) {
|
|
9028
|
-
|
|
9029
|
-
|
|
9030
|
-
|
|
9095
|
+
// The race's idle branch is converted to StreamIdleTimeoutError above.
|
|
9096
|
+
// Keep a fail-closed guard for future changes to this loop.
|
|
9097
|
+
throw new Error('stream idle timeout branch escaped recovery');
|
|
9031
9098
|
}
|
|
9032
9099
|
if (step.r.done) break;
|
|
9033
9100
|
const ev = step.r.value;
|
|
@@ -10289,7 +10356,8 @@ export async function streamLLMWithTools(
|
|
|
10289
10356
|
// rejection without colliding with the auto-narrow path)
|
|
10290
10357
|
// - call is in SEARCH_ONLY_TOOLS
|
|
10291
10358
|
if (
|
|
10292
|
-
|
|
10359
|
+
!opts.researchTurn
|
|
10360
|
+
&& dispatchedReadCount === 0
|
|
10293
10361
|
&& autoNarrowedReadCount === 0
|
|
10294
10362
|
&& searchOnlyTurnStreak >= 3
|
|
10295
10363
|
&& SEARCH_ONLY_TOOLS.has(call.name)
|
|
@@ -11066,7 +11134,7 @@ export async function streamLLMWithTools(
|
|
|
11066
11134
|
resultBlocks.push({
|
|
11067
11135
|
type: 'tool_result',
|
|
11068
11136
|
tool_use_id: call.id,
|
|
11069
|
-
content:
|
|
11137
|
+
content: toolResultContentForCall(call.name, result),
|
|
11070
11138
|
...(isError ? { isError: true } : {}),
|
|
11071
11139
|
});
|
|
11072
11140
|
}
|
|
@@ -11245,7 +11313,8 @@ export async function streamLLMWithTools(
|
|
|
11245
11313
|
// synthesis attempt. Extended to gemini 2026-05-04 alongside
|
|
11246
11314
|
// W5-E/W5-F for the same pathology shape.
|
|
11247
11315
|
if (
|
|
11248
|
-
!
|
|
11316
|
+
!opts.researchTurn
|
|
11317
|
+
&& !forceSynthesisAttempted
|
|
11249
11318
|
&& noContentReadTurnStreak >= 4
|
|
11250
11319
|
&& (modelFamily === 'gemini'
|
|
11251
11320
|
|| applyCodexBehaviorGuard('force-synthesis', effectiveModel, codexGuardCandidate, true))
|
|
@@ -11500,6 +11569,7 @@ function makeOpenAICompatProvider(
|
|
|
11500
11569
|
throw new Error(`${name} unavailable: configure apiKey via \`elanous setup\``);
|
|
11501
11570
|
}
|
|
11502
11571
|
const activeModel = opts.model || model;
|
|
11572
|
+
if (getModelFamily(activeModel) === 'claude') assertNoTopLevelToolSchemaCombinators(opts.tools);
|
|
11503
11573
|
const wireModel = name === 'openrouter' ? openRouterWireModel(activeModel) : activeModel;
|
|
11504
11574
|
const tools = toOpenAITools(
|
|
11505
11575
|
opts.tools,
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import { effectiveInstanceRoot } from '../../instance/resolve.js';
|
|
3
|
+
import { resolveConfiguredAgentRoleLlm } from '../../user-config.js';
|
|
4
|
+
import type { RoleLlmSpec } from '../../user-config.js';
|
|
5
|
+
import { loadAgentRolePack } from '../agent-reply.js';
|
|
6
|
+
import type { MsgStore } from '../../msg/msg-store.js';
|
|
7
|
+
import { runAskOpContextInbox, runCoordinatorAgentInbox, type CoordinatorInboxResult } from './inbox.js';
|
|
8
|
+
import type { AskOpContextBundle } from '../../context-bus/context-now.js';
|
|
9
|
+
|
|
10
|
+
export interface InboxOnceOptions {
|
|
11
|
+
root?: string;
|
|
12
|
+
store?: MsgStore;
|
|
13
|
+
role?: RoleLlmSpec | null;
|
|
14
|
+
limit?: number;
|
|
15
|
+
context?: (question: string, options: { audience?: string; limit?: number }) => Promise<AskOpContextBundle>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** One scan of the same durable inbox as the orchestrator tick, without running its graph. */
|
|
19
|
+
export async function runCoordinatorInboxOnce(options: InboxOnceOptions = {}): Promise<CoordinatorInboxResult> {
|
|
20
|
+
const root = options.root ?? effectiveInstanceRoot();
|
|
21
|
+
const path = join(root, 'msg', 'messages.db');
|
|
22
|
+
const role = options.role === undefined ? resolveConfiguredAgentRoleLlm('coordinator') : options.role;
|
|
23
|
+
if (role) return runCoordinatorAgentInbox({ role, pack: loadAgentRolePack('coordinator'), root, path,
|
|
24
|
+
limit: options.limit ?? 100, ...(options.store ? { store: options.store } : {}) });
|
|
25
|
+
return runAskOpContextInbox({ path, limit: options.limit ?? 100,
|
|
26
|
+
...(options.store ? { store: options.store } : {}),
|
|
27
|
+
...(options.context ? { context: options.context } : {}) });
|
|
28
|
+
}
|
|
@@ -1,15 +1,90 @@
|
|
|
1
|
+
import { ASK_OP_COMMAND } from '../../session/channel-ask-op-envelope.js';
|
|
1
2
|
import { openMsgStore, type Message, type MsgStore } from '../../msg/msg-store.js';
|
|
2
3
|
import { classifySeatTrafficProposal } from '../../seat-loop/traffic-signal.js';
|
|
3
|
-
import { debug } from '../../debug/log.js';
|
|
4
|
+
import { debug, redactSecretText } from '../../debug/log.js';
|
|
4
5
|
import { LOOP_MESSAGE_ROUTES } from '../msg-address.js';
|
|
5
6
|
import { replyWithAgent, type AgentReplyInput } from '../agent-reply.js';
|
|
6
7
|
import { knowhowAdvice, type KnowhowAdvice, type KnowhowOptions } from './knowhow-pack.js';
|
|
7
8
|
import type { RoleLlmSpec } from '../../user-config.js';
|
|
8
9
|
import type { LLMProvider } from '../../llm.js';
|
|
10
|
+
import { askOpContextBundle, type AskOpContextBundle } from '../../context-bus/context-now.js';
|
|
9
11
|
|
|
10
12
|
const RECIPIENT = LOOP_MESSAGE_ROUTES.orchestrator.msgAddress;
|
|
11
13
|
|
|
12
14
|
export interface CoordinatorInboxResult { replied: number; acknowledged: number }
|
|
15
|
+
export interface AskOpTestHarness {
|
|
16
|
+
/** A test-only sink; this never defaults to a real surface transport. */
|
|
17
|
+
replySink: (reply: { from: string; to: string; body: string; kind: 'reply'; replyTo: number }) => Message;
|
|
18
|
+
/** Capture both clocks without writing to the production log store in tests. */
|
|
19
|
+
eventSink?: (event: { requestId: number; requestToReplyMs: number | null; processingMs: number }) => void;
|
|
20
|
+
}
|
|
21
|
+
export interface AskOpContextInboxOptions {
|
|
22
|
+
store?: MsgStore;
|
|
23
|
+
path?: string;
|
|
24
|
+
limit?: number;
|
|
25
|
+
context?: typeof askOpContextBundle;
|
|
26
|
+
knowhow?: KnowhowOptions | false;
|
|
27
|
+
/** Only the ordered tick scan may advance the durable cursor. */
|
|
28
|
+
acknowledge?: boolean;
|
|
29
|
+
/** SSE delivery handles exactly its message; the ordered tick scans the cursor. */
|
|
30
|
+
request?: Message;
|
|
31
|
+
/** Explicit opt-in for synthetic TEST ASK-OP questions only. Production callers must omit this. */
|
|
32
|
+
testHarness?: AskOpTestHarness;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const ASK_OP_SENDERS = new Set(['TELEGRAM', 'DISCORD']);
|
|
36
|
+
const REFUSE = '모름 — 확인된 근거가 없어 답할 수 없습니다.';
|
|
37
|
+
|
|
38
|
+
function isAskOpRequest(request: Message, allowTestSource = false): boolean {
|
|
39
|
+
const testSource = allowTestSource && request.from === 'TEST'
|
|
40
|
+
&& /^Test \/(?:askop|ask-op)(?:\r?\n|$)/.test(request.body);
|
|
41
|
+
return request.kind === 'question' && (ASK_OP_SENDERS.has(request.from) || testSource)
|
|
42
|
+
&& (testSource || new RegExp(`^(?:Telegram|Discord) \/(?:${ASK_OP_COMMAND}|ask-op)(?:\\r?\\n|$)`).test(request.body));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function askOpLatencyMs(request: Message, repliedAt: number): number | null {
|
|
46
|
+
const createdAt = Date.parse(request.createdAt);
|
|
47
|
+
const latencyMs = repliedAt - createdAt;
|
|
48
|
+
return Number.isFinite(createdAt) && latencyMs >= 0 ? latencyMs : null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function writeAskOpReply(store: MsgStore, request: Message, replyText: string, options: AskOpContextInboxOptions) {
|
|
52
|
+
if (options.testHarness && request.from === 'TEST') {
|
|
53
|
+
const marker = `re #${request.id}\n`;
|
|
54
|
+
const body = replyText.startsWith(marker) ? replyText.slice(marker.length) : replyText;
|
|
55
|
+
const reply = options.testHarness.replySink({ from: RECIPIENT, to: request.from,
|
|
56
|
+
body, kind: 'reply', replyTo: request.id });
|
|
57
|
+
return { id: reply.id, posted: true };
|
|
58
|
+
}
|
|
59
|
+
return writeCoordinatorReply(store, request, replyText);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function askOpQuestion(request: Message): string {
|
|
63
|
+
const match = /^question: (.*)$/m.exec(request.body);
|
|
64
|
+
return match?.[1]?.trim() ?? '';
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function unsafeAskOp(question: string): boolean {
|
|
68
|
+
// Reject explicit commands, not descriptive questions such as "What changed since the release?".
|
|
69
|
+
return /^(?:(?:please|can you|could you|would you)\s+)?(?:run|execute|deploy|publish|push|merge|delete|drop|write|edit|change|set)\b|(?:실행해|발행해|배포해|푸시해|병합해|삭제해|수정해|바꿔|설정해)(?:줘|주세요)?|\b(?:show|reveal|give|tell|display|print|read|open|what is|what's)\b.{0,80}\b(?:secret|token|password|credential|api[ -]?key|private[ -]?key)\b|(?:비밀|토큰|암호|패스워드|인증키|API\s*키).{0,80}(?:보여|알려|공개|읽어)/i.test(question);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async function askOpAnswer(request: Message, options: AskOpContextInboxOptions): Promise<string> {
|
|
73
|
+
const question = askOpQuestion(request);
|
|
74
|
+
if (!question) return `제안: ${REFUSE}\n근거: 질문이 비었습니다.`;
|
|
75
|
+
if (unsafeAskOp(question)) return '제안: 요청한 권한 실행·비밀 조회·traffic/칸 변경은 실행할 수 없습니다.\n근거: OP 질문 답변은 읽기 전용입니다.';
|
|
76
|
+
let bundle: AskOpContextBundle;
|
|
77
|
+
// These replies are delivered to an external channel, not the private operator console.
|
|
78
|
+
try { bundle = await (options.context ?? askOpContextBundle)(question, { audience: 'public-demo', limit: 8 }); }
|
|
79
|
+
catch { return `제안: ${REFUSE}\n근거: 맥락 조회 실패.`; }
|
|
80
|
+
const facts = bundle.facts.filter(fact => fact.source?.trim() && fact.summary?.trim()).slice(0, 8);
|
|
81
|
+
if (!facts.length) {
|
|
82
|
+
const gaps = bundle.gaps.slice(0, 3).map(gap => `${redactSecretText(gap.kind)}: ${redactSecretText(gap.reason)}`).join('; ');
|
|
83
|
+
return `제안: ${REFUSE}\n근거: ${gaps || '미관측'}.`;
|
|
84
|
+
}
|
|
85
|
+
const evidence = facts.map(fact => `- ${redactSecretText(fact.summary)} — ${redactSecretText(fact.source)} (관측 ${redactSecretText(fact.observedAt)})`).join('\n');
|
|
86
|
+
return `제안: 다음은 관측된 OP 맥락입니다 (${redactSecretText(bundle.topic)}; 조회 ${redactSecretText(bundle.queriedAt)}).\n근거:\n${evidence}\n판단·승인·실행은 하지 않았습니다.`;
|
|
87
|
+
}
|
|
13
88
|
export interface CoordinatorAgentInboxOptions {
|
|
14
89
|
role: RoleLlmSpec;
|
|
15
90
|
pack: string;
|
|
@@ -95,6 +170,57 @@ function writeCoordinatorReply(store: MsgStore, request: Message, replyText: str
|
|
|
95
170
|
return { id: reply.id, posted: true };
|
|
96
171
|
}
|
|
97
172
|
|
|
173
|
+
/** Surface ask-op questions use the same linked reply and durable acknowledgement as the resident inbox. */
|
|
174
|
+
export async function runAskOpContextInbox(options: AskOpContextInboxOptions = {}): Promise<CoordinatorInboxResult> {
|
|
175
|
+
const store = options.store ?? openMsgStore(options.path);
|
|
176
|
+
const ownStore = options.store === undefined;
|
|
177
|
+
const result = { replied: 0, acknowledged: 0 };
|
|
178
|
+
const acknowledge = options.acknowledge !== false;
|
|
179
|
+
try {
|
|
180
|
+
const requests = options.request ? [options.request]
|
|
181
|
+
: store.listByRecipient(RECIPIENT, store.getCursor(RECIPIENT), options.limit ?? 100);
|
|
182
|
+
for (const request of requests) {
|
|
183
|
+
if (request.to !== RECIPIENT || request.from === RECIPIENT ||
|
|
184
|
+
(request.kind !== undefined && request.kind !== 'request' && request.kind !== 'question')) {
|
|
185
|
+
if (acknowledge) { store.ack(RECIPIENT, request.id); result.acknowledged++; }
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
const testAskOp = request.from === 'TEST' && isAskOpRequest(request, true);
|
|
189
|
+
if (testAskOp && !options.testHarness) continue;
|
|
190
|
+
const key = `coord-inbox:${request.id}:${request.from}`;
|
|
191
|
+
const existing = store.db.query('SELECT message_id FROM msg_provenance WHERE provenance_key = ?')
|
|
192
|
+
.get(key) as { message_id: number } | null;
|
|
193
|
+
// Legacy seat traffic and knowhow requests preserve the existing answer path.
|
|
194
|
+
const startedAt = Date.now();
|
|
195
|
+
const replyText = existing ? '' : (isAskOpRequest(request, options.testHarness !== undefined)
|
|
196
|
+
? `re #${request.id}\n${await askOpAnswer(request, options)}` : coordinatorReply(request, options.knowhow ?? {}));
|
|
197
|
+
const one = store.db.transaction(() => {
|
|
198
|
+
const receipt = store.db.query('SELECT message_id FROM msg_provenance WHERE provenance_key = ?')
|
|
199
|
+
.get(key) as { message_id: number } | null;
|
|
200
|
+
const reply = receipt ? { id: receipt.message_id, posted: false } : writeAskOpReply(store, request, replyText, options);
|
|
201
|
+
if (!receipt) store.db.query('INSERT INTO msg_provenance(provenance_key, message_id) VALUES (?, ?)').run(key, reply.id);
|
|
202
|
+
if (acknowledge) store.ack(RECIPIENT, request.id);
|
|
203
|
+
return reply.posted;
|
|
204
|
+
}).immediate();
|
|
205
|
+
if (one) result.replied++;
|
|
206
|
+
if (acknowledge) result.acknowledged++;
|
|
207
|
+
debug.log('loop.coordinator-inbox', 'reply', { requestId: request.id, recipient: request.from, duplicate: !one });
|
|
208
|
+
if (one && isAskOpRequest(request, options.testHarness !== undefined)) {
|
|
209
|
+
const repliedAt = Date.now();
|
|
210
|
+
const latencyMs = askOpLatencyMs(request, repliedAt);
|
|
211
|
+
const processingMs = Math.max(0, repliedAt - startedAt);
|
|
212
|
+
if (options.testHarness && request.from === 'TEST') {
|
|
213
|
+
options.testHarness.eventSink?.({ requestId: request.id, requestToReplyMs: latencyMs, processingMs });
|
|
214
|
+
} else {
|
|
215
|
+
debug.log('ask-op.inbox', 'replied', { requestId: request.id, requestToReplyMs: latencyMs,
|
|
216
|
+
processingMs, clockSkew: latencyMs === null });
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return result;
|
|
221
|
+
} finally { if (ownStore) store.close(); }
|
|
222
|
+
}
|
|
223
|
+
|
|
98
224
|
/** One transaction ties a reply to its acknowledgement. A retry finds the durable receipt. */
|
|
99
225
|
export function runCoordinatorInbox(inputStore?: MsgStore, limit = 100, path?: string,
|
|
100
226
|
options: CoordinatorInboxOptions = {}): CoordinatorInboxResult {
|
|
@@ -144,6 +270,9 @@ export async function handleCoordinatorAgentMessage(
|
|
|
144
270
|
const ownStore = input.store === undefined;
|
|
145
271
|
const acknowledge = input.acknowledge === true;
|
|
146
272
|
try {
|
|
273
|
+
if (isAskOpRequest(request) && request.to === RECIPIENT) {
|
|
274
|
+
return await runAskOpContextInbox({ store, request, acknowledge });
|
|
275
|
+
}
|
|
147
276
|
if (request.to !== RECIPIENT || request.from === RECIPIENT ||
|
|
148
277
|
(request.kind !== undefined && request.kind !== 'request' && request.kind !== 'question')) {
|
|
149
278
|
if (acknowledge) store.ack(RECIPIENT, request.id);
|
|
@@ -25,7 +25,7 @@ import * as testGuard from '../../instance/test-write-guard.js';
|
|
|
25
25
|
import { seatCapDetails } from '../budget.js';
|
|
26
26
|
export { isLaunchEligible } from './traffic.js';
|
|
27
27
|
import { readTaskAgentState, TASK_SEATS, type HandTaskOptions, type TaskCard as TaskAgentCard, type HandTaskResult, type TaskLauncher, type TaskSeat } from '../../task-agent/task-hand.js';
|
|
28
|
-
import {
|
|
28
|
+
import { runAskOpContextInbox, runCoordinatorAgentInbox, type CoordinatorInboxResult } from './inbox.js';
|
|
29
29
|
import type { KnowhowOptions } from './knowhow-pack.js';
|
|
30
30
|
import { loadAgentRolePack, type AgentReplyInput } from '../agent-reply.js';
|
|
31
31
|
import type { LLMProvider } from '../../llm.js';
|
|
@@ -97,6 +97,8 @@ export interface TickDeps {
|
|
|
97
97
|
coordinatorAgentProvider?: LLMProvider;
|
|
98
98
|
/** Resident knowhow pack seam; the real intake reads 내부 문서 `KNOWHOW` every tick. */
|
|
99
99
|
coordinatorKnowhow?: KnowhowOptions | false;
|
|
100
|
+
/** Deterministic read-only ask-op context seam for isolated tick tests. */
|
|
101
|
+
coordinatorContext?: typeof import('../../context-bus/context-now.js').askOpContextBundle;
|
|
100
102
|
}
|
|
101
103
|
|
|
102
104
|
/** ORCH-TA-HAND ledger — one row per handed `orch:<card>:<cell>` key so a cell is handed once across ticks and processes. */
|
|
@@ -521,8 +523,9 @@ export async function runOrchestratorNode(node: Node, deps: TickDeps = {}): Prom
|
|
|
521
523
|
? runCoordinatorAgentInbox({ role, pack: loadAgentRolePack('coordinator'), path: inboxPath, root,
|
|
522
524
|
...(deps.coordinatorAgentRun ? { runAgent: deps.coordinatorAgentRun } : {}),
|
|
523
525
|
...(deps.coordinatorAgentProvider ? { provider: deps.coordinatorAgentProvider } : {}) })
|
|
524
|
-
:
|
|
525
|
-
|
|
526
|
+
: runAskOpContextInbox({ path: inboxPath, limit: 100,
|
|
527
|
+
...(deps.coordinatorKnowhow === undefined ? {} : { knowhow: deps.coordinatorKnowhow }),
|
|
528
|
+
...(deps.coordinatorContext ? { context: deps.coordinatorContext } : {}) });
|
|
526
529
|
}))();
|
|
527
530
|
if (inbox.replied || inbox.acknowledged) {
|
|
528
531
|
observe('exchange', 'coordinator-inbox-replied', inbox.replied);
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { Message, MessageEnvelope } from '../../msg/msg-store.js';
|
|
2
|
+
import type { TgSlashCommand } from '../../telegram-commands.js';
|
|
3
|
+
import { ASK_OP_COMMAND, formatAskOpQuestionEnvelope } from '../../session/channel-ask-op-envelope.js';
|
|
4
|
+
|
|
5
|
+
export interface AskOpTelegramOptions {
|
|
6
|
+
allowedUserIds: readonly number[];
|
|
7
|
+
append: (message: MessageEnvelope, provenanceKey: string) => Message;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface AskOpDiscordOptions {
|
|
11
|
+
allowedUserIds: readonly string[];
|
|
12
|
+
allowedChannelIds: readonly string[];
|
|
13
|
+
resolveBotId: () => Promise<string>;
|
|
14
|
+
append: (message: MessageEnvelope, provenanceKey: string) => Message;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface AskOpDiscordContext {
|
|
18
|
+
userId: string;
|
|
19
|
+
channelId: string;
|
|
20
|
+
messageId: string;
|
|
21
|
+
text: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function appendAskOpQuestion(
|
|
25
|
+
options: { append: AskOpTelegramOptions['append'] },
|
|
26
|
+
input: { from: 'TELEGRAM' | 'DISCORD'; surface: string; correlation: string[]; question: string; provenanceKey: string },
|
|
27
|
+
): Message {
|
|
28
|
+
return options.append({
|
|
29
|
+
from: input.from,
|
|
30
|
+
to: 'COORDINATOR',
|
|
31
|
+
kind: 'question',
|
|
32
|
+
body: [`${input.surface} /${ASK_OP_COMMAND}`, ...input.correlation, `question: ${input.question}`].join('\n'),
|
|
33
|
+
}, input.provenanceKey);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function extractQuestion(text: string): string | null {
|
|
37
|
+
const match = new RegExp(`^/(?:${ASK_OP_COMMAND}|ask-op)(?:@[-_a-z0-9]+)?(?:\\s+([\\s\\S]*))?$`, 'i').exec(text.trim());
|
|
38
|
+
const question = match?.[1]?.trim();
|
|
39
|
+
return question || null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function createAskOpTelegramSlashCommand(options: AskOpTelegramOptions): TgSlashCommand {
|
|
43
|
+
return {
|
|
44
|
+
name: ASK_OP_COMMAND,
|
|
45
|
+
description: '운영 책임자에게 질문을 보냅니다',
|
|
46
|
+
handler: async (_args, ctx) => {
|
|
47
|
+
if (!options.allowedUserIds.includes(ctx.userId)) return '허용된 사용자만 OP에게 질문할 수 있습니다.';
|
|
48
|
+
const question = extractQuestion(ctx.text);
|
|
49
|
+
if (!question) return `사용법: /${ASK_OP_COMMAND} <질문>`;
|
|
50
|
+
if (!Number.isSafeInteger(ctx.updateId) || ctx.updateId < 0) return 'Telegram update 식별값을 확인할 수 없어 질문을 저장하지 못했습니다.';
|
|
51
|
+
|
|
52
|
+
const botId = (ctx.botId ?? 'unknown').replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
53
|
+
const message = options.append({
|
|
54
|
+
from: 'TELEGRAM',
|
|
55
|
+
to: 'COORDINATOR',
|
|
56
|
+
kind: 'question',
|
|
57
|
+
body: formatAskOpQuestionEnvelope({
|
|
58
|
+
surface: 'telegram', botId, chatId: ctx.chatId, threadId: ctx.threadId,
|
|
59
|
+
messageId: ctx.messageId, updateId: ctx.updateId, question,
|
|
60
|
+
}),
|
|
61
|
+
}, `coord:tg-${botId}-${ctx.updateId}:COORDINATOR`);
|
|
62
|
+
|
|
63
|
+
return `OP에게 질문 #${message.id}로 접수했습니다.`;
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** Handle a Discord text command from an already-routed message. Returning
|
|
69
|
+
* undefined leaves every non-/askop message on its existing chat path. */
|
|
70
|
+
export function createAskOpDiscordIngress(options: AskOpDiscordOptions) {
|
|
71
|
+
return async (ctx: AskOpDiscordContext): Promise<string | undefined> => {
|
|
72
|
+
const match = new RegExp(`^/${ASK_OP_COMMAND}(?:\\s+([\\s\\S]*))?$`, 'i').exec(ctx.text.trim());
|
|
73
|
+
if (!match) return undefined;
|
|
74
|
+
if (!options.allowedUserIds.includes(ctx.userId)) return '허용된 사용자만 OP에게 질문할 수 있습니다.';
|
|
75
|
+
if (!options.allowedChannelIds.includes(ctx.channelId)) return '허용된 Discord 채널에서만 OP에게 질문할 수 있습니다.';
|
|
76
|
+
const question = match[1]?.trim();
|
|
77
|
+
if (!question) return `사용법: /${ASK_OP_COMMAND} <질문>`;
|
|
78
|
+
if (!/^\d+$/.test(ctx.messageId)) return 'Discord 메시지 식별값을 확인할 수 없어 질문을 저장하지 못했습니다.';
|
|
79
|
+
|
|
80
|
+
let botId: string;
|
|
81
|
+
try { botId = await options.resolveBotId(); }
|
|
82
|
+
catch { return 'Discord 봇 식별값을 확인할 수 없어 질문을 저장하지 못했습니다.'; }
|
|
83
|
+
if (!/^[A-Za-z0-9_-]+$/.test(botId)) return 'Discord 봇 식별값이 올바르지 않아 질문을 저장하지 못했습니다.';
|
|
84
|
+
|
|
85
|
+
const message = appendAskOpQuestion(options, {
|
|
86
|
+
from: 'DISCORD', surface: 'Discord',
|
|
87
|
+
correlation: [
|
|
88
|
+
`botId=${botId}`, `channelId=${ctx.channelId}`,
|
|
89
|
+
`messageId=${ctx.messageId}`, `updateId=${ctx.messageId}`,
|
|
90
|
+
],
|
|
91
|
+
question,
|
|
92
|
+
provenanceKey: `coord:dc-${botId}-${ctx.messageId}:COORDINATOR`,
|
|
93
|
+
});
|
|
94
|
+
return `OP에게 질문 #${message.id}로 접수했습니다.`;
|
|
95
|
+
};
|
|
96
|
+
}
|
|
@@ -37,6 +37,8 @@ import { createDiscordStreamSink } from '../../session/streaming/discord-stream-
|
|
|
37
37
|
import { splitForDiscord } from '../../discord.js';
|
|
38
38
|
import { formatForDiscord } from '../../discord-markdown.js';
|
|
39
39
|
import { receiveChannelEvent } from '../outbound/router.js';
|
|
40
|
+
import { openMsgStore } from '../../msg/msg-store.js';
|
|
41
|
+
import { createAskOpDiscordIngress } from './channel-ask-op.js';
|
|
40
42
|
|
|
41
43
|
export interface NexusDiscordTriggerBotOpts {
|
|
42
44
|
/** Bot token (without `Bot ` prefix). Production reads
|
|
@@ -156,6 +158,30 @@ export function createNexusDiscordTriggerBot(
|
|
|
156
158
|
// LF2 — 콘솔 하트비트 유지 + debug.log 병행(telegram-trigger 동형).
|
|
157
159
|
const log = opts.log ?? createDiscordTriggerLogger();
|
|
158
160
|
const onTriggerTap = buildDiscordTriggerTap(opts.dispatch, log);
|
|
161
|
+
let botRef: DiscordBot | undefined;
|
|
162
|
+
let botIdPromise: Promise<string> | undefined;
|
|
163
|
+
const askOpIngress = createAskOpDiscordIngress({
|
|
164
|
+
allowedUserIds: opts.allowedUsers,
|
|
165
|
+
allowedChannelIds: opts.guildTextChannels ?? [],
|
|
166
|
+
resolveBotId: () => {
|
|
167
|
+
if (!botRef) return Promise.reject(new Error('Discord bot is not ready'));
|
|
168
|
+
botIdPromise ??= botRef.getMe().then(({ id }) => id).catch((error: unknown) => {
|
|
169
|
+
botIdPromise = undefined;
|
|
170
|
+
throw error;
|
|
171
|
+
});
|
|
172
|
+
return botIdPromise;
|
|
173
|
+
},
|
|
174
|
+
append: (message, provenanceKey) => {
|
|
175
|
+
const store = openMsgStore();
|
|
176
|
+
try { return store.appendWithProvenance(message, provenanceKey); }
|
|
177
|
+
finally { store.close(); }
|
|
178
|
+
},
|
|
179
|
+
});
|
|
180
|
+
const onMessage: DcMessageHandler = async (ctx, streamer) => {
|
|
181
|
+
const askReply = await askOpIngress(ctx);
|
|
182
|
+
if (askReply !== undefined) return askReply;
|
|
183
|
+
return opts.onMessage?.(ctx, streamer);
|
|
184
|
+
};
|
|
159
185
|
|
|
160
186
|
const botWasInjected = opts.bot !== undefined;
|
|
161
187
|
const bot = opts.bot ?? new DiscordBot({
|
|
@@ -165,7 +191,7 @@ export function createNexusDiscordTriggerBot(
|
|
|
165
191
|
// Chat path: the injected self-turn handler (M4b nexus wire) or the
|
|
166
192
|
// legacy trigger-only no-op. Workflows wanting a chat reply can
|
|
167
193
|
// still declare a `chatTrigger` (routes via `/v1/workflows/chat/*`).
|
|
168
|
-
onMessage
|
|
194
|
+
onMessage,
|
|
169
195
|
log,
|
|
170
196
|
onTriggerTap,
|
|
171
197
|
...(opts.voiceTap ? { voiceTap: opts.voiceTap } : {}),
|
|
@@ -173,6 +199,7 @@ export function createNexusDiscordTriggerBot(
|
|
|
173
199
|
...(opts.fetchImpl ? { fetchImpl: opts.fetchImpl } : {}),
|
|
174
200
|
...(opts.wsImpl ? { wsImpl: opts.wsImpl } : {}),
|
|
175
201
|
});
|
|
202
|
+
botRef = bot;
|
|
176
203
|
|
|
177
204
|
// §C3 — discord 서피스 sink(config gate·telegram-trigger 동형). shadowFanout OR
|
|
178
205
|
// primary.discord 시 등록. endpoint 완전스코프면 parse→인스턴스 가드 후 channelId 배달,
|