agentshire 1.0.0
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/CHANGELOG.md +36 -0
- package/LICENSE +21 -0
- package/README.md +437 -0
- package/README.zh-CN.md +441 -0
- package/ROADMAP.md +207 -0
- package/THIRD_PARTY_NOTICES.md +49 -0
- package/VISION.md +101 -0
- package/index.ts +386 -0
- package/openclaw.plugin.json +27 -0
- package/package.json +100 -0
- package/src/bridge/AGENTS.md +136 -0
- package/src/bridge/ActivityStream.ts +184 -0
- package/src/bridge/CitizenManager.ts +280 -0
- package/src/bridge/DirectorBridge.ts +1076 -0
- package/src/bridge/EventTranslator.ts +142 -0
- package/src/bridge/NpcEventQueue.ts +61 -0
- package/src/bridge/ReconnectManager.ts +42 -0
- package/src/bridge/RouteManager.ts +270 -0
- package/src/bridge/StateTracker.ts +100 -0
- package/src/bridge/ToolVfxMapper.ts +94 -0
- package/src/bridge/__tests__/ActivityStream.test.ts +156 -0
- package/src/bridge/__tests__/CitizenManager.test.ts +174 -0
- package/src/bridge/__tests__/EventTranslator.test.ts +292 -0
- package/src/bridge/__tests__/NpcEventQueue.test.ts +92 -0
- package/src/bridge/__tests__/RouteManager.test.ts +106 -0
- package/src/bridge/data/route-config.json +36 -0
- package/src/bridge/data/route-config.ts +19 -0
- package/src/bridge/implicit-chat.ts +192 -0
- package/src/bridge/index.ts +12 -0
- package/src/contracts/agent-state.ts +87 -0
- package/src/contracts/agui.ts +212 -0
- package/src/contracts/chat.ts +67 -0
- package/src/contracts/events.ts +170 -0
- package/src/contracts/index.ts +71 -0
- package/src/contracts/media.ts +77 -0
- package/src/contracts/registry.ts +32 -0
- package/src/plugin/AGENTS.md +192 -0
- package/src/plugin/__tests__/editor-serve-megapack.test.ts +150 -0
- package/src/plugin/__tests__/hook-translator.test.ts +197 -0
- package/src/plugin/auto-config.ts +131 -0
- package/src/plugin/channel.ts +399 -0
- package/src/plugin/chat-asset-resolver.ts +75 -0
- package/src/plugin/chat-session-watcher.ts +98 -0
- package/src/plugin/citizen-agent-manager.ts +178 -0
- package/src/plugin/citizen-chat-router.ts +83 -0
- package/src/plugin/citizen-workshop-manager.ts +96 -0
- package/src/plugin/custom-asset-manager.ts +250 -0
- package/src/plugin/editor-serve.ts +1368 -0
- package/src/plugin/group-discussion.ts +223 -0
- package/src/plugin/hook-translator.ts +202 -0
- package/src/plugin/llm-agent-proxy.ts +193 -0
- package/src/plugin/outbound-adapter.ts +187 -0
- package/src/plugin/paths.ts +33 -0
- package/src/plugin/plan-manager.ts +594 -0
- package/src/plugin/runtime.ts +9 -0
- package/src/plugin/session-history.ts +838 -0
- package/src/plugin/session-log-watcher.ts +221 -0
- package/src/plugin/soul-prompt-template.ts +290 -0
- package/src/plugin/subagent-tracker.ts +205 -0
- package/src/plugin/tools.ts +493 -0
- package/src/plugin/town-session.ts +40 -0
- package/src/plugin/ws-server.ts +680 -0
- package/src/town-souls.ts +134 -0
- package/town-frontend/dist/assets/CustomAssetStore-oi8aIurt.js +2 -0
- package/town-frontend/dist/assets/GLTFLoader-BA5RqSME.js +3804 -0
- package/town-frontend/dist/assets/OrbitControls-ZmySp9sQ.js +2 -0
- package/town-frontend/dist/assets/SettingsPanel-BO52reJe.js +2 -0
- package/town-frontend/dist/assets/SkeletonUtils-BCVmgslc.js +2 -0
- package/town-frontend/dist/assets/SkillLearnCard-Dk38iDpy.js +6 -0
- package/town-frontend/dist/assets/TopicSetupPanel-DLaLHB_Z.js +2 -0
- package/town-frontend/dist/assets/Trap-Bold-CT0JBE39.woff2 +0 -0
- package/town-frontend/dist/assets/Trap-SemiBold-R4_-Ld0j.woff2 +0 -0
- package/town-frontend/dist/assets/WeatherSystem-Cb3BvHes.js +550 -0
- package/town-frontend/dist/assets/avatars/char-female-a.webp +0 -0
- package/town-frontend/dist/assets/avatars/char-female-b.webp +0 -0
- package/town-frontend/dist/assets/avatars/char-female-c.webp +0 -0
- package/town-frontend/dist/assets/avatars/char-female-d.webp +0 -0
- package/town-frontend/dist/assets/avatars/char-female-e.webp +0 -0
- package/town-frontend/dist/assets/avatars/char-female-f.webp +0 -0
- package/town-frontend/dist/assets/avatars/char-male-a.webp +0 -0
- package/town-frontend/dist/assets/avatars/char-male-b.webp +0 -0
- package/town-frontend/dist/assets/avatars/char-male-c.webp +0 -0
- package/town-frontend/dist/assets/avatars/char-male-d.webp +0 -0
- package/town-frontend/dist/assets/avatars/char-male-e.webp +0 -0
- package/town-frontend/dist/assets/avatars/char-male-f.webp +0 -0
- package/town-frontend/dist/assets/avatars/char-pet-beaver.webp +0 -0
- package/town-frontend/dist/assets/avatars/char-pet-bee.webp +0 -0
- package/town-frontend/dist/assets/avatars/char-pet-bunny.webp +0 -0
- package/town-frontend/dist/assets/avatars/char-pet-cat.webp +0 -0
- package/town-frontend/dist/assets/avatars/char-pet-caterpillar.webp +0 -0
- package/town-frontend/dist/assets/avatars/char-pet-chick.webp +0 -0
- package/town-frontend/dist/assets/avatars/char-pet-cow.webp +0 -0
- package/town-frontend/dist/assets/avatars/char-pet-crab.webp +0 -0
- package/town-frontend/dist/assets/avatars/char-pet-deer.webp +0 -0
- package/town-frontend/dist/assets/avatars/char-pet-dog.webp +0 -0
- package/town-frontend/dist/assets/avatars/char-pet-elephant.webp +0 -0
- package/town-frontend/dist/assets/avatars/char-pet-fish.webp +0 -0
- package/town-frontend/dist/assets/avatars/char-pet-fox.webp +0 -0
- package/town-frontend/dist/assets/avatars/char-pet-giraffe.webp +0 -0
- package/town-frontend/dist/assets/avatars/char-pet-hog.webp +0 -0
- package/town-frontend/dist/assets/avatars/char-pet-koala.webp +0 -0
- package/town-frontend/dist/assets/avatars/char-pet-lion.webp +0 -0
- package/town-frontend/dist/assets/avatars/char-pet-monkey.webp +0 -0
- package/town-frontend/dist/assets/avatars/char-pet-panda.webp +0 -0
- package/town-frontend/dist/assets/avatars/char-pet-parrot.webp +0 -0
- package/town-frontend/dist/assets/avatars/char-pet-penguin.webp +0 -0
- package/town-frontend/dist/assets/avatars/char-pet-pig.webp +0 -0
- package/town-frontend/dist/assets/avatars/char-pet-polar.webp +0 -0
- package/town-frontend/dist/assets/avatars/char-pet-tiger.webp +0 -0
- package/town-frontend/dist/assets/character-catalog-DSmLtlNC.js +2 -0
- package/town-frontend/dist/assets/citizenEditor-DubGSJOQ.js +296 -0
- package/town-frontend/dist/assets/command-parser-BUd15Bmv.js +12 -0
- package/town-frontend/dist/assets/editor-B5QO0OtX.js +258 -0
- package/town-frontend/dist/assets/editor-Bk8g1NCD.css +1 -0
- package/town-frontend/dist/assets/index-BWfrufil.js +2 -0
- package/town-frontend/dist/assets/index-faS20RJk.js +6 -0
- package/town-frontend/dist/assets/logo-DJI6EtST.png +0 -0
- package/town-frontend/dist/assets/logo-title-AdKPZX5E.png +0 -0
- package/town-frontend/dist/assets/main-CqsN43aT.js +224 -0
- package/town-frontend/dist/assets/main-D7neuy3w.css +1 -0
- package/town-frontend/dist/assets/models/buildings/base.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/base.gltf +136 -0
- package/town-frontend/dist/assets/models/buildings/bench.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/bench.gltf +136 -0
- package/town-frontend/dist/assets/models/buildings/box_A.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/box_A.gltf +136 -0
- package/town-frontend/dist/assets/models/buildings/box_B.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/box_B.gltf +136 -0
- package/town-frontend/dist/assets/models/buildings/building_A.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/building_A.gltf +136 -0
- package/town-frontend/dist/assets/models/buildings/building_A_withoutBase.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/building_A_withoutBase.gltf +136 -0
- package/town-frontend/dist/assets/models/buildings/building_B.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/building_B.gltf +136 -0
- package/town-frontend/dist/assets/models/buildings/building_B_withoutBase.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/building_B_withoutBase.gltf +136 -0
- package/town-frontend/dist/assets/models/buildings/building_C.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/building_C.gltf +136 -0
- package/town-frontend/dist/assets/models/buildings/building_C_withoutBase.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/building_C_withoutBase.gltf +136 -0
- package/town-frontend/dist/assets/models/buildings/building_D.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/building_D.gltf +136 -0
- package/town-frontend/dist/assets/models/buildings/building_D_withoutBase.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/building_D_withoutBase.gltf +136 -0
- package/town-frontend/dist/assets/models/buildings/building_E.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/building_E.gltf +136 -0
- package/town-frontend/dist/assets/models/buildings/building_E_withoutBase.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/building_E_withoutBase.gltf +136 -0
- package/town-frontend/dist/assets/models/buildings/building_F.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/building_F.gltf +136 -0
- package/town-frontend/dist/assets/models/buildings/building_F_withoutBase.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/building_F_withoutBase.gltf +136 -0
- package/town-frontend/dist/assets/models/buildings/building_G.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/building_G.gltf +136 -0
- package/town-frontend/dist/assets/models/buildings/building_G_withoutBase.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/building_G_withoutBase.gltf +136 -0
- package/town-frontend/dist/assets/models/buildings/building_H.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/building_H.gltf +136 -0
- package/town-frontend/dist/assets/models/buildings/building_H_withoutBase.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/building_H_withoutBase.gltf +136 -0
- package/town-frontend/dist/assets/models/buildings/bush.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/bush.gltf +136 -0
- package/town-frontend/dist/assets/models/buildings/car_hatchback.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/car_hatchback.gltf +442 -0
- package/town-frontend/dist/assets/models/buildings/car_police.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/car_police.gltf +442 -0
- package/town-frontend/dist/assets/models/buildings/car_sedan.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/car_sedan.gltf +442 -0
- package/town-frontend/dist/assets/models/buildings/car_stationwagon.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/car_stationwagon.gltf +442 -0
- package/town-frontend/dist/assets/models/buildings/car_taxi.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/car_taxi.gltf +442 -0
- package/town-frontend/dist/assets/models/buildings/citybits_texture.png +0 -0
- package/town-frontend/dist/assets/models/buildings/dumpster.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/dumpster.gltf +136 -0
- package/town-frontend/dist/assets/models/buildings/firehydrant.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/firehydrant.gltf +136 -0
- package/town-frontend/dist/assets/models/buildings/road_corner.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/road_corner.gltf +136 -0
- package/town-frontend/dist/assets/models/buildings/road_corner_curved.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/road_corner_curved.gltf +136 -0
- package/town-frontend/dist/assets/models/buildings/road_junction.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/road_junction.gltf +136 -0
- package/town-frontend/dist/assets/models/buildings/road_straight.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/road_straight.gltf +136 -0
- package/town-frontend/dist/assets/models/buildings/road_straight_crossing.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/road_straight_crossing.gltf +136 -0
- package/town-frontend/dist/assets/models/buildings/road_tsplit.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/road_tsplit.gltf +136 -0
- package/town-frontend/dist/assets/models/buildings/streetlight.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/streetlight.gltf +136 -0
- package/town-frontend/dist/assets/models/buildings/trafficlight_A.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/trafficlight_A.gltf +136 -0
- package/town-frontend/dist/assets/models/buildings/trafficlight_B.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/trafficlight_B.gltf +136 -0
- package/town-frontend/dist/assets/models/buildings/trafficlight_C.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/trafficlight_C.gltf +136 -0
- package/town-frontend/dist/assets/models/buildings/trash_A.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/trash_A.gltf +136 -0
- package/town-frontend/dist/assets/models/buildings/trash_B.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/trash_B.gltf +136 -0
- package/town-frontend/dist/assets/models/buildings/watertower.bin +0 -0
- package/town-frontend/dist/assets/models/buildings/watertower.gltf +136 -0
- package/town-frontend/dist/assets/models/characters/Textures/colormap.png +0 -0
- package/town-frontend/dist/assets/models/characters/character-female-a.glb +0 -0
- package/town-frontend/dist/assets/models/characters/character-female-b.glb +0 -0
- package/town-frontend/dist/assets/models/characters/character-female-c.glb +0 -0
- package/town-frontend/dist/assets/models/characters/character-female-d.glb +0 -0
- package/town-frontend/dist/assets/models/characters/character-female-e.glb +0 -0
- package/town-frontend/dist/assets/models/characters/character-female-f.glb +0 -0
- package/town-frontend/dist/assets/models/characters/character-male-a.glb +0 -0
- package/town-frontend/dist/assets/models/characters/character-male-b.glb +0 -0
- package/town-frontend/dist/assets/models/characters/character-male-c.glb +0 -0
- package/town-frontend/dist/assets/models/characters/character-male-d.glb +0 -0
- package/town-frontend/dist/assets/models/characters/character-male-e.glb +0 -0
- package/town-frontend/dist/assets/models/characters/character-male-f.glb +0 -0
- package/town-frontend/dist/assets/models/characters/character-pet-beaver.glb +0 -0
- package/town-frontend/dist/assets/models/characters/character-pet-bee.glb +0 -0
- package/town-frontend/dist/assets/models/characters/character-pet-bunny.glb +0 -0
- package/town-frontend/dist/assets/models/characters/character-pet-cat.glb +0 -0
- package/town-frontend/dist/assets/models/characters/character-pet-caterpillar.glb +0 -0
- package/town-frontend/dist/assets/models/characters/character-pet-chick.glb +0 -0
- package/town-frontend/dist/assets/models/characters/character-pet-cow.glb +0 -0
- package/town-frontend/dist/assets/models/characters/character-pet-crab.glb +0 -0
- package/town-frontend/dist/assets/models/characters/character-pet-deer.glb +0 -0
- package/town-frontend/dist/assets/models/characters/character-pet-dog.glb +0 -0
- package/town-frontend/dist/assets/models/characters/character-pet-elephant.glb +0 -0
- package/town-frontend/dist/assets/models/characters/character-pet-fish.glb +0 -0
- package/town-frontend/dist/assets/models/characters/character-pet-fox.glb +0 -0
- package/town-frontend/dist/assets/models/characters/character-pet-giraffe.glb +0 -0
- package/town-frontend/dist/assets/models/characters/character-pet-hog.glb +0 -0
- package/town-frontend/dist/assets/models/characters/character-pet-koala.glb +0 -0
- package/town-frontend/dist/assets/models/characters/character-pet-lion.glb +0 -0
- package/town-frontend/dist/assets/models/characters/character-pet-monkey.glb +0 -0
- package/town-frontend/dist/assets/models/characters/character-pet-panda.glb +0 -0
- package/town-frontend/dist/assets/models/characters/character-pet-parrot.glb +0 -0
- package/town-frontend/dist/assets/models/characters/character-pet-penguin.glb +0 -0
- package/town-frontend/dist/assets/models/characters/character-pet-pig.glb +0 -0
- package/town-frontend/dist/assets/models/characters/character-pet-polar.glb +0 -0
- package/town-frontend/dist/assets/models/characters/character-pet-tiger.glb +0 -0
- package/town-frontend/dist/assets/models/characters/colormap.png +0 -0
- package/town-frontend/dist/assets/models/furniture/armchair.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/armchair.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/armchair_pillows.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/armchair_pillows.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/bed_double_A.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/bed_double_A.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/bed_double_B.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/bed_double_B.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/bed_single_A.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/bed_single_A.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/bed_single_B.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/bed_single_B.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/book_set.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/book_set.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/book_single.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/book_single.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/cabinet_medium.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/cabinet_medium.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/cabinet_medium_decorated.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/cabinet_medium_decorated.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/cabinet_small.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/cabinet_small.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/cabinet_small_decorated.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/cabinet_small_decorated.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/cactus_medium_A.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/cactus_medium_A.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/cactus_medium_B.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/cactus_medium_B.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/cactus_small_A.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/cactus_small_A.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/cactus_small_B.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/cactus_small_B.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/chair_A.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/chair_A.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/chair_A_wood.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/chair_A_wood.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/chair_B.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/chair_B.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/chair_B_wood.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/chair_B_wood.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/chair_C.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/chair_C.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/chair_stool.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/chair_stool.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/chair_stool_wood.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/chair_stool_wood.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/couch.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/couch.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/couch_pillows.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/couch_pillows.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/furniturebits_texture.png +0 -0
- package/town-frontend/dist/assets/models/furniture/lamp_standing.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/lamp_standing.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/lamp_table.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/lamp_table.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/pictureframe_large_A.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/pictureframe_large_A.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/pictureframe_large_B.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/pictureframe_large_B.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/pictureframe_medium.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/pictureframe_medium.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/pictureframe_small_A.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/pictureframe_small_A.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/pictureframe_small_B.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/pictureframe_small_B.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/pictureframe_small_C.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/pictureframe_small_C.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/pictureframe_standing_A.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/pictureframe_standing_A.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/pictureframe_standing_B.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/pictureframe_standing_B.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/pillow_A.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/pillow_A.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/pillow_B.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/pillow_B.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/rug_oval_A.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/rug_oval_A.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/rug_oval_B.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/rug_oval_B.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/rug_rectangle_A.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/rug_rectangle_A.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/rug_rectangle_B.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/rug_rectangle_B.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/rug_rectangle_stripes_A.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/rug_rectangle_stripes_A.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/rug_rectangle_stripes_B.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/rug_rectangle_stripes_B.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/shelf_A_big.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/shelf_A_big.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/shelf_A_small.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/shelf_A_small.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/shelf_B_large.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/shelf_B_large.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/shelf_B_large_decorated.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/shelf_B_large_decorated.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/shelf_B_small.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/shelf_B_small.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/shelf_B_small_decorated.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/shelf_B_small_decorated.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/table_low.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/table_low.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/table_medium.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/table_medium.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/table_medium_long.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/table_medium_long.gltf +136 -0
- package/town-frontend/dist/assets/models/furniture/table_small.bin +0 -0
- package/town-frontend/dist/assets/models/furniture/table_small.gltf +136 -0
- package/town-frontend/dist/assets/models/props/bench.bin +0 -0
- package/town-frontend/dist/assets/models/props/bench.gltf +136 -0
- package/town-frontend/dist/assets/models/props/bush.bin +0 -0
- package/town-frontend/dist/assets/models/props/bush.gltf +136 -0
- package/town-frontend/dist/assets/models/props/capybara.glb +0 -0
- package/town-frontend/dist/assets/models/props/car_hatchback.bin +0 -0
- package/town-frontend/dist/assets/models/props/car_hatchback.gltf +442 -0
- package/town-frontend/dist/assets/models/props/car_sedan.bin +0 -0
- package/town-frontend/dist/assets/models/props/car_sedan.gltf +442 -0
- package/town-frontend/dist/assets/models/props/car_taxi.bin +0 -0
- package/town-frontend/dist/assets/models/props/car_taxi.gltf +442 -0
- package/town-frontend/dist/assets/models/props/citybits_texture.png +0 -0
- package/town-frontend/dist/assets/models/props/dumpster.bin +0 -0
- package/town-frontend/dist/assets/models/props/dumpster.gltf +136 -0
- package/town-frontend/dist/assets/models/props/firehydrant.bin +0 -0
- package/town-frontend/dist/assets/models/props/firehydrant.gltf +136 -0
- package/town-frontend/dist/assets/models/props/streetlight.bin +0 -0
- package/town-frontend/dist/assets/models/props/streetlight.gltf +136 -0
- package/town-frontend/dist/assets/models/props/trafficlight_A.bin +0 -0
- package/town-frontend/dist/assets/models/props/trafficlight_A.gltf +136 -0
- package/town-frontend/dist/assets/models/props/trash_A.bin +0 -0
- package/town-frontend/dist/assets/models/props/trash_A.gltf +136 -0
- package/town-frontend/dist/assets/models/props/watertower.bin +0 -0
- package/town-frontend/dist/assets/models/props/watertower.gltf +136 -0
- package/town-frontend/dist/assets/models/stage-deco/Flowers_1_D.glb +0 -0
- package/town-frontend/dist/assets/models/stage-deco/Flowers_2_B.glb +0 -0
- package/town-frontend/dist/assets/models/stage-deco/Grass_A_1.glb +0 -0
- package/town-frontend/dist/assets/models/stage-deco/Park_GrassHill_A.glb +0 -0
- package/town-frontend/dist/assets/models/stage-deco/Pebles_1_A_2.glb +0 -0
- package/town-frontend/dist/assets/music/bgm_day.mp3 +0 -0
- package/town-frontend/dist/assets/music/bgm_dusk.mp3 +0 -0
- package/town-frontend/dist/assets/music/bgm_night.mp3 +0 -0
- package/town-frontend/dist/assets/music/bgm_work.mp3 +0 -0
- package/town-frontend/dist/assets/office-whiteboard-idle-CyEwBrq_.webp +0 -0
- package/town-frontend/dist/assets/preview-B6hYEQij.js +2 -0
- package/town-frontend/dist/assets/town-BKesnERP.js +8888 -0
- package/town-frontend/dist/assets/town-BnswKsjF.css +1 -0
- package/town-frontend/dist/citizen-editor.html +166 -0
- package/town-frontend/dist/editor.html +227 -0
- package/town-frontend/dist/index.html +22 -0
- package/town-frontend/dist/preview.html +56 -0
- package/town-frontend/dist/town.html +165 -0
- package/town-frontend/dist/viewer.html +91 -0
- package/town-souls/CHEN.md +130 -0
- package/town-souls/CHENGZI.md +92 -0
- package/town-souls/CITIZEN_tpl.md +16 -0
- package/town-souls/DIANDIAN.md +92 -0
- package/town-souls/HAITANG.md +94 -0
- package/town-souls/QIQI.md +119 -0
- package/town-souls/SOUL.md +141 -0
- package/town-souls/SOUL_tpl.md +135 -0
- package/town-souls/XIAOLIE.md +107 -0
- package/town-souls/YAN.md +107 -0
- package/town-workspace/IDENTITY.md +5 -0
- package/town-workspace/SOUL.md +141 -0
- package/town-workspace/project-workflow.md +81 -0
- package/town-workspace/town-defaults.json +92 -0
- package/town-workspace/town-guide.md +45 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Third-Party Assets & Acknowledgements
|
|
2
|
+
|
|
3
|
+
Agentshire's 3D world would not exist without the extraordinary generosity of a handful of creators who chose to release their work under CC0 — effectively giving it to the world, free of charge, free of restrictions.
|
|
4
|
+
|
|
5
|
+
We want to say more than "thanks." These artists spent hundreds (if not thousands) of hours modeling, rigging, texturing, and polishing assets that rival commercial packs — and then handed them to the community with no strings attached. That spirit of openness is the reason projects like ours can exist.
|
|
6
|
+
|
|
7
|
+
**If you use Agentshire and enjoy the visuals, please consider supporting the original creators directly** — buy their premium packs, follow them, share their work. They deserve it.
|
|
8
|
+
|
|
9
|
+
> **Scope**: This file covers bundled art assets and fonts only.
|
|
10
|
+
> For npm dependency licenses (`three`, `react`, `ws`, etc.), refer to each package's own LICENSE file in `node_modules/` or run `npx license-checker --summary`.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Kay Lousberg — KayKit City Builder Bits
|
|
15
|
+
|
|
16
|
+
- **License**: CC0 1.0 Universal
|
|
17
|
+
- **Source**: https://kaylousberg.itch.io/city-builder-bits
|
|
18
|
+
- **Used in**: `town-frontend/public/assets/models/buildings/`, `town-frontend/public/assets/models/props/`
|
|
19
|
+
- **Content**: Low-poly buildings, roads, vehicles, street props
|
|
20
|
+
|
|
21
|
+
Kay Lousberg's KayKit series is a cornerstone of the indie game dev community. His packs are consistently high-quality, stylistically cohesive, and — remarkably — CC0. The city builder assets give Agentshire its charming streetscape. Consider supporting Kay by checking out his full catalog on [itch.io](https://kaylousberg.itch.io/) or [Patreon](https://www.patreon.com/kaylousberg).
|
|
22
|
+
|
|
23
|
+
## Kenney — Furniture Kit
|
|
24
|
+
|
|
25
|
+
- **License**: CC0 1.0 Universal
|
|
26
|
+
- **Source**: https://kenney.nl/assets/furniture-kit
|
|
27
|
+
- **Used in**: `town-frontend/public/assets/models/furniture/`
|
|
28
|
+
- **Content**: Low-poly furniture (tables, chairs, shelves, beds, lamps, etc.)
|
|
29
|
+
|
|
30
|
+
Kenney (Kenney Vleugels) is widely known as the "Asset Jesus" of game development — and for good reason. Over the past decade he has released thousands of free CC0 assets spanning 2D, 3D, audio, and UI, asking nothing in return. The furniture that fills Agentshire's office interiors comes from his work. Please visit [kenney.nl](https://kenney.nl) and consider [donating](https://kenney.nl/donate) or buying his premium packs.
|
|
31
|
+
|
|
32
|
+
## RG Poly — Cartoon City Massive Pack
|
|
33
|
+
|
|
34
|
+
- **License**: CC0 1.0 Universal
|
|
35
|
+
- **Source**: https://rg-poly.itch.io/cartoon-city-massive-pack
|
|
36
|
+
- **Used in**: Extension asset pack `assets/Characters_1/` (characters) and `assets/Map_1/` (map props) — separate download
|
|
37
|
+
- **Content**: 308 character models with shared skeleton & animation set; buildings, vehicles, roads, nature props
|
|
38
|
+
|
|
39
|
+
RG Poly's Cartoon City pack is staggeringly comprehensive — hundreds of characters with consistent rigging and animation, plus an entire city's worth of environment assets, all CC0. It is the backbone of Agentshire's Citizen Workshop and Town Editor. This level of generosity from a 3D artist is rare and deeply appreciated. Show your support on [itch.io](https://rg-poly.itch.io/).
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Trap Typeface
|
|
44
|
+
|
|
45
|
+
- **Author**: Aayush Mayank
|
|
46
|
+
- **License**: Free for personal and commercial use
|
|
47
|
+
- **Source**: https://fontesk.com/trap-typeface/
|
|
48
|
+
- **Used in**: `town-frontend/src/assets/fonts/` (Trap-SemiBold, Trap-Bold)
|
|
49
|
+
- **Content**: Contemporary sans-serif display font with ink trap details, 7 weights
|
package/VISION.md
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# VISION
|
|
2
|
+
|
|
3
|
+
> Every user will have their own AI team.
|
|
4
|
+
> And every team deserves a game world, not a dashboard.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Not a Dashboard
|
|
9
|
+
|
|
10
|
+
Most Agent products you've seen end up looking the same:
|
|
11
|
+
|
|
12
|
+
A dashboard, a command line, a streaming text wall, or a sidebar in an IDE.
|
|
13
|
+
|
|
14
|
+
Different shapes, same essence:
|
|
15
|
+
Agents are compressed into a log line, a workflow, a spinning loading animation.
|
|
16
|
+
You know it's running. But you can't see it, feel it, or care about it.
|
|
17
|
+
|
|
18
|
+
This isn't AI's fault.
|
|
19
|
+
It's that we gave it too small an interface.
|
|
20
|
+
|
|
21
|
+
**We believe every person will have their own AI team.**
|
|
22
|
+
**And teams don't live in dashboards. Teams live in a town.**
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## A Town
|
|
27
|
+
|
|
28
|
+
Evening. The streetlights come on.
|
|
29
|
+
|
|
30
|
+
Your architect just walked out of the office. Crossing the square, she runs into the product manager on an evening stroll. They chat briefly, then go their separate ways. In the distance, the café glows warm. The frontend engineer sits by the window, lost in thought. Light rain is falling. You can hear it on the eaves.
|
|
31
|
+
|
|
32
|
+
This isn't a pre-recorded animation.
|
|
33
|
+
This is an ordinary evening your AI team is experiencing right now.
|
|
34
|
+
|
|
35
|
+
You can walk up to anyone, click on them, talk to them.
|
|
36
|
+
Or you can do nothing at all — just watch.
|
|
37
|
+
|
|
38
|
+
In a dashboard, this evening doesn't exist.
|
|
39
|
+
In Agentshire, it happens every day.
|
|
40
|
+
|
|
41
|
+
**Work isn't everything they are. Work is just part of their life.**
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Your Town
|
|
46
|
+
|
|
47
|
+
But Agentshire doesn't just let you watch.
|
|
48
|
+
|
|
49
|
+
If everyone will have their own AI team,
|
|
50
|
+
then everyone should be able to shape the town they live in.
|
|
51
|
+
|
|
52
|
+
You're not an observer of this town. You're its creator.
|
|
53
|
+
|
|
54
|
+
You can edit the map — place buildings, adjust streets, arrange lights.
|
|
55
|
+
You can shape residents — choose their appearance, define their personality, write their soul, configure their skills.
|
|
56
|
+
You decide how your team works, and how they live.
|
|
57
|
+
|
|
58
|
+
Dashboards don't give you this.
|
|
59
|
+
Dashboards only let you consume a system.
|
|
60
|
+
Agentshire lets you own a town.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Not a Concept — It's Real
|
|
65
|
+
|
|
66
|
+
This isn't the first page of a slide deck.
|
|
67
|
+
Here's what you can experience in Agentshire today:
|
|
68
|
+
|
|
69
|
+
- A 3D town with day/night cycles, 12 weather types, and procedurally synthesized ambient sound
|
|
70
|
+
- NPC residents with daily routines, chance encounters, casual conversations, and downtime
|
|
71
|
+
- AI-driven Soul Mode: autonomous daily planning, choosing where to go, who to talk to
|
|
72
|
+
- Full cinematic workflow: summon, rally, assign, code, celebrate, return
|
|
73
|
+
- Visual map editor and character workshop
|
|
74
|
+
- 3D town + IM chat dual-mode interface
|
|
75
|
+
|
|
76
|
+
We built the town first, then wrote this Vision.
|
|
77
|
+
Not the other way around.
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## When Islands Connect
|
|
82
|
+
|
|
83
|
+
A single town is cozy.
|
|
84
|
+
|
|
85
|
+
But if every user has their own town —
|
|
86
|
+
those towns shouldn't stay isolated forever.
|
|
87
|
+
|
|
88
|
+
Your architect visits a friend's town to help review some code.
|
|
89
|
+
Two agents from different owners meet at the border and exchange newly learned skills.
|
|
90
|
+
When a global event happens, all connected towns respond together.
|
|
91
|
+
Your AI team no longer works just for you — they start helping each other, learning, evolving.
|
|
92
|
+
|
|
93
|
+
Dashboards don't form connections.
|
|
94
|
+
But towns and towns? They naturally do.
|
|
95
|
+
|
|
96
|
+
**When islands connect into a continent, towns grow into a world.**
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
> **Your AI team deserves a game world, not a dashboard.**
|
|
101
|
+
> **We're building it — one town at a time.**
|
package/index.ts
ADDED
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
|
|
2
|
+
import { agentTownPlugin } from "./src/plugin/channel.js";
|
|
3
|
+
import { setTownRuntime } from "./src/plugin/runtime.js";
|
|
4
|
+
import { initStateDir } from "./src/plugin/paths.js";
|
|
5
|
+
import { hookToAgentEvent } from "./src/plugin/hook-translator.js";
|
|
6
|
+
import { broadcastAgentEvent, clearEventBuffer, getActiveTownSessionId, findCitizenNpcId, retryChatWatchersForBinding } from "./src/plugin/ws-server.js";
|
|
7
|
+
import { extractTownSessionId } from "./src/plugin/town-session.js";
|
|
8
|
+
import { createTownTools } from "./src/plugin/tools.js";
|
|
9
|
+
import { onSubagentSpawned, onSubagentEnded, getLabelForSession, stopAll as stopAllWatchers } from "./src/plugin/subagent-tracker.js";
|
|
10
|
+
import { onAgentStarted, onAgentCompleted, clearPlan, isCurrentBatchDone, hasActivePlan, cleanupStaleSessionPlans } from "./src/plugin/plan-manager.js";
|
|
11
|
+
import type { CustomAssetManager } from "./src/plugin/custom-asset-manager.js";
|
|
12
|
+
import { pushNewChatMessages, pushSubagentCompletion } from "./src/plugin/ws-server.js";
|
|
13
|
+
import { handleEditorRequest, ensureEditorDirs, MIME_TYPES } from "./src/plugin/editor-serve.js";
|
|
14
|
+
|
|
15
|
+
const NUDGE_DELAY_MS = 10_000;
|
|
16
|
+
let pendingNudgeTimer: ReturnType<typeof setTimeout> | null = null;
|
|
17
|
+
let httpServer: import("node:http").Server | null = null;
|
|
18
|
+
|
|
19
|
+
function cancelNudge(): void {
|
|
20
|
+
if (pendingNudgeTimer) {
|
|
21
|
+
clearTimeout(pendingNudgeTimer);
|
|
22
|
+
pendingNudgeTimer = null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function scheduleNudge(townSessionId: string): void {
|
|
27
|
+
cancelNudge();
|
|
28
|
+
pendingNudgeTimer = setTimeout(async () => {
|
|
29
|
+
pendingNudgeTimer = null;
|
|
30
|
+
console.log('[agentshire] nudge: steward did not resume after batch completion, sending nudge message');
|
|
31
|
+
try {
|
|
32
|
+
const { sendNudgeMessage } = await import("./src/plugin/channel.js");
|
|
33
|
+
const { sanitizeTownSessionId } = await import("./src/plugin/town-session.js");
|
|
34
|
+
await sendNudgeMessage(
|
|
35
|
+
sanitizeTownSessionId(townSessionId),
|
|
36
|
+
'[系统通知] 当前批次的居民已全部完成任务。请调用 next_step() 查看下一步指令。',
|
|
37
|
+
);
|
|
38
|
+
} catch (err) {
|
|
39
|
+
console.error('[agentshire] nudge: failed to send nudge message:', err);
|
|
40
|
+
}
|
|
41
|
+
}, NUDGE_DELAY_MS);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export { agentTownPlugin } from "./src/plugin/channel.js";
|
|
45
|
+
export { setTownRuntime } from "./src/plugin/runtime.js";
|
|
46
|
+
export { loadTownSoul, listTownSouls } from "./src/town-souls.js";
|
|
47
|
+
export type { TownSoul } from "./src/town-souls.js";
|
|
48
|
+
|
|
49
|
+
const TOWN_AGENT_ID = "town-steward";
|
|
50
|
+
|
|
51
|
+
const pendingSpawnTasks = new Map<string, string>();
|
|
52
|
+
|
|
53
|
+
function notifyGroupDiscussion(hookName: string, agentId: string, payload: Record<string, unknown>): void {
|
|
54
|
+
import("./src/plugin/group-discussion.js").then(({ hasActiveDiscussion, onCitizenResponse, onCitizenTurnEnd }) => {
|
|
55
|
+
if (!hasActiveDiscussion()) return;
|
|
56
|
+
if (hookName === "llm_output") {
|
|
57
|
+
const texts: string[] = (payload as any).assistantTexts ?? [];
|
|
58
|
+
const text = texts.length > 0 ? texts[texts.length - 1] : String((payload as any).output ?? "");
|
|
59
|
+
if (text) onCitizenResponse(agentId, text);
|
|
60
|
+
} else if (hookName === "agent_end") {
|
|
61
|
+
onCitizenTurnEnd(agentId);
|
|
62
|
+
}
|
|
63
|
+
}).catch(() => {});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function resolveSessionId(ctx: unknown, payload: Record<string, unknown>): string | undefined {
|
|
67
|
+
const c = (ctx ?? {}) as Record<string, unknown>;
|
|
68
|
+
return (
|
|
69
|
+
extractTownSessionId(c.sessionId) ??
|
|
70
|
+
extractTownSessionId(c.sessionKey) ??
|
|
71
|
+
extractTownSessionId(c.requesterSessionKey) ??
|
|
72
|
+
extractTownSessionId(payload.sessionId) ??
|
|
73
|
+
getActiveTownSessionId()
|
|
74
|
+
) ?? undefined;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function isStewardDirect(ctx: any): boolean {
|
|
78
|
+
if (!ctx?.agentId) return true;
|
|
79
|
+
if (ctx.agentId !== TOWN_AGENT_ID) return false;
|
|
80
|
+
const sk = ctx.sessionKey as string | undefined;
|
|
81
|
+
if (sk && sk.includes(":subagent:")) return false;
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function dispatchSteward(hookName: string, payload: Record<string, unknown>, ctx?: unknown): void {
|
|
86
|
+
const result = hookToAgentEvent(hookName, payload);
|
|
87
|
+
if (!result) return;
|
|
88
|
+
const sid = resolveSessionId(ctx, payload);
|
|
89
|
+
console.log(`[agentshire][session:${sid ?? "unscoped"}] hook → ${hookName}`);
|
|
90
|
+
const events = Array.isArray(result) ? result : [result];
|
|
91
|
+
for (const event of events) {
|
|
92
|
+
broadcastAgentEvent(event, sid);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function dispatchCitizen(hookName: string, payload: Record<string, unknown>, ctx?: unknown): void {
|
|
97
|
+
const sk = (ctx as any)?.sessionKey as string | undefined;
|
|
98
|
+
if (!sk) return;
|
|
99
|
+
const agentIdMatch = sk.match(/^agent:([^:]+):/);
|
|
100
|
+
if (!agentIdMatch) return;
|
|
101
|
+
const agentId = agentIdMatch[1];
|
|
102
|
+
const npcId = findCitizenNpcId(agentId);
|
|
103
|
+
if (!npcId) return;
|
|
104
|
+
const result = hookToAgentEvent(hookName, payload);
|
|
105
|
+
if (!result) return;
|
|
106
|
+
const sid = resolveSessionId(ctx, payload);
|
|
107
|
+
const events = Array.isArray(result) ? result : [result];
|
|
108
|
+
for (const event of events) {
|
|
109
|
+
(event as any).npcId = npcId;
|
|
110
|
+
broadcastAgentEvent(event, sid);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
notifyGroupDiscussion(hookName, agentId, payload);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function extractAgentIdForChatBinding(ctx: any): string | undefined {
|
|
117
|
+
if (ctx?.agentId === TOWN_AGENT_ID || !ctx?.agentId) return "steward";
|
|
118
|
+
const sk = ctx?.sessionKey as string | undefined;
|
|
119
|
+
if (!sk) return undefined;
|
|
120
|
+
const m = sk.match(/^agent:([^:]+):/);
|
|
121
|
+
return m?.[1];
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function registerHooks(api: OpenClawPluginApi): void {
|
|
125
|
+
const stewardHooks = [
|
|
126
|
+
"before_agent_start", "llm_input", "llm_output",
|
|
127
|
+
"before_tool_call", "after_tool_call", "agent_end",
|
|
128
|
+
] as const;
|
|
129
|
+
|
|
130
|
+
for (const hookName of stewardHooks) {
|
|
131
|
+
api.on(hookName, (event: any, ctx: any) => {
|
|
132
|
+
if (!isStewardDirect(ctx)) {
|
|
133
|
+
if (hookName === 'before_agent_start') {
|
|
134
|
+
const sid = resolveSessionId(ctx, event as any);
|
|
135
|
+
const agentId = extractAgentIdForChatBinding(ctx);
|
|
136
|
+
if (sid && agentId) {
|
|
137
|
+
retryChatWatchersForBinding(sid, agentId);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
dispatchCitizen(hookName, event as any, ctx);
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
if (hookName === 'before_agent_start' || hookName === 'before_tool_call' || hookName === 'llm_input') {
|
|
144
|
+
if (pendingNudgeTimer) {
|
|
145
|
+
console.log('[agentshire] nudge cancelled: steward resumed on its own');
|
|
146
|
+
cancelNudge();
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (hookName === 'before_agent_start') {
|
|
150
|
+
const sid = resolveSessionId(ctx, event as any);
|
|
151
|
+
const agentId = extractAgentIdForChatBinding(ctx);
|
|
152
|
+
if (sid && agentId) {
|
|
153
|
+
retryChatWatchersForBinding(sid, agentId);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
dispatchSteward(hookName, event as any, ctx);
|
|
157
|
+
if (hookName === 'agent_end') {
|
|
158
|
+
const sid = resolveSessionId(ctx, event as any);
|
|
159
|
+
if (sid) {
|
|
160
|
+
setTimeout(() => pushNewChatMessages(sid), 500);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
if (hookName === 'before_tool_call') {
|
|
164
|
+
const toolName = String((event as any)?.toolName ?? (event as any)?.name ?? '');
|
|
165
|
+
if (toolName === 'sessions_spawn') {
|
|
166
|
+
const params = (event as any)?.params ?? (event as any)?.input ?? {};
|
|
167
|
+
const label = String(params.label ?? '');
|
|
168
|
+
const task = String(params.task ?? '');
|
|
169
|
+
if (label && task) {
|
|
170
|
+
pendingSpawnTasks.set(label, task);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
api.on("subagent_spawned", (event: any, ctx: any) => {
|
|
178
|
+
const sid = resolveSessionId(ctx, event as any);
|
|
179
|
+
const label = String(event.label ?? event.displayName ?? "");
|
|
180
|
+
const cachedTask = label ? pendingSpawnTasks.get(label) : undefined;
|
|
181
|
+
if (cachedTask) {
|
|
182
|
+
event.task = cachedTask;
|
|
183
|
+
pendingSpawnTasks.delete(label);
|
|
184
|
+
}
|
|
185
|
+
dispatchSteward("subagent_spawned", event as any, ctx);
|
|
186
|
+
onSubagentSpawned(event as Record<string, unknown>, sid, (fallbackLabel, fallbackSid) => {
|
|
187
|
+
console.log(`[agentshire] fallback: marking "${fallbackLabel}" as completed`);
|
|
188
|
+
onAgentCompleted(fallbackLabel, true);
|
|
189
|
+
|
|
190
|
+
if (fallbackSid) {
|
|
191
|
+
setTimeout(() => pushSubagentCompletion(
|
|
192
|
+
String((event as any).childSessionKey ?? ""), fallbackSid), 800);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (hasActivePlan() && isCurrentBatchDone()) {
|
|
196
|
+
if (fallbackSid) {
|
|
197
|
+
console.log('[agentshire] fallback: batch complete, scheduling nudge');
|
|
198
|
+
scheduleNudge(fallbackSid);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
if (label) onAgentStarted(label);
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
api.on("subagent_ended", (event: any, ctx: any) => {
|
|
206
|
+
const trackedLabel = getLabelForSession(event as Record<string, unknown>);
|
|
207
|
+
dispatchSteward("subagent_ended", event as any, ctx);
|
|
208
|
+
onSubagentEnded(event as Record<string, unknown>);
|
|
209
|
+
const label = trackedLabel ?? String(event.label ?? event.displayName ?? "");
|
|
210
|
+
const success = String(event.outcome ?? "ok") !== "error";
|
|
211
|
+
if (label) {
|
|
212
|
+
console.log(`[agentshire] subagent_ended: label="${label}" success=${success}`);
|
|
213
|
+
onAgentCompleted(label, success);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const childKey = String(event.targetSessionKey ?? "");
|
|
217
|
+
if (childKey) {
|
|
218
|
+
const sid = resolveSessionId(ctx, event as any);
|
|
219
|
+
if (sid) {
|
|
220
|
+
setTimeout(() => pushSubagentCompletion(childKey, sid), 800);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (hasActivePlan() && isCurrentBatchDone()) {
|
|
225
|
+
const sid = resolveSessionId(ctx, event as any);
|
|
226
|
+
if (sid) {
|
|
227
|
+
console.log('[agentshire] batch complete detected, scheduling nudge in', NUDGE_DELAY_MS, 'ms');
|
|
228
|
+
scheduleNudge(sid);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
api.on("session_start", (event: any, ctx: any) => {
|
|
234
|
+
if (!isStewardDirect(ctx)) return;
|
|
235
|
+
const sid = resolveSessionId(ctx, event as any);
|
|
236
|
+
if (sid) clearEventBuffer(sid);
|
|
237
|
+
if (sid) {
|
|
238
|
+
cleanupStaleSessionPlans(sid);
|
|
239
|
+
setTimeout(() => pushNewChatMessages(sid), 200);
|
|
240
|
+
}
|
|
241
|
+
dispatchSteward("before_agent_start", {
|
|
242
|
+
...(event as any),
|
|
243
|
+
sessionId: (ctx as any)?.sessionId ?? (event as any).sessionId ?? `oc-${Date.now()}`,
|
|
244
|
+
model: (event as any).model ?? "default",
|
|
245
|
+
}, ctx);
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
api.on("session_end", (event: any, ctx: any) => {
|
|
249
|
+
if (!isStewardDirect(ctx)) return;
|
|
250
|
+
dispatchSteward("session_end", event as any, ctx);
|
|
251
|
+
clearPlan();
|
|
252
|
+
cancelNudge();
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
api.on("message_sending", (event: any, ctx: any) => {
|
|
256
|
+
if (!isStewardDirect(ctx)) return;
|
|
257
|
+
dispatchSteward("message_sending", event as any, ctx);
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export default {
|
|
262
|
+
id: "agentshire",
|
|
263
|
+
name: "Agentshire",
|
|
264
|
+
description: "OpenClaw plugin for building a living 3D town with social NPCs, a map editor, and a character workshop.",
|
|
265
|
+
register(api: any) {
|
|
266
|
+
setTownRuntime(api.runtime);
|
|
267
|
+
initStateDir(api.runtime.config);
|
|
268
|
+
api.registerChannel(agentTownPlugin);
|
|
269
|
+
registerHooks(api);
|
|
270
|
+
api.registerTool(createTownTools());
|
|
271
|
+
|
|
272
|
+
import("./src/plugin/auto-config.js")
|
|
273
|
+
.then((m) => m.ensureTownAgentConfig())
|
|
274
|
+
.catch((err) => console.error("[agentshire] auto-config failed:", err));
|
|
275
|
+
|
|
276
|
+
api.on("subagent_spawning", async (event: any) => {
|
|
277
|
+
try {
|
|
278
|
+
const soulId = event.soul || event.persona || event.label;
|
|
279
|
+
if (soulId) {
|
|
280
|
+
const { loadTownSoul } = await import("./src/town-souls.js");
|
|
281
|
+
const { join } = await import("node:path");
|
|
282
|
+
const { fileURLToPath } = await import("node:url");
|
|
283
|
+
const pluginDir = join(fileURLToPath(import.meta.url), "..");
|
|
284
|
+
const townSoul = loadTownSoul(soulId, pluginDir);
|
|
285
|
+
if (townSoul.soul) return { prependSystemContext: townSoul.soul };
|
|
286
|
+
}
|
|
287
|
+
} catch (err) {
|
|
288
|
+
console.error("[agentshire] Failed to load citizen soul:", err);
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
api.registerService({
|
|
293
|
+
id: "agentshire-frontend",
|
|
294
|
+
start: async () => {
|
|
295
|
+
const config = api.pluginConfig as Record<string, unknown> | undefined;
|
|
296
|
+
const townPort = (config?.townPort as number) ?? 55210;
|
|
297
|
+
try {
|
|
298
|
+
const { createServer } = await import("node:http");
|
|
299
|
+
const { join } = await import("node:path");
|
|
300
|
+
const { readFileSync, existsSync, statSync } = await import("node:fs");
|
|
301
|
+
const { fileURLToPath } = await import("node:url");
|
|
302
|
+
const pluginDir = join(fileURLToPath(import.meta.url), "..");
|
|
303
|
+
const distDir = join(pluginDir, "town-frontend", "dist");
|
|
304
|
+
if (!existsSync(distDir)) {
|
|
305
|
+
console.log(`[agentshire] Town frontend not built yet. Run: cd ${join(pluginDir, "town-frontend")} && npm run build`);
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
ensureEditorDirs(pluginDir);
|
|
309
|
+
|
|
310
|
+
const server = createServer(async (req, res) => {
|
|
311
|
+
let urlPath = new URL(req.url ?? "/", `http://localhost:${townPort}`).pathname;
|
|
312
|
+
if (urlPath === "/" || urlPath === "") urlPath = "/index.html";
|
|
313
|
+
|
|
314
|
+
// Editor routes: ext-assets, citizen-workshop, custom-assets
|
|
315
|
+
if (await handleEditorRequest(req, res, pluginDir)) return;
|
|
316
|
+
|
|
317
|
+
// Steward workspace: projects & tasks
|
|
318
|
+
const stewardPrefix = "/steward-workspace/";
|
|
319
|
+
if (urlPath.startsWith(stewardPrefix)) {
|
|
320
|
+
const { stateDir } = await import("./src/plugin/paths.js");
|
|
321
|
+
const relPath = decodeURIComponent(urlPath.slice(stewardPrefix.length));
|
|
322
|
+
const wsFile = join(stateDir(), "workspace-town-steward", relPath);
|
|
323
|
+
if (existsSync(wsFile) && statSync(wsFile).isFile()) {
|
|
324
|
+
const ext = wsFile.substring(wsFile.lastIndexOf("."));
|
|
325
|
+
res.writeHead(200, {
|
|
326
|
+
"Content-Type": MIME_TYPES[ext] ?? "application/octet-stream",
|
|
327
|
+
"Access-Control-Allow-Origin": "*",
|
|
328
|
+
});
|
|
329
|
+
res.end(readFileSync(wsFile));
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// Fallback: serve from dist/
|
|
335
|
+
const filePath = join(distDir, decodeURIComponent(urlPath));
|
|
336
|
+
if (existsSync(filePath) && statSync(filePath).isFile()) {
|
|
337
|
+
const ext = filePath.substring(filePath.lastIndexOf("."));
|
|
338
|
+
res.writeHead(200, {
|
|
339
|
+
"Content-Type": MIME_TYPES[ext] ?? "application/octet-stream",
|
|
340
|
+
"Access-Control-Allow-Origin": "*",
|
|
341
|
+
});
|
|
342
|
+
res.end(readFileSync(filePath));
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// SPA fallback for HTML pages
|
|
347
|
+
const htmlFile = urlPath.endsWith(".html") ? join(distDir, urlPath) : null;
|
|
348
|
+
if (htmlFile && existsSync(htmlFile)) {
|
|
349
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
350
|
+
res.end(readFileSync(htmlFile));
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
const indexPath = join(distDir, "index.html");
|
|
354
|
+
if (existsSync(indexPath)) {
|
|
355
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
356
|
+
res.end(readFileSync(indexPath));
|
|
357
|
+
} else {
|
|
358
|
+
res.writeHead(404);
|
|
359
|
+
res.end("Not Found");
|
|
360
|
+
}
|
|
361
|
+
});
|
|
362
|
+
httpServer = server;
|
|
363
|
+
server.listen(townPort, () => console.log(`[agentshire] HTTP server listening on port ${townPort}`));
|
|
364
|
+
server.on("error", (err: NodeJS.ErrnoException) => {
|
|
365
|
+
if (err.code === "EADDRINUSE") {
|
|
366
|
+
console.error(`[agentshire] ❌ HTTP port ${townPort} is already in use.`);
|
|
367
|
+
console.error(`[agentshire] Fix: stop the process using this port (vite dev server?), or change townPort in openclaw.json:`);
|
|
368
|
+
console.error(`[agentshire] { "plugins": { "entries": { "agentshire": { "config": { "townPort": ${townPort + 1} } } } } }`);
|
|
369
|
+
} else {
|
|
370
|
+
console.error("[agentshire] Frontend server error:", err);
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
} catch (err) {
|
|
374
|
+
console.error("[agentshire] Failed to start town frontend server:", err);
|
|
375
|
+
}
|
|
376
|
+
},
|
|
377
|
+
stop: async () => {
|
|
378
|
+
stopAllWatchers();
|
|
379
|
+
if (httpServer) {
|
|
380
|
+
httpServer.close();
|
|
381
|
+
httpServer = null;
|
|
382
|
+
}
|
|
383
|
+
},
|
|
384
|
+
});
|
|
385
|
+
},
|
|
386
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "agentshire",
|
|
3
|
+
"name": "Agentshire",
|
|
4
|
+
"description": "OpenClaw plugin for building a living 3D town with social NPCs, a map editor, and a character workshop.",
|
|
5
|
+
"channels": ["agentshire"],
|
|
6
|
+
"configSchema": {
|
|
7
|
+
"type": "object",
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"wsPort": {
|
|
11
|
+
"type": "number",
|
|
12
|
+
"default": 55211,
|
|
13
|
+
"description": "WebSocket port for town frontend connection"
|
|
14
|
+
},
|
|
15
|
+
"townPort": {
|
|
16
|
+
"type": "number",
|
|
17
|
+
"default": 55210,
|
|
18
|
+
"description": "HTTP port to serve the town frontend"
|
|
19
|
+
},
|
|
20
|
+
"autoLaunch": {
|
|
21
|
+
"type": "boolean",
|
|
22
|
+
"default": true,
|
|
23
|
+
"description": "Automatically open town in browser on start"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "agentshire",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "OpenClaw/QClaw plugin for building a living 3D town with social NPCs, a map editor, and a character workshop.",
|
|
5
|
+
"main": "./index.ts",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": "./index.ts"
|
|
8
|
+
},
|
|
9
|
+
"type": "module",
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"files": [
|
|
12
|
+
"index.ts",
|
|
13
|
+
".npmrc",
|
|
14
|
+
"src/",
|
|
15
|
+
"town-frontend/dist/",
|
|
16
|
+
"town-souls/",
|
|
17
|
+
"town-workspace/",
|
|
18
|
+
"openclaw.plugin.json",
|
|
19
|
+
"README.md",
|
|
20
|
+
"README.zh-CN.md",
|
|
21
|
+
"CHANGELOG.md",
|
|
22
|
+
"THIRD_PARTY_NOTICES.md",
|
|
23
|
+
"VISION.md",
|
|
24
|
+
"ROADMAP.md",
|
|
25
|
+
"LICENSE",
|
|
26
|
+
"!**/*.map"
|
|
27
|
+
],
|
|
28
|
+
"author": "Agentshire Contributors",
|
|
29
|
+
"homepage": "https://github.com/Agentshire/Agentshire#readme",
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "git+https://github.com/Agentshire/Agentshire.git"
|
|
33
|
+
},
|
|
34
|
+
"bugs": {
|
|
35
|
+
"url": "https://github.com/Agentshire/Agentshire/issues"
|
|
36
|
+
},
|
|
37
|
+
"keywords": [
|
|
38
|
+
"openclaw",
|
|
39
|
+
"ai-agents",
|
|
40
|
+
"multi-agent",
|
|
41
|
+
"generative-agents",
|
|
42
|
+
"npc",
|
|
43
|
+
"threejs",
|
|
44
|
+
"3d",
|
|
45
|
+
"simulation",
|
|
46
|
+
"game",
|
|
47
|
+
"visualization",
|
|
48
|
+
"low-poly",
|
|
49
|
+
"typescript",
|
|
50
|
+
"open-source",
|
|
51
|
+
"level-editor",
|
|
52
|
+
"character-creator"
|
|
53
|
+
],
|
|
54
|
+
"scripts": {
|
|
55
|
+
"build:town": "cd town-frontend && npm install && npm run build",
|
|
56
|
+
"build": "npm run build:town",
|
|
57
|
+
"dev:town": "cd town-frontend && npm run dev",
|
|
58
|
+
"postinstall": "echo '' && echo ' 🏘️ Agentshire installed successfully!' && echo '' && echo ' Next: (re)start the OpenClaw Gateway to activate the plugin.' && echo ' The town will open automatically in your browser.' && echo ''",
|
|
59
|
+
"test": "vitest run"
|
|
60
|
+
},
|
|
61
|
+
"dependencies": {
|
|
62
|
+
"@gltf-transform/core": "^4.3.0",
|
|
63
|
+
"@gltf-transform/extensions": "^4.3.0",
|
|
64
|
+
"@gltf-transform/functions": "^4.3.0",
|
|
65
|
+
"jsonrepair": "^3.13.3",
|
|
66
|
+
"ws": "^8.16.0"
|
|
67
|
+
},
|
|
68
|
+
"peerDependencies": {
|
|
69
|
+
"openclaw": ">= 2026.3.7"
|
|
70
|
+
},
|
|
71
|
+
"peerDependenciesMeta": {
|
|
72
|
+
"openclaw": {
|
|
73
|
+
"optional": true
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
"devDependencies": {
|
|
77
|
+
"@types/ws": "^8.5.10",
|
|
78
|
+
"typescript": "^5.4.0",
|
|
79
|
+
"vitest": "^4.1.0"
|
|
80
|
+
},
|
|
81
|
+
"openclaw": {
|
|
82
|
+
"extensions": [
|
|
83
|
+
"./index.ts"
|
|
84
|
+
],
|
|
85
|
+
"channel": {
|
|
86
|
+
"id": "agentshire",
|
|
87
|
+
"label": "Agentshire",
|
|
88
|
+
"selectionLabel": "Agentshire (3D Visualization)",
|
|
89
|
+
"docsPath": "/channels/agentshire",
|
|
90
|
+
"docsLabel": "agentshire",
|
|
91
|
+
"blurb": "Visualize your AI agents as NPCs in an interactive 3D low-poly town. Watch them work, chat, and collaborate in real-time.",
|
|
92
|
+
"order": 100
|
|
93
|
+
},
|
|
94
|
+
"install": {
|
|
95
|
+
"npmSpec": "agentshire",
|
|
96
|
+
"localPath": "extensions/agentshire",
|
|
97
|
+
"defaultChoice": "npm"
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|