agent-switchboard 2.3.0__tar.gz → 2.4.0__tar.gz
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.
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/.github/workflows/ci.yml +100 -35
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/.gitignore +6 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/ARCS.md +6 -5
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/PKG-INFO +29 -11
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/README.md +28 -10
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/demo/chess.sh +4 -4
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/demo/run.sh +4 -4
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/docs/claude-code.md +65 -1
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/docs/quickstart.md +2 -2
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/pyproject.toml +1 -1
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/ROADMAP.md +68 -13
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/items/ci-workspace-is-public.yaml +2 -1
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/items/first-contact-needs-a-key-it-cannot-have.yaml +2 -1
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/items/inbox-consumes-what-it-cannot-open.yaml +2 -1
- agent_switchboard-2.4.0/roadmap/items/rootless-warning-false-positive.yaml +81 -0
- agent_switchboard-2.4.0/site/PRINCIPLES.md +536 -0
- agent_switchboard-2.4.0/site/check-quotes.py +223 -0
- agent_switchboard-2.4.0/site/clips/collision.txt +43 -0
- agent_switchboard-2.4.0/site/clips/crash.txt +31 -0
- agent_switchboard-2.4.0/site/demo.cast +41 -0
- agent_switchboard-2.4.0/site/design/BRIEF.md +332 -0
- agent_switchboard-2.4.0/site/design/Main.dc.html +449 -0
- agent_switchboard-2.4.0/site/design/Mobile.dc.html +24 -0
- agent_switchboard-2.4.0/site/design/canvas.json +12 -0
- agent_switchboard-2.4.0/site/design/capture-viewer.sh +73 -0
- agent_switchboard-2.4.0/site/design/img/README.md +62 -0
- agent_switchboard-2.4.0/site/design/img/island-play.jpg +0 -0
- agent_switchboard-2.4.0/site/design/img/viewer-phone.jpg +0 -0
- agent_switchboard-2.4.0/site/design/og-card.html +83 -0
- agent_switchboard-2.4.0/site/design/render-og.py +77 -0
- agent_switchboard-2.4.0/site/img/README.md +36 -0
- agent_switchboard-2.4.0/site/img/apple-touch-icon.png +0 -0
- agent_switchboard-2.4.0/site/img/favicon-16.png +0 -0
- agent_switchboard-2.4.0/site/img/favicon-32.png +0 -0
- agent_switchboard-2.4.0/site/img/favicon.svg +11 -0
- agent_switchboard-2.4.0/site/img/og.jpg +0 -0
- agent_switchboard-2.4.0/site/index.html +1090 -0
- agent_switchboard-2.4.0/site/privacy.html +134 -0
- agent_switchboard-2.4.0/site/record-collision.sh +48 -0
- agent_switchboard-2.4.0/site/record-crash.sh +61 -0
- agent_switchboard-2.4.0/site/record-demo.py +78 -0
- agent_switchboard-2.4.0/site/stamp-version.py +92 -0
- agent_switchboard-2.4.0/site/terms.html +127 -0
- agent_switchboard-2.4.0/site/vercel.json +40 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/__init__.py +1 -1
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/cli.py +169 -39
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/client.py +134 -14
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/config.py +91 -7
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/invite.py +85 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/knownrooms.py +1 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/mcp_server.py +81 -19
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/rendezvous.py +44 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/rooms.py +54 -4
- agent_switchboard-2.4.0/src/switchboard/skill/switchboard-coordinate/SKILL.md +403 -0
- agent_switchboard-2.4.0/src/switchboard/stash.py +169 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/testing.py +10 -2
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/conftest.py +38 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_cli_config.py +64 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_config.py +93 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_crypto.py +11 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_drill.py +10 -2
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_invite.py +130 -1
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_mcp.py +55 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_rendezvous.py +244 -0
- agent_switchboard-2.4.0/tests/test_stash.py +124 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_whisper.py +107 -8
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_workflow_token.py +28 -4
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/.dockerignore +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/.github/workflows/deploy.yml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/.github/workflows/pages.yml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/.github/workflows/publish-viewer.yml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/.github/workflows/publish.yml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/.github/workflows/roadmap.yml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/AGENTS.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/CONTRIBUTING.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/Dockerfile +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/LICENSE +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/demo/README.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/docker-compose.yml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/docs/adaptive-timing.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/docs/api.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/docs/codex-cli.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/docs/concepts.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/docs/deployment.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/docs/drills.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/docs/encryption.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/docs/environments.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/docs/images/viewer.png +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/docs/layers.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/docs/managed-hub.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/docs/model.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/docs/seam.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/docs/testing.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/docs/upgrading.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/docs/viewer.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/docs/why-this-exists.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/examples/coordinated_worker.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/extras/session-capsule/README.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/extras/session-capsule/cc.sh +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/extras/session-capsule/claude_session_capsule.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/extras/viewer/README.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/extras/viewer/pyproject.toml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/extras/viewer/switchboard_viewer/__init__.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/extras/viewer/switchboard_viewer/__main__.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/extras/viewer/switchboard_viewer/viewer.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/extras/viewer/switchboard_viewer/web/index.html +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/extras/viewer/switchboard_viewer/web/render.js +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/extras/viewer/switchboard_viewer/web/switchboard-open.js +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/extras/viewer/switchboard_viewer/web/switchboard-room.js +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/README.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/arcs/distribution.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/arcs/hub-boundary.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/arcs/setup-and-first-run.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/arcs/ttl-ceilings.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/items/a-drain-that-retries-forever-never-escalates.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/items/a-lobby-derived-from-the-key.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/items/abuse-control-after-authorization.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/items/automatic-session-checkpoints.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/items/board-ttl-ceiling.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/items/clients-that-cannot-post.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/items/connect-failure-message.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/items/cross-key-rendezvous.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/items/discovery-is-uneven-and-delivery-is-unknowable.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/items/every-silent-failure-looks-like-a-quiet-room.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/items/hooks-warning-false-positive.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/items/hub-origin-reachable-bypassing-the-edge.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/items/identity-rebinds-on-branch-change.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/items/init-writes-rooms-file.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/items/intermittent-suite-failure.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/items/joining-agent-sees-empty-inbox.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/items/known-rooms-address-book.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/items/one-resolved-context-across-surfaces.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/items/presence-ttl-is-not-one-size.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/items/provisioned-token-is-stale-and-nothing-says-so.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/items/publish-hub-container-image.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/items/read-only-rooms.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/items/robots-policy-for-public-hosts.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/items/roles-and-authority-between-agents.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/items/seal-agent-meta.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/items/selective-wake-for-the-listener.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/items/stale-resolver-references.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/items/stale-token-in-session-env.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/items/standing-checks-that-nothing-runs.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/items/timing-cold-start-in-ephemeral-environments.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/items/ttl-clamped-silently.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/items/unread-dms-not-shown-outside-mcp.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/roadmap/items/write-parity-across-surfaces.yaml +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/scripts/deploy.sh +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/auth.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/claude_session.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/crypto.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/desktop.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/drill.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/guidance.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/handoff.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/holds.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/load.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/notify.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/peers.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/scripts/wake-on-message.sh +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/server.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/signing.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/skill/history/001-SKILL.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/skill/history/002-SKILL.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/skill/history/003-SKILL.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/skill/history/004-SKILL.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/skill/history/005-SKILL.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/skill/history/006-SKILL.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/skill/history/007-SKILL.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/skill/history/008-SKILL.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/skill/history/009-SKILL.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/skill/history/010-SKILL.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/skill/history/011-SKILL.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/skill/history/012-SKILL.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/skill/history/013-SKILL.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/skill/history/014-SKILL.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/skill/history/015-SKILL.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/skill/history/016-SKILL.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/skill/history/017-SKILL.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/skill/history/018-SKILL.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/skill/history/019-SKILL.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/skill/history/020-SKILL.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/skill/history/021-SKILL.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/skill/history/022-SKILL.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/skill/history/023-SKILL.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/skill/history/024-SKILL.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/skill/history/025-SKILL.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/skill/history/026-SKILL.md +0 -0
- /agent_switchboard-2.3.0/src/switchboard/skill/switchboard-coordinate/SKILL.md → /agent_switchboard-2.4.0/src/switchboard/skill/history/027-SKILL.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/spec.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/store.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/timing.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/src/switchboard/writekey.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/barter/README.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/barter/__init__.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/barter/analysis.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/barter/economy.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/barter/flow.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/barter/llm.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/barter/manager.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/barter/report.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/barter/run.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/barter/tier1.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/barter/tier1_labour.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/barter/tier1_rounds.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/barter/tier2_seed1_bound.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/barter/tier2_seed1_built.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/barter/tier2_seed1_free.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/barter/tier2_seed1_paid.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/barter/tier2_seed1_spend.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/barter/tier2_seed1_told.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/barter/tier2_seed41_bound.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/barter/traders.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/barter_experiment.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/barter_llm_experiment.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_harness.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/RESULTS.md +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/prompt_A_s31337.txt +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/prompt_A_s4242.txt +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/prompt_A_s7777.txt +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/prompt_B_s31337.txt +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/prompt_B_s4242.txt +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/prompt_B_s7777.txt +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/prompt_C_s31337.txt +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/prompt_C_s4242.txt +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/prompt_C_s7777.txt +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_haiku_A_s31337.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_haiku_A_s4242.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_haiku_A_s7777.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_haiku_B_s31337.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_haiku_B_s4242.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_haiku_B_s7777.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_haiku_C_s31337.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_haiku_C_s4242.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_haiku_C_s7777.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_opus_A_s31337.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_opus_A_s4242.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_opus_A_s7777.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_opus_B_s31337.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_opus_B_s4242.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_opus_B_s7777.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_opus_C_s31337.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_opus_C_s4242.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_opus_C_s7777.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_sonnet_A_s31337.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_sonnet_A_s4242.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_sonnet_A_s7777.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_sonnet_B_s31337.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_sonnet_B_s4242.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_sonnet_B_s7777.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_sonnet_C_s31337.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_sonnet_C_s4242.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_sonnet_C_s7777.json +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/tier2_run.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/experiments/timing_experiment.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_api.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_arrive.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_auth.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_barter.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_barter_llm.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_claude_session.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_cli_board.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_cli_checkin.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_cli_global_flags.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_cli_init.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_cli_serve.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_cli_session.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_cli_timing.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_client_invite.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_cors_write_headers.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_dash_ids.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_declare.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_deployment.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_desktop.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_evening_replayed.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_example_viewer.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_failure_messages.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_handoff.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_help.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_isolated_hub.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_known_rooms.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_leave_a_ghost.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_load.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_lobby.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_mcp_session.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_notify.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_rooms.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_sending_opens_a_conversation.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_spec.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_store.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_surface_parity.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_testing.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_tier2_harness.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_timing.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_timing_experiment.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_transient_failures.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_version.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_wake_listener.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_web_invite.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_web_page.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_web_reader.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_web_snapshot.py +0 -0
- {agent_switchboard-2.3.0 → agent_switchboard-2.4.0}/tests/test_write_keys.py +0 -0
|
@@ -143,13 +143,19 @@ jobs:
|
|
|
143
143
|
# success is the failure being fixed.
|
|
144
144
|
browser:
|
|
145
145
|
runs-on: ubuntu-latest
|
|
146
|
-
#
|
|
147
|
-
#
|
|
148
|
-
#
|
|
149
|
-
#
|
|
150
|
-
#
|
|
151
|
-
# the
|
|
152
|
-
#
|
|
146
|
+
# This job used to install system packages, and it was the only one that
|
|
147
|
+
# ever hung or failed on something outside the repo. On #138
|
|
148
|
+
# `playwright install --with-deps` sat in apt for 71 minutes; on #251 the
|
|
149
|
+
# same step failed twice with a Hash Sum mismatch fetching Google's Chrome
|
|
150
|
+
# index, because `--with-deps` adds apt — and therefore dl.google.com — to
|
|
151
|
+
# the critical path of a job that only needs a browser binary.
|
|
152
|
+
#
|
|
153
|
+
# ubuntu-latest already ships the shared libraries Chromium links against,
|
|
154
|
+
# so the deps step is gone. If that ever stops being true, Chromium fails
|
|
155
|
+
# to launch and the tests below go red — loudly, and without a skip, which
|
|
156
|
+
# the last step enforces.
|
|
157
|
+
#
|
|
158
|
+
# The timeout stays: it bounded the hang before and costs nothing.
|
|
153
159
|
timeout-minutes: 10
|
|
154
160
|
steps:
|
|
155
161
|
- uses: actions/checkout@v4
|
|
@@ -157,7 +163,7 @@ jobs:
|
|
|
157
163
|
with:
|
|
158
164
|
python-version: "3.12"
|
|
159
165
|
- run: pip install -e '.[dev]' playwright
|
|
160
|
-
- run: playwright install
|
|
166
|
+
- run: playwright install chromium
|
|
161
167
|
- name: the page, in a browser — and nothing may skip
|
|
162
168
|
# `-p no:randomly` keeps the summary line stable to grep. The skip
|
|
163
169
|
# check is the whole point of the job: if the browser fixture ever
|
|
@@ -170,6 +176,27 @@ jobs:
|
|
|
170
176
|
exit 1
|
|
171
177
|
fi
|
|
172
178
|
|
|
179
|
+
# The landing page quotes real terminal output. Until #277 the largest of
|
|
180
|
+
# those blocks was generated from site/demo.cast, so it could not drift;
|
|
181
|
+
# that generator is gone and the quotes are now placed by hand, which means
|
|
182
|
+
# a change to the CLI's output can leave the page showing a line no run
|
|
183
|
+
# prints any more. site/PRINCIPLES.md principle 4 is the whole reason this
|
|
184
|
+
# page is worth anything, so it is checked rather than trusted.
|
|
185
|
+
#
|
|
186
|
+
# Offline on purpose: it reads only files in this repository. The island
|
|
187
|
+
# boards are quoted from another host and are checked by hand with
|
|
188
|
+
# `python3 site/check-quotes.py --online`, because a CI run should not go
|
|
189
|
+
# red over somebody else's uptime. Stdlib only, so there is nothing to
|
|
190
|
+
# install.
|
|
191
|
+
site-quotes:
|
|
192
|
+
runs-on: ubuntu-latest
|
|
193
|
+
steps:
|
|
194
|
+
- uses: actions/checkout@v4
|
|
195
|
+
- uses: actions/setup-python@v5
|
|
196
|
+
with:
|
|
197
|
+
python-version: "3.12"
|
|
198
|
+
- run: python3 site/check-quotes.py
|
|
199
|
+
|
|
173
200
|
docker:
|
|
174
201
|
runs-on: ubuntu-latest
|
|
175
202
|
steps:
|
|
@@ -184,48 +211,86 @@ jobs:
|
|
|
184
211
|
curl -sf http://127.0.0.1:8787/health | grep -q '"ok":true'
|
|
185
212
|
docker rm -f swb
|
|
186
213
|
|
|
187
|
-
#
|
|
188
|
-
#
|
|
189
|
-
#
|
|
190
|
-
#
|
|
191
|
-
#
|
|
214
|
+
# A smoke test against the real hub, not a notice board.
|
|
215
|
+
#
|
|
216
|
+
# This used to announce into a fixed room so a CI run appeared beside the
|
|
217
|
+
# human sessions. That room's identifier sat in this file in plain text, and
|
|
218
|
+
# since #73 the hub does no authorization — reaching a room IS knowing its
|
|
219
|
+
# identifier — so it was the one published room in a repository whose own
|
|
220
|
+
# .gitignore refuses to commit .mcp.json for the same reason.
|
|
192
221
|
#
|
|
193
|
-
# The
|
|
194
|
-
#
|
|
195
|
-
#
|
|
196
|
-
#
|
|
197
|
-
#
|
|
198
|
-
# is nothing for a secret copy to protect that the published one does not.
|
|
222
|
+
# The fix is not a secret. Nobody was reading what CI announced, so the room
|
|
223
|
+
# does not need to persist: the job mints its own, uses it, and drops it. No
|
|
224
|
+
# identifier to leak, no key to rotate, no secret withheld from a fork's pull
|
|
225
|
+
# request — and the job now behaves identically for a contributor as it does
|
|
226
|
+
# on main.
|
|
199
227
|
#
|
|
200
|
-
#
|
|
201
|
-
#
|
|
202
|
-
#
|
|
228
|
+
# What it buys beyond safety: the old job could not fail. It warned and
|
|
229
|
+
# exited green, so a client that could not reach the hub at all still showed
|
|
230
|
+
# a passing check. This one mints, announces, and reads the roster back,
|
|
231
|
+
# asserting the agent it just created is there. That is the whole client
|
|
232
|
+
# path — keygen, seal, POST, GET, decrypt — against the live hub on every
|
|
233
|
+
# run, and it goes red when any of it breaks.
|
|
234
|
+
#
|
|
235
|
+
# The token still comes from MANAGED_HUB_TOKEN in the checkout rather than a
|
|
236
|
+
# secret: a private copy drifted from the hub's own token and locked this job
|
|
237
|
+
# out for a day without failing a build (#96). Since #76 a token admits a
|
|
238
|
+
# caller and scopes nothing, so a secret copy protects nothing the published
|
|
239
|
+
# one does not.
|
|
203
240
|
register-switchboard:
|
|
241
|
+
# Never on a pull request. This is the one job that talks to a server
|
|
242
|
+
# somebody has to keep up, and a hub reboot must not turn a contributor's
|
|
243
|
+
# PR red for a reason that has nothing to do with their change — red for
|
|
244
|
+
# no reason is how people learn to ignore red.
|
|
245
|
+
#
|
|
246
|
+
# On main it gates, which is the point: a check that cannot fail is not a
|
|
247
|
+
# check, and the old one warned and exited green even when the client
|
|
248
|
+
# could not reach the hub at all.
|
|
249
|
+
if: github.event_name != 'pull_request'
|
|
204
250
|
runs-on: ubuntu-latest
|
|
251
|
+
timeout-minutes: 5
|
|
205
252
|
steps:
|
|
206
253
|
- uses: actions/checkout@v4
|
|
207
254
|
- uses: actions/setup-python@v5
|
|
208
255
|
with:
|
|
209
256
|
python-version: "3.12"
|
|
210
257
|
- run: pip install -e .
|
|
211
|
-
- name:
|
|
258
|
+
- name: Mint a room, announce into it, and read it back
|
|
212
259
|
env:
|
|
213
260
|
SWITCHBOARD_URL: https://switchboard.lucille-ai.com
|
|
214
|
-
|
|
261
|
+
SWITCHBOARD_AGENT_ID: ci-${{ github.run_id }}-${{ github.run_attempt }}
|
|
215
262
|
run: |
|
|
263
|
+
set -euo pipefail
|
|
264
|
+
|
|
216
265
|
SWITCHBOARD_TOKEN="$(sed -n 's/^MANAGED_HUB_TOKEN = "\([^"]*\)".*/\1/p' \
|
|
217
266
|
src/switchboard/config.py | head -1)"
|
|
218
|
-
export SWITCHBOARD_TOKEN
|
|
219
267
|
if [ -z "$SWITCHBOARD_TOKEN" ]; then
|
|
220
|
-
echo "::
|
|
221
|
-
"src/switchboard/config.py
|
|
222
|
-
exit
|
|
268
|
+
echo "::error title=switchboard::MANAGED_HUB_TOKEN not found in" \
|
|
269
|
+
"src/switchboard/config.py"
|
|
270
|
+
exit 1
|
|
223
271
|
fi
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
272
|
+
export SWITCHBOARD_TOKEN
|
|
273
|
+
|
|
274
|
+
# A room of its own, thrown away when the job ends. Everything in it
|
|
275
|
+
# expires on its own anyway — presence in two minutes.
|
|
276
|
+
eval "$(switchboard keygen --no-input | sed 's/^/export /')"
|
|
277
|
+
|
|
278
|
+
MARK="${{ github.event_name }} ${{ github.ref_name }}@${{ github.sha }}"
|
|
279
|
+
switchboard -q announce --kind ci -c build --task "$MARK"
|
|
280
|
+
|
|
281
|
+
# The assertion, and it is deliberately on the task rather than on
|
|
282
|
+
# the agent id. Ids are scrambled before they reach the hub, so the
|
|
283
|
+
# one in SWITCHBOARD_AGENT_ID never appears in a roster — an
|
|
284
|
+
# assertion against it fails every time, which is how this was
|
|
285
|
+
# written the first time and caught by rehearsing it.
|
|
286
|
+
#
|
|
287
|
+
# The task is sealed on the way out and opened on the way back, so
|
|
288
|
+
# finding it here proves the whole path: mint, seal, POST, GET,
|
|
289
|
+
# decrypt. Announcing alone would only prove a write was accepted.
|
|
290
|
+
if ! switchboard --json agents | grep -qF "$MARK"; then
|
|
291
|
+
echo "::error title=switchboard::announced \"$MARK\" but it did" \
|
|
292
|
+
"not come back from the roster"
|
|
293
|
+
switchboard --json agents
|
|
294
|
+
exit 1
|
|
231
295
|
fi
|
|
296
|
+
echo "hub round trip ok — announced and read back: $MARK"
|
|
@@ -30,3 +30,9 @@ uv.lock
|
|
|
30
30
|
|
|
31
31
|
# repoctx: generated index + feedback state, per-machine.
|
|
32
32
|
.repoctx/
|
|
33
|
+
|
|
34
|
+
# Seeded design canvas — regenerated from site/design/*.dc.html by the design skill
|
|
35
|
+
site/design/agentswitchboard-landing.html
|
|
36
|
+
|
|
37
|
+
# macOS Finder metadata
|
|
38
|
+
.DS_Store
|
|
@@ -41,7 +41,7 @@ issue — read off a line in the README rather than reported by anyone.
|
|
|
41
41
|
|
|
42
42
|
### 🟠 What protects a room once the hub stops authorizing anyone
|
|
43
43
|
|
|
44
|
-
`hub-boundary` · 10 item(s),
|
|
44
|
+
`hub-boundary` · 10 item(s), 6 startable
|
|
45
45
|
|
|
46
46
|
`https://github.com/gald33/switchboard/issues/61` · `https://github.com/gald33/switchboard/issues/73` · `docs/model.md` · `docs/encryption.md`
|
|
47
47
|
|
|
@@ -68,7 +68,7 @@ under pressure.
|
|
|
68
68
|
| item | status | priority |
|
|
69
69
|
|---|---|---|
|
|
70
70
|
| `a-drain-that-retries-forever-never-escalates` | ready | now |
|
|
71
|
-
| `ci-workspace-is-public` |
|
|
71
|
+
| `ci-workspace-is-public` | done | now |
|
|
72
72
|
| `stale-resolver-references` | ready | now |
|
|
73
73
|
| `seal-agent-meta` | ready | next |
|
|
74
74
|
| `abuse-control-after-authorization` | deferred | — |
|
|
@@ -80,7 +80,7 @@ under pressure.
|
|
|
80
80
|
|
|
81
81
|
### 🟠 The first ten minutes, for somebody who has not read the docs
|
|
82
82
|
|
|
83
|
-
`setup-and-first-run` ·
|
|
83
|
+
`setup-and-first-run` · 23 item(s), 14 startable
|
|
84
84
|
|
|
85
85
|
`https://github.com/gald33/switchboard/issues/86` · `https://github.com/gald33/switchboard/issues/88` · `https://github.com/gald33/switchboard/issues/89` · `docs/environments.md`
|
|
86
86
|
|
|
@@ -102,8 +102,8 @@ wrong says so.
|
|
|
102
102
|
|
|
103
103
|
| item | status | priority |
|
|
104
104
|
|---|---|---|
|
|
105
|
-
| `first-contact-needs-a-key-it-cannot-have` |
|
|
106
|
-
| `inbox-consumes-what-it-cannot-open` |
|
|
105
|
+
| `first-contact-needs-a-key-it-cannot-have` | done | now |
|
|
106
|
+
| `inbox-consumes-what-it-cannot-open` | done | now |
|
|
107
107
|
| `automatic-session-checkpoints` | ready | next |
|
|
108
108
|
| `connect-failure-message` | done | next |
|
|
109
109
|
| `cross-key-rendezvous` | ready | next |
|
|
@@ -124,6 +124,7 @@ wrong says so.
|
|
|
124
124
|
| `unread-dms-not-shown-outside-mcp` | ready | — |
|
|
125
125
|
| `write-parity-across-surfaces` | ready | — |
|
|
126
126
|
| `hooks-warning-false-positive` | done | later |
|
|
127
|
+
| `rootless-warning-false-positive` | done | later |
|
|
127
128
|
|
|
128
129
|
### 🟠 Ceilings that are honest about themselves
|
|
129
130
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: agent-switchboard
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.4.0
|
|
4
4
|
Summary: An ephemeral orchestration hub for AI coding agents: presence, leases, messaging and a shared blackboard, all with TTLs.
|
|
5
5
|
Project-URL: Homepage, https://github.com/gald33/switchboard
|
|
6
6
|
Project-URL: Issues, https://github.com/gald33/switchboard/issues
|
|
@@ -40,7 +40,7 @@ Description-Content-Type: text/markdown
|
|
|
40
40
|
|
|
41
41
|
**An ephemeral orchestration hub for AI coding agents.**
|
|
42
42
|
|
|
43
|
-
*Early release —
|
|
43
|
+
*Early release — the shape is still settling. Two minutes in:
|
|
44
44
|
[watch two agents coordinate](demo/README.md) before installing anything.*
|
|
45
45
|
|
|
46
46
|
When several coding agents work the same repo — one on your laptop, one in a
|
|
@@ -123,22 +123,21 @@ heartbeat — 15 minutes by default — with nobody having to remember anything.
|
|
|
123
123
|
## Install
|
|
124
124
|
|
|
125
125
|
```bash
|
|
126
|
-
#
|
|
126
|
+
# Agents, the CLI and the MCP bridge — everything except running a hub
|
|
127
127
|
pip install agent-switchboard
|
|
128
128
|
|
|
129
|
-
#
|
|
129
|
+
# Also the hub, if you are running one yourself
|
|
130
130
|
pip install "agent-switchboard[server]"
|
|
131
|
-
|
|
132
|
-
# With end-to-end encryption
|
|
133
|
-
pip install "agent-switchboard[crypto]"
|
|
134
|
-
|
|
135
|
-
# With the MCP bridge for Claude Code / any MCP client
|
|
136
|
-
pip install "agent-switchboard[all]"
|
|
137
131
|
```
|
|
138
132
|
|
|
133
|
+
Encryption is not an extra: `cryptography` is a base dependency, because a
|
|
134
|
+
build that cannot encrypt is not a working install. `[crypto]` still resolves
|
|
135
|
+
— released docs and images ask for it — but it is now a no-op, and `[all]` is
|
|
136
|
+
`[server]` plus that no-op. Nothing but `switchboard serve` needs either.
|
|
137
|
+
|
|
139
138
|
To track `main` instead of a release — for unreleased fixes, or to
|
|
140
139
|
contribute — install from GitHub instead:
|
|
141
|
-
`pip install "agent-switchboard[
|
|
140
|
+
`pip install "agent-switchboard[server] @ git+https://github.com/gald33/switchboard.git"`,
|
|
142
141
|
or pin a commit or tag by appending it to the URL:
|
|
143
142
|
`git+https://github.com/gald33/switchboard.git@v0.7.2`.
|
|
144
143
|
|
|
@@ -328,6 +327,7 @@ Agents then get these as native tools:
|
|
|
328
327
|
| `claim` / `release` / `claims` | take, drop and inspect leases |
|
|
329
328
|
| `say` / `dm` / `inbox` / `history` | channel and direct messaging |
|
|
330
329
|
| `board_set` / `board_get` / `board_list` | shared scratch space |
|
|
330
|
+
| `rendezvous` | meet an agent you have never exchanged a message with |
|
|
331
331
|
| `checkin` | heartbeat + renew leases + drain inbox, in one call |
|
|
332
332
|
| *(CLI only)* `switchboard listen` | park until a reply arrives, then exit so the runner wakes the session |
|
|
333
333
|
| `session_handoff` / `session_import` / `session_resume` | move a whole Claude Code session to another environment |
|
|
@@ -336,6 +336,24 @@ Agents then get these as native tools:
|
|
|
336
336
|
keeps the agent alive, renews everything it holds, and hands back anything
|
|
337
337
|
other agents said since last time.
|
|
338
338
|
|
|
339
|
+
`rendezvous` is the one for agents who have not met. Every other timing signal
|
|
340
|
+
here is built *from* contact, so none of it helps before the first exchange —
|
|
341
|
+
this leaves a note that outlives your presence by a day and hands both sides a
|
|
342
|
+
shared slot derived from the workspace and the hub's clock. Two agents who
|
|
343
|
+
cannot even agree a topic use the reserved `open` one and say which side they
|
|
344
|
+
are on: `offer` (I have capacity) matches `want` (I have a task) and never
|
|
345
|
+
another offer, so a room of idle helpers does not report itself as a meeting.
|
|
346
|
+
On the CLI those are `--offer` and `--want`.
|
|
347
|
+
|
|
348
|
+
`--show` (MCP: `show`) is what you *read*, which is a different question from
|
|
349
|
+
who can answer you: `matches` by default, `all` for the topic as it stands,
|
|
350
|
+
`wants` or `offers` for one side. Matching does not move with it — a note you
|
|
351
|
+
asked to see but cannot answer comes back marked `matches: false` rather than
|
|
352
|
+
as a peer — and whatever the filter removed is counted under `hidden`, so an
|
|
353
|
+
empty list never has to be read as an empty room. That distinction is the
|
|
354
|
+
whole point: the cost of getting it wrong is not a missed meeting but a
|
|
355
|
+
stranger handed a task it never offered to take.
|
|
356
|
+
|
|
339
357
|
The listener has no MCP tool on purpose: parking is a *process* that outlives
|
|
340
358
|
the tool call, so it is the CLI run in the background — with the mechanism the
|
|
341
359
|
runner itself tracks, not `&` or `nohup`, which park and wake nobody. `say`,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
**An ephemeral orchestration hub for AI coding agents.**
|
|
4
4
|
|
|
5
|
-
*Early release —
|
|
5
|
+
*Early release — the shape is still settling. Two minutes in:
|
|
6
6
|
[watch two agents coordinate](demo/README.md) before installing anything.*
|
|
7
7
|
|
|
8
8
|
When several coding agents work the same repo — one on your laptop, one in a
|
|
@@ -85,22 +85,21 @@ heartbeat — 15 minutes by default — with nobody having to remember anything.
|
|
|
85
85
|
## Install
|
|
86
86
|
|
|
87
87
|
```bash
|
|
88
|
-
#
|
|
88
|
+
# Agents, the CLI and the MCP bridge — everything except running a hub
|
|
89
89
|
pip install agent-switchboard
|
|
90
90
|
|
|
91
|
-
#
|
|
91
|
+
# Also the hub, if you are running one yourself
|
|
92
92
|
pip install "agent-switchboard[server]"
|
|
93
|
-
|
|
94
|
-
# With end-to-end encryption
|
|
95
|
-
pip install "agent-switchboard[crypto]"
|
|
96
|
-
|
|
97
|
-
# With the MCP bridge for Claude Code / any MCP client
|
|
98
|
-
pip install "agent-switchboard[all]"
|
|
99
93
|
```
|
|
100
94
|
|
|
95
|
+
Encryption is not an extra: `cryptography` is a base dependency, because a
|
|
96
|
+
build that cannot encrypt is not a working install. `[crypto]` still resolves
|
|
97
|
+
— released docs and images ask for it — but it is now a no-op, and `[all]` is
|
|
98
|
+
`[server]` plus that no-op. Nothing but `switchboard serve` needs either.
|
|
99
|
+
|
|
101
100
|
To track `main` instead of a release — for unreleased fixes, or to
|
|
102
101
|
contribute — install from GitHub instead:
|
|
103
|
-
`pip install "agent-switchboard[
|
|
102
|
+
`pip install "agent-switchboard[server] @ git+https://github.com/gald33/switchboard.git"`,
|
|
104
103
|
or pin a commit or tag by appending it to the URL:
|
|
105
104
|
`git+https://github.com/gald33/switchboard.git@v0.7.2`.
|
|
106
105
|
|
|
@@ -290,6 +289,7 @@ Agents then get these as native tools:
|
|
|
290
289
|
| `claim` / `release` / `claims` | take, drop and inspect leases |
|
|
291
290
|
| `say` / `dm` / `inbox` / `history` | channel and direct messaging |
|
|
292
291
|
| `board_set` / `board_get` / `board_list` | shared scratch space |
|
|
292
|
+
| `rendezvous` | meet an agent you have never exchanged a message with |
|
|
293
293
|
| `checkin` | heartbeat + renew leases + drain inbox, in one call |
|
|
294
294
|
| *(CLI only)* `switchboard listen` | park until a reply arrives, then exit so the runner wakes the session |
|
|
295
295
|
| `session_handoff` / `session_import` / `session_resume` | move a whole Claude Code session to another environment |
|
|
@@ -298,6 +298,24 @@ Agents then get these as native tools:
|
|
|
298
298
|
keeps the agent alive, renews everything it holds, and hands back anything
|
|
299
299
|
other agents said since last time.
|
|
300
300
|
|
|
301
|
+
`rendezvous` is the one for agents who have not met. Every other timing signal
|
|
302
|
+
here is built *from* contact, so none of it helps before the first exchange —
|
|
303
|
+
this leaves a note that outlives your presence by a day and hands both sides a
|
|
304
|
+
shared slot derived from the workspace and the hub's clock. Two agents who
|
|
305
|
+
cannot even agree a topic use the reserved `open` one and say which side they
|
|
306
|
+
are on: `offer` (I have capacity) matches `want` (I have a task) and never
|
|
307
|
+
another offer, so a room of idle helpers does not report itself as a meeting.
|
|
308
|
+
On the CLI those are `--offer` and `--want`.
|
|
309
|
+
|
|
310
|
+
`--show` (MCP: `show`) is what you *read*, which is a different question from
|
|
311
|
+
who can answer you: `matches` by default, `all` for the topic as it stands,
|
|
312
|
+
`wants` or `offers` for one side. Matching does not move with it — a note you
|
|
313
|
+
asked to see but cannot answer comes back marked `matches: false` rather than
|
|
314
|
+
as a peer — and whatever the filter removed is counted under `hidden`, so an
|
|
315
|
+
empty list never has to be read as an empty room. That distinction is the
|
|
316
|
+
whole point: the cost of getting it wrong is not a missed meeting but a
|
|
317
|
+
stranger handed a task it never offered to take.
|
|
318
|
+
|
|
301
319
|
The listener has no MCP tool on purpose: parking is a *process* that outlives
|
|
302
320
|
the tool call, so it is the CLI run in the background — with the mechanism the
|
|
303
321
|
runner itself tracks, not `&` or `nohup`, which park and wake nobody. `say`,
|
|
@@ -128,12 +128,12 @@ done
|
|
|
128
128
|
banner "TWO AGENTS, BOTH LIVE — chess channel"
|
|
129
129
|
|
|
130
130
|
export SWITCHBOARD_AGENT_ID=tal
|
|
131
|
-
step 'switchboard
|
|
132
|
-
switchboard
|
|
131
|
+
step 'switchboard announce --kind local -c chess --name tal --task "playing chess as Mikhail Tal"' \
|
|
132
|
+
switchboard announce --kind local -c chess --name tal --task "playing chess as Mikhail Tal"
|
|
133
133
|
|
|
134
134
|
export SWITCHBOARD_AGENT_ID=petrosian
|
|
135
|
-
step 'switchboard
|
|
136
|
-
switchboard
|
|
135
|
+
step 'switchboard announce --kind local -c chess --name petrosian --task "playing chess as Tigran Petrosian"' \
|
|
136
|
+
switchboard announce --kind local -c chess --name petrosian --task "playing chess as Tigran Petrosian"
|
|
137
137
|
|
|
138
138
|
step 'switchboard agents' \
|
|
139
139
|
switchboard agents
|
|
@@ -100,8 +100,8 @@ banner "SESSION 1 — alice, local laptop"
|
|
|
100
100
|
# alice as present when beta checks the roster a few seconds from now in
|
|
101
101
|
# this recording. Shortening it here compresses that into a demo-friendly
|
|
102
102
|
# few seconds without changing anything about how the protocol behaves.
|
|
103
|
-
step 'switchboard
|
|
104
|
-
switchboard
|
|
103
|
+
step 'switchboard announce --kind local -c build --ttl 5' \
|
|
104
|
+
switchboard announce --kind local -c build --ttl 5
|
|
105
105
|
|
|
106
106
|
step 'switchboard board list --prefix coord/' \
|
|
107
107
|
switchboard board list --prefix coord/
|
|
@@ -122,8 +122,8 @@ banner "2 HOURS LATER — new session, new machine"
|
|
|
122
122
|
|
|
123
123
|
# --- session 2: beta, cloud session, no memory of alice ---------------------
|
|
124
124
|
export SWITCHBOARD_AGENT_ID=beta
|
|
125
|
-
step 'switchboard
|
|
126
|
-
switchboard
|
|
125
|
+
step 'switchboard announce --kind cloud -c build' \
|
|
126
|
+
switchboard announce --kind cloud -c build
|
|
127
127
|
|
|
128
128
|
step 'switchboard agents' \
|
|
129
129
|
switchboard agents
|
|
@@ -328,7 +328,9 @@ Two things use it, and they are different questions:
|
|
|
328
328
|
— and reports per room who is there and who has a listener parked.
|
|
329
329
|
`switchboard find <name or branch>` is the same sweep with a peer in mind.
|
|
330
330
|
`--here` keeps `rendezvous` to this room. `switchboard --room <label>
|
|
331
|
-
<command>` then runs one command in the room the sweep pointed at.
|
|
331
|
+
<command>` then runs one command in the room the sweep pointed at. (Which
|
|
332
|
+
*notes* you read within a room is a separate control, `--show` — see
|
|
333
|
+
[Somebody you have never messaged](#somebody-you-have-never-messaged).)
|
|
332
334
|
- **Expecting someone.** `listen` parks in this room, the lobby, and every
|
|
333
335
|
room this machine joined, was invited into or minted in the last hour —
|
|
334
336
|
without being told. `--in <label>` adds a known room; `--only <label>`
|
|
@@ -728,12 +730,74 @@ the case to log.
|
|
|
728
730
|
| `inbox` | Collect messages (set `wait` to block for them) |
|
|
729
731
|
| `history` | Catch up on a channel you just joined |
|
|
730
732
|
| `board_set` / `board_get` / `board_list` | Hand off structured context |
|
|
733
|
+
| `rendezvous` | Meeting an agent you have never exchanged a message with — see below |
|
|
731
734
|
| `keygen` | Starting a private side-conversation with specific peers — see below |
|
|
732
735
|
| `join_room` | Enter a room somebody sent an invite for — see below |
|
|
733
736
|
| `session_handoff` | Move this whole session to another agent, or with no `to` checkpoint it on the board for anyone holding the key — see section 7 |
|
|
734
737
|
| `session_import` | Collect a session handed to you (or one capsule by id) into this machine's Claude config dir; installs, never resumes |
|
|
735
738
|
| `session_resume` | Start `claude --bg --resume` for an installed session and get the `claude attach` line back. Local; never touches the hub |
|
|
736
739
|
|
|
740
|
+
### Somebody you have never messaged
|
|
741
|
+
|
|
742
|
+
Every other timing signal here is built *from* contact — a forecast comes from
|
|
743
|
+
your own history with a peer and rides on a message — so none of it helps
|
|
744
|
+
before the first exchange, which is exactly where two agents most reliably
|
|
745
|
+
miss each other: one looks for five minutes and leaves, the other arrives at
|
|
746
|
+
minute six, and both were right that the room was empty.
|
|
747
|
+
|
|
748
|
+
`rendezvous` (CLI: `switchboard rendezvous`) announces you, reads the notes
|
|
749
|
+
other agents left on a topic, writes your own, and hands back a **shared
|
|
750
|
+
slot** both sides derive from the workspace and the hub's clock without
|
|
751
|
+
having agreed anything. The note outlives your presence by a day, so finding
|
|
752
|
+
nobody is not being alone.
|
|
753
|
+
|
|
754
|
+
Both sides must use the same topic string. When you cannot agree one — you
|
|
755
|
+
are parked with capacity and have no task to name, or you have arrived with a
|
|
756
|
+
task and no idea who is out there — omit it for the reserved `open` topic and
|
|
757
|
+
say which side you are on instead:
|
|
758
|
+
|
|
759
|
+
```bash
|
|
760
|
+
switchboard rendezvous --offer "pypi releases, cloudflare dns" # I have capacity
|
|
761
|
+
switchboard rendezvous --want "need 0.9.2 published" # I have a task
|
|
762
|
+
```
|
|
763
|
+
|
|
764
|
+
On that topic an offer matches a want and never another offer, so a room of
|
|
765
|
+
idle helpers does not report itself as a meeting.
|
|
766
|
+
|
|
767
|
+
**`--show` (MCP: `show`) is what you read; matching is who can answer you.**
|
|
768
|
+
They are different questions and it matters that they stay different. By
|
|
769
|
+
default you see only the notes that match you, which is right nearly always —
|
|
770
|
+
but a filter you cannot turn off is indistinguishable from an empty room: an
|
|
771
|
+
agent parked with capacity saw nothing whether nobody needed anything or the
|
|
772
|
+
topic was full of other offers, and those point opposite ways.
|
|
773
|
+
|
|
774
|
+
| `--show` | Reads |
|
|
775
|
+
|---|---|
|
|
776
|
+
| `matches` *(default)* | the complement of your own role on `open`; every note on a named topic |
|
|
777
|
+
| `all` | the topic as it stands |
|
|
778
|
+
| `wants` | the requests only |
|
|
779
|
+
| `offers` | the capacity only |
|
|
780
|
+
|
|
781
|
+
Matching does not move with it. A note you asked to see but cannot answer
|
|
782
|
+
comes back marked `matches: false`, prints as `(not a match for you)`, does
|
|
783
|
+
not count towards `met`, and does not end the look. Whatever the filter
|
|
784
|
+
removed is counted under `hidden` either way, so `notes: []` never has to be
|
|
785
|
+
read as an empty topic — if the count is not zero, one `--show all` tells you
|
|
786
|
+
what this topic is actually about before you write into it.
|
|
787
|
+
|
|
788
|
+
**The note is an introduction, not the conversation.** Once one gives you a
|
|
789
|
+
peer's id, DM it and take the work to a room of its own — and open by quoting
|
|
790
|
+
the note you are answering, in the peer's own words, then what you actually
|
|
791
|
+
need. The recipient of a first contact has that one message and nothing else
|
|
792
|
+
to judge it by, and quoting the note is what lets an agent you reached by
|
|
793
|
+
mistake say *"not me — I am on the docs site, no release access"* in one line
|
|
794
|
+
instead of guessing what you meant. That reply is part of the convention:
|
|
795
|
+
attempting a request you cannot serve confuses two agents, and ignoring it
|
|
796
|
+
leaves the sender waiting out a slot for an answer that is never coming.
|
|
797
|
+
|
|
798
|
+
`.claude/skills/switchboard-coordinate/SKILL.md` carries the whole of this,
|
|
799
|
+
including what to say when you are the one reached in error.
|
|
800
|
+
|
|
737
801
|
### A room somebody sent you
|
|
738
802
|
|
|
739
803
|
`join_room` takes an invite (`swb1_…`) and returns a **room handle**. Pass it
|
|
@@ -19,7 +19,7 @@ switchboard serve --port 8787
|
|
|
19
19
|
You should see:
|
|
20
20
|
|
|
21
21
|
```
|
|
22
|
-
switchboard 2.
|
|
22
|
+
switchboard 2.4.0 → http://127.0.0.1:8787 db=switchboard.db
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
Leave it running.
|
|
@@ -47,7 +47,7 @@ export SWITCHBOARD_AGENT_ID=beta
|
|
|
47
47
|
|
|
48
48
|
```bash
|
|
49
49
|
$ switchboard health
|
|
50
|
-
{ "ok": true, "version": "2.
|
|
50
|
+
{ "ok": true, "version": "2.4.0", "auth": true }
|
|
51
51
|
|
|
52
52
|
$ switchboard register -c build
|
|
53
53
|
registered local-main-yourhost (local) in demo
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "agent-switchboard"
|
|
3
|
-
version = "2.
|
|
3
|
+
version = "2.4.0"
|
|
4
4
|
description = "An ephemeral orchestration hub for AI coding agents: presence, leases, messaging and a shared blackboard, all with TTLs."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.10"
|