@particle-academy/fancy-flow 0.65.2 → 0.66.1
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 +100 -3
- package/dist/{FlowViewer-BI_AyyvU.d.ts → FlowViewer-BCc_BvuD.d.ts} +1 -1
- package/dist/{FlowViewer-DABx-6A-.d.cts → FlowViewer-CoAJ3o52.d.cts} +1 -1
- package/dist/{HumanPrompt-Bpp3JiVH.d.cts → HumanPrompt--pXDOyYC.d.cts} +2 -2
- package/dist/{HumanPrompt-BKThiyjB.d.ts → HumanPrompt-DXm_FP9z.d.ts} +2 -2
- package/dist/chunk-27RZJAE2.js +2586 -0
- package/dist/chunk-27RZJAE2.js.map +1 -0
- package/dist/{chunk-MBVX4ZRB.js → chunk-2QTEELJE.js} +4 -3
- package/dist/chunk-2QTEELJE.js.map +1 -0
- package/dist/chunk-2QXKDLGT.js +58 -0
- package/dist/chunk-2QXKDLGT.js.map +1 -0
- package/dist/{chunk-W5DPKJY4.js → chunk-6AYC3BWI.js} +4 -4
- package/dist/chunk-6AYC3BWI.js.map +1 -0
- package/dist/{chunk-5H54OTKT.js → chunk-6TH646CS.js} +127 -5
- package/dist/chunk-6TH646CS.js.map +1 -0
- package/dist/{chunk-EO6444T2.js → chunk-BUNFPBTF.js} +5 -4
- package/dist/chunk-BUNFPBTF.js.map +1 -0
- package/dist/{chunk-77V4QC6Y.js → chunk-FV3D366L.js} +3 -3
- package/dist/{chunk-77V4QC6Y.js.map → chunk-FV3D366L.js.map} +1 -1
- package/dist/{chunk-JF6WCRBU.js → chunk-OWENS2H5.js} +36 -1905
- package/dist/chunk-OWENS2H5.js.map +1 -0
- package/dist/{chunk-RIAFHQT5.js → chunk-RE3XNVSB.js} +3 -3
- package/dist/{chunk-RIAFHQT5.js.map → chunk-RE3XNVSB.js.map} +1 -1
- package/dist/connectors.d.cts +2 -2
- package/dist/connectors.d.ts +2 -2
- package/dist/durable/index.d.cts +2 -2
- package/dist/durable/index.d.ts +2 -2
- package/dist/durable.cjs +865 -9135
- package/dist/durable.cjs.map +1 -1
- package/dist/durable.js +2 -4
- package/dist/durable.js.map +1 -1
- package/dist/engine.cjs +927 -9278
- package/dist/engine.cjs.map +1 -1
- package/dist/engine.d.cts +6 -7
- package/dist/engine.d.ts +6 -7
- package/dist/engine.js +5 -7
- package/dist/engine.js.map +1 -1
- package/dist/fields/react-fancy.d.cts +3 -3
- package/dist/fields/react-fancy.d.ts +3 -3
- package/dist/index.cjs +11009 -10282
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +65 -36
- package/dist/index.d.ts +65 -36
- package/dist/index.js +22 -19
- package/dist/index.js.map +1 -1
- package/dist/layout/index.d.cts +1 -1
- package/dist/layout/index.d.ts +1 -1
- package/dist/llm/prism.cjs.map +1 -1
- package/dist/llm/prism.d.cts +1 -2
- package/dist/llm/prism.d.ts +1 -2
- package/dist/llm/prism.js +1 -1
- package/dist/llm/vercel-ai.cjs.map +1 -1
- package/dist/llm/vercel-ai.d.cts +1 -2
- package/dist/llm/vercel-ai.d.ts +1 -2
- package/dist/llm/vercel-ai.js +1 -1
- package/dist/registry/index.d.cts +20 -9
- package/dist/registry/index.d.ts +20 -9
- package/dist/{registry-CntAdUcY.d.cts → registry-BcgllSk2.d.cts} +1 -1
- package/dist/{registry-DYoV-MQi.d.ts → registry-h-2QswZ5.d.ts} +1 -1
- package/dist/registry.cjs +11252 -10409
- package/dist/registry.cjs.map +1 -1
- package/dist/registry.js +5 -4
- package/dist/{run-cohort-C1nRh_mi.d.ts → run-cohort-CjUBWg6X.d.ts} +2 -2
- package/dist/{run-cohort-CBRAUj-z.d.cts → run-cohort-DL9JzzPU.d.cts} +2 -2
- package/dist/{run-flow-2XsHBwpd.d.cts → run-flow-B_8hgO5_.d.cts} +1 -1
- package/dist/{run-flow-D7AOCcfE.d.ts → run-flow-CxEGBOxd.d.ts} +1 -1
- package/dist/runtime/index.d.cts +5 -5
- package/dist/runtime/index.d.ts +5 -5
- package/dist/runtime.cjs +10843 -10194
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.js +5 -5
- package/dist/schema/index.d.cts +19 -6
- package/dist/schema/index.d.ts +19 -6
- package/dist/schema.cjs +881 -9142
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.js +4 -5
- package/dist/screens.cjs +842 -86
- package/dist/screens.cjs.map +1 -1
- package/dist/screens.d.cts +2 -2
- package/dist/screens.d.ts +2 -2
- package/dist/screens.js +7 -6
- package/dist/screens.js.map +1 -1
- package/dist/terminal/fancy-term-host.cjs +99 -0
- package/dist/terminal/fancy-term-host.cjs.map +1 -0
- package/dist/terminal/fancy-term-host.d.cts +76 -0
- package/dist/terminal/fancy-term-host.d.ts +76 -0
- package/dist/terminal/fancy-term-host.js +92 -0
- package/dist/terminal/fancy-term-host.js.map +1 -0
- package/dist/types-B-Syk9-M.d.cts +620 -0
- package/dist/types-B-Syk9-M.d.ts +620 -0
- package/dist/{types-D71SKA5A.d.cts → types-C2ATTmjN.d.cts} +1 -1
- package/dist/{types-Ckhz-YwC.d.ts → types-VunLGqrn.d.ts} +1 -1
- package/dist/ux.cjs +885 -9142
- package/dist/ux.cjs.map +1 -1
- package/dist/ux.d.cts +2 -2
- package/dist/ux.d.ts +2 -2
- package/dist/ux.js +2 -3
- package/dist/ux.js.map +1 -1
- package/package.json +11 -1
- package/dist/capabilities-BYa5p5jw.d.cts +0 -112
- package/dist/capabilities-COOXRiNL.d.ts +0 -112
- package/dist/chunk-5H54OTKT.js.map +0 -1
- package/dist/chunk-EO6444T2.js.map +0 -1
- package/dist/chunk-JF6WCRBU.js.map +0 -1
- package/dist/chunk-MBVX4ZRB.js.map +0 -1
- package/dist/chunk-UM4C46AF.js +0 -103
- package/dist/chunk-UM4C46AF.js.map +0 -1
- package/dist/chunk-USL4FMFU.js +0 -41
- package/dist/chunk-USL4FMFU.js.map +0 -1
- package/dist/chunk-W5DPKJY4.js.map +0 -1
- package/dist/types-JFYjPJAG.d.cts +0 -333
- package/dist/types-JFYjPJAG.d.ts +0 -333
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/runtime/use-flow-run.ts","../src/runtime/use-flow-state.ts","../src/runtime/history.ts","../src/runtime/use-flow-history.ts"],"names":["useState","useCallback","useRef"],"mappings":";;;AA8DO,SAAS,WAAW,EAAE,OAAA,GAAU,GAAA,EAAI,GAAuB,EAAC,EAAqB;AACtF,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAI,QAAA,CAAwC,EAAE,CAAA;AAC1E,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAI,QAAA,CAA6C,EAAE,CAAA;AACnF,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAI,QAAA,CAA6C,EAAE,CAAA;AACvF,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,QAAA,CAAkC,EAAE,CAAA;AAClE,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,QAAA,CAA6B,EAAE,CAAA;AACvD,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAS,KAAK,CAAA;AAC5C,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAI,SAA2B,IAAI,CAAA;AACnE,EAAA,MAAM,QAAA,GAAW,OAA+B,IAAI,CAAA;AAEpD,EAAA,MAAM,WAAA,GAAc,WAAA;AAAA,IAClB,CAAC,CAAA,KAAgB;AACf,MAAA,QAAQ,EAAE,IAAA;AAAM,QACd,KAAK,aAAA;AACH,UAAA,WAAA,CAAY,CAAC,CAAA,MAAO,EAAE,GAAG,CAAA,EAAG,CAAC,CAAA,CAAE,MAAM,GAAG,CAAA,CAAE,MAAA,EAAO,CAAE,CAAA;AACnD,UAAA,aAAA,CAAc,CAAC,CAAA,MAAO,EAAE,GAAG,CAAA,EAAG,CAAC,CAAA,CAAE,MAAM,GAAG,CAAA,CAAE,IAAA,EAAK,CAAE,CAAA;AACnD,UAAA,UAAA,CAAW,EAAE,OAAO,QAAA,EAAU,IAAA,EAAM,GAAG,CAAA,CAAE,MAAM,CAAA,QAAA,EAAM,CAAA,CAAE,MAAM,CAAA,EAAG,EAAE,IAAA,GAAO,CAAA,EAAA,EAAK,EAAE,IAAI,CAAA,CAAA,CAAA,GAAM,EAAE,CAAA,CAAA,EAAI,MAAA,EAAQ,CAAA,CAAE,MAAA,EAAQ,CAAA;AAClH,UAAA;AAAA,QACF,KAAK,cAAA;AACH,UAAA,eAAA,CAAgB,CAAC,CAAA,MAAO,EAAE,GAAG,CAAA,EAAG,CAAC,CAAA,CAAE,MAAM,GAAG,CAAA,CAAE,OAAA,EAAQ,CAAE,CAAA;AACxD,UAAA,UAAA,CAAW,EAAE,OAAO,SAAA,EAAW,IAAA,EAAM,EAAE,OAAA,EAAS,MAAA,EAAQ,CAAA,CAAE,MAAA,EAAQ,CAAA;AAClE,UAAA;AAAA,QACF,KAAK,aAAA;AACH,UAAA,UAAA,CAAW,CAAC,CAAA,MAAO,EAAE,GAAG,CAAA,EAAG,CAAC,CAAA,CAAE,MAAM,GAAG,CAAA,CAAE,KAAA,EAAM,CAAE,CAAA;AACjD,UAAA,UAAA,CAAW,EAAE,OAAO,MAAA,EAAQ,IAAA,EAAM,GAAG,CAAA,CAAE,MAAM,CAAA,CAAA,EAAI,CAAA,CAAE,MAAM,CAAA,GAAA,EAAM,QAAQ,CAAA,CAAE,KAAK,CAAC,CAAA,CAAA,EAAI,MAAA,EAAQ,EAAE,MAAA,EAAQ,MAAA,EAAQ,CAAA,CAAE,KAAA,EAAO,CAAA;AACtH,UAAA;AAAA,QACF,KAAK,KAAA;AACH,UAAA,UAAA,CAAW,EAAE,KAAA,EAAO,CAAA,CAAE,KAAA,EAAO,IAAA,EAAM,CAAA,CAAE,OAAA,EAAS,MAAA,EAAQ,CAAA,CAAE,MAAA,EAAQ,MAAA,EAAQ,CAAA,CAAE,QAAQ,CAAA;AAClF,UAAA;AAAA,QACF,KAAK,WAAA;AACH,UAAA,UAAA,CAAW,EAAE,KAAA,EAAO,MAAA,EAAQ,IAAA,EAAM,sBAAiB,CAAA;AACnD,UAAA;AAAA,QACF,KAAK,SAAA;AACH,UAAA,UAAA,CAAW,EAAE,KAAA,EAAO,CAAA,CAAE,EAAA,GAAK,MAAA,GAAS,OAAA,EAAS,IAAA,EAAM,CAAA,CAAE,EAAA,GAAK,qBAAA,GAAmB,mBAAA,EAAgB,CAAA;AAC7F,UAAA;AAAA,QACF,KAAK,WAAA;AACH,UAAA,UAAA,CAAW,EAAE,KAAA,EAAO,OAAA,EAAS,IAAA,EAAM,CAAA,CAAE,OAAO,CAAA;AAC5C,UAAA;AAAA;AAEJ,MAAA,SAAS,WAAW,OAAA,EAA8C;AAChE,QAAA,OAAA,CAAQ,CAAC,CAAA,KAAM;AACb,UAAA,MAAM,QAA0B,EAAE,EAAA,EAAI,CAAA,EAAG,IAAA,CAAK,KAAK,CAAA,CAAA,EAAI,CAAA,CAAE,MAAM,IAAI,EAAA,EAAI,IAAA,CAAK,GAAA,EAAI,EAAG,GAAG,OAAA,EAAQ;AAC9F,UAAA,MAAM,IAAA,GAAO,CAAC,GAAG,CAAA,EAAG,KAAK,CAAA;AACzB,UAAA,OAAO,IAAA,CAAK,SAAS,OAAA,GAAU,IAAA,CAAK,MAAM,IAAA,CAAK,MAAA,GAAS,OAAO,CAAA,GAAI,IAAA;AAAA,QACrE,CAAC,CAAA;AAAA,MACH;AAAA,IACF,CAAA;AAAA,IACA,CAAC,OAAO;AAAA,GACV;AAEA,EAAA,MAAM,GAAA,GAAM,WAAA;AAAA,IACV,OAAO,KAAA,EAAkB,SAAA,EAA6B,OAAA,GAAsB,EAAC,KAAM;AACjF,MAAA,IAAI,OAAA,EAAS;AACX,QAAA,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,SAAS,EAAC,EAAG,OAAO,oCAAA,EAAqC;AAAA,MAC/E;AACA,MAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,MAAA,QAAA,CAAS,OAAA,GAAU,UAAA;AAEnB,MAAA,MAAM,eAA8C,EAAC;AACrD,MAAA,KAAA,MAAW,KAAK,KAAA,CAAM,KAAA,EAAO,YAAA,CAAa,CAAA,CAAE,EAAE,CAAA,GAAI,MAAA;AAClD,MAAA,WAAA,CAAY,YAAY,CAAA;AACxB,MAAA,aAAA,CAAc,EAAE,CAAA;AAChB,MAAA,UAAA,CAAW,EAAE,CAAA;AACb,MAAA,UAAA,CAAW,IAAI,CAAA;AACf,MAAA,IAAI;AACF,QAAA,MAAM,MAAA,GAAS,MAAM,OAAA,CAAQ,KAAA,EAAO,SAAA,EAAW,WAAA,EAAa,EAAE,GAAG,OAAA,EAAS,MAAA,EAAQ,UAAA,CAAW,MAAA,EAAQ,CAAA;AACrG,QAAA,aAAA,CAAc,MAAM,CAAA;AACpB,QAAA,OAAO,MAAA;AAAA,MACT,CAAA,SAAE;AACA,QAAA,UAAA,CAAW,KAAK,CAAA;AAChB,QAAA,QAAA,CAAS,OAAA,GAAU,IAAA;AAAA,MACrB;AAAA,IACF,CAAA;AAAA,IACA,CAAC,aAAa,OAAO;AAAA,GACvB;AAEA,EAAA,MAAM,MAAA,GAAS,YAAY,MAAM,QAAA,CAAS,SAAS,KAAA,EAAM,EAAG,EAAE,CAAA;AAE9D,EAAA,MAAM,KAAA,GAAQ,YAAY,MAAM;AAC9B,IAAA,WAAA,CAAY,EAAE,CAAA;AACd,IAAA,aAAA,CAAc,EAAE,CAAA;AAChB,IAAA,UAAA,CAAW,EAAE,CAAA;AACb,IAAA,OAAA,CAAQ,EAAE,CAAA;AACV,IAAA,aAAA,CAAc,IAAI,CAAA;AAAA,EACpB,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,OAAO,EAAE,QAAA,EAAU,UAAA,EAAY,YAAA,EAAc,OAAA,EAAS,MAAM,OAAA,EAAS,UAAA,EAAY,GAAA,EAAK,MAAA,EAAQ,KAAA,EAAM;AACtG;AAOO,SAAS,mBAAA,CACd,OACA,OAAA,EACS;AACT,EAAA,OAAO,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,KAAM;AACtB,IAAA,MAAM,OAAO,WAAA,CAAa,CAAA,CAAE,MAAc,IAAA,IAAQ,CAAA,CAAE,QAAQ,EAAE,CAAA;AAC9D,IAAA,IAAI,CAAC,IAAA,EAAM,QAAA,IAAY,EAAE,CAAA,CAAE,EAAA,IAAM,UAAU,OAAO,CAAA;AAClD,IAAA,OAAO,EAAE,GAAG,CAAA,EAAG,IAAA,EAAM,EAAE,GAAG,CAAA,CAAE,IAAA,EAAM,MAAA,EAAQ,OAAA,CAAQ,CAAA,CAAE,EAAE,GAAE,EAAE;AAAA,EAC5D,CAAC,CAAA;AACH;AAGO,SAAS,oBAAA,CACd,KAAA,EACA,QAAA,EACA,UAAA,EACS;AACT,EAAA,OAAO,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,IACvB,GAAG,CAAA;AAAA,IACH,IAAA,EAAM;AAAA,MACJ,GAAG,CAAA,CAAE,IAAA;AAAA,MACL,QAAQ,QAAA,CAAS,CAAA,CAAE,EAAE,CAAA,IAAK,CAAA,CAAE,MAAM,MAAA,IAAU,MAAA;AAAA,MAC5C,YAAY,UAAA,CAAW,CAAA,CAAE,EAAE,CAAA,IAAK,EAAE,IAAA,EAAM;AAAA;AAC1C,GACF,CAAE,CAAA;AACJ;AAEA,SAAS,QAAQ,CAAA,EAAoB;AACnC,EAAA,IAAI;AACF,IAAA,MAAM,CAAA,GAAI,IAAA,CAAK,SAAA,CAAU,CAAC,CAAA;AAC1B,IAAA,OAAO,CAAA,IAAK,CAAA,CAAE,MAAA,GAAS,EAAA,GAAK,CAAA,CAAE,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA,GAAI,QAAA,GAAO,CAAA,IAAK,MAAA,CAAO,CAAC,CAAA;AAAA,EACnE,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,OAAO,CAAC,CAAA;AAAA,EACjB;AACF;AC3JO,SAAS,aAAa,OAAA,EAAwC;AACnE,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIA,QAAAA,CAAqB,QAAQ,KAAK,CAAA;AAC5D,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIA,QAAAA,CAAqB,QAAQ,KAAK,CAAA;AAE5D,EAAA,MAAM,aAAA,GAAgBC,WAAAA,CAAY,CAAC,OAAA,KAA0B;AAC3D,IAAA,QAAA,CAAS,CAAC,EAAA,KAAO,gBAAA,CAAiB,OAAA,EAAS,EAAE,CAAe,CAAA;AAAA,EAC9D,CAAA,EAAG,EAAE,CAAA;AACL,EAAA,MAAM,aAAA,GAAgBA,WAAAA,CAAY,CAAC,OAAA,KAA0B;AAC3D,IAAA,QAAA,CAAS,CAAC,EAAA,KAAO,gBAAA,CAAiB,OAAA,EAAS,EAAE,CAAC,CAAA;AAAA,EAChD,CAAA,EAAG,EAAE,CAAA;AACL,EAAA,MAAM,SAAA,GAAYA,WAAAA,CAAY,CAAC,UAAA,KAA2B;AACxD,IAAA,QAAA,CAAS,CAAC,EAAA,KAAO,OAAA,CAAQ,UAAA,EAAY,EAAE,CAAW,CAAA;AAAA,EACpD,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,QAAA,GAAWA,WAAAA,CAAY,CAAC,KAAA,KAAqB;AAEjD,IAAA,QAAA,CAAS,MAAM,KAAK,CAAA;AACpB,IAAA,QAAA,CAAS,MAAM,KAAK,CAAA;AAAA,EACtB,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,OAAA,GAAUA,WAAAA,CAAY,OAAO,EAAE,KAAA,EAAO,OAAM,CAAA,EAAI,CAAC,KAAA,EAAO,KAAK,CAAC,CAAA;AAEpE,EAAA,OAAO,EAAE,OAAO,KAAA,EAAO,QAAA,EAAU,UAAU,QAAA,EAAU,aAAA,EAAe,aAAA,EAAe,SAAA,EAAW,OAAA,EAAQ;AACxG;;;ACjCO,SAAS,aAAA,CAAc,QAAQ,GAAA,EAAwB;AAC5D,EAAA,IAAI,OAAoB,EAAC;AACzB,EAAA,IAAI,SAAsB,EAAC;AAE3B,EAAA,OAAO;AAAA,IACL,KAAK,KAAA,EAAO;AACV,MAAA,IAAA,CAAK,KAAK,KAAK,CAAA;AACf,MAAA,IAAI,IAAA,CAAK,MAAA,GAAS,KAAA,EAAO,IAAA,CAAK,KAAA,EAAM;AACpC,MAAA,MAAA,GAAS,EAAC;AAAA,IACZ,CAAA;AAAA,IACA,KAAK,OAAA,EAAS;AACZ,MAAA,MAAM,IAAA,GAAO,KAAK,GAAA,EAAI;AACtB,MAAA,IAAI,IAAA,KAAS,QAAW,OAAO,IAAA;AAC/B,MAAA,MAAA,CAAO,KAAK,OAAO,CAAA;AACnB,MAAA,OAAO,IAAA;AAAA,IACT,CAAA;AAAA,IACA,KAAK,OAAA,EAAS;AACZ,MAAA,MAAM,IAAA,GAAO,OAAO,GAAA,EAAI;AACxB,MAAA,IAAI,IAAA,KAAS,QAAW,OAAO,IAAA;AAC/B,MAAA,IAAA,CAAK,KAAK,OAAO,CAAA;AACjB,MAAA,OAAO,IAAA;AAAA,IACT,CAAA;AAAA,IACA,OAAA,EAAS,MAAM,IAAA,CAAK,MAAA,GAAS,CAAA;AAAA,IAC7B,OAAA,EAAS,MAAM,MAAA,CAAO,MAAA,GAAS,CAAA;AAAA,IAC/B,KAAA,GAAQ;AACN,MAAA,IAAA,GAAO,EAAC;AACR,MAAA,MAAA,GAAS,EAAC;AAAA,IACZ,CAAA;AAAA,IACA,IAAA,EAAM,OAAO,EAAE,IAAA,EAAM,KAAK,MAAA,EAAQ,MAAA,EAAQ,OAAO,MAAA,EAAO;AAAA,GAC1D;AACF;;;ACxBO,SAAS,eAAe,IAAA,EAAgD;AAC7E,EAAA,MAAM,OAAA,GAAUC,MAAAA,CAAO,aAAA,EAAe,CAAA,CAAE,OAAA;AACxC,EAAA,MAAM,SAAA,GAAYA,OAAO,KAAK,CAAA;AAC9B,EAAA,MAAM,SAAA,GAAYA,OAAO,KAAK,CAAA;AAC9B,EAAA,MAAM,GAAG,IAAI,CAAA,GAAIF,SAAS,CAAC,CAAA;AAC3B,EAAA,MAAM,QAAA,GAAWC,WAAAA,CAAY,MAAM,IAAA,CAAK,CAAC,MAAM,CAAA,GAAI,CAAC,CAAA,EAAG,EAAE,CAAA;AAGzD,EAAA,MAAM,QAAA,GAAWC,OAAkB,EAAE,KAAA,EAAO,KAAK,KAAA,EAAO,KAAA,EAAO,IAAA,CAAK,KAAA,EAAO,CAAA;AAC3E,EAAA,QAAA,CAAS,UAAU,EAAE,KAAA,EAAO,KAAK,KAAA,EAAO,KAAA,EAAO,KAAK,KAAA,EAAM;AAE1D,EAAA,MAAM,OAAA,GAAUD,YAAY,MAAM;AAChC,IAAA,IAAI,SAAA,CAAU,OAAA,IAAW,SAAA,CAAU,OAAA,EAAS;AAC5C,IAAA,SAAA,CAAU,OAAA,GAAU,IAAA;AACpB,IAAA,cAAA,CAAe,MAAM;AACnB,MAAA,SAAA,CAAU,OAAA,GAAU,KAAA;AAAA,IACtB,CAAC,CAAA;AACD,IAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,OAAO,CAAA;AAC7B,IAAA,QAAA,EAAS;AAAA,EACX,CAAA,EAAG,CAAC,OAAA,EAAS,QAAQ,CAAC,CAAA;AAEtB,EAAA,MAAM,OAAA,GAAUA,WAAAA;AAAA,IACd,CAAC,CAAA,KAAwB;AACvB,MAAA,IAAI,CAAC,CAAA,EAAG;AACR,MAAA,SAAA,CAAU,OAAA,GAAU,IAAA;AACpB,MAAA,IAAA,CAAK,SAAS,CAAC,CAAA;AACf,MAAA,cAAA,CAAe,MAAM;AACnB,QAAA,SAAA,CAAU,OAAA,GAAU,KAAA;AAAA,MACtB,CAAC,CAAA;AACD,MAAA,QAAA,EAAS;AAAA,IACX,CAAA;AAAA,IACA,CAAC,MAAM,QAAQ;AAAA,GACjB;AAEA,EAAA,MAAM,IAAA,GAAOA,WAAAA,CAAY,MAAM,OAAA,CAAQ,OAAA,CAAQ,IAAA,CAAK,QAAA,CAAS,OAAO,CAAC,CAAA,EAAG,CAAC,OAAA,EAAS,OAAO,CAAC,CAAA;AAC1F,EAAA,MAAM,IAAA,GAAOA,WAAAA,CAAY,MAAM,OAAA,CAAQ,OAAA,CAAQ,IAAA,CAAK,QAAA,CAAS,OAAO,CAAC,CAAA,EAAG,CAAC,OAAA,EAAS,OAAO,CAAC,CAAA;AAE1F,EAAA,MAAM,OAAA,GAAU,OAAA;AAAA,IACd,OAAO;AAAA,MACL,GAAG,IAAA;AAAA,MACH,QAAA,EAAU,CAAC,IAAA,KAAS;AAClB,QAAA,OAAA,EAAQ;AACR,QAAA,IAAA,CAAK,SAAS,IAAI,CAAA;AAAA,MACpB,CAAA;AAAA,MACA,QAAA,EAAU,CAAC,IAAA,KAAS;AAClB,QAAA,OAAA,EAAQ;AACR,QAAA,IAAA,CAAK,SAAS,IAAI,CAAA;AAAA,MACpB,CAAA;AAAA,MACA,QAAA,EAAU,CAAC,CAAA,KAAM;AACf,QAAA,OAAA,EAAQ;AACR,QAAA,IAAA,CAAK,SAAS,CAAC,CAAA;AAAA,MACjB,CAAA;AAAA,MACA,aAAA,EAAe,CAAC,OAAA,KAA0B;AAExC,QAAA,IAAI,CAAC,SAAA,CAAU,OAAA,IAAW,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,KAAS,QAAQ,CAAA,EAAG,OAAA,EAAQ;AAC5E,QAAA,IAAA,CAAK,cAAc,OAAO,CAAA;AAAA,MAC5B,CAAA;AAAA,MACA,aAAA,EAAe,CAAC,OAAA,KAA0B;AACxC,QAAA,IAAI,CAAC,SAAA,CAAU,OAAA,IAAW,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,KAAS,QAAQ,CAAA,EAAG,OAAA,EAAQ;AAC5E,QAAA,IAAA,CAAK,cAAc,OAAO,CAAA;AAAA,MAC5B,CAAA;AAAA,MACA,SAAA,EAAW,CAAC,IAAA,KAAS;AACnB,QAAA,OAAA,EAAQ;AACR,QAAA,IAAA,CAAK,UAAU,IAAI,CAAA;AAAA,MACrB;AAAA,KACF,CAAA;AAAA,IACA,CAAC,MAAM,OAAO;AAAA,GAChB;AAEA,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,OAAA;AAAA,IACN,IAAA;AAAA,IACA,IAAA;AAAA,IACA,OAAA,EAAS,QAAQ,OAAA,EAAQ;AAAA,IACzB,OAAA,EAAS,QAAQ,OAAA,EAAQ;AAAA,IACzB,OAAA;AAAA,IACA,eAAA,EAAiB;AAAA,GACnB;AACF","file":"chunk-MBVX4ZRB.js","sourcesContent":["import { useCallback, useRef, useState } from \"react\";\nimport { runFlow, type RunOptions, type RunResult } from \"./run-flow\";\nimport { getNodeKind } from \"../registry/registry\";\nimport type {\n ExecutorRegistry,\n FlowGraph,\n NodeRunStatus,\n RunEvent,\n} from \"../types\";\n\nexport type FlowRunFeedEntry = {\n id: string;\n at: number;\n /**\n * `message` is a node's own human-facing announcement (`startingMsg` /\n * `stoppingMsg`), kept distinct from `status` and `info` so a progress UI can\n * show ONLY the narration. Folded in with diagnostics it would be unfindable,\n * which is the same as not having it.\n */\n level: \"info\" | \"warn\" | \"error\" | \"status\" | \"message\";\n text: string;\n nodeId?: string;\n detail?: unknown;\n};\n\nexport type UseFlowRunReturn = {\n /** Status keyed by nodeId — drive the UI overlay from this. */\n statuses: Record<string, NodeRunStatus>;\n /** Per-node status text (e.g. error message). */\n statusText: Record<string, string | undefined>;\n /** Latest computed output value per node (for reactive kinds). */\n outputs: Record<string, unknown>;\n /**\n * Latest status message per nodeId, from the node's own `startingMsg` /\n * `stoppingMsg`. Undefined for the nodes that declared none, which is most\n * of them by design.\n */\n nodeMessages: Record<string, string | undefined>;\n /** Live event log (capped to last N). */\n feed: FlowRunFeedEntry[];\n /** Whether a run is currently in progress. */\n running: boolean;\n /** Last run result, or null. */\n lastResult: RunResult | null;\n /** Kick off a run with the provided graph + executors. */\n run: (graph: FlowGraph, executors: ExecutorRegistry, options?: RunOptions) => Promise<RunResult>;\n /** Cancel the current run (if any). */\n cancel: () => void;\n /** Reset all runtime state (statuses, feed, lastResult). */\n reset: () => void;\n};\n\nexport type UseFlowRunOptions = {\n /** Cap the in-memory feed to this many entries. Default 200. */\n maxFeed?: number;\n};\n\n/**\n * useFlowRun — drives `runFlow` + maintains observability state. Pair with\n * `applyStatusesToNodes` (below) before passing nodes to `<FlowCanvas>` so\n * the per-node status badge renders.\n */\nexport function useFlowRun({ maxFeed = 200 }: UseFlowRunOptions = {}): UseFlowRunReturn {\n const [statuses, setStatuses] = useState<Record<string, NodeRunStatus>>({});\n const [statusText, setStatusText] = useState<Record<string, string | undefined>>({});\n const [nodeMessages, setNodeMessages] = useState<Record<string, string | undefined>>({});\n const [outputs, setOutputs] = useState<Record<string, unknown>>({});\n const [feed, setFeed] = useState<FlowRunFeedEntry[]>([]);\n const [running, setRunning] = useState(false);\n const [lastResult, setLastResult] = useState<RunResult | null>(null);\n const abortRef = useRef<AbortController | null>(null);\n\n const handleEvent = useCallback(\n (e: RunEvent) => {\n switch (e.type) {\n case \"node-status\":\n setStatuses((s) => ({ ...s, [e.nodeId]: e.status }));\n setStatusText((t) => ({ ...t, [e.nodeId]: e.text }));\n appendFeed({ level: \"status\", text: `${e.nodeId} → ${e.status}${e.text ? ` (${e.text})` : \"\"}`, nodeId: e.nodeId });\n break;\n case \"node-message\":\n setNodeMessages((m) => ({ ...m, [e.nodeId]: e.message }));\n appendFeed({ level: \"message\", text: e.message, nodeId: e.nodeId });\n break;\n case \"node-output\":\n setOutputs((o) => ({ ...o, [e.nodeId]: e.value }));\n appendFeed({ level: \"info\", text: `${e.nodeId}.${e.portId} = ${preview(e.value)}`, nodeId: e.nodeId, detail: e.value });\n break;\n case \"log\":\n appendFeed({ level: e.level, text: e.message, nodeId: e.nodeId, detail: e.detail });\n break;\n case \"run-start\":\n appendFeed({ level: \"info\", text: \"▶ run started\" });\n break;\n case \"run-end\":\n appendFeed({ level: e.ok ? \"info\" : \"error\", text: e.ok ? \"✓ run complete\" : \"✗ run failed\" });\n break;\n case \"run-error\":\n appendFeed({ level: \"error\", text: e.error });\n break;\n }\n function appendFeed(partial: Omit<FlowRunFeedEntry, \"id\" | \"at\">) {\n setFeed((f) => {\n const entry: FlowRunFeedEntry = { id: `${Date.now()}_${f.length}`, at: Date.now(), ...partial };\n const next = [...f, entry];\n return next.length > maxFeed ? next.slice(next.length - maxFeed) : next;\n });\n }\n },\n [maxFeed],\n );\n\n const run = useCallback(\n async (graph: FlowGraph, executors: ExecutorRegistry, options: RunOptions = {}) => {\n if (running) {\n return { ok: false, outputs: {}, error: \"another run is already in progress\" } satisfies RunResult;\n }\n const controller = new AbortController();\n abortRef.current = controller;\n // Reset previous statuses for the nodes we're about to run.\n const idleStatuses: Record<string, NodeRunStatus> = {};\n for (const n of graph.nodes) idleStatuses[n.id] = \"idle\";\n setStatuses(idleStatuses);\n setStatusText({});\n setOutputs({});\n setRunning(true);\n try {\n const result = await runFlow(graph, executors, handleEvent, { ...options, signal: controller.signal });\n setLastResult(result);\n return result;\n } finally {\n setRunning(false);\n abortRef.current = null;\n }\n },\n [handleEvent, running],\n );\n\n const cancel = useCallback(() => abortRef.current?.abort(), []);\n\n const reset = useCallback(() => {\n setStatuses({});\n setStatusText({});\n setOutputs({});\n setFeed([]);\n setLastResult(null);\n }, []);\n\n return { statuses, statusText, nodeMessages, outputs, feed, running, lastResult, run, cancel, reset };\n}\n\n/**\n * Write each reactive kind's latest run output into its `data.output`, so its\n * card can render the computed value live. Non-reactive kinds are returned\n * untouched. Pair with `applyStatusesToNodes` before rendering.\n */\nexport function applyOutputsToNodes<TNode extends { id: string; type?: string; data: any }>(\n nodes: TNode[],\n outputs: Record<string, unknown>,\n): TNode[] {\n return nodes.map((n) => {\n const kind = getNodeKind((n.data as any)?.kind ?? n.type ?? \"\");\n if (!kind?.reactive || !(n.id in outputs)) return n;\n return { ...n, data: { ...n.data, output: outputs[n.id] } };\n });\n}\n\n/** Merge runtime statuses into nodes for rendering. */\nexport function applyStatusesToNodes<TNode extends { id: string; data: any }>(\n nodes: TNode[],\n statuses: Record<string, NodeRunStatus>,\n statusText: Record<string, string | undefined>,\n): TNode[] {\n return nodes.map((n) => ({\n ...n,\n data: {\n ...n.data,\n status: statuses[n.id] ?? n.data?.status ?? \"idle\",\n statusText: statusText[n.id] ?? n.data?.statusText,\n },\n }));\n}\n\nfunction preview(v: unknown): string {\n try {\n const s = JSON.stringify(v);\n return s && s.length > 60 ? s.slice(0, 57) + \"…\" : (s ?? String(v));\n } catch {\n return String(v);\n }\n}\n","import { useCallback, useState } from \"react\";\nimport {\n addEdge,\n applyEdgeChanges,\n applyNodeChanges,\n type Connection,\n type Edge,\n type EdgeChange,\n type NodeChange,\n} from \"@xyflow/react\";\nimport type { FlowEdge, FlowGraph, FlowNode } from \"../types\";\n\nexport type UseFlowStateReturn = {\n nodes: FlowNode[];\n edges: FlowEdge[];\n setNodes: React.Dispatch<React.SetStateAction<FlowNode[]>>;\n setEdges: React.Dispatch<React.SetStateAction<FlowEdge[]>>;\n /**\n * Replace nodes AND edges atomically in a single commit. Use this for any op\n * that touches both (delete-with-edge-prune, undo/redo restore, setGraph):\n * calling `setNodes` then `setEdges` is NOT atomic in controlled mode (each\n * closes over a stale `value`), so the second write clobbers the first.\n */\n setGraph: (graph: FlowGraph) => void;\n onNodesChange: (changes: NodeChange[]) => void;\n onEdgesChange: (changes: EdgeChange[]) => void;\n onConnect: (connection: Connection) => void;\n /** Snapshot the current graph (suitable for serialization). */\n toGraph: () => FlowGraph;\n};\n\n/**\n * useFlowState — React Flow's standard controlled-state plumbing in one hook.\n * Spread into <FlowCanvas>.\n */\nexport function useFlowState(initial: FlowGraph): UseFlowStateReturn {\n const [nodes, setNodes] = useState<FlowNode[]>(initial.nodes);\n const [edges, setEdges] = useState<FlowEdge[]>(initial.edges);\n\n const onNodesChange = useCallback((changes: NodeChange[]) => {\n setNodes((ns) => applyNodeChanges(changes, ns) as FlowNode[]);\n }, []);\n const onEdgesChange = useCallback((changes: EdgeChange[]) => {\n setEdges((es) => applyEdgeChanges(changes, es));\n }, []);\n const onConnect = useCallback((connection: Connection) => {\n setEdges((es) => addEdge(connection, es) as Edge[]);\n }, []);\n\n const setGraph = useCallback((graph: FlowGraph) => {\n // Two useState writes in one event are batched, so this IS atomic here.\n setNodes(graph.nodes);\n setEdges(graph.edges);\n }, []);\n\n const toGraph = useCallback(() => ({ nodes, edges }), [nodes, edges]);\n\n return { nodes, edges, setNodes, setEdges, setGraph, onNodesChange, onEdgesChange, onConnect, toGraph };\n}\n","import type { FlowGraph } from \"../types\";\n\n/**\n * Undo/redo history — a pure, React-free snapshot controller. The editor pushes\n * a graph snapshot BEFORE each committing mutation; `undo`/`redo` swap snapshots\n * between the past/future stacks. Kept free of React so it can be unit-tested\n * and reused by any host (or a headless driver).\n *\n * Coalescing (collapsing a burst of setState calls from one logical op into a\n * single undo step) is the caller's job — see `useFlowHistory`.\n */\nexport type HistoryController = {\n /** Record `graph` as an undo point. Clears the redo stack (new branch). */\n push: (graph: FlowGraph) => void;\n /** Pop the last undo point; `current` is pushed onto the redo stack. */\n undo: (current: FlowGraph) => FlowGraph | null;\n /** Pop the last redo point; `current` is pushed back onto the undo stack. */\n redo: (current: FlowGraph) => FlowGraph | null;\n canUndo: () => boolean;\n canRedo: () => boolean;\n clear: () => void;\n /** Test/inspection helper — sizes of the two stacks. */\n size: () => { past: number; future: number };\n};\n\nexport function createHistory(limit = 100): HistoryController {\n let past: FlowGraph[] = [];\n let future: FlowGraph[] = [];\n\n return {\n push(graph) {\n past.push(graph);\n if (past.length > limit) past.shift();\n future = [];\n },\n undo(current) {\n const prev = past.pop();\n if (prev === undefined) return null;\n future.push(current);\n return prev;\n },\n redo(current) {\n const next = future.pop();\n if (next === undefined) return null;\n past.push(current);\n return next;\n },\n canUndo: () => past.length > 0,\n canRedo: () => future.length > 0,\n clear() {\n past = [];\n future = [];\n },\n size: () => ({ past: past.length, future: future.length }),\n };\n}\n","import { useCallback, useMemo, useRef, useState } from \"react\";\nimport type { EdgeChange, NodeChange } from \"@xyflow/react\";\nimport type { FlowGraph } from \"../types\";\nimport { createHistory } from \"./history\";\nimport type { UseFlowStateReturn } from \"./use-flow-state\";\n\nexport type UseFlowHistoryReturn = {\n /** The flow sink wrapped so committing mutations snapshot for undo first. */\n flow: UseFlowStateReturn;\n undo: () => void;\n redo: () => void;\n canUndo: boolean;\n canRedo: boolean;\n /** Snapshot the current graph as an undo point (before a programmatic edit). */\n capture: () => void;\n /** Wire to `<FlowCanvas onNodeDragStart>` — snapshots the pre-drag graph. */\n onNodeDragStart: () => void;\n};\n\n/**\n * useFlowHistory — the commit/undo pipeline. Wraps a flow sink (the uncontrolled\n * `useFlowState` hook OR the controlled adapter) so every *committing* mutation\n * records a snapshot first, giving undo/redo without the editor threading\n * history through each call site. This is the single interception point the\n * two-sink architecture otherwise lacks.\n *\n * Granularity: a burst of setState calls from one logical op (e.g. a\n * delete = setNodes+setEdges) is coalesced into ONE undo step; transient\n * interactive changes (drag-move, dimension-measure, selection) are NOT captured\n * — a drag is captured once at `onNodeDragStart` instead.\n */\nexport function useFlowHistory(flow: UseFlowStateReturn): UseFlowHistoryReturn {\n const history = useRef(createHistory()).current;\n const restoring = useRef(false);\n const coalesced = useRef(false);\n const [, bump] = useState(0);\n const rerender = useCallback(() => bump((n) => n + 1), []);\n\n // Latest graph via a ref, so capture never reads a stale snapshot.\n const graphRef = useRef<FlowGraph>({ nodes: flow.nodes, edges: flow.edges });\n graphRef.current = { nodes: flow.nodes, edges: flow.edges };\n\n const capture = useCallback(() => {\n if (restoring.current || coalesced.current) return;\n coalesced.current = true;\n queueMicrotask(() => {\n coalesced.current = false;\n });\n history.push(graphRef.current);\n rerender();\n }, [history, rerender]);\n\n const restore = useCallback(\n (g: FlowGraph | null) => {\n if (!g) return;\n restoring.current = true;\n flow.setGraph(g);\n queueMicrotask(() => {\n restoring.current = false;\n });\n rerender();\n },\n [flow, rerender],\n );\n\n const undo = useCallback(() => restore(history.undo(graphRef.current)), [history, restore]);\n const redo = useCallback(() => restore(history.redo(graphRef.current)), [history, restore]);\n\n const wrapped = useMemo<UseFlowStateReturn>(\n () => ({\n ...flow,\n setNodes: (next) => {\n capture();\n flow.setNodes(next);\n },\n setEdges: (next) => {\n capture();\n flow.setEdges(next);\n },\n setGraph: (g) => {\n capture();\n flow.setGraph(g);\n },\n onNodesChange: (changes: NodeChange[]) => {\n // Only structural removes commit; position/dimensions/select are transient.\n if (!restoring.current && changes.some((c) => c.type === \"remove\")) capture();\n flow.onNodesChange(changes);\n },\n onEdgesChange: (changes: EdgeChange[]) => {\n if (!restoring.current && changes.some((c) => c.type === \"remove\")) capture();\n flow.onEdgesChange(changes);\n },\n onConnect: (conn) => {\n capture();\n flow.onConnect(conn);\n },\n }),\n [flow, capture],\n );\n\n return {\n flow: wrapped,\n undo,\n redo,\n canUndo: history.canUndo(),\n canRedo: history.canRedo(),\n capture,\n onNodeDragStart: capture,\n };\n}\n"]}
|
package/dist/chunk-UM4C46AF.js
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
// src/expressions/expr.ts
|
|
2
|
-
function wholeExpression(trimmed) {
|
|
3
|
-
if (trimmed.length < 4) return null;
|
|
4
|
-
if (!trimmed.startsWith("{{") || !trimmed.endsWith("}}")) return null;
|
|
5
|
-
return trimmed.slice(2, -2);
|
|
6
|
-
}
|
|
7
|
-
function interpolate(template, resolve) {
|
|
8
|
-
let out = "";
|
|
9
|
-
let i = 0;
|
|
10
|
-
for (; ; ) {
|
|
11
|
-
const open = template.indexOf("{{", i);
|
|
12
|
-
if (open === -1) return out + template.slice(i);
|
|
13
|
-
const close = template.indexOf("}}", open + 2);
|
|
14
|
-
if (close === -1) return out + template.slice(i);
|
|
15
|
-
out += template.slice(i, open) + resolve(template.slice(open + 2, close));
|
|
16
|
-
i = close + 2;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
var FALSY_STRINGS = /* @__PURE__ */ new Set(["", "0", "false", "no", "off", "null"]);
|
|
20
|
-
var UnresolvedPathError = class extends Error {
|
|
21
|
-
constructor(path) {
|
|
22
|
-
super(
|
|
23
|
-
`Expression path "${path}" did not resolve. Under the "throw" policy an unresolvable path is an error rather than an empty string.`
|
|
24
|
-
);
|
|
25
|
-
this.path = path;
|
|
26
|
-
this.name = "UnresolvedPathError";
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
function tryResolvePath(path, context) {
|
|
30
|
-
const unresolved = { resolved: false, value: null };
|
|
31
|
-
const trimmed = path.trim();
|
|
32
|
-
if (trimmed === "") return unresolved;
|
|
33
|
-
const segments = trimmed.split(".");
|
|
34
|
-
let cursor;
|
|
35
|
-
const head = segments[0];
|
|
36
|
-
if (head === "$json" || head === "$input") {
|
|
37
|
-
cursor = context !== null && typeof context === "object" && "in" in context ? context.in : context;
|
|
38
|
-
segments.shift();
|
|
39
|
-
} else {
|
|
40
|
-
cursor = context;
|
|
41
|
-
}
|
|
42
|
-
for (const segment of segments) {
|
|
43
|
-
if (cursor === null || cursor === void 0) return unresolved;
|
|
44
|
-
if (typeof cursor !== "object") return unresolved;
|
|
45
|
-
const next = cursor[segment];
|
|
46
|
-
if (next === void 0) return unresolved;
|
|
47
|
-
cursor = next;
|
|
48
|
-
}
|
|
49
|
-
return { resolved: true, value: cursor === void 0 ? null : cursor };
|
|
50
|
-
}
|
|
51
|
-
function resolvePath(path, context) {
|
|
52
|
-
return tryResolvePath(path, context).value;
|
|
53
|
-
}
|
|
54
|
-
function evaluateExpression(template, context, options = {}) {
|
|
55
|
-
if (typeof template !== "string") return template;
|
|
56
|
-
const policy = options.onUnresolved ?? "empty";
|
|
57
|
-
const whole = wholeExpression(template.trim());
|
|
58
|
-
if (whole !== null) {
|
|
59
|
-
const r = tryResolvePath(whole, context);
|
|
60
|
-
if (r.resolved) return r.value;
|
|
61
|
-
if (policy === "throw") throw new UnresolvedPathError(whole);
|
|
62
|
-
return policy === "keep" ? template : null;
|
|
63
|
-
}
|
|
64
|
-
return interpolate(template, (path) => {
|
|
65
|
-
const r = tryResolvePath(path, context);
|
|
66
|
-
if (r.resolved) return stringify(r.value);
|
|
67
|
-
if (policy === "throw") throw new UnresolvedPathError(path);
|
|
68
|
-
return policy === "keep" ? `{{${path}}}` : "";
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
function truthy(value) {
|
|
72
|
-
if (typeof value === "boolean") return value;
|
|
73
|
-
if (value === null || value === void 0) return false;
|
|
74
|
-
if (typeof value === "string") return !FALSY_STRINGS.has(value.trim().toLowerCase());
|
|
75
|
-
if (Array.isArray(value)) return value.length > 0;
|
|
76
|
-
if (typeof value === "number") return value !== 0;
|
|
77
|
-
return Boolean(value);
|
|
78
|
-
}
|
|
79
|
-
function text(value) {
|
|
80
|
-
return stringify(value);
|
|
81
|
-
}
|
|
82
|
-
function stringify(value) {
|
|
83
|
-
if (typeof value === "string") return value;
|
|
84
|
-
if (typeof value === "boolean") return value ? "true" : "false";
|
|
85
|
-
if (value === null || value === void 0) return "";
|
|
86
|
-
if (typeof value === "number" || typeof value === "bigint") return String(value);
|
|
87
|
-
try {
|
|
88
|
-
return JSON.stringify(value) ?? "";
|
|
89
|
-
} catch {
|
|
90
|
-
return "";
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
function evaluateConfig(config, context, options = {}) {
|
|
94
|
-
const out = {};
|
|
95
|
-
for (const [key, value] of Object.entries(config)) {
|
|
96
|
-
out[key] = Array.isArray(value) ? value.map((v) => evaluateExpression(v, context, options)) : value !== null && typeof value === "object" ? evaluateConfig(value, context, options) : evaluateExpression(value, context, options);
|
|
97
|
-
}
|
|
98
|
-
return out;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export { UnresolvedPathError, evaluateConfig, evaluateExpression, resolvePath, text, truthy, tryResolvePath };
|
|
102
|
-
//# sourceMappingURL=chunk-UM4C46AF.js.map
|
|
103
|
-
//# sourceMappingURL=chunk-UM4C46AF.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/expressions/expr.ts"],"names":[],"mappings":"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","file":"chunk-UM4C46AF.js","sourcesContent":["/**\n * `{{ }}` resolution — the TypeScript twin of `FancyFlow\\Nodes\\Support\\Expr`.\n *\n * ## Why this is opt-in and not wired into `runFlow`\n *\n * The PHP runtime resolves expressions inside its batteries-included executors.\n * The JS runtime never has: `runFlow` hands `node.data.config` to your executor\n * verbatim, so every host that uses `{{ }}` today already resolves it itself.\n * Turning resolution on inside `runFlow` would interpolate a second time over\n * values those hosts had already substituted — silently, and only for graphs\n * that happen to contain `{{` in their DATA.\n *\n * So this exports the semantics and changes no behaviour. Call it yourself:\n *\n * ```ts\n * const url = evaluateExpression(node.data.config.url, inputs);\n * ```\n *\n * ## The semantics are the PHP file's, deliberately\n *\n * This is not a general expression language and must not grow into one. It\n * resolves a dot-path against a context and nothing else — no arithmetic, no\n * comparisons, no calls. Hosts that want real expressions override the executor\n * (the PHP docblock points at symfony/expression-language for the same reason).\n *\n * Divergence here is a correctness bug rather than a style difference: the same\n * graph is authored once and may run on either runtime. `suites/shared/expr`\n * in `@particle-academy/fancy-conformance` is the fixture table both sides run,\n * so parity is a test result instead of a claim.\n */\n\n/** Anything a context or a resolved value can be. */\nexport type ExprValue = unknown;\n\n/** The context an expression resolves against — the executor's `inputs`. */\nexport type ExprContext = Record<string, ExprValue>;\n\n/**\n * `{{ … }}` is parsed by SCANNING, not by a regular expression.\n *\n * Two CodeQL `js/polynomial-redos` alerts (#2, #3) came out of the regex\n * version, and the second survived the obvious fix — which is the useful part.\n * Dropping the ambiguous `\\s*` around the capture killed one witness\n * (`'{{{{' + ' '.repeat(n)`) and CodeQL immediately produced another\n * (`'{{{{a'` repeated). That is not a pattern bug: a GLOBAL lazy scan for a\n * delimiter that never arrives is quadratic by construction — O(n) starts, each\n * scanning O(n) forward — and no amount of tuning the pattern removes it.\n *\n * `indexOf` has no backtracking at all. Each character is visited a bounded\n * number of times, so this is linear by construction rather than by careful\n * pattern-writing, and there is no next witness to find.\n *\n * The behaviour is deliberately identical to the regexes it replaces, including\n * the odd corner: `{{a}}{{b}}` is a WHOLE expression whose path is `a}}{{b`\n * (which resolves to null), because the old pattern was `$`-anchored and its\n * lazy capture had to grow to reach the end. The PHP twin does the same, and\n * `shared/expr` is what holds the two together.\n */\n\n/** The inner text of a template that is exactly one expression, else `null`. */\nfunction wholeExpression(trimmed: string): string | null {\n if (trimmed.length < 4) return null;\n if (!trimmed.startsWith(\"{{\") || !trimmed.endsWith(\"}}\")) return null;\n return trimmed.slice(2, -2);\n}\n\n/**\n * Replace every `{{ … }}` run, left to right, in a single pass.\n *\n * An unterminated `{{` is literal text — the same thing the regex did by simply\n * not matching, and the case an author hits constantly while typing.\n */\nfunction interpolate(template: string, resolve: (path: string) => string): string {\n let out = \"\";\n let i = 0;\n\n for (;;) {\n const open = template.indexOf(\"{{\", i);\n if (open === -1) return out + template.slice(i);\n\n const close = template.indexOf(\"}}\", open + 2);\n if (close === -1) return out + template.slice(i);\n\n out += template.slice(i, open) + resolve(template.slice(open + 2, close));\n i = close + 2;\n }\n}\n\n/**\n * Strings PHP's `Expr::truthy` treats as false.\n *\n * `\"0\"` and `\"false\"` are the ones that matter: a branch condition arriving as\n * text from a form or a JSON body would otherwise be truthy for every non-empty\n * string, and `\"false\"` taking the true branch is the kind of bug that looks\n * like the engine is broken.\n */\nconst FALSY_STRINGS = new Set([\"\", \"0\", \"false\", \"no\", \"off\", \"null\"]);\n\n/**\n * What a resolution attempt ANSWERS — did the path resolve, and to what.\n *\n * `resolvePath` cannot express this, and that is the defect it exists to fix:\n * it returns `null` both for \"this path does not exist\" and for \"this path\n * exists and holds null\". One value standing for two states.\n *\n * At the interpolation layer the collapse is worse, because `null` stringifies\n * to `\"\"`. A consumer put it exactly:\n *\n * > \"An unresolvable path yields `''`, so a wrong field is indistinguishable\n * > from an empty one at runtime.\"\n *\n * A misspelled field renders as an empty string, which looks precisely like a\n * field that is legitimately empty. The graph runs, the node succeeds, and the\n * output is quietly missing a value nobody is told about — worst on\n * LLM-authored graphs, where the field name was guessed in the first place.\n *\n * Same shape as the four `??` collapses fixed across all four runtimes on\n * 2026-08-26 (absent vs null), one layer up: **presence is the only correct\n * test, and a return value that cannot express presence cannot be tested for\n * it.** Hence a second return channel rather than a cleverer sentinel — every\n * sentinel is a legal value for somebody.\n */\nexport interface Resolution {\n /** Whether the path resolved at all. `false` means it does not exist. */\n resolved: boolean;\n /** The value, when `resolved`. `null` when not — do not read it blind. */\n value: ExprValue;\n}\n\n/** Thrown by the `\"throw\"` policy when a path does not resolve. */\nexport class UnresolvedPathError extends Error {\n constructor(readonly path: string) {\n super(\n `Expression path \"${path}\" did not resolve. ` +\n `Under the \"throw\" policy an unresolvable path is an error rather than an empty string.`,\n );\n this.name = \"UnresolvedPathError\";\n }\n}\n\n/**\n * What evaluation does with a path that does not resolve.\n *\n * - `\"empty\"` — today's behaviour, and the DEFAULT. Interpolates to `\"\"`; a\n * whole expression yields `null`. Unchanged so that widening this API breaks\n * nobody: 40 call sites across the runtimes assume it.\n * - `\"keep\"` — leave the `{{ … }}` text in place. The failure becomes VISIBLE\n * in the output without stopping the run, which is what you want for\n * human-reviewed content: a rendered `{{ in.recipient_naem }}` is self-\n * diagnosing in a way an absence never is.\n * - `\"throw\"` — refuse. For hosts that would rather fail a run than deliver a\n * silently incomplete result.\n *\n * Opt-in before default at the request of the consumer who reported it — the\n * host with the most LLM-authored graphs, and so both the biggest beneficiary\n * and the right place for it to break first if it is going to.\n */\nexport type UnresolvedPolicy = \"empty\" | \"keep\" | \"throw\";\n\n/** Options for {@link evaluateExpression} / {@link evaluateConfig}. */\nexport interface EvaluateOptions {\n /** What to do with a path that does not resolve. Default `\"empty\"`. */\n onUnresolved?: UnresolvedPolicy;\n}\n\n/**\n * Resolve a dot-path, reporting WHETHER it resolved.\n *\n * The same walk as `resolvePath` — deliberately, so the two can never disagree\n * about what resolves; `resolvePath` is defined in terms of this one below.\n *\n * A note on JS having two absent values: a key present with the value\n * `undefined` reports `resolved: false`, matching `resolvePath`'s long-standing\n * behaviour. It cannot arise from graph data (JSON has no `undefined`), and\n * changing it would make the two functions disagree for no reachable gain.\n */\nexport function tryResolvePath(path: string, context: ExprContext): Resolution {\n const unresolved: Resolution = { resolved: false, value: null };\n\n const trimmed = path.trim();\n if (trimmed === \"\") return unresolved;\n\n const segments = trimmed.split(\".\");\n let cursor: ExprValue;\n\n const head = segments[0];\n if (head === \"$json\" || head === \"$input\") {\n cursor = context !== null && typeof context === \"object\" && \"in\" in context ? context.in : context;\n segments.shift();\n } else {\n cursor = context;\n }\n\n for (const segment of segments) {\n if (cursor === null || cursor === undefined) return unresolved;\n if (typeof cursor !== \"object\") return unresolved;\n // Arrays are indexed by their numeric keys, matching PHP's list access.\n const next = (cursor as Record<string, ExprValue>)[segment];\n if (next === undefined) return unresolved;\n cursor = next;\n }\n\n return { resolved: true, value: cursor === undefined ? null : cursor };\n}\n\n/**\n * Resolve a dot-path against the context, honouring the `$json` / `$input`\n * alias.\n *\n * Both aliases point at the `in` port value when the context has one, and at\n * the whole context otherwise — the same fallback the PHP does, which is what\n * makes `{{ $json.x }}` work on a trigger node that has no upstream input.\n *\n * A path that does not resolve returns `null`, never `undefined`: PHP has one\n * absent value and JS has two, and letting the difference leak would make the\n * two runtimes disagree about `{{ missing }}` for no useful reason.\n */\nexport function resolvePath(path: string, context: ExprContext): ExprValue {\n // Defined in terms of `tryResolvePath` rather than repeating the walk. Two\n // copies of a traversal agree right up until someone edits one of them, and\n // nothing anywhere reports that -- the same reason the shared conformance\n // tables exist instead of hand-copied fixture rows.\n return tryResolvePath(path, context).value;\n}\n\n/**\n * Evaluate a template against a context.\n *\n * A string that is EXACTLY one expression returns the resolved value with its\n * type intact — `{{ $json.count }}` gives you a number, not `\"3\"`. Anything\n * else interpolates each run as text. That distinction is load-bearing: it is\n * what lets a config field carry either a value or a sentence.\n *\n * Non-string templates pass through untouched, so this is safe to map over a\n * whole config object.\n */\nexport function evaluateExpression(\n template: ExprValue,\n context: ExprContext,\n options: EvaluateOptions = {},\n): ExprValue {\n if (typeof template !== \"string\") return template;\n\n const policy = options.onUnresolved ?? \"empty\";\n\n const whole = wholeExpression(template.trim());\n if (whole !== null) {\n const r = tryResolvePath(whole, context);\n if (r.resolved) return r.value;\n\n // The whole-expression branch returns `null` under `\"empty\"`, not `\"\"` --\n // that is what it has always done, and the asymmetry is deliberate: this\n // branch preserves TYPE, so its absent value is the typed one.\n if (policy === \"throw\") throw new UnresolvedPathError(whole);\n return policy === \"keep\" ? template : null;\n }\n\n return interpolate(template, (path) => {\n const r = tryResolvePath(path, context);\n if (r.resolved) return stringify(r.value);\n if (policy === \"throw\") throw new UnresolvedPathError(path);\n return policy === \"keep\" ? `{{${path}}}` : \"\";\n });\n}\n\n/**\n * Truthiness for branch / switch decisions.\n *\n * Mirrors PHP's rules rather than JavaScript's, because the graph is authored\n * once and may run on either side. The two disagree in exactly the places a\n * workflow hits: `\"0\"` and `\"false\"` are truthy in JS and falsy here, and an\n * empty array is truthy in JS and falsy here.\n */\nexport function truthy(value: ExprValue): boolean {\n if (typeof value === \"boolean\") return value;\n if (value === null || value === undefined) return false;\n if (typeof value === \"string\") return !FALSY_STRINGS.has(value.trim().toLowerCase());\n if (Array.isArray(value)) return value.length > 0;\n if (typeof value === \"number\") return value !== 0;\n return Boolean(value);\n}\n\n/** Coerce a value to text the way interpolation does. */\nexport function text(value: ExprValue): string {\n return stringify(value);\n}\n\nfunction stringify(value: ExprValue): string {\n if (typeof value === \"string\") return value;\n if (typeof value === \"boolean\") return value ? \"true\" : \"false\";\n if (value === null || value === undefined) return \"\";\n if (typeof value === \"number\" || typeof value === \"bigint\") return String(value);\n try {\n return JSON.stringify(value) ?? \"\";\n } catch {\n return \"\";\n }\n}\n\n/**\n * Resolve every string in a config object, one level of nesting at a time.\n *\n * The convenience most hosts actually want, and the shape their hand-rolled\n * version usually takes. Opt-in like the rest of this module.\n */\nexport function evaluateConfig<T extends Record<string, ExprValue>>(\n config: T,\n context: ExprContext,\n options: EvaluateOptions = {},\n): T {\n const out: Record<string, ExprValue> = {};\n for (const [key, value] of Object.entries(config)) {\n out[key] = Array.isArray(value)\n ? value.map((v) => evaluateExpression(v, context, options))\n : value !== null && typeof value === \"object\"\n ? evaluateConfig(value as Record<string, ExprValue>, context, options)\n : evaluateExpression(value, context, options);\n }\n return out as T;\n}\n"]}
|
package/dist/chunk-USL4FMFU.js
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
// src/registry/capabilities.ts
|
|
2
|
-
var llmClient = null;
|
|
3
|
-
function registerLlmClient(client) {
|
|
4
|
-
llmClient = client;
|
|
5
|
-
return () => {
|
|
6
|
-
if (llmClient === client) llmClient = null;
|
|
7
|
-
};
|
|
8
|
-
}
|
|
9
|
-
function getLlmClient() {
|
|
10
|
-
return llmClient;
|
|
11
|
-
}
|
|
12
|
-
function isResolutionFailure(value) {
|
|
13
|
-
return typeof value === "object" && value !== null && "reason" in value && value.reason !== void 0;
|
|
14
|
-
}
|
|
15
|
-
var workflowResolver = null;
|
|
16
|
-
function registerWorkflowResolver(resolver) {
|
|
17
|
-
workflowResolver = resolver;
|
|
18
|
-
return () => {
|
|
19
|
-
if (workflowResolver === resolver) workflowResolver = null;
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
function getWorkflowResolver() {
|
|
23
|
-
return workflowResolver;
|
|
24
|
-
}
|
|
25
|
-
function capabilityStatus() {
|
|
26
|
-
let documentReady = false;
|
|
27
|
-
try {
|
|
28
|
-
documentReady = Boolean(globalThis.__fancyFlowDocumentAdapter);
|
|
29
|
-
} catch {
|
|
30
|
-
documentReady = false;
|
|
31
|
-
}
|
|
32
|
-
return {
|
|
33
|
-
llm: llmClient !== null,
|
|
34
|
-
workflow_resolver: workflowResolver !== null,
|
|
35
|
-
document: documentReady
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export { capabilityStatus, getLlmClient, getWorkflowResolver, isResolutionFailure, registerLlmClient, registerWorkflowResolver };
|
|
40
|
-
//# sourceMappingURL=chunk-USL4FMFU.js.map
|
|
41
|
-
//# sourceMappingURL=chunk-USL4FMFU.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/registry/capabilities.ts"],"names":[],"mappings":";AAwDA,IAAI,SAAA,GAA8B,IAAA;AAG3B,SAAS,kBAAkB,MAAA,EAA+B;AAC/D,EAAA,SAAA,GAAY,MAAA;AACZ,EAAA,OAAO,MAAM;AACX,IAAA,IAAI,SAAA,KAAc,QAAQ,SAAA,GAAY,IAAA;AAAA,EACxC,CAAA;AACF;AAEO,SAAS,YAAA,GAAiC;AAC/C,EAAA,OAAO,SAAA;AACT;AAqDO,SAAS,oBAAoB,KAAA,EAA+D;AACjG,EAAA,OACE,OAAO,UAAU,QAAA,IACjB,KAAA,KAAU,QACV,QAAA,IAAY,KAAA,IACX,MAAoC,MAAA,KAAW,MAAA;AAEpD;AAEA,IAAI,gBAAA,GAA4C,IAAA;AAGzC,SAAS,yBAAyB,QAAA,EAAwC;AAC/E,EAAA,gBAAA,GAAmB,QAAA;AACnB,EAAA,OAAO,MAAM;AACX,IAAA,IAAI,gBAAA,KAAqB,UAAU,gBAAA,GAAmB,IAAA;AAAA,EACxD,CAAA;AACF;AAEO,SAAS,mBAAA,GAA+C;AAC7D,EAAA,OAAO,gBAAA;AACT;AAYO,SAAS,gBAAA,GAAkD;AAGhE,EAAA,IAAI,aAAA,GAAgB,KAAA;AACpB,EAAA,IAAI;AAEF,IAAA,aAAA,GAAgB,OAAA,CAAS,WAAmB,0BAA0B,CAAA;AAAA,EACxE,CAAA,CAAA,MAAQ;AACN,IAAA,aAAA,GAAgB,KAAA;AAAA,EAClB;AACA,EAAA,OAAO;AAAA,IACL,KAAK,SAAA,KAAc,IAAA;AAAA,IACnB,mBAAmB,gBAAA,KAAqB,IAAA;AAAA,IACxC,QAAA,EAAU;AAAA,GACZ;AACF","file":"chunk-USL4FMFU.js","sourcesContent":["import type { FlowGraph } from \"../types\";\n\n/**\n * Host capabilities — the services core nodes need but must never depend on.\n *\n * A node that imports a provider SDK forces every consumer to install it: a\n * workflow app that never calls a model should not inherit an LLM dependency.\n * So core declares the CONTRACT and the host supplies the implementation, the\n * same arrangement `renderDocumentField` already uses for documents.\n *\n * That keeps opinionated nodes in core without their opinions: `llm_branch`\n * ships the routing semantics, port derivation and config UI, while whichever\n * client the host registers — Prism, an OpenAI SDK, a local model, a fake in a\n * test — decides how the question actually gets asked.\n *\n * Registration is deliberately explicit and typed per capability rather than a\n * stringly-keyed bag, so a missing one is a clear error at the seam instead of\n * an undefined somewhere downstream.\n */\n\n// ── LLM ─────────────────────────────────────────────────────────────────────\n\nexport type LlmRoute = { port: string; description?: string };\n\nexport type LlmRouteRequest = {\n /** Optional framing for the decision. */\n system?: string;\n /** What the model is deciding about. */\n prompt: string;\n /** The ports it must choose between. */\n routes: LlmRoute[];\n provider?: string;\n model?: string;\n /** Host-resolved credential reference, never a raw key. */\n credential?: string;\n};\n\nexport type LlmRouteChoice = {\n /** Must be one of the requested route ports. */\n port: string;\n /** Why — carried down the chosen port so a run is explainable afterwards. */\n reason?: string;\n};\n\n/**\n * The only thing core asks of an LLM: given routes, pick one.\n *\n * Deliberately not a general chat interface. A narrow contract is one a host\n * can satisfy in a few lines over any SDK, and it keeps the choice\n * machine-checkable — an implementation should constrain the model to the\n * declared ports (structured output / enum) rather than parsing prose.\n */\nexport type LlmClient = {\n chooseRoute: (request: LlmRouteRequest) => Promise<LlmRouteChoice> | LlmRouteChoice;\n};\n\nlet llmClient: LlmClient | null = null;\n\n/** Install the host's LLM client. Returns an unregister function. */\nexport function registerLlmClient(client: LlmClient): () => void {\n llmClient = client;\n return () => {\n if (llmClient === client) llmClient = null;\n };\n}\n\nexport function getLlmClient(): LlmClient | null {\n return llmClient;\n}\n\n// ── Workflow resolution ─────────────────────────────────────────────────────\n\n/**\n * Why a workflow reference could not be resolved.\n *\n * `missing` and `version-mismatch` are deliberately distinct. Collapsing them\n * into a bare null makes \"no such workflow\" indistinguishable from \"that\n * workflow exists, but it is not the one you pinned\" — and the second wants an\n * error naming both versions, because it is the interesting failure.\n */\nexport type WorkflowResolutionFailure = {\n reason: \"missing\" | \"version-mismatch\";\n /** The version the host actually holds, when it holds one. */\n available?: number;\n message?: string;\n};\n\nexport type WorkflowResolution = FlowGraph | WorkflowResolutionFailure | null;\n\n/**\n * Resolve a workflow reference to a runnable graph.\n *\n * `subflow` names another workflow rather than embedding it, so the host owns\n * where workflows live — a database, a file, an API.\n *\n * ## Why `version` is here\n *\n * A workflow another workflow depends on is an INTERFACE, and interfaces need\n * pins. Without a version, a parent goes on calling `invoice-triage`, someone\n * edits that child, and the parent now runs different logic having reported\n * success the whole time — correct-looking, no error, wrong behaviour. The same\n * failure family as the 0.9.0 routing divergence.\n *\n * The parameter lives on the resolver rather than being encoded into the ref\n * string (`invoice-triage@3`) because a stringly-typed protocol is one every\n * host invents differently — the \"three vocabularies for one node\" problem.\n *\n * Raised by the MOIC Suite consumer, whose `workflow_ref` pins versions and\n * fails loudly on mismatch. Their point: a host COULD NOT implement pinning\n * before this, because the node had no way to ask and the resolver no way to\n * receive.\n *\n * Returning `null` still means \"no such workflow\". Return a\n * {@link WorkflowResolutionFailure} to distinguish a version mismatch.\n */\nexport type WorkflowResolver = (\n ref: string,\n version?: number,\n) => Promise<WorkflowResolution> | WorkflowResolution;\n\n/** Narrow a resolver's return value to an explicit failure. */\nexport function isResolutionFailure(value: WorkflowResolution): value is WorkflowResolutionFailure {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"reason\" in value &&\n (value as WorkflowResolutionFailure).reason !== undefined\n );\n}\n\nlet workflowResolver: WorkflowResolver | null = null;\n\n/** Install the host's workflow resolver. Returns an unregister function. */\nexport function registerWorkflowResolver(resolver: WorkflowResolver): () => void {\n workflowResolver = resolver;\n return () => {\n if (workflowResolver === resolver) workflowResolver = null;\n };\n}\n\nexport function getWorkflowResolver(): WorkflowResolver | null {\n return workflowResolver;\n}\n\n// ── Introspection ───────────────────────────────────────────────────────────\n\nexport type CapabilityId = \"llm\" | \"workflow_resolver\" | \"document\";\n\n/**\n * Which capabilities are currently satisfied.\n *\n * Exists so a host (or the CLI, or an agent over MCP) can answer \"what does\n * this graph need that I haven't wired?\" BEFORE a run fails halfway through.\n */\nexport function capabilityStatus(): Record<CapabilityId, boolean> {\n // Imported lazily to avoid dragging the React-dependent rich-input module\n // into the headless engine.\n let documentReady = false;\n try {\n // eslint-disable-next-line @typescript-eslint/no-var-requires, no-undef\n documentReady = Boolean((globalThis as any).__fancyFlowDocumentAdapter);\n } catch {\n documentReady = false;\n }\n return {\n llm: llmClient !== null,\n workflow_resolver: workflowResolver !== null,\n document: documentReady,\n };\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/schema/workflow-schema.ts"],"names":[],"mappings":"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","file":"chunk-W5DPKJY4.js","sourcesContent":["import type { FlowEdge, FlowGraph, FlowNode, PortDescriptor, WorkflowInput } from \"../types\";\nimport { checkGraphConnectivity } from \"../analysis/graph-connectivity\";\nimport { defaultConfigFor, getNodeKind, validateConfig } from \"../registry/registry\";\nimport { resolveNodePorts } from \"../registry/ports\";\n\n/** Schema version. Bump on breaking shape changes; add migrations as needed. */\nexport const WORKFLOW_SCHEMA_VERSION = 1 as const;\nexport const WORKFLOW_SCHEMA_URL = \"https://particle.academy/schemas/workflow/v1.json\";\n\nexport type WorkflowSchema = {\n $schema: typeof WORKFLOW_SCHEMA_URL;\n version: typeof WORKFLOW_SCHEMA_VERSION;\n metadata?: WorkflowMetadata;\n /**\n * What this workflow accepts at run start, passed BY NAME.\n *\n * Lives beside `graph` rather than inside it because it describes the\n * workflow's CONTRACT, not its topology: a caller reads this to know what to\n * pass, and reading it should not mean walking nodes looking for a trigger.\n *\n * Omitted entirely when a workflow takes none, so every existing saved\n * document is unchanged byte for byte.\n */\n inputs?: WorkflowInput[];\n graph: {\n nodes: WorkflowSchemaNode[];\n edges: WorkflowSchemaEdge[];\n };\n view?: {\n viewport?: { x: number; y: number; zoom: number };\n };\n};\n\nexport type WorkflowMetadata = {\n id?: string;\n name?: string;\n description?: string;\n createdAt?: number;\n updatedAt?: number;\n author?: string;\n tags?: string[];\n};\n\nexport type WorkflowSchemaNode = {\n id: string;\n /** Registry kind name (e.g. \"memory_store\"). */\n kind: string;\n position: { x: number; y: number };\n label?: string;\n description?: string;\n /**\n * Announced to a person just before / just after this node runs. Omitted\n * entirely when unset, so a graph of ordinary plumbing nodes does not carry\n * a pair of empty keys per node and every diff of a saved graph stays\n * readable.\n */\n startingMsg?: string;\n stoppingMsg?: string;\n config?: Record<string, unknown>;\n /**\n * Resolved ports, written on export.\n *\n * A kind may derive its ports from config (`switch_case` cases,\n * `llm_branch` routes), and that derivation is a JavaScript function — a\n * runtime in another language cannot execute it. Without the resolved ports\n * in the document, the PHP twin sees no declared outputs and falls back to a\n * single `out`, so every branch edge in an exported flow silently stops\n * firing. Serializing them keeps the schema self-describing and preserves\n * the cross-runtime guarantee: same JSON in, same routing out.\n *\n * Optional and additive — a hand-written schema may omit them, and each\n * runtime then falls back to its own kind registry.\n */\n inputs?: PortDescriptor[];\n outputs?: PortDescriptor[];\n /**\n * Visual layout — additive + optional. `parentId`/`extent` carry node grouping\n * (swimlanes / containers); `width`/`height` carry an explicit (resized) size;\n * `style` carries inline presentation. A runtime that only walks edges/ports\n * (e.g. the PHP twin) ignores all of these — they exist purely for the canvas,\n * so an older reader that doesn't know them simply drops them.\n */\n parentId?: string;\n extent?: \"parent\" | [[number, number], [number, number]];\n width?: number;\n height?: number;\n style?: Record<string, unknown>;\n};\n\nexport type WorkflowSchemaEdge = {\n id: string;\n source: string;\n target: string;\n sourceHandle?: string;\n targetHandle?: string;\n label?: string;\n};\n\nexport type ImportIssue = {\n level: \"error\" | \"warning\";\n nodeId?: string;\n edgeId?: string;\n message: string;\n};\n\nexport type ImportResult = {\n graph: FlowGraph;\n issues: ImportIssue[];\n /** True when the import produced a usable graph (errors may have been\n * rewritten to warnings via `lenient: true`). */\n ok: boolean;\n};\n\n/** Snapshot the in-memory graph as a portable WorkflowSchema. */\nexport function exportWorkflow(\n graph: FlowGraph,\n metadata?: WorkflowMetadata,\n view?: WorkflowSchema[\"view\"],\n): WorkflowSchema {\n return {\n $schema: WORKFLOW_SCHEMA_URL,\n version: WORKFLOW_SCHEMA_VERSION,\n metadata: metadata ? { ...metadata, updatedAt: Date.now() } : undefined,\n // Round-trips, or a saved workflow silently forgets its own contract and\n // every caller's props become \"unknown input\" on the next load.\n ...(graph.inputs && graph.inputs.length > 0 ? { inputs: graph.inputs } : {}),\n graph: {\n nodes: graph.nodes.map(toSchemaNode),\n edges: graph.edges.map(toSchemaEdge),\n },\n view,\n };\n}\n\nfunction toSchemaNode(n: FlowNode): WorkflowSchemaNode {\n const data: any = n.data ?? {};\n const kindName = data.kind ?? n.type ?? \"custom\";\n // Resolve through the same helper the canvas and runtime use, so a\n // config-driven kind writes its ACTUAL ports into the document instead of\n // leaving another language's runtime to guess at them.\n const ports = resolveNodePorts(n, getNodeKind(kindName) ?? undefined);\n const node = n as any;\n return {\n id: n.id,\n kind: kindName,\n position: { x: n.position.x, y: n.position.y },\n label: data.label,\n description: data.description,\n ...(typeof data.startingMsg === \"string\" && data.startingMsg !== \"\" ? { startingMsg: data.startingMsg } : {}),\n ...(typeof data.stoppingMsg === \"string\" && data.stoppingMsg !== \"\" ? { stoppingMsg: data.stoppingMsg } : {}),\n config: data.config,\n inputs: ports.inputs,\n outputs: ports.outputs,\n // Visual layout — only when explicitly set (never persist auto-`measured`\n // dimensions, which are derived, not authored).\n ...(node.parentId ? { parentId: node.parentId } : {}),\n ...(node.extent ? { extent: node.extent } : {}),\n ...(typeof node.width === \"number\" ? { width: node.width } : {}),\n ...(typeof node.height === \"number\" ? { height: node.height } : {}),\n ...(node.style ? { style: node.style } : {}),\n };\n}\n\nfunction toSchemaEdge(e: FlowEdge): WorkflowSchemaEdge {\n return {\n id: e.id,\n source: e.source,\n target: e.target,\n sourceHandle: e.sourceHandle ?? undefined,\n targetHandle: e.targetHandle ?? undefined,\n label: typeof e.label === \"string\" ? e.label : undefined,\n };\n}\n\nexport type ImportOptions = {\n /** When true, unknown kinds become warnings + a \"custom\" placeholder\n * instead of errors. Default false. */\n lenient?: boolean;\n};\n\n/** A migration step: takes a version-N document to version N+1. */\nexport type MigrationStep = (schema: Record<string, unknown>) => Record<string, unknown>;\n\n/**\n * Every migration step, keyed by the version it upgrades FROM.\n *\n * Empty today because v1 is current — when a BREAKING bump lands, add the step\n * here and every stored document upgrades on read, in this runtime and its\n * PHP and Python twins.\n */\nexport const MIGRATIONS: Record<number, MigrationStep> = {};\n\n/**\n * Migrate a raw schema object up to the current version, as far as it can go.\n *\n * Additive changes need no migration — an older document simply lacks the newer\n * optional fields. This is the seam for a future BREAKING bump, and\n * `importWorkflow` runs it before validating the version.\n *\n * ## The three rules, each with a reason\n *\n * - **A PAST version migrates forward**, step by step, to the current one.\n * - **A FUTURE version is left ALONE.** We cannot know what a later schema\n * means, and migrating downward would be guessing. Untouched hands it to the\n * version check, which reports it honestly.\n * - **A GAP in the table is left alone too.** A missing step is not a licence\n * to guess.\n *\n * ## Why `steps` is a parameter\n *\n * With only v1 in existence there is no old document to migrate, so a seam\n * tested against the built-in (empty) table is a check that CANNOT fail — it\n * would pass identically against a function that returned its input untouched,\n * which is what this was until the twins needed the same seam.\n *\n * The PHP and Python runtimes carry the identical shape. That mattered more\n * than it sounds: they had no migration at all and errored on any version\n * mismatch, so a v2 bump would have made every stored Op unreadable on exactly\n * the runtimes where durable runs resume.\n */\nexport function migrateSchema(\n schema: unknown,\n steps: Record<number, MigrationStep> = MIGRATIONS,\n): unknown {\n if (!schema || typeof schema !== \"object\") return schema;\n\n const doc = schema as Record<string, unknown>;\n let version = doc.version;\n\n if (typeof version !== \"number\" || !Number.isInteger(version) || version >= WORKFLOW_SCHEMA_VERSION) {\n return schema;\n }\n\n let out = doc;\n while (version < WORKFLOW_SCHEMA_VERSION) {\n const step = steps[version];\n if (!step) return out;\n\n out = step(out);\n version += 1;\n out.version = version;\n }\n\n return out;\n}\n\n/**\n * Hydrate a schema into runtime FlowGraph + validate kinds/configs against\n * the registry. Reports issues for unknown kinds, missing required config,\n * and dangling edges.\n */\nexport function importWorkflow(schema: unknown, options: ImportOptions = {}): ImportResult {\n const issues: ImportIssue[] = [];\n const lenient = options.lenient === true;\n schema = migrateSchema(schema);\n\n if (!schema || typeof schema !== \"object\") {\n return { ok: false, graph: { nodes: [], edges: [] }, issues: [{ level: \"error\", message: \"Schema is not an object.\" }] };\n }\n const s = schema as Partial<WorkflowSchema>;\n if (s.version !== WORKFLOW_SCHEMA_VERSION) {\n issues.push({\n level: lenient ? \"warning\" : \"error\",\n message: `Unsupported workflow schema version: ${s.version} (expected ${WORKFLOW_SCHEMA_VERSION})`,\n });\n if (!lenient) return { ok: false, graph: { nodes: [], edges: [] }, issues };\n }\n\n const rawNodes = s.graph?.nodes ?? [];\n const rawEdges = s.graph?.edges ?? [];\n\n const nodes: FlowNode[] = rawNodes.map((n) => {\n const kind = getNodeKind(n.kind);\n if (!kind) {\n issues.push({\n level: lenient ? \"warning\" : \"error\",\n nodeId: n.id,\n message: `Unknown kind \"${n.kind}\" — register it before importing.`,\n });\n }\n const config = n.config ?? (kind ? defaultConfigFor(kind) : {});\n if (kind) {\n for (const iss of validateConfig(kind, config)) {\n issues.push({ level: \"warning\", nodeId: n.id, message: `${iss.key}: ${iss.message}` });\n }\n }\n // Canonicalise on the way in: a document may carry a pre-namespace id, and\n // rewriting it here means the graph converges on the canonical id the next\n // time it is saved, rather than carrying the ambiguous name forever.\n const kindId = kind?.name ?? n.kind;\n return {\n id: n.id,\n type: kindId,\n position: { x: n.position?.x ?? 0, y: n.position?.y ?? 0 },\n // Rehydrate visual layout onto the node's top level (where xyflow reads it).\n ...(n.parentId ? { parentId: n.parentId } : {}),\n ...(n.extent ? { extent: n.extent } : {}),\n ...(typeof n.width === \"number\" ? { width: n.width } : {}),\n ...(typeof n.height === \"number\" ? { height: n.height } : {}),\n ...(n.style ? { style: n.style } : {}),\n data: {\n kind: kindId,\n label: n.label ?? kind?.label ?? n.kind,\n description: n.description,\n ...(n.startingMsg ? { startingMsg: n.startingMsg } : {}),\n ...(n.stoppingMsg ? { stoppingMsg: n.stoppingMsg } : {}),\n config,\n // Carry serialized ports back onto the node so a round-trip is stable\n // and an unknown kind still routes the way the document described.\n ...(n.inputs ? { inputs: n.inputs } : {}),\n ...(n.outputs ? { outputs: n.outputs } : {}),\n } as any,\n };\n });\n\n const nodeIds = new Set(nodes.map((n) => n.id));\n const edges: FlowEdge[] = rawEdges\n .map((e) => {\n if (!nodeIds.has(e.source)) {\n issues.push({ level: \"warning\", edgeId: e.id, message: `Edge source \"${e.source}\" not found.` });\n return null;\n }\n if (!nodeIds.has(e.target)) {\n issues.push({ level: \"warning\", edgeId: e.id, message: `Edge target \"${e.target}\" not found.` });\n return null;\n }\n return {\n id: e.id,\n source: e.source,\n target: e.target,\n sourceHandle: e.sourceHandle,\n targetHandle: e.targetHandle,\n label: e.label,\n } as FlowEdge;\n })\n .filter((e): e is FlowEdge => e !== null);\n\n // WIRING, not merely dataflow: a node no edge reaches and that reaches no\n // edge, and an edge reading from a node that publishes nothing.\n //\n // Deliberately AFTER the edge loop, so it sees the same edges the engine will\n // -- a dangling edge is dropped with a warning above, and running this first\n // would let a dropped edge count as a connection.\n //\n // Deliberately NOT gated on `lenient`. That flag is about unknown VOCABULARY\n // (a kind this host has not registered), never about wiring.\n issues.push(...checkGraphConnectivity({ nodes, edges }));\n\n const ok = issues.every((i) => i.level !== \"error\");\n // The declaration comes back with the graph. Dropping it on import would be\n // the worse half of losing it on export: the document still says what it\n // accepts, the loaded graph does not, and every prop a caller passes becomes\n // \"unknown input\" — an error pointing at the caller for a bug in the loader.\n const declaredInputs = Array.isArray(s.inputs)\n ? (s.inputs as WorkflowInput[]).filter(\n (input): input is WorkflowInput =>\n input !== null && typeof input === \"object\" && typeof (input as WorkflowInput).name === \"string\",\n )\n : undefined;\n\n return {\n ok,\n graph: {\n nodes,\n edges,\n ...(declaredInputs && declaredInputs.length > 0 ? { inputs: declaredInputs } : {}),\n },\n issues,\n };\n}\n\n/** Convenience: serialize a schema as a downloadable JSON Blob. */\nexport function workflowToBlob(schema: WorkflowSchema): Blob {\n return new Blob([JSON.stringify(schema, null, 2)], { type: \"application/json\" });\n}\n"]}
|