@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
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
declare class TodoItem {
|
|
2
|
+
title: string;
|
|
3
|
+
done: boolean;
|
|
4
|
+
/** @description Toggle done state */
|
|
5
|
+
toggle(): void;
|
|
6
|
+
}
|
|
7
|
+
declare class TodoList {
|
|
8
|
+
title: string;
|
|
9
|
+
/** @description Add a new todo item */
|
|
10
|
+
add(data: {
|
|
11
|
+
title: string;
|
|
12
|
+
}): Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
export { TodoItem, TodoList };
|
|
15
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../todo/types.ts"],"names":[],"mappings":"AAEA,cAAM,QAAQ;IACZ,KAAK,SAAM;IACX,IAAI,UAAS;IAEb,qCAAqC;IACrC,MAAM;CAGP;AAED,cAAM,QAAQ;IACZ,KAAK,SAAc;IAEnB,uCAAuC;IACjC,GAAG,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE;CAWlC;AAID,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { getCtx, registerType } from '@treenity/core/comp';
|
|
2
|
+
class TodoItem {
|
|
3
|
+
title = '';
|
|
4
|
+
done = false;
|
|
5
|
+
/** @description Toggle done state */
|
|
6
|
+
toggle() {
|
|
7
|
+
this.done = !this.done;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
class TodoList {
|
|
11
|
+
title = 'My Todos';
|
|
12
|
+
/** @description Add a new todo item */
|
|
13
|
+
async add(data) {
|
|
14
|
+
if (!data.title?.trim())
|
|
15
|
+
throw new Error('Title required');
|
|
16
|
+
const { node, store } = getCtx();
|
|
17
|
+
const id = Date.now().toString(36);
|
|
18
|
+
await store.set({
|
|
19
|
+
$path: `${node.$path}/${id}`,
|
|
20
|
+
$type: 'todo.item',
|
|
21
|
+
title: data.title.trim(),
|
|
22
|
+
done: false,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
registerType('todo.item', TodoItem);
|
|
27
|
+
registerType('todo.list', TodoList);
|
|
28
|
+
export { TodoItem, TodoList };
|
|
29
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../todo/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAE3D,MAAM,QAAQ;IACZ,KAAK,GAAG,EAAE,CAAC;IACX,IAAI,GAAG,KAAK,CAAC;IAEb,qCAAqC;IACrC,MAAM;QACJ,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;IACzB,CAAC;CACF;AAED,MAAM,QAAQ;IACZ,KAAK,GAAG,UAAU,CAAC;IAEnB,uCAAuC;IACvC,KAAK,CAAC,GAAG,CAAC,IAAuB;QAC/B,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;QAC3D,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,EAAE,CAAC;QACjC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACnC,MAAM,KAAK,CAAC,GAAG,CAAC;YACd,KAAK,EAAE,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,EAAE;YAC5B,KAAK,EAAE,WAAW;YAClB,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;YACxB,IAAI,EAAE,KAAK;SACZ,CAAC,CAAC;IACL,CAAC;CACF;AAED,YAAY,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;AACpC,YAAY,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../../todo/view.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { register } from '@treenity/core';
|
|
3
|
+
import { useChildren, usePath } from '@treenity/react/hooks';
|
|
4
|
+
import { useState } from 'react';
|
|
5
|
+
import { TodoItem, TodoList } from './types';
|
|
6
|
+
function TodoListView({ value }) {
|
|
7
|
+
const list = usePath(value.$path, TodoList);
|
|
8
|
+
const children = useChildren(value.$path, { watch: true, watchNew: true });
|
|
9
|
+
const [draft, setDraft] = useState('');
|
|
10
|
+
const handleAdd = async () => {
|
|
11
|
+
if (!draft.trim())
|
|
12
|
+
return;
|
|
13
|
+
await list.add({ title: draft });
|
|
14
|
+
setDraft('');
|
|
15
|
+
};
|
|
16
|
+
return (_jsxs("div", { className: "max-w-md mx-auto p-4", children: [_jsx("h2", { className: "text-xl font-bold mb-4", children: list.title }), _jsxs("div", { className: "flex gap-2 mb-4", children: [_jsx("input", { className: "flex-1 border rounded px-3 py-1.5 text-sm", placeholder: "What needs to be done?", value: draft, onChange: e => setDraft(e.target.value), onKeyDown: e => e.key === 'Enter' && handleAdd() }), _jsx("button", { className: "bg-blue-600 text-white px-3 py-1.5 rounded text-sm", onClick: handleAdd, children: "Add" })] }), _jsx("ul", { className: "space-y-1", children: children.map(child => (_jsx(TodoItemRow, { value: child }, child.$path))) })] }));
|
|
17
|
+
}
|
|
18
|
+
function TodoItemRow({ value }) {
|
|
19
|
+
const item = usePath(value.$path, TodoItem);
|
|
20
|
+
return (_jsxs("li", { className: "flex items-center gap-2 px-3 py-2 rounded\n hover:bg-neutral-100 cursor-pointer", onClick: () => item.toggle(), children: [_jsx("span", { className: `w-4 h-4 rounded border flex items-center
|
|
21
|
+
justify-center text-xs ${item.done
|
|
22
|
+
? 'bg-blue-600 border-blue-600 text-white'
|
|
23
|
+
: 'border-neutral-300'}`, children: item.done ? '✓' : '' }), _jsx("span", { className: item.done ? 'line-through text-neutral-400' : '', children: item.title })] }));
|
|
24
|
+
}
|
|
25
|
+
register('todo.list', 'react', TodoListView);
|
|
26
|
+
register('todo.item', 'react', TodoItemRow);
|
|
27
|
+
//# sourceMappingURL=view.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"view.js","sourceRoot":"","sources":["../../todo/view.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAiB,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE7C,SAAS,YAAY,CAAC,EAAE,KAAK,EAAuB;IAClD,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAC5C,MAAM,QAAQ,GAAG,WAAW,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3E,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IAEvC,MAAM,SAAS,GAAG,KAAK,IAAI,EAAE;QAC3B,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;YAAE,OAAO;QAC1B,MAAM,IAAI,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QACjC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACf,CAAC,CAAC;IAEF,OAAO,CACL,eAAK,SAAS,EAAC,sBAAsB,aACnC,aAAI,SAAS,EAAC,wBAAwB,YAAE,IAAI,CAAC,KAAK,GAAM,EAExD,eAAK,SAAS,EAAC,iBAAiB,aAC9B,gBACE,SAAS,EAAC,2CAA2C,EACrD,WAAW,EAAC,wBAAwB,EACpC,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EACvC,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,OAAO,IAAI,SAAS,EAAE,GAChD,EACF,iBACE,SAAS,EAAC,oDAAoD,EAC9D,OAAO,EAAE,SAAS,oBACP,IACT,EAEN,aAAI,SAAS,EAAC,WAAW,YACtB,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CACrB,KAAC,WAAW,IAAmB,KAAK,EAAE,KAAK,IAAzB,KAAK,CAAC,KAAK,CAAkB,CAChD,CAAC,GACC,IACD,CACP,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,EAAE,KAAK,EAAuB;IACjD,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAE5C,OAAO,CACL,cACE,SAAS,EAAC,wFAC4B,EACtC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,aAE5B,eAAM,SAAS,EAAE;iCACU,IAAI,CAAC,IAAI;oBAChC,CAAC,CAAC,wCAAwC;oBAC1C,CAAC,CAAC,oBAAoB,EAAE,YACzB,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAChB,EACP,eAAM,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC,CAAC,EAAE,YAC9D,IAAI,CAAC,KAAK,GACN,IACJ,CACN,CAAC;AACJ,CAAC;AAED,QAAQ,CAAC,WAAW,EAAE,OAAO,EAAE,YAAmB,CAAC,CAAC;AACpD,QAAQ,CAAC,WAAW,EAAE,OAAO,EAAE,WAAkB,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../whisper/client.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../whisper/client.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbox.d.ts","sourceRoot":"","sources":["../../whisper/inbox.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// Whisper → Agent bridge service
|
|
2
|
+
// Watches a whisper channel for completed transcriptions, creates agent tasks
|
|
3
|
+
import { createNode, getComponent, register } from '@treenity/core';
|
|
4
|
+
import { WhisperInbox, WhisperText } from './types';
|
|
5
|
+
const log = (msg) => console.log(`[whisper.inbox] ${msg}`);
|
|
6
|
+
function getText(node) {
|
|
7
|
+
const comp = getComponent(node, WhisperText);
|
|
8
|
+
if (!comp)
|
|
9
|
+
return undefined;
|
|
10
|
+
return comp.content && comp.content !== '...' ? comp.content : undefined;
|
|
11
|
+
}
|
|
12
|
+
register('whisper.inbox', 'service', async (node, ctx) => {
|
|
13
|
+
const config = getComponent(node, WhisperInbox);
|
|
14
|
+
if (!config)
|
|
15
|
+
throw new Error(`missing config on ${node.$path}`);
|
|
16
|
+
const sent = new Set();
|
|
17
|
+
// Mark existing COMPLETED transcriptions as already processed
|
|
18
|
+
const { items } = await ctx.store.getChildren(config.source);
|
|
19
|
+
for (const child of items) {
|
|
20
|
+
if (child.$type !== 'whisper.transcription')
|
|
21
|
+
continue;
|
|
22
|
+
if (getText(child))
|
|
23
|
+
sent.add(child.$path);
|
|
24
|
+
}
|
|
25
|
+
log(`watching ${config.source} → ${config.target} (${sent.size} existing)`);
|
|
26
|
+
const unsub = ctx.subscribe(config.source, (event) => {
|
|
27
|
+
if (event.type !== 'set' && event.type !== 'patch')
|
|
28
|
+
return;
|
|
29
|
+
ctx.store.get(event.path).then(async (n) => {
|
|
30
|
+
if (!n || n.$type !== 'whisper.transcription')
|
|
31
|
+
return;
|
|
32
|
+
if (sent.has(n.$path))
|
|
33
|
+
return;
|
|
34
|
+
const text = getText(n);
|
|
35
|
+
if (!text)
|
|
36
|
+
return;
|
|
37
|
+
sent.add(n.$path);
|
|
38
|
+
const taskId = `t-${Date.now()}`;
|
|
39
|
+
const taskPath = `${config.target}/tasks/${taskId}`;
|
|
40
|
+
await ctx.store.set(createNode(taskPath, 'agent.task', {
|
|
41
|
+
prompt: text,
|
|
42
|
+
status: 'pending',
|
|
43
|
+
createdAt: Date.now(),
|
|
44
|
+
}));
|
|
45
|
+
log(`${n.$path} → ${taskPath}`);
|
|
46
|
+
}).catch(err => console.error(`[whisper.inbox] error processing ${event.path}:`, err));
|
|
47
|
+
}, { children: true });
|
|
48
|
+
return { stop: async () => unsub() };
|
|
49
|
+
});
|
|
50
|
+
//# sourceMappingURL=inbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbox.js","sourceRoot":"","sources":["../../whisper/inbox.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Tree } from '@treenity/core/tree';
|
|
2
|
+
import { type IncomingMessage, type ServerResponse } from 'node:http';
|
|
3
|
+
export type WhisperRouteConfig = {
|
|
4
|
+
nodePath: string;
|
|
5
|
+
model: string;
|
|
6
|
+
language: string;
|
|
7
|
+
audioDir: string;
|
|
8
|
+
};
|
|
9
|
+
export declare function createWhisperHandler(cfg: WhisperRouteConfig): (req: IncomingMessage, res: ServerResponse, store: Tree) => Promise<void>;
|
|
10
|
+
//# sourceMappingURL=route.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../whisper/route.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAGhD,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AAwDtE,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,kBAAkB,IAM5C,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,OAAO,IAAI,mBAuGrE"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
// Whisper audio transcription — HTTP handler
|
|
2
|
+
// POST ?id=channel-id with audio body → create node immediately, transcribe in background, update node
|
|
3
|
+
import { pipeline } from '@huggingface/transformers';
|
|
4
|
+
import { createNode } from '@treenity/core';
|
|
5
|
+
import { newComp } from '@treenity/core/comp';
|
|
6
|
+
import { execFile } from 'node:child_process';
|
|
7
|
+
import { mkdir, readFile, unlink, writeFile } from 'node:fs/promises';
|
|
8
|
+
import { join, resolve } from 'node:path';
|
|
9
|
+
import { promisify } from 'node:util';
|
|
10
|
+
import WaveFile from 'wavefile';
|
|
11
|
+
import { WhisperAudio, WhisperChecklist, WhisperMeta, WhisperText } from './types';
|
|
12
|
+
const execFileAsync = promisify(execFile);
|
|
13
|
+
// Lazy-initialized pipelines keyed by model name
|
|
14
|
+
const pipelines = new Map();
|
|
15
|
+
function getTranscriber(model) {
|
|
16
|
+
let p = pipelines.get(model);
|
|
17
|
+
if (!p) {
|
|
18
|
+
const modelId = model.includes('/') ? model : `onnx-community/whisper-${model}`;
|
|
19
|
+
console.log(`[whisper] loading model ${modelId}...`);
|
|
20
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- pipeline() union type is too complex for TS
|
|
21
|
+
p = pipeline('automatic-speech-recognition', modelId, {
|
|
22
|
+
dtype: {
|
|
23
|
+
encoder_model: 'fp32',
|
|
24
|
+
decoder_model_merged: 'q4',
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
p.then(() => console.log(`[whisper] model ${modelId} ready`))
|
|
28
|
+
.catch((e) => {
|
|
29
|
+
console.error(`[whisper] model ${modelId} failed:`, e);
|
|
30
|
+
pipelines.delete(model); // allow retry on next request
|
|
31
|
+
});
|
|
32
|
+
pipelines.set(model, p);
|
|
33
|
+
}
|
|
34
|
+
return p;
|
|
35
|
+
}
|
|
36
|
+
function respond(res, status, body) {
|
|
37
|
+
res.writeHead(status, { 'Content-Type': 'application/json' });
|
|
38
|
+
res.end(JSON.stringify(body));
|
|
39
|
+
}
|
|
40
|
+
// Sortable time-based id: YYYYMMDD-HHmmss-SSS
|
|
41
|
+
function timeId() {
|
|
42
|
+
const d = new Date();
|
|
43
|
+
const pad = (n, w = 2) => String(n).padStart(w, '0');
|
|
44
|
+
return `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}-${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}-${pad(d.getMilliseconds(), 3)}`;
|
|
45
|
+
}
|
|
46
|
+
/** Read 16kHz mono WAV file → Float32Array for transformers.js */
|
|
47
|
+
async function readWavAsFloat32(wavPath) {
|
|
48
|
+
const buf = await readFile(wavPath);
|
|
49
|
+
const wav = new WaveFile.WaveFile(buf);
|
|
50
|
+
wav.toBitDepth('32f');
|
|
51
|
+
wav.toSampleRate(16000);
|
|
52
|
+
let samples = wav.getSamples();
|
|
53
|
+
if (Array.isArray(samples))
|
|
54
|
+
samples = samples[0];
|
|
55
|
+
return new Float32Array(samples);
|
|
56
|
+
}
|
|
57
|
+
export function createWhisperHandler(cfg) {
|
|
58
|
+
const audioDir = resolve(cfg.audioDir);
|
|
59
|
+
// Pre-warm the pipeline
|
|
60
|
+
getTranscriber(cfg.model);
|
|
61
|
+
return async (req, res, store) => {
|
|
62
|
+
if (req.method !== 'POST') {
|
|
63
|
+
return respond(res, 405, { error: 'Method not allowed' });
|
|
64
|
+
}
|
|
65
|
+
const url = new URL(req.url ?? '/', 'http://localhost');
|
|
66
|
+
const id = url.searchParams.get('id');
|
|
67
|
+
if (!id) {
|
|
68
|
+
return respond(res, 400, { error: 'Missing ?id= query parameter' });
|
|
69
|
+
}
|
|
70
|
+
const chunks = [];
|
|
71
|
+
for await (const chunk of req)
|
|
72
|
+
chunks.push(chunk);
|
|
73
|
+
const body = Buffer.concat(chunks);
|
|
74
|
+
if (body.length === 0) {
|
|
75
|
+
return respond(res, 400, { error: 'Empty request body' });
|
|
76
|
+
}
|
|
77
|
+
const mime = req.headers['content-type'] || 'audio/wav';
|
|
78
|
+
const ext = mime.includes('mp3') ? 'mp3'
|
|
79
|
+
: mime.includes('ogg') ? 'ogg'
|
|
80
|
+
: mime.includes('webm') ? 'webm'
|
|
81
|
+
: mime.includes('m4a') ? 'm4a'
|
|
82
|
+
: 'wav';
|
|
83
|
+
const noteId = timeId();
|
|
84
|
+
const filename = `${id}-${noteId}.${ext}`;
|
|
85
|
+
const filePath = join(audioDir, filename);
|
|
86
|
+
const wavPath = join(audioDir, `${id}-${noteId}_16k.wav`);
|
|
87
|
+
try {
|
|
88
|
+
await mkdir(audioDir, { recursive: true });
|
|
89
|
+
await writeFile(filePath, body);
|
|
90
|
+
// Ensure {servicePath}/{id} dir exists
|
|
91
|
+
const idDirPath = `${cfg.nodePath}/${id}`;
|
|
92
|
+
if (!(await store.get(idDirPath))) {
|
|
93
|
+
await store.set(createNode(idDirPath, 'whisper.channel', {}, {
|
|
94
|
+
checklist: newComp(WhisperChecklist, {}),
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
// 1. Create node immediately with audio — appears in tree right away
|
|
98
|
+
const nodePath = `${idDirPath}/${noteId}`;
|
|
99
|
+
const node = createNode(nodePath, 'whisper.transcription', {}, {
|
|
100
|
+
audio: newComp(WhisperAudio, { filename, size: body.length, mime }),
|
|
101
|
+
text: newComp(WhisperText, { content: '...' }),
|
|
102
|
+
meta: newComp(WhisperMeta, {
|
|
103
|
+
model: cfg.model,
|
|
104
|
+
language: cfg.language,
|
|
105
|
+
duration: 0,
|
|
106
|
+
segments: 0,
|
|
107
|
+
transcribedAt: Date.now(),
|
|
108
|
+
}),
|
|
109
|
+
});
|
|
110
|
+
await store.set(node);
|
|
111
|
+
console.log(`[whisper] ${filename} → ${nodePath} (processing...)`);
|
|
112
|
+
// 2. Respond immediately — client sees the node path
|
|
113
|
+
respond(res, 200, { path: nodePath, status: 'processing' });
|
|
114
|
+
// 3. Transcribe in background, update node when done
|
|
115
|
+
execFileAsync('ffmpeg', ['-i', filePath, '-ar', '16000', '-ac', '1', '-f', 'wav', '-y', wavPath])
|
|
116
|
+
.then(() => readWavAsFloat32(wavPath))
|
|
117
|
+
.then(async (audioData) => {
|
|
118
|
+
const transcriber = await getTranscriber(cfg.model);
|
|
119
|
+
const result = await transcriber(audioData, {
|
|
120
|
+
language: cfg.language,
|
|
121
|
+
return_timestamps: true,
|
|
122
|
+
});
|
|
123
|
+
const output = Array.isArray(result) ? result[0] : result;
|
|
124
|
+
const text = (output.text ?? '').trim();
|
|
125
|
+
const outputChunks = output.chunks;
|
|
126
|
+
const duration = outputChunks?.length
|
|
127
|
+
? (outputChunks[outputChunks.length - 1].timestamp[1] ?? 0)
|
|
128
|
+
: 0;
|
|
129
|
+
const updated = await store.get(nodePath);
|
|
130
|
+
if (!updated)
|
|
131
|
+
return;
|
|
132
|
+
updated.text = newComp(WhisperText, { content: text });
|
|
133
|
+
updated.meta = newComp(WhisperMeta, {
|
|
134
|
+
model: cfg.model,
|
|
135
|
+
language: cfg.language,
|
|
136
|
+
duration,
|
|
137
|
+
segments: outputChunks?.length ?? 0,
|
|
138
|
+
transcribedAt: Date.now(),
|
|
139
|
+
});
|
|
140
|
+
await store.set(updated);
|
|
141
|
+
console.log(`[whisper] ${nodePath} done (${outputChunks?.length ?? 0} seg, ${duration}s)`);
|
|
142
|
+
})
|
|
143
|
+
.catch((err) => console.error(`[whisper] ${nodePath} transcription failed:`, err))
|
|
144
|
+
.finally(() => {
|
|
145
|
+
unlink(wavPath).catch(() => { });
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
console.error('[whisper] transcription error:', err);
|
|
150
|
+
respond(res, 500, { error: String(err) });
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=route.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route.js","sourceRoot":"","sources":["../../whisper/route.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seed.d.ts","sourceRoot":"","sources":["../../whisper/seed.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { registerPrefab } from '@treenity/core/mod';
|
|
2
|
+
registerPrefab('whisper', 'seed', [
|
|
3
|
+
{ $path: 'whisper', $type: 'whisper.service',
|
|
4
|
+
config: {
|
|
5
|
+
$type: 'whisper.config', model: 'small', language: 'ru',
|
|
6
|
+
audioDir: './data/audio', url: '/api/notice/audio',
|
|
7
|
+
},
|
|
8
|
+
},
|
|
9
|
+
{ $path: '/sys/autostart/whisper', $type: 'ref', $ref: '/whisper' },
|
|
10
|
+
{ $path: 'whisper/inbox', $type: 'whisper.inbox',
|
|
11
|
+
source: '/whisper/default', target: '/agent' },
|
|
12
|
+
{ $path: '/sys/autostart/whisper-inbox', $type: 'ref', $ref: '/whisper/inbox' },
|
|
13
|
+
]);
|
|
14
|
+
//# sourceMappingURL=seed.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seed.js","sourceRoot":"","sources":["../../whisper/seed.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE;IAChC,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,iBAAiB;QAC1C,MAAM,EAAE;YACN,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI;YACvD,QAAQ,EAAE,cAAc,EAAE,GAAG,EAAE,mBAAmB;SACnD;KACF;IACD,EAAE,KAAK,EAAE,wBAAwB,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE;IACnE,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,eAAe;QAC9C,MAAM,EAAE,kBAAkB,EAAE,MAAM,EAAE,QAAQ,EAAE;IAChD,EAAE,KAAK,EAAE,8BAA8B,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,gBAAgB,EAAE;CAClE,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../whisper/server.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,CAAC;AACjB,OAAO,WAAW,CAAC;AACnB,OAAO,SAAS,CAAC;AACjB,OAAO,QAAQ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../whisper/server.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,CAAC;AACjB,OAAO,WAAW,CAAC;AACnB,OAAO,SAAS,CAAC;AACjB,OAAO,QAAQ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../whisper/service.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Whisper service — autostart-compatible, registers HTTP route dynamically
|
|
2
|
+
import { getComponent, register } from '@treenity/core';
|
|
3
|
+
import { routeRegistry } from '@treenity/core/server/server';
|
|
4
|
+
import { createWhisperHandler } from './route';
|
|
5
|
+
import { WhisperConfig } from './types';
|
|
6
|
+
register('whisper.service', 'service', async (node, _ctx) => {
|
|
7
|
+
const config = getComponent(node, WhisperConfig);
|
|
8
|
+
if (!config)
|
|
9
|
+
throw new Error(`[whisper] missing config on ${node.$path}`);
|
|
10
|
+
const routePath = config.url || node.$path;
|
|
11
|
+
const handler = createWhisperHandler({
|
|
12
|
+
nodePath: node.$path,
|
|
13
|
+
model: config.model,
|
|
14
|
+
language: config.language,
|
|
15
|
+
audioDir: config.audioDir,
|
|
16
|
+
});
|
|
17
|
+
routeRegistry.set(routePath, handler);
|
|
18
|
+
console.log(`[whisper] route ${routePath} (model: ${config.model})`);
|
|
19
|
+
return {
|
|
20
|
+
stop: async () => {
|
|
21
|
+
routeRegistry.delete(routePath);
|
|
22
|
+
console.log(`[whisper] unregistered ${routePath}`);
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
//# sourceMappingURL=service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../whisper/service.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAE3E,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAExC,QAAQ,CAAC,iBAAiB,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;IAC1D,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;IACjD,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;IAE1E,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC;IAC3C,MAAM,OAAO,GAAG,oBAAoB,CAAC;QACnC,QAAQ,EAAE,IAAI,CAAC,KAAK;QACpB,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,QAAQ,EAAE,MAAM,CAAC,QAAQ;KAC1B,CAAC,CAAC;IAEH,aAAa,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACtC,OAAO,CAAC,GAAG,CAAC,mBAAmB,SAAS,YAAY,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC;IAErE,OAAO;QACL,IAAI,EAAE,KAAK,IAAI,EAAE;YACf,aAAa,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YAChC,OAAO,CAAC,GAAG,CAAC,0BAA0B,SAAS,EAAE,CAAC,CAAC;QACrD,CAAC;KACF,CAAC;AACJ,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/** Speech-to-text config — Whisper model, language, audio path */
|
|
2
|
+
export declare class WhisperConfig {
|
|
3
|
+
model: string;
|
|
4
|
+
language: string;
|
|
5
|
+
audioDir: string;
|
|
6
|
+
url: string;
|
|
7
|
+
}
|
|
8
|
+
/** Audio file metadata — filename, size, MIME type */
|
|
9
|
+
export declare class WhisperAudio {
|
|
10
|
+
filename: string;
|
|
11
|
+
size: number;
|
|
12
|
+
mime: string;
|
|
13
|
+
}
|
|
14
|
+
/** Transcription result — recognized text content */
|
|
15
|
+
export declare class WhisperText {
|
|
16
|
+
/** @format textarea */
|
|
17
|
+
content: string;
|
|
18
|
+
}
|
|
19
|
+
/** Transcription metadata — model, language, duration, segments */
|
|
20
|
+
export declare class WhisperMeta {
|
|
21
|
+
model: string;
|
|
22
|
+
language: string;
|
|
23
|
+
duration: number;
|
|
24
|
+
segments: number;
|
|
25
|
+
transcribedAt: number;
|
|
26
|
+
}
|
|
27
|
+
/** Meeting checklist — action items from transcription */
|
|
28
|
+
export declare class WhisperChecklist {
|
|
29
|
+
checked: string[];
|
|
30
|
+
}
|
|
31
|
+
/** Bridge: auto-send whisper transcriptions to a task inbox */
|
|
32
|
+
export declare class WhisperInbox {
|
|
33
|
+
/** @format path @description Whisper channel to watch, e.g. /whisper/kriz */
|
|
34
|
+
source: string;
|
|
35
|
+
/** @format path @description Target inbox, e.g. /agent */
|
|
36
|
+
target: string;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../whisper/types.ts"],"names":[],"mappings":"AAEA,kEAAkE;AAClE,qBAAa,aAAa;IACxB,KAAK,SAAW;IAChB,QAAQ,SAAQ;IAChB,QAAQ,SAAkB;IAC1B,GAAG,SAAM;CACV;AAED,sDAAsD;AACtD,qBAAa,YAAY;IACvB,QAAQ,SAAM;IACd,IAAI,SAAK;IACT,IAAI,SAAe;CACpB;AAED,qDAAqD;AACrD,qBAAa,WAAW;IACtB,uBAAuB;IACvB,OAAO,SAAM;CACd;AAED,mEAAmE;AACnE,qBAAa,WAAW;IACtB,KAAK,SAAM;IACX,QAAQ,SAAM;IACd,QAAQ,SAAK;IACb,QAAQ,SAAK;IACb,aAAa,SAAK;CACnB;AAED,0DAA0D;AAC1D,qBAAa,gBAAgB;IAC3B,OAAO,EAAE,MAAM,EAAE,CAAM;CACxB;AAED,+DAA+D;AAC/D,qBAAa,YAAY;IACvB,6EAA6E;IAC7E,MAAM,SAAM;IACZ,0DAA0D;IAC1D,MAAM,SAAM;CACb"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { registerType } from '@treenity/core/comp';
|
|
2
|
+
/** Speech-to-text config — Whisper model, language, audio path */
|
|
3
|
+
export class WhisperConfig {
|
|
4
|
+
model = 'small';
|
|
5
|
+
language = 'ru';
|
|
6
|
+
audioDir = './data/audio';
|
|
7
|
+
url = ''; // override route path; empty = use node's $path
|
|
8
|
+
}
|
|
9
|
+
/** Audio file metadata — filename, size, MIME type */
|
|
10
|
+
export class WhisperAudio {
|
|
11
|
+
filename = '';
|
|
12
|
+
size = 0;
|
|
13
|
+
mime = 'audio/wav';
|
|
14
|
+
}
|
|
15
|
+
/** Transcription result — recognized text content */
|
|
16
|
+
export class WhisperText {
|
|
17
|
+
/** @format textarea */
|
|
18
|
+
content = '';
|
|
19
|
+
}
|
|
20
|
+
/** Transcription metadata — model, language, duration, segments */
|
|
21
|
+
export class WhisperMeta {
|
|
22
|
+
model = '';
|
|
23
|
+
language = '';
|
|
24
|
+
duration = 0;
|
|
25
|
+
segments = 0;
|
|
26
|
+
transcribedAt = 0;
|
|
27
|
+
}
|
|
28
|
+
/** Meeting checklist — action items from transcription */
|
|
29
|
+
export class WhisperChecklist {
|
|
30
|
+
checked = [];
|
|
31
|
+
}
|
|
32
|
+
/** Bridge: auto-send whisper transcriptions to a task inbox */
|
|
33
|
+
export class WhisperInbox {
|
|
34
|
+
/** @format path @description Whisper channel to watch, e.g. /whisper/kriz */
|
|
35
|
+
source = '';
|
|
36
|
+
/** @format path @description Target inbox, e.g. /agent */
|
|
37
|
+
target = '';
|
|
38
|
+
}
|
|
39
|
+
registerType('whisper.config', WhisperConfig);
|
|
40
|
+
registerType('whisper.audio', WhisperAudio);
|
|
41
|
+
registerType('whisper.text', WhisperText);
|
|
42
|
+
registerType('whisper.meta', WhisperMeta);
|
|
43
|
+
registerType('whisper.checklist', WhisperChecklist);
|
|
44
|
+
registerType('whisper.inbox', WhisperInbox);
|
|
45
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../whisper/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,kEAAkE;AAClE,MAAM,OAAO,aAAa;IACxB,KAAK,GAAG,OAAO,CAAC;IAChB,QAAQ,GAAG,IAAI,CAAC;IAChB,QAAQ,GAAG,cAAc,CAAC;IAC1B,GAAG,GAAG,EAAE,CAAC,CAAE,gDAAgD;CAC5D;AAED,sDAAsD;AACtD,MAAM,OAAO,YAAY;IACvB,QAAQ,GAAG,EAAE,CAAC;IACd,IAAI,GAAG,CAAC,CAAC;IACT,IAAI,GAAG,WAAW,CAAC;CACpB;AAED,qDAAqD;AACrD,MAAM,OAAO,WAAW;IACtB,uBAAuB;IACvB,OAAO,GAAG,EAAE,CAAC;CACd;AAED,mEAAmE;AACnE,MAAM,OAAO,WAAW;IACtB,KAAK,GAAG,EAAE,CAAC;IACX,QAAQ,GAAG,EAAE,CAAC;IACd,QAAQ,GAAG,CAAC,CAAC;IACb,QAAQ,GAAG,CAAC,CAAC;IACb,aAAa,GAAG,CAAC,CAAC;CACnB;AAED,0DAA0D;AAC1D,MAAM,OAAO,gBAAgB;IAC3B,OAAO,GAAa,EAAE,CAAC;CACxB;AAED,+DAA+D;AAC/D,MAAM,OAAO,YAAY;IACvB,6EAA6E;IAC7E,MAAM,GAAG,EAAE,CAAC;IACZ,0DAA0D;IAC1D,MAAM,GAAG,EAAE,CAAC;CACb;AAED,YAAY,CAAC,gBAAgB,EAAE,aAAa,CAAC,CAAC;AAC9C,YAAY,CAAC,eAAe,EAAE,YAAY,CAAC,CAAC;AAC5C,YAAY,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;AAC1C,YAAY,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;AAC1C,YAAY,CAAC,mBAAmB,EAAE,gBAAgB,CAAC,CAAC;AACpD,YAAY,CAAC,eAAe,EAAE,YAAY,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../../whisper/view.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// Whisper channel view — checklist of transcribed audio notes
|
|
3
|
+
import { register } from '@treenity/core';
|
|
4
|
+
import { set, useChildren, usePath } from '@treenity/react/hooks';
|
|
5
|
+
function ChannelView({ value }) {
|
|
6
|
+
const children = useChildren(value.$path, { watchNew: true });
|
|
7
|
+
const node = usePath(value.$path);
|
|
8
|
+
const checklist = node?.checklist;
|
|
9
|
+
const checked = new Set(checklist?.checked ?? []);
|
|
10
|
+
const items = children.filter(c => {
|
|
11
|
+
const text = c.text;
|
|
12
|
+
return text?.$type === 'whisper.text' && text.content && text.content !== '...';
|
|
13
|
+
});
|
|
14
|
+
const processing = children.filter(c => {
|
|
15
|
+
const text = c.text;
|
|
16
|
+
return text?.$type === 'whisper.text' && text.content === '...';
|
|
17
|
+
});
|
|
18
|
+
const toggle = (path) => {
|
|
19
|
+
if (!node)
|
|
20
|
+
return;
|
|
21
|
+
const next = new Set(checked);
|
|
22
|
+
if (next.has(path))
|
|
23
|
+
next.delete(path);
|
|
24
|
+
else
|
|
25
|
+
next.add(path);
|
|
26
|
+
set({ ...node, checklist: { $type: 'whisper.checklist', checked: [...next] } });
|
|
27
|
+
};
|
|
28
|
+
return (_jsxs("div", { className: "node-default-view", children: [items.map(child => {
|
|
29
|
+
const text = child.text.content;
|
|
30
|
+
const name = child.$path.slice(child.$path.lastIndexOf('/') + 1);
|
|
31
|
+
const meta = child.meta;
|
|
32
|
+
const done = checked.has(child.$path);
|
|
33
|
+
return (_jsxs("label", { className: `flex gap-2.5 px-3 py-2.5 cursor-pointer border-b border-[var(--border)] ${done ? 'opacity-50' : ''}`, children: [_jsx("input", { type: "checkbox", checked: done, onChange: () => toggle(child.$path), className: "mt-0.5 shrink-0 w-4 h-4 p-0" }), _jsxs("div", { className: "flex-1", children: [_jsx("div", { className: `text-[13px] leading-snug ${done ? 'line-through' : ''}`, children: text }), _jsxs("div", { className: "text-[11px] text-[var(--text-3)] mt-1", children: [name, meta?.duration ? ` · ${meta.duration}s` : ''] })] })] }, child.$path));
|
|
34
|
+
}), processing.map(child => {
|
|
35
|
+
const name = child.$path.slice(child.$path.lastIndexOf('/') + 1);
|
|
36
|
+
return (_jsxs("div", { className: "px-3 py-2.5 border-b border-[var(--border)] text-[var(--text-3)] text-[13px] italic", children: [name, " \u2014 transcribing..."] }, child.$path));
|
|
37
|
+
}), items.length === 0 && processing.length === 0 && (_jsx("div", { className: "node-empty", children: "No transcriptions yet" }))] }));
|
|
38
|
+
}
|
|
39
|
+
register('whisper.channel', 'react', ChannelView);
|
|
40
|
+
//# sourceMappingURL=view.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"view.js","sourceRoot":"","sources":["../../whisper/view.tsx"],"names":[],"mappings":"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"}
|