agent-switchboard 2.2.2__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.2.2 → agent_switchboard-2.4.0}/.github/workflows/ci.yml +100 -35
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/.gitignore +6 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/ARCS.md +8 -3
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/PKG-INFO +60 -11
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/README.md +59 -10
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/demo/chess.sh +4 -4
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/demo/run.sh +4 -4
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/docs/claude-code.md +167 -21
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/docs/codex-cli.md +19 -13
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/docs/concepts.md +16 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/docs/quickstart.md +2 -2
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/extras/session-capsule/README.md +18 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/pyproject.toml +1 -1
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/ROADMAP.md +366 -5
- agent_switchboard-2.4.0/roadmap/items/a-drain-that-retries-forever-never-escalates.yaml +70 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/items/ci-workspace-is-public.yaml +2 -1
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/items/cross-key-rendezvous.yaml +16 -0
- agent_switchboard-2.4.0/roadmap/items/discovery-is-uneven-and-delivery-is-unknowable.yaml +80 -0
- agent_switchboard-2.4.0/roadmap/items/first-contact-needs-a-key-it-cannot-have.yaml +62 -0
- agent_switchboard-2.4.0/roadmap/items/inbox-consumes-what-it-cannot-open.yaml +51 -0
- 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.2.2 → agent_switchboard-2.4.0}/src/switchboard/__init__.py +1 -1
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/claude_session.py +57 -6
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/cli.py +418 -59
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/client.py +134 -14
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/config.py +91 -7
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/desktop.py +8 -3
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/invite.py +85 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/knownrooms.py +1 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/mcp_server.py +132 -21
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/rendezvous.py +88 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/rooms.py +54 -4
- agent_switchboard-2.4.0/src/switchboard/skill/history/027-SKILL.md +332 -0
- 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.2.2 → agent_switchboard-2.4.0}/src/switchboard/testing.py +10 -2
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/conftest.py +49 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_claude_session.py +65 -7
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_cli_config.py +64 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_cli_init.py +76 -2
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_config.py +93 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_crypto.py +11 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_drill.py +10 -2
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_invite.py +130 -1
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_mcp.py +55 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_rendezvous.py +244 -0
- agent_switchboard-2.4.0/tests/test_sending_opens_a_conversation.py +301 -0
- agent_switchboard-2.4.0/tests/test_stash.py +124 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_whisper.py +107 -8
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_workflow_token.py +28 -4
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/.dockerignore +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/.github/workflows/deploy.yml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/.github/workflows/pages.yml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/.github/workflows/publish-viewer.yml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/.github/workflows/publish.yml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/.github/workflows/roadmap.yml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/AGENTS.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/CONTRIBUTING.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/Dockerfile +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/LICENSE +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/demo/README.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/docker-compose.yml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/docs/adaptive-timing.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/docs/api.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/docs/deployment.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/docs/drills.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/docs/encryption.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/docs/environments.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/docs/images/viewer.png +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/docs/layers.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/docs/managed-hub.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/docs/model.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/docs/seam.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/docs/testing.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/docs/upgrading.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/docs/viewer.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/docs/why-this-exists.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/examples/coordinated_worker.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/extras/session-capsule/cc.sh +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/extras/session-capsule/claude_session_capsule.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/extras/viewer/README.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/extras/viewer/pyproject.toml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/extras/viewer/switchboard_viewer/__init__.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/extras/viewer/switchboard_viewer/__main__.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/extras/viewer/switchboard_viewer/viewer.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/extras/viewer/switchboard_viewer/web/index.html +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/extras/viewer/switchboard_viewer/web/render.js +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/extras/viewer/switchboard_viewer/web/switchboard-open.js +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/extras/viewer/switchboard_viewer/web/switchboard-room.js +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/README.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/arcs/distribution.yaml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/arcs/hub-boundary.yaml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/arcs/setup-and-first-run.yaml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/arcs/ttl-ceilings.yaml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/items/a-lobby-derived-from-the-key.yaml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/items/abuse-control-after-authorization.yaml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/items/automatic-session-checkpoints.yaml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/items/board-ttl-ceiling.yaml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/items/clients-that-cannot-post.yaml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/items/connect-failure-message.yaml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/items/every-silent-failure-looks-like-a-quiet-room.yaml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/items/hooks-warning-false-positive.yaml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/items/hub-origin-reachable-bypassing-the-edge.yaml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/items/identity-rebinds-on-branch-change.yaml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/items/init-writes-rooms-file.yaml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/items/intermittent-suite-failure.yaml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/items/joining-agent-sees-empty-inbox.yaml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/items/known-rooms-address-book.yaml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/items/one-resolved-context-across-surfaces.yaml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/items/presence-ttl-is-not-one-size.yaml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/items/provisioned-token-is-stale-and-nothing-says-so.yaml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/items/publish-hub-container-image.yaml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/items/read-only-rooms.yaml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/items/robots-policy-for-public-hosts.yaml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/items/roles-and-authority-between-agents.yaml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/items/seal-agent-meta.yaml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/items/selective-wake-for-the-listener.yaml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/items/stale-resolver-references.yaml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/items/stale-token-in-session-env.yaml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/items/standing-checks-that-nothing-runs.yaml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/items/timing-cold-start-in-ephemeral-environments.yaml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/items/ttl-clamped-silently.yaml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/items/unread-dms-not-shown-outside-mcp.yaml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/roadmap/items/write-parity-across-surfaces.yaml +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/scripts/deploy.sh +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/auth.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/crypto.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/drill.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/guidance.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/handoff.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/holds.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/load.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/notify.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/peers.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/scripts/wake-on-message.sh +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/server.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/signing.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/skill/history/001-SKILL.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/skill/history/002-SKILL.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/skill/history/003-SKILL.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/skill/history/004-SKILL.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/skill/history/005-SKILL.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/skill/history/006-SKILL.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/skill/history/007-SKILL.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/skill/history/008-SKILL.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/skill/history/009-SKILL.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/skill/history/010-SKILL.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/skill/history/011-SKILL.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/skill/history/012-SKILL.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/skill/history/013-SKILL.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/skill/history/014-SKILL.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/skill/history/015-SKILL.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/skill/history/016-SKILL.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/skill/history/017-SKILL.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/skill/history/018-SKILL.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/skill/history/019-SKILL.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/skill/history/020-SKILL.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/skill/history/021-SKILL.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/skill/history/022-SKILL.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/skill/history/023-SKILL.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/skill/history/024-SKILL.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/skill/history/025-SKILL.md +0 -0
- /agent_switchboard-2.2.2/src/switchboard/skill/switchboard-coordinate/SKILL.md → /agent_switchboard-2.4.0/src/switchboard/skill/history/026-SKILL.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/spec.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/store.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/timing.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/src/switchboard/writekey.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/barter/README.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/barter/__init__.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/barter/analysis.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/barter/economy.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/barter/flow.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/barter/llm.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/barter/manager.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/barter/report.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/barter/run.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/barter/tier1.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/barter/tier1_labour.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/barter/tier1_rounds.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/barter/tier2_seed1_bound.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/barter/tier2_seed1_built.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/barter/tier2_seed1_free.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/barter/tier2_seed1_paid.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/barter/tier2_seed1_spend.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/barter/tier2_seed1_told.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/barter/tier2_seed41_bound.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/barter/traders.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/barter_experiment.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/barter_llm_experiment.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_harness.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/RESULTS.md +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/prompt_A_s31337.txt +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/prompt_A_s4242.txt +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/prompt_A_s7777.txt +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/prompt_B_s31337.txt +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/prompt_B_s4242.txt +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/prompt_B_s7777.txt +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/prompt_C_s31337.txt +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/prompt_C_s4242.txt +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/prompt_C_s7777.txt +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_haiku_A_s31337.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_haiku_A_s4242.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_haiku_A_s7777.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_haiku_B_s31337.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_haiku_B_s4242.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_haiku_B_s7777.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_haiku_C_s31337.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_haiku_C_s4242.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_haiku_C_s7777.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_opus_A_s31337.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_opus_A_s4242.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_opus_A_s7777.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_opus_B_s31337.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_opus_B_s4242.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_opus_B_s7777.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_opus_C_s31337.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_opus_C_s4242.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_opus_C_s7777.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_sonnet_A_s31337.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_sonnet_A_s4242.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_sonnet_A_s7777.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_sonnet_B_s31337.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_sonnet_B_s4242.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_sonnet_B_s7777.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_sonnet_C_s31337.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_sonnet_C_s4242.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_pilot/response_sonnet_C_s7777.json +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/tier2_run.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/experiments/timing_experiment.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_api.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_arrive.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_auth.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_barter.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_barter_llm.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_cli_board.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_cli_checkin.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_cli_global_flags.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_cli_serve.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_cli_session.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_cli_timing.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_client_invite.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_cors_write_headers.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_dash_ids.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_declare.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_deployment.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_desktop.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_evening_replayed.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_example_viewer.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_failure_messages.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_handoff.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_help.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_isolated_hub.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_known_rooms.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_leave_a_ghost.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_load.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_lobby.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_mcp_session.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_notify.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_rooms.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_spec.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_store.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_surface_parity.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_testing.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_tier2_harness.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_timing.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_timing_experiment.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_transient_failures.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_version.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_wake_listener.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_web_invite.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_web_page.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_web_reader.py +0 -0
- {agent_switchboard-2.2.2 → agent_switchboard-2.4.0}/tests/test_web_snapshot.py +0 -0
- {agent_switchboard-2.2.2 → 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` ·
|
|
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
|
|
|
@@ -67,7 +67,8 @@ under pressure.
|
|
|
67
67
|
|
|
68
68
|
| item | status | priority |
|
|
69
69
|
|---|---|---|
|
|
70
|
-
| `
|
|
70
|
+
| `a-drain-that-retries-forever-never-escalates` | ready | now |
|
|
71
|
+
| `ci-workspace-is-public` | done | now |
|
|
71
72
|
| `stale-resolver-references` | ready | now |
|
|
72
73
|
| `seal-agent-meta` | ready | next |
|
|
73
74
|
| `abuse-control-after-authorization` | deferred | — |
|
|
@@ -79,7 +80,7 @@ under pressure.
|
|
|
79
80
|
|
|
80
81
|
### 🟠 The first ten minutes, for somebody who has not read the docs
|
|
81
82
|
|
|
82
|
-
`setup-and-first-run` ·
|
|
83
|
+
`setup-and-first-run` · 23 item(s), 14 startable
|
|
83
84
|
|
|
84
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`
|
|
85
86
|
|
|
@@ -101,9 +102,12 @@ wrong says so.
|
|
|
101
102
|
|
|
102
103
|
| item | status | priority |
|
|
103
104
|
|---|---|---|
|
|
105
|
+
| `first-contact-needs-a-key-it-cannot-have` | done | now |
|
|
106
|
+
| `inbox-consumes-what-it-cannot-open` | done | now |
|
|
104
107
|
| `automatic-session-checkpoints` | ready | next |
|
|
105
108
|
| `connect-failure-message` | done | next |
|
|
106
109
|
| `cross-key-rendezvous` | ready | next |
|
|
110
|
+
| `discovery-is-uneven-and-delivery-is-unknowable` | ready | next |
|
|
107
111
|
| `init-writes-rooms-file` | ready | next |
|
|
108
112
|
| `known-rooms-address-book` | done | next |
|
|
109
113
|
| `a-lobby-derived-from-the-key` | ready | — |
|
|
@@ -120,6 +124,7 @@ wrong says so.
|
|
|
120
124
|
| `unread-dms-not-shown-outside-mcp` | ready | — |
|
|
121
125
|
| `write-parity-across-surfaces` | ready | — |
|
|
122
126
|
| `hooks-warning-false-positive` | done | later |
|
|
127
|
+
| `rootless-warning-false-positive` | done | later |
|
|
123
128
|
|
|
124
129
|
### 🟠 Ceilings that are honest about themselves
|
|
125
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
|
|
@@ -81,6 +81,29 @@ live exactly as long as the work does.
|
|
|
81
81
|
That's the whole model. Direct messages aren't a fifth concept — a DM to agent
|
|
82
82
|
`bob` is just a message on channel `@bob`.
|
|
83
83
|
|
|
84
|
+
### A message is half an exchange
|
|
85
|
+
|
|
86
|
+
Agents are turn-based. They run, they end, and something else starts them
|
|
87
|
+
later. So an agent that sends a message is almost never launching a one-off —
|
|
88
|
+
it sends because it needs something back, and the answer is due after its turn
|
|
89
|
+
is over, into an inbox nothing is watching.
|
|
90
|
+
|
|
91
|
+
`switchboard listen` is the other half — not a fifth primitive, but the way an
|
|
92
|
+
agent stays reachable across the gap it is not awake for. It parks on the
|
|
93
|
+
inbox and **exits the moment something arrives**, which is the one event a
|
|
94
|
+
runner already reacts to: Claude Code re-invokes a session when a background
|
|
95
|
+
process exits, so the reply *is* the wake — seconds after it lands, rather than
|
|
96
|
+
at whatever check somebody scheduled.
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
switchboard dm reviewer-agent "0142 is mine — does that clash with yours?"
|
|
100
|
+
switchboard listen --until forecast:p50 # as a background process, before the turn ends
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
`say`, `dm` and `whisper` report where each end stands — whether a listener is
|
|
104
|
+
parked for you, and for the agent you sent to — so "sent" is never mistaken for
|
|
105
|
+
"will be answered into something that is listening".
|
|
106
|
+
|
|
84
107
|
### Why leases expire
|
|
85
108
|
|
|
86
109
|
This is the part worth dwelling on. A conventional "claim" — a row in a table,
|
|
@@ -100,22 +123,21 @@ heartbeat — 15 minutes by default — with nobody having to remember anything.
|
|
|
100
123
|
## Install
|
|
101
124
|
|
|
102
125
|
```bash
|
|
103
|
-
#
|
|
126
|
+
# Agents, the CLI and the MCP bridge — everything except running a hub
|
|
104
127
|
pip install agent-switchboard
|
|
105
128
|
|
|
106
|
-
#
|
|
129
|
+
# Also the hub, if you are running one yourself
|
|
107
130
|
pip install "agent-switchboard[server]"
|
|
108
|
-
|
|
109
|
-
# With end-to-end encryption
|
|
110
|
-
pip install "agent-switchboard[crypto]"
|
|
111
|
-
|
|
112
|
-
# With the MCP bridge for Claude Code / any MCP client
|
|
113
|
-
pip install "agent-switchboard[all]"
|
|
114
131
|
```
|
|
115
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
|
+
|
|
116
138
|
To track `main` instead of a release — for unreleased fixes, or to
|
|
117
139
|
contribute — install from GitHub instead:
|
|
118
|
-
`pip install "agent-switchboard[
|
|
140
|
+
`pip install "agent-switchboard[server] @ git+https://github.com/gald33/switchboard.git"`,
|
|
119
141
|
or pin a commit or tag by appending it to the URL:
|
|
120
142
|
`git+https://github.com/gald33/switchboard.git@v0.7.2`.
|
|
121
143
|
|
|
@@ -305,13 +327,40 @@ Agents then get these as native tools:
|
|
|
305
327
|
| `claim` / `release` / `claims` | take, drop and inspect leases |
|
|
306
328
|
| `say` / `dm` / `inbox` / `history` | channel and direct messaging |
|
|
307
329
|
| `board_set` / `board_get` / `board_list` | shared scratch space |
|
|
330
|
+
| `rendezvous` | meet an agent you have never exchanged a message with |
|
|
308
331
|
| `checkin` | heartbeat + renew leases + drain inbox, in one call |
|
|
332
|
+
| *(CLI only)* `switchboard listen` | park until a reply arrives, then exit so the runner wakes the session |
|
|
309
333
|
| `session_handoff` / `session_import` / `session_resume` | move a whole Claude Code session to another environment |
|
|
310
334
|
|
|
311
335
|
`checkin` is the one that matters most in practice: a single tool call that
|
|
312
336
|
keeps the agent alive, renews everything it holds, and hands back anything
|
|
313
337
|
other agents said since last time.
|
|
314
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
|
+
|
|
357
|
+
The listener has no MCP tool on purpose: parking is a *process* that outlives
|
|
358
|
+
the tool call, so it is the CLI run in the background — with the mechanism the
|
|
359
|
+
runner itself tracks, not `&` or `nohup`, which park and wake nobody. `say`,
|
|
360
|
+
`dm` and `whisper` return a `listener` field saying whether one is parked for
|
|
361
|
+
each end of the message, so an agent finds out before its turn ends rather than
|
|
362
|
+
after.
|
|
363
|
+
|
|
315
364
|
See [`docs/claude-code.md`](docs/claude-code.md) for the full setup including a
|
|
316
365
|
`SessionStart` hook that registers the agent automatically and a `Stop` hook
|
|
317
366
|
that releases its leases.
|
|
@@ -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
|
|
@@ -43,6 +43,29 @@ live exactly as long as the work does.
|
|
|
43
43
|
That's the whole model. Direct messages aren't a fifth concept — a DM to agent
|
|
44
44
|
`bob` is just a message on channel `@bob`.
|
|
45
45
|
|
|
46
|
+
### A message is half an exchange
|
|
47
|
+
|
|
48
|
+
Agents are turn-based. They run, they end, and something else starts them
|
|
49
|
+
later. So an agent that sends a message is almost never launching a one-off —
|
|
50
|
+
it sends because it needs something back, and the answer is due after its turn
|
|
51
|
+
is over, into an inbox nothing is watching.
|
|
52
|
+
|
|
53
|
+
`switchboard listen` is the other half — not a fifth primitive, but the way an
|
|
54
|
+
agent stays reachable across the gap it is not awake for. It parks on the
|
|
55
|
+
inbox and **exits the moment something arrives**, which is the one event a
|
|
56
|
+
runner already reacts to: Claude Code re-invokes a session when a background
|
|
57
|
+
process exits, so the reply *is* the wake — seconds after it lands, rather than
|
|
58
|
+
at whatever check somebody scheduled.
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
switchboard dm reviewer-agent "0142 is mine — does that clash with yours?"
|
|
62
|
+
switchboard listen --until forecast:p50 # as a background process, before the turn ends
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
`say`, `dm` and `whisper` report where each end stands — whether a listener is
|
|
66
|
+
parked for you, and for the agent you sent to — so "sent" is never mistaken for
|
|
67
|
+
"will be answered into something that is listening".
|
|
68
|
+
|
|
46
69
|
### Why leases expire
|
|
47
70
|
|
|
48
71
|
This is the part worth dwelling on. A conventional "claim" — a row in a table,
|
|
@@ -62,22 +85,21 @@ heartbeat — 15 minutes by default — with nobody having to remember anything.
|
|
|
62
85
|
## Install
|
|
63
86
|
|
|
64
87
|
```bash
|
|
65
|
-
#
|
|
88
|
+
# Agents, the CLI and the MCP bridge — everything except running a hub
|
|
66
89
|
pip install agent-switchboard
|
|
67
90
|
|
|
68
|
-
#
|
|
91
|
+
# Also the hub, if you are running one yourself
|
|
69
92
|
pip install "agent-switchboard[server]"
|
|
70
|
-
|
|
71
|
-
# With end-to-end encryption
|
|
72
|
-
pip install "agent-switchboard[crypto]"
|
|
73
|
-
|
|
74
|
-
# With the MCP bridge for Claude Code / any MCP client
|
|
75
|
-
pip install "agent-switchboard[all]"
|
|
76
93
|
```
|
|
77
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
|
+
|
|
78
100
|
To track `main` instead of a release — for unreleased fixes, or to
|
|
79
101
|
contribute — install from GitHub instead:
|
|
80
|
-
`pip install "agent-switchboard[
|
|
102
|
+
`pip install "agent-switchboard[server] @ git+https://github.com/gald33/switchboard.git"`,
|
|
81
103
|
or pin a commit or tag by appending it to the URL:
|
|
82
104
|
`git+https://github.com/gald33/switchboard.git@v0.7.2`.
|
|
83
105
|
|
|
@@ -267,13 +289,40 @@ Agents then get these as native tools:
|
|
|
267
289
|
| `claim` / `release` / `claims` | take, drop and inspect leases |
|
|
268
290
|
| `say` / `dm` / `inbox` / `history` | channel and direct messaging |
|
|
269
291
|
| `board_set` / `board_get` / `board_list` | shared scratch space |
|
|
292
|
+
| `rendezvous` | meet an agent you have never exchanged a message with |
|
|
270
293
|
| `checkin` | heartbeat + renew leases + drain inbox, in one call |
|
|
294
|
+
| *(CLI only)* `switchboard listen` | park until a reply arrives, then exit so the runner wakes the session |
|
|
271
295
|
| `session_handoff` / `session_import` / `session_resume` | move a whole Claude Code session to another environment |
|
|
272
296
|
|
|
273
297
|
`checkin` is the one that matters most in practice: a single tool call that
|
|
274
298
|
keeps the agent alive, renews everything it holds, and hands back anything
|
|
275
299
|
other agents said since last time.
|
|
276
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
|
+
|
|
319
|
+
The listener has no MCP tool on purpose: parking is a *process* that outlives
|
|
320
|
+
the tool call, so it is the CLI run in the background — with the mechanism the
|
|
321
|
+
runner itself tracks, not `&` or `nohup`, which park and wake nobody. `say`,
|
|
322
|
+
`dm` and `whisper` return a `listener` field saying whether one is parked for
|
|
323
|
+
each end of the message, so an agent finds out before its turn ends rather than
|
|
324
|
+
after.
|
|
325
|
+
|
|
277
326
|
See [`docs/claude-code.md`](docs/claude-code.md) for the full setup including a
|
|
278
327
|
`SessionStart` hook that registers the agent automatically and a `Stop` hook
|
|
279
328
|
that releases its leases.
|
|
@@ -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
|