agents-city 0.3.0-beta.21
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/.claude-plugin/marketplace.json +16 -0
- package/LICENSE +202 -0
- package/NOTICE +5 -0
- package/README.es.md +2021 -0
- package/README.md +1999 -0
- package/benchmarks/committee/README.md +39 -0
- package/benchmarks/committee/metrics.py +51 -0
- package/benchmarks/committee/run.py +64 -0
- package/benchmarks/committee/traces/01-single.json +8 -0
- package/benchmarks/committee/traces/02-mesh.json +16 -0
- package/benchmarks/committee/traces/03-chair.json +15 -0
- package/benchmarks/latency/README.md +35 -0
- package/benchmarks/latency/fake-claude-cli.mjs +119 -0
- package/benchmarks/latency/fake-native-server.mjs +340 -0
- package/benchmarks/latency/fake-tui.py +91 -0
- package/benchmarks/latency/live.py +380 -0
- package/benchmarks/stress/README.md +20 -0
- package/benchmarks/stress/run.py +487 -0
- package/bin/agents +4 -0
- package/bin/agents-city.js +116 -0
- package/bin/benchmark +17 -0
- package/bin/bus +6 -0
- package/bin/cities +3 -0
- package/bin/city +86 -0
- package/bin/committee +6 -0
- package/bin/demo +200 -0
- package/bin/exit +5 -0
- package/bin/hall +73 -0
- package/bin/hall.html +426 -0
- package/bin/logs +3 -0
- package/bin/report.py +14 -0
- package/bin/reset +3 -0
- package/bin/road +3 -0
- package/bin/seat +10 -0
- package/bin/serve.py +1428 -0
- package/bin/setup.py +753 -0
- package/bin/skills +3 -0
- package/bin/test +131 -0
- package/bin/test-adapter.py +183 -0
- package/bin/test-admision.py +99 -0
- package/bin/test-avatar.py +58 -0
- package/bin/test-benchmark.py +40 -0
- package/bin/test-broker.py +334 -0
- package/bin/test-cage.py +206 -0
- package/bin/test-card.py +402 -0
- package/bin/test-channel.py +379 -0
- package/bin/test-cities.py +453 -0
- package/bin/test-claude-runtime.py +252 -0
- package/bin/test-committee.py +340 -0
- package/bin/test-contracts.py +544 -0
- package/bin/test-crecimiento.py +164 -0
- package/bin/test-demo.py +308 -0
- package/bin/test-doctor.py +106 -0
- package/bin/test-domains.py +151 -0
- package/bin/test-evidencia.py +50 -0
- package/bin/test-exit.py +128 -0
- package/bin/test-hall-protocol.py +93 -0
- package/bin/test-launch.py +169 -0
- package/bin/test-live-feed.py +508 -0
- package/bin/test-pairing.py +99 -0
- package/bin/test-parcels.py +283 -0
- package/bin/test-runtime-failures.py +252 -0
- package/bin/test-runtime-ui.py +488 -0
- package/bin/test-runtime.py +268 -0
- package/bin/test-rutas.py +80 -0
- package/bin/test-seat.py +1386 -0
- package/bin/test-security.py +150 -0
- package/bin/test-serve.py +1057 -0
- package/bin/test-stress.py +64 -0
- package/bin/test-widgets.py +143 -0
- package/bin/test-workspace.py +188 -0
- package/bin/testlib.py +95 -0
- package/bin/tokens.py +14 -0
- package/bus/scripts/deploy.sh +60 -0
- package/bus/scripts/mint-token.sh +68 -0
- package/bus/scripts/setup-dev.sh +79 -0
- package/bus/scripts/test-channel.ts +8 -0
- package/bus/scripts/test-hub.ts +266 -0
- package/bus/scripts/test-local.sh +40 -0
- package/bus/scripts/test-queue.ts +132 -0
- package/bus/worker/package-lock.json +1971 -0
- package/bus/worker/package.json +17 -0
- package/bus/worker/src/index.ts +485 -0
- package/bus/worker/tsconfig.json +13 -0
- package/bus/worker/wrangler.toml +32 -0
- package/city/oven/README.md +59 -0
- package/city/oven/collect.py +43 -0
- package/city/oven/oven.html +4 -0
- package/city/scripts/history.py +120 -0
- package/city/scripts/seed.py +442 -0
- package/city/web/assets/modelos/License.txt +28 -0
- package/city/web/assets/modelos/PROCEDENCIA.txt +3 -0
- package/city/web/assets/modelos/building-a.glb +0 -0
- package/city/web/assets/modelos/building-b.glb +0 -0
- package/city/web/assets/modelos/building-c.glb +0 -0
- package/city/web/assets/modelos/building-d.glb +0 -0
- package/city/web/assets/modelos/building-e.glb +0 -0
- package/city/web/assets/modelos/building-f.glb +0 -0
- package/city/web/assets/modelos/building-g.glb +0 -0
- package/city/web/assets/modelos/building-h.glb +0 -0
- package/city/web/assets/sprites/building-a.png +0 -0
- package/city/web/assets/sprites/building-b.png +0 -0
- package/city/web/assets/sprites/building-c.png +0 -0
- package/city/web/assets/sprites/building-d.png +0 -0
- package/city/web/assets/sprites/building-e.png +0 -0
- package/city/web/assets/sprites/building-f.png +0 -0
- package/city/web/assets/sprites/building-g.png +0 -0
- package/city/web/assets/sprites/building-h.png +0 -0
- package/city/web/assets/sprites/building-i.png +0 -0
- package/city/web/assets/sprites/building-j.png +0 -0
- package/city/web/assets/sprites/building-k.png +0 -0
- package/city/web/assets/sprites/building-l.png +0 -0
- package/city/web/assets/sprites/building-m.png +0 -0
- package/city/web/assets/sprites/building-n.png +0 -0
- package/city/web/assets/sprites/building-skyscraper-a.png +0 -0
- package/city/web/assets/sprites/building-skyscraper-b.png +0 -0
- package/city/web/assets/sprites/building-skyscraper-c.png +0 -0
- package/city/web/assets/sprites/building-skyscraper-d.png +0 -0
- package/city/web/assets/sprites/building-skyscraper-e.png +0 -0
- package/city/web/assets/sprites/catalogo.json +47 -0
- package/city/web/assets/sprites/detail-awning-wide.png +0 -0
- package/city/web/assets/sprites/detail-awning.png +0 -0
- package/city/web/assets/sprites/detail-overhang-wide.png +0 -0
- package/city/web/assets/sprites/detail-overhang.png +0 -0
- package/city/web/assets/sprites/detail-parasol-a.png +0 -0
- package/city/web/assets/sprites/detail-parasol-b.png +0 -0
- package/city/web/assets/sprites/low-detail-building-a.png +0 -0
- package/city/web/assets/sprites/low-detail-building-b.png +0 -0
- package/city/web/assets/sprites/low-detail-building-c.png +0 -0
- package/city/web/assets/sprites/low-detail-building-d.png +0 -0
- package/city/web/assets/sprites/low-detail-building-e.png +0 -0
- package/city/web/assets/sprites/low-detail-building-f.png +0 -0
- package/city/web/assets/sprites/low-detail-building-g.png +0 -0
- package/city/web/assets/sprites/low-detail-building-h.png +0 -0
- package/city/web/assets/sprites/low-detail-building-i.png +0 -0
- package/city/web/assets/sprites/low-detail-building-j.png +0 -0
- package/city/web/assets/sprites/low-detail-building-k.png +0 -0
- package/city/web/assets/sprites/low-detail-building-l.png +0 -0
- package/city/web/assets/sprites/low-detail-building-m.png +0 -0
- package/city/web/assets/sprites/low-detail-building-n.png +0 -0
- package/city/web/assets/sprites/low-detail-building-wide-a.png +0 -0
- package/city/web/assets/sprites/low-detail-building-wide-b.png +0 -0
- package/city/web/assets/sprites/medidas.json +248 -0
- package/city/web/dist/city.js +939 -0
- package/city/web/dist/index.html +294 -0
- package/city/web/dist/modelos/License.txt +28 -0
- package/city/web/dist/modelos/PROCEDENCIA.txt +3 -0
- package/city/web/dist/modelos/building-a.glb +0 -0
- package/city/web/dist/modelos/building-b.glb +0 -0
- package/city/web/dist/modelos/building-c.glb +0 -0
- package/city/web/dist/modelos/building-d.glb +0 -0
- package/city/web/dist/modelos/building-e.glb +0 -0
- package/city/web/dist/modelos/building-f.glb +0 -0
- package/city/web/dist/modelos/building-g.glb +0 -0
- package/city/web/dist/modelos/building-h.glb +0 -0
- package/city/web/dist/sprites/building-a.png +0 -0
- package/city/web/dist/sprites/building-b.png +0 -0
- package/city/web/dist/sprites/building-c.png +0 -0
- package/city/web/dist/sprites/building-d.png +0 -0
- package/city/web/dist/sprites/building-e.png +0 -0
- package/city/web/dist/sprites/building-f.png +0 -0
- package/city/web/dist/sprites/building-g.png +0 -0
- package/city/web/dist/sprites/building-h.png +0 -0
- package/city/web/dist/sprites/building-i.png +0 -0
- package/city/web/dist/sprites/building-j.png +0 -0
- package/city/web/dist/sprites/building-k.png +0 -0
- package/city/web/dist/sprites/building-l.png +0 -0
- package/city/web/dist/sprites/building-m.png +0 -0
- package/city/web/dist/sprites/building-n.png +0 -0
- package/city/web/dist/sprites/building-skyscraper-a.png +0 -0
- package/city/web/dist/sprites/building-skyscraper-b.png +0 -0
- package/city/web/dist/sprites/building-skyscraper-c.png +0 -0
- package/city/web/dist/sprites/building-skyscraper-d.png +0 -0
- package/city/web/dist/sprites/building-skyscraper-e.png +0 -0
- package/city/web/dist/sprites/catalogo.json +47 -0
- package/city/web/dist/sprites/detail-awning-wide.png +0 -0
- package/city/web/dist/sprites/detail-awning.png +0 -0
- package/city/web/dist/sprites/detail-overhang-wide.png +0 -0
- package/city/web/dist/sprites/detail-overhang.png +0 -0
- package/city/web/dist/sprites/detail-parasol-a.png +0 -0
- package/city/web/dist/sprites/detail-parasol-b.png +0 -0
- package/city/web/dist/sprites/low-detail-building-a.png +0 -0
- package/city/web/dist/sprites/low-detail-building-b.png +0 -0
- package/city/web/dist/sprites/low-detail-building-c.png +0 -0
- package/city/web/dist/sprites/low-detail-building-d.png +0 -0
- package/city/web/dist/sprites/low-detail-building-e.png +0 -0
- package/city/web/dist/sprites/low-detail-building-f.png +0 -0
- package/city/web/dist/sprites/low-detail-building-g.png +0 -0
- package/city/web/dist/sprites/low-detail-building-h.png +0 -0
- package/city/web/dist/sprites/low-detail-building-i.png +0 -0
- package/city/web/dist/sprites/low-detail-building-j.png +0 -0
- package/city/web/dist/sprites/low-detail-building-k.png +0 -0
- package/city/web/dist/sprites/low-detail-building-l.png +0 -0
- package/city/web/dist/sprites/low-detail-building-m.png +0 -0
- package/city/web/dist/sprites/low-detail-building-n.png +0 -0
- package/city/web/dist/sprites/low-detail-building-wide-a.png +0 -0
- package/city/web/dist/sprites/low-detail-building-wide-b.png +0 -0
- package/city/web/dist/sprites/medidas.json +248 -0
- package/city/web/dist-hall/hall.js +264 -0
- package/city/web/index.html +294 -0
- package/city/web/package.json +18 -0
- package/city/web/sella.py +21 -0
- package/city/web/src/activity-actors.ts +47 -0
- package/city/web/src/activity.ts +172 -0
- package/city/web/src/ayuntamiento.ts +580 -0
- package/city/web/src/draw.ts +640 -0
- package/city/web/src/game-speech.ts +79 -0
- package/city/web/src/hall.ts +1867 -0
- package/city/web/src/main.ts +2225 -0
- package/city/web/src/oven.ts +124 -0
- package/city/web/src/people.ts +244 -0
- package/city/web/src/presencia.ts +193 -0
- package/city/web/src/puertas.ts +180 -0
- package/city/web/src/repo-roles.ts +59 -0
- package/city/worker/package.json +16 -0
- package/city/worker/schema.sql +117 -0
- package/city/worker/src/index.ts +702 -0
- package/city/worker/src/square.ts +218 -0
- package/city/worker/wrangler.toml +58 -0
- package/demo/ada.md +50 -0
- package/demo/bruno.md +62 -0
- package/demo/camila.md +56 -0
- package/demo/city/ada.md +40 -0
- package/demo/city/city.yml +8 -0
- package/demo/city/parcels.yml +15 -0
- package/demo/city/roads.json +4 -0
- package/demo/city/units.yml +10 -0
- package/demo/clinica/city.yml +8 -0
- package/demo/clinica/parcels.yml +15 -0
- package/demo/clinica/roads.json +4 -0
- package/demo/clinica/units.yml +9 -0
- package/demo/clinica/vera.md +46 -0
- package/demo/dante.md +54 -0
- package/demo/despacho/city.yml +8 -0
- package/demo/despacho/marta.md +46 -0
- package/demo/despacho/parcels.yml +15 -0
- package/demo/despacho/roads.json +4 -0
- package/demo/despacho/units.yml +9 -0
- package/demo/elsa.md +50 -0
- package/demo/farid.md +52 -0
- package/demo/greta.md +50 -0
- package/demo/hugo.md +49 -0
- package/demo/iris.md +49 -0
- package/demo/jonas.md +51 -0
- package/demo/kira.md +51 -0
- package/demo/luca.md +49 -0
- package/demo/parcels.yml +92 -0
- package/demo/seed.py +20 -0
- package/demo/show.py +161 -0
- package/demo/stories.py +824 -0
- package/demo/units.yml +33 -0
- package/docs/agents-first.md +99 -0
- package/docs/glossary.md +55 -0
- package/docs/map-live-layers.md +73 -0
- package/docs/security.md +231 -0
- package/docs/self-host.md +151 -0
- package/docs/testing.md +205 -0
- package/package.json +73 -0
- package/plugin/.claude-plugin/plugin.json +62 -0
- package/plugin/.mcp.json +15 -0
- package/plugin/channel/activity-cli.ts +16 -0
- package/plugin/channel/adapter-prompts.ts +113 -0
- package/plugin/channel/adapter.js +4292 -0
- package/plugin/channel/adapter.ts +133 -0
- package/plugin/channel/bus.js +20188 -0
- package/plugin/channel/bus.ts +131 -0
- package/plugin/channel/city-config.ts +125 -0
- package/plugin/channel/claude-channel.ts +58 -0
- package/plugin/channel/cli-args.ts +75 -0
- package/plugin/channel/client.js +4200 -0
- package/plugin/channel/client.ts +38 -0
- package/plugin/channel/committee/activity.ts +256 -0
- package/plugin/channel/committee/collection.ts +154 -0
- package/plugin/channel/committee/decision.ts +175 -0
- package/plugin/channel/committee/floor.ts +135 -0
- package/plugin/channel/committee/guards.ts +30 -0
- package/plugin/channel/committee/history.ts +38 -0
- package/plugin/channel/committee/render.ts +102 -0
- package/plugin/channel/committee/service.ts +72 -0
- package/plugin/channel/committee/storage.ts +92 -0
- package/plugin/channel/committee/types.ts +163 -0
- package/plugin/channel/committee/view.ts +63 -0
- package/plugin/channel/committee-cli.ts +109 -0
- package/plugin/channel/delivery-metrics.ts +61 -0
- package/plugin/channel/delivery-queue.ts +118 -0
- package/plugin/channel/hub/activity-controller.ts +72 -0
- package/plugin/channel/hub/activity-feed.ts +169 -0
- package/plugin/channel/hub/committee-controller.ts +60 -0
- package/plugin/channel/hub/connections.ts +48 -0
- package/plugin/channel/hub/diagnostics.ts +67 -0
- package/plugin/channel/hub/envelope-validity.ts +109 -0
- package/plugin/channel/hub/envelopes.ts +66 -0
- package/plugin/channel/hub/lifecycle.ts +91 -0
- package/plugin/channel/hub/local-roads.ts +89 -0
- package/plugin/channel/hub/remote-roads.ts +165 -0
- package/plugin/channel/hub/road-controller.ts +99 -0
- package/plugin/channel/hub-client.ts +149 -0
- package/plugin/channel/local-hub.js +5995 -0
- package/plugin/channel/local-hub.ts +349 -0
- package/plugin/channel/map-reporter.ts +48 -0
- package/plugin/channel/package-lock.json +1731 -0
- package/plugin/channel/package.json +19 -0
- package/plugin/channel/protocol.ts +98 -0
- package/plugin/channel/road-cli.ts +18 -0
- package/plugin/channel/run.sh +15 -0
- package/plugin/channel/runtime/claude.ts +458 -0
- package/plugin/channel/runtime/codex-config.ts +77 -0
- package/plugin/channel/runtime/codex.ts +669 -0
- package/plugin/channel/runtime/command.ts +62 -0
- package/plugin/channel/runtime/factory.ts +15 -0
- package/plugin/channel/runtime/json-rpc.ts +154 -0
- package/plugin/channel/runtime/kimi.ts +277 -0
- package/plugin/channel/runtime/opencode.ts +248 -0
- package/plugin/channel/runtime/process.ts +84 -0
- package/plugin/channel/runtime/types.ts +45 -0
- package/plugin/channel/runtime-files.ts +73 -0
- package/plugin/channel/runtime-gateway.js +6396 -0
- package/plugin/channel/runtime-gateway.ts +358 -0
- package/plugin/channel/runtime-metrics.ts +52 -0
- package/plugin/channel/runtime-subscription.ts +180 -0
- package/plugin/channel/terminal-delivery.ts +131 -0
- package/plugin/channel/untrusted.ts +60 -0
- package/plugin/commands/committee.md +31 -0
- package/plugin/commands/exit.md +32 -0
- package/plugin/commands/goals.md +20 -0
- package/plugin/commands/join.md +18 -0
- package/plugin/commands/notice.md +20 -0
- package/plugin/commands/propose.md +19 -0
- package/plugin/commands/round.md +17 -0
- package/plugin/commands/session.md +22 -0
- package/plugin/commands/settings.md +25 -0
- package/plugin/commands/setup.md +21 -0
- package/plugin/commands/team.md +23 -0
- package/plugin/domains/custom.md +27 -0
- package/plugin/domains/finance.md +31 -0
- package/plugin/domains/healthcare.md +34 -0
- package/plugin/domains/legal.md +31 -0
- package/plugin/domains/marketing.md +33 -0
- package/plugin/domains/operations.md +31 -0
- package/plugin/domains/research.md +32 -0
- package/plugin/domains/sales.md +30 -0
- package/plugin/domains/software.md +37 -0
- package/plugin/hooks/activity.sh +6 -0
- package/plugin/hooks/digging.sh +68 -0
- package/plugin/hooks/growth.sh +42 -0
- package/plugin/hooks/hooks.json +106 -0
- package/plugin/hooks/notice-on-pr.sh +35 -0
- package/plugin/hooks/notice-on-stop.sh +80 -0
- package/plugin/hooks/notice-pending.sh +58 -0
- package/plugin/hooks/solo-en-ciudad.sh +23 -0
- package/plugin/hooks/tokens.sh +47 -0
- package/plugin/roles/examples/account-executive.md +25 -0
- package/plugin/roles/examples/ai-manager.md +34 -0
- package/plugin/roles/examples/associate.md +24 -0
- package/plugin/roles/examples/brand-lead.md +20 -0
- package/plugin/roles/examples/cfo.md +20 -0
- package/plugin/roles/examples/city-lead.md +25 -0
- package/plugin/roles/examples/clinical-director.md +26 -0
- package/plugin/roles/examples/clinical-ops.md +25 -0
- package/plugin/roles/examples/clinician.md +25 -0
- package/plugin/roles/examples/compliance.md +27 -0
- package/plugin/roles/examples/content.md +24 -0
- package/plugin/roles/examples/controller.md +27 -0
- package/plugin/roles/examples/cpto.md +41 -0
- package/plugin/roles/examples/customer-success.md +25 -0
- package/plugin/roles/examples/data-engineer.md +37 -0
- package/plugin/roles/examples/data.md +60 -0
- package/plugin/roles/examples/dev.md +37 -0
- package/plugin/roles/examples/devops.md +39 -0
- package/plugin/roles/examples/enablement.md +24 -0
- package/plugin/roles/examples/ethics.md +24 -0
- package/plugin/roles/examples/fin-analytics.md +27 -0
- package/plugin/roles/examples/health-compliance.md +25 -0
- package/plugin/roles/examples/health-data.md +26 -0
- package/plugin/roles/examples/knowledge.md +25 -0
- package/plugin/roles/examples/lifecycle.md +26 -0
- package/plugin/roles/examples/llm-engineer.md +34 -0
- package/plugin/roles/examples/managing-partner.md +20 -0
- package/plugin/roles/examples/methods.md +23 -0
- package/plugin/roles/examples/operations-lead.md +23 -0
- package/plugin/roles/examples/ops.md +24 -0
- package/plugin/roles/examples/patient-safety.md +26 -0
- package/plugin/roles/examples/performance.md +27 -0
- package/plugin/roles/examples/po.md +36 -0
- package/plugin/roles/examples/process-owner.md +23 -0
- package/plugin/roles/examples/product-design.md +39 -0
- package/plugin/roles/examples/program-manager.md +24 -0
- package/plugin/roles/examples/quality.md +25 -0
- package/plugin/roles/examples/research-director.md +24 -0
- package/plugin/roles/examples/research-ops.md +25 -0
- package/plugin/roles/examples/researcher.md +25 -0
- package/plugin/roles/examples/revenue-lead.md +25 -0
- package/plugin/roles/examples/revops.md +26 -0
- package/plugin/roles/examples/seo.md +27 -0
- package/plugin/roles/examples/specialist.md +24 -0
- package/plugin/scripts/admision.py +165 -0
- package/plugin/scripts/apaga.py +232 -0
- package/plugin/scripts/avatar.py +211 -0
- package/plugin/scripts/broker.py +531 -0
- package/plugin/scripts/cage.py +252 -0
- package/plugin/scripts/capabilities.py +197 -0
- package/plugin/scripts/card.py +312 -0
- package/plugin/scripts/cities.py +520 -0
- package/plugin/scripts/city-env.sh +90 -0
- package/plugin/scripts/city-runtime.sh +87 -0
- package/plugin/scripts/city-session.sh +526 -0
- package/plugin/scripts/city_env.py +67 -0
- package/plugin/scripts/crecimiento.py +140 -0
- package/plugin/scripts/deliberations.py +48 -0
- package/plugin/scripts/doctor.py +172 -0
- package/plugin/scripts/domains.py +201 -0
- package/plugin/scripts/evidencia.py +64 -0
- package/plugin/scripts/find-repos.sh +111 -0
- package/plugin/scripts/gh.py +159 -0
- package/plugin/scripts/hall_protocol.py +147 -0
- package/plugin/scripts/hook_activity.py +139 -0
- package/plugin/scripts/launch.py +94 -0
- package/plugin/scripts/logs.py +98 -0
- package/plugin/scripts/pairing.py +185 -0
- package/plugin/scripts/parcels.py +132 -0
- package/plugin/scripts/read-card.py +51 -0
- package/plugin/scripts/report.py +201 -0
- package/plugin/scripts/reset.py +180 -0
- package/plugin/scripts/roads.py +230 -0
- package/plugin/scripts/roles.py +274 -0
- package/plugin/scripts/runtime_log.py +69 -0
- package/plugin/scripts/runtime_processes.py +132 -0
- package/plugin/scripts/rutas.py +83 -0
- package/plugin/scripts/seat.py +1349 -0
- package/plugin/scripts/tokens.py +194 -0
- package/plugin/scripts/trust-repos.py +59 -0
- package/plugin/scripts/ui.py +280 -0
- package/plugin/scripts/units.py +80 -0
- package/plugin/scripts/workspace.py +364 -0
- package/plugin/skills/city/SKILL.md +191 -0
- package/templates/blank.md +39 -0
- package/templates/finance.md +44 -0
- package/templates/legal.md +45 -0
- package/templates/marketing.md +48 -0
- package/templates/product.md +45 -0
package/bin/city
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Bring YOUR city up, from your data repo. Same idea as bin/demo.
|
|
3
|
+
#
|
|
4
|
+
# ./bin/city uses the selected city
|
|
5
|
+
# ./bin/city ~/.agents-city/me/x uses that one
|
|
6
|
+
set -euo pipefail
|
|
7
|
+
cd "$(dirname "$0")/.."
|
|
8
|
+
RAIZ="$PWD"
|
|
9
|
+
|
|
10
|
+
# A free port, starting at 8787.
|
|
11
|
+
#
|
|
12
|
+
# Not a nicety: the first run of this on somebody else's machine died because
|
|
13
|
+
# something else already held 8787, and the error wrangler prints for that is a
|
|
14
|
+
# wall of C++ stack trace. A demo that refuses to start on its first attempt is a
|
|
15
|
+
# demo nobody runs twice.
|
|
16
|
+
puerto_libre() {
|
|
17
|
+
local p=${1:-8787}
|
|
18
|
+
for _ in 1 2 3 4 5 6 7 8 9 10; do
|
|
19
|
+
if ! lsof -ti:"$p" >/dev/null 2>&1; then echo "$p"; return; fi
|
|
20
|
+
p=$((p + 1))
|
|
21
|
+
done
|
|
22
|
+
echo "$p"
|
|
23
|
+
}
|
|
24
|
+
PUERTO="$(puerto_libre 8787)"
|
|
25
|
+
|
|
26
|
+
if [ $# -gt 0 ]; then
|
|
27
|
+
DATOS="$1"
|
|
28
|
+
elif [ -n "${AGENTS_CITY_DATA:-}" ]; then
|
|
29
|
+
DATOS="$AGENTS_CITY_DATA"
|
|
30
|
+
else
|
|
31
|
+
DATOS="$(python3 "$RAIZ/plugin/scripts/cities.py" current)"
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
if [ ! -d "$DATOS" ]; then
|
|
35
|
+
echo " No data repo at $DATOS"
|
|
36
|
+
echo " Run ./bin/setup.py first — it writes one — or pass the path: ./bin/city ~/my-data"
|
|
37
|
+
exit 1
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
if command -v bunx >/dev/null 2>&1; then CORRE=(bunx)
|
|
41
|
+
elif command -v bun >/dev/null 2>&1; then CORRE=(bun x)
|
|
42
|
+
elif command -v npx >/dev/null 2>&1; then CORRE=(npx --yes)
|
|
43
|
+
else echo " I need npx (comes with Node) or bun."; exit 1; fi
|
|
44
|
+
|
|
45
|
+
printf '\n \033[1mBuilding the map\033[0m\n'
|
|
46
|
+
# Skip the build when a built front end shipped with the package (an npm install
|
|
47
|
+
# has dist/ ready-made) or when the package dir is not ours to write.
|
|
48
|
+
if [ ! -f city/web/dist/index.html ] || { [ -w city/web ] && [ city/web/src/main.ts -nt city/web/dist/city.js ]; }; then
|
|
49
|
+
if [ -w city/web ]; then
|
|
50
|
+
(cd city/web && npm install --silent && npm run build >/dev/null)
|
|
51
|
+
else
|
|
52
|
+
echo " The front end is not built and this install is not writable."
|
|
53
|
+
echo " Reinstall without sudo (nvm makes this the default), or run from a clone."
|
|
54
|
+
exit 1
|
|
55
|
+
fi
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
printf '\n \033[1mLoading %s\033[0m\n' "$DATOS"
|
|
59
|
+
cd "$RAIZ/city/worker"
|
|
60
|
+
# Demo and your city keep their state apart, and that is not tidiness.
|
|
61
|
+
# Sharing one .wrangler/state means the Durable Object holding "who is connected"
|
|
62
|
+
# survives from one to the other: run the demo once, open your own city, and three
|
|
63
|
+
# of Aurora Games' agents are sitting on your bus with timestamps from hours ago.
|
|
64
|
+
# D1 gets reseeded so the houses were right; the live state is what leaked.
|
|
65
|
+
# Local D1/DO state lives in the home directory, never inside the package:
|
|
66
|
+
# an npm -g install is shared and possibly read-only, and state is yours.
|
|
67
|
+
# One local database per city, keyed by cities.py's slug: two cities — even two
|
|
68
|
+
# folders that share a basename — must never overwrite each other's map.
|
|
69
|
+
CIUDAD_ID="$(python3 "$RAIZ/plugin/scripts/cities.py" slug "$DATOS" 2>/dev/null)"
|
|
70
|
+
ESTADO="${AGENTS_CITY_HOME:-$HOME/.agents-city}/state/${CIUDAD_ID:-mine}"
|
|
71
|
+
VARS=(--var "CITY_ID:$(python3 "$RAIZ/plugin/scripts/cities.py" id "$DATOS" 2>/dev/null)")
|
|
72
|
+
# The secret travels as a flag, not as a file written into the package: a global
|
|
73
|
+
# npm install may be read-only, and a local one should not be dirtied either.
|
|
74
|
+
[ -f .dev.vars ] || VARS+=(--var "CITY_SECRET:local-test")
|
|
75
|
+
mkdir -p "$ESTADO"
|
|
76
|
+
"${CORRE[@]}" wrangler@4 d1 execute city --local --persist-to "$ESTADO" --file schema.sql >/dev/null
|
|
77
|
+
cd "$RAIZ"
|
|
78
|
+
CITY_PERSIST="$ESTADO" ./city/scripts/seed.py --data "$DATOS" --local
|
|
79
|
+
|
|
80
|
+
printf '\n \033[1mYour city is at\033[0m http://127.0.0.1:%s\n' "$PUERTO"
|
|
81
|
+
echo " Houses have no floors yet: growth comes from your repos or from ./bin/report.py"
|
|
82
|
+
echo " ctrl-c to stop"
|
|
83
|
+
[ "$PUERTO" = 8787 ] || echo " (8787 was busy, so this one is on $PUERTO)"
|
|
84
|
+
cd "$RAIZ/city/worker"
|
|
85
|
+
exec "${CORRE[@]}" wrangler@4 dev --local --persist-to "$ESTADO" \
|
|
86
|
+
"${VARS[@]}" --port "$PUERTO"
|
package/bin/committee
ADDED
package/bin/demo
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Aurora Games: one disposable personal city, the real Hall, the real local
|
|
3
|
+
# WebSocket bus and a guided chair-mediated committee. No provider account,
|
|
4
|
+
# repository or permanent Agents City data is required.
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
cd "$(dirname "$0")/.."
|
|
7
|
+
RAIZ="$PWD"
|
|
8
|
+
|
|
9
|
+
ABRIR=1
|
|
10
|
+
DOMINIO=software
|
|
11
|
+
while [ $# -gt 0 ]; do
|
|
12
|
+
case "$1" in
|
|
13
|
+
--no-browser) ABRIR=0 ;;
|
|
14
|
+
--domain)
|
|
15
|
+
shift
|
|
16
|
+
DOMINIO="${1:-}"
|
|
17
|
+
;;
|
|
18
|
+
-h|--help)
|
|
19
|
+
cat <<'EOF'
|
|
20
|
+
usage: agents-city demo [--domain software|medicina|legal] [--no-browser]
|
|
21
|
+
|
|
22
|
+
Opens one disposable demo city in the full Town Hall. The centre is the map;
|
|
23
|
+
the right sidebar receives a guided committee over the real local WebSocket
|
|
24
|
+
bus, and the same events become short game-style speech bubbles over each
|
|
25
|
+
agent. The stories are real chaos told in plain words, one per domain:
|
|
26
|
+
|
|
27
|
+
software Aurora Games — la noche en que desaparecieron las partidas
|
|
28
|
+
medicina Clínica Alba — la mañana de las citas duplicadas
|
|
29
|
+
legal Costa & Ley — el plazo de mañana a las nueve
|
|
30
|
+
|
|
31
|
+
No Claude/Codex account is used and your own cities are not selected or changed.
|
|
32
|
+
EOF
|
|
33
|
+
exit 0
|
|
34
|
+
;;
|
|
35
|
+
*) echo " Unknown demo option: $1" >&2; exit 2 ;;
|
|
36
|
+
esac
|
|
37
|
+
shift
|
|
38
|
+
done
|
|
39
|
+
|
|
40
|
+
# One fixture per domain: the story's cast are the city's agents, so a clinic
|
|
41
|
+
# argues about patients and a firm about deadlines — never a repo about either.
|
|
42
|
+
case "$DOMINIO" in
|
|
43
|
+
software) FIXTURE=city ;;
|
|
44
|
+
medicina) FIXTURE=clinica ;;
|
|
45
|
+
legal) FIXTURE=despacho ;;
|
|
46
|
+
*) echo " Unknown demo domain: $DOMINIO (software, medicina or legal)" >&2; exit 2 ;;
|
|
47
|
+
esac
|
|
48
|
+
|
|
49
|
+
[ -f city/worker/schema.sql ] && [ -f "demo/$FIXTURE/city.yml" ] || {
|
|
50
|
+
echo " This install is incomplete: the $DOMINIO demo city or map schema is missing." >&2
|
|
51
|
+
exit 1
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
lee_ciudad() { sed -n "s/^$1:[[:space:]]*//p" "demo/$FIXTURE/city.yml" | head -1; }
|
|
55
|
+
DEMO_OWNER="$(lee_ciudad owner)"
|
|
56
|
+
DEMO_SLUG="$(lee_ciudad slug)"
|
|
57
|
+
|
|
58
|
+
need() {
|
|
59
|
+
command -v "$1" >/dev/null 2>&1 || {
|
|
60
|
+
echo " I need $1. $2" >&2
|
|
61
|
+
exit 1
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
need npm "Install Node from nodejs.org."
|
|
65
|
+
need node "Install Node from nodejs.org."
|
|
66
|
+
need python3 "It ships with macOS; on Linux install python3."
|
|
67
|
+
need curl "Install curl and try again."
|
|
68
|
+
|
|
69
|
+
if command -v bunx >/dev/null 2>&1; then
|
|
70
|
+
RUNNER=(bunx)
|
|
71
|
+
elif command -v bun >/dev/null 2>&1; then
|
|
72
|
+
RUNNER=(bun x)
|
|
73
|
+
elif command -v npx >/dev/null 2>&1; then
|
|
74
|
+
RUNNER=(npx --yes)
|
|
75
|
+
else
|
|
76
|
+
echo " I need npx (comes with Node) or bun." >&2
|
|
77
|
+
exit 1
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
free_port() {
|
|
81
|
+
local port=8787
|
|
82
|
+
for _ in 1 2 3 4 5 6 7 8 9 10; do
|
|
83
|
+
if ! lsof -ti:"$port" >/dev/null 2>&1; then
|
|
84
|
+
echo "$port"
|
|
85
|
+
return
|
|
86
|
+
fi
|
|
87
|
+
port=$((port + 1))
|
|
88
|
+
done
|
|
89
|
+
echo " No free map port from 8787 to 8796." >&2
|
|
90
|
+
return 1
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
step() { printf '\n \033[1m%s\033[0m\n' "$1"; }
|
|
94
|
+
|
|
95
|
+
DEMO_PREFIX="${TMPDIR:-/tmp}/agents-city-demo."
|
|
96
|
+
DEMO_RUNTIME="$(mktemp -d "${DEMO_PREFIX}XXXXXX")"
|
|
97
|
+
DEMO_DATA="$DEMO_RUNTIME/city"
|
|
98
|
+
DEMO_APP="$DEMO_RUNTIME/app"
|
|
99
|
+
DEMO_STATE="$DEMO_RUNTIME/state"
|
|
100
|
+
DEMO_CITY_ID="$(lee_ciudad id)"
|
|
101
|
+
MAP_PORT="$(free_port)"
|
|
102
|
+
MAP_PID=""
|
|
103
|
+
STORY_PID=""
|
|
104
|
+
|
|
105
|
+
cleanup() {
|
|
106
|
+
set +e
|
|
107
|
+
[ -n "$STORY_PID" ] && kill -TERM "$STORY_PID" 2>/dev/null
|
|
108
|
+
[ -n "$MAP_PID" ] && kill -TERM "$MAP_PID" 2>/dev/null
|
|
109
|
+
# The hub deliberately detaches in normal cities. This demo owns a temporary
|
|
110
|
+
# app home, so close only the PID recorded below that exact directory.
|
|
111
|
+
python3 - "$DEMO_APP" <<'PY'
|
|
112
|
+
import glob, json, os, signal, sys
|
|
113
|
+
for path in glob.glob(os.path.join(sys.argv[1], '.runtime', 'bus', '*', 'endpoint.json')):
|
|
114
|
+
try:
|
|
115
|
+
pid = int(json.load(open(path, encoding='utf-8')).get('pid', 0))
|
|
116
|
+
if pid > 1:
|
|
117
|
+
os.kill(pid, signal.SIGTERM)
|
|
118
|
+
except (OSError, ValueError, TypeError, json.JSONDecodeError):
|
|
119
|
+
pass
|
|
120
|
+
PY
|
|
121
|
+
sleep 0.35
|
|
122
|
+
if command -v lsof >/dev/null 2>&1 && [ -d "$DEMO_RUNTIME" ]; then
|
|
123
|
+
while IFS= read -r pid; do
|
|
124
|
+
case "$pid" in ''|*[!0-9]*) ;; *) kill -TERM "$pid" 2>/dev/null ;; esac
|
|
125
|
+
done < <(lsof -t +D "$DEMO_RUNTIME" 2>/dev/null | sort -u)
|
|
126
|
+
fi
|
|
127
|
+
case "$DEMO_RUNTIME" in
|
|
128
|
+
"$DEMO_PREFIX"*) rm -rf -- "$DEMO_RUNTIME" ;;
|
|
129
|
+
esac
|
|
130
|
+
}
|
|
131
|
+
trap cleanup EXIT
|
|
132
|
+
trap 'exit 130' INT TERM
|
|
133
|
+
|
|
134
|
+
mkdir -p "$DEMO_DATA" "$DEMO_APP" "$DEMO_STATE"
|
|
135
|
+
cp -R "$RAIZ/demo/$FIXTURE/." "$DEMO_DATA/"
|
|
136
|
+
|
|
137
|
+
step "1/5 Building the full Hall and city map"
|
|
138
|
+
if [ ! -f city/web/dist/index.html ] || [ ! -f city/web/dist-hall/hall.js ] \
|
|
139
|
+
|| { [ -w city/web ] && [ city/web/src/main.ts -nt city/web/dist/city.js ]; } \
|
|
140
|
+
|| { [ -w city/web ] && [ city/web/src/hall.ts -nt city/web/dist-hall/hall.js ]; }; then
|
|
141
|
+
if [ -w city/web ]; then
|
|
142
|
+
(cd city/web && npm install --silent && npm run build >/dev/null)
|
|
143
|
+
else
|
|
144
|
+
echo " The installed front end is missing. Reinstall agents-city without sudo." >&2
|
|
145
|
+
exit 1
|
|
146
|
+
fi
|
|
147
|
+
fi
|
|
148
|
+
|
|
149
|
+
step "2/5 Creating a disposable demo city ($DOMINIO)"
|
|
150
|
+
cd "$RAIZ/city/worker"
|
|
151
|
+
"${RUNNER[@]}" wrangler@4 d1 execute city --local --persist-to "$DEMO_STATE" \
|
|
152
|
+
--file schema.sql >/dev/null
|
|
153
|
+
cd "$RAIZ"
|
|
154
|
+
CITY_PERSIST="$DEMO_STATE" ./city/scripts/seed.py \
|
|
155
|
+
--data "$DEMO_DATA" --fake-history --local
|
|
156
|
+
|
|
157
|
+
step "3/5 Starting the city map"
|
|
158
|
+
MAP_LOG="$DEMO_RUNTIME/map.log"
|
|
159
|
+
cd "$RAIZ/city/worker"
|
|
160
|
+
"${RUNNER[@]}" wrangler@4 dev --local --persist-to "$DEMO_STATE" \
|
|
161
|
+
--var "CITY_SECRET:local-test" --var "CITY_ID:$DEMO_CITY_ID" \
|
|
162
|
+
--port "$MAP_PORT" >"$MAP_LOG" 2>&1 &
|
|
163
|
+
MAP_PID=$!
|
|
164
|
+
cd "$RAIZ"
|
|
165
|
+
|
|
166
|
+
MAP_READY=0
|
|
167
|
+
for _ in $(seq 1 120); do
|
|
168
|
+
if curl -fsS "http://127.0.0.1:$MAP_PORT/api/identity" 2>/dev/null \
|
|
169
|
+
| python3 -c 'import json,sys; raise SystemExit(json.load(sys.stdin).get("cityId") != sys.argv[1])' \
|
|
170
|
+
"$DEMO_CITY_ID" 2>/dev/null; then
|
|
171
|
+
MAP_READY=1
|
|
172
|
+
break
|
|
173
|
+
fi
|
|
174
|
+
sleep 0.25
|
|
175
|
+
done
|
|
176
|
+
if [ "$MAP_READY" -ne 1 ]; then
|
|
177
|
+
echo " The map did not become ready. Last output:" >&2
|
|
178
|
+
tail -20 "$MAP_LOG" >&2 || true
|
|
179
|
+
exit 1
|
|
180
|
+
fi
|
|
181
|
+
|
|
182
|
+
step "4/5 Connecting the authenticated WebSocket bus"
|
|
183
|
+
DEMO_ENV=(
|
|
184
|
+
"AGENTS_CITY_HOME=$DEMO_APP"
|
|
185
|
+
"AGENTS_CITY_DATA=$DEMO_DATA"
|
|
186
|
+
"AGENTS_CITY_USER=$DEMO_OWNER"
|
|
187
|
+
"CITY_ADDRESS=$DEMO_OWNER/$DEMO_SLUG"
|
|
188
|
+
)
|
|
189
|
+
env "${DEMO_ENV[@]}" python3 "$RAIZ/demo/show.py" --story "$DOMINIO" &
|
|
190
|
+
STORY_PID=$!
|
|
191
|
+
|
|
192
|
+
step "5/5 Opening the playable Town Hall"
|
|
193
|
+
echo " The map owns the centre. Follow the complete committee on the right."
|
|
194
|
+
echo " Each live turn also appears over its speaker as Para <recipient>: …"
|
|
195
|
+
echo " Everything disappears when you press ctrl-c; your cities stay untouched."
|
|
196
|
+
if [ "$ABRIR" -eq 1 ]; then
|
|
197
|
+
env "${DEMO_ENV[@]}" "$RAIZ/bin/hall"
|
|
198
|
+
else
|
|
199
|
+
env "${DEMO_ENV[@]}" "$RAIZ/bin/hall" --no-browser
|
|
200
|
+
fi
|
package/bin/exit
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Close the day — everything, or one city: `./bin/exit [city] [--dry-run]`.
|
|
3
|
+
# The logic lives in plugin/scripts/apaga.py so /city:exit inside Claude and this
|
|
4
|
+
# launcher are the same code through two doors.
|
|
5
|
+
exec python3 "$(cd "$(dirname "$0")/../plugin/scripts" && pwd)/apaga.py" "$@"
|
package/bin/hall
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""The town hall: manage your city from the browser.
|
|
3
|
+
|
|
4
|
+
./bin/hall open it
|
|
5
|
+
./bin/hall --city lab open one known city
|
|
6
|
+
./bin/hall --no-browser print the address instead
|
|
7
|
+
|
|
8
|
+
One page on localhost: the selected city's identity, owner seat (role, folders,
|
|
9
|
+
goal), repo support agents, recognised skills, roads, districts and houses. It
|
|
10
|
+
writes the same plain files every other door writes, through the same modules.
|
|
11
|
+
|
|
12
|
+
The server is bin/serve.py. It binds to 127.0.0.1 on a port the OS picks, and
|
|
13
|
+
every request carries a token minted for this run, because this process writes to
|
|
14
|
+
your disk.
|
|
15
|
+
"""
|
|
16
|
+
import argparse
|
|
17
|
+
import os
|
|
18
|
+
import sys
|
|
19
|
+
|
|
20
|
+
AQUI = os.path.dirname(os.path.abspath(__file__))
|
|
21
|
+
sys.path.insert(0, AQUI)
|
|
22
|
+
sys.path.insert(0, os.path.join(os.path.dirname(AQUI), 'plugin', 'scripts'))
|
|
23
|
+
import serve # noqa: E402
|
|
24
|
+
import cities # noqa: E402
|
|
25
|
+
|
|
26
|
+
def asegura_build():
|
|
27
|
+
"""hall.js, built if missing or older than its source. Same npm the map already
|
|
28
|
+
requires — the hall's headline feature is framing the map, so this is not a new
|
|
29
|
+
dependency, just the same one earlier."""
|
|
30
|
+
import subprocess
|
|
31
|
+
web = os.path.join(os.path.dirname(AQUI), 'city', 'web')
|
|
32
|
+
js = os.path.join(web, 'dist-hall', 'hall.js')
|
|
33
|
+
ts = os.path.join(web, 'src', 'hall.ts')
|
|
34
|
+
if os.path.isfile(js):
|
|
35
|
+
# Freshness only matters in a clone, where hall.ts gets edited. An npm
|
|
36
|
+
# install ships hall.js prebuilt — and npm normalises file times, so an
|
|
37
|
+
# mtime comparison there rebuilds for no reason, or fails where the
|
|
38
|
+
# install is not writable.
|
|
39
|
+
es_clon = os.path.isdir(os.path.join(os.path.dirname(AQUI), '.git'))
|
|
40
|
+
if not es_clon or os.path.getmtime(js) >= os.path.getmtime(ts):
|
|
41
|
+
return True
|
|
42
|
+
print(' Building the hall (first time needs npm install)…')
|
|
43
|
+
r = subprocess.run('npm install --silent && npm run build',
|
|
44
|
+
shell=True, cwd=web, capture_output=True, text=True)
|
|
45
|
+
if not os.path.isfile(js):
|
|
46
|
+
print(' The build failed. Run by hand and read its output:\n'
|
|
47
|
+
' cd city/web && npm install && npm run build\n'
|
|
48
|
+
f' {(r.stderr or r.stdout).strip().splitlines()[-1:] or [""] }'[0:400],
|
|
49
|
+
file=sys.stderr)
|
|
50
|
+
return False
|
|
51
|
+
return True
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
if __name__ == '__main__':
|
|
55
|
+
ap = argparse.ArgumentParser(description='Open one personal city in the local Hall')
|
|
56
|
+
ap.add_argument('--city', default='', help='known city name, id or path')
|
|
57
|
+
ap.add_argument('--no-browser', action='store_true', help='print the URL only')
|
|
58
|
+
a = ap.parse_args()
|
|
59
|
+
if not asegura_build():
|
|
60
|
+
sys.exit(1)
|
|
61
|
+
usuario = cities.usuario_actual()
|
|
62
|
+
datos = cities.resuelve(a.city, usuario) if a.city else cities.actual(usuario)
|
|
63
|
+
if not datos:
|
|
64
|
+
print(f' No city called {a.city!r}.', file=sys.stderr)
|
|
65
|
+
sys.exit(1)
|
|
66
|
+
owner = cities.lee_clave(datos, 'owner')
|
|
67
|
+
if owner and owner != usuario:
|
|
68
|
+
print(f" This city belongs to {owner!r}, not {usuario!r}.", file=sys.stderr)
|
|
69
|
+
sys.exit(1)
|
|
70
|
+
cities.selecciona(usuario, datos)
|
|
71
|
+
sys.exit(0 if serve.sirve(datos,
|
|
72
|
+
abrir=not a.no_browser,
|
|
73
|
+
pagina='hall') else 0)
|