@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/sim/service.ts
ADDED
|
@@ -0,0 +1,594 @@
|
|
|
1
|
+
// AgentSim — round-based multi-agent simulation (Layer 6)
|
|
2
|
+
// Handlers = MCP-style tools: each entity type exposes action:* handlers
|
|
3
|
+
// Agents discover nearby entities + their capabilities → rich context for AI
|
|
4
|
+
// speak(to?) with hear events, move, remember, interact(target, action)
|
|
5
|
+
// No ANTHROPIC_API_KEY → mock mode (random actions for demo)
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
createNode,
|
|
9
|
+
getComponent,
|
|
10
|
+
getContextsForType,
|
|
11
|
+
getMeta,
|
|
12
|
+
type NodeData,
|
|
13
|
+
register,
|
|
14
|
+
resolve,
|
|
15
|
+
} from '@treenity/core';
|
|
16
|
+
import '@treenity/core/contexts/service';
|
|
17
|
+
import { newComp, setComp } from '@treenity/core/comp';
|
|
18
|
+
import { type ActionCtx, serverNodeHandle } from '@treenity/core/server/actions';
|
|
19
|
+
import {
|
|
20
|
+
type AgentEvent,
|
|
21
|
+
type EventEntry,
|
|
22
|
+
SimAi,
|
|
23
|
+
SimConfig,
|
|
24
|
+
SimDescriptive,
|
|
25
|
+
SimEvents,
|
|
26
|
+
SimMemory,
|
|
27
|
+
SimNearby,
|
|
28
|
+
SimPosition,
|
|
29
|
+
SimRound,
|
|
30
|
+
} from './types';
|
|
31
|
+
|
|
32
|
+
export type { EventEntry };
|
|
33
|
+
|
|
34
|
+
type Tool = { tool: string; [k: string]: unknown };
|
|
35
|
+
|
|
36
|
+
// ── Helpers ──
|
|
37
|
+
|
|
38
|
+
function dist(a: SimPosition, b: SimPosition) {
|
|
39
|
+
return Math.sqrt((a.x - b.x) ** 2 + (a.y - b.y) ** 2);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function getNearby(agent: NodeData, all: NodeData[]): NodeData[] {
|
|
43
|
+
const pos = getComponent(agent, SimPosition);
|
|
44
|
+
if (!pos) return [];
|
|
45
|
+
return all.filter((a) => {
|
|
46
|
+
if (a.$path === agent.$path) return false;
|
|
47
|
+
const ap = getComponent(a, SimPosition);
|
|
48
|
+
return ap && dist(pos, ap) <= pos.radius;
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function eName(n: NodeData): string {
|
|
53
|
+
return getComponent(n, SimDescriptive)?.name ?? n.$path.split('/').at(-1)!;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Discover registered action:* handlers for a type → MCP-style tool list with meta
|
|
57
|
+
type ActionInfo = { name: string; description?: string; params?: string };
|
|
58
|
+
|
|
59
|
+
function getEntityActions(type: string): ActionInfo[] {
|
|
60
|
+
return getContextsForType(type)
|
|
61
|
+
.filter((c) => c.startsWith('action:'))
|
|
62
|
+
.map((c) => {
|
|
63
|
+
const name = c.slice(7);
|
|
64
|
+
const meta = getMeta(type, c);
|
|
65
|
+
return {
|
|
66
|
+
name,
|
|
67
|
+
description: meta?.description as string | undefined,
|
|
68
|
+
params: meta?.params as string | undefined,
|
|
69
|
+
};
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function formatActions(actions: ActionInfo[]): string {
|
|
74
|
+
if (!actions.length) return '';
|
|
75
|
+
return actions
|
|
76
|
+
.map((a) => {
|
|
77
|
+
let s = a.name;
|
|
78
|
+
if (a.params) s += `(${a.params})`;
|
|
79
|
+
if (a.description) s += ` — ${a.description}`;
|
|
80
|
+
return s;
|
|
81
|
+
})
|
|
82
|
+
.join('; ');
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Build environment context string for AI — like collectEnvironment() in original
|
|
86
|
+
function collectEnvironment(agent: NodeData, allEntities: NodeData[]): string {
|
|
87
|
+
const near = getNearby(agent, allEntities);
|
|
88
|
+
if (!near.length) return 'Nobody and nothing nearby.';
|
|
89
|
+
|
|
90
|
+
return near
|
|
91
|
+
.map((n, i) => {
|
|
92
|
+
const d = getComponent(n, SimDescriptive);
|
|
93
|
+
const p = getComponent(n, SimPosition);
|
|
94
|
+
const actions = getEntityActions(n.$type);
|
|
95
|
+
const actionsStr = actions.length ? `\n Actions: ${formatActions(actions)}` : '';
|
|
96
|
+
return `${i + 1}. ${n.$type} "${d?.name ?? n.$path}" ${d?.icon ?? ''} at (${p?.x},${p?.y}): ${d?.description ?? ''}${actionsStr}`;
|
|
97
|
+
})
|
|
98
|
+
.join('\n');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Get per-agent event history
|
|
102
|
+
function getAgentEvents(n: NodeData): AgentEvent[] {
|
|
103
|
+
const ev = getComponent(n, SimEvents);
|
|
104
|
+
return ev?.entries ?? [];
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Append event to agent's inbox (capped at 30)
|
|
108
|
+
function pushAgentEvent(n: NodeData, event: AgentEvent) {
|
|
109
|
+
const ev = getComponent(n, SimEvents);
|
|
110
|
+
const entries = [...(ev?.entries ?? []), event].slice(-30);
|
|
111
|
+
setComp(n, SimEvents, { entries });
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// ── LLM tools — base + interact ──
|
|
115
|
+
|
|
116
|
+
const BASE_TOOLS = [
|
|
117
|
+
{
|
|
118
|
+
name: 'speak',
|
|
119
|
+
description: 'Say something. If "to" is given, direct message to that entity. Otherwise, all nearby entities hear you.',
|
|
120
|
+
input_schema: {
|
|
121
|
+
type: 'object' as const,
|
|
122
|
+
properties: {
|
|
123
|
+
message: { type: 'string', description: 'What to say' },
|
|
124
|
+
to: { type: 'string', description: 'Name of specific entity to address (optional)' },
|
|
125
|
+
},
|
|
126
|
+
required: ['message'],
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
name: 'move',
|
|
131
|
+
description: 'Move to a new position on the map.',
|
|
132
|
+
input_schema: {
|
|
133
|
+
type: 'object' as const,
|
|
134
|
+
properties: {
|
|
135
|
+
x: { type: 'number', description: 'Target X coordinate' },
|
|
136
|
+
y: { type: 'number', description: 'Target Y coordinate' },
|
|
137
|
+
},
|
|
138
|
+
required: ['x', 'y'],
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
name: 'remember',
|
|
143
|
+
description: 'Save a thought or observation to your memory.',
|
|
144
|
+
input_schema: {
|
|
145
|
+
type: 'object' as const,
|
|
146
|
+
properties: { text: { type: 'string', description: 'What to remember' } },
|
|
147
|
+
required: ['text'],
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
name: 'interact',
|
|
152
|
+
description: 'Call an action on a nearby entity. Use this to interact with items, agents, or objects you can see.',
|
|
153
|
+
input_schema: {
|
|
154
|
+
type: 'object' as const,
|
|
155
|
+
properties: {
|
|
156
|
+
target: { type: 'string', description: 'Name of the entity to interact with' },
|
|
157
|
+
action: { type: 'string', description: 'Action name to invoke (from the entity\'s available actions)' },
|
|
158
|
+
data: { type: 'object', description: 'Parameters for the action' },
|
|
159
|
+
},
|
|
160
|
+
required: ['target', 'action'],
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
];
|
|
164
|
+
|
|
165
|
+
// ── LLM call ──
|
|
166
|
+
|
|
167
|
+
async function callLLM(
|
|
168
|
+
agent: NodeData,
|
|
169
|
+
allEntities: NodeData[],
|
|
170
|
+
worldLog: EventEntry[],
|
|
171
|
+
round: number,
|
|
172
|
+
model: string,
|
|
173
|
+
): Promise<Tool[]> {
|
|
174
|
+
const apiKey = process.env.ANTHROPIC_API_KEY;
|
|
175
|
+
if (!apiKey) return mockThink(agent, allEntities);
|
|
176
|
+
|
|
177
|
+
const desc = getComponent(agent, SimDescriptive);
|
|
178
|
+
const pos = getComponent(agent, SimPosition);
|
|
179
|
+
const mem = getComponent(agent, SimMemory);
|
|
180
|
+
const ai = getComponent(agent, SimAi);
|
|
181
|
+
|
|
182
|
+
const myName = desc?.name ?? 'agent';
|
|
183
|
+
|
|
184
|
+
// Per-agent events (directed + heard)
|
|
185
|
+
const agentEvents = getAgentEvents(agent)
|
|
186
|
+
.slice(-15)
|
|
187
|
+
.map((e) => `[R${e.round}] ${e.from}→${e.to ?? 'all'} ${e.type}: ${JSON.stringify(e.data)}`)
|
|
188
|
+
.join('\n');
|
|
189
|
+
|
|
190
|
+
// Environment: nearby entities with capabilities
|
|
191
|
+
const env = collectEnvironment(agent, allEntities);
|
|
192
|
+
|
|
193
|
+
const memText = mem?.entries?.length ? mem.entries.slice(-10).join('\n') : '(empty)';
|
|
194
|
+
|
|
195
|
+
// My own actions (what others can ask me to do)
|
|
196
|
+
const myActions = getEntityActions(agent.$type);
|
|
197
|
+
|
|
198
|
+
const system = `${ai?.systemPrompt ?? `You are ${myName}.`}
|
|
199
|
+
|
|
200
|
+
You are "${myName}" ${desc?.icon ?? ''} — ${desc?.description ?? ''}
|
|
201
|
+
Position: (${pos?.x}, ${pos?.y}), hearing radius: ${pos?.radius}.
|
|
202
|
+
Your available actions others can call on you: ${formatActions(myActions) || 'none'}
|
|
203
|
+
|
|
204
|
+
Environment (nearby entities and their capabilities):
|
|
205
|
+
${env}
|
|
206
|
+
|
|
207
|
+
Your memory:
|
|
208
|
+
${memText}
|
|
209
|
+
|
|
210
|
+
${agentEvents ? `Recent events involving you:\n${agentEvents}` : 'No recent events.'}
|
|
211
|
+
|
|
212
|
+
Round ${round}. Use tools to act. You can speak (optionally TO someone), move, remember, or interact with nearby entities by calling their actions. Be concise. Stay in character.`;
|
|
213
|
+
|
|
214
|
+
const res = await fetch('https://api.anthropic.com/v1/messages', {
|
|
215
|
+
method: 'POST',
|
|
216
|
+
headers: {
|
|
217
|
+
'Content-Type': 'application/json',
|
|
218
|
+
'x-api-key': apiKey,
|
|
219
|
+
'anthropic-version': '2023-06-01',
|
|
220
|
+
},
|
|
221
|
+
body: JSON.stringify({
|
|
222
|
+
model: ai?.model ?? model,
|
|
223
|
+
max_tokens: 400,
|
|
224
|
+
system,
|
|
225
|
+
messages: [{ role: 'user', content: "It's your turn. What do you do?" }],
|
|
226
|
+
tools: BASE_TOOLS,
|
|
227
|
+
}),
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
if (!res.ok) {
|
|
231
|
+
console.error(`[sim] AI ${res.status}:`, await res.text());
|
|
232
|
+
return [];
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const body = (await res.json()) as {
|
|
236
|
+
content: { type: string; name?: string; input?: Record<string, unknown> }[];
|
|
237
|
+
};
|
|
238
|
+
return body.content
|
|
239
|
+
.filter((b) => b.type === 'tool_use')
|
|
240
|
+
.map((b) => ({ tool: b.name!, ...b.input }));
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// ── Mock mode (no API key) ──
|
|
244
|
+
|
|
245
|
+
function mockThink(agent: NodeData, all: NodeData[]): Tool[] {
|
|
246
|
+
const near = getNearby(agent, all);
|
|
247
|
+
const r = Math.random();
|
|
248
|
+
if (r < 0.35 && near.length > 0) {
|
|
249
|
+
const target = near[Math.floor(Math.random() * near.length)];
|
|
250
|
+
const msgs = ['Hello!', 'Nice day!', 'Interesting...', 'I wonder...', 'Look at that!'];
|
|
251
|
+
// 50% directed, 50% broadcast
|
|
252
|
+
const to = Math.random() < 0.5 ? eName(target) : undefined;
|
|
253
|
+
return [{ tool: 'speak', message: msgs[Math.floor(Math.random() * msgs.length)], to }];
|
|
254
|
+
}
|
|
255
|
+
if (r < 0.6) {
|
|
256
|
+
return [
|
|
257
|
+
{ tool: 'move', x: Math.floor(Math.random() * 600), y: Math.floor(Math.random() * 400) },
|
|
258
|
+
];
|
|
259
|
+
}
|
|
260
|
+
if (r < 0.8) {
|
|
261
|
+
return [{ tool: 'remember', text: `Observation at ${new Date().toLocaleTimeString()}` }];
|
|
262
|
+
}
|
|
263
|
+
// interact with nearby item/agent
|
|
264
|
+
if (near.length > 0) {
|
|
265
|
+
const target = near[Math.floor(Math.random() * near.length)];
|
|
266
|
+
const actions = getEntityActions(target.$type).filter((a) => a.name !== 'update');
|
|
267
|
+
if (actions.length > 0) {
|
|
268
|
+
return [{
|
|
269
|
+
tool: 'interact',
|
|
270
|
+
target: eName(target),
|
|
271
|
+
action: actions[Math.floor(Math.random() * actions.length)].name,
|
|
272
|
+
data: {},
|
|
273
|
+
}];
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
return [{ tool: 'remember', text: `Nothing interesting happening` }];
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// ── Node-level actions (UI control) ──
|
|
280
|
+
|
|
281
|
+
/** @description Start the agent simulation loop */
|
|
282
|
+
register('sim.world', 'action:start', async (ctx: ActionCtx) => {
|
|
283
|
+
const cfg = getComponent(ctx.node, SimConfig)!;
|
|
284
|
+
setComp(ctx.node, SimConfig, { ...cfg, running: true });
|
|
285
|
+
}, { description: 'Start the simulation' });
|
|
286
|
+
|
|
287
|
+
/** @description Stop the agent simulation loop */
|
|
288
|
+
register('sim.world', 'action:stop', async (ctx: ActionCtx) => {
|
|
289
|
+
const cfg = getComponent(ctx.node, SimConfig)!;
|
|
290
|
+
setComp(ctx.node, SimConfig, { ...cfg, running: false });
|
|
291
|
+
}, { description: 'Stop the simulation' });
|
|
292
|
+
|
|
293
|
+
/** @description Update simulation settings (roundDelay, model, dimensions) */
|
|
294
|
+
register('sim.world', 'action:set-config', async (ctx: ActionCtx, params: any) => {
|
|
295
|
+
const cfg = getComponent(ctx.node, SimConfig)!;
|
|
296
|
+
const next = { ...cfg };
|
|
297
|
+
if (params.roundDelay !== undefined) next.roundDelay = Number(params.roundDelay);
|
|
298
|
+
if (params.model !== undefined) next.model = String(params.model);
|
|
299
|
+
if (params.width !== undefined) next.width = Number(params.width);
|
|
300
|
+
if (params.height !== undefined) next.height = Number(params.height);
|
|
301
|
+
setComp(ctx.node, SimConfig, next);
|
|
302
|
+
}, { description: 'Update simulation settings', params: 'roundDelay?, model?, width?, height?' });
|
|
303
|
+
|
|
304
|
+
/** @description Add an agent or item entity to the simulation world */
|
|
305
|
+
register('sim.world', 'action:add-entity', async (ctx: ActionCtx, params: any) => {
|
|
306
|
+
const id = params.id || `e-${Date.now()}`;
|
|
307
|
+
const type = params.type || 'sim.item';
|
|
308
|
+
const path = `${ctx.node.$path}/${id}`;
|
|
309
|
+
const components: Record<string, any> = {
|
|
310
|
+
descriptive: newComp(SimDescriptive, {
|
|
311
|
+
name: params.name || id,
|
|
312
|
+
icon: params.icon || '?',
|
|
313
|
+
description: params.description || '',
|
|
314
|
+
}),
|
|
315
|
+
position: newComp(SimPosition, {
|
|
316
|
+
x: params.x ?? 300,
|
|
317
|
+
y: params.y ?? 200,
|
|
318
|
+
radius: params.radius ?? 100,
|
|
319
|
+
}),
|
|
320
|
+
};
|
|
321
|
+
if (type === 'sim.agent') {
|
|
322
|
+
components.ai = newComp(SimAi, { systemPrompt: params.systemPrompt || `You are ${params.name}.` });
|
|
323
|
+
components.memory = newComp(SimMemory, { entries: [] });
|
|
324
|
+
components.events = newComp(SimEvents, { entries: [] });
|
|
325
|
+
}
|
|
326
|
+
await ctx.store.set(createNode(path, type, {}, components));
|
|
327
|
+
}, { description: 'Add agent or item to the world', params: 'name, icon, type?, x?, y?, radius?, systemPrompt?, description?' });
|
|
328
|
+
|
|
329
|
+
// Agent actions (callable by other agents via interact, or by UI)
|
|
330
|
+
/** @description Move agent to a new position on the map */
|
|
331
|
+
register('sim.agent', 'action:move', async (ctx: ActionCtx, params: any) => {
|
|
332
|
+
const pos = getComponent(ctx.node, SimPosition)!;
|
|
333
|
+
const next = { ...pos };
|
|
334
|
+
if (params.x !== undefined) next.x = Math.round(Number(params.x));
|
|
335
|
+
if (params.y !== undefined) next.y = Math.round(Number(params.y));
|
|
336
|
+
setComp(ctx.node, SimPosition, next);
|
|
337
|
+
}, { description: 'Move to position', params: 'x, y' });
|
|
338
|
+
|
|
339
|
+
/** @description Update agent properties (systemPrompt, radius, name, icon, description) */
|
|
340
|
+
register('sim.agent', 'action:update', async (ctx: ActionCtx, params: any) => {
|
|
341
|
+
if (params.systemPrompt !== undefined) {
|
|
342
|
+
const ai = getComponent(ctx.node, SimAi)!;
|
|
343
|
+
setComp(ctx.node, SimAi, { ...ai, systemPrompt: String(params.systemPrompt) });
|
|
344
|
+
}
|
|
345
|
+
if (params.radius !== undefined) {
|
|
346
|
+
const pos = getComponent(ctx.node, SimPosition)!;
|
|
347
|
+
setComp(ctx.node, SimPosition, { ...pos, radius: Number(params.radius) });
|
|
348
|
+
}
|
|
349
|
+
if (params.name !== undefined || params.icon !== undefined || params.description !== undefined) {
|
|
350
|
+
const desc = getComponent(ctx.node, SimDescriptive)!;
|
|
351
|
+
const next = { ...desc };
|
|
352
|
+
if (params.name !== undefined) next.name = String(params.name);
|
|
353
|
+
if (params.icon !== undefined) next.icon = String(params.icon);
|
|
354
|
+
if (params.description !== undefined) next.description = String(params.description);
|
|
355
|
+
setComp(ctx.node, SimDescriptive, next);
|
|
356
|
+
}
|
|
357
|
+
}, { description: 'Update agent properties', params: 'systemPrompt?, radius?, name?, icon?, description?' });
|
|
358
|
+
|
|
359
|
+
// Item actions — example extensible types
|
|
360
|
+
/** @description Examine the item and return its description */
|
|
361
|
+
register('sim.item', 'action:examine', async (ctx: ActionCtx) => {
|
|
362
|
+
const desc = getComponent(ctx.node, SimDescriptive);
|
|
363
|
+
return { description: desc?.description ?? 'Nothing special.' };
|
|
364
|
+
}, { description: 'Look at the item closely' });
|
|
365
|
+
|
|
366
|
+
/** @description Use or interact with the item */
|
|
367
|
+
register('sim.item', 'action:use', async (ctx: ActionCtx, params: any) => {
|
|
368
|
+
const desc = getComponent(ctx.node, SimDescriptive);
|
|
369
|
+
return { result: `You used ${desc?.name ?? 'item'}. ${params.how ?? ''}` };
|
|
370
|
+
}, { description: 'Interact with the item', params: 'how?' });
|
|
371
|
+
|
|
372
|
+
// ── World Service ──
|
|
373
|
+
|
|
374
|
+
register('sim.world', 'service', async (node, ctx) => {
|
|
375
|
+
let stopped = false;
|
|
376
|
+
const wp = node.$path;
|
|
377
|
+
|
|
378
|
+
async function getAllEntities() {
|
|
379
|
+
return (await ctx.store.getChildren(wp)).items.filter(
|
|
380
|
+
(n) => n.$type === 'sim.agent' || n.$type === 'sim.item',
|
|
381
|
+
);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
async function getAgents() {
|
|
385
|
+
return (await ctx.store.getChildren(wp)).items.filter((n) => n.$type === 'sim.agent');
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
async function runRound() {
|
|
389
|
+
const world = await ctx.store.get(wp);
|
|
390
|
+
if (!world) return;
|
|
391
|
+
const cfg = getComponent(world, SimConfig);
|
|
392
|
+
if (!cfg?.running) return;
|
|
393
|
+
|
|
394
|
+
const round = getComponent(world, SimRound)!;
|
|
395
|
+
const num = round.current ?? 0;
|
|
396
|
+
const allEntities = await getAllEntities();
|
|
397
|
+
const agents = allEntities.filter((n) => n.$type === 'sim.agent');
|
|
398
|
+
if (!agents.length) return;
|
|
399
|
+
|
|
400
|
+
// Phase: thinking
|
|
401
|
+
setComp(world, SimRound, { ...round, phase: 'thinking' });
|
|
402
|
+
await ctx.store.set(world);
|
|
403
|
+
|
|
404
|
+
const log = round.log ?? [];
|
|
405
|
+
const model = cfg.model ?? 'claude-haiku-4-5-20251001';
|
|
406
|
+
|
|
407
|
+
// All agents think in parallel — quorum
|
|
408
|
+
const results = await Promise.allSettled(
|
|
409
|
+
agents.map(async (a) => ({
|
|
410
|
+
agent: a,
|
|
411
|
+
tools: await callLLM(a, allEntities, log, num, model),
|
|
412
|
+
})),
|
|
413
|
+
);
|
|
414
|
+
|
|
415
|
+
// Execute actions
|
|
416
|
+
const newEntries: EventEntry[] = [];
|
|
417
|
+
// Map name→path for interact resolution
|
|
418
|
+
const nameToPath = new Map<string, string>();
|
|
419
|
+
for (const e of allEntities) nameToPath.set(eName(e), e.$path);
|
|
420
|
+
|
|
421
|
+
for (const r of results) {
|
|
422
|
+
if (r.status !== 'fulfilled') continue;
|
|
423
|
+
const { agent, tools } = r.value;
|
|
424
|
+
const agentName = eName(agent);
|
|
425
|
+
const desc = getComponent(agent, SimDescriptive);
|
|
426
|
+
|
|
427
|
+
for (const t of tools) {
|
|
428
|
+
const ts = Date.now();
|
|
429
|
+
switch (t.tool) {
|
|
430
|
+
case 'speak': {
|
|
431
|
+
const to = t.to as string | undefined;
|
|
432
|
+
const nearAgents = getNearby(agent, agents);
|
|
433
|
+
const hearers = nearAgents.map(eName);
|
|
434
|
+
|
|
435
|
+
// Push event to directed target or all hearers
|
|
436
|
+
for (const hearer of nearAgents) {
|
|
437
|
+
const fresh = await ctx.store.get(hearer.$path);
|
|
438
|
+
if (!fresh) continue;
|
|
439
|
+
const hName = eName(fresh);
|
|
440
|
+
const eventType = to && to === hName ? 'speak' : 'hear';
|
|
441
|
+
pushAgentEvent(fresh, {
|
|
442
|
+
round: num,
|
|
443
|
+
type: eventType,
|
|
444
|
+
from: agentName,
|
|
445
|
+
to: to || undefined,
|
|
446
|
+
data: { message: t.message as string },
|
|
447
|
+
ts,
|
|
448
|
+
});
|
|
449
|
+
await ctx.store.set(fresh);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
newEntries.push({
|
|
453
|
+
round: num,
|
|
454
|
+
agent: agentName,
|
|
455
|
+
icon: desc?.icon ?? '',
|
|
456
|
+
action: to ? `speak→${to}` : 'speak',
|
|
457
|
+
data: { message: t.message as string },
|
|
458
|
+
heardBy: hearers,
|
|
459
|
+
ts,
|
|
460
|
+
});
|
|
461
|
+
break;
|
|
462
|
+
}
|
|
463
|
+
case 'move': {
|
|
464
|
+
const fresh = await ctx.store.get(agent.$path);
|
|
465
|
+
if (!fresh) break;
|
|
466
|
+
const pos = getComponent(fresh, SimPosition)!;
|
|
467
|
+
setComp(fresh, SimPosition, {
|
|
468
|
+
...pos,
|
|
469
|
+
x: Math.max(0, Math.min(cfg.width, t.x as number)),
|
|
470
|
+
y: Math.max(0, Math.min(cfg.height, t.y as number)),
|
|
471
|
+
});
|
|
472
|
+
await ctx.store.set(fresh);
|
|
473
|
+
newEntries.push({
|
|
474
|
+
round: num,
|
|
475
|
+
agent: agentName,
|
|
476
|
+
icon: desc?.icon ?? '',
|
|
477
|
+
action: 'move',
|
|
478
|
+
data: { x: t.x as number, y: t.y as number },
|
|
479
|
+
ts,
|
|
480
|
+
});
|
|
481
|
+
break;
|
|
482
|
+
}
|
|
483
|
+
case 'remember': {
|
|
484
|
+
const fresh = await ctx.store.get(agent.$path);
|
|
485
|
+
if (!fresh) break;
|
|
486
|
+
const mem = getComponent(fresh, SimMemory);
|
|
487
|
+
setComp(fresh, SimMemory, {
|
|
488
|
+
entries: [...(mem?.entries ?? []), t.text as string].slice(-20),
|
|
489
|
+
});
|
|
490
|
+
await ctx.store.set(fresh);
|
|
491
|
+
break;
|
|
492
|
+
}
|
|
493
|
+
case 'interact': {
|
|
494
|
+
const targetName = t.target as string;
|
|
495
|
+
const action = t.action as string;
|
|
496
|
+
const data = (t.data as Record<string, unknown>) ?? {};
|
|
497
|
+
const targetPath = nameToPath.get(targetName);
|
|
498
|
+
if (!targetPath) break;
|
|
499
|
+
|
|
500
|
+
const targetNode = await ctx.store.get(targetPath);
|
|
501
|
+
if (!targetNode) break;
|
|
502
|
+
|
|
503
|
+
// Check proximity
|
|
504
|
+
const near = getNearby(agent, allEntities);
|
|
505
|
+
if (!near.find((n) => n.$path === targetPath)) break;
|
|
506
|
+
|
|
507
|
+
// Resolve and call target's action handler
|
|
508
|
+
const handler = resolve(targetNode.$type, `action:${action}`);
|
|
509
|
+
if (!handler) break;
|
|
510
|
+
|
|
511
|
+
const actx: ActionCtx = {
|
|
512
|
+
node: targetNode,
|
|
513
|
+
store: ctx.store,
|
|
514
|
+
signal: AbortSignal.timeout(5000),
|
|
515
|
+
nc: serverNodeHandle(ctx.store),
|
|
516
|
+
};
|
|
517
|
+
const result = await (handler as any)(actx, data);
|
|
518
|
+
// Persist handler mutations (handlers don't call store.set — executeAction/caller does)
|
|
519
|
+
await ctx.store.set(targetNode);
|
|
520
|
+
|
|
521
|
+
// Push event to target agent's inbox
|
|
522
|
+
if (targetNode.$type === 'sim.agent') {
|
|
523
|
+
const freshTarget = await ctx.store.get(targetPath);
|
|
524
|
+
if (freshTarget) {
|
|
525
|
+
pushAgentEvent(freshTarget, {
|
|
526
|
+
round: num,
|
|
527
|
+
type: `interact:${action}`,
|
|
528
|
+
from: agentName,
|
|
529
|
+
data: { ...data, result },
|
|
530
|
+
ts,
|
|
531
|
+
});
|
|
532
|
+
await ctx.store.set(freshTarget);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
newEntries.push({
|
|
537
|
+
round: num,
|
|
538
|
+
agent: agentName,
|
|
539
|
+
icon: desc?.icon ?? '',
|
|
540
|
+
action: `${action}→${targetName}`,
|
|
541
|
+
data: { ...data, result },
|
|
542
|
+
ts,
|
|
543
|
+
});
|
|
544
|
+
break;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
// Recompute proximity links on all entities (engine-owned data)
|
|
551
|
+
const freshEntities = await getAllEntities();
|
|
552
|
+
for (const a of freshEntities) {
|
|
553
|
+
const near = getNearby(a, freshEntities);
|
|
554
|
+
setComp(a, SimNearby, { agents: near.map(eName) });
|
|
555
|
+
await ctx.store.set(a);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
// Advance round
|
|
559
|
+
const worldFresh = await ctx.store.get(wp);
|
|
560
|
+
if (!worldFresh) return;
|
|
561
|
+
setComp(worldFresh, SimRound, {
|
|
562
|
+
current: num + 1,
|
|
563
|
+
phase: 'idle',
|
|
564
|
+
log: [...log, ...newEntries].slice(-50),
|
|
565
|
+
});
|
|
566
|
+
await ctx.store.set(worldFresh);
|
|
567
|
+
console.log(`[sim] round ${num} done: ${newEntries.length} events`);
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
// Main loop
|
|
571
|
+
(async () => {
|
|
572
|
+
console.log(`[sim] started on ${wp}`);
|
|
573
|
+
while (!stopped) {
|
|
574
|
+
try {
|
|
575
|
+
const w = await ctx.store.get(wp);
|
|
576
|
+
const cfg = w ? getComponent(w, SimConfig) : null;
|
|
577
|
+
if (cfg?.running) await runRound();
|
|
578
|
+
await new Promise((r) => setTimeout(r, cfg?.roundDelay ?? 5000));
|
|
579
|
+
} catch (e: any) {
|
|
580
|
+
if (e?.message?.startsWith('OptimisticConcurrencyError')) {
|
|
581
|
+
continue;
|
|
582
|
+
}
|
|
583
|
+
console.error('[sim] error:', e);
|
|
584
|
+
await new Promise((r) => setTimeout(r, 5000));
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
})();
|
|
588
|
+
|
|
589
|
+
return {
|
|
590
|
+
stop: async () => {
|
|
591
|
+
stopped = true;
|
|
592
|
+
},
|
|
593
|
+
};
|
|
594
|
+
});
|