@treenity/mods 3.0.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/board/board.test.ts +212 -0
- package/board/client.ts +1 -0
- package/board/seed.ts +26 -0
- package/board/server.ts +5 -0
- package/board/types.ts +87 -0
- package/board/view.tsx +574 -0
- package/brahman/CLAUDE.md +18 -0
- package/brahman/brahman.test.ts +855 -0
- package/brahman/client.ts +2 -0
- package/brahman/helpers.ts +374 -0
- package/brahman/server.ts +2 -0
- package/brahman/service.ts +328 -0
- package/brahman/types.ts +727 -0
- package/brahman/view.tsx +73 -0
- package/brahman/views/action-cards.tsx +615 -0
- package/brahman/views/bot-view.tsx +76 -0
- package/brahman/views/chat-editor.tsx +782 -0
- package/brahman/views/chat-preview.tsx +266 -0
- package/brahman/views/menu-editor.tsx +451 -0
- package/brahman/views/page-layout.tsx +285 -0
- package/brahman/views/tstring-input.tsx +84 -0
- package/cafe/CLAUDE.md +7 -0
- package/cafe/seed.ts +8 -0
- package/cafe/server.ts +2 -0
- package/cafe/types.ts +32 -0
- package/canary/seed.ts +8 -0
- package/canary/server.ts +3 -0
- package/canary/service.ts +101 -0
- package/canary/types.ts +16 -0
- package/dist/board/client.d.ts +2 -0
- package/dist/board/client.d.ts.map +1 -0
- package/dist/board/client.js +2 -0
- package/dist/board/client.js.map +1 -0
- package/dist/board/seed.d.ts +2 -0
- package/dist/board/seed.d.ts.map +1 -0
- package/dist/board/seed.js +23 -0
- package/dist/board/seed.js.map +1 -0
- package/dist/board/server.d.ts +3 -0
- package/dist/board/server.d.ts.map +1 -0
- package/dist/board/server.js +5 -0
- package/dist/board/server.js.map +1 -0
- package/dist/board/types.d.ts +45 -0
- package/dist/board/types.d.ts.map +1 -0
- package/dist/board/types.js +82 -0
- package/dist/board/types.js.map +1 -0
- package/dist/board/view.d.ts +2 -0
- package/dist/board/view.d.ts.map +1 -0
- package/dist/board/view.js +254 -0
- package/dist/board/view.js.map +1 -0
- package/dist/brahman/client.d.ts +3 -0
- package/dist/brahman/client.d.ts.map +1 -0
- package/dist/brahman/client.js +3 -0
- package/dist/brahman/client.js.map +1 -0
- package/dist/brahman/helpers.d.ts +51 -0
- package/dist/brahman/helpers.d.ts.map +1 -0
- package/dist/brahman/helpers.js +321 -0
- package/dist/brahman/helpers.js.map +1 -0
- package/dist/brahman/server.d.ts +3 -0
- package/dist/brahman/server.d.ts.map +1 -0
- package/dist/brahman/server.js +3 -0
- package/dist/brahman/server.js.map +1 -0
- package/dist/brahman/service.d.ts +2 -0
- package/dist/brahman/service.d.ts.map +1 -0
- package/dist/brahman/service.js +310 -0
- package/dist/brahman/service.js.map +1 -0
- package/dist/brahman/types.d.ts +335 -0
- package/dist/brahman/types.d.ts.map +1 -0
- package/dist/brahman/types.js +633 -0
- package/dist/brahman/types.js.map +1 -0
- package/dist/brahman/view.d.ts +2 -0
- package/dist/brahman/view.d.ts.map +1 -0
- package/dist/brahman/view.js +47 -0
- package/dist/brahman/view.js.map +1 -0
- package/dist/brahman/views/action-cards.d.ts +60 -0
- package/dist/brahman/views/action-cards.d.ts.map +1 -0
- package/dist/brahman/views/action-cards.js +283 -0
- package/dist/brahman/views/action-cards.js.map +1 -0
- package/dist/brahman/views/bot-view.d.ts +5 -0
- package/dist/brahman/views/bot-view.d.ts.map +1 -0
- package/dist/brahman/views/bot-view.js +14 -0
- package/dist/brahman/views/bot-view.js.map +1 -0
- package/dist/brahman/views/chat-editor.d.ts +5 -0
- package/dist/brahman/views/chat-editor.d.ts.map +1 -0
- package/dist/brahman/views/chat-editor.js +306 -0
- package/dist/brahman/views/chat-editor.js.map +1 -0
- package/dist/brahman/views/chat-preview.d.ts +5 -0
- package/dist/brahman/views/chat-preview.d.ts.map +1 -0
- package/dist/brahman/views/chat-preview.js +145 -0
- package/dist/brahman/views/chat-preview.js.map +1 -0
- package/dist/brahman/views/menu-editor.d.ts +11 -0
- package/dist/brahman/views/menu-editor.d.ts.map +1 -0
- package/dist/brahman/views/menu-editor.js +171 -0
- package/dist/brahman/views/menu-editor.js.map +1 -0
- package/dist/brahman/views/page-layout.d.ts +5 -0
- package/dist/brahman/views/page-layout.d.ts.map +1 -0
- package/dist/brahman/views/page-layout.js +114 -0
- package/dist/brahman/views/page-layout.js.map +1 -0
- package/dist/brahman/views/tstring-input.d.ts +15 -0
- package/dist/brahman/views/tstring-input.d.ts.map +1 -0
- package/dist/brahman/views/tstring-input.js +23 -0
- package/dist/brahman/views/tstring-input.js.map +1 -0
- package/dist/cafe/seed.d.ts +2 -0
- package/dist/cafe/seed.d.ts.map +1 -0
- package/dist/cafe/seed.js +7 -0
- package/dist/cafe/seed.js.map +1 -0
- package/dist/cafe/server.d.ts +3 -0
- package/dist/cafe/server.d.ts.map +1 -0
- package/dist/cafe/server.js +3 -0
- package/dist/cafe/server.js.map +1 -0
- package/dist/cafe/types.d.ts +2 -0
- package/dist/cafe/types.d.ts.map +1 -0
- package/dist/cafe/types.js +31 -0
- package/dist/cafe/types.js.map +1 -0
- package/dist/canary/seed.d.ts +2 -0
- package/dist/canary/seed.d.ts.map +1 -0
- package/dist/canary/seed.js +7 -0
- package/dist/canary/seed.js.map +1 -0
- package/dist/canary/server.d.ts +4 -0
- package/dist/canary/server.d.ts.map +1 -0
- package/dist/canary/server.js +4 -0
- package/dist/canary/server.js.map +1 -0
- package/dist/canary/service.d.ts +2 -0
- package/dist/canary/service.d.ts.map +1 -0
- package/dist/canary/service.js +101 -0
- package/dist/canary/service.js.map +1 -0
- package/dist/canary/types.d.ts +9 -0
- package/dist/canary/types.d.ts.map +1 -0
- package/dist/canary/types.js +13 -0
- package/dist/canary/types.js.map +1 -0
- package/dist/doc/client.d.ts +3 -0
- package/dist/doc/client.d.ts.map +1 -0
- package/dist/doc/client.js +5 -0
- package/dist/doc/client.js.map +1 -0
- package/dist/doc/fs-codec.d.ts +2 -0
- package/dist/doc/fs-codec.d.ts.map +1 -0
- package/dist/doc/fs-codec.js +44 -0
- package/dist/doc/fs-codec.js.map +1 -0
- package/dist/doc/markdown.d.ts +13 -0
- package/dist/doc/markdown.d.ts.map +1 -0
- package/dist/doc/markdown.js +250 -0
- package/dist/doc/markdown.js.map +1 -0
- package/dist/doc/prefab.d.ts +2 -0
- package/dist/doc/prefab.d.ts.map +1 -0
- package/dist/doc/prefab.js +23 -0
- package/dist/doc/prefab.js.map +1 -0
- package/dist/doc/renderers.d.ts +2 -0
- package/dist/doc/renderers.d.ts.map +1 -0
- package/dist/doc/renderers.js +94 -0
- package/dist/doc/renderers.js.map +1 -0
- package/dist/doc/seed.d.ts +2 -0
- package/dist/doc/seed.d.ts.map +1 -0
- package/dist/doc/seed.js +9 -0
- package/dist/doc/seed.js.map +1 -0
- package/dist/doc/server.d.ts +6 -0
- package/dist/doc/server.d.ts.map +1 -0
- package/dist/doc/server.js +6 -0
- package/dist/doc/server.js.map +1 -0
- package/dist/doc/slash-command.d.ts +3 -0
- package/dist/doc/slash-command.d.ts.map +1 -0
- package/dist/doc/slash-command.js +123 -0
- package/dist/doc/slash-command.js.map +1 -0
- package/dist/doc/slash-menu.d.ts +15 -0
- package/dist/doc/slash-menu.d.ts.map +1 -0
- package/dist/doc/slash-menu.js +54 -0
- package/dist/doc/slash-menu.js.map +1 -0
- package/dist/doc/text.d.ts +2 -0
- package/dist/doc/text.d.ts.map +1 -0
- package/dist/doc/text.js +22 -0
- package/dist/doc/text.js.map +1 -0
- package/dist/doc/toolbar.d.ts +5 -0
- package/dist/doc/toolbar.d.ts.map +1 -0
- package/dist/doc/toolbar.js +15 -0
- package/dist/doc/toolbar.js.map +1 -0
- package/dist/doc/treenity-block-view.d.ts +2 -0
- package/dist/doc/treenity-block-view.d.ts.map +1 -0
- package/dist/doc/treenity-block-view.js +37 -0
- package/dist/doc/treenity-block-view.js.map +1 -0
- package/dist/doc/treenity-block.d.ts +3 -0
- package/dist/doc/treenity-block.d.ts.map +1 -0
- package/dist/doc/treenity-block.js +27 -0
- package/dist/doc/treenity-block.js.map +1 -0
- package/dist/doc/types.d.ts +2 -0
- package/dist/doc/types.d.ts.map +1 -0
- package/dist/doc/types.js +10 -0
- package/dist/doc/types.js.map +1 -0
- package/dist/launcher/client.d.ts +5 -0
- package/dist/launcher/client.d.ts.map +1 -0
- package/dist/launcher/client.js +5 -0
- package/dist/launcher/client.js.map +1 -0
- package/dist/launcher/icons.d.ts +2 -0
- package/dist/launcher/icons.d.ts.map +1 -0
- package/dist/launcher/icons.js +57 -0
- package/dist/launcher/icons.js.map +1 -0
- package/dist/launcher/seed.d.ts +2 -0
- package/dist/launcher/seed.d.ts.map +1 -0
- package/dist/launcher/seed.js +36 -0
- package/dist/launcher/seed.js.map +1 -0
- package/dist/launcher/server.d.ts +3 -0
- package/dist/launcher/server.d.ts.map +1 -0
- package/dist/launcher/server.js +3 -0
- package/dist/launcher/server.js.map +1 -0
- package/dist/launcher/types.d.ts +21 -0
- package/dist/launcher/types.d.ts.map +1 -0
- package/dist/launcher/types.js +47 -0
- package/dist/launcher/types.js.map +1 -0
- package/dist/launcher/view.d.ts +2 -0
- package/dist/launcher/view.d.ts.map +1 -0
- package/dist/launcher/view.js +187 -0
- package/dist/launcher/view.js.map +1 -0
- package/dist/launcher/widgets.d.ts +2 -0
- package/dist/launcher/widgets.d.ts.map +1 -0
- package/dist/launcher/widgets.js +73 -0
- package/dist/launcher/widgets.js.map +1 -0
- package/dist/mindmap/branch.d.ts +17 -0
- package/dist/mindmap/branch.d.ts.map +1 -0
- package/dist/mindmap/branch.js +47 -0
- package/dist/mindmap/branch.js.map +1 -0
- package/dist/mindmap/client.d.ts +3 -0
- package/dist/mindmap/client.d.ts.map +1 -0
- package/dist/mindmap/client.js +3 -0
- package/dist/mindmap/client.js.map +1 -0
- package/dist/mindmap/radial-tree.d.ts +14 -0
- package/dist/mindmap/radial-tree.d.ts.map +1 -0
- package/dist/mindmap/radial-tree.js +184 -0
- package/dist/mindmap/radial-tree.js.map +1 -0
- package/dist/mindmap/sidebar.d.ts +8 -0
- package/dist/mindmap/sidebar.d.ts.map +1 -0
- package/dist/mindmap/sidebar.js +24 -0
- package/dist/mindmap/sidebar.js.map +1 -0
- package/dist/mindmap/types.d.ts +8 -0
- package/dist/mindmap/types.d.ts.map +1 -0
- package/dist/mindmap/types.js +10 -0
- package/dist/mindmap/types.js.map +1 -0
- package/dist/mindmap/use-tree-data.d.ts +14 -0
- package/dist/mindmap/use-tree-data.d.ts.map +1 -0
- package/dist/mindmap/use-tree-data.js +95 -0
- package/dist/mindmap/use-tree-data.js.map +1 -0
- package/dist/mindmap/view.d.ts +3 -0
- package/dist/mindmap/view.d.ts.map +1 -0
- package/dist/mindmap/view.js +141 -0
- package/dist/mindmap/view.js.map +1 -0
- package/dist/sensor-demo/client.d.ts +2 -0
- package/dist/sensor-demo/client.d.ts.map +1 -0
- package/dist/sensor-demo/client.js +2 -0
- package/dist/sensor-demo/client.js.map +1 -0
- package/dist/sensor-demo/server.d.ts +2 -0
- package/dist/sensor-demo/server.d.ts.map +1 -0
- package/dist/sensor-demo/server.js +2 -0
- package/dist/sensor-demo/server.js.map +1 -0
- package/dist/sensor-demo/service.d.ts +2 -0
- package/dist/sensor-demo/service.d.ts.map +1 -0
- package/dist/sensor-demo/service.js +27 -0
- package/dist/sensor-demo/service.js.map +1 -0
- package/dist/sensor-demo/types.d.ts +15 -0
- package/dist/sensor-demo/types.d.ts.map +1 -0
- package/dist/sensor-demo/types.js +18 -0
- package/dist/sensor-demo/types.js.map +1 -0
- package/dist/sensor-demo/view.d.ts +2 -0
- package/dist/sensor-demo/view.d.ts.map +1 -0
- package/dist/sensor-demo/view.js +33 -0
- package/dist/sensor-demo/view.js.map +1 -0
- package/dist/sensor-generator/action.d.ts +2 -0
- package/dist/sensor-generator/action.d.ts.map +1 -0
- package/dist/sensor-generator/action.js +23 -0
- package/dist/sensor-generator/action.js.map +1 -0
- package/dist/sensor-generator/client.d.ts +2 -0
- package/dist/sensor-generator/client.d.ts.map +1 -0
- package/dist/sensor-generator/client.js +2 -0
- package/dist/sensor-generator/client.js.map +1 -0
- package/dist/sensor-generator/server.d.ts +2 -0
- package/dist/sensor-generator/server.d.ts.map +1 -0
- package/dist/sensor-generator/server.js +2 -0
- package/dist/sensor-generator/server.js.map +1 -0
- package/dist/sensor-generator/view.d.ts +2 -0
- package/dist/sensor-generator/view.d.ts.map +1 -0
- package/dist/sensor-generator/view.js +64 -0
- package/dist/sensor-generator/view.js.map +1 -0
- package/dist/sim/client.d.ts +2 -0
- package/dist/sim/client.d.ts.map +1 -0
- package/dist/sim/client.js +2 -0
- package/dist/sim/client.js.map +1 -0
- package/dist/sim/seed.d.ts +2 -0
- package/dist/sim/seed.d.ts.map +1 -0
- package/dist/sim/seed.js +50 -0
- package/dist/sim/seed.js.map +1 -0
- package/dist/sim/server.d.ts +3 -0
- package/dist/sim/server.d.ts.map +1 -0
- package/dist/sim/server.js +3 -0
- package/dist/sim/server.js.map +1 -0
- package/dist/sim/service.d.ts +4 -0
- package/dist/sim/service.d.ts.map +1 -0
- package/dist/sim/service.js +528 -0
- package/dist/sim/service.js.map +1 -0
- package/dist/sim/types.d.ts +63 -0
- package/dist/sim/types.d.ts.map +1 -0
- package/dist/sim/types.js +57 -0
- package/dist/sim/types.js.map +1 -0
- package/dist/sim/view.d.ts +2 -0
- package/dist/sim/view.d.ts.map +1 -0
- package/dist/sim/view.js +205 -0
- package/dist/sim/view.js.map +1 -0
- package/dist/table/client.d.ts +4 -0
- package/dist/table/client.d.ts.map +1 -0
- package/dist/table/client.js +4 -0
- package/dist/table/client.js.map +1 -0
- package/dist/table/edit.d.ts +2 -0
- package/dist/table/edit.d.ts.map +1 -0
- package/dist/table/edit.js +115 -0
- package/dist/table/edit.js.map +1 -0
- package/dist/table/server.d.ts +2 -0
- package/dist/table/server.d.ts.map +1 -0
- package/dist/table/server.js +2 -0
- package/dist/table/server.js.map +1 -0
- package/dist/table/types.d.ts +18 -0
- package/dist/table/types.d.ts.map +1 -0
- package/dist/table/types.js +13 -0
- package/dist/table/types.js.map +1 -0
- package/dist/table/use-debounced-sync.d.ts +8 -0
- package/dist/table/use-debounced-sync.d.ts.map +1 -0
- package/dist/table/use-debounced-sync.js +56 -0
- package/dist/table/use-debounced-sync.js.map +1 -0
- package/dist/table/view.d.ts +2 -0
- package/dist/table/view.d.ts.map +1 -0
- package/dist/table/view.js +199 -0
- package/dist/table/view.js.map +1 -0
- package/dist/tasks/server.d.ts +2 -0
- package/dist/tasks/server.d.ts.map +1 -0
- package/dist/tasks/server.js +2 -0
- package/dist/tasks/server.js.map +1 -0
- package/dist/tasks/types.d.ts +22 -0
- package/dist/tasks/types.d.ts.map +1 -0
- package/dist/tasks/types.js +34 -0
- package/dist/tasks/types.js.map +1 -0
- package/dist/three/client.d.ts +2 -0
- package/dist/three/client.d.ts.map +1 -0
- package/dist/three/client.js +2 -0
- package/dist/three/client.js.map +1 -0
- package/dist/three/seed.d.ts +2 -0
- package/dist/three/seed.d.ts.map +1 -0
- package/dist/three/seed.js +45 -0
- package/dist/three/seed.js.map +1 -0
- package/dist/three/server.d.ts +3 -0
- package/dist/three/server.d.ts.map +1 -0
- package/dist/three/server.js +3 -0
- package/dist/three/server.js.map +1 -0
- package/dist/three/types.d.ts +178 -0
- package/dist/three/types.d.ts.map +1 -0
- package/dist/three/types.js +209 -0
- package/dist/three/types.js.map +1 -0
- package/dist/three/view.d.ts +2 -0
- package/dist/three/view.d.ts.map +1 -0
- package/dist/three/view.js +307 -0
- package/dist/three/view.js.map +1 -0
- package/dist/todo/client.d.ts +3 -0
- package/dist/todo/client.d.ts.map +1 -0
- package/dist/todo/client.js +3 -0
- package/dist/todo/client.js.map +1 -0
- package/dist/todo/seed.d.ts +2 -0
- package/dist/todo/seed.d.ts.map +1 -0
- package/dist/todo/seed.js +8 -0
- package/dist/todo/seed.js.map +1 -0
- package/dist/todo/server.d.ts +3 -0
- package/dist/todo/server.d.ts.map +1 -0
- package/dist/todo/server.js +3 -0
- package/dist/todo/server.js.map +1 -0
- package/dist/todo/types.d.ts +15 -0
- package/dist/todo/types.d.ts.map +1 -0
- package/dist/todo/types.js +29 -0
- package/dist/todo/types.js.map +1 -0
- package/dist/todo/view.d.ts +2 -0
- package/dist/todo/view.d.ts.map +1 -0
- package/dist/todo/view.js +27 -0
- package/dist/todo/view.js.map +1 -0
- package/dist/whisper/client.d.ts +2 -0
- package/dist/whisper/client.d.ts.map +1 -0
- package/dist/whisper/client.js +2 -0
- package/dist/whisper/client.js.map +1 -0
- package/dist/whisper/inbox.d.ts +2 -0
- package/dist/whisper/inbox.d.ts.map +1 -0
- package/dist/whisper/inbox.js +50 -0
- package/dist/whisper/inbox.js.map +1 -0
- package/dist/whisper/route.d.ts +10 -0
- package/dist/whisper/route.d.ts.map +1 -0
- package/dist/whisper/route.js +154 -0
- package/dist/whisper/route.js.map +1 -0
- package/dist/whisper/seed.d.ts +2 -0
- package/dist/whisper/seed.d.ts.map +1 -0
- package/dist/whisper/seed.js +14 -0
- package/dist/whisper/seed.js.map +1 -0
- package/dist/whisper/server.d.ts +5 -0
- package/dist/whisper/server.d.ts.map +1 -0
- package/dist/whisper/server.js +5 -0
- package/dist/whisper/server.js.map +1 -0
- package/dist/whisper/service.d.ts +2 -0
- package/dist/whisper/service.d.ts.map +1 -0
- package/dist/whisper/service.js +26 -0
- package/dist/whisper/service.js.map +1 -0
- package/dist/whisper/types.d.ts +38 -0
- package/dist/whisper/types.d.ts.map +1 -0
- package/dist/whisper/types.js +45 -0
- package/dist/whisper/types.js.map +1 -0
- package/dist/whisper/view.d.ts +2 -0
- package/dist/whisper/view.d.ts.map +1 -0
- package/dist/whisper/view.js +40 -0
- package/dist/whisper/view.js.map +1 -0
- package/doc/CLAUDE.md +49 -0
- package/doc/client.ts +5 -0
- package/doc/editor.css +283 -0
- package/doc/fs-codec.test.ts +119 -0
- package/doc/fs-codec.ts +50 -0
- package/doc/markdown.test.ts +152 -0
- package/doc/markdown.ts +284 -0
- package/doc/prefab.ts +26 -0
- package/doc/renderers.tsx +126 -0
- package/doc/seed.ts +10 -0
- package/doc/server.ts +5 -0
- package/doc/slash-command.ts +136 -0
- package/doc/slash-menu.tsx +91 -0
- package/doc/text.ts +20 -0
- package/doc/toolbar.tsx +86 -0
- package/doc/treenity-block-view.tsx +116 -0
- package/doc/treenity-block.ts +31 -0
- package/doc/types.ts +10 -0
- package/launcher/client.ts +4 -0
- package/launcher/icons.tsx +234 -0
- package/launcher/launcher.css +64 -0
- package/launcher/seed.ts +41 -0
- package/launcher/server.ts +2 -0
- package/launcher/types.ts +53 -0
- package/launcher/view.tsx +401 -0
- package/launcher/widgets.tsx +171 -0
- package/mindmap/branch.tsx +163 -0
- package/mindmap/client.ts +2 -0
- package/mindmap/mindmap.css +243 -0
- package/mindmap/sidebar.tsx +127 -0
- package/mindmap/types.ts +10 -0
- package/mindmap/view.tsx +247 -0
- package/package.json +75 -0
- package/sensor-demo/CLAUDE.md +3 -0
- package/sensor-demo/client.ts +1 -0
- package/sensor-demo/server.ts +1 -0
- package/sensor-demo/service.ts +27 -0
- package/sensor-demo/types.ts +20 -0
- package/sensor-demo/view.tsx +64 -0
- package/sensor-generator/CLAUDE.md +3 -0
- package/sensor-generator/action.ts +28 -0
- package/sensor-generator/client.ts +1 -0
- package/sensor-generator/server.ts +1 -0
- package/sensor-generator/view.tsx +107 -0
- package/sim/CLAUDE.md +16 -0
- package/sim/client.ts +1 -0
- package/sim/seed.ts +55 -0
- package/sim/server.ts +2 -0
- package/sim/service.ts +594 -0
- package/sim/sim.test.ts +282 -0
- package/sim/types.ts +87 -0
- package/sim/view.tsx +446 -0
- package/table/client.ts +3 -0
- package/table/edit.tsx +241 -0
- package/table/server.ts +1 -0
- package/table/types.ts +22 -0
- package/table/use-debounced-sync.ts +67 -0
- package/table/view.tsx +339 -0
- package/tasks/CLAUDE.md +6 -0
- package/tasks/server.ts +1 -0
- package/tasks/types.ts +36 -0
- package/three/CLAUDE.md +6 -0
- package/three/client.ts +1 -0
- package/three/seed.ts +54 -0
- package/three/server.ts +2 -0
- package/three/types.ts +238 -0
- package/three/view.tsx +453 -0
- package/todo/client.ts +2 -0
- package/todo/seed.ts +9 -0
- package/todo/server.ts +2 -0
- package/todo/types.ts +32 -0
- package/todo/view.tsx +67 -0
- package/whisper/CLAUDE.md +16 -0
- package/whisper/client.ts +1 -0
- package/whisper/inbox.ts +54 -0
- package/whisper/route.ts +182 -0
- package/whisper/seed.ts +15 -0
- package/whisper/server.ts +4 -0
- package/whisper/service.ts +29 -0
- package/whisper/types.ts +51 -0
- package/whisper/view.tsx +81 -0
package/brahman/view.tsx
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// Brahman — view registrations
|
|
2
|
+
// Registers react + react:list handlers for all brahman types
|
|
3
|
+
|
|
4
|
+
import { register } from '@treenity/core';
|
|
5
|
+
import './types';
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
ActionListItem,
|
|
9
|
+
BackEditor,
|
|
10
|
+
BroadcastEditor,
|
|
11
|
+
EmitTextEditor,
|
|
12
|
+
EvalEditor,
|
|
13
|
+
FileEditor,
|
|
14
|
+
ForwardEditor,
|
|
15
|
+
GetValueEditor,
|
|
16
|
+
IfElseEditor,
|
|
17
|
+
KeywordSelectEditor,
|
|
18
|
+
MessageEditor,
|
|
19
|
+
OnErrorEditor,
|
|
20
|
+
PageNavEditor,
|
|
21
|
+
ParamsEditor,
|
|
22
|
+
QuestionEditor,
|
|
23
|
+
RemoveEditor,
|
|
24
|
+
ResetHistoryEditor,
|
|
25
|
+
ResetSessionEditor,
|
|
26
|
+
SelectLanguageEditor,
|
|
27
|
+
SetValueEditor,
|
|
28
|
+
TagEditor,
|
|
29
|
+
} from './views/action-cards';
|
|
30
|
+
import { BotView } from './views/bot-view';
|
|
31
|
+
import { PageChatEditor } from './views/chat-editor';
|
|
32
|
+
import { PageChatPreview } from './views/chat-preview';
|
|
33
|
+
import { PageLayoutView } from './views/page-layout';
|
|
34
|
+
|
|
35
|
+
// ── Node-level views (react context) ──
|
|
36
|
+
|
|
37
|
+
register('brahman.bot', 'react', BotView as any);
|
|
38
|
+
register('brahman.page', 'react', PageLayoutView as any);
|
|
39
|
+
register('brahman.page', 'react:chat', PageChatPreview as any);
|
|
40
|
+
register('brahman.page', 'react:chat:edit', PageChatEditor as any);
|
|
41
|
+
register('brahman.action.message', 'react', MessageEditor as any);
|
|
42
|
+
register('brahman.action.question', 'react', QuestionEditor as any);
|
|
43
|
+
register('brahman.action.ifelse', 'react', IfElseEditor as any);
|
|
44
|
+
register('brahman.action.page', 'react', PageNavEditor as any);
|
|
45
|
+
register('brahman.action.back', 'react', BackEditor as any);
|
|
46
|
+
register('brahman.action.tag', 'react', TagEditor as any);
|
|
47
|
+
register('brahman.action.broadcast', 'react', BroadcastEditor as any);
|
|
48
|
+
register('brahman.action.getvalue', 'react', GetValueEditor as any);
|
|
49
|
+
register('brahman.action.setvalue', 'react', SetValueEditor as any);
|
|
50
|
+
register('brahman.action.params', 'react', ParamsEditor as any);
|
|
51
|
+
register('brahman.action.file', 'react', FileEditor as any);
|
|
52
|
+
register('brahman.action.eval', 'react', EvalEditor as any);
|
|
53
|
+
register('brahman.action.remove', 'react', RemoveEditor as any);
|
|
54
|
+
register('brahman.action.emittext', 'react', EmitTextEditor as any);
|
|
55
|
+
register('brahman.action.forward', 'react', ForwardEditor as any);
|
|
56
|
+
register('brahman.action.resetsession', 'react', ResetSessionEditor as any);
|
|
57
|
+
register('brahman.action.resethistory', 'react', ResetHistoryEditor as any);
|
|
58
|
+
register('brahman.action.onerror', 'react', OnErrorEditor as any);
|
|
59
|
+
register('brahman.action.keywordselect', 'react', KeywordSelectEditor as any);
|
|
60
|
+
register('brahman.action.selectlang', 'react', SelectLanguageEditor as any);
|
|
61
|
+
|
|
62
|
+
// ── Compact list items (react:list context) ──
|
|
63
|
+
|
|
64
|
+
const listTypes = [
|
|
65
|
+
'brahman.action.message', 'brahman.action.question', 'brahman.action.ifelse',
|
|
66
|
+
'brahman.action.page', 'brahman.action.back', 'brahman.action.tag',
|
|
67
|
+
'brahman.action.broadcast', 'brahman.action.getvalue', 'brahman.action.setvalue',
|
|
68
|
+
'brahman.action.params', 'brahman.action.file', 'brahman.action.eval',
|
|
69
|
+
'brahman.action.remove', 'brahman.action.emittext', 'brahman.action.forward',
|
|
70
|
+
'brahman.action.resetsession', 'brahman.action.resethistory', 'brahman.action.onerror',
|
|
71
|
+
'brahman.action.keywordselect', 'brahman.action.selectlang',
|
|
72
|
+
];
|
|
73
|
+
for (const t of listTypes) register(t, 'react:list', ActionListItem as any);
|
|
@@ -0,0 +1,615 @@
|
|
|
1
|
+
// Action type views — full editors (react) + compact cards (react:list)
|
|
2
|
+
// Each action type gets: icon helper, summary helper, full editor, list item
|
|
3
|
+
|
|
4
|
+
import type { NodeData } from '@treenity/core';
|
|
5
|
+
import { Checkbox } from '@treenity/react/components/ui/checkbox';
|
|
6
|
+
import { Input } from '@treenity/react/components/ui/input';
|
|
7
|
+
import { set, usePath } from '@treenity/react/hooks';
|
|
8
|
+
import { trpc } from '@treenity/react/trpc';
|
|
9
|
+
import {
|
|
10
|
+
AlertTriangle,
|
|
11
|
+
ArrowLeft,
|
|
12
|
+
Code,
|
|
13
|
+
Download,
|
|
14
|
+
File,
|
|
15
|
+
FileText,
|
|
16
|
+
Forward,
|
|
17
|
+
GitBranch,
|
|
18
|
+
Globe,
|
|
19
|
+
HelpCircle,
|
|
20
|
+
History,
|
|
21
|
+
MessageSquare,
|
|
22
|
+
Repeat,
|
|
23
|
+
RotateCcw,
|
|
24
|
+
Search,
|
|
25
|
+
Send,
|
|
26
|
+
Settings2,
|
|
27
|
+
Tag,
|
|
28
|
+
Trash2,
|
|
29
|
+
Upload,
|
|
30
|
+
} from 'lucide-react';
|
|
31
|
+
import { type ReactNode, useCallback, useEffect, useRef, useState } from 'react';
|
|
32
|
+
import type {
|
|
33
|
+
BroadcastAction,
|
|
34
|
+
EmitTextAction,
|
|
35
|
+
EvalAction,
|
|
36
|
+
FileAction,
|
|
37
|
+
ForwardAction,
|
|
38
|
+
GetValueAction,
|
|
39
|
+
IfElseAction,
|
|
40
|
+
KeywordSelectAction,
|
|
41
|
+
MessageAction,
|
|
42
|
+
OnErrorAction,
|
|
43
|
+
ParamsAction,
|
|
44
|
+
QuestionAction,
|
|
45
|
+
SelectLanguageAction,
|
|
46
|
+
SetValueAction,
|
|
47
|
+
TagAction,
|
|
48
|
+
} from '../types';
|
|
49
|
+
import { MenuEditor } from './menu-editor';
|
|
50
|
+
import { TStringInput, tstringPreview } from './tstring-input';
|
|
51
|
+
|
|
52
|
+
// ── Icon mapping ──
|
|
53
|
+
|
|
54
|
+
const ICONS: Record<string, ReactNode> = {
|
|
55
|
+
'brahman.action.message': <MessageSquare className="h-4 w-4 text-blue-500" />,
|
|
56
|
+
'brahman.action.question': <HelpCircle className="h-4 w-4 text-amber-500" />,
|
|
57
|
+
'brahman.action.ifelse': <GitBranch className="h-4 w-4 text-purple-500" />,
|
|
58
|
+
'brahman.action.page': <FileText className="h-4 w-4 text-green-500" />,
|
|
59
|
+
'brahman.action.back': <ArrowLeft className="h-4 w-4 text-gray-500" />,
|
|
60
|
+
'brahman.action.tag': <Tag className="h-4 w-4 text-orange-500" />,
|
|
61
|
+
'brahman.action.broadcast': <Send className="h-4 w-4 text-red-500" />,
|
|
62
|
+
'brahman.action.getvalue': <Download className="h-4 w-4 text-cyan-500" />,
|
|
63
|
+
'brahman.action.setvalue': <Upload className="h-4 w-4 text-cyan-500" />,
|
|
64
|
+
'brahman.action.params': <Settings2 className="h-4 w-4 text-gray-500" />,
|
|
65
|
+
'brahman.action.file': <File className="h-4 w-4 text-indigo-500" />,
|
|
66
|
+
'brahman.action.eval': <Code className="h-4 w-4 text-yellow-600" />,
|
|
67
|
+
'brahman.action.remove': <Trash2 className="h-4 w-4 text-red-500" />,
|
|
68
|
+
'brahman.action.emittext': <Repeat className="h-4 w-4 text-teal-500" />,
|
|
69
|
+
'brahman.action.forward': <Forward className="h-4 w-4 text-blue-400" />,
|
|
70
|
+
'brahman.action.resetsession': <RotateCcw className="h-4 w-4 text-rose-500" />,
|
|
71
|
+
'brahman.action.resethistory': <History className="h-4 w-4 text-rose-400" />,
|
|
72
|
+
'brahman.action.onerror': <AlertTriangle className="h-4 w-4 text-amber-600" />,
|
|
73
|
+
'brahman.action.keywordselect': <Search className="h-4 w-4 text-emerald-500" />,
|
|
74
|
+
'brahman.action.selectlang': <Globe className="h-4 w-4 text-sky-500" />,
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export function actionIcon(type: string): ReactNode {
|
|
78
|
+
return ICONS[type] ?? <Settings2 className="h-4 w-4 text-muted-foreground" />;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ── Summary helpers for compact display ──
|
|
82
|
+
|
|
83
|
+
export function actionSummary(node: NodeData): string {
|
|
84
|
+
const c = findActionComp(node) as any;
|
|
85
|
+
if (!c) return '';
|
|
86
|
+
|
|
87
|
+
switch (node.$type) {
|
|
88
|
+
case 'brahman.action.message': return tstringPreview(c.text ?? {});
|
|
89
|
+
case 'brahman.action.question': return `${tstringPreview(c.text ?? {}, 25)} -> ${c.saveTo || '?'}`;
|
|
90
|
+
case 'brahman.action.ifelse': return c.condition || 'no condition';
|
|
91
|
+
case 'brahman.action.page': return c.targetPage || 'no target';
|
|
92
|
+
case 'brahman.action.back': return 'pop history';
|
|
93
|
+
case 'brahman.action.tag': return `${c.tag} = ${c.value}`;
|
|
94
|
+
case 'brahman.action.broadcast': return `to ${(c.userTags ?? []).join(', ') || 'all'}`;
|
|
95
|
+
case 'brahman.action.getvalue': return `${c.path} -> ${c.saveTo}`;
|
|
96
|
+
case 'brahman.action.setvalue': return `${c.value} -> ${c.saveTo}`;
|
|
97
|
+
case 'brahman.action.params': return (c.names ?? []).join(', ') || 'no params';
|
|
98
|
+
case 'brahman.action.file': return c.fileId || 'no file';
|
|
99
|
+
case 'brahman.action.eval': return (c.value ?? '').slice(0, 40) || 'empty';
|
|
100
|
+
case 'brahman.action.remove': return 'delete message';
|
|
101
|
+
case 'brahman.action.emittext': return c.from || 'no text';
|
|
102
|
+
case 'brahman.action.forward': return c.toFrom || 'current chat';
|
|
103
|
+
case 'brahman.action.resetsession': return 'clear session';
|
|
104
|
+
case 'brahman.action.resethistory': return 'clear history';
|
|
105
|
+
case 'brahman.action.onerror': return c.error || 'any error';
|
|
106
|
+
case 'brahman.action.keywordselect': return `${(c.elements ?? []).length} keywords`;
|
|
107
|
+
case 'brahman.action.selectlang': return tstringPreview(c.text ?? {});
|
|
108
|
+
default: return '';
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Find the action component on a node (node itself if $type matches, then scan)
|
|
113
|
+
function findActionComp(node: NodeData): Record<string, unknown> | undefined {
|
|
114
|
+
if (node.$type?.startsWith('brahman.action.')) return node;
|
|
115
|
+
for (const [k, v] of Object.entries(node)) {
|
|
116
|
+
if (k.startsWith('$')) continue;
|
|
117
|
+
if (typeof v === 'object' && v && '$type' in v && typeof (v as any).$type === 'string'
|
|
118
|
+
&& (v as any).$type.startsWith('brahman.action.')) {
|
|
119
|
+
return v as Record<string, unknown>;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// ── Shared field helpers ──
|
|
125
|
+
|
|
126
|
+
function FieldRow({ label, children }: { label: string; children: ReactNode }) {
|
|
127
|
+
return (
|
|
128
|
+
<div className="flex items-start gap-3">
|
|
129
|
+
<label className="text-xs font-medium text-muted-foreground w-28 pt-2 shrink-0">{label}</label>
|
|
130
|
+
<div className="flex-1">{children}</div>
|
|
131
|
+
</div>
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function getLangs(node: NodeData): string[] {
|
|
136
|
+
// Walk up to find bot config's langs
|
|
137
|
+
// Default fallback
|
|
138
|
+
return ['ru', 'en'];
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Generic component updater — debounced persist (500ms), instant UI via local state
|
|
142
|
+
function useActionComp(path: string) {
|
|
143
|
+
const node = usePath(path);
|
|
144
|
+
const [pending, setPending] = useState<Record<string, unknown>>({});
|
|
145
|
+
const pendingRef = useRef<Record<string, unknown>>({});
|
|
146
|
+
const timerRef = useRef<ReturnType<typeof setTimeout>>(undefined);
|
|
147
|
+
const nodeRef = useRef(node);
|
|
148
|
+
nodeRef.current = node;
|
|
149
|
+
|
|
150
|
+
const flush = useCallback(() => {
|
|
151
|
+
clearTimeout(timerRef.current);
|
|
152
|
+
const p = pendingRef.current;
|
|
153
|
+
const n = nodeRef.current;
|
|
154
|
+
if (!n || Object.keys(p).length === 0) return;
|
|
155
|
+
pendingRef.current = {};
|
|
156
|
+
setPending({});
|
|
157
|
+
set({ ...n, ...p } as NodeData);
|
|
158
|
+
}, []);
|
|
159
|
+
|
|
160
|
+
// Flush on unmount (e.g. collapsing the action card)
|
|
161
|
+
useEffect(() => () => { flush(); }, [flush]);
|
|
162
|
+
|
|
163
|
+
// pending IS read in render → React Compiler keeps setPending calls
|
|
164
|
+
const display = node && Object.keys(pending).length > 0
|
|
165
|
+
? { ...node, ...pending } as NodeData
|
|
166
|
+
: node;
|
|
167
|
+
const comp = display ? findActionComp(display) : undefined;
|
|
168
|
+
|
|
169
|
+
function update(patch: Record<string, unknown>) {
|
|
170
|
+
if (!node) return;
|
|
171
|
+
const next = { ...pendingRef.current, ...patch };
|
|
172
|
+
pendingRef.current = next;
|
|
173
|
+
setPending(next);
|
|
174
|
+
clearTimeout(timerRef.current);
|
|
175
|
+
timerRef.current = setTimeout(flush, 2000);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return { node: display, comp, update, langs: getLangs(node!) };
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// ── Full editors (react context) ──
|
|
182
|
+
|
|
183
|
+
export function MessageEditor({ value }: { value: NodeData }) {
|
|
184
|
+
const { comp, update, langs } = useActionComp(value.$path);
|
|
185
|
+
if (!comp) return null;
|
|
186
|
+
const msg = comp as unknown as MessageAction;
|
|
187
|
+
|
|
188
|
+
return (
|
|
189
|
+
<div className="space-y-4 max-w-2xl">
|
|
190
|
+
<FieldRow label="Text">
|
|
191
|
+
<TStringInput value={msg.text} onChange={text => update({ text })} langs={langs} />
|
|
192
|
+
</FieldRow>
|
|
193
|
+
|
|
194
|
+
<FieldRow label="Disable links">
|
|
195
|
+
<Checkbox
|
|
196
|
+
checked={msg.disableLinks}
|
|
197
|
+
onChange={e => update({ disableLinks: e.target.checked })}
|
|
198
|
+
/>
|
|
199
|
+
</FieldRow>
|
|
200
|
+
|
|
201
|
+
<MenuEditor
|
|
202
|
+
menuType={msg.menuType}
|
|
203
|
+
rows={msg.rows}
|
|
204
|
+
langs={langs}
|
|
205
|
+
onChangeType={menuType => update({ menuType })}
|
|
206
|
+
onChangeRows={rows => update({ rows })}
|
|
207
|
+
/>
|
|
208
|
+
</div>
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export function QuestionEditor({ value }: { value: NodeData }) {
|
|
213
|
+
const { comp, update, langs } = useActionComp(value.$path);
|
|
214
|
+
if (!comp) return null;
|
|
215
|
+
const q = comp as unknown as QuestionAction;
|
|
216
|
+
|
|
217
|
+
return (
|
|
218
|
+
<div className="space-y-4 max-w-2xl">
|
|
219
|
+
<FieldRow label="Prompt">
|
|
220
|
+
<TStringInput value={q.text} onChange={text => update({ text })} langs={langs} />
|
|
221
|
+
</FieldRow>
|
|
222
|
+
|
|
223
|
+
<FieldRow label="Input type">
|
|
224
|
+
<select className="h-8 text-sm border border-border rounded-md bg-background px-2"
|
|
225
|
+
value={q.inputType} onChange={e => update({ inputType: e.target.value })}>
|
|
226
|
+
<option value="text">Text</option>
|
|
227
|
+
<option value="photo">Photo</option>
|
|
228
|
+
</select>
|
|
229
|
+
</FieldRow>
|
|
230
|
+
|
|
231
|
+
<FieldRow label="Save to">
|
|
232
|
+
<Input className="font-mono" placeholder="session.field"
|
|
233
|
+
value={q.saveTo} onChange={e => update({ saveTo: e.target.value })} />
|
|
234
|
+
</FieldRow>
|
|
235
|
+
</div>
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export function IfElseEditor({ value }: { value: NodeData }) {
|
|
240
|
+
const { comp, update } = useActionComp(value.$path);
|
|
241
|
+
if (!comp) return null;
|
|
242
|
+
const ie = comp as unknown as IfElseAction;
|
|
243
|
+
|
|
244
|
+
return (
|
|
245
|
+
<div className="space-y-4 max-w-2xl">
|
|
246
|
+
<FieldRow label="Condition">
|
|
247
|
+
<Input className="font-mono" placeholder="session.data.role === 'admin'"
|
|
248
|
+
value={ie.condition} onChange={e => update({ condition: e.target.value })} />
|
|
249
|
+
</FieldRow>
|
|
250
|
+
|
|
251
|
+
<FieldRow label="Action if true">
|
|
252
|
+
<Input className="font-mono" placeholder="/path/to/action"
|
|
253
|
+
value={ie.actionIf} onChange={e => update({ actionIf: e.target.value })} />
|
|
254
|
+
</FieldRow>
|
|
255
|
+
|
|
256
|
+
<FieldRow label="Action if false">
|
|
257
|
+
<Input className="font-mono" placeholder="/path/to/action"
|
|
258
|
+
value={ie.actionElse} onChange={e => update({ actionElse: e.target.value })} />
|
|
259
|
+
</FieldRow>
|
|
260
|
+
|
|
261
|
+
<FieldRow label="Stop after">
|
|
262
|
+
<Checkbox checked={ie.stopAfterAction}
|
|
263
|
+
onChange={e => update({ stopAfterAction: e.target.checked })} />
|
|
264
|
+
</FieldRow>
|
|
265
|
+
</div>
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export function PageNavEditor({ value }: { value: NodeData }) {
|
|
270
|
+
const { comp, update } = useActionComp(value.$path);
|
|
271
|
+
const [dragOver, setDragOver] = useState(false);
|
|
272
|
+
if (!comp) return null;
|
|
273
|
+
|
|
274
|
+
return (
|
|
275
|
+
<div className="space-y-4 max-w-2xl">
|
|
276
|
+
<FieldRow label="Target page">
|
|
277
|
+
<div
|
|
278
|
+
className={`rounded-md transition-colors ${dragOver ? 'ring-1 ring-primary bg-primary/5' : ''}`}
|
|
279
|
+
onDragOver={e => {
|
|
280
|
+
if (e.dataTransfer.types.includes('application/treenity-path')) {
|
|
281
|
+
e.preventDefault();
|
|
282
|
+
e.dataTransfer.dropEffect = 'link';
|
|
283
|
+
setDragOver(true);
|
|
284
|
+
}
|
|
285
|
+
}}
|
|
286
|
+
onDragLeave={() => setDragOver(false)}
|
|
287
|
+
onDrop={async e => {
|
|
288
|
+
const path = e.dataTransfer.getData('application/treenity-path');
|
|
289
|
+
setDragOver(false);
|
|
290
|
+
if (!path) return;
|
|
291
|
+
e.preventDefault();
|
|
292
|
+
const node = await trpc.get.query({ path });
|
|
293
|
+
if (node?.$type === 'brahman.page') update({ targetPage: path });
|
|
294
|
+
}}
|
|
295
|
+
>
|
|
296
|
+
<Input className="font-mono" placeholder="Drop a page here or type path"
|
|
297
|
+
value={(comp as any).targetPage ?? ''}
|
|
298
|
+
onChange={e => update({ targetPage: e.target.value })} />
|
|
299
|
+
</div>
|
|
300
|
+
</FieldRow>
|
|
301
|
+
</div>
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
export function BackEditor() {
|
|
306
|
+
return (
|
|
307
|
+
<div className="text-sm text-muted-foreground py-4">
|
|
308
|
+
Pops the last page from navigation history. No configuration needed.
|
|
309
|
+
</div>
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
export function TagEditor({ value }: { value: NodeData }) {
|
|
314
|
+
const { comp, update } = useActionComp(value.$path);
|
|
315
|
+
if (!comp) return null;
|
|
316
|
+
const t = comp as unknown as TagAction;
|
|
317
|
+
|
|
318
|
+
return (
|
|
319
|
+
<div className="space-y-4 max-w-2xl">
|
|
320
|
+
<FieldRow label="Tag name">
|
|
321
|
+
<Input placeholder="admin" value={t.tag} onChange={e => update({ tag: e.target.value })} />
|
|
322
|
+
</FieldRow>
|
|
323
|
+
<FieldRow label="Value">
|
|
324
|
+
<Input className="font-mono" placeholder="true" value={t.value}
|
|
325
|
+
onChange={e => update({ value: e.target.value })} />
|
|
326
|
+
</FieldRow>
|
|
327
|
+
</div>
|
|
328
|
+
);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
export function BroadcastEditor({ value }: { value: NodeData }) {
|
|
332
|
+
const { comp, update } = useActionComp(value.$path);
|
|
333
|
+
if (!comp) return null;
|
|
334
|
+
const b = comp as unknown as BroadcastAction;
|
|
335
|
+
|
|
336
|
+
return (
|
|
337
|
+
<div className="space-y-4 max-w-2xl">
|
|
338
|
+
<FieldRow label="User tags">
|
|
339
|
+
<Input placeholder="premium, active" value={b.userTags.join(', ')}
|
|
340
|
+
onChange={e => update({ userTags: e.target.value.split(',').map(s => s.trim()).filter(Boolean) })} />
|
|
341
|
+
</FieldRow>
|
|
342
|
+
<FieldRow label="Action path">
|
|
343
|
+
<Input className="font-mono" placeholder="/path/to/action"
|
|
344
|
+
value={b.action} onChange={e => update({ action: e.target.value })} />
|
|
345
|
+
</FieldRow>
|
|
346
|
+
</div>
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
export function GetValueEditor({ value }: { value: NodeData }) {
|
|
351
|
+
const { comp, update } = useActionComp(value.$path);
|
|
352
|
+
if (!comp) return null;
|
|
353
|
+
const g = comp as unknown as GetValueAction;
|
|
354
|
+
|
|
355
|
+
return (
|
|
356
|
+
<div className="space-y-4 max-w-2xl">
|
|
357
|
+
<FieldRow label="Source path">
|
|
358
|
+
<Input className="font-mono" placeholder="session.data.name"
|
|
359
|
+
value={g.path} onChange={e => update({ path: e.target.value })} />
|
|
360
|
+
</FieldRow>
|
|
361
|
+
<FieldRow label="Save to">
|
|
362
|
+
<Input className="font-mono" placeholder="result"
|
|
363
|
+
value={g.saveTo} onChange={e => update({ saveTo: e.target.value })} />
|
|
364
|
+
</FieldRow>
|
|
365
|
+
</div>
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
export function SetValueEditor({ value }: { value: NodeData }) {
|
|
370
|
+
const { comp, update } = useActionComp(value.$path);
|
|
371
|
+
if (!comp) return null;
|
|
372
|
+
const s = comp as unknown as SetValueAction;
|
|
373
|
+
|
|
374
|
+
return (
|
|
375
|
+
<div className="space-y-4 max-w-2xl">
|
|
376
|
+
<FieldRow label="Value">
|
|
377
|
+
<Input className="font-mono" placeholder="'hello'" value={s.value}
|
|
378
|
+
onChange={e => update({ value: e.target.value })} />
|
|
379
|
+
</FieldRow>
|
|
380
|
+
<FieldRow label="Save to">
|
|
381
|
+
<Input className="font-mono" placeholder="session.data.greeting"
|
|
382
|
+
value={s.saveTo} onChange={e => update({ saveTo: e.target.value })} />
|
|
383
|
+
</FieldRow>
|
|
384
|
+
</div>
|
|
385
|
+
);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
export function ParamsEditor({ value }: { value: NodeData }) {
|
|
389
|
+
const { comp, update } = useActionComp(value.$path);
|
|
390
|
+
if (!comp) return null;
|
|
391
|
+
const p = comp as unknown as ParamsAction;
|
|
392
|
+
|
|
393
|
+
return (
|
|
394
|
+
<div className="space-y-4 max-w-2xl">
|
|
395
|
+
<FieldRow label="Base64 decode">
|
|
396
|
+
<Checkbox checked={p.base64} onChange={e => update({ base64: e.target.checked })} />
|
|
397
|
+
</FieldRow>
|
|
398
|
+
<FieldRow label="Split delimiter">
|
|
399
|
+
<Input className="w-20 font-mono" value={p.split}
|
|
400
|
+
onChange={e => update({ split: e.target.value })} />
|
|
401
|
+
</FieldRow>
|
|
402
|
+
<FieldRow label="Param names">
|
|
403
|
+
<Input placeholder="id, name, email" value={p.names.join(', ')}
|
|
404
|
+
onChange={e => update({ names: e.target.value.split(',').map(s => s.trim()).filter(Boolean) })} />
|
|
405
|
+
</FieldRow>
|
|
406
|
+
</div>
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
export function FileEditor({ value }: { value: NodeData }) {
|
|
411
|
+
const { comp, update } = useActionComp(value.$path);
|
|
412
|
+
if (!comp) return null;
|
|
413
|
+
const f = comp as unknown as FileAction;
|
|
414
|
+
|
|
415
|
+
return (
|
|
416
|
+
<div className="space-y-4 max-w-2xl">
|
|
417
|
+
<FieldRow label="File path">
|
|
418
|
+
<Input className="font-mono" placeholder="/files/image.png"
|
|
419
|
+
value={f.fileId} onChange={e => update({ fileId: e.target.value })} />
|
|
420
|
+
</FieldRow>
|
|
421
|
+
<FieldRow label="Send as">
|
|
422
|
+
<select className="h-8 text-sm border border-border rounded-md bg-background px-2"
|
|
423
|
+
value={f.asType} onChange={e => update({ asType: e.target.value })}>
|
|
424
|
+
<option value="">Auto-detect</option>
|
|
425
|
+
<option value="photo">Photo</option>
|
|
426
|
+
<option value="document">Document</option>
|
|
427
|
+
<option value="video">Video</option>
|
|
428
|
+
<option value="audio">Audio</option>
|
|
429
|
+
<option value="voice">Voice</option>
|
|
430
|
+
</select>
|
|
431
|
+
</FieldRow>
|
|
432
|
+
</div>
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// ── New action editors ──
|
|
437
|
+
|
|
438
|
+
export function EvalEditor({ value }: { value: NodeData }) {
|
|
439
|
+
const { comp, update } = useActionComp(value.$path);
|
|
440
|
+
if (!comp) return null;
|
|
441
|
+
const ev = comp as unknown as EvalAction;
|
|
442
|
+
|
|
443
|
+
return (
|
|
444
|
+
<div className="space-y-4 max-w-2xl">
|
|
445
|
+
<FieldRow label="JavaScript">
|
|
446
|
+
<textarea
|
|
447
|
+
className="w-full h-40 text-sm font-mono border border-border rounded-md bg-background p-2 resize-y"
|
|
448
|
+
placeholder="// async function body await ctx.reply('Hello');"
|
|
449
|
+
value={ev.value}
|
|
450
|
+
onChange={e => update({ value: e.target.value })}
|
|
451
|
+
/>
|
|
452
|
+
</FieldRow>
|
|
453
|
+
</div>
|
|
454
|
+
);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
export function RemoveEditor() {
|
|
458
|
+
return (
|
|
459
|
+
<div className="text-sm text-muted-foreground py-4">
|
|
460
|
+
Deletes the current message. No configuration needed.
|
|
461
|
+
</div>
|
|
462
|
+
);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
export function EmitTextEditor({ value }: { value: NodeData }) {
|
|
466
|
+
const { comp, update } = useActionComp(value.$path);
|
|
467
|
+
if (!comp) return null;
|
|
468
|
+
const et = comp as unknown as EmitTextAction;
|
|
469
|
+
|
|
470
|
+
return (
|
|
471
|
+
<div className="space-y-4 max-w-2xl">
|
|
472
|
+
<FieldRow label="Text template">
|
|
473
|
+
<Input className="font-mono" placeholder="/start or {data.command}"
|
|
474
|
+
value={et.from} onChange={e => update({ from: e.target.value })} />
|
|
475
|
+
</FieldRow>
|
|
476
|
+
</div>
|
|
477
|
+
);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
export function ForwardEditor({ value }: { value: NodeData }) {
|
|
481
|
+
const { comp, update } = useActionComp(value.$path);
|
|
482
|
+
if (!comp) return null;
|
|
483
|
+
const fw = comp as unknown as ForwardAction;
|
|
484
|
+
|
|
485
|
+
return (
|
|
486
|
+
<div className="space-y-4 max-w-2xl">
|
|
487
|
+
<FieldRow label="Message ID from">
|
|
488
|
+
<Input className="font-mono" placeholder="Empty = current message"
|
|
489
|
+
value={fw.msgIdFrom} onChange={e => update({ msgIdFrom: e.target.value })} />
|
|
490
|
+
</FieldRow>
|
|
491
|
+
<FieldRow label="Forward to">
|
|
492
|
+
<Input className="font-mono" placeholder="Chat/user ID or {data.to}"
|
|
493
|
+
value={fw.toFrom} onChange={e => update({ toFrom: e.target.value })} />
|
|
494
|
+
</FieldRow>
|
|
495
|
+
</div>
|
|
496
|
+
);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
export function ResetSessionEditor() {
|
|
500
|
+
return (
|
|
501
|
+
<div className="text-sm text-muted-foreground py-4">
|
|
502
|
+
Clears all session data. History is preserved. No configuration needed.
|
|
503
|
+
</div>
|
|
504
|
+
);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
export function ResetHistoryEditor() {
|
|
508
|
+
return (
|
|
509
|
+
<div className="text-sm text-muted-foreground py-4">
|
|
510
|
+
Clears navigation history. No configuration needed.
|
|
511
|
+
</div>
|
|
512
|
+
);
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
export function OnErrorEditor({ value }: { value: NodeData }) {
|
|
516
|
+
const { comp, update } = useActionComp(value.$path);
|
|
517
|
+
if (!comp) return null;
|
|
518
|
+
const oe = comp as unknown as OnErrorAction;
|
|
519
|
+
|
|
520
|
+
return (
|
|
521
|
+
<div className="space-y-4 max-w-2xl">
|
|
522
|
+
<FieldRow label="Error match">
|
|
523
|
+
<Input placeholder="Substring to match in error message (empty = any)"
|
|
524
|
+
value={oe.error} onChange={e => update({ error: e.target.value })} />
|
|
525
|
+
</FieldRow>
|
|
526
|
+
<FieldRow label="Action path">
|
|
527
|
+
<Input className="font-mono" placeholder="/path/to/action"
|
|
528
|
+
value={oe.action} onChange={e => update({ action: e.target.value })} />
|
|
529
|
+
</FieldRow>
|
|
530
|
+
</div>
|
|
531
|
+
);
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
export function KeywordSelectEditor({ value }: { value: NodeData }) {
|
|
535
|
+
const { comp, update } = useActionComp(value.$path);
|
|
536
|
+
if (!comp) return null;
|
|
537
|
+
const ks = comp as unknown as KeywordSelectAction;
|
|
538
|
+
|
|
539
|
+
function updateElement(idx: number, patch: Partial<{ keywords: string[]; message: string }>) {
|
|
540
|
+
const elements = [...(ks.elements ?? [])];
|
|
541
|
+
elements[idx] = { ...elements[idx], ...patch };
|
|
542
|
+
update({ elements });
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
function addElement() {
|
|
546
|
+
update({ elements: [...(ks.elements ?? []), { keywords: [], message: '' }] });
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
function removeElement(idx: number) {
|
|
550
|
+
const elements = [...(ks.elements ?? [])];
|
|
551
|
+
elements.splice(idx, 1);
|
|
552
|
+
update({ elements });
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
return (
|
|
556
|
+
<div className="space-y-4 max-w-2xl">
|
|
557
|
+
<FieldRow label="Source text">
|
|
558
|
+
<Input className="font-mono" placeholder="{data.text} or empty for message text"
|
|
559
|
+
value={ks.textFrom} onChange={e => update({ textFrom: e.target.value })} />
|
|
560
|
+
</FieldRow>
|
|
561
|
+
|
|
562
|
+
<div className="space-y-2">
|
|
563
|
+
<label className="text-xs font-medium text-muted-foreground">Keyword entries</label>
|
|
564
|
+
{(ks.elements ?? []).map((el, i) => (
|
|
565
|
+
<div key={i} className="flex gap-2 items-start p-2 border border-border rounded-md">
|
|
566
|
+
<div className="flex-1 space-y-1">
|
|
567
|
+
<Input placeholder="keyword1, keyword2" value={el.keywords.join(', ')}
|
|
568
|
+
onChange={e => updateElement(i, {
|
|
569
|
+
keywords: e.target.value.split(',').map(s => s.trim()).filter(Boolean),
|
|
570
|
+
})} />
|
|
571
|
+
<Input className="font-mono" placeholder="/command or reply text"
|
|
572
|
+
value={el.message} onChange={e => updateElement(i, { message: e.target.value })} />
|
|
573
|
+
</div>
|
|
574
|
+
<button onClick={() => removeElement(i)}
|
|
575
|
+
className="text-muted-foreground hover:text-destructive p-1">
|
|
576
|
+
<Trash2 className="h-4 w-4" />
|
|
577
|
+
</button>
|
|
578
|
+
</div>
|
|
579
|
+
))}
|
|
580
|
+
<button onClick={addElement}
|
|
581
|
+
className="text-xs text-primary hover:underline">
|
|
582
|
+
+ Add keyword entry
|
|
583
|
+
</button>
|
|
584
|
+
</div>
|
|
585
|
+
</div>
|
|
586
|
+
);
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
export function SelectLanguageEditor({ value }: { value: NodeData }) {
|
|
590
|
+
const { comp, update, langs } = useActionComp(value.$path);
|
|
591
|
+
if (!comp) return null;
|
|
592
|
+
const sl = comp as unknown as SelectLanguageAction;
|
|
593
|
+
|
|
594
|
+
return (
|
|
595
|
+
<div className="space-y-4 max-w-2xl">
|
|
596
|
+
<FieldRow label="Prompt text">
|
|
597
|
+
<TStringInput value={sl.text} onChange={text => update({ text })} langs={langs} />
|
|
598
|
+
</FieldRow>
|
|
599
|
+
</div>
|
|
600
|
+
);
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
// ── Compact list items (react:list context) ──
|
|
604
|
+
|
|
605
|
+
export function ActionListItem({ value }: { value: NodeData }) {
|
|
606
|
+
return (
|
|
607
|
+
<div className="flex items-center gap-2 py-1 flex-1">
|
|
608
|
+
{actionIcon(value.$type)}
|
|
609
|
+
<span className="text-xs font-medium text-muted-foreground">
|
|
610
|
+
{value.$type.split('.').at(-1)}
|
|
611
|
+
</span>
|
|
612
|
+
<span className="text-sm truncate">{actionSummary(value)}</span>
|
|
613
|
+
</div>
|
|
614
|
+
);
|
|
615
|
+
}
|