@graphrefly/graphrefly 0.45.0 → 0.46.0
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/README.md +1 -2
- package/dist/_internal-B23BagFd.d.cts +33 -0
- package/dist/_internal-B23BagFd.d.ts +33 -0
- package/dist/adaptive-rate-limiter-Dch_xYIi.d.cts +111 -0
- package/dist/adaptive-rate-limiter-Dch_xYIi.d.ts +111 -0
- package/dist/agents-C0Ji9ldU.d.cts +629 -0
- package/dist/agents-C9zexT7I.d.ts +629 -0
- package/dist/audit-BAXb3VOg.d.ts +246 -0
- package/dist/audit-C_bPfkqS.d.cts +246 -0
- package/dist/backoff-7KIK3WQW.js +24 -0
- package/dist/backoff-7KIK3WQW.js.map +1 -0
- package/dist/backoff-Bnb9OoPh.d.cts +6 -0
- package/dist/backoff-Bnb9OoPh.d.ts +6 -0
- package/dist/base/composition/index.cjs +811 -0
- package/dist/base/composition/index.cjs.map +1 -0
- package/dist/base/composition/index.d.cts +469 -0
- package/dist/base/composition/index.d.ts +469 -0
- package/dist/base/composition/index.js +40 -0
- package/dist/base/composition/index.js.map +1 -0
- package/dist/base/index.cjs +6336 -0
- package/dist/base/index.cjs.map +1 -0
- package/dist/base/index.d.cts +22 -0
- package/dist/base/index.d.ts +22 -0
- package/dist/base/index.js +259 -0
- package/dist/base/index.js.map +1 -0
- package/dist/base/io/index.cjs +3270 -0
- package/dist/base/io/index.cjs.map +1 -0
- package/dist/base/io/index.d.cts +2245 -0
- package/dist/base/io/index.d.ts +2245 -0
- package/dist/base/io/index.js +117 -0
- package/dist/base/io/index.js.map +1 -0
- package/dist/base/meta/index.cjs +43 -0
- package/dist/base/meta/index.cjs.map +1 -0
- package/dist/base/meta/index.d.cts +45 -0
- package/dist/base/meta/index.d.ts +45 -0
- package/dist/base/meta/index.js +13 -0
- package/dist/base/meta/index.js.map +1 -0
- package/dist/base/mutation/index.cjs +200 -0
- package/dist/base/mutation/index.cjs.map +1 -0
- package/dist/base/mutation/index.d.cts +177 -0
- package/dist/base/mutation/index.d.ts +177 -0
- package/dist/base/mutation/index.js +22 -0
- package/dist/base/mutation/index.js.map +1 -0
- package/dist/base/render/index.cjs +1120 -0
- package/dist/base/render/index.cjs.map +1 -0
- package/dist/base/render/index.d.cts +227 -0
- package/dist/base/render/index.d.ts +227 -0
- package/dist/base/render/index.js +24 -0
- package/dist/base/render/index.js.map +1 -0
- package/dist/base/sources/browser/index.cjs +172 -0
- package/dist/base/sources/browser/index.cjs.map +1 -0
- package/dist/base/sources/browser/index.d.cts +84 -0
- package/dist/base/sources/browser/index.d.ts +84 -0
- package/dist/base/sources/browser/index.js +151 -0
- package/dist/base/sources/browser/index.js.map +1 -0
- package/dist/base/sources/event/index.cjs +98 -0
- package/dist/base/sources/event/index.cjs.map +1 -0
- package/dist/base/sources/event/index.d.cts +91 -0
- package/dist/base/sources/event/index.d.ts +91 -0
- package/dist/base/sources/event/index.js +13 -0
- package/dist/base/sources/event/index.js.map +1 -0
- package/dist/base/sources/index.cjs +755 -0
- package/dist/base/sources/index.cjs.map +1 -0
- package/dist/base/sources/index.d.cts +357 -0
- package/dist/base/sources/index.d.ts +357 -0
- package/dist/base/sources/index.js +42 -0
- package/dist/base/sources/index.js.map +1 -0
- package/dist/base/sources/node/index.cjs +320 -0
- package/dist/base/sources/node/index.cjs.map +1 -0
- package/dist/base/sources/node/index.d.cts +185 -0
- package/dist/base/sources/node/index.d.ts +185 -0
- package/dist/base/sources/node/index.js +306 -0
- package/dist/base/sources/node/index.js.map +1 -0
- package/dist/base/utils/index.cjs +37 -0
- package/dist/base/utils/index.cjs.map +1 -0
- package/dist/base/utils/index.d.cts +37 -0
- package/dist/base/utils/index.d.ts +37 -0
- package/dist/base/utils/index.js +11 -0
- package/dist/base/utils/index.js.map +1 -0
- package/dist/base/worker/index.cjs +548 -0
- package/dist/base/worker/index.cjs.map +1 -0
- package/dist/base/worker/index.d.cts +207 -0
- package/dist/base/worker/index.d.ts +207 -0
- package/dist/base/worker/index.js +20 -0
- package/dist/base/worker/index.js.map +1 -0
- package/dist/breaker-C9skL3d8.d.ts +175 -0
- package/dist/breaker-ugSdq54q.d.cts +175 -0
- package/dist/cascading-CSSbKGrJ.d.ts +199 -0
- package/dist/cascading-baGkiihI.d.cts +199 -0
- package/dist/chunk-255UCBG4.js +58 -0
- package/dist/chunk-255UCBG4.js.map +1 -0
- package/dist/chunk-2LO3EL4W.js +1 -0
- package/dist/chunk-2LO3EL4W.js.map +1 -0
- package/dist/chunk-2OB3CEJS.js +1065 -0
- package/dist/chunk-2OB3CEJS.js.map +1 -0
- package/dist/chunk-36NMM65U.js +144 -0
- package/dist/chunk-36NMM65U.js.map +1 -0
- package/dist/chunk-3CEXCBN6.js +1 -0
- package/dist/chunk-3CEXCBN6.js.map +1 -0
- package/dist/chunk-3MUSLI6E.js +105 -0
- package/dist/chunk-3MUSLI6E.js.map +1 -0
- package/dist/chunk-3PSLNJDU.js +884 -0
- package/dist/chunk-3PSLNJDU.js.map +1 -0
- package/dist/chunk-3QZY5BI7.js +92 -0
- package/dist/chunk-3QZY5BI7.js.map +1 -0
- package/dist/chunk-42FQ27MQ.js +594 -0
- package/dist/chunk-42FQ27MQ.js.map +1 -0
- package/dist/chunk-4GYMCUDZ.js +1085 -0
- package/dist/chunk-4GYMCUDZ.js.map +1 -0
- package/dist/chunk-4S53H2KR.js +382 -0
- package/dist/chunk-4S53H2KR.js.map +1 -0
- package/dist/chunk-4XCHZRUJ.js +128 -0
- package/dist/chunk-4XCHZRUJ.js.map +1 -0
- package/dist/chunk-5THCXDWY.js +725 -0
- package/dist/chunk-5THCXDWY.js.map +1 -0
- package/dist/chunk-6XZYT4SW.js +256 -0
- package/dist/chunk-6XZYT4SW.js.map +1 -0
- package/dist/chunk-7EGRP2VX.js +76 -0
- package/dist/chunk-7EGRP2VX.js.map +1 -0
- package/dist/chunk-A7KV5UK4.js +150 -0
- package/dist/chunk-A7KV5UK4.js.map +1 -0
- package/dist/chunk-APY2SS5X.js +156 -0
- package/dist/chunk-APY2SS5X.js.map +1 -0
- package/dist/chunk-AZDQPQ3V.js +66 -0
- package/dist/chunk-AZDQPQ3V.js.map +1 -0
- package/dist/chunk-BU3SEFA5.js +90 -0
- package/dist/chunk-BU3SEFA5.js.map +1 -0
- package/dist/chunk-BXGZFGZ4.js +189 -0
- package/dist/chunk-BXGZFGZ4.js.map +1 -0
- package/dist/chunk-CGHORL6G.js +579 -0
- package/dist/chunk-CGHORL6G.js.map +1 -0
- package/dist/chunk-CXANAIZU.js +530 -0
- package/dist/chunk-CXANAIZU.js.map +1 -0
- package/dist/chunk-CZQHCKKG.js +1 -0
- package/dist/chunk-CZQHCKKG.js.map +1 -0
- package/dist/chunk-DKNHAICT.js +133 -0
- package/dist/chunk-DKNHAICT.js.map +1 -0
- package/dist/chunk-DM4OMPWK.js +584 -0
- package/dist/chunk-DM4OMPWK.js.map +1 -0
- package/dist/chunk-DMSNO6ZB.js +452 -0
- package/dist/chunk-DMSNO6ZB.js.map +1 -0
- package/dist/chunk-E5OZPDIW.js +229 -0
- package/dist/chunk-E5OZPDIW.js.map +1 -0
- package/dist/chunk-EVYY4X5A.js +509 -0
- package/dist/chunk-EVYY4X5A.js.map +1 -0
- package/dist/chunk-FDFD67UO.js +1 -0
- package/dist/chunk-FDFD67UO.js.map +1 -0
- package/dist/chunk-FMPF42Q4.js +13 -0
- package/dist/chunk-FMPF42Q4.js.map +1 -0
- package/dist/chunk-FR6RGA3B.js +1277 -0
- package/dist/chunk-FR6RGA3B.js.map +1 -0
- package/dist/chunk-FW23JYNQ.js +454 -0
- package/dist/chunk-FW23JYNQ.js.map +1 -0
- package/dist/chunk-GBCENOLN.js +1575 -0
- package/dist/chunk-GBCENOLN.js.map +1 -0
- package/dist/chunk-HL7HUJIX.js +1 -0
- package/dist/chunk-HL7HUJIX.js.map +1 -0
- package/dist/chunk-HULCUY35.js +2508 -0
- package/dist/chunk-HULCUY35.js.map +1 -0
- package/dist/chunk-IHTWQEDR.js +169 -0
- package/dist/chunk-IHTWQEDR.js.map +1 -0
- package/dist/chunk-IJRR6YAI.js +128 -0
- package/dist/chunk-IJRR6YAI.js.map +1 -0
- package/dist/chunk-JGFRAFDL.js +221 -0
- package/dist/chunk-JGFRAFDL.js.map +1 -0
- package/dist/chunk-KIIXR252.js +211 -0
- package/dist/chunk-KIIXR252.js.map +1 -0
- package/dist/chunk-KN3H5CNT.js +11 -0
- package/dist/chunk-KN3H5CNT.js.map +1 -0
- package/dist/chunk-KPG3DGLA.js +1 -0
- package/dist/chunk-KPG3DGLA.js.map +1 -0
- package/dist/chunk-KRNQ6RGQ.js +1 -0
- package/dist/chunk-KRNQ6RGQ.js.map +1 -0
- package/dist/chunk-LBAJK24K.js +1071 -0
- package/dist/chunk-LBAJK24K.js.map +1 -0
- package/dist/chunk-MLTPJMH6.js +417 -0
- package/dist/chunk-MLTPJMH6.js.map +1 -0
- package/dist/chunk-N3SZ7BMH.js +95 -0
- package/dist/chunk-N3SZ7BMH.js.map +1 -0
- package/dist/chunk-NDUD3IMO.js +540 -0
- package/dist/chunk-NDUD3IMO.js.map +1 -0
- package/dist/chunk-NY2PYHNC.js +873 -0
- package/dist/chunk-NY2PYHNC.js.map +1 -0
- package/dist/chunk-O3MT7DYI.js +225 -0
- package/dist/chunk-O3MT7DYI.js.map +1 -0
- package/dist/chunk-OCUDSN63.js +2386 -0
- package/dist/chunk-OCUDSN63.js.map +1 -0
- package/dist/chunk-OIWU3NYV.js +199 -0
- package/dist/chunk-OIWU3NYV.js.map +1 -0
- package/dist/chunk-OO5BM6CJ.js +1153 -0
- package/dist/chunk-OO5BM6CJ.js.map +1 -0
- package/dist/chunk-OQUIJT7A.js +1 -0
- package/dist/chunk-OQUIJT7A.js.map +1 -0
- package/dist/chunk-P5LBT622.js +105 -0
- package/dist/chunk-P5LBT622.js.map +1 -0
- package/dist/chunk-PKGQG5QQ.js +519 -0
- package/dist/chunk-PKGQG5QQ.js.map +1 -0
- package/dist/chunk-PKPO3JTZ.js +561 -0
- package/dist/chunk-PKPO3JTZ.js.map +1 -0
- package/dist/chunk-PL5UDIQ5.js +118 -0
- package/dist/chunk-PL5UDIQ5.js.map +1 -0
- package/dist/chunk-PZWISPIQ.js +432 -0
- package/dist/chunk-PZWISPIQ.js.map +1 -0
- package/dist/chunk-Q3EYOCZB.js +510 -0
- package/dist/chunk-Q3EYOCZB.js.map +1 -0
- package/dist/chunk-QMBYUVRL.js +15 -0
- package/dist/chunk-QMBYUVRL.js.map +1 -0
- package/dist/chunk-RAGGHLCV.js +200 -0
- package/dist/chunk-RAGGHLCV.js.map +1 -0
- package/dist/chunk-RGL53X5G.js +574 -0
- package/dist/chunk-RGL53X5G.js.map +1 -0
- package/dist/chunk-RJOG4IJU.js +1039 -0
- package/dist/chunk-RJOG4IJU.js.map +1 -0
- package/dist/chunk-SOOKUYVM.js +403 -0
- package/dist/chunk-SOOKUYVM.js.map +1 -0
- package/dist/chunk-T5BN5KG7.js +1 -0
- package/dist/chunk-T5BN5KG7.js.map +1 -0
- package/dist/chunk-TP7244Y6.js +207 -0
- package/dist/chunk-TP7244Y6.js.map +1 -0
- package/dist/chunk-TSBFTJKM.js +57 -0
- package/dist/chunk-TSBFTJKM.js.map +1 -0
- package/dist/chunk-URQ2CBBF.js +143 -0
- package/dist/chunk-URQ2CBBF.js.map +1 -0
- package/dist/chunk-W2BOPXTI.js +1 -0
- package/dist/chunk-W2BOPXTI.js.map +1 -0
- package/dist/chunk-WKSWLSCX.js +207 -0
- package/dist/chunk-WKSWLSCX.js.map +1 -0
- package/dist/chunk-Y52CS6YA.js +88 -0
- package/dist/chunk-Y52CS6YA.js.map +1 -0
- package/dist/chunk-YCBUWK77.js +92 -0
- package/dist/chunk-YCBUWK77.js.map +1 -0
- package/dist/chunk-YJ4U2D2C.js +314 -0
- package/dist/chunk-YJ4U2D2C.js.map +1 -0
- package/dist/chunk-Z4YXAUDN.js +239 -0
- package/dist/chunk-Z4YXAUDN.js.map +1 -0
- package/dist/chunk-Z6EGP5D7.js +92 -0
- package/dist/chunk-Z6EGP5D7.js.map +1 -0
- package/dist/compat/index.cjs +3083 -2
- package/dist/compat/index.cjs.map +1 -1
- package/dist/compat/index.d.cts +116 -1
- package/dist/compat/index.d.ts +116 -1
- package/dist/compat/index.js +175 -2
- package/dist/compat/index.js.map +1 -1
- package/dist/compat/jotai/index.cjs +130 -2
- package/dist/compat/jotai/index.cjs.map +1 -1
- package/dist/compat/jotai/index.d.cts +2 -1
- package/dist/compat/jotai/index.d.ts +2 -1
- package/dist/compat/jotai/index.js +7 -2
- package/dist/compat/jotai/index.js.map +1 -1
- package/dist/compat/nanostores/index.cjs +186 -2
- package/dist/compat/nanostores/index.cjs.map +1 -1
- package/dist/compat/nanostores/index.d.cts +2 -1
- package/dist/compat/nanostores/index.d.ts +2 -1
- package/dist/compat/nanostores/index.js +21 -2
- package/dist/compat/nanostores/index.js.map +1 -1
- package/dist/compat/nestjs/index.cjs +2224 -2
- package/dist/compat/nestjs/index.cjs.map +1 -1
- package/dist/compat/nestjs/index.d.cts +10 -1
- package/dist/compat/nestjs/index.d.ts +10 -1
- package/dist/compat/nestjs/index.js +77 -2
- package/dist/compat/nestjs/index.js.map +1 -1
- package/dist/compat/react/index.cjs +95 -2
- package/dist/compat/react/index.cjs.map +1 -1
- package/dist/compat/react/index.d.cts +2 -1
- package/dist/compat/react/index.d.ts +2 -1
- package/dist/compat/react/index.js +11 -2
- package/dist/compat/react/index.js.map +1 -1
- package/dist/compat/solid/index.cjs +82 -2
- package/dist/compat/solid/index.cjs.map +1 -1
- package/dist/compat/solid/index.d.cts +2 -1
- package/dist/compat/solid/index.d.ts +2 -1
- package/dist/compat/solid/index.js +11 -2
- package/dist/compat/solid/index.js.map +1 -1
- package/dist/compat/svelte/index.cjs +85 -2
- package/dist/compat/svelte/index.cjs.map +1 -1
- package/dist/compat/svelte/index.d.cts +2 -1
- package/dist/compat/svelte/index.d.ts +2 -1
- package/dist/compat/svelte/index.js +11 -2
- package/dist/compat/svelte/index.js.map +1 -1
- package/dist/compat/vue/index.cjs +100 -2
- package/dist/compat/vue/index.cjs.map +1 -1
- package/dist/compat/vue/index.d.cts +3 -1
- package/dist/compat/vue/index.d.ts +3 -1
- package/dist/compat/vue/index.js +11 -2
- package/dist/compat/vue/index.js.map +1 -1
- package/dist/compat/zustand/index.cjs +50 -2
- package/dist/compat/zustand/index.cjs.map +1 -1
- package/dist/compat/zustand/index.d.cts +2 -1
- package/dist/compat/zustand/index.d.ts +2 -1
- package/dist/compat/zustand/index.js +7 -2
- package/dist/compat/zustand/index.js.map +1 -1
- package/dist/distill-De6Rnn15.d.cts +48 -0
- package/dist/distill-De6Rnn15.d.ts +48 -0
- package/dist/external-register-CWyroXb_.d.cts +138 -0
- package/dist/external-register-CWyroXb_.d.ts +138 -0
- package/dist/fallback-Bx46zqky.d.cts +243 -0
- package/dist/fallback-pIWW8A2d.d.ts +243 -0
- package/dist/guarded-execution-BcdtxeBk.d.ts +207 -0
- package/dist/guarded-execution-C-3hnP6A.d.cts +207 -0
- package/dist/index-5SU_O78r.d.cts +754 -0
- package/dist/index-B6pxYJzO.d.cts +36 -0
- package/dist/index-B6pxYJzO.d.ts +36 -0
- package/dist/index-BFsng6v1.d.cts +44 -0
- package/dist/index-BFsng6v1.d.ts +44 -0
- package/dist/index-Bg-LwEt-.d.cts +45 -0
- package/dist/index-Bg-LwEt-.d.ts +45 -0
- package/dist/index-Brp888t0.d.cts +127 -0
- package/dist/index-Brp888t0.d.ts +127 -0
- package/dist/index-CDfk6jHN.d.cts +37 -0
- package/dist/index-CDfk6jHN.d.ts +37 -0
- package/dist/index-CEXCtYYJ.d.ts +754 -0
- package/dist/index-DLAxYaN5.d.cts +169 -0
- package/dist/index-DLAxYaN5.d.ts +169 -0
- package/dist/index-DeWbQzMe.d.cts +34 -0
- package/dist/index-DeWbQzMe.d.ts +34 -0
- package/dist/index-dX9IzPqj.d.cts +86 -0
- package/dist/index-dX9IzPqj.d.ts +86 -0
- package/dist/index.cjs +25950 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +56 -42
- package/dist/index.d.ts +56 -42
- package/dist/index.js +849 -0
- package/dist/index.js.map +1 -1
- package/dist/layout-types-B5aiHYgk.d.cts +72 -0
- package/dist/layout-types-B5aiHYgk.d.ts +72 -0
- package/dist/memory-composers-BryDrRBX.d.cts +529 -0
- package/dist/memory-composers-CVQqPYEV.d.ts +529 -0
- package/dist/observable-BXQoW1P-.d.cts +36 -0
- package/dist/observable-BXQoW1P-.d.ts +36 -0
- package/dist/pipeline-graph-Ce47CB6Y.d.cts +145 -0
- package/dist/pipeline-graph-DXCwY9vG.d.ts +145 -0
- package/dist/presets/ai/index.cjs +4377 -0
- package/dist/presets/ai/index.cjs.map +1 -0
- package/dist/presets/ai/index.d.cts +98 -0
- package/dist/presets/ai/index.d.ts +98 -0
- package/dist/presets/ai/index.js +54 -0
- package/dist/presets/ai/index.js.map +1 -0
- package/dist/presets/harness/index.cjs +5929 -0
- package/dist/presets/harness/index.cjs.map +1 -0
- package/dist/presets/harness/index.d.cts +566 -0
- package/dist/presets/harness/index.d.ts +566 -0
- package/dist/presets/harness/index.js +71 -0
- package/dist/presets/harness/index.js.map +1 -0
- package/dist/presets/index.cjs +9782 -0
- package/dist/presets/index.cjs.map +1 -0
- package/dist/presets/index.d.cts +28 -0
- package/dist/presets/index.d.ts +28 -0
- package/dist/presets/index.js +129 -0
- package/dist/presets/index.js.map +1 -0
- package/dist/presets/inspect/index.cjs +1087 -0
- package/dist/presets/inspect/index.cjs.map +1 -0
- package/dist/presets/inspect/index.d.cts +172 -0
- package/dist/presets/inspect/index.d.ts +172 -0
- package/dist/presets/inspect/index.js +21 -0
- package/dist/presets/inspect/index.js.map +1 -0
- package/dist/presets/resilience/index.cjs +1593 -0
- package/dist/presets/resilience/index.cjs.map +1 -0
- package/dist/presets/resilience/index.d.cts +205 -0
- package/dist/presets/resilience/index.d.ts +205 -0
- package/dist/presets/resilience/index.js +18 -0
- package/dist/presets/resilience/index.js.map +1 -0
- package/dist/rate-limiter-CEALq4N1.d.ts +559 -0
- package/dist/rate-limiter-DpVbSYdH.d.cts +559 -0
- package/dist/reactive-layout-fswlBUvX.d.cts +195 -0
- package/dist/reactive-layout-fswlBUvX.d.ts +195 -0
- package/dist/retry-BDbRZ_gx.d.ts +125 -0
- package/dist/retry-DWuhjvsA.d.cts +125 -0
- package/dist/solutions/index.cjs +8200 -0
- package/dist/solutions/index.cjs.map +1 -0
- package/dist/solutions/index.d.cts +23 -0
- package/dist/solutions/index.d.ts +23 -0
- package/dist/solutions/index.js +55 -0
- package/dist/solutions/index.js.map +1 -0
- package/dist/spawnable-5mDY501F.d.cts +746 -0
- package/dist/spawnable-D3lR0oQu.d.ts +746 -0
- package/dist/status-U-rUI79b.d.cts +84 -0
- package/dist/status-U-rUI79b.d.ts +84 -0
- package/dist/timeout-U5O4ESK3.js +12 -0
- package/dist/timeout-U5O4ESK3.js.map +1 -0
- package/dist/types-BB5Lw-pB.d.cts +442 -0
- package/dist/types-BB5Lw-pB.d.ts +442 -0
- package/dist/types-CJWIMJiZ.d.ts +548 -0
- package/dist/types-vCq7ShIm.d.cts +548 -0
- package/dist/utils/ai/browser.cjs +2169 -0
- package/dist/utils/ai/browser.cjs.map +1 -0
- package/dist/utils/ai/browser.d.cts +129 -0
- package/dist/utils/ai/browser.d.ts +129 -0
- package/dist/utils/ai/browser.js +255 -0
- package/dist/utils/ai/browser.js.map +1 -0
- package/dist/utils/ai/index.cjs +8468 -0
- package/dist/utils/ai/index.cjs.map +1 -0
- package/dist/utils/ai/index.d.cts +1777 -0
- package/dist/utils/ai/index.d.ts +1777 -0
- package/dist/utils/ai/index.js +173 -0
- package/dist/utils/ai/index.js.map +1 -0
- package/dist/utils/ai/node.cjs +648 -0
- package/dist/utils/ai/node.cjs.map +1 -0
- package/dist/utils/ai/node.d.cts +57 -0
- package/dist/utils/ai/node.d.ts +57 -0
- package/dist/utils/ai/node.js +84 -0
- package/dist/utils/ai/node.js.map +1 -0
- package/dist/utils/cqrs/index.cjs +1036 -0
- package/dist/utils/cqrs/index.cjs.map +1 -0
- package/dist/utils/cqrs/index.d.cts +438 -0
- package/dist/utils/cqrs/index.d.ts +438 -0
- package/dist/utils/cqrs/index.js +18 -0
- package/dist/utils/cqrs/index.js.map +1 -0
- package/dist/utils/demo-shell/index.cjs +865 -0
- package/dist/utils/demo-shell/index.cjs.map +1 -0
- package/dist/utils/demo-shell/index.d.cts +90 -0
- package/dist/utils/demo-shell/index.d.ts +90 -0
- package/dist/utils/demo-shell/index.js +13 -0
- package/dist/utils/demo-shell/index.js.map +1 -0
- package/dist/utils/domain-templates/index.cjs +732 -0
- package/dist/utils/domain-templates/index.cjs.map +1 -0
- package/dist/utils/domain-templates/index.d.cts +214 -0
- package/dist/utils/domain-templates/index.d.ts +214 -0
- package/dist/utils/domain-templates/index.js +17 -0
- package/dist/utils/domain-templates/index.js.map +1 -0
- package/dist/utils/graphspec/index.cjs +1174 -0
- package/dist/utils/graphspec/index.cjs.map +1 -0
- package/dist/utils/graphspec/index.d.cts +449 -0
- package/dist/utils/graphspec/index.d.ts +449 -0
- package/dist/utils/graphspec/index.js +35 -0
- package/dist/utils/graphspec/index.js.map +1 -0
- package/dist/utils/harness/index.cjs +656 -0
- package/dist/utils/harness/index.cjs.map +1 -0
- package/dist/utils/harness/index.d.cts +542 -0
- package/dist/utils/harness/index.d.ts +542 -0
- package/dist/utils/harness/index.js +56 -0
- package/dist/utils/harness/index.js.map +1 -0
- package/dist/utils/index.cjs +17609 -0
- package/dist/utils/index.cjs.map +1 -0
- package/dist/utils/index.d.cts +96 -0
- package/dist/utils/index.d.ts +96 -0
- package/dist/utils/index.js +514 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/inspect/index.cjs +807 -0
- package/dist/utils/inspect/index.cjs.map +1 -0
- package/dist/utils/inspect/index.d.cts +123 -0
- package/dist/utils/inspect/index.d.ts +123 -0
- package/dist/utils/inspect/index.js +30 -0
- package/dist/utils/inspect/index.js.map +1 -0
- package/dist/utils/job-queue/index.cjs +717 -0
- package/dist/utils/job-queue/index.cjs.map +1 -0
- package/dist/utils/job-queue/index.d.cts +200 -0
- package/dist/utils/job-queue/index.d.ts +200 -0
- package/dist/utils/job-queue/index.js +18 -0
- package/dist/utils/job-queue/index.js.map +1 -0
- package/dist/utils/memory/index.cjs +1451 -0
- package/dist/utils/memory/index.cjs.map +1 -0
- package/dist/utils/memory/index.d.cts +582 -0
- package/dist/utils/memory/index.d.ts +582 -0
- package/dist/utils/memory/index.js +19 -0
- package/dist/utils/memory/index.js.map +1 -0
- package/dist/utils/messaging/index.cjs +666 -0
- package/dist/utils/messaging/index.cjs.map +1 -0
- package/dist/utils/messaging/index.d.cts +562 -0
- package/dist/utils/messaging/index.d.ts +562 -0
- package/dist/utils/messaging/index.js +50 -0
- package/dist/utils/messaging/index.js.map +1 -0
- package/dist/utils/orchestration/index.cjs +876 -0
- package/dist/utils/orchestration/index.cjs.map +1 -0
- package/dist/utils/orchestration/index.d.cts +233 -0
- package/dist/utils/orchestration/index.d.ts +233 -0
- package/dist/utils/orchestration/index.js +19 -0
- package/dist/utils/orchestration/index.js.map +1 -0
- package/dist/utils/process/index.cjs +743 -0
- package/dist/utils/process/index.cjs.map +1 -0
- package/dist/utils/process/index.d.cts +411 -0
- package/dist/utils/process/index.d.ts +411 -0
- package/dist/utils/process/index.js +14 -0
- package/dist/utils/process/index.js.map +1 -0
- package/dist/utils/reactive-layout/index.cjs +1607 -0
- package/dist/utils/reactive-layout/index.cjs.map +1 -0
- package/dist/utils/reactive-layout/index.d.cts +492 -0
- package/dist/utils/reactive-layout/index.d.ts +492 -0
- package/dist/utils/reactive-layout/index.js +52 -0
- package/dist/utils/reactive-layout/index.js.map +1 -0
- package/dist/utils/reduction/index.cjs +203 -0
- package/dist/utils/reduction/index.cjs.map +1 -0
- package/dist/utils/reduction/index.d.cts +102 -0
- package/dist/utils/reduction/index.d.ts +102 -0
- package/dist/utils/reduction/index.js +14 -0
- package/dist/utils/reduction/index.js.map +1 -0
- package/dist/utils/resilience/index.cjs +1617 -0
- package/dist/utils/resilience/index.cjs.map +1 -0
- package/dist/utils/resilience/index.d.cts +9 -0
- package/dist/utils/resilience/index.d.ts +9 -0
- package/dist/utils/resilience/index.js +44 -0
- package/dist/utils/resilience/index.js.map +1 -0
- package/dist/utils/surface/index.cjs +1070 -0
- package/dist/utils/surface/index.cjs.map +1 -0
- package/dist/utils/surface/index.d.cts +240 -0
- package/dist/utils/surface/index.d.ts +240 -0
- package/dist/utils/surface/index.js +30 -0
- package/dist/utils/surface/index.js.map +1 -0
- package/dist/utils/topology-view/index.cjs +620 -0
- package/dist/utils/topology-view/index.cjs.map +1 -0
- package/dist/utils/topology-view/index.d.cts +68 -0
- package/dist/utils/topology-view/index.d.ts +68 -0
- package/dist/utils/topology-view/index.js +11 -0
- package/dist/utils/topology-view/index.js.map +1 -0
- package/package.json +293 -237
- package/dist/core/index.cjs +0 -21
- package/dist/core/index.cjs.map +0 -1
- package/dist/core/index.d.cts +0 -1
- package/dist/core/index.d.ts +0 -1
- package/dist/core/index.js +0 -3
- package/dist/core/index.js.map +0 -1
- package/dist/extra/browser.cjs +0 -21
- package/dist/extra/browser.cjs.map +0 -1
- package/dist/extra/browser.d.cts +0 -1
- package/dist/extra/browser.d.ts +0 -1
- package/dist/extra/browser.js +0 -3
- package/dist/extra/browser.js.map +0 -1
- package/dist/extra/index.cjs +0 -21
- package/dist/extra/index.cjs.map +0 -1
- package/dist/extra/index.d.cts +0 -1
- package/dist/extra/index.d.ts +0 -1
- package/dist/extra/index.js +0 -3
- package/dist/extra/index.js.map +0 -1
- package/dist/extra/node.cjs +0 -21
- package/dist/extra/node.cjs.map +0 -1
- package/dist/extra/node.d.cts +0 -1
- package/dist/extra/node.d.ts +0 -1
- package/dist/extra/node.js +0 -3
- package/dist/extra/node.js.map +0 -1
- package/dist/extra/operators.cjs +0 -21
- package/dist/extra/operators.cjs.map +0 -1
- package/dist/extra/operators.d.cts +0 -1
- package/dist/extra/operators.d.ts +0 -1
- package/dist/extra/operators.js +0 -3
- package/dist/extra/operators.js.map +0 -1
- package/dist/extra/reactive.cjs +0 -21
- package/dist/extra/reactive.cjs.map +0 -1
- package/dist/extra/reactive.d.cts +0 -1
- package/dist/extra/reactive.d.ts +0 -1
- package/dist/extra/reactive.js +0 -3
- package/dist/extra/reactive.js.map +0 -1
- package/dist/extra/render/index.cjs +0 -21
- package/dist/extra/render/index.cjs.map +0 -1
- package/dist/extra/render/index.d.cts +0 -1
- package/dist/extra/render/index.d.ts +0 -1
- package/dist/extra/render/index.js +0 -3
- package/dist/extra/render/index.js.map +0 -1
- package/dist/extra/sources.cjs +0 -21
- package/dist/extra/sources.cjs.map +0 -1
- package/dist/extra/sources.d.cts +0 -1
- package/dist/extra/sources.d.ts +0 -1
- package/dist/extra/sources.js +0 -3
- package/dist/extra/sources.js.map +0 -1
- package/dist/extra/storage-browser.cjs +0 -21
- package/dist/extra/storage-browser.cjs.map +0 -1
- package/dist/extra/storage-browser.d.cts +0 -1
- package/dist/extra/storage-browser.d.ts +0 -1
- package/dist/extra/storage-browser.js +0 -3
- package/dist/extra/storage-browser.js.map +0 -1
- package/dist/extra/storage-core.cjs +0 -21
- package/dist/extra/storage-core.cjs.map +0 -1
- package/dist/extra/storage-core.d.cts +0 -1
- package/dist/extra/storage-core.d.ts +0 -1
- package/dist/extra/storage-core.js +0 -3
- package/dist/extra/storage-core.js.map +0 -1
- package/dist/extra/storage-node.cjs +0 -21
- package/dist/extra/storage-node.cjs.map +0 -1
- package/dist/extra/storage-node.d.cts +0 -1
- package/dist/extra/storage-node.d.ts +0 -1
- package/dist/extra/storage-node.js +0 -3
- package/dist/extra/storage-node.js.map +0 -1
- package/dist/extra/storage-tiers-browser.cjs +0 -21
- package/dist/extra/storage-tiers-browser.cjs.map +0 -1
- package/dist/extra/storage-tiers-browser.d.cts +0 -1
- package/dist/extra/storage-tiers-browser.d.ts +0 -1
- package/dist/extra/storage-tiers-browser.js +0 -3
- package/dist/extra/storage-tiers-browser.js.map +0 -1
- package/dist/extra/storage-tiers-node.cjs +0 -21
- package/dist/extra/storage-tiers-node.cjs.map +0 -1
- package/dist/extra/storage-tiers-node.d.cts +0 -1
- package/dist/extra/storage-tiers-node.d.ts +0 -1
- package/dist/extra/storage-tiers-node.js +0 -3
- package/dist/extra/storage-tiers-node.js.map +0 -1
- package/dist/extra/storage-tiers.cjs +0 -21
- package/dist/extra/storage-tiers.cjs.map +0 -1
- package/dist/extra/storage-tiers.d.cts +0 -1
- package/dist/extra/storage-tiers.d.ts +0 -1
- package/dist/extra/storage-tiers.js +0 -3
- package/dist/extra/storage-tiers.js.map +0 -1
- package/dist/extra/storage-wal.cjs +0 -21
- package/dist/extra/storage-wal.cjs.map +0 -1
- package/dist/extra/storage-wal.d.cts +0 -1
- package/dist/extra/storage-wal.d.ts +0 -1
- package/dist/extra/storage-wal.js +0 -3
- package/dist/extra/storage-wal.js.map +0 -1
- package/dist/graph/index.cjs +0 -21
- package/dist/graph/index.cjs.map +0 -1
- package/dist/graph/index.d.cts +0 -1
- package/dist/graph/index.d.ts +0 -1
- package/dist/graph/index.js +0 -3
- package/dist/graph/index.js.map +0 -1
- package/dist/patterns/ai/browser.cjs +0 -21
- package/dist/patterns/ai/browser.cjs.map +0 -1
- package/dist/patterns/ai/browser.d.cts +0 -1
- package/dist/patterns/ai/browser.d.ts +0 -1
- package/dist/patterns/ai/browser.js +0 -3
- package/dist/patterns/ai/browser.js.map +0 -1
- package/dist/patterns/ai/index.cjs +0 -21
- package/dist/patterns/ai/index.cjs.map +0 -1
- package/dist/patterns/ai/index.d.cts +0 -1
- package/dist/patterns/ai/index.d.ts +0 -1
- package/dist/patterns/ai/index.js +0 -3
- package/dist/patterns/ai/index.js.map +0 -1
- package/dist/patterns/ai/node.cjs +0 -21
- package/dist/patterns/ai/node.cjs.map +0 -1
- package/dist/patterns/ai/node.d.cts +0 -1
- package/dist/patterns/ai/node.d.ts +0 -1
- package/dist/patterns/ai/node.js +0 -3
- package/dist/patterns/ai/node.js.map +0 -1
- package/dist/patterns/cqrs/index.cjs +0 -21
- package/dist/patterns/cqrs/index.cjs.map +0 -1
- package/dist/patterns/cqrs/index.d.cts +0 -1
- package/dist/patterns/cqrs/index.d.ts +0 -1
- package/dist/patterns/cqrs/index.js +0 -3
- package/dist/patterns/cqrs/index.js.map +0 -1
- package/dist/patterns/demo-shell/index.cjs +0 -21
- package/dist/patterns/demo-shell/index.cjs.map +0 -1
- package/dist/patterns/demo-shell/index.d.cts +0 -1
- package/dist/patterns/demo-shell/index.d.ts +0 -1
- package/dist/patterns/demo-shell/index.js +0 -3
- package/dist/patterns/demo-shell/index.js.map +0 -1
- package/dist/patterns/domain-templates/index.cjs +0 -21
- package/dist/patterns/domain-templates/index.cjs.map +0 -1
- package/dist/patterns/domain-templates/index.d.cts +0 -1
- package/dist/patterns/domain-templates/index.d.ts +0 -1
- package/dist/patterns/domain-templates/index.js +0 -3
- package/dist/patterns/domain-templates/index.js.map +0 -1
- package/dist/patterns/graphspec/index.cjs +0 -21
- package/dist/patterns/graphspec/index.cjs.map +0 -1
- package/dist/patterns/graphspec/index.d.cts +0 -1
- package/dist/patterns/graphspec/index.d.ts +0 -1
- package/dist/patterns/graphspec/index.js +0 -3
- package/dist/patterns/graphspec/index.js.map +0 -1
- package/dist/patterns/harness/index.cjs +0 -21
- package/dist/patterns/harness/index.cjs.map +0 -1
- package/dist/patterns/harness/index.d.cts +0 -1
- package/dist/patterns/harness/index.d.ts +0 -1
- package/dist/patterns/harness/index.js +0 -3
- package/dist/patterns/harness/index.js.map +0 -1
- package/dist/patterns/inspect/index.cjs +0 -21
- package/dist/patterns/inspect/index.cjs.map +0 -1
- package/dist/patterns/inspect/index.d.cts +0 -1
- package/dist/patterns/inspect/index.d.ts +0 -1
- package/dist/patterns/inspect/index.js +0 -3
- package/dist/patterns/inspect/index.js.map +0 -1
- package/dist/patterns/job-queue/index.cjs +0 -21
- package/dist/patterns/job-queue/index.cjs.map +0 -1
- package/dist/patterns/job-queue/index.d.cts +0 -1
- package/dist/patterns/job-queue/index.d.ts +0 -1
- package/dist/patterns/job-queue/index.js +0 -3
- package/dist/patterns/job-queue/index.js.map +0 -1
- package/dist/patterns/memory/index.cjs +0 -21
- package/dist/patterns/memory/index.cjs.map +0 -1
- package/dist/patterns/memory/index.d.cts +0 -1
- package/dist/patterns/memory/index.d.ts +0 -1
- package/dist/patterns/memory/index.js +0 -3
- package/dist/patterns/memory/index.js.map +0 -1
- package/dist/patterns/messaging/index.cjs +0 -21
- package/dist/patterns/messaging/index.cjs.map +0 -1
- package/dist/patterns/messaging/index.d.cts +0 -1
- package/dist/patterns/messaging/index.d.ts +0 -1
- package/dist/patterns/messaging/index.js +0 -3
- package/dist/patterns/messaging/index.js.map +0 -1
- package/dist/patterns/orchestration/index.cjs +0 -21
- package/dist/patterns/orchestration/index.cjs.map +0 -1
- package/dist/patterns/orchestration/index.d.cts +0 -1
- package/dist/patterns/orchestration/index.d.ts +0 -1
- package/dist/patterns/orchestration/index.js +0 -3
- package/dist/patterns/orchestration/index.js.map +0 -1
- package/dist/patterns/process/index.cjs +0 -21
- package/dist/patterns/process/index.cjs.map +0 -1
- package/dist/patterns/process/index.d.cts +0 -1
- package/dist/patterns/process/index.d.ts +0 -1
- package/dist/patterns/process/index.js +0 -3
- package/dist/patterns/process/index.js.map +0 -1
- package/dist/patterns/reactive-layout/index.cjs +0 -21
- package/dist/patterns/reactive-layout/index.cjs.map +0 -1
- package/dist/patterns/reactive-layout/index.d.cts +0 -1
- package/dist/patterns/reactive-layout/index.d.ts +0 -1
- package/dist/patterns/reactive-layout/index.js +0 -3
- package/dist/patterns/reactive-layout/index.js.map +0 -1
- package/dist/patterns/reduction/index.cjs +0 -21
- package/dist/patterns/reduction/index.cjs.map +0 -1
- package/dist/patterns/reduction/index.d.cts +0 -1
- package/dist/patterns/reduction/index.d.ts +0 -1
- package/dist/patterns/reduction/index.js +0 -3
- package/dist/patterns/reduction/index.js.map +0 -1
- package/dist/patterns/surface/index.cjs +0 -21
- package/dist/patterns/surface/index.cjs.map +0 -1
- package/dist/patterns/surface/index.d.cts +0 -1
- package/dist/patterns/surface/index.d.ts +0 -1
- package/dist/patterns/surface/index.js +0 -3
- package/dist/patterns/surface/index.js.map +0 -1
- package/dist/patterns/topology-view/index.cjs +0 -21
- package/dist/patterns/topology-view/index.cjs.map +0 -1
- package/dist/patterns/topology-view/index.d.cts +0 -1
- package/dist/patterns/topology-view/index.d.ts +0 -1
- package/dist/patterns/topology-view/index.js +0 -3
- package/dist/patterns/topology-view/index.js.map +0 -1
- package/dist/testing/index.cjs +0 -21
- package/dist/testing/index.cjs.map +0 -1
- package/dist/testing/index.d.cts +0 -1
- package/dist/testing/index.d.ts +0 -1
- package/dist/testing/index.js +0 -3
- package/dist/testing/index.js.map +0 -1
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import {
|
|
2
|
+
domainMeta
|
|
3
|
+
} from "./chunk-FMPF42Q4.js";
|
|
4
|
+
import {
|
|
5
|
+
tryIncrementBounded
|
|
6
|
+
} from "./chunk-BXGZFGZ4.js";
|
|
7
|
+
|
|
8
|
+
// src/utils/reduction/index.ts
|
|
9
|
+
import {
|
|
10
|
+
batch,
|
|
11
|
+
COMPLETE,
|
|
12
|
+
DATA,
|
|
13
|
+
ERROR,
|
|
14
|
+
node
|
|
15
|
+
} from "@graphrefly/pure-ts/core";
|
|
16
|
+
import { merge } from "@graphrefly/pure-ts/extra";
|
|
17
|
+
import { Graph } from "@graphrefly/pure-ts/graph";
|
|
18
|
+
import { keepalive } from "@graphrefly/pure-ts/extra";
|
|
19
|
+
function baseMeta(kind, meta) {
|
|
20
|
+
return domainMeta("reduction", kind, meta);
|
|
21
|
+
}
|
|
22
|
+
function funnel(name, sources, stages, opts) {
|
|
23
|
+
if (sources.length === 0) throw new RangeError("funnel requires at least one source");
|
|
24
|
+
if (stages.length === 0) throw new RangeError("funnel requires at least one stage");
|
|
25
|
+
const g = new Graph(name, opts);
|
|
26
|
+
const merged = sources.length === 1 ? sources[0] : merge(...sources);
|
|
27
|
+
g.add(merged, { name: "merged" });
|
|
28
|
+
let prevOutputPath = "merged";
|
|
29
|
+
for (let i = 0; i < stages.length; i++) {
|
|
30
|
+
const stage = stages[i];
|
|
31
|
+
const sub = new Graph(stage.name);
|
|
32
|
+
stage.build(sub);
|
|
33
|
+
try {
|
|
34
|
+
sub.resolve("input");
|
|
35
|
+
} catch {
|
|
36
|
+
throw new Error(`funnel stage "${stage.name}" must define an "input" node`);
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
sub.resolve("output");
|
|
40
|
+
} catch {
|
|
41
|
+
throw new Error(`funnel stage "${stage.name}" must define an "output" node`);
|
|
42
|
+
}
|
|
43
|
+
g.mount(stage.name, sub);
|
|
44
|
+
const prevNode = g.resolve(prevOutputPath);
|
|
45
|
+
const stageInputPath = `${stage.name}::input`;
|
|
46
|
+
const stageInput = g.resolve(stageInputPath);
|
|
47
|
+
const bridgeName = `__bridge_${prevOutputPath}\u2192${stage.name}_input`;
|
|
48
|
+
const br = node(
|
|
49
|
+
[prevNode],
|
|
50
|
+
(batchData, _actions, ctx) => {
|
|
51
|
+
const data = batchData.map(
|
|
52
|
+
(batch2, i2) => batch2 != null && batch2.length > 0 ? batch2.at(-1) : ctx.prevData[i2]
|
|
53
|
+
);
|
|
54
|
+
stageInput.emit(data[0]);
|
|
55
|
+
return void 0;
|
|
56
|
+
},
|
|
57
|
+
{ describeKind: "effect", name: bridgeName }
|
|
58
|
+
);
|
|
59
|
+
g.add(br, { name: bridgeName });
|
|
60
|
+
g.addDisposer(keepalive(br));
|
|
61
|
+
prevOutputPath = `${stage.name}::output`;
|
|
62
|
+
}
|
|
63
|
+
return g;
|
|
64
|
+
}
|
|
65
|
+
function feedback(graph, condition, reentry, opts) {
|
|
66
|
+
const maxIter = opts?.maxIterations ?? 10;
|
|
67
|
+
const counterName = `__feedback_${condition}`;
|
|
68
|
+
const counter = node([], {
|
|
69
|
+
...{
|
|
70
|
+
meta: baseMeta("feedback_counter", {
|
|
71
|
+
maxIterations: maxIter,
|
|
72
|
+
feedbackFrom: condition,
|
|
73
|
+
feedbackTo: reentry
|
|
74
|
+
})
|
|
75
|
+
},
|
|
76
|
+
initial: 0
|
|
77
|
+
});
|
|
78
|
+
graph.add(counter, { name: counterName });
|
|
79
|
+
const condNode = graph.resolve(condition);
|
|
80
|
+
const reentryNode = graph.resolve(reentry);
|
|
81
|
+
const feedbackEffectName = `__feedback_effect_${condition}`;
|
|
82
|
+
const feedbackEffect = node(
|
|
83
|
+
[],
|
|
84
|
+
(_data, _feedbackActions) => {
|
|
85
|
+
const unsub = condNode.subscribe((msgs) => {
|
|
86
|
+
for (const msg of msgs) {
|
|
87
|
+
const t = msg[0];
|
|
88
|
+
if (t === DATA) {
|
|
89
|
+
const condValue = msg[1];
|
|
90
|
+
if (condValue == null) return;
|
|
91
|
+
batch(() => {
|
|
92
|
+
if (tryIncrementBounded(counter, maxIter)) {
|
|
93
|
+
reentryNode.emit(condValue);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
} else if (t === COMPLETE || t === ERROR) {
|
|
97
|
+
const terminal = t === ERROR && msg.length > 1 ? [ERROR, msg[1]] : [t];
|
|
98
|
+
counter.down([terminal]);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
return () => unsub();
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
name: feedbackEffectName,
|
|
106
|
+
describeKind: "effect",
|
|
107
|
+
meta: {
|
|
108
|
+
...baseMeta("feedback_effect", {
|
|
109
|
+
feedbackFrom: condition,
|
|
110
|
+
feedbackTo: reentry
|
|
111
|
+
}),
|
|
112
|
+
_internal: true
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
);
|
|
116
|
+
graph.add(feedbackEffect, { name: feedbackEffectName });
|
|
117
|
+
graph.addDisposer(keepalive(feedbackEffect));
|
|
118
|
+
return graph;
|
|
119
|
+
}
|
|
120
|
+
function scorer(sources, weights, opts) {
|
|
121
|
+
if (sources.length === 0) throw new RangeError("scorer requires at least one source");
|
|
122
|
+
if (sources.length !== weights.length) {
|
|
123
|
+
throw new RangeError("scorer requires the same number of sources and weights");
|
|
124
|
+
}
|
|
125
|
+
const allDeps = [...sources, ...weights];
|
|
126
|
+
const n = sources.length;
|
|
127
|
+
const scoreFns = opts?.scoreFns;
|
|
128
|
+
return node(
|
|
129
|
+
allDeps,
|
|
130
|
+
(batchData, actions, ctx) => {
|
|
131
|
+
const vals = batchData.map(
|
|
132
|
+
(batch2, i) => batch2 != null && batch2.length > 0 ? batch2.at(-1) : ctx.prevData[i]
|
|
133
|
+
);
|
|
134
|
+
const signals = vals.slice(0, n);
|
|
135
|
+
const weightValues = vals.slice(n);
|
|
136
|
+
const breakdown = [];
|
|
137
|
+
let totalScore = 0;
|
|
138
|
+
for (let i = 0; i < n; i++) {
|
|
139
|
+
const sig = signals[i] ?? 0;
|
|
140
|
+
const wt = weightValues[i] ?? 0;
|
|
141
|
+
const rawScore = scoreFns?.[i] ? scoreFns[i](sig) : sig;
|
|
142
|
+
const weighted = rawScore * wt;
|
|
143
|
+
breakdown.push(weighted);
|
|
144
|
+
totalScore += weighted;
|
|
145
|
+
}
|
|
146
|
+
actions.emit({
|
|
147
|
+
value: signals,
|
|
148
|
+
score: totalScore,
|
|
149
|
+
breakdown
|
|
150
|
+
});
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
...opts ? {
|
|
154
|
+
equals: opts.equals,
|
|
155
|
+
resubscribable: opts.resubscribable,
|
|
156
|
+
resetOnTeardown: opts.resetOnTeardown
|
|
157
|
+
} : {},
|
|
158
|
+
describeKind: "derived",
|
|
159
|
+
meta: baseMeta("scorer", opts?.meta)
|
|
160
|
+
}
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export {
|
|
165
|
+
funnel,
|
|
166
|
+
feedback,
|
|
167
|
+
scorer
|
|
168
|
+
};
|
|
169
|
+
//# sourceMappingURL=chunk-IHTWQEDR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/reduction/index.ts"],"sourcesContent":["/**\n * Reduction primitives (roadmap §8.1).\n *\n * Composable building blocks for taking heterogeneous massive inputs and producing\n * prioritized, auditable, human-actionable output. Each primitive is either a Graph\n * factory or a Node factory, built on top of core + extra primitives.\n *\n * @module\n */\n\nimport {\n\tbatch,\n\tCOMPLETE,\n\tDATA,\n\tERROR,\n\ttype Message,\n\ttype Node,\n\ttype NodeOptions,\n\tnode,\n} from \"@graphrefly/pure-ts/core\";\n\nimport { merge } from \"@graphrefly/pure-ts/extra\";\nimport { Graph, type GraphOptions } from \"@graphrefly/pure-ts/graph\";\n\n// ---------------------------------------------------------------------------\n// Shared helpers (same pattern as orchestration.ts)\n// ---------------------------------------------------------------------------\n\nexport type { StepRef } from \"../orchestration/pipeline-graph.js\";\n\nimport { keepalive } from \"@graphrefly/pure-ts/extra\";\nimport { domainMeta } from \"../../base/meta/domain-meta.js\";\nimport { tryIncrementBounded } from \"../../base/mutation/index.js\";\nimport type { StepRef } from \"../orchestration/pipeline-graph.js\";\n\nfunction baseMeta(kind: string, meta?: Record<string, unknown>): Record<string, unknown> {\n\treturn domainMeta(\"reduction\", kind, meta);\n}\n\n// stratify moved to `src/extra/stratify.ts` (protocol-level primitive).\n\n// ---------------------------------------------------------------------------\n// funnel\n// ---------------------------------------------------------------------------\n\n/** A named stage for {@link funnel}. */\nexport type FunnelStage = {\n\t/** Stage name (mounted as subgraph). */\n\tname: string;\n\t/** Builder: receives a sub-graph, should add an `\"input\"` and `\"output\"` node. */\n\tbuild: (sub: Graph) => void;\n};\n\n/** Options for {@link funnel}. */\nexport type FunnelOptions = GraphOptions & {\n\tmeta?: Record<string, unknown>;\n};\n\n/**\n * Multi-source merge with sequential reduction stages.\n *\n * Sources are merged into a single stream. Each stage is a named subgraph\n * (mounted via `graph.mount()`). Stages connect linearly:\n * `merged → stage[0].input → stage[0].output → stage[1].input → ...`\n *\n * @param name - Graph name.\n * @param sources - Input nodes to merge.\n * @param stages - Sequential reduction stages.\n * @param opts - Optional graph/meta options.\n * @returns Graph with `\"merged\"` and mounted stage subgraphs.\n *\n * @category patterns\n */\nexport function funnel<T>(\n\tname: string,\n\tsources: ReadonlyArray<Node<T>>,\n\tstages: ReadonlyArray<FunnelStage>,\n\topts?: FunnelOptions,\n): Graph {\n\tif (sources.length === 0) throw new RangeError(\"funnel requires at least one source\");\n\tif (stages.length === 0) throw new RangeError(\"funnel requires at least one stage\");\n\n\tconst g = new Graph(name, opts);\n\n\t// Merge all sources\n\tconst merged = sources.length === 1 ? sources[0] : merge(...(sources as unknown as Node<T>[]));\n\tg.add(merged as Node<unknown>, { name: \"merged\" });\n\n\t// Build and mount each stage linearly.\n\t// Stage inputs are standalone state nodes, so we bridge via subscribe\n\t// (connect() requires constructor deps). Bridge effects forward DATA\n\t// from the previous output to the next stage's input.\n\tlet prevOutputPath = \"merged\";\n\tfor (let i = 0; i < stages.length; i++) {\n\t\tconst stage = stages[i];\n\t\tconst sub = new Graph(stage.name);\n\t\tstage.build(sub);\n\n\t\t// Validate that the stage has input and output nodes\n\t\ttry {\n\t\t\tsub.resolve(\"input\");\n\t\t} catch {\n\t\t\tthrow new Error(`funnel stage \"${stage.name}\" must define an \"input\" node`);\n\t\t}\n\t\ttry {\n\t\t\tsub.resolve(\"output\");\n\t\t} catch {\n\t\t\tthrow new Error(`funnel stage \"${stage.name}\" must define an \"output\" node`);\n\t\t}\n\n\t\tg.mount(stage.name, sub);\n\n\t\t// Bridge replacement: effect that forwards DATA from previous output\n\t\t// to the next stage's input. TEARDOWN excluded because stage lifecycle\n\t\t// is managed by the parent graph. Shows up in describe().\n\t\tconst prevNode = g.resolve(prevOutputPath);\n\t\tconst stageInputPath = `${stage.name}::input`;\n\t\tconst stageInput = g.resolve(stageInputPath);\n\t\tconst bridgeName = `__bridge_${prevOutputPath}→${stage.name}_input`;\n\t\tconst br = node(\n\t\t\t[prevNode],\n\t\t\t(batchData, _actions, ctx) => {\n\t\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\tstageInput.emit(data[0]);\n\t\t\t\treturn undefined;\n\t\t\t},\n\t\t\t{ describeKind: \"effect\", name: bridgeName },\n\t\t);\n\t\tg.add(br as Node<unknown>, { name: bridgeName });\n\t\tg.addDisposer(keepalive(br));\n\n\t\tprevOutputPath = `${stage.name}::output`;\n\t}\n\n\treturn g;\n}\n\n// ---------------------------------------------------------------------------\n// feedback\n// ---------------------------------------------------------------------------\n\n/** Options for {@link feedback}. */\nexport type FeedbackOptions = {\n\t/** Maximum feedback iterations before stopping (default: 10). */\n\tmaxIterations?: number;\n\t/** Optional budget gate node path for cost-bounded iteration. */\n\tbudgetNode?: StepRef;\n\tmeta?: Record<string, unknown>;\n};\n\n/**\n * Introduce a bounded reactive cycle into an existing graph.\n *\n * When `condition` emits a non-null DATA value, the feedback effect routes it\n * back to the `reentry` state node — creating a cycle. Bounded by\n * `maxIterations` (default 10). The counter node (`__feedback_<condition>`)\n * is the source of truth — reset it to 0 to allow more iterations.\n *\n * To remove the feedback cycle, call `graph.remove(\"__feedback_<condition>\")`.\n *\n * @param graph - Existing graph to augment with a feedback cycle.\n * @param condition - Path to a node whose DATA triggers feedback.\n * @param reentry - Path to a state node that receives the feedback value.\n * @param opts - Iteration bounds and metadata.\n * @returns The same graph (mutated with feedback nodes added).\n *\n * @category patterns\n */\nexport function feedback(\n\tgraph: Graph,\n\tcondition: string,\n\treentry: string,\n\topts?: FeedbackOptions,\n): Graph {\n\tconst maxIter = opts?.maxIterations ?? 10;\n\n\t// Internal counter node — source of truth for iteration bound.\n\t// Reset to 0 to allow more iterations.\n\tconst counterName = `__feedback_${condition}`;\n\tconst counter = node<number>([], {\n\t\t...{\n\t\t\tmeta: baseMeta(\"feedback_counter\", {\n\t\t\t\tmaxIterations: maxIter,\n\t\t\t\tfeedbackFrom: condition,\n\t\t\t\tfeedbackTo: reentry,\n\t\t\t}),\n\t\t},\n\t\tinitial: 0,\n\t});\n\tgraph.add(counter as Node<unknown>, { name: counterName });\n\n\t// Resolve the condition and reentry nodes\n\tconst condNode = graph.resolve(condition);\n\tconst reentryNode = graph.resolve(reentry);\n\n\t// Graph-visible feedback effect: intercepts condition DATA, routes back to\n\t// reentry with iteration counting. Registered in the graph so it shows up\n\t// in describe() and cleans up on graph.destroy().\n\t// Feedback effect: subscribe to condition node for per-message interception\n\t// (onMessage removed in v5 — use producer+subscribe instead)\n\tconst feedbackEffectName = `__feedback_effect_${condition}`;\n\tconst feedbackEffect = node(\n\t\t[],\n\t\t(_data, _feedbackActions) => {\n\t\t\tconst unsub = condNode.subscribe((msgs) => {\n\t\t\t\tfor (const msg of msgs) {\n\t\t\t\t\tconst t = msg[0];\n\t\t\t\t\tif (t === DATA) {\n\t\t\t\t\t\tconst condValue = msg[1];\n\t\t\t\t\t\tif (condValue == null) return;\n\t\t\t\t\t\tbatch(() => {\n\t\t\t\t\t\t\tif (tryIncrementBounded(counter, maxIter)) {\n\t\t\t\t\t\t\t\treentryNode.emit(condValue);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t} else if (t === COMPLETE || t === ERROR) {\n\t\t\t\t\t\tconst terminal: Message = t === ERROR && msg.length > 1 ? [ERROR, msg[1]] : [t];\n\t\t\t\t\t\tcounter.down([terminal]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn () => unsub();\n\t\t},\n\t\t{\n\t\t\tname: feedbackEffectName,\n\t\t\tdescribeKind: \"effect\",\n\t\t\tmeta: {\n\t\t\t\t...baseMeta(\"feedback_effect\", {\n\t\t\t\t\tfeedbackFrom: condition,\n\t\t\t\t\tfeedbackTo: reentry,\n\t\t\t\t}),\n\t\t\t\t_internal: true,\n\t\t\t},\n\t\t},\n\t);\n\tgraph.add(feedbackEffect as Node<unknown>, { name: feedbackEffectName });\n\tgraph.addDisposer(keepalive(feedbackEffect));\n\n\treturn graph;\n}\n\n// `budgetGate` was promoted to `extra/resilience/budget-gate.ts` per Tier 2.2.\n// Import from `@graphrefly/graphrefly/extra` (or `../../extra/resilience/budget-gate.js`\n// internally) instead. See the resilience family for sibling primitives:\n// `retry`, `circuitBreaker`, `rateLimiter`, `tokenBucket`, `fallback`, `withStatus`.\n\n// ---------------------------------------------------------------------------\n// scorer\n// ---------------------------------------------------------------------------\n\n/** A scored item with full breakdown. */\nexport type ScoredItem<T = unknown> = {\n\t/** Original value. */\n\tvalue: T;\n\t/** Final weighted score. */\n\tscore: number;\n\t/** Per-signal breakdown: signal index → weighted contribution. */\n\tbreakdown: number[];\n};\n\n/** Options for {@link scorer}. */\nexport type ScorerOptions = Omit<NodeOptions<unknown>, \"describeKind\" | \"name\" | \"meta\"> & {\n\tmeta?: Record<string, unknown>;\n\t/** Custom scoring function per signal. Default: identity (signal value IS the score). */\n\tscoreFns?: ReadonlyArray<(value: unknown) => number>;\n};\n\n/**\n * Reactive multi-signal scoring with live weights.\n *\n * Each source emits items to score. Weights are reactive state nodes that\n * LLM or human can adjust live. Output is sorted scored items with full\n * breakdown.\n *\n * @param sources - Signal nodes (each emits a numeric score dimension).\n * @param weights - Reactive weight nodes (one per source).\n * @param opts - Optional node/meta options.\n * @returns Node emitting scored output.\n *\n * @category patterns\n */\nexport function scorer(\n\tsources: ReadonlyArray<Node<number>>,\n\tweights: ReadonlyArray<Node<number>>,\n\topts?: ScorerOptions,\n): Node<ScoredItem<number[]>> {\n\tif (sources.length === 0) throw new RangeError(\"scorer requires at least one source\");\n\tif (sources.length !== weights.length) {\n\t\tthrow new RangeError(\"scorer requires the same number of sources and weights\");\n\t}\n\n\tconst allDeps = [...(sources as unknown as Node[]), ...(weights as unknown as Node[])];\n\tconst n = sources.length;\n\tconst scoreFns = opts?.scoreFns;\n\n\treturn node<ScoredItem<number[]>>(\n\t\tallDeps,\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst vals = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst signals = vals.slice(0, n) as number[];\n\t\t\tconst weightValues = vals.slice(n) as number[];\n\n\t\t\tconst breakdown: number[] = [];\n\t\t\tlet totalScore = 0;\n\n\t\t\tfor (let i = 0; i < n; i++) {\n\t\t\t\tconst sig = signals[i] ?? 0;\n\t\t\t\tconst wt = weightValues[i] ?? 0;\n\t\t\t\tconst rawScore = scoreFns?.[i] ? scoreFns[i](sig) : sig;\n\t\t\t\tconst weighted = (rawScore as number) * wt;\n\t\t\t\tbreakdown.push(weighted);\n\t\t\t\ttotalScore += weighted;\n\t\t\t}\n\n\t\t\tactions.emit({\n\t\t\t\tvalue: signals,\n\t\t\t\tscore: totalScore,\n\t\t\t\tbreakdown,\n\t\t\t});\n\t\t},\n\t\t{\n\t\t\t...(opts\n\t\t\t\t? {\n\t\t\t\t\t\tequals: opts.equals,\n\t\t\t\t\t\tresubscribable: opts.resubscribable,\n\t\t\t\t\t\tresetOnTeardown: opts.resetOnTeardown,\n\t\t\t\t\t}\n\t\t\t\t: {}),\n\t\t\tdescribeKind: \"derived\",\n\t\t\tmeta: baseMeta(\"scorer\", opts?.meta),\n\t\t},\n\t);\n}\n\n// `effectivenessTracker` was deleted per Class B audit Alt E (2026-04-30).\n// The shared substrate now lives in `extra/composition/audited-success-tracker.ts`\n// — re-exported via `@graphrefly/graphrefly-ts/extra` for general use.\n"],"mappings":"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","names":["batch","i"]}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
// src/base/composition/external-register.ts
|
|
2
|
+
import {
|
|
3
|
+
batch,
|
|
4
|
+
COMPLETE,
|
|
5
|
+
DATA,
|
|
6
|
+
ERROR,
|
|
7
|
+
node
|
|
8
|
+
} from "@graphrefly/pure-ts/core";
|
|
9
|
+
function sourceOpts(opts) {
|
|
10
|
+
return { describeKind: "producer", ...opts };
|
|
11
|
+
}
|
|
12
|
+
function externalProducer(register, opts) {
|
|
13
|
+
return node((_data, a) => {
|
|
14
|
+
let active = true;
|
|
15
|
+
const triad = {
|
|
16
|
+
emit(value) {
|
|
17
|
+
if (!active) return;
|
|
18
|
+
a.emit(value);
|
|
19
|
+
},
|
|
20
|
+
error(err) {
|
|
21
|
+
if (!active) return;
|
|
22
|
+
active = false;
|
|
23
|
+
a.down([[ERROR, err]]);
|
|
24
|
+
},
|
|
25
|
+
complete() {
|
|
26
|
+
if (!active) return;
|
|
27
|
+
active = false;
|
|
28
|
+
a.down([[COMPLETE]]);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
let cleanup;
|
|
32
|
+
try {
|
|
33
|
+
const ret = register(triad);
|
|
34
|
+
cleanup = typeof ret === "function" ? ret : void 0;
|
|
35
|
+
} catch (err) {
|
|
36
|
+
triad.error(err);
|
|
37
|
+
return () => {
|
|
38
|
+
active = false;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
return () => {
|
|
42
|
+
active = false;
|
|
43
|
+
try {
|
|
44
|
+
cleanup?.();
|
|
45
|
+
} catch {
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
}, sourceOpts(opts));
|
|
49
|
+
}
|
|
50
|
+
function externalBundle(register, channels, opts) {
|
|
51
|
+
let active = true;
|
|
52
|
+
let cleanup;
|
|
53
|
+
let activatedCount = 0;
|
|
54
|
+
let teardownCount = 0;
|
|
55
|
+
const nodes = {};
|
|
56
|
+
const channelNodes = [];
|
|
57
|
+
const finishCleanup = () => {
|
|
58
|
+
const fn = cleanup;
|
|
59
|
+
cleanup = void 0;
|
|
60
|
+
try {
|
|
61
|
+
fn?.();
|
|
62
|
+
} catch {
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
for (const ch of channels) {
|
|
66
|
+
const name = opts?.name ? `${opts.name}::${ch}` : ch;
|
|
67
|
+
const chOpts = opts?.channelOpts?.[ch];
|
|
68
|
+
const n = node(
|
|
69
|
+
(_data, _a) => {
|
|
70
|
+
activatedCount++;
|
|
71
|
+
return () => {
|
|
72
|
+
teardownCount++;
|
|
73
|
+
if (activatedCount > 0 && teardownCount >= activatedCount && teardownCount >= channels.length) {
|
|
74
|
+
finishCleanup();
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
},
|
|
78
|
+
sourceOpts({ ...chOpts, name })
|
|
79
|
+
);
|
|
80
|
+
nodes[ch] = n;
|
|
81
|
+
channelNodes.push(n);
|
|
82
|
+
}
|
|
83
|
+
const bundle = {};
|
|
84
|
+
for (const ch of channels) {
|
|
85
|
+
bundle[ch] = (value) => {
|
|
86
|
+
if (!active) return;
|
|
87
|
+
nodes[ch].down([[DATA, value]]);
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
bundle.error = (err) => {
|
|
91
|
+
if (!active) return;
|
|
92
|
+
active = false;
|
|
93
|
+
batch(() => {
|
|
94
|
+
for (const n of channelNodes) n.down([[ERROR, err]]);
|
|
95
|
+
});
|
|
96
|
+
finishCleanup();
|
|
97
|
+
};
|
|
98
|
+
bundle.complete = () => {
|
|
99
|
+
if (!active) return;
|
|
100
|
+
active = false;
|
|
101
|
+
batch(() => {
|
|
102
|
+
for (const n of channelNodes) n.down([[COMPLETE]]);
|
|
103
|
+
});
|
|
104
|
+
finishCleanup();
|
|
105
|
+
};
|
|
106
|
+
const ret = register(bundle);
|
|
107
|
+
cleanup = typeof ret === "function" ? ret : void 0;
|
|
108
|
+
const dispose = () => {
|
|
109
|
+
if (!active) return;
|
|
110
|
+
active = false;
|
|
111
|
+
batch(() => {
|
|
112
|
+
for (const n of channelNodes) {
|
|
113
|
+
try {
|
|
114
|
+
n.down([[COMPLETE]]);
|
|
115
|
+
} catch {
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
finishCleanup();
|
|
120
|
+
};
|
|
121
|
+
return Object.assign(nodes, { dispose });
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export {
|
|
125
|
+
externalProducer,
|
|
126
|
+
externalBundle
|
|
127
|
+
};
|
|
128
|
+
//# sourceMappingURL=chunk-IJRR6YAI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/base/composition/external-register.ts"],"sourcesContent":["/**\n * External-register helpers — the common `register({emit, error, complete})`\n * contract shared by webhook, MCP, syslog, StatsD, OTel and other callback-\n * based integrations. Absorbs the `active` flag that every such adapter needs\n * to guard against emits after teardown (§5.10 boundary pattern).\n *\n * Two shapes:\n *\n * - {@link externalProducer} — single channel. Lazy activation: the register\n * fn runs when the node gains its first subscriber; its returned cleanup\n * runs on deactivation.\n *\n * - {@link externalBundle} — multiple named channels. Eager activation: the\n * register fn runs at bundle construction time so externally-owned servers\n * (HTTP endpoints, UDP sockets) start accepting traffic immediately. A\n * shared refcount fires the returned cleanup once every channel has fully\n * torn down.\n */\n\nimport {\n\tbatch,\n\tCOMPLETE,\n\tDATA,\n\tERROR,\n\ttype Node,\n\ttype NodeOptions,\n\tnode,\n} from \"@graphrefly/pure-ts/core\";\n\ntype ExtraOpts = Omit<NodeOptions<unknown>, \"describeKind\">;\n\nfunction sourceOpts<T>(opts?: ExtraOpts): NodeOptions<T> {\n\treturn { describeKind: \"producer\", ...opts } as NodeOptions<T>;\n}\n\n/**\n * Standard emit-triad passed to a single-channel external registrar.\n *\n * Post-teardown calls on any of these are automatically no-ops — the\n * registrar does not need its own guard flag.\n *\n * @category extra\n */\nexport type EmitTriad<T> = {\n\t/** Emit a value as `DATA`. */\n\temit: (value: T) => void;\n\t/** Terminate with `ERROR`. Subsequent `emit` / `error` / `complete` are ignored. */\n\terror: (err: unknown) => void;\n\t/** Terminate with `COMPLETE`. Subsequent `emit` / `error` / `complete` are ignored. */\n\tcomplete: () => void;\n};\n\n/**\n * Multi-channel emit bundle. Each declared channel name maps to an emit fn;\n * `error` and `complete` terminate every channel atomically.\n *\n * @category extra\n */\nexport type BundleTriad<TChannels extends Record<string, unknown>> = {\n\t[K in keyof TChannels]: (value: TChannels[K]) => void;\n} & {\n\t/** Terminate every channel with `ERROR`. */\n\terror: (err: unknown) => void;\n\t/** Terminate every channel with `COMPLETE`. */\n\tcomplete: () => void;\n};\n\n/**\n * Generic external registrator contract. The caller installs handlers into a\n * third-party library / framework / server and optionally returns a cleanup\n * callback. Returning `undefined` / `void` is equivalent to a no-op cleanup.\n *\n * @category extra\n */\nexport type ExternalRegister<H> = (handlers: H) => (() => void) | undefined;\n\n/**\n * Wraps a callback-style external integration as a reactive source.\n *\n * The registrar installs the supplied `emit` / `error` / `complete` handlers\n * into the external SDK; post-teardown calls are silently dropped. Synchronous\n * exceptions thrown by the registrar surface as terminal `ERROR`.\n *\n * @param register - Installs handlers. Optionally returns a cleanup fn.\n * @param opts - Node options (name, equals, resubscribable, ...).\n *\n * @example\n * ```ts\n * import { externalProducer } from \"@graphrefly/graphrefly-ts\";\n *\n * const hook$ = externalProducer<Payload>(({ emit, error }) => {\n * const id = transport.onMessage((raw) => {\n * try { emit(parse(raw)); } catch (e) { error(e); }\n * });\n * return () => transport.off(id);\n * });\n * ```\n *\n * @category extra\n */\nexport function externalProducer<T = unknown>(\n\tregister: ExternalRegister<EmitTriad<T>>,\n\topts?: ExtraOpts,\n): Node<T> {\n\treturn node<T>((_data, a) => {\n\t\tlet active = true;\n\t\tconst triad: EmitTriad<T> = {\n\t\t\temit(value) {\n\t\t\t\tif (!active) return;\n\t\t\t\ta.emit(value);\n\t\t\t},\n\t\t\terror(err) {\n\t\t\t\tif (!active) return;\n\t\t\t\tactive = false;\n\t\t\t\ta.down([[ERROR, err]]);\n\t\t\t},\n\t\t\tcomplete() {\n\t\t\t\tif (!active) return;\n\t\t\t\tactive = false;\n\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t},\n\t\t};\n\t\tlet cleanup: (() => void) | undefined;\n\t\ttry {\n\t\t\tconst ret = register(triad);\n\t\t\tcleanup = typeof ret === \"function\" ? ret : undefined;\n\t\t} catch (err) {\n\t\t\ttriad.error(err);\n\t\t\treturn () => {\n\t\t\t\tactive = false;\n\t\t\t};\n\t\t}\n\t\treturn () => {\n\t\t\tactive = false;\n\t\t\ttry {\n\t\t\t\tcleanup?.();\n\t\t\t} catch {\n\t\t\t\t/* registrar cleanup failure is not a reactive signal */\n\t\t\t}\n\t\t};\n\t}, sourceOpts(opts));\n}\n\n/**\n * Options for {@link externalBundle}.\n *\n * @category extra\n */\nexport type ExternalBundleOptions<TChannels extends Record<string, unknown>> = {\n\t/** Base name prefix for channel nodes; each node is named `${name}::${channel}`. */\n\tname?: string;\n\t/** Per-channel node options (equals, resubscribable, ...). */\n\tchannelOpts?: { [K in keyof TChannels]?: ExtraOpts };\n};\n\n/**\n * Multi-channel variant — one `Node<T>` per named channel, sharing a single\n * registrar. Activation is eager: the registrar runs at construction time so\n * externally-owned servers (HTTP, UDP, queue consumers) can start accepting\n * traffic immediately. The returned cleanup fires once every channel has been\n * subscribed and then fully deactivated (refcount-on-teardown).\n *\n * Any call to `error` or `complete` propagates to every channel atomically.\n *\n * @param register - Installs handlers for each channel plus shared error/complete.\n * @param channels - Ordered channel names; determines the returned object shape.\n * @param opts - Optional name prefix and per-channel node options.\n *\n * @example\n * ```ts\n * import { externalBundle } from \"@graphrefly/graphrefly-ts\";\n *\n * type OTelChannels = { traces: Span; metrics: Metric; logs: LogRec };\n * const otel = externalBundle<OTelChannels>(\n * ({ traces, metrics, logs, error }) => {\n * app.post(\"/v1/traces\", (req, res) => { traces(req.body); res.sendStatus(200); });\n * app.post(\"/v1/metrics\", (req, res) => { metrics(req.body); res.sendStatus(200); });\n * app.post(\"/v1/logs\", (req, res) => { logs(req.body); res.sendStatus(200); });\n * server.on(\"error\", error);\n * return () => server.close();\n * },\n * [\"traces\", \"metrics\", \"logs\"],\n * );\n * otel.traces.subscribe(...);\n * ```\n *\n * @category extra\n */\nexport function externalBundle<TChannels extends Record<string, unknown>>(\n\tregister: ExternalRegister<BundleTriad<TChannels>>,\n\tchannels: readonly (keyof TChannels & string)[],\n\topts?: ExternalBundleOptions<TChannels>,\n): { [K in keyof TChannels]: Node<TChannels[K]> } & { dispose(): void } {\n\tlet active = true;\n\tlet cleanup: (() => void) | undefined;\n\tlet activatedCount = 0;\n\tlet teardownCount = 0;\n\n\tconst nodes = {} as { [K in keyof TChannels]: Node<TChannels[K]> };\n\tconst channelNodes: Array<Node<unknown>> = [];\n\n\tconst finishCleanup = () => {\n\t\tconst fn = cleanup;\n\t\tcleanup = undefined;\n\t\ttry {\n\t\t\tfn?.();\n\t\t} catch {\n\t\t\t/* registrar cleanup failure is not a reactive signal */\n\t\t}\n\t};\n\n\tfor (const ch of channels) {\n\t\tconst name = opts?.name ? `${opts.name}::${ch}` : ch;\n\t\tconst chOpts = opts?.channelOpts?.[ch];\n\t\tconst n = node<TChannels[typeof ch]>(\n\t\t\t(_data, _a) => {\n\t\t\t\tactivatedCount++;\n\t\t\t\treturn () => {\n\t\t\t\t\tteardownCount++;\n\t\t\t\t\t// Cleanup fires once every channel has activated at least once\n\t\t\t\t\t// and then deactivated. Channels that never subscribe do not\n\t\t\t\t\t// gate cleanup — use the explicit `.dispose()` method for\n\t\t\t\t\t// unconditional teardown.\n\t\t\t\t\tif (\n\t\t\t\t\t\tactivatedCount > 0 &&\n\t\t\t\t\t\tteardownCount >= activatedCount &&\n\t\t\t\t\t\tteardownCount >= channels.length\n\t\t\t\t\t) {\n\t\t\t\t\t\tfinishCleanup();\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t},\n\t\t\tsourceOpts({ ...chOpts, name }),\n\t\t);\n\t\tnodes[ch as keyof TChannels] = n as Node<TChannels[typeof ch]>;\n\t\tchannelNodes.push(n as Node<unknown>);\n\t}\n\n\tconst bundle = {} as BundleTriad<TChannels>;\n\tfor (const ch of channels) {\n\t\t(bundle as Record<string, unknown>)[ch] = (value: unknown) => {\n\t\t\tif (!active) return;\n\t\t\t(nodes[ch as keyof TChannels] as Node<unknown>).down([[DATA, value]]);\n\t\t};\n\t}\n\tbundle.error = (err: unknown) => {\n\t\tif (!active) return;\n\t\tactive = false;\n\t\tbatch(() => {\n\t\t\tfor (const n of channelNodes) n.down([[ERROR, err]]);\n\t\t});\n\t\tfinishCleanup();\n\t};\n\tbundle.complete = () => {\n\t\tif (!active) return;\n\t\tactive = false;\n\t\tbatch(() => {\n\t\t\tfor (const n of channelNodes) n.down([[COMPLETE]]);\n\t\t});\n\t\tfinishCleanup();\n\t};\n\n\t// Eager activation — register fires at construction time so externally-\n\t// owned servers can start accepting traffic immediately. Synchronous throws\n\t// propagate to the caller (no subscribers exist yet, so there is no\n\t// reactive ERROR path to deliver to). This matches the existing `fromOTel`\n\t// contract.\n\tconst ret = register(bundle);\n\tcleanup = typeof ret === \"function\" ? ret : undefined;\n\n\tconst dispose = () => {\n\t\tif (!active) return;\n\t\tactive = false;\n\t\t// Fire COMPLETE on every channel so downstream sees a clean terminal.\n\t\tbatch(() => {\n\t\t\tfor (const n of channelNodes) {\n\t\t\t\ttry {\n\t\t\t\t\tn.down([[COMPLETE]]);\n\t\t\t\t} catch {\n\t\t\t\t\t/* terminal filter / re-entrance — swallow */\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tfinishCleanup();\n\t};\n\n\treturn Object.assign(nodes, { dispose });\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import {
|
|
2
|
+
policyGate
|
|
3
|
+
} from "./chunk-FW23JYNQ.js";
|
|
4
|
+
import {
|
|
5
|
+
TopicGraph
|
|
6
|
+
} from "./chunk-Q3EYOCZB.js";
|
|
7
|
+
import {
|
|
8
|
+
domainMeta
|
|
9
|
+
} from "./chunk-FMPF42Q4.js";
|
|
10
|
+
|
|
11
|
+
// src/presets/inspect/guarded-execution.ts
|
|
12
|
+
import { DATA, monotonicNs, node } from "@graphrefly/pure-ts/core";
|
|
13
|
+
import { keepalive } from "@graphrefly/pure-ts/extra";
|
|
14
|
+
import {
|
|
15
|
+
Graph
|
|
16
|
+
} from "@graphrefly/pure-ts/graph";
|
|
17
|
+
function isNode(x) {
|
|
18
|
+
return typeof x === "object" && x !== null && "subscribe" in x && "down" in x;
|
|
19
|
+
}
|
|
20
|
+
function guardedMeta(kind) {
|
|
21
|
+
return domainMeta("guarded", kind);
|
|
22
|
+
}
|
|
23
|
+
var GuardedExecutionGraph = class extends Graph {
|
|
24
|
+
enforcer;
|
|
25
|
+
violations;
|
|
26
|
+
lints;
|
|
27
|
+
scope;
|
|
28
|
+
/**
|
|
29
|
+
* Canonical reactive describe scoped to the wrapper's configured `actor`.
|
|
30
|
+
* Subscribes ONCE at construction; lifecycle owned by the wrapper (disposed
|
|
31
|
+
* on `wrapper.destroy()`). Use this property for the common case
|
|
32
|
+
* (long-lived consumer wanting "describe scoped to my actor"); use
|
|
33
|
+
* {@link scopedDescribeNode} only when a per-call actor override or
|
|
34
|
+
* different `detail`/`fields` is required.
|
|
35
|
+
*
|
|
36
|
+
* Re-derives on every settle of the target graph: structural changes,
|
|
37
|
+
* status transitions (errors flip nodes into `"errored"`), and actor
|
|
38
|
+
* emissions (when a `Node<Actor>` is bound, including the SENTINEL bridge
|
|
39
|
+
* applied internally — see qa G1B).
|
|
40
|
+
*/
|
|
41
|
+
scopedDescribe;
|
|
42
|
+
_target;
|
|
43
|
+
_actorNode;
|
|
44
|
+
_mode;
|
|
45
|
+
_firedLintKinds = /* @__PURE__ */ new Set();
|
|
46
|
+
constructor(target, opts) {
|
|
47
|
+
super(opts.name ?? `${target.name}_guarded`, opts.graph);
|
|
48
|
+
this._target = target;
|
|
49
|
+
this._mode = opts.mode ?? "enforce";
|
|
50
|
+
const policiesOpt = opts.policies;
|
|
51
|
+
const policiesIsNode = isNode(policiesOpt);
|
|
52
|
+
if (!policiesIsNode && this._mode === "enforce" && policiesOpt.length === 0) {
|
|
53
|
+
throw new RangeError(
|
|
54
|
+
'guardedExecution: empty `policies` in `mode: "enforce"` denies every action. Pass at least `{ effect: "allow", action: "*" }` and layer deny rules on top.'
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
this.lints = new TopicGraph("lints", {
|
|
58
|
+
retainedLimit: opts.lintsLimit ?? 64
|
|
59
|
+
});
|
|
60
|
+
this.mount("lints", this.lints);
|
|
61
|
+
const actorOpt = opts.actor;
|
|
62
|
+
if (actorOpt == null) {
|
|
63
|
+
this._actorNode = node([], { name: "actor", initial: null });
|
|
64
|
+
} else if (isNode(actorOpt)) {
|
|
65
|
+
this._actorNode = node(
|
|
66
|
+
[actorOpt],
|
|
67
|
+
(batchData, actions, ctx) => {
|
|
68
|
+
const data = batchData.map(
|
|
69
|
+
(batch, i) => batch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i]
|
|
70
|
+
);
|
|
71
|
+
actions.emit(data[0] ?? null);
|
|
72
|
+
},
|
|
73
|
+
{ describeKind: "derived", name: "actor", initial: null }
|
|
74
|
+
);
|
|
75
|
+
} else {
|
|
76
|
+
this._actorNode = node([], { name: "actor", initial: actorOpt });
|
|
77
|
+
}
|
|
78
|
+
const enforcerOpts = {
|
|
79
|
+
mode: this._mode,
|
|
80
|
+
name: "enforcer"
|
|
81
|
+
};
|
|
82
|
+
if (opts.violationsLimit != null) enforcerOpts.violationsLimit = opts.violationsLimit;
|
|
83
|
+
this.enforcer = policyGate(target, opts.policies, enforcerOpts);
|
|
84
|
+
this.violations = this.enforcer.violations;
|
|
85
|
+
this.mount("enforcer", this.enforcer);
|
|
86
|
+
if (policiesIsNode && this._mode === "enforce") {
|
|
87
|
+
const policiesNode = policiesOpt;
|
|
88
|
+
const cached = policiesNode.cache;
|
|
89
|
+
if (cached != null && cached.length === 0) {
|
|
90
|
+
this._fireLint(
|
|
91
|
+
"empty-policies",
|
|
92
|
+
'`policies` Node cached an empty array in `mode: "enforce"` \u2014 every action will be denied. Add at least one allow rule.'
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
const offEmpty = policiesNode.subscribe((msgs) => {
|
|
96
|
+
for (const m of msgs) {
|
|
97
|
+
if (m[0] !== DATA) continue;
|
|
98
|
+
const v = m[1];
|
|
99
|
+
if (v == null || v.length === 0) {
|
|
100
|
+
this._fireLint(
|
|
101
|
+
"empty-policies",
|
|
102
|
+
'`policies` Node emitted an empty array in `mode: "enforce"` \u2014 every action will be denied. Add at least one allow rule.'
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
this.addDisposer(offEmpty);
|
|
108
|
+
}
|
|
109
|
+
if (this._mode === "audit") {
|
|
110
|
+
const described = target.describe({ detail: "full" });
|
|
111
|
+
const anyGuard = Object.values(described.nodes).some((n) => n.guard != null);
|
|
112
|
+
if (!anyGuard) {
|
|
113
|
+
this._fireLint(
|
|
114
|
+
"audit-no-effect",
|
|
115
|
+
'`mode: "audit"` + target has no per-node guards \u2014 `scopedDescribeNode` filters by per-node guards only, so policy rules will not affect describe() visibility. Policies still populate the `violations` topic on writes.'
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (actorOpt == null) {
|
|
120
|
+
this._fireLint(
|
|
121
|
+
"no-actor",
|
|
122
|
+
"no actor configured \u2014 `wrapper.scopedDescribe` and `scopedDescribeNode()` will return an unscoped describe (full visibility) unless a per-call actor is supplied."
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
this.scope = node(
|
|
126
|
+
[this._actorNode, this.enforcer.policies],
|
|
127
|
+
(batchData, actions, ctx) => {
|
|
128
|
+
const data = batchData.map(
|
|
129
|
+
(batch, i) => batch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i]
|
|
130
|
+
);
|
|
131
|
+
actions.emit({
|
|
132
|
+
actor: data[0] ?? null,
|
|
133
|
+
mode: this._mode,
|
|
134
|
+
policiesCount: data[1].length
|
|
135
|
+
});
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
name: "scope",
|
|
139
|
+
describeKind: "derived",
|
|
140
|
+
meta: guardedMeta("scope")
|
|
141
|
+
}
|
|
142
|
+
);
|
|
143
|
+
this.add(this.scope, { name: "scope" });
|
|
144
|
+
this.addDisposer(keepalive(this.scope));
|
|
145
|
+
const scopedHandle = target.describe({
|
|
146
|
+
reactive: true,
|
|
147
|
+
// F8 (Tier 5.2): `_actorNode` is `Node<Actor | null>`. The cast is
|
|
148
|
+
// safe at runtime per the `resolveActorOption` null-tolerance
|
|
149
|
+
// contract — `null` / `undefined` cache is treated as "no scoping"
|
|
150
|
+
// (full visibility). See `scopedDescribeNode` for the matching
|
|
151
|
+
// per-call site and graph.ts § "Cache-undefined semantics".
|
|
152
|
+
actor: this._actorNode,
|
|
153
|
+
reactiveName: "scopedDescribe"
|
|
154
|
+
});
|
|
155
|
+
this.scopedDescribe = scopedHandle.node;
|
|
156
|
+
this.add(this.scopedDescribe, { name: "scopedDescribe" });
|
|
157
|
+
this.addDisposer(scopedHandle.dispose);
|
|
158
|
+
}
|
|
159
|
+
_fireLint(kind, message) {
|
|
160
|
+
if (this._firedLintKinds.has(kind)) return;
|
|
161
|
+
this._firedLintKinds.add(kind);
|
|
162
|
+
this.lints.publish({ kind, message, timestamp_ns: monotonicNs() });
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* **Per-call escape hatch.** Prefer {@link scopedDescribe} (the mounted
|
|
166
|
+
* property) for the common case of "describe scoped to my actor." Use
|
|
167
|
+
* this method ONLY when you need a per-call actor override or different
|
|
168
|
+
* `detail`/`fields`/`filter`.
|
|
169
|
+
*
|
|
170
|
+
* Returns a live `Node<GraphDescribeOutput>` scoped to the supplied (or
|
|
171
|
+
* configured) actor, plus an explicit `dispose` for caller-controlled
|
|
172
|
+
* lifecycle. Re-derives on every settle of the target graph: structural
|
|
173
|
+
* changes, status transitions, and actor emissions (when a `Node<Actor>`
|
|
174
|
+
* is bound).
|
|
175
|
+
*
|
|
176
|
+
* **Lifecycle (qa G1A — EC1 fix).** Each call instantiates a fresh
|
|
177
|
+
* `target.describe({reactive: true})` handle (with its own version state,
|
|
178
|
+
* observe handle, transitive topology subscriptions, derived + keepalive).
|
|
179
|
+
* The caller MUST invoke the returned `dispose()` when finished to release
|
|
180
|
+
* these resources. Disposers ARE also tracked on the wrapper graph so
|
|
181
|
+
* `wrapper.destroy()` cleans up any handles the caller forgot — but a
|
|
182
|
+
* long-lived wrapper with heavy per-call usage will leak until destroy
|
|
183
|
+
* unless `dispose()` is called explicitly.
|
|
184
|
+
*
|
|
185
|
+
* @param actorOverride - Optional per-call override. Static {@link Actor}
|
|
186
|
+
* or `Node<Actor>`. Omit to use the wrapper-configured default.
|
|
187
|
+
* @param opts - Standard {@link GraphDescribeOptions} fields (`detail`,
|
|
188
|
+
* `fields`, `filter`). `actor` / `reactive` / `reactiveName` are
|
|
189
|
+
* controlled by the wrapper.
|
|
190
|
+
* @returns `{node, dispose}` — `node` is the live describe Node; `dispose`
|
|
191
|
+
* tears down the underlying reactive describe subscription idempotently.
|
|
192
|
+
*/
|
|
193
|
+
scopedDescribeNode(actorOverride, opts) {
|
|
194
|
+
const actorNode = actorOverride == null ? this._actorNode : isNode(actorOverride) ? actorOverride : node([], { name: "actor_override", initial: actorOverride });
|
|
195
|
+
const handle = this._target.describe({
|
|
196
|
+
reactive: true,
|
|
197
|
+
// `_actorNode` is `Node<Actor | null>`. The `as Node<Actor>` cast is
|
|
198
|
+
// safe at runtime: `_describeReactive` resolves the actor via
|
|
199
|
+
// `resolveActorOption`, which treats `null`/`undefined` cache as
|
|
200
|
+
// "no scoping" (full visibility). Documented in graph.ts §
|
|
201
|
+
// "Cache-undefined semantics."
|
|
202
|
+
actor: actorNode,
|
|
203
|
+
...opts ?? {}
|
|
204
|
+
});
|
|
205
|
+
this.addDisposer(handle.dispose);
|
|
206
|
+
return { node: handle.node, dispose: handle.dispose };
|
|
207
|
+
}
|
|
208
|
+
/** The wrapped graph (escape hatch for tooling). */
|
|
209
|
+
get target() {
|
|
210
|
+
return this._target;
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
function guardedExecution(target, opts) {
|
|
214
|
+
return new GuardedExecutionGraph(target, opts);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export {
|
|
218
|
+
GuardedExecutionGraph,
|
|
219
|
+
guardedExecution
|
|
220
|
+
};
|
|
221
|
+
//# sourceMappingURL=chunk-JGFRAFDL.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/presets/inspect/guarded-execution.ts"],"sourcesContent":["/**\n * Composable safety layer (roadmap §9.0b — Tier 5.1 Wave-B rebuild).\n *\n * {@link guardedExecution} wraps any {@link Graph} with:\n *\n * - {@link policyGate} — reactive ABAC (Tier 2.3 rename of `policyEnforcer`),\n * policies stored as a `Node` so LLMs / humans can update them at runtime.\n * Full transitive dynamic coverage via `watchTopologyTree`.\n * - Reactive {@link GuardedExecutionGraph.scopedDescribeNode} — a thin\n * delegate over `target.describe({ reactive: true, actor })` that re-derives\n * on every settle (topology change, error transition, actor swap).\n * - The enforcer's `violations` topic is republished as `violations` on\n * the wrapper, composable with {@link graphLens}'s `health`.\n * - The wrapper-level `lints` topic surfaces non-policy diagnostic warnings\n * (`empty-policies` / `audit-no-effect` / `no-actor`) so misconfigurations\n * are caught reactively rather than via thrown errors at scattered call sites.\n * - The `scope` derived publishes the current configuration tuple\n * (`{actor, mode, policiesCount}`) for dashboards.\n *\n * V1 scope: policies + actor + reactive scoped describe + lints + scope.\n * Budget-as-option is NOT in V1 — it requires a cost-tracking design that\n * hasn't landed yet. Callers who need a budget limit today append a\n * budget-aware {@link PolicyRuleData} to the policies list (check current\n * cost and `deny` when exhausted).\n *\n * @module\n */\nimport type { Actor, PolicyRuleData } from \"@graphrefly/pure-ts/core\";\nimport { DATA, monotonicNs, type Node, node } from \"@graphrefly/pure-ts/core\";\nimport { keepalive } from \"@graphrefly/pure-ts/extra\";\nimport {\n\ttype DescribeFilter,\n\tGraph,\n\ttype GraphDescribeOptions,\n\ttype GraphDescribeOutput,\n\ttype GraphOptions,\n} from \"@graphrefly/pure-ts/graph\";\nimport { domainMeta } from \"../../base/meta/domain-meta.js\";\nimport {\n\ttype PolicyGateGraph,\n\ttype PolicyViolation,\n\tpolicyGate,\n} from \"../../utils/inspect/audit.js\";\nimport { TopicGraph } from \"../../utils/messaging/index.js\";\n\nfunction isNode<T>(x: unknown): x is Node<T> {\n\treturn (\n\t\ttypeof x === \"object\" && x !== null && \"subscribe\" in (x as object) && \"down\" in (x as object)\n\t);\n}\n\nfunction guardedMeta(kind: string): Record<string, unknown> {\n\treturn domainMeta(\"guarded\", kind);\n}\n\n/** Diagnostic warning published on {@link GuardedExecutionGraph.lints}. */\nexport interface GuardedExecutionLint {\n\t/**\n\t * - `\"empty-policies\"` — `policies` Node emitted an empty array in\n\t * `mode: \"enforce\"`. Static empty arrays throw at construction; this\n\t * covers the reactive case.\n\t * - `\"audit-no-effect\"` — `mode: \"audit\"` plus the target has no per-node\n\t * guards, so `scopedDescribeNode` filters by per-node guards only and\n\t * policies will never gate visibility (they still populate `violations`\n\t * on writes).\n\t * - `\"no-actor\"` — neither a wrapper-configured nor per-call actor was\n\t * supplied. `scopedDescribeNode` falls back to \"describe everything\"\n\t * for the corresponding subscription.\n\t */\n\tkind: \"empty-policies\" | \"audit-no-effect\" | \"no-actor\";\n\tmessage: string;\n\ttimestamp_ns: number;\n}\n\n/** Configuration tuple published on {@link GuardedExecutionGraph.scope}. */\nexport interface GuardedScope {\n\t/** The wrapper-configured default actor, or `null` when none configured. */\n\tactor: Actor | null;\n\tmode: \"audit\" | \"enforce\";\n\t/** Current policy count (reactive — re-emits on `policies` Node updates). */\n\tpoliciesCount: number;\n}\n\n/** Options for {@link guardedExecution}. */\nexport interface GuardedExecutionOptions {\n\t/**\n\t * Policies enforced against every guarded write. Static list or a live\n\t * `Node<readonly PolicyRuleData[]>` (LLM-updatable).\n\t *\n\t * **Empty-policies handling:**\n\t * - Static empty array + `mode: \"enforce\"` throws `RangeError` at\n\t * construction (deny-by-default is almost certainly a misconfiguration).\n\t * - Node-supplied empty array + `mode: \"enforce\"` emits a one-time\n\t * `\"empty-policies\"` lint on first such emission (the wrapper can't\n\t * throw mid-run — surface the warning reactively).\n\t * - `mode: \"audit\"` tolerates empty policies (no guards stacked; policies\n\t * only feed the `violations` channel on writes).\n\t */\n\tpolicies: readonly PolicyRuleData[] | Node<readonly PolicyRuleData[]>;\n\t/**\n\t * Default actor used when the caller invokes\n\t * {@link GuardedExecutionGraph.scopedDescribeNode} without an override.\n\t * Accepts a static {@link Actor} or a `Node<Actor>` — when a Node is\n\t * supplied, the reactive describe re-derives on every actor emission so\n\t * harnesses binding a per-turn actor get a single live describe Node\n\t * instead of re-creating one per turn.\n\t *\n\t * Omit to scope per-call only. A `\"no-actor\"` lint fires once per instance\n\t * if neither a configured nor per-call actor is ever supplied (the\n\t * resulting describe is unscoped — full visibility).\n\t */\n\tactor?: Actor | Node<Actor>;\n\t/**\n\t * `\"enforce\"` (default) — push guards onto target nodes so disallowed\n\t * writes throw {@link GuardDenied}.\n\t * `\"audit\"` — record would-be denials to the `violations` topic without\n\t * blocking writes.\n\t */\n\tmode?: \"audit\" | \"enforce\";\n\t/** Ring-buffer cap for the `violations` topic. Default 1000 (inherited from policyGate). */\n\tviolationsLimit?: number;\n\t/** Ring-buffer cap for the `lints` topic. Default 64 — each lint kind fires at most once per instance. */\n\tlintsLimit?: number;\n\t/** Wrapper graph name. Default `${target.name}_guarded`. */\n\tname?: string;\n\t/** Wrapper graph options. */\n\tgraph?: GraphOptions;\n}\n\n/**\n * Wrapper over a target {@link Graph} providing reactive ABAC + reactive\n * scoped describe + diagnostic lints. Mounts a {@link PolicyGateGraph} under\n * `enforcer`, a {@link TopicGraph} of {@link GuardedExecutionLint} under\n * `lints`, and a `scope` derived publishing `{actor, mode, policiesCount}`.\n *\n * @category patterns\n */\nexport class GuardedExecutionGraph extends Graph {\n\treadonly enforcer: PolicyGateGraph;\n\treadonly violations: TopicGraph<PolicyViolation>;\n\treadonly lints: TopicGraph<GuardedExecutionLint>;\n\treadonly scope: Node<GuardedScope>;\n\t/**\n\t * Canonical reactive describe scoped to the wrapper's configured `actor`.\n\t * Subscribes ONCE at construction; lifecycle owned by the wrapper (disposed\n\t * on `wrapper.destroy()`). Use this property for the common case\n\t * (long-lived consumer wanting \"describe scoped to my actor\"); use\n\t * {@link scopedDescribeNode} only when a per-call actor override or\n\t * different `detail`/`fields` is required.\n\t *\n\t * Re-derives on every settle of the target graph: structural changes,\n\t * status transitions (errors flip nodes into `\"errored\"`), and actor\n\t * emissions (when a `Node<Actor>` is bound, including the SENTINEL bridge\n\t * applied internally — see qa G1B).\n\t */\n\treadonly scopedDescribe: Node<GraphDescribeOutput>;\n\tprivate readonly _target: Graph;\n\tprivate readonly _actorNode: Node<Actor | null>;\n\tprivate readonly _mode: \"audit\" | \"enforce\";\n\tprivate readonly _firedLintKinds = new Set<GuardedExecutionLint[\"kind\"]>();\n\n\tconstructor(target: Graph, opts: GuardedExecutionOptions) {\n\t\tsuper(opts.name ?? `${target.name}_guarded`, opts.graph);\n\t\tthis._target = target;\n\t\tthis._mode = opts.mode ?? \"enforce\";\n\n\t\tconst policiesOpt = opts.policies;\n\t\tconst policiesIsNode = isNode<readonly PolicyRuleData[]>(policiesOpt);\n\t\t// Static empty + enforce → throw (deny-by-default = misconfig).\n\t\tif (\n\t\t\t!policiesIsNode &&\n\t\t\tthis._mode === \"enforce\" &&\n\t\t\t(policiesOpt as readonly PolicyRuleData[]).length === 0\n\t\t) {\n\t\t\tthrow new RangeError(\n\t\t\t\t'guardedExecution: empty `policies` in `mode: \"enforce\"` denies every action. ' +\n\t\t\t\t\t'Pass at least `{ effect: \"allow\", action: \"*\" }` and layer deny rules on top.',\n\t\t\t);\n\t\t}\n\n\t\t// Lints topic — mounted before any potential first-DATA emission.\n\t\tthis.lints = new TopicGraph<GuardedExecutionLint>(\"lints\", {\n\t\t\tretainedLimit: opts.lintsLimit ?? 64,\n\t\t});\n\t\tthis.mount(\"lints\", this.lints);\n\n\t\t// Normalize `actor` to a Node<Actor | null>. `null` (a valid DATA in\n\t\t// the v5 sentinel-as-undefined model) means \"no actor configured\" —\n\t\t// `target.describe({ reactive: true })`'s `resolveActorOption` treats\n\t\t// `null` cache as \"no scoping\" (full visibility), and the `scope`\n\t\t// derived can publish `actor: null` cleanly. Using `node([], { initial: undefined })`\n\t\t// here would leave the actor node in sentinel state, which never fires\n\t\t// DATA on subscribe and would block the `scope` derived's first-run\n\t\t// gate from completing.\n\t\t//\n\t\t// qa G1B (EC2 fix): when the caller passes a `Node<Actor>`, that node's\n\t\t// cache may itself be SENTINEL at construction (e.g. a `producer`\n\t\t// awaiting first emission, or a deferred `derived`). Forwarding the raw\n\t\t// Node would re-introduce the same sentinel-stall on `scope`. Bridge\n\t\t// through a node bridge with a `null` initial so the\n\t\t// internal `_actorNode` always carries non-sentinel cache; the bridge\n\t\t// re-emits whenever the caller's Node emits, and forwards `null`\n\t\t// through unchanged.\n\t\tconst actorOpt = opts.actor;\n\t\tif (actorOpt == null) {\n\t\t\tthis._actorNode = node<Actor | null>([], { name: \"actor\", initial: null });\n\t\t} else if (isNode<Actor>(actorOpt)) {\n\t\t\tthis._actorNode = node<Actor | null>(\n\t\t\t\t[actorOpt],\n\t\t\t\t(batchData, actions, ctx) => {\n\t\t\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t\t);\n\t\t\t\t\tactions.emit((data[0] as Actor | null | undefined) ?? null);\n\t\t\t\t},\n\t\t\t\t{ describeKind: \"derived\", name: \"actor\", initial: null },\n\t\t\t);\n\t\t} else {\n\t\t\tthis._actorNode = node<Actor | null>([], { name: \"actor\", initial: actorOpt });\n\t\t}\n\n\t\t// Mount the enforcer.\n\t\tconst enforcerOpts: { mode: \"audit\" | \"enforce\"; name: string; violationsLimit?: number } = {\n\t\t\tmode: this._mode,\n\t\t\tname: \"enforcer\",\n\t\t};\n\t\tif (opts.violationsLimit != null) enforcerOpts.violationsLimit = opts.violationsLimit;\n\t\tthis.enforcer = policyGate(target, opts.policies, enforcerOpts);\n\t\tthis.violations = this.enforcer.violations;\n\t\tthis.mount(\"enforcer\", this.enforcer);\n\n\t\t// Empty-policies one-time lint (Node form, enforce mode only).\n\t\tif (policiesIsNode && this._mode === \"enforce\") {\n\t\t\tconst policiesNode = policiesOpt as Node<readonly PolicyRuleData[]>;\n\t\t\t// Two paths here intentionally:\n\t\t\t// (1) Synchronous cache seed — fires immediately if the Node was\n\t\t\t// constructed with an empty array as its current cache. This\n\t\t\t// covers `node<…[]>([], { initial: [] })` and any pre-emitted derived.\n\t\t\t// (2) Subscribe path — catches subsequent empty emissions AND\n\t\t\t// handles the SENTINEL case (cache=undefined at construction)\n\t\t\t// where the Node fires its first DATA after the wrapper is\n\t\t\t// built. The `_firedLintKinds` Set keeps the lint one-shot\n\t\t\t// across both paths.\n\t\t\t// qa F6 (deferred): if a Node's initial cache is SENTINEL (undefined)\n\t\t\t// AND it never emits an empty array (only ever non-empty), the lint\n\t\t\t// never fires — that's correct behavior, the configuration is\n\t\t\t// effectively non-empty for the wrapper's lifetime.\n\t\t\tconst cached = policiesNode.cache as readonly PolicyRuleData[] | undefined;\n\t\t\tif (cached != null && cached.length === 0) {\n\t\t\t\tthis._fireLint(\n\t\t\t\t\t\"empty-policies\",\n\t\t\t\t\t'`policies` Node cached an empty array in `mode: \"enforce\"` — every action will be denied. Add at least one allow rule.',\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst offEmpty = policiesNode.subscribe((msgs) => {\n\t\t\t\tfor (const m of msgs) {\n\t\t\t\t\tif (m[0] !== DATA) continue;\n\t\t\t\t\tconst v = m[1] as readonly PolicyRuleData[] | undefined;\n\t\t\t\t\tif (v == null || v.length === 0) {\n\t\t\t\t\t\tthis._fireLint(\n\t\t\t\t\t\t\t\"empty-policies\",\n\t\t\t\t\t\t\t'`policies` Node emitted an empty array in `mode: \"enforce\"` — every action will be denied. Add at least one allow rule.',\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\tthis.addDisposer(offEmpty);\n\t\t}\n\n\t\t// Audit-mode + no per-node guards on the target → fire once.\n\t\t// qa EC5 (deferred): the check is one-shot at construction. If the\n\t\t// caller later mounts a guarded node into the target, the lint stays\n\t\t// retained even though the configuration is now effective. Recommended\n\t\t// pattern: mount per-node guards on the target BEFORE wrapping.\n\t\t// Reactive recompute (subscribe to target.topology, clear lint when a\n\t\t// guard appears) is filed in `docs/optimizations.md` as a follow-up.\n\t\tif (this._mode === \"audit\") {\n\t\t\tconst described = target.describe({ detail: \"full\" });\n\t\t\tconst anyGuard = Object.values(described.nodes).some((n) => n.guard != null);\n\t\t\tif (!anyGuard) {\n\t\t\t\tthis._fireLint(\n\t\t\t\t\t\"audit-no-effect\",\n\t\t\t\t\t'`mode: \"audit\"` + target has no per-node guards — `scopedDescribeNode` filters by per-node guards only, so policy rules will not affect describe() visibility. Policies still populate the `violations` topic on writes.',\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// No-actor lint: fires at construction when neither configured nor\n\t\t// implicitly carried via a Node-cache. Per-call overrides on\n\t\t// `scopedDescribeNode` cannot retroactively suppress this — the\n\t\t// configured-default branch is what callers most often miss.\n\t\tif (actorOpt == null) {\n\t\t\tthis._fireLint(\n\t\t\t\t\"no-actor\",\n\t\t\t\t\"no actor configured — `wrapper.scopedDescribe` and `scopedDescribeNode()` will return an unscoped describe (full visibility) unless a per-call actor is supplied.\",\n\t\t\t);\n\t\t}\n\n\t\t// Scope derived: live tuple of {actor, mode, policiesCount}.\n\t\tthis.scope = node<GuardedScope>(\n\t\t\t[this._actorNode, this.enforcer.policies],\n\t\t\t(batchData, actions, ctx) => {\n\t\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\tactions.emit({\n\t\t\t\t\tactor: (data[0] as Actor | null | undefined) ?? null,\n\t\t\t\t\tmode: this._mode,\n\t\t\t\t\tpoliciesCount: (data[1] as readonly PolicyRuleData[]).length,\n\t\t\t\t});\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"scope\",\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tmeta: guardedMeta(\"scope\"),\n\t\t\t},\n\t\t);\n\t\tthis.add(this.scope, { name: \"scope\" });\n\t\tthis.addDisposer(keepalive(this.scope));\n\n\t\t// qa G1A \"same concept\": single canonical reactive describe bound to\n\t\t// the configured actor, mounted once at construction. Removes the\n\t\t// per-call handle proliferation from the prior `scopedDescribeNode`\n\t\t// pattern (the method is retained as the per-call escape hatch). The\n\t\t// reactive describe re-derives on actor swap / topology change /\n\t\t// status transition; lifecycle owned by the wrapper.\n\t\tconst scopedHandle = target.describe({\n\t\t\treactive: true,\n\t\t\t// F8 (Tier 5.2): `_actorNode` is `Node<Actor | null>`. The cast is\n\t\t\t// safe at runtime per the `resolveActorOption` null-tolerance\n\t\t\t// contract — `null` / `undefined` cache is treated as \"no scoping\"\n\t\t\t// (full visibility). See `scopedDescribeNode` for the matching\n\t\t\t// per-call site and graph.ts § \"Cache-undefined semantics\".\n\t\t\tactor: this._actorNode as Node<Actor>,\n\t\t\treactiveName: \"scopedDescribe\",\n\t\t});\n\t\tthis.scopedDescribe = scopedHandle.node;\n\t\tthis.add(this.scopedDescribe, { name: \"scopedDescribe\" });\n\t\tthis.addDisposer(scopedHandle.dispose);\n\t}\n\n\tprivate _fireLint(kind: GuardedExecutionLint[\"kind\"], message: string): void {\n\t\tif (this._firedLintKinds.has(kind)) return;\n\t\tthis._firedLintKinds.add(kind);\n\t\tthis.lints.publish({ kind, message, timestamp_ns: monotonicNs() });\n\t}\n\n\t/**\n\t * **Per-call escape hatch.** Prefer {@link scopedDescribe} (the mounted\n\t * property) for the common case of \"describe scoped to my actor.\" Use\n\t * this method ONLY when you need a per-call actor override or different\n\t * `detail`/`fields`/`filter`.\n\t *\n\t * Returns a live `Node<GraphDescribeOutput>` scoped to the supplied (or\n\t * configured) actor, plus an explicit `dispose` for caller-controlled\n\t * lifecycle. Re-derives on every settle of the target graph: structural\n\t * changes, status transitions, and actor emissions (when a `Node<Actor>`\n\t * is bound).\n\t *\n\t * **Lifecycle (qa G1A — EC1 fix).** Each call instantiates a fresh\n\t * `target.describe({reactive: true})` handle (with its own version state,\n\t * observe handle, transitive topology subscriptions, derived + keepalive).\n\t * The caller MUST invoke the returned `dispose()` when finished to release\n\t * these resources. Disposers ARE also tracked on the wrapper graph so\n\t * `wrapper.destroy()` cleans up any handles the caller forgot — but a\n\t * long-lived wrapper with heavy per-call usage will leak until destroy\n\t * unless `dispose()` is called explicitly.\n\t *\n\t * @param actorOverride - Optional per-call override. Static {@link Actor}\n\t * or `Node<Actor>`. Omit to use the wrapper-configured default.\n\t * @param opts - Standard {@link GraphDescribeOptions} fields (`detail`,\n\t * `fields`, `filter`). `actor` / `reactive` / `reactiveName` are\n\t * controlled by the wrapper.\n\t * @returns `{node, dispose}` — `node` is the live describe Node; `dispose`\n\t * tears down the underlying reactive describe subscription idempotently.\n\t */\n\tscopedDescribeNode(\n\t\tactorOverride?: Actor | Node<Actor>,\n\t\topts?: Omit<GraphDescribeOptions, \"actor\" | \"reactive\" | \"reactiveName\">,\n\t): { node: Node<GraphDescribeOutput>; dispose: () => void } {\n\t\tconst actorNode =\n\t\t\tactorOverride == null\n\t\t\t\t? this._actorNode\n\t\t\t\t: isNode<Actor>(actorOverride)\n\t\t\t\t\t? actorOverride\n\t\t\t\t\t: node<Actor>([], { name: \"actor_override\", initial: actorOverride });\n\t\tconst handle = this._target.describe({\n\t\t\treactive: true,\n\t\t\t// `_actorNode` is `Node<Actor | null>`. The `as Node<Actor>` cast is\n\t\t\t// safe at runtime: `_describeReactive` resolves the actor via\n\t\t\t// `resolveActorOption`, which treats `null`/`undefined` cache as\n\t\t\t// \"no scoping\" (full visibility). Documented in graph.ts §\n\t\t\t// \"Cache-undefined semantics.\"\n\t\t\tactor: actorNode as Node<Actor>,\n\t\t\t...(opts ?? {}),\n\t\t});\n\t\t// Track on the wrapper as a safety net for callers who forget to\n\t\t// dispose; explicit `dispose()` is still the canonical lifecycle path.\n\t\tthis.addDisposer(handle.dispose);\n\t\treturn { node: handle.node, dispose: handle.dispose };\n\t}\n\n\t/** The wrapped graph (escape hatch for tooling). */\n\tget target(): Graph {\n\t\treturn this._target;\n\t}\n}\n\n/**\n * Wrap a {@link Graph} with {@link policyGate} plus a reactive scoped describe\n * lens. Returns a {@link GuardedExecutionGraph} that can be mounted, diffed,\n * or composed with {@link graphLens}.\n *\n * @param target - The graph to guard.\n * @param opts - See {@link GuardedExecutionOptions}.\n *\n * @example\n * ```ts\n * const guarded = guardedExecution(app, {\n * actor: node<Actor>([], { initial: { type: \"human\", id: \"alice\" } }), // reactive — re-derive on swap\n * policies: [\n * { effect: \"allow\", action: \"read\", actorType: \"human\" },\n * { effect: \"deny\", action: \"write\", pathPattern: \"system::*\" },\n * ],\n * mode: \"enforce\",\n * });\n *\n * // Canonical: subscribe to the mounted reactive describe (no per-call leak).\n * guarded.scopedDescribe.subscribe((msgs) => { /* live describe per actor / topology change *\\/ });\n * // Per-call escape hatch (different actor / detail) — caller manages dispose.\n * const detailed = guarded.scopedDescribeNode(undefined, { detail: \"standard\" });\n * try { detailed.node.subscribe(/* … *\\/); } finally { detailed.dispose(); }\n * guarded.violations.events.subscribe(msgs => console.log(\"violations:\", msgs));\n * guarded.lints.events.subscribe(msgs => console.warn(\"lints:\", msgs));\n * guarded.scope.subscribe(msgs => console.log(\"scope:\", msgs));\n * ```\n *\n * @category patterns\n */\nexport function guardedExecution(\n\ttarget: Graph,\n\topts: GuardedExecutionOptions,\n): GuardedExecutionGraph {\n\treturn new GuardedExecutionGraph(target, opts);\n}\n\n// Re-export types useful for call sites.\nexport type { DescribeFilter };\n"],"mappings":";;;;;;;;;;;AA4BA,SAAS,MAAM,aAAwB,YAAY;AACnD,SAAS,iBAAiB;AAC1B;AAAA,EAEC;AAAA,OAIM;AASP,SAAS,OAAU,GAA0B;AAC5C,SACC,OAAO,MAAM,YAAY,MAAM,QAAQ,eAAgB,KAAgB,UAAW;AAEpF;AAEA,SAAS,YAAY,MAAuC;AAC3D,SAAO,WAAW,WAAW,IAAI;AAClC;AAoFO,IAAM,wBAAN,cAAoC,MAAM;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA;AAAA,EACQ;AAAA,EACA;AAAA,EACA;AAAA,EACA,kBAAkB,oBAAI,IAAkC;AAAA,EAEzE,YAAY,QAAe,MAA+B;AACzD,UAAM,KAAK,QAAQ,GAAG,OAAO,IAAI,YAAY,KAAK,KAAK;AACvD,SAAK,UAAU;AACf,SAAK,QAAQ,KAAK,QAAQ;AAE1B,UAAM,cAAc,KAAK;AACzB,UAAM,iBAAiB,OAAkC,WAAW;AAEpE,QACC,CAAC,kBACD,KAAK,UAAU,aACd,YAA0C,WAAW,GACrD;AACD,YAAM,IAAI;AAAA,QACT;AAAA,MAED;AAAA,IACD;AAGA,SAAK,QAAQ,IAAI,WAAiC,SAAS;AAAA,MAC1D,eAAe,KAAK,cAAc;AAAA,IACnC,CAAC;AACD,SAAK,MAAM,SAAS,KAAK,KAAK;AAmB9B,UAAM,WAAW,KAAK;AACtB,QAAI,YAAY,MAAM;AACrB,WAAK,aAAa,KAAmB,CAAC,GAAG,EAAE,MAAM,SAAS,SAAS,KAAK,CAAC;AAAA,IAC1E,WAAW,OAAc,QAAQ,GAAG;AACnC,WAAK,aAAa;AAAA,QACjB,CAAC,QAAQ;AAAA,QACT,CAAC,WAAW,SAAS,QAAQ;AAC5B,gBAAM,OAAO,UAAU;AAAA,YAAI,CAAC,OAAO,MAClC,SAAS,QAAQ,MAAM,SAAS,IAAI,MAAM,GAAG,EAAE,IAAI,IAAI,SAAS,CAAC;AAAA,UAClE;AACA,kBAAQ,KAAM,KAAK,CAAC,KAAkC,IAAI;AAAA,QAC3D;AAAA,QACA,EAAE,cAAc,WAAW,MAAM,SAAS,SAAS,KAAK;AAAA,MACzD;AAAA,IACD,OAAO;AACN,WAAK,aAAa,KAAmB,CAAC,GAAG,EAAE,MAAM,SAAS,SAAS,SAAS,CAAC;AAAA,IAC9E;AAGA,UAAM,eAAsF;AAAA,MAC3F,MAAM,KAAK;AAAA,MACX,MAAM;AAAA,IACP;AACA,QAAI,KAAK,mBAAmB,KAAM,cAAa,kBAAkB,KAAK;AACtE,SAAK,WAAW,WAAW,QAAQ,KAAK,UAAU,YAAY;AAC9D,SAAK,aAAa,KAAK,SAAS;AAChC,SAAK,MAAM,YAAY,KAAK,QAAQ;AAGpC,QAAI,kBAAkB,KAAK,UAAU,WAAW;AAC/C,YAAM,eAAe;AAcrB,YAAM,SAAS,aAAa;AAC5B,UAAI,UAAU,QAAQ,OAAO,WAAW,GAAG;AAC1C,aAAK;AAAA,UACJ;AAAA,UACA;AAAA,QACD;AAAA,MACD;AACA,YAAM,WAAW,aAAa,UAAU,CAAC,SAAS;AACjD,mBAAW,KAAK,MAAM;AACrB,cAAI,EAAE,CAAC,MAAM,KAAM;AACnB,gBAAM,IAAI,EAAE,CAAC;AACb,cAAI,KAAK,QAAQ,EAAE,WAAW,GAAG;AAChC,iBAAK;AAAA,cACJ;AAAA,cACA;AAAA,YACD;AAAA,UACD;AAAA,QACD;AAAA,MACD,CAAC;AACD,WAAK,YAAY,QAAQ;AAAA,IAC1B;AASA,QAAI,KAAK,UAAU,SAAS;AAC3B,YAAM,YAAY,OAAO,SAAS,EAAE,QAAQ,OAAO,CAAC;AACpD,YAAM,WAAW,OAAO,OAAO,UAAU,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI;AAC3E,UAAI,CAAC,UAAU;AACd,aAAK;AAAA,UACJ;AAAA,UACA;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAMA,QAAI,YAAY,MAAM;AACrB,WAAK;AAAA,QACJ;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAGA,SAAK,QAAQ;AAAA,MACZ,CAAC,KAAK,YAAY,KAAK,SAAS,QAAQ;AAAA,MACxC,CAAC,WAAW,SAAS,QAAQ;AAC5B,cAAM,OAAO,UAAU;AAAA,UAAI,CAAC,OAAO,MAClC,SAAS,QAAQ,MAAM,SAAS,IAAI,MAAM,GAAG,EAAE,IAAI,IAAI,SAAS,CAAC;AAAA,QAClE;AACA,gBAAQ,KAAK;AAAA,UACZ,OAAQ,KAAK,CAAC,KAAkC;AAAA,UAChD,MAAM,KAAK;AAAA,UACX,eAAgB,KAAK,CAAC,EAAgC;AAAA,QACvD,CAAC;AAAA,MACF;AAAA,MACA;AAAA,QACC,MAAM;AAAA,QACN,cAAc;AAAA,QACd,MAAM,YAAY,OAAO;AAAA,MAC1B;AAAA,IACD;AACA,SAAK,IAAI,KAAK,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,SAAK,YAAY,UAAU,KAAK,KAAK,CAAC;AAQtC,UAAM,eAAe,OAAO,SAAS;AAAA,MACpC,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAMV,OAAO,KAAK;AAAA,MACZ,cAAc;AAAA,IACf,CAAC;AACD,SAAK,iBAAiB,aAAa;AACnC,SAAK,IAAI,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,SAAK,YAAY,aAAa,OAAO;AAAA,EACtC;AAAA,EAEQ,UAAU,MAAoC,SAAuB;AAC5E,QAAI,KAAK,gBAAgB,IAAI,IAAI,EAAG;AACpC,SAAK,gBAAgB,IAAI,IAAI;AAC7B,SAAK,MAAM,QAAQ,EAAE,MAAM,SAAS,cAAc,YAAY,EAAE,CAAC;AAAA,EAClE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA+BA,mBACC,eACA,MAC2D;AAC3D,UAAM,YACL,iBAAiB,OACd,KAAK,aACL,OAAc,aAAa,IAC1B,gBACA,KAAY,CAAC,GAAG,EAAE,MAAM,kBAAkB,SAAS,cAAc,CAAC;AACvE,UAAM,SAAS,KAAK,QAAQ,SAAS;AAAA,MACpC,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAMV,OAAO;AAAA,MACP,GAAI,QAAQ,CAAC;AAAA,IACd,CAAC;AAGD,SAAK,YAAY,OAAO,OAAO;AAC/B,WAAO,EAAE,MAAM,OAAO,MAAM,SAAS,OAAO,QAAQ;AAAA,EACrD;AAAA;AAAA,EAGA,IAAI,SAAgB;AACnB,WAAO,KAAK;AAAA,EACb;AACD;AAiCO,SAAS,iBACf,QACA,MACwB;AACxB,SAAO,IAAI,sBAAsB,QAAQ,IAAI;AAC9C;","names":[]}
|