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/vault.py
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Writer Vault module for managing secret retrieval and caching.
|
|
3
|
+
|
|
4
|
+
This module provides the WriterVault class which handles fetching and caching
|
|
5
|
+
secrets from the Writer vault service, with support for environment-based
|
|
6
|
+
configuration and error handling.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import logging
|
|
10
|
+
from typing import Dict, Optional
|
|
11
|
+
|
|
12
|
+
import httpx
|
|
13
|
+
|
|
14
|
+
from writer.keyvalue_storage import writer_kv_storage
|
|
15
|
+
|
|
16
|
+
logger = logging.getLogger("vault")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class WriterVault:
|
|
20
|
+
"""Manages retrieval and caching of secrets from the Writer vault service."""
|
|
21
|
+
|
|
22
|
+
def __init__(self) -> None:
|
|
23
|
+
"""Initialize vault with empty cache."""
|
|
24
|
+
self.secrets: Optional[Dict] = None
|
|
25
|
+
|
|
26
|
+
def get_secrets(self) -> Dict:
|
|
27
|
+
"""Get cached secrets, fetching from vault if not already loaded."""
|
|
28
|
+
if self.secrets is None:
|
|
29
|
+
self.secrets = self._fetch()
|
|
30
|
+
return self.secrets
|
|
31
|
+
|
|
32
|
+
def refresh(self):
|
|
33
|
+
"""Force refresh of secrets from the vault service."""
|
|
34
|
+
self.secrets = self._fetch()
|
|
35
|
+
|
|
36
|
+
def _fetch(self) -> Dict:
|
|
37
|
+
try:
|
|
38
|
+
data = writer_kv_storage.get("vault", "secret")
|
|
39
|
+
secrets = data.get("secret")
|
|
40
|
+
if isinstance(secrets, dict):
|
|
41
|
+
return secrets
|
|
42
|
+
logger.warning("Invalid vault response format: expected dict in 'secret' field")
|
|
43
|
+
except (httpx.HTTPStatusError, ValueError) as e:
|
|
44
|
+
logger.error("Failed to fetch vault secrets: %s", e)
|
|
45
|
+
return {}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
writer_vault = WriterVault()
|
writer/wf_project.py
CHANGED
|
@@ -7,6 +7,7 @@ This module manipulates the folder of a wf project stored into `wf`.
|
|
|
7
7
|
"""
|
|
8
8
|
import dataclasses
|
|
9
9
|
import glob
|
|
10
|
+
import hashlib
|
|
10
11
|
import io
|
|
11
12
|
import json
|
|
12
13
|
import logging
|
|
@@ -22,17 +23,18 @@ from typing import Any, Dict, List, Tuple
|
|
|
22
23
|
from writer import core_ui
|
|
23
24
|
from writer.ss_types import ComponentDefinition, MetadataDefinition, SourceFilesDirectory
|
|
24
25
|
|
|
25
|
-
ROOTS = ['root', '
|
|
26
|
-
COMPONENT_ROOTS = ['page', '
|
|
26
|
+
ROOTS = ['root', 'blueprints_root']
|
|
27
|
+
COMPONENT_ROOTS = ['page', 'blueprints_blueprint']
|
|
27
28
|
|
|
28
29
|
shared_queue_write_files: typing.Optional[Queue] = None
|
|
29
30
|
|
|
30
31
|
@dataclasses.dataclass
|
|
31
32
|
class WfProjectContext:
|
|
32
33
|
app_path: str
|
|
33
|
-
write_files_async_queue: Queue = Queue
|
|
34
|
+
write_files_async_queue: Queue = dataclasses.field(default_factory=Queue)
|
|
34
35
|
write_files_async_process: typing.Optional[multiprocessing.Process] = None
|
|
35
|
-
write_files_async_stop: Any = multiprocessing.Event
|
|
36
|
+
write_files_async_stop: Any = dataclasses.field(default_factory=multiprocessing.Event) # Note: Event is a function, not a class in python, it can't be typed
|
|
37
|
+
file_hashes: Dict[str, str] = dataclasses.field(default_factory=dict)
|
|
36
38
|
|
|
37
39
|
|
|
38
40
|
def write_files_async(context: WfProjectContext, metadata: MetadataDefinition, components: Dict[str, ComponentDefinition]) -> None:
|
|
@@ -43,19 +45,26 @@ def write_files_async(context: WfProjectContext, metadata: MetadataDefinition, c
|
|
|
43
45
|
|
|
44
46
|
>>> wf_project.write_files_async('app/hello', metadata={"writer_version": "0.1" }, components=...)
|
|
45
47
|
"""
|
|
48
|
+
|
|
49
|
+
while not context.write_files_async_queue.empty():
|
|
50
|
+
try:
|
|
51
|
+
context.write_files_async_queue.get_nowait()
|
|
52
|
+
except queue.Empty:
|
|
53
|
+
break
|
|
54
|
+
|
|
46
55
|
context.write_files_async_queue.put((context.app_path, metadata, components))
|
|
47
56
|
|
|
48
|
-
def write_files(app_path: str, metadata: MetadataDefinition, components: Dict[str, ComponentDefinition]) -> None:
|
|
57
|
+
def write_files(app_path: str, metadata: MetadataDefinition, components: Dict[str, ComponentDefinition], context: WfProjectContext) -> None:
|
|
49
58
|
"""
|
|
50
59
|
Writes the meta data of the WF project to the `.wf` directory (metadata, components, ...).
|
|
51
60
|
|
|
52
61
|
* the metadata.json file is written in json format
|
|
53
62
|
* a file for the root component written in jsonline format
|
|
54
|
-
* a file for the
|
|
63
|
+
* a file for the blueprints_root component written in jsonline format
|
|
55
64
|
* one file per page is created in the form `components-page-{id}.json` in jsonline format
|
|
56
|
-
* one file per
|
|
65
|
+
* one file per blueprint is created in the form `components-blueprints_blueprint-{id}.json` in jsonline format
|
|
57
66
|
|
|
58
|
-
>>> wf_project.write_files('app/hello', metadata={"writer_version": "0.1" }, components
|
|
67
|
+
>>> wf_project.write_files('app/hello', metadata={"writer_version": "0.1" }, components=..., context=wf_project.WfProjectContext(app_path="app/path"))
|
|
59
68
|
"""
|
|
60
69
|
|
|
61
70
|
wf_directory = os.path.join(app_path, ".wf")
|
|
@@ -64,10 +73,16 @@ def write_files(app_path: str, metadata: MetadataDefinition, components: Dict[st
|
|
|
64
73
|
|
|
65
74
|
with io.open(os.path.join(wf_directory, "metadata.json"), "w") as f:
|
|
66
75
|
json.dump(metadata, f, indent=4)
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
76
|
+
f.flush()
|
|
77
|
+
os.fsync(f.fileno())
|
|
78
|
+
|
|
79
|
+
logger = logging.getLogger("writer")
|
|
80
|
+
time_start = time.time()
|
|
81
|
+
logger.info("Saving project...")
|
|
82
|
+
_write_root_files(wf_directory, components, context)
|
|
83
|
+
_write_component_files(wf_directory, components, context)
|
|
70
84
|
_remove_obsolete_component_files(wf_directory, components)
|
|
85
|
+
logger.info("Saved. Time elapsed: %.4fs", time.time() - time_start)
|
|
71
86
|
|
|
72
87
|
|
|
73
88
|
def start_process_write_files_async(context: WfProjectContext, save_interval: float) -> None:
|
|
@@ -103,13 +118,13 @@ def read_files(app_path: str) -> Tuple[MetadataDefinition, dict[str, ComponentDe
|
|
|
103
118
|
"""
|
|
104
119
|
Reads project files in the `.wf` folder.
|
|
105
120
|
|
|
106
|
-
The components are read in page and
|
|
121
|
+
The components are read in page and blueprints_blueprint order.
|
|
107
122
|
|
|
108
123
|
>>> metadata, components = wf_project.read_files('app/hello')
|
|
109
124
|
"""
|
|
110
125
|
components: dict[str, ComponentDefinition] = {}
|
|
111
|
-
roots = ['root', '
|
|
112
|
-
component_part_file_type = ['page', '
|
|
126
|
+
roots = ['root', 'blueprints_root']
|
|
127
|
+
component_part_file_type = ['page', 'blueprints_blueprint']
|
|
113
128
|
|
|
114
129
|
meta_data_path = os.path.join(app_path, ".wf", "metadata.json")
|
|
115
130
|
try:
|
|
@@ -148,36 +163,13 @@ def read_files(app_path: str) -> Tuple[MetadataDefinition, dict[str, ComponentDe
|
|
|
148
163
|
return metadata, components
|
|
149
164
|
|
|
150
165
|
|
|
151
|
-
def
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
The ui.json file is removed after the migration.
|
|
156
|
-
|
|
157
|
-
>>> wf_project.migrate_obsolete_ui_json('app/hello')
|
|
158
|
-
"""
|
|
159
|
-
assert os.path.isfile(os.path.join(app_path, "ui.json")), f"ui.json file required for migration into {app_path}"
|
|
160
|
-
|
|
161
|
-
logger = logging.getLogger('writer')
|
|
162
|
-
with io.open(os.path.join(app_path, "ui.json"), "r") as f:
|
|
163
|
-
parsed_file = json.load(f)
|
|
164
|
-
|
|
165
|
-
if not isinstance(parsed_file, dict):
|
|
166
|
-
raise ValueError("No dictionary found in components file.")
|
|
167
|
-
|
|
168
|
-
file_payload = parsed_file
|
|
169
|
-
# metadata = file_payload.get("metadata", {})
|
|
170
|
-
components = file_payload.get("components", {})
|
|
171
|
-
write_files(app_path, metadata, components)
|
|
172
|
-
os.remove(os.path.join(app_path, "ui.json"))
|
|
173
|
-
logger.warning('project format has changed and has been migrated with success. ui.json file has been removed.')
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
def create_default_workflows_root(abs_path: str) -> None:
|
|
177
|
-
with io.open(os.path.join(abs_path, '.wf', 'components-workflows_root.jsonl'), 'w') as f:
|
|
178
|
-
f.write('{"id": "workflows_root", "type": "workflows_root", "content": {}, "isCodeManaged": false, "position": 0, "handlers": {}, "visible": {"expression": true, "binding": "", "reversed": false}}')
|
|
166
|
+
def create_default_blueprints_root(abs_path: str) -> None:
|
|
167
|
+
with io.open(os.path.join(abs_path, '.wf', 'components-blueprints_root.jsonl'), 'w') as f:
|
|
168
|
+
f.write('{"id": "blueprints_root", "type": "blueprints_root", "content": {}, "isCodeManaged": false, "position": 0, "handlers": {}, "visible": {"expression": true, "binding": "", "reversed": false}}')
|
|
179
169
|
logger = logging.getLogger('writer')
|
|
180
|
-
logger.warning('project format has changed and has been migrated with success. components-
|
|
170
|
+
logger.warning('project format has changed and has been migrated with success. components-blueprints_root.jsonl has been added.')
|
|
171
|
+
f.flush()
|
|
172
|
+
os.fsync(f.fileno())
|
|
181
173
|
|
|
182
174
|
|
|
183
175
|
def _expected_component_fileinfos(components: dict[str, ComponentDefinition]) -> List[Tuple[str, str]]:
|
|
@@ -238,7 +230,7 @@ def _sort_wf_component_keys(obj: typing.Union[ComponentDefinition, dict]) -> Any
|
|
|
238
230
|
return OrderedDict((k, _sort_wf_component_keys(v)) for k, v in sorted_items)
|
|
239
231
|
|
|
240
232
|
|
|
241
|
-
def _write_component_files(wf_directory: str, components: Dict[str, ComponentDefinition]) -> None:
|
|
233
|
+
def _write_component_files(wf_directory: str, components: Dict[str, ComponentDefinition], context: WfProjectContext) -> None:
|
|
242
234
|
"""
|
|
243
235
|
Writes the component files in the .wf folder. It preserve obsolete files.
|
|
244
236
|
|
|
@@ -247,17 +239,48 @@ def _write_component_files(wf_directory: str, components: Dict[str, ComponentDef
|
|
|
247
239
|
for component_id, filename in _expected_component_fileinfos(components):
|
|
248
240
|
filtered_components = core_ui.filter_components_by(components, parent=component_id)
|
|
249
241
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
242
|
+
file_path = os.path.join(wf_directory, filename)
|
|
243
|
+
file_contents = "".join(
|
|
244
|
+
[json.dumps(_sort_wf_component_keys(p)) + "\n" for p in _order_components(filtered_components)]
|
|
245
|
+
)
|
|
253
246
|
|
|
247
|
+
has_changed = _has_file_hash_changed(filename, file_contents, context)
|
|
248
|
+
if not has_changed:
|
|
249
|
+
continue
|
|
250
|
+
|
|
251
|
+
with io.open(file_path, "w") as f:
|
|
252
|
+
f.write(file_contents)
|
|
253
|
+
f.flush()
|
|
254
|
+
os.fsync(f.fileno())
|
|
254
255
|
|
|
255
|
-
|
|
256
|
+
|
|
257
|
+
def _write_root_files(wf_directory, components, context: WfProjectContext):
|
|
256
258
|
for root in ROOTS:
|
|
257
259
|
root_component = components.get(root, None)
|
|
258
260
|
if root_component:
|
|
261
|
+
file_contents = json.dumps(_sort_wf_component_keys(root_component))
|
|
262
|
+
|
|
263
|
+
has_changed = _has_file_hash_changed(f"components-{root}.jsonl", file_contents, context)
|
|
264
|
+
if not has_changed:
|
|
265
|
+
continue
|
|
266
|
+
|
|
259
267
|
with io.open(os.path.join(wf_directory, f"components-{root}.jsonl"), "w") as f:
|
|
260
|
-
f.write(
|
|
268
|
+
f.write(file_contents)
|
|
269
|
+
f.flush()
|
|
270
|
+
os.fsync(f.fileno())
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
def _has_file_hash_changed(file_name: str, new_contents: str, context: WfProjectContext) -> bool:
|
|
274
|
+
"""
|
|
275
|
+
Returns whether a hash of a file changed given new file contents;
|
|
276
|
+
|
|
277
|
+
Missing file counts as hash invalidation and return True.
|
|
278
|
+
"""
|
|
279
|
+
new_hash = hashlib.md5(new_contents.encode('utf-8')).hexdigest()
|
|
280
|
+
|
|
281
|
+
old_hash = context.file_hashes.get(file_name)
|
|
282
|
+
context.file_hashes[file_name] = new_hash
|
|
283
|
+
return old_hash != new_hash
|
|
261
284
|
|
|
262
285
|
|
|
263
286
|
def _order_components(components: Dict[str, ComponentDefinition]) -> List[ComponentDefinition]:
|
|
@@ -290,7 +313,7 @@ def _start_process_write_files_async_process(context: WfProjectContext, save_int
|
|
|
290
313
|
|
|
291
314
|
if obj is not None:
|
|
292
315
|
app_path, metadata, components = obj
|
|
293
|
-
write_files(app_path, metadata, components)
|
|
316
|
+
write_files(app_path, metadata, components, context)
|
|
294
317
|
|
|
295
318
|
time.sleep(save_interval)
|
|
296
319
|
|
|
@@ -303,9 +326,8 @@ def is_project(path: str) -> bool:
|
|
|
303
326
|
"""
|
|
304
327
|
has_main_py = os.path.isfile(os.path.join(path, "main.py"))
|
|
305
328
|
has_wf_directory = os.path.isdir(os.path.join(path, ".wf"))
|
|
306
|
-
has_ui_json_file = os.path.isfile(os.path.join(path, "ui.json"))
|
|
307
329
|
|
|
308
|
-
return has_main_py and
|
|
330
|
+
return has_main_py and has_wf_directory
|
|
309
331
|
|
|
310
332
|
|
|
311
333
|
def can_create_project(path: str) -> bool:
|
|
@@ -340,26 +362,25 @@ def build_source_files(app_path: str) -> SourceFilesDirectory:
|
|
|
340
362
|
with open(path, "r", encoding='utf-8') as f:
|
|
341
363
|
return f.read()
|
|
342
364
|
|
|
365
|
+
|
|
366
|
+
ignore_dirs = ['.venv', 'venv', '__pycache__', '.wf']
|
|
367
|
+
ignore_files = ['.DS_Store']
|
|
343
368
|
files = []
|
|
344
369
|
for root, dirs, filenames in os.walk(app_path):
|
|
345
|
-
|
|
346
|
-
dirs[:] = [d for d in dirs if d not in {'.venv', 'venv', '__pycache__', '.wf'}]
|
|
370
|
+
dirs[:] = [d for d in dirs if d not in ignore_dirs]
|
|
347
371
|
for filename in filenames:
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
file_tree: SourceFilesDirectory = {
|
|
351
|
-
"type": "directory",
|
|
352
|
-
"children": {}
|
|
353
|
-
}
|
|
372
|
+
if filename not in ignore_files:
|
|
373
|
+
files.append(os.path.realpath(os.path.join(root, filename)))
|
|
354
374
|
|
|
375
|
+
file_tree: SourceFilesDirectory = { "type": "directory", "children": {} }
|
|
355
376
|
|
|
356
377
|
for file in files:
|
|
357
378
|
relative_path = os.path.relpath(file, app_path)
|
|
358
379
|
parts = relative_path.split(os.sep)
|
|
359
380
|
current_level: SourceFilesDirectory = file_tree
|
|
360
381
|
|
|
361
|
-
for part in parts:
|
|
362
|
-
if os.path.isdir(os.path.join(app_path, *parts[:
|
|
382
|
+
for i, part in enumerate(parts):
|
|
383
|
+
if os.path.isdir(os.path.join(app_path, *parts[: i + 1])):
|
|
363
384
|
if part not in current_level["children"]:
|
|
364
385
|
current_level["children"][part] = { "type": "directory", "children": {} }
|
|
365
386
|
|
|
@@ -372,13 +393,16 @@ def build_source_files(app_path: str) -> SourceFilesDirectory:
|
|
|
372
393
|
content = load_persisted_script(relative_path)
|
|
373
394
|
extension = os.path.splitext(relative_path)[1]
|
|
374
395
|
# limit only the first 100 characters to limit bandwidth usage, the rest will be lazy loaded
|
|
375
|
-
|
|
396
|
+
excerpt = content if extension == '.py' else content[0:100]
|
|
376
397
|
current_level["children"][part] = {
|
|
377
398
|
"type": "file",
|
|
378
|
-
"content":
|
|
379
|
-
"complete":
|
|
399
|
+
"content": excerpt,
|
|
400
|
+
"complete": excerpt == content,
|
|
380
401
|
}
|
|
381
|
-
except
|
|
402
|
+
except UnicodeDecodeError:
|
|
403
|
+
# TODO: get mimetype
|
|
404
|
+
current_level["children"][part] = { "type": "binary" }
|
|
405
|
+
except FileNotFoundError:
|
|
382
406
|
pass
|
|
383
407
|
|
|
384
408
|
return file_tree
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: writer
|
|
3
|
+
Version: 1.25.1rc1
|
|
4
|
+
Summary: An open-source, Python framework for building feature-rich apps that are fully integrated with the Writer platform.
|
|
5
|
+
License-File: LICENSE.txt
|
|
6
|
+
Keywords: data apps,gui,ui,framework,writer framework
|
|
7
|
+
Author: Writer, Inc.
|
|
8
|
+
Requires-Python: >=3.9.2,<4.0
|
|
9
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Provides-Extra: redis
|
|
18
|
+
Requires-Dist: authlib (>=1.3.0,<1.7)
|
|
19
|
+
Requires-Dist: click (>=8.1.7,<9.0.0)
|
|
20
|
+
Requires-Dist: fastapi (>=0.89.1,<1)
|
|
21
|
+
Requires-Dist: gitignore-parser (>=0.1.11,<0.2.0)
|
|
22
|
+
Requires-Dist: jinja2 (>=3.1.4,<4.0.0)
|
|
23
|
+
Requires-Dist: numpy (<=2.0.2) ; python_version < "3.10"
|
|
24
|
+
Requires-Dist: numpy (>=2.0,<3.0) ; python_version >= "3.10"
|
|
25
|
+
Requires-Dist: orjson (>=3.11.0,<4.0.0)
|
|
26
|
+
Requires-Dist: pandas (>=2.2.0,<3)
|
|
27
|
+
Requires-Dist: plotly (>=5.24.1,<6.0.0)
|
|
28
|
+
Requires-Dist: pyarrow (>=15.0.0,<19.0.0)
|
|
29
|
+
Requires-Dist: pydantic (>=2.6.0,<3)
|
|
30
|
+
Requires-Dist: python-dateutil (>=2.9.0.post0,<3.0.0)
|
|
31
|
+
Requires-Dist: python-multipart (>=0.0.7,<1)
|
|
32
|
+
Requires-Dist: pytz (>=2024.1,<2025.0)
|
|
33
|
+
Requires-Dist: requests (>=2.31.0,<2.33)
|
|
34
|
+
Requires-Dist: uvicorn (>=0.20.0,<1)
|
|
35
|
+
Requires-Dist: watchdog (>=3.0.0,<4)
|
|
36
|
+
Requires-Dist: websockets (>=12,<16)
|
|
37
|
+
Requires-Dist: writer-sdk (>=2.3.1,<3)
|
|
38
|
+
Project-URL: Documentation, https://dev.writer.com/framework
|
|
39
|
+
Project-URL: Homepage, https://www.writer.com
|
|
40
|
+
Project-URL: Repository, https://github.com/writer/writer-framework
|
|
41
|
+
Description-Content-Type: text/markdown
|
|
42
|
+
|
|
43
|
+
## What is Writer Framework?
|
|
44
|
+
|
|
45
|
+
Writer Framework is an open-source framework for creating AI applications. Build user interfaces using a visual editor; write the backend code in Python.
|
|
46
|
+
|
|
47
|
+
Writer Framework is fast and flexible with a clean, easily-testable syntax. It provides separation of concerns between UI and business logic, enabling more complex applications.
|
|
48
|
+
|
|
49
|
+
## Quick Start
|
|
50
|
+
|
|
51
|
+
### Installation
|
|
52
|
+
|
|
53
|
+
Writer Framework works on Linux, Mac, and Windows. It supports Python versions 3.9.2 through 3.12.
|
|
54
|
+
|
|
55
|
+
```sh
|
|
56
|
+
pip install writer
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Create and Run Your First App
|
|
60
|
+
|
|
61
|
+
```sh
|
|
62
|
+
# Create a demo app
|
|
63
|
+
writer hello
|
|
64
|
+
|
|
65
|
+
# Create a new app
|
|
66
|
+
writer create my_app
|
|
67
|
+
|
|
68
|
+
# Edit your app (opens visual editor)
|
|
69
|
+
writer edit my_app
|
|
70
|
+
|
|
71
|
+
# Run your app
|
|
72
|
+
writer run my_app
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
The `writer edit` command opens the visual editor in your browser where you can build your UI by dragging and dropping components.
|
|
76
|
+
|
|
77
|
+
## Documentation
|
|
78
|
+
|
|
79
|
+
For comprehensive guides, tutorials, and API reference, visit the [official documentation](https://dev.writer.com/framework/quickstart).
|
|
80
|
+
|
|
81
|
+
## Contributing
|
|
82
|
+
|
|
83
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md)
|
|
84
|
+
|
|
85
|
+
## About Writer
|
|
86
|
+
|
|
87
|
+
Writer is the full-stack generative AI platform for enterprises. Quickly and easily build and deploy generative AI apps with a suite of developer tools fully integrated with our platform of LLMs, graph-based RAG tools, AI guardrails, and more. Learn more at [writer.com](https://www.writer.com?utm_source=github&utm_medium=readme&utm_campaign=framework).
|
|
88
|
+
|
|
89
|
+
## License
|
|
90
|
+
|
|
91
|
+
This project is licensed under the Apache 2.0 License.
|
|
92
|
+
|