writer 0.8.3rc4__py3-none-any.whl → 1.25.1rc1__py3-none-any.whl
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.
- writer/__init__.py +1 -1
- writer/abstract.py +1 -1
- writer/{ai.py → ai/__init__.py} +867 -163
- writer/app_runner.py +596 -241
- writer/app_templates/default/.wf/components-blueprints_blueprint-0-0decp3w5erhvl0nw.jsonl +11 -0
- writer/app_templates/default/.wf/components-blueprints_root.jsonl +1 -0
- writer/app_templates/default/.wf/components-page-0-c0f99a9e-5004-4e75-a6c6-36f17490b134.jsonl +27 -0
- writer/app_templates/default/.wf/components-root.jsonl +1 -0
- writer/app_templates/default/.wf/components-workflows_root.jsonl +1 -0
- writer/app_templates/default/.wf/components-workflows_workflow-0-lfltcky7l1fsm6j2.jsonl +1 -0
- writer/app_templates/default/.wf/metadata.json +3 -0
- writer/app_templates/default/README.md +3 -0
- writer/app_templates/default/main.py +16 -0
- writer/app_templates/default/requirements.txt +1 -0
- writer/app_templates/default/static/README.md +8 -0
- writer/app_templates/default/static/agent_builder_demo.png +0 -0
- writer/app_templates/default/static/favicon.png +0 -0
- writer/app_templates/hello/.wf/components-blueprints_blueprint-0-t84xyhxau9ej3823.jsonl +18 -0
- writer/app_templates/hello/.wf/components-blueprints_root.jsonl +1 -0
- writer/app_templates/hello/.wf/components-page-0-c0f99a9e-5004-4e75-a6c6-36f17490b134.jsonl +15 -0
- writer/app_templates/hello/.wf/components-root.jsonl +1 -0
- writer/app_templates/hello/.wf/metadata.json +3 -0
- writer/app_templates/hello/main.py +16 -0
- writer/app_templates/hello/static/README.md +8 -0
- writer/app_templates/hello/static/favicon.png +0 -0
- writer/app_templates/hello/static/welcome.svg +40 -0
- writer/auth.py +7 -2
- writer/autogen.py +352 -0
- writer/blocks/__init__.py +51 -17
- writer/blocks/addtostatelist.py +10 -9
- writer/blocks/apitrigger.py +45 -0
- writer/blocks/base_block.py +332 -21
- writer/blocks/base_trigger.py +14 -0
- writer/blocks/calleventhandler.py +39 -35
- writer/blocks/changepage.py +48 -0
- writer/blocks/code.py +102 -0
- writer/blocks/crontrigger.py +49 -0
- writer/blocks/foreach.py +70 -53
- writer/blocks/httprequest.py +112 -99
- writer/blocks/ifelse.py +71 -0
- writer/blocks/logmessage.py +34 -39
- writer/blocks/parsejson.py +30 -29
- writer/blocks/returnvalue.py +7 -7
- writer/blocks/runblueprint.py +63 -0
- writer/blocks/setstate.py +43 -33
- writer/blocks/sharedblueprint.py +86 -0
- writer/blocks/uieventtrigger.py +49 -0
- writer/blocks/writeraddchatmessage.py +50 -12
- writer/blocks/writeraddtokg.py +38 -11
- writer/blocks/writeraskkg.py +123 -0
- writer/blocks/writerchat.py +80 -61
- writer/blocks/writerchatreply.py +279 -0
- writer/blocks/writerchatreplywithtoolconfig.py +393 -0
- writer/blocks/writerclassification.py +78 -39
- writer/blocks/writercompletion.py +49 -44
- writer/blocks/writerfileapi.py +85 -0
- writer/blocks/writerinitchat.py +24 -12
- writer/blocks/writerkeyvaluestorage.py +106 -0
- writer/blocks/writernocodeapp.py +35 -37
- writer/blocks/writerparsepdf.py +73 -0
- writer/blocks/writerstructuredoutput.py +105 -0
- writer/blocks/writertoolcalling.py +251 -0
- writer/blocks/writervision.py +141 -0
- writer/blocks/writerwebsearch.py +175 -0
- writer/blueprints.py +839 -0
- writer/command_line.py +52 -16
- writer/core.py +562 -290
- writer/core_ui.py +6 -2
- writer/evaluator.py +98 -46
- writer/journal.py +227 -0
- writer/keyvalue_storage.py +93 -0
- writer/logs.py +277 -0
- writer/serve.py +625 -327
- writer/ss_types.py +101 -12
- writer/static/assets/Arrow.dom-GBJpMYQS.js +1 -0
- writer/static/assets/BaseMarkdown-Wrvby5J8.js +1 -0
- writer/static/assets/BlueprintToolbar-BuXNRxWT.js +1 -0
- writer/static/assets/BlueprintToolbar-wpfX0jo_.css +1 -0
- writer/static/assets/BuilderApp-PTOI76jZ.js +8 -0
- writer/static/assets/BuilderApp-WimUfNZr.css +1 -0
- writer/static/assets/BuilderApplicationSelect-DXzy4e_h.js +7 -0
- writer/static/assets/BuilderApplicationSelect-XaM1D5fv.css +1 -0
- writer/static/assets/BuilderBlueprintLibraryPanel-Ckrhknlh.css +1 -0
- writer/static/assets/BuilderBlueprintLibraryPanel-DBDzhTlc.js +1 -0
- writer/static/assets/BuilderEmbeddedCodeEditor-B0bcjlhk.css +1 -0
- writer/static/assets/BuilderEmbeddedCodeEditor-Dn7eDICN.js +726 -0
- writer/static/assets/BuilderGraphSelect-C-LRsO8W.js +7 -0
- writer/static/assets/BuilderGraphSelect-D7B61d5s.css +1 -0
- writer/static/assets/BuilderInsertionLabel-BhyL9wgn.js +1 -0
- writer/static/assets/BuilderInsertionLabel-_YS5WPfq.css +1 -0
- writer/static/assets/BuilderInsertionOverlay-D2XS0ij9.css +1 -0
- writer/static/assets/BuilderInsertionOverlay-MkAIVruY.js +1 -0
- writer/static/assets/BuilderJournal-A0LcEwGI.js +7 -0
- writer/static/assets/BuilderJournal-DHv3Pvvm.css +1 -0
- writer/static/assets/BuilderModelSelect-CdSo_sih.js +7 -0
- writer/static/assets/BuilderModelSelect-Dc4IPLp2.css +1 -0
- writer/static/assets/BuilderSettings-BDwZBveu.js +16 -0
- writer/static/assets/BuilderSettings-lZkOXEYw.css +1 -0
- writer/static/assets/BuilderSettingsArtifactAPITriggerDetails-3O6jKBXD.js +4 -0
- writer/static/assets/BuilderSettingsArtifactAPITriggerDetails-DnX66iRg.css +1 -0
- writer/static/assets/BuilderSettingsDeploySharedBlueprint-BR_3ptsd.js +1 -0
- writer/static/assets/BuilderSettingsDeploySharedBlueprint-KJTl8gxP.css +1 -0
- writer/static/assets/BuilderSettingsHandlers-CBtEQFSo.js +1 -0
- writer/static/assets/BuilderSettingsHandlers-DJPeASfz.css +1 -0
- writer/static/assets/BuilderSidebarComponentTree-DLltgas5.js +1 -0
- writer/static/assets/BuilderSidebarComponentTree-DYu1F793.css +1 -0
- writer/static/assets/BuilderSidebarToolkit-CApZNTAq.js +7 -0
- writer/static/assets/BuilderSidebarToolkit-CwqbjRv8.css +1 -0
- writer/static/assets/BuilderTemplateEditor-CYSDeWgV.css +1 -0
- writer/static/assets/BuilderTemplateEditor-DnRDRcA0.js +87 -0
- writer/static/assets/BuilderVault-2vGoV0sx.js +1 -0
- writer/static/assets/BuilderVault-Cx6oQSES.css +1 -0
- writer/static/assets/ComponentRenderer-72hqvEvI.css +1 -0
- writer/static/assets/ComponentRenderer-D4Pj1i3s.js +1 -0
- writer/static/assets/SharedCopyClipboardButton-BipJKGtz.css +1 -0
- writer/static/assets/SharedCopyClipboardButton-DNI9kLe6.js +1 -0
- writer/static/assets/WdsCheckbox-DKvpPA4D.css +1 -0
- writer/static/assets/WdsCheckbox-edQcn1cf.js +1 -0
- writer/static/assets/WdsDropdownMenu-CzzPN9Wg.css +1 -0
- writer/static/assets/WdsDropdownMenu-DQnrRBNV.js +1 -0
- writer/static/assets/WdsFieldWrapper-Cmufx5Nj.js +1 -0
- writer/static/assets/WdsFieldWrapper-CsemOh8D.css +1 -0
- writer/static/assets/WdsTabs-DKj7BqI0.css +1 -0
- writer/static/assets/WdsTabs-DcfY_zn5.js +1 -0
- writer/static/assets/abap-D8nrxEjS.js +6 -0
- writer/static/assets/apex-BrXDlLUW.js +6 -0
- writer/static/assets/art-paper-D70v1WMA.svg +180 -0
- writer/static/assets/azcli-CElzELwZ.js +6 -0
- writer/static/assets/bat-CUsyEhik.js +6 -0
- writer/static/assets/bicep-BtxyJn6H.js +7 -0
- writer/static/assets/cameligo-ClBCoF8h.js +6 -0
- writer/static/assets/clojure-B9TqLHAk.js +6 -0
- writer/static/assets/codicon-BA2IlpFX.ttf +0 -0
- writer/static/assets/coffee-DYsfeylR.js +6 -0
- writer/static/assets/cpp-VVGvvgir.js +6 -0
- writer/static/assets/csharp-Z6z2stHy.js +6 -0
- writer/static/assets/csp-DgZoLDI1.js +6 -0
- writer/static/assets/css-KqQ96-gC.js +8 -0
- writer/static/assets/css.worker-DvNUQFd1.js +84 -0
- writer/static/assets/cssMode-BYq4oZGq.js +9 -0
- writer/static/assets/cypher-CYoSlgTu.js +6 -0
- writer/static/assets/dart-BGDl7St1.js +6 -0
- writer/static/assets/dockerfile-CuCtxA7T.js +6 -0
- writer/static/assets/ecl-BCTFAUpS.js +6 -0
- writer/static/assets/editor.worker-BVwmgLrR.js +11 -0
- writer/static/assets/elixir-C7hRTYZ9.js +6 -0
- writer/static/assets/flow9-Bi_qi707.js +6 -0
- writer/static/assets/freemarker2-CnNourkO.js +8 -0
- writer/static/assets/fsharp-CxaaEKKi.js +6 -0
- writer/static/assets/go-DUImKuGY.js +6 -0
- writer/static/assets/graphql-D5sGVkLV.js +6 -0
- writer/static/assets/handlebars-Bm22yapJ.js +6 -0
- writer/static/assets/hcl-zD_CCkZ1.js +6 -0
- writer/static/assets/html-CAKAfoZF.js +6 -0
- writer/static/assets/html.worker-BJMlcbMU.js +458 -0
- writer/static/assets/htmlMode-BGZ97n-V.js +9 -0
- writer/static/assets/index-5u5REPT4.js +16 -0
- writer/static/assets/index-BKNuk68o.css +1 -0
- writer/static/assets/index-BQNXU3IR.js +17 -0
- writer/static/assets/index-BQr1pfrb.js +1 -0
- writer/static/assets/index-DHXAd5Yn.js +4 -0
- writer/static/assets/index-Zki-pfO-.js +8525 -0
- writer/static/assets/index.esm-B1ZQtduY.js +17 -0
- writer/static/assets/ini-8kKHd4ZL.js +6 -0
- writer/static/assets/java-De1axCfe.js +6 -0
- writer/static/assets/javascript-X1f02eyK.js +6 -0
- writer/static/assets/json.worker-BwvX8PuZ.js +42 -0
- writer/static/assets/jsonMode-hT0bNgT8.js +11 -0
- writer/static/assets/julia-D3ApGBxz.js +6 -0
- writer/static/assets/kotlin-GbSrCElU.js +6 -0
- writer/static/assets/less-DNUaDNdz.js +7 -0
- writer/static/assets/lexon-Bg9QKxBu.js +6 -0
- writer/static/assets/liquid-KmCCiJw2.js +6 -0
- writer/static/assets/lua-Crkvc3mc.js +6 -0
- writer/static/assets/m3-DsrzVyM1.js +6 -0
- writer/static/assets/mapbox-gl-C0cyFYYW.js +2329 -0
- writer/static/assets/markdown-CY5IOZuu.js +6 -0
- writer/static/assets/marked.esm-273vDTCT.js +45 -0
- writer/static/assets/mdx-DtRFauUw.js +6 -0
- writer/static/assets/mips-BE8RsGBA.js +6 -0
- writer/static/assets/msdax-N5ajIiFQ.js +6 -0
- writer/static/assets/mysql-DRxbB97D.js +6 -0
- writer/static/assets/objective-c-BHUZy23s.js +6 -0
- writer/static/assets/pascal-BemVzBTY.js +6 -0
- writer/static/assets/pascaligo-BACCcnx_.js +6 -0
- writer/static/assets/pdf-B6-yWJ-Y.js +12 -0
- writer/static/assets/pdf.worker.min-CyUfim15.mjs +21 -0
- writer/static/assets/perl-CuU66Ptk.js +6 -0
- writer/static/assets/pgsql-CQ6TMH2r.js +6 -0
- writer/static/assets/php-BvyzZa65.js +6 -0
- writer/static/assets/pla-DrIuu9u1.js +6 -0
- writer/static/assets/plotly.min-DutuuatZ.js +4030 -0
- writer/static/assets/poppins-latin-300-italic-4WBEAciR.woff +0 -0
- writer/static/assets/poppins-latin-300-italic-EWCPeN2Y.woff2 +0 -0
- writer/static/assets/poppins-latin-300-normal-DCNuMXUj.woff +0 -0
- writer/static/assets/poppins-latin-300-normal-Dku2WoCh.woff2 +0 -0
- writer/static/assets/poppins-latin-400-italic-B4GYq972.woff2 +0 -0
- writer/static/assets/poppins-latin-400-italic-BPejoDS-.woff +0 -0
- writer/static/assets/poppins-latin-400-normal-BOb3E3N0.woff +0 -0
- writer/static/assets/poppins-latin-400-normal-cpxAROuN.woff2 +0 -0
- writer/static/assets/poppins-latin-500-italic-Ce_qjtl5.woff +0 -0
- writer/static/assets/poppins-latin-500-italic-o28Otv0U.woff2 +0 -0
- writer/static/assets/poppins-latin-500-normal-C8OXljZJ.woff2 +0 -0
- writer/static/assets/poppins-latin-500-normal-DGXqpDMm.woff +0 -0
- writer/static/assets/poppins-latin-600-italic-BhOZippK.woff +0 -0
- writer/static/assets/poppins-latin-600-italic-CZ4wqKBi.woff2 +0 -0
- writer/static/assets/poppins-latin-600-normal-BJdTmd5m.woff +0 -0
- writer/static/assets/poppins-latin-600-normal-zEkxB9Mr.woff2 +0 -0
- writer/static/assets/poppins-latin-700-italic-CW91C-LJ.woff +0 -0
- writer/static/assets/poppins-latin-700-italic-RKf6esGj.woff2 +0 -0
- writer/static/assets/poppins-latin-700-normal-BVuQR_eA.woff +0 -0
- writer/static/assets/poppins-latin-700-normal-Qrb0O0WB.woff2 +0 -0
- writer/static/assets/poppins-latin-ext-300-italic-CBzyU4Pf.woff +0 -0
- writer/static/assets/poppins-latin-ext-300-italic-DdDvTq5-.woff2 +0 -0
- writer/static/assets/poppins-latin-ext-300-normal-7Zg2msWE.woff2 +0 -0
- writer/static/assets/poppins-latin-ext-300-normal-C9p7gvmA.woff +0 -0
- writer/static/assets/poppins-latin-ext-400-italic-BiCGV3eO.woff2 +0 -0
- writer/static/assets/poppins-latin-ext-400-italic-gsPYOGqV.woff +0 -0
- writer/static/assets/poppins-latin-ext-400-normal-CIpeJEZw.woff2 +0 -0
- writer/static/assets/poppins-latin-ext-400-normal-Ce_uWq1Z.woff +0 -0
- writer/static/assets/poppins-latin-ext-500-italic-CwrTHwbn.woff2 +0 -0
- writer/static/assets/poppins-latin-ext-500-italic-jdc8Bv4M.woff +0 -0
- writer/static/assets/poppins-latin-ext-500-normal-Bl1-S02S.woff +0 -0
- writer/static/assets/poppins-latin-ext-500-normal-H4Q0z8D2.woff2 +0 -0
- writer/static/assets/poppins-latin-ext-600-italic-BqeDa496.woff2 +0 -0
- writer/static/assets/poppins-latin-ext-600-italic-C7MQPb_A.woff +0 -0
- writer/static/assets/poppins-latin-ext-600-normal-Cn4C8475.woff2 +0 -0
- writer/static/assets/poppins-latin-ext-600-normal-DB6FJURc.woff +0 -0
- writer/static/assets/poppins-latin-ext-700-italic-BAdhB_WS.woff2 +0 -0
- writer/static/assets/poppins-latin-ext-700-italic-WKTwQMp8.woff +0 -0
- writer/static/assets/poppins-latin-ext-700-normal-CE2WFKmF.woff +0 -0
- writer/static/assets/poppins-latin-ext-700-normal-DDaViAzG.woff2 +0 -0
- writer/static/assets/postiats-BR_hrfni.js +6 -0
- writer/static/assets/powerquery-CKDUeRmd.js +6 -0
- writer/static/assets/powershell-Dsa4rhA_.js +6 -0
- writer/static/assets/protobuf-CGsvhooB.js +7 -0
- writer/static/assets/pug-D2p3uOX2.js +6 -0
- writer/static/assets/python-DVhxg746.js +6 -0
- writer/static/assets/qsharp-B7F3HtPF.js +6 -0
- writer/static/assets/r-3aLoi2fs.js +6 -0
- writer/static/assets/razor-DR5Ns_BC.js +6 -0
- writer/static/assets/redis-jqFeRM5s.js +6 -0
- writer/static/assets/redshift-BriwQgXR.js +6 -0
- writer/static/assets/restructuredtext-hbBFZ0w9.js +6 -0
- writer/static/assets/ruby-ByThyB2Q.js +6 -0
- writer/static/assets/rust-DIEZMp5R.js +6 -0
- writer/static/assets/sb-C6Gjjw_x.js +6 -0
- writer/static/assets/scala-DZNw3jJB.js +6 -0
- writer/static/assets/scheme-55eqh71t.js +6 -0
- writer/static/assets/scss-D-OVkc4F.js +8 -0
- writer/static/assets/serialization-DJC7NP0N.js +20 -0
- writer/static/assets/shell-DSpi8_qN.js +6 -0
- writer/static/assets/solidity-BHddiNFS.js +6 -0
- writer/static/assets/sophia-D6taVZFb.js +6 -0
- writer/static/assets/sparql-LA0C7mUc.js +6 -0
- writer/static/assets/sql-C3-3IcFM.js +6 -0
- writer/static/assets/st-C4g7059C.js +6 -0
- writer/static/assets/swift-DNI1vH3h.js +8 -0
- writer/static/assets/systemverilog-DL_FVbcQ.js +6 -0
- writer/static/assets/tcl-DVJXmIwd.js +6 -0
- writer/static/assets/ts.worker-CwG1rUES.js +37021 -0
- writer/static/assets/tsMode-BNUEZzir.js +16 -0
- writer/static/assets/twig-BVWDLtw5.js +6 -0
- writer/static/assets/typescript-CRVt7Hx0.js +6 -0
- writer/static/assets/useBlueprintRun-C00bCxh-.js +1 -0
- writer/static/assets/useKeyValueEditor-nDmI7cTJ.js +1 -0
- writer/static/assets/useListResources-DLkZhRSJ.js +1 -0
- writer/static/assets/vb-Btz91-7U.js +6 -0
- writer/static/assets/vega-embed.module-SNP5iNdJ.js +201 -0
- writer/static/assets/wgsl-D8V_buCG.js +303 -0
- writer/static/assets/xml-C_6-t1tb.js +6 -0
- writer/static/assets/yaml-DIw8G7jk.js +6 -0
- writer/static/components/annotatedtext.svg +4 -0
- writer/static/components/avatar.svg +4 -0
- writer/static/components/blueprints_addtostatelist.svg +4 -0
- writer/static/components/blueprints_apitrigger.svg +4 -0
- writer/static/components/blueprints_calleventhandler.svg +9 -0
- writer/static/components/blueprints_category_Logic.svg +4 -0
- writer/static/components/blueprints_category_Other.svg +4 -0
- writer/static/components/blueprints_category_Triggers.svg +4 -0
- writer/static/components/blueprints_category_Writer.svg +25 -0
- writer/static/components/blueprints_code.svg +9 -0
- writer/static/components/blueprints_crontrigger.svg +6 -0
- writer/static/components/blueprints_foreach.svg +4 -0
- writer/static/components/blueprints_httprequest.svg +11 -0
- writer/static/components/blueprints_logmessage.svg +11 -0
- writer/static/components/blueprints_parsejson.svg +4 -0
- writer/static/components/blueprints_returnvalue.svg +4 -0
- writer/static/components/blueprints_runblueprint.svg +4 -0
- writer/static/components/blueprints_setstate.svg +4 -0
- writer/static/components/blueprints_uieventtrigger.svg +4 -0
- writer/static/components/blueprints_writeraddchatmessage.svg +19 -0
- writer/static/components/blueprints_writeraddtokg.svg +19 -0
- writer/static/components/blueprints_writerchat.svg +11 -0
- writer/static/components/blueprints_writerchatreply.svg +19 -0
- writer/static/components/blueprints_writerclassification.svg +24 -0
- writer/static/components/blueprints_writercompletion.svg +14 -0
- writer/static/components/blueprints_writerinitchat.svg +11 -0
- writer/static/components/blueprints_writernocodeapp.svg +14 -0
- writer/static/components/button.svg +4 -0
- writer/static/components/category_Content.svg +4 -0
- writer/static/components/category_Embed.svg +4 -0
- writer/static/components/category_Input.svg +5 -0
- writer/static/components/category_Layout.svg +9 -0
- writer/static/components/category_Other.svg +4 -0
- writer/static/components/chatbot.svg +4 -0
- writer/static/components/checkboxinput.svg +4 -0
- writer/static/components/colorinput.svg +11 -0
- writer/static/components/column.svg +4 -0
- writer/static/components/columns.svg +4 -0
- writer/static/components/dataframe.svg +4 -0
- writer/static/components/dateinput.svg +4 -0
- writer/static/components/dropdowninput.svg +5 -0
- writer/static/components/fileinput.svg +4 -0
- writer/static/components/googlemaps.svg +4 -0
- writer/static/components/header.svg +4 -0
- writer/static/components/heading.svg +9 -0
- writer/static/components/horizontalstack.svg +4 -0
- writer/static/components/html.svg +9 -0
- writer/static/components/icon.svg +4 -0
- writer/static/components/iframe.svg +4 -0
- writer/static/components/image.svg +11 -0
- writer/static/components/jsonviewer.svg +4 -0
- writer/static/components/link.svg +12 -0
- writer/static/components/mapbox.svg +4 -0
- writer/static/components/message.svg +4 -0
- writer/static/components/metric.svg +4 -0
- writer/static/components/multiselectinput.svg +4 -0
- writer/static/components/numberinput.svg +4 -0
- writer/static/components/page.svg +50 -0
- writer/static/components/pagination.svg +4 -0
- writer/static/components/pdf.svg +4 -0
- writer/static/components/plotlygraph.svg +7 -0
- writer/static/components/progressbar.svg +5 -0
- writer/static/components/radioinput.svg +4 -0
- writer/static/components/rangeinput.svg +4 -0
- writer/static/components/ratinginput.svg +4 -0
- writer/static/components/repeater.svg +4 -0
- writer/static/components/reuse.svg +4 -0
- writer/static/components/section.svg +4 -0
- writer/static/components/selectinput.svg +5 -0
- writer/static/components/separator.svg +4 -0
- writer/static/components/sidebar.svg +4 -0
- writer/static/components/sliderinput.svg +4 -0
- writer/static/components/step.svg +4 -0
- writer/static/components/steps.svg +4 -0
- writer/static/components/switchinput.svg +4 -0
- writer/static/components/tab.svg +4 -0
- writer/static/components/tabs.svg +4 -0
- writer/static/components/tags.svg +11 -0
- writer/static/components/text.svg +4 -0
- writer/static/components/textareainput.svg +11 -0
- writer/static/components/textinput.svg +4 -0
- writer/static/components/timeinput.svg +4 -0
- writer/static/components/timer.svg +4 -0
- writer/static/components/vegalitechart.svg +7 -0
- writer/static/components/videoplayer.svg +11 -0
- writer/static/components/webcamcapture.svg +4 -0
- writer/static/favicon.png +0 -0
- writer/static/index.html +84 -0
- writer/static/status/cancelled.svg +5 -0
- writer/static/status/error.svg +5 -0
- writer/static/status/skipped.svg +4 -0
- writer/static/status/stopped.svg +4 -0
- writer/static/status/success.svg +4 -0
- writer/sync.py +431 -0
- writer/ui.py +2268 -0
- writer/vault.py +48 -0
- writer/wf_project.py +90 -66
- writer-1.25.1rc1.dist-info/METADATA +92 -0
- writer-1.25.1rc1.dist-info/RECORD +382 -0
- {writer-0.8.3rc4.dist-info → writer-1.25.1rc1.dist-info}/WHEEL +1 -1
- writer/blocks/runworkflow.py +0 -59
- writer/workflows.py +0 -183
- writer-0.8.3rc4.dist-info/METADATA +0 -117
- writer-0.8.3rc4.dist-info/RECORD +0 -44
- {writer-0.8.3rc4.dist-info → writer-1.25.1rc1.dist-info}/entry_points.txt +0 -0
- {writer-0.8.3rc4.dist-info → writer-1.25.1rc1.dist-info/licenses}/LICENSE.txt +0 -0
writer/blocks/base_block.py
CHANGED
|
@@ -1,42 +1,76 @@
|
|
|
1
|
-
from typing import TYPE_CHECKING, Any, Dict, Type
|
|
1
|
+
from typing import TYPE_CHECKING, Any, Dict, Optional, Type
|
|
2
2
|
|
|
3
|
+
import httpx
|
|
4
|
+
from writerai import DefaultHttpxClient, Writer
|
|
5
|
+
|
|
6
|
+
import writer.core_ui
|
|
3
7
|
import writer.evaluator
|
|
4
8
|
from writer.ss_types import WriterConfigurationError
|
|
5
9
|
|
|
6
10
|
if TYPE_CHECKING:
|
|
11
|
+
from writer.blueprints import BlueprintRunner
|
|
7
12
|
from writer.core_ui import Component
|
|
8
13
|
from writer.ss_types import InstancePath
|
|
9
|
-
from writer.workflows import WorkflowRunner
|
|
10
14
|
|
|
11
|
-
|
|
12
|
-
block_map:Dict[str,
|
|
15
|
+
BlueprintBlock_T = Type["BlueprintBlock"]
|
|
16
|
+
block_map: Dict[str, BlueprintBlock_T] = {}
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class BlueprintBlock:
|
|
20
|
+
_parent_client_class = httpx.Client
|
|
21
|
+
_custom_httpx_client: Optional[httpx.Client] = None
|
|
22
|
+
_log_requests: bool = True
|
|
13
23
|
|
|
14
|
-
class WorkflowBlock:
|
|
15
|
-
|
|
16
24
|
@classmethod
|
|
17
25
|
def register(cls, type: str):
|
|
18
26
|
block_map[type] = cls
|
|
19
27
|
|
|
20
|
-
def
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
28
|
+
def __init_subclass__(
|
|
29
|
+
cls,
|
|
30
|
+
custom_httpx_client: Optional['httpx.Client'] = None,
|
|
31
|
+
log_requests: bool = True,
|
|
32
|
+
**kwargs
|
|
33
|
+
):
|
|
34
|
+
super().__init_subclass__(**kwargs)
|
|
35
|
+
cls._custom_httpx_client = custom_httpx_client
|
|
36
|
+
cls._log_requests = log_requests
|
|
37
|
+
|
|
38
|
+
def __init__(
|
|
39
|
+
self,
|
|
40
|
+
component: writer.core_ui.Component,
|
|
41
|
+
runner: "BlueprintRunner",
|
|
42
|
+
execution_environment: Dict,
|
|
43
|
+
):
|
|
44
|
+
self.outcome: Optional[str] = None
|
|
45
|
+
self.message: Optional[str] = None
|
|
46
|
+
self.component = component
|
|
24
47
|
self.runner = runner
|
|
25
48
|
self.execution_time_in_seconds = -1.0
|
|
49
|
+
self.started_at = -1.0
|
|
50
|
+
self.captured_stdout = ""
|
|
51
|
+
self.captured_logs = ""
|
|
26
52
|
self.execution_environment = execution_environment
|
|
53
|
+
# A stable snapshot of the execution environment taken after the block
|
|
54
|
+
# has finished running. Used when generating logs to avoid concurrent
|
|
55
|
+
# mutations while serialising.
|
|
56
|
+
self.execution_environment_snapshot: Optional[Dict] = None
|
|
27
57
|
self.result = None
|
|
28
58
|
self.return_value = None
|
|
29
|
-
self.instance_path: InstancePath = [{"componentId":
|
|
30
|
-
self.evaluator = writer.evaluator.Evaluator(
|
|
59
|
+
self.instance_path: InstancePath = [{"componentId": component.id, "instanceNumber": 0}]
|
|
60
|
+
self.evaluator = writer.evaluator.Evaluator(
|
|
61
|
+
runner.session.session_state, runner.session.session_component_tree
|
|
62
|
+
)
|
|
31
63
|
|
|
32
64
|
def _handle_missing_field(self, field_key):
|
|
33
|
-
|
|
34
|
-
component = component_tree.get_component(self.component_id)
|
|
35
|
-
field_content = component.content.get(field_key)
|
|
65
|
+
field_content = self.component.content.get(field_key)
|
|
36
66
|
if field_content:
|
|
37
|
-
raise WriterConfigurationError(
|
|
67
|
+
raise WriterConfigurationError(
|
|
68
|
+
f"The field `{field_key}` is required. The expression specified, `{field_content}`, resulted in an empty value."
|
|
69
|
+
)
|
|
38
70
|
else:
|
|
39
|
-
raise WriterConfigurationError(
|
|
71
|
+
raise WriterConfigurationError(
|
|
72
|
+
f"The field `{field_key}` is required. It was left empty."
|
|
73
|
+
)
|
|
40
74
|
|
|
41
75
|
def _get_field(self, field_key: str, as_json=False, default_field_value=None, required=False):
|
|
42
76
|
if default_field_value is None:
|
|
@@ -44,15 +78,292 @@ class WorkflowBlock:
|
|
|
44
78
|
default_field_value = "{}"
|
|
45
79
|
else:
|
|
46
80
|
default_field_value = ""
|
|
47
|
-
value = self.evaluator.evaluate_field(
|
|
81
|
+
value = self.evaluator.evaluate_field(
|
|
82
|
+
self.instance_path, field_key, as_json, default_field_value, self.execution_environment
|
|
83
|
+
)
|
|
48
84
|
|
|
49
85
|
if required and (value is None or value == "" or value == {}):
|
|
50
86
|
self._handle_missing_field(field_key)
|
|
51
|
-
|
|
87
|
+
|
|
52
88
|
return value
|
|
53
89
|
|
|
54
90
|
def _set_state(self, expr: str, value: Any):
|
|
55
|
-
self.evaluator.set_state(
|
|
91
|
+
self.evaluator.set_state(
|
|
92
|
+
expr, self.instance_path, value, base_context=self.execution_environment
|
|
93
|
+
)
|
|
56
94
|
|
|
57
95
|
def run(self):
|
|
58
|
-
pass
|
|
96
|
+
pass
|
|
97
|
+
|
|
98
|
+
def create_httpx_client(self, *args, **kwargs) -> httpx.Client:
|
|
99
|
+
"""
|
|
100
|
+
Create a custom HTTPX client with request and response logging.
|
|
101
|
+
"""
|
|
102
|
+
logger = self.create_logger() if self._log_requests else None
|
|
103
|
+
|
|
104
|
+
event_hooks = {
|
|
105
|
+
"request": [logger.request_hook] if logger else [],
|
|
106
|
+
"response": [logger.response_hook] if logger else [],
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
def send(self_inner, request, **kw):
|
|
110
|
+
response = self._parent_client_class.send(self_inner, request, **kw)
|
|
111
|
+
log_entry = response.extensions.get("log_entry")
|
|
112
|
+
if log_entry:
|
|
113
|
+
# Store reference to log entry for later update
|
|
114
|
+
response._log_entry_ref = log_entry
|
|
115
|
+
|
|
116
|
+
try:
|
|
117
|
+
# For non-streaming responses, capture content immediately
|
|
118
|
+
if response.is_closed or response.is_stream_consumed:
|
|
119
|
+
log_entry["response"]["content"] = response.text
|
|
120
|
+
else:
|
|
121
|
+
# For streaming responses, we'll update after consumption
|
|
122
|
+
log_entry["response"]["content"] = "<pending stream consumption>"
|
|
123
|
+
|
|
124
|
+
# Wrap the response read/iter methods to capture content after streaming
|
|
125
|
+
original_read = response.read
|
|
126
|
+
original_iter_raw = response.iter_raw
|
|
127
|
+
original_iter_bytes = response.iter_bytes
|
|
128
|
+
original_iter_text = response.iter_text
|
|
129
|
+
original_iter_lines = response.iter_lines
|
|
130
|
+
|
|
131
|
+
def wrapped_read():
|
|
132
|
+
try:
|
|
133
|
+
content = original_read()
|
|
134
|
+
except Exception as e:
|
|
135
|
+
if hasattr(response, '_log_entry_ref'):
|
|
136
|
+
response._log_entry_ref["response"]["content"] = f"<error reading response stream: {e}>"
|
|
137
|
+
raise
|
|
138
|
+
else:
|
|
139
|
+
if hasattr(response, '_log_entry_ref'):
|
|
140
|
+
try:
|
|
141
|
+
response._log_entry_ref["response"]["content"] = content.decode('utf-8', errors='replace')
|
|
142
|
+
except Exception:
|
|
143
|
+
response._log_entry_ref["response"]["content"] = "<binary content>"
|
|
144
|
+
return content
|
|
145
|
+
|
|
146
|
+
def wrapped_iter_raw(*args, **kwargs):
|
|
147
|
+
chunks = []
|
|
148
|
+
try:
|
|
149
|
+
for chunk in original_iter_raw(*args, **kwargs):
|
|
150
|
+
chunks.append(chunk)
|
|
151
|
+
yield chunk
|
|
152
|
+
finally:
|
|
153
|
+
if hasattr(response, '_log_entry_ref'):
|
|
154
|
+
try:
|
|
155
|
+
response._log_entry_ref["response"]["content"] = b"".join(chunks).decode("utf-8", errors="replace")
|
|
156
|
+
except Exception:
|
|
157
|
+
response._log_entry_ref["response"]["content"] = "<binary content>"
|
|
158
|
+
|
|
159
|
+
def wrapped_iter_bytes(*args, **kwargs):
|
|
160
|
+
accumulated_content = []
|
|
161
|
+
try:
|
|
162
|
+
for chunk in original_iter_bytes(*args, **kwargs):
|
|
163
|
+
accumulated_content.append(chunk)
|
|
164
|
+
yield chunk
|
|
165
|
+
finally:
|
|
166
|
+
if hasattr(response, '_log_entry_ref'):
|
|
167
|
+
try:
|
|
168
|
+
full_content = b''.join(accumulated_content)
|
|
169
|
+
response._log_entry_ref["response"]["content"] = full_content.decode('utf-8', errors='replace')
|
|
170
|
+
except Exception:
|
|
171
|
+
response._log_entry_ref["response"]["content"] = "<binary content>"
|
|
172
|
+
|
|
173
|
+
def wrapped_iter_text(*args, **kwargs):
|
|
174
|
+
text_chunks = []
|
|
175
|
+
try:
|
|
176
|
+
for chunk in original_iter_text(*args, **kwargs):
|
|
177
|
+
text_chunks.append(chunk)
|
|
178
|
+
yield chunk
|
|
179
|
+
finally:
|
|
180
|
+
if hasattr(response, '_log_entry_ref'):
|
|
181
|
+
response._log_entry_ref["response"]["content"] = ''.join(text_chunks)
|
|
182
|
+
|
|
183
|
+
def wrapped_iter_lines(*args, **kwargs):
|
|
184
|
+
lines = []
|
|
185
|
+
try:
|
|
186
|
+
for line in original_iter_lines(*args, **kwargs):
|
|
187
|
+
lines.append(line)
|
|
188
|
+
yield line
|
|
189
|
+
finally:
|
|
190
|
+
if hasattr(response, '_log_entry_ref'):
|
|
191
|
+
response._log_entry_ref["response"]["content"] = '\n'.join(lines)
|
|
192
|
+
|
|
193
|
+
response.read = wrapped_read
|
|
194
|
+
response.iter_raw = wrapped_iter_raw
|
|
195
|
+
response.iter_bytes = wrapped_iter_bytes
|
|
196
|
+
response.iter_text = wrapped_iter_text
|
|
197
|
+
response.iter_lines = wrapped_iter_lines
|
|
198
|
+
except Exception as e:
|
|
199
|
+
log_entry["response"]["content"] = f"<error reading response: {e}>"
|
|
200
|
+
return response
|
|
201
|
+
|
|
202
|
+
# Create a new class that inherits from the parent client class
|
|
203
|
+
# and overrides the send method to include logging.
|
|
204
|
+
LoggingHttpxClient = type(
|
|
205
|
+
"LoggingHttpxClient",
|
|
206
|
+
(self._parent_client_class,),
|
|
207
|
+
{"send": send}
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
return LoggingHttpxClient(
|
|
211
|
+
*args,
|
|
212
|
+
event_hooks=kwargs.pop("event_hooks", {}) | event_hooks,
|
|
213
|
+
**kwargs
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
def acquire_httpx_client(self) -> httpx.Client:
|
|
217
|
+
"""
|
|
218
|
+
Acquire an HTTPX client for making requests.
|
|
219
|
+
"""
|
|
220
|
+
if self._custom_httpx_client:
|
|
221
|
+
return self._custom_httpx_client
|
|
222
|
+
|
|
223
|
+
# Create a new HTTPX client with request and response logging
|
|
224
|
+
return self.create_httpx_client()
|
|
225
|
+
|
|
226
|
+
def create_logger(
|
|
227
|
+
self,
|
|
228
|
+
env_storage_key: Optional[str] = None
|
|
229
|
+
):
|
|
230
|
+
import uuid
|
|
231
|
+
instance_path = self.instance_path[0].get('componentId', None)
|
|
232
|
+
|
|
233
|
+
class ExecutionEnvironmentLogger:
|
|
234
|
+
"""
|
|
235
|
+
This class provides hooks to log requests and responses
|
|
236
|
+
to the execution environment.
|
|
237
|
+
"""
|
|
238
|
+
env_storage_key = 'httpx_requests'
|
|
239
|
+
|
|
240
|
+
def __init__(
|
|
241
|
+
self,
|
|
242
|
+
env: Dict,
|
|
243
|
+
env_storage_key: Optional[str] = None
|
|
244
|
+
):
|
|
245
|
+
self.env = env # Fallback environment
|
|
246
|
+
|
|
247
|
+
if env_storage_key:
|
|
248
|
+
self.env_storage_key = env_storage_key
|
|
249
|
+
|
|
250
|
+
# Create a copy of inherited API calls to avoid shared reference issues
|
|
251
|
+
inherited_calls = self.env.get(self.env_storage_key, [])
|
|
252
|
+
self.env[self.env_storage_key] = inherited_calls.copy()
|
|
253
|
+
self.instance_path = instance_path
|
|
254
|
+
|
|
255
|
+
def _get_current_execution_environment(self) -> Dict:
|
|
256
|
+
"""Resolve the currently executing block's environment for logging."""
|
|
257
|
+
try:
|
|
258
|
+
from writer.blueprints import get_current_block
|
|
259
|
+
current_block = get_current_block()
|
|
260
|
+
if current_block and hasattr(current_block, 'execution_environment'):
|
|
261
|
+
return current_block.execution_environment
|
|
262
|
+
except Exception:
|
|
263
|
+
pass
|
|
264
|
+
return self.env
|
|
265
|
+
|
|
266
|
+
def request_hook(self, request: httpx.Request):
|
|
267
|
+
import datetime as dt
|
|
268
|
+
request_id = str(uuid.uuid4())
|
|
269
|
+
|
|
270
|
+
# Get the current block's ID for accurate logging
|
|
271
|
+
current_block_id = self.instance_path # fallback (should be componentId)
|
|
272
|
+
try:
|
|
273
|
+
from writer.blueprints import get_current_block
|
|
274
|
+
current_block = get_current_block()
|
|
275
|
+
if current_block and hasattr(current_block, 'instance_path'):
|
|
276
|
+
# Extract componentId from the current block's instance path
|
|
277
|
+
current_block_id = current_block.instance_path[0].get('componentId', None)
|
|
278
|
+
except Exception:
|
|
279
|
+
pass
|
|
280
|
+
|
|
281
|
+
# Capture request content
|
|
282
|
+
content = None
|
|
283
|
+
if request.content:
|
|
284
|
+
try:
|
|
285
|
+
content = request.content.decode('utf-8', errors='replace')
|
|
286
|
+
except Exception:
|
|
287
|
+
content = "<binary content>"
|
|
288
|
+
elif request.stream:
|
|
289
|
+
# For streaming requests, we can't easily capture the content
|
|
290
|
+
# without consuming the stream
|
|
291
|
+
content = "<streaming request body>"
|
|
292
|
+
else:
|
|
293
|
+
content = None
|
|
294
|
+
|
|
295
|
+
log_entry = {
|
|
296
|
+
'id': request_id,
|
|
297
|
+
'created_at': dt.datetime.now(dt.timezone.utc).isoformat(),
|
|
298
|
+
'created_by': current_block_id,
|
|
299
|
+
'request': {
|
|
300
|
+
'method': request.method,
|
|
301
|
+
'url': str(request.url),
|
|
302
|
+
'headers': dict(request.headers),
|
|
303
|
+
'content': content
|
|
304
|
+
},
|
|
305
|
+
'response': None # Will populate later
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
# Resolve current block's environment for accurate logging
|
|
309
|
+
target_env = self._get_current_execution_environment()
|
|
310
|
+
target_env.setdefault(self.env_storage_key, []).append(log_entry)
|
|
311
|
+
request.extensions['log_entry'] = log_entry
|
|
312
|
+
|
|
313
|
+
def response_hook(self, response: httpx.Response):
|
|
314
|
+
log_entry = response.request.extensions.get('log_entry')
|
|
315
|
+
if not log_entry:
|
|
316
|
+
# Unlikely scenario
|
|
317
|
+
return
|
|
318
|
+
|
|
319
|
+
log_entry['response'] = {
|
|
320
|
+
'status_code': response.status_code,
|
|
321
|
+
'url': str(response.url),
|
|
322
|
+
'headers': dict(response.headers),
|
|
323
|
+
'content': None # Initially empty
|
|
324
|
+
}
|
|
325
|
+
response.extensions['log_entry'] = log_entry
|
|
326
|
+
|
|
327
|
+
return ExecutionEnvironmentLogger(
|
|
328
|
+
self.execution_environment,
|
|
329
|
+
env_storage_key=env_storage_key
|
|
330
|
+
)
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
class WriterBlock(BlueprintBlock):
|
|
334
|
+
"""
|
|
335
|
+
Base class for all Writer blocks.
|
|
336
|
+
"""
|
|
337
|
+
_parent_client_class = DefaultHttpxClient
|
|
338
|
+
|
|
339
|
+
def __init__(
|
|
340
|
+
self,
|
|
341
|
+
component: writer.core_ui.Component,
|
|
342
|
+
runner: "BlueprintRunner",
|
|
343
|
+
execution_environment: Dict,
|
|
344
|
+
):
|
|
345
|
+
super().__init__(component, runner, execution_environment)
|
|
346
|
+
|
|
347
|
+
# Initialize the SDK client via block property
|
|
348
|
+
# to set the context and enable logging for AI module downstream.
|
|
349
|
+
# This way, the AI module can use the same HTTPX client
|
|
350
|
+
# without explicitly passing it.
|
|
351
|
+
_ = self.writer_sdk_client
|
|
352
|
+
|
|
353
|
+
def _acquire_writer_client(
|
|
354
|
+
self,
|
|
355
|
+
force_new_client: Optional[bool] = False
|
|
356
|
+
) -> Writer:
|
|
357
|
+
from writer.ai import WriterAIManager
|
|
358
|
+
|
|
359
|
+
return WriterAIManager.acquire_client(
|
|
360
|
+
custom_httpx_client=self.acquire_httpx_client(),
|
|
361
|
+
force_new_client=force_new_client
|
|
362
|
+
)
|
|
363
|
+
|
|
364
|
+
def create_logger(self, env_storage_key: Optional[str] = "api_calls"):
|
|
365
|
+
return super().create_logger(env_storage_key=env_storage_key)
|
|
366
|
+
|
|
367
|
+
@property
|
|
368
|
+
def writer_sdk_client(self) -> Writer:
|
|
369
|
+
return self._acquire_writer_client()
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from writer.blocks.base_block import BlueprintBlock
|
|
2
|
+
from writer.ss_types import WriterConfigurationError
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class BlueprintTrigger(BlueprintBlock):
|
|
6
|
+
def run(self):
|
|
7
|
+
self.result = self.execution_environment.get("payload")
|
|
8
|
+
|
|
9
|
+
if not self.result:
|
|
10
|
+
try:
|
|
11
|
+
self.result = self._get_field("defaultResult", True, None)
|
|
12
|
+
except WriterConfigurationError:
|
|
13
|
+
self.result = self._get_field("defaultResult", False, None)
|
|
14
|
+
|
|
@@ -2,49 +2,52 @@ import inspect
|
|
|
2
2
|
|
|
3
3
|
import writer.core
|
|
4
4
|
from writer.abstract import register_abstract_template
|
|
5
|
-
from writer.blocks.base_block import
|
|
5
|
+
from writer.blocks.base_block import BlueprintBlock
|
|
6
6
|
from writer.ss_types import AbstractTemplate
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
class CallEventHandler(
|
|
10
|
-
|
|
9
|
+
class CallEventHandler(BlueprintBlock):
|
|
11
10
|
@classmethod
|
|
12
11
|
def register(cls, type: str):
|
|
13
12
|
super(CallEventHandler, cls).register(type)
|
|
14
|
-
register_abstract_template(
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
"
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
"name": "Success",
|
|
37
|
-
"description": "The event handler execution was successful.",
|
|
38
|
-
"style": "success",
|
|
13
|
+
register_abstract_template(
|
|
14
|
+
type,
|
|
15
|
+
AbstractTemplate(
|
|
16
|
+
baseType="blueprints_node",
|
|
17
|
+
writer={
|
|
18
|
+
"name": "Call event handler",
|
|
19
|
+
"description": "Executes an event handler.",
|
|
20
|
+
"category": "Logic",
|
|
21
|
+
"deprecated": True,
|
|
22
|
+
"fields": {
|
|
23
|
+
"name": {
|
|
24
|
+
"name": "Name",
|
|
25
|
+
"type": "Handler",
|
|
26
|
+
"desc": "The name of the event handling function.",
|
|
27
|
+
},
|
|
28
|
+
"additionalArgs": {
|
|
29
|
+
"name": "Additional arguments",
|
|
30
|
+
"init": '{ "my_arg": 2 }',
|
|
31
|
+
"type": "Object",
|
|
32
|
+
"control": "Textarea",
|
|
33
|
+
"default": "{}",
|
|
34
|
+
},
|
|
39
35
|
},
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
|
|
43
|
-
|
|
36
|
+
"outs": {
|
|
37
|
+
"success": {
|
|
38
|
+
"name": "Success",
|
|
39
|
+
"description": "The event handler execution was successful.",
|
|
40
|
+
"style": "success",
|
|
41
|
+
},
|
|
42
|
+
"error": {
|
|
43
|
+
"name": "Error",
|
|
44
|
+
"description": "The event handler execution wasn't successful.",
|
|
45
|
+
"style": "error",
|
|
46
|
+
},
|
|
44
47
|
},
|
|
45
48
|
},
|
|
46
|
-
|
|
47
|
-
)
|
|
49
|
+
),
|
|
50
|
+
)
|
|
48
51
|
|
|
49
52
|
def run(self):
|
|
50
53
|
try:
|
|
@@ -59,6 +62,7 @@ class CallEventHandler(WorkflowBlock):
|
|
|
59
62
|
"state": self.runner.session.session_state,
|
|
60
63
|
"context": self.execution_environment,
|
|
61
64
|
"session": writer.core._event_handler_session_info(),
|
|
65
|
+
"ui": writer.core._event_handler_ui_manager(),
|
|
62
66
|
} | additional_args
|
|
63
67
|
|
|
64
68
|
handler_args = inspect.getfullargspec(callable_handler).args
|
|
@@ -70,4 +74,4 @@ class CallEventHandler(WorkflowBlock):
|
|
|
70
74
|
self.outcome = "success"
|
|
71
75
|
except BaseException as e:
|
|
72
76
|
self.outcome = "error"
|
|
73
|
-
raise e
|
|
77
|
+
raise e
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
from writer.abstract import register_abstract_template
|
|
2
|
+
from writer.blocks.base_block import BlueprintBlock
|
|
3
|
+
from writer.ss_types import AbstractTemplate
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ChangePage(BlueprintBlock):
|
|
7
|
+
@classmethod
|
|
8
|
+
def register(cls, type: str):
|
|
9
|
+
super(ChangePage, cls).register(type)
|
|
10
|
+
register_abstract_template(
|
|
11
|
+
type,
|
|
12
|
+
AbstractTemplate(
|
|
13
|
+
baseType="blueprints_node",
|
|
14
|
+
writer={
|
|
15
|
+
"name": "Change page",
|
|
16
|
+
"description": "Navigates the user to another page in the app. Requires a valid page key.",
|
|
17
|
+
"category": "Other",
|
|
18
|
+
"fields": {
|
|
19
|
+
"pageKey": {
|
|
20
|
+
"name": "Page key",
|
|
21
|
+
"type": "Text",
|
|
22
|
+
"desc": "The identifying key of the target page.",
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
"outs": {
|
|
26
|
+
"success": {
|
|
27
|
+
"name": "Success",
|
|
28
|
+
"description": "The page change was successful.",
|
|
29
|
+
"style": "success",
|
|
30
|
+
},
|
|
31
|
+
"error": {
|
|
32
|
+
"name": "Error",
|
|
33
|
+
"description": "There was an error changing the page.",
|
|
34
|
+
"style": "error",
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
),
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
def run(self):
|
|
42
|
+
try:
|
|
43
|
+
page_key = self._get_field("pageKey", required=True)
|
|
44
|
+
self.runner.session.session_state.set_page(page_key)
|
|
45
|
+
self.outcome = "success"
|
|
46
|
+
except BaseException as e:
|
|
47
|
+
self.outcome = "error"
|
|
48
|
+
raise e
|
writer/blocks/code.py
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import sys
|
|
3
|
+
import traceback
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from writer.abstract import register_abstract_template
|
|
7
|
+
from writer.blocks.base_block import BlueprintBlock
|
|
8
|
+
from writer.logs import use_logging_redirect, use_stdout_redirect
|
|
9
|
+
from writer.ss_types import AbstractTemplate
|
|
10
|
+
|
|
11
|
+
exec_logger = logging.getLogger("exec_logger")
|
|
12
|
+
|
|
13
|
+
INIT_CODE = """
|
|
14
|
+
# State is accessible as a global variable. For example:
|
|
15
|
+
state["counter"] = 10
|
|
16
|
+
|
|
17
|
+
# Other variables from the execution environment are also available. For example:
|
|
18
|
+
result # Result from the execution of the last block
|
|
19
|
+
results # Dictionary with the execution results of each block, with the block id as key
|
|
20
|
+
payload # When executing via API or via an UI event with a payload
|
|
21
|
+
logger # logging.Logger object for capturing logs
|
|
22
|
+
|
|
23
|
+
# To set the output of this block, which will be available via result to the next block:
|
|
24
|
+
set_output("a sample result")
|
|
25
|
+
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class CodeBlock(BlueprintBlock):
|
|
30
|
+
@classmethod
|
|
31
|
+
def register(cls, type: str):
|
|
32
|
+
super(CodeBlock, cls).register(type)
|
|
33
|
+
register_abstract_template(
|
|
34
|
+
type,
|
|
35
|
+
AbstractTemplate(
|
|
36
|
+
baseType="blueprints_node",
|
|
37
|
+
writer={
|
|
38
|
+
"name": "Python code",
|
|
39
|
+
"description": "Runs custom Python code. Useful for logic not covered by existing blocks.",
|
|
40
|
+
"category": "Logic",
|
|
41
|
+
"fields": {
|
|
42
|
+
"code": {
|
|
43
|
+
"name": "Code",
|
|
44
|
+
"type": "Code",
|
|
45
|
+
"control": "Textarea",
|
|
46
|
+
"desc": "The code to be executed.",
|
|
47
|
+
"init": INIT_CODE,
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
"outs": {
|
|
51
|
+
"success": {
|
|
52
|
+
"name": "Success",
|
|
53
|
+
"description": "The code executed successfully.",
|
|
54
|
+
"style": "success",
|
|
55
|
+
},
|
|
56
|
+
"error": {
|
|
57
|
+
"name": "Error",
|
|
58
|
+
"description": "There was an error executing the code.",
|
|
59
|
+
"style": "error",
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
),
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
def set_output(self, output: Any):
|
|
67
|
+
self.result = output
|
|
68
|
+
|
|
69
|
+
def run(self):
|
|
70
|
+
try:
|
|
71
|
+
code = self._get_field("code")
|
|
72
|
+
self.result = None
|
|
73
|
+
|
|
74
|
+
writeruserapp = sys.modules.get("writeruserapp")
|
|
75
|
+
block_globals = (
|
|
76
|
+
self.execution_environment
|
|
77
|
+
| writeruserapp.__dict__
|
|
78
|
+
| {
|
|
79
|
+
"state": self.runner.session.session_state,
|
|
80
|
+
"set_output": self.set_output,
|
|
81
|
+
"logger": exec_logger,
|
|
82
|
+
}
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
with (
|
|
86
|
+
use_stdout_redirect([
|
|
87
|
+
lambda entry: self.runner.session.session_state.add_log_entry("info", "Captured stdout", entry),
|
|
88
|
+
lambda entry: setattr(self, 'captured_stdout', entry)
|
|
89
|
+
]),
|
|
90
|
+
use_logging_redirect([
|
|
91
|
+
lambda entry: self.runner.session.session_state.add_log_entry("info", "Captured logs", entry),
|
|
92
|
+
lambda entry: setattr(self, 'captured_logs', entry)
|
|
93
|
+
]),
|
|
94
|
+
):
|
|
95
|
+
exec(code, block_globals)
|
|
96
|
+
|
|
97
|
+
self.outcome = "success"
|
|
98
|
+
except BaseException as e:
|
|
99
|
+
self.outcome = "error"
|
|
100
|
+
# Wrap the message as a preformatted block to display as "raw" text in Markdown
|
|
101
|
+
self.message = f"<pre>{traceback.format_exc()}</pre>"
|
|
102
|
+
raise e
|