Skip to content

fix(gateway): auto-lowercase agent name in Register Agent dialog - #1

Closed
abeldantas wants to merge 21 commits into
mainfrom
feat/auto-lowercase-agent-name
Closed

fix(gateway): auto-lowercase agent name in Register Agent dialog#1
abeldantas wants to merge 21 commits into
mainfrom
feat/auto-lowercase-agent-name

Conversation

@abeldantas

Copy link
Copy Markdown
Owner

Summary

  • Auto-lowercase the agent name input in the gateway's Register Agent dialog so uppercase input like "MyAgent" becomes "myagent" instead of being rejected by server-side validation.
  • Genuinely invalid characters are still caught by the backend.

Test plan

  • Type an uppercase name (e.g. "MyAgent") in the Register Agent dialog — it should appear lowered as you type
  • Submit — no validation error for casing
  • Type genuinely invalid characters (spaces, !, #) — server still rejects them

amaudruz and others added 21 commits August 26, 2026 11:19
…ADME (sandbox-quantum#303)

* Show Switch working in a chat app, with room for one recording per app

* Add the Slack recording

* Replace the overview diagram

* Add the Mattermost recording

* Use the cropped overview diagram
)

* Update CLAUDE.md module layout and doc references to match the tree

The module layout listed directories that do not exist and missed some
that do, and the reference section said the synced docs/official
documentation does not exist.

* Remove tasks from the standalone feature lists

CHOO-1418 removed the task protocol from the skills, but the codex
README and the configure skills still list it as working, which can
confuse agents.

* Rename the generated docs index to TOC.md to fix a case collision

The repo tracked both INDEX.md and index.md. On macOS and Windows these
are the same path, so one of them wins, the docs/README.md link opens
the wrong file, and git status is never clean. The sync script now
writes TOC.md.

* Fix stale references in the codex docs, CONTRIBUTING and console/AGENTS.md

Small stale bits: a comparison with a Claude connector mechanism that
no longer exists, mcp_servers where the file says mcpServers, an
outdated docs row and a dead anchor in CONTRIBUTING, and connector
paths in console/AGENTS.md that resolve from the wrong directory.

* Add Mattermost to the architecture section's platform lists

The architecture section names four platforms but the README supports
five. Added Mattermost to the transport list and the image alt text.
The diagram PNG still shows four icons.

* Add release and CI badges to the readme
…4) (sandbox-quantum#304)

Dismissing the "Setting up Switch" checklist wrote the setting straight
over IPC instead of going through the settings mutation. The panel renders
from the cached `onboarding` setting and nothing broadcasts a settings
change back to the renderer, so the write persisted but the cache kept
saying `showChecklist: true` — the ✕ looked dead until the next launch.

Route the dismissal through the same mutation the Settings toggle uses, so
the cache is updated optimistically and invalidated. This also drops the
`if (!onboarding) return` guard, which silently did nothing when the
setting had not loaded; the mutation merges from the cache itself.

The existing tests mount the presentational panel with a stub `onDismiss`,
so they never touched the wiring. Add a test that mounts the hook and
asserts the cached setting flips, which fails against the old call.
…10 (sandbox-quantum#305)

switch-console 0.31.0 → 0.31.1 (patch):
- fix(console): the setup checklist's ✕ now actually dismisses it (sandbox-quantum#304)

Connector plugins patched so the sandbox-quantum#302 configure-skill correction re-downloads:
switch-connector 0.9.8 → 0.9.9, switch-connector-codex 0.3.9 → 0.3.10. The
standalone feature list no longer claims the task protocol works (removed in
CHOO-1418); codex skill also fixes an mcp_servers → mcpServers reference.
opencode untouched (0.1.5).

No switch-core release: the doc-sync PR (sandbox-quantum#295) only touched a Teams README and a
test under core/, no shipping code — bundle pin stays at 0.21.0. agent-runtime
(0.3.2) and sidecar (1.9.4) unchanged. Contracts stay 1/1.

artifacts.yaml + generated modules regenerated; artifacts-check passes.
Authored all changelog entries (every [Unreleased] was empty).

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…er (sandbox-quantum#307)

* fix(agent-runtime): exit when the host does, instead of running forever

The runtime intended to shut down with its host — `transport.onclose`
stopped the stream, the heartbeat and the lease renewal, then exited. It
never fired. The MCP SDK's stdio transport binds only 'data' and 'error'
on stdin, so `onclose` is reached only by an orderly `close()`, never by
a host that was killed, crashed or force-quit. That exit path was dead
code in exactly the case it existed for.

Nothing else stopped the process either: the hook listener's TCP server
held the event loop open, the 2s heartbeat and lease timers kept running
against a Switch that was gone, and `uncaughtException` swallowed the
resulting EPIPE once `serving` was true rather than letting it escalate.

Measured on one developer machine: 486 processes, 3.5 GB resident, ~198%
CPU, 242 stale loopback listeners, across five runtime versions, the
oldest 18 days. The two longest-lived had grown to 470 MB and 367 MB —
consistent with writes queueing against a stderr pipe whose reader is
gone but which was never closed.

Four independent triggers now, because each covers a case the others
miss: stdin 'end'/'close' for a dropped pipe, the termination signals
for an orderly kill, a stdout/stderr 'error' for a peer that is gone but
not closed, and a ppid watchdog as the backstop — reparenting is the one
signal that survives every way a host can vanish, and SESSION_PPID was
already recorded for the session directory. Any one of them would have
prevented all 486.

The hook listener is also unref'd, so the stdin reader is what holds the
loop open: alive now means a host is attached rather than a port is
bound.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* feat(agent-runtime): clear up runtimes that already outlived their host

The shutdown fix stops new orphans. It does nothing about the ones
already running: every published version up to 0.3.2 lacks it, and those
processes sit there until the machine reboots — 486 of them, 3.5 GB, on
the machine that prompted this. A new runtime now clears them out on its
way up, which reaches a user through the connector pin without waiting
for an app release.

The signal is the process tree, not anything on disk. When the host dies
its `npm exec` wrapper is reparented to init while the runtime carries
on pointing at a wrapper that is alive but orphaned — so "is the parent
dead?" is the wrong question, and would have missed both of the worst
offenders (15765 was very much alive; only its parent was gone).
Reaching init without passing through a live host is the right one, and
it needs no port file, no session directory and no hook.

The match is anchored on argv[0] rather than a substring of the command
line. A substring test also matches any shell that merely mentions the
package — installing it, grepping for it — and an orphaned one of those
would have been killed. An early draft did exactly that; the cases are
pinned in the tests.

The reaper excludes its own chain outright rather than relying on the
walk to spare it. The walk does spare it, since a freshly spawned
runtime has a live host by construction, but a reaper that can reach
itself is one bad predicate away from killing the session it serves.

Stale session directories go too — pure litter from runtimes that were
killed outright and never ran `unpublishPort`, 8071 of them here.

Verified end to end against a real orphan built the way the bug builds
one (host killed with its stdin held open by a third party, so the
runtime never sees EOF): a fresh runtime reported `reaping 2 runtime
process(es) whose host is gone` and `removing 8016 stale session
director(ies)`, and left itself running.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
agent-runtime 0.3.2 → 0.3.3 (patch):
- fix(sandbox-quantum#307): the runtime exits when its host does instead of running forever.
  Its onclose-based shutdown never fired for a killed/crashed/force-quit host,
  and the hook listener + heartbeat/lease timers kept the process alive,
  leaving stale processes and loopback listeners accumulating. Shutdown is now
  driven by four independent triggers (stdin end/close, termination signals,
  stdout/stderr write error, parent-pid watchdog).

Phase 1 of a two-phase runtime release: this publishes 0.3.3 to npm via the
switch-agent-runtime-v0.3.3 tag. The connector runtime pins (claude/codex
.mcp.json, opencode opencode.json, SWITCH_AGENT_RUNTIME_PIN), the plugin
versions, and the sidecar are DELIBERATELY left at their current versions —
a pin must never name a version npm does not have yet. Phase 2 (re-pin +
plugin/sidecar bumps) follows once 0.3.3 is live, on request.

artifacts.yaml + generated modules regenerated; artifacts-check passes.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…-quantum#310)

Phase 2 of the agent-runtime 0.3.3 release (0.3.3 is live on npm). Moves every
runtime pin from 0.3.2 → 0.3.3 and bumps each consumer so the host-exit fix
(sandbox-quantum#307) reaches users:

- Runtime pin → 0.3.3 in all four places: claude & codex .mcp.json, opencode
  opencode.json, and SWITCH_AGENT_RUNTIME_PIN in console distribution.ts (the
  embedded opencode config derives from that constant, so it follows).
- Plugin versions bumped so installs re-download: switch-connector 0.9.9 →
  0.9.10, switch-connector-codex 0.3.10 → 0.3.11, switch-connector-opencode
  0.1.5 → 0.1.6.
- sidecar 1.9.4 → 1.9.5 (runs the new runtime; major stays 1, wire unchanged).

claude/codex reach users on next marketplace Update; opencode + sidecar ride the
next Switch Console release. artifacts.yaml + generated modules regenerated;
artifacts-check passes; pins agree with each other (runtime-pin/connector-assets
tests green).

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
)

* feat(console): reap orphaned agent runtimes at boot

The runtime learned to exit when its host dies, and to clear up
predecessors on startup. Both reach a machine only through the connector
pin, which moves when a user updates a marketplace plugin — so a user who
never revisits Settings → Agents keeps their backlog indefinitely. This
path reaches them when they update the app instead.

The two populations do not overlap as much as they look: someone who
updates the app but not the connector is reached only from here, and
someone running Codex standalone with no Switch Console is reached only by
the runtime. Neither alone covers the fleet.

The predicate is imported from the runtime package, not reimplemented.
Two copies of "is this runtime abandoned?" is a failure mode this repo
already knows — where they disagree, one of them kills a live session —
so `reapOrphanedRuntimes` moved to the package's public surface and both
callers share it.

It now returns what it did rather than taking a log callback. There were
two callers with two ideas of a log line: the runtime writes prose to
stderr, the app wants an enumerated event, and threading either through
the sweep was the wrong shape.

Runs unawaited after the RPC router is up and before session relaunch, so
an abandoned runtime is gone before its replacement starts, without the
window waiting on a full process scan.

Verified against real orphans rather than mocks, twice:

  reaped: 4, removedSessionDirs: 3     — four genuine orphans, all gone
  reaped: 0                            — with a healthy session running,
                                         its runtime, its wrapper and its
                                         session directory all untouched

The second matters more than the first. Killing a live session would be
far worse than leaving an orphan, and it is the case no unit test can
fully stand in for.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* feat(console): bring installed Switch connectors up to date once

A connector's pinned runtime version only moves when a user goes looking
for it in Settings → Agents. Someone who never does keeps whatever they
first installed, across every release — which is how an install ends up
several runtime versions behind without anything being broken enough to
notice.

This is a one-shot catch-up, deliberately not a standing auto-updater.
It latches a generation marker on success and does nothing on every
later launch; the Update button stays the normal path. Bumping
CATCH_UP_GENERATION — a deliberate edit, not a release — is what makes
it run again.

What it will not do:

- install a connector that is not installed. Which agents have one is
  the user's decision, and this is a version catch-up, not an installer.
- latch when the marketplace could not be refreshed. `updateAvailable`
  is false both for "no update" and "could not look", and spending the
  single shot on an answer that never arrived is the one way a one-shot
  fails silently.
- retry forever. Three attempts, then it stops, because "runs every
  launch" is precisely what this is not.

Runs unawaited before session relaunch, so a session started on the old
pin picks the new one up next launch rather than holding up this one.

Verified locally against a real gap. First launch:

  connector_catch_up_updated  claude    0.9.8 -> 0.9.10
  connector_catch_up_updated  opencode  0.1.5 -> 0.1.6
  connector_catch_up_complete updated: 2

Second launch on the same install: no catch-up activity, no marketplace
call, nothing logged — latched.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
switch-console 0.31.1 → 0.31.2 (patch, per request — contains sandbox-quantum#309):
- reap orphaned agent runtimes at boot (sandbox-quantum#309)
- one-shot catch-up to bring already-installed connectors up to date once (sandbox-quantum#309)

Also ships the console-side Phase 2 rollout already on main: the bundled sidecar
(1.9.5) and OpenCode connector (0.1.6) now run agent-runtime 0.3.3. Bundle pin
stays at core 0.21.0 (no core release).

Runtime version drift from sandbox-quantum#309 (runtime source changed but package.json still
0.3.3, matching npm) is deliberately left for the next runtime release — no
user-facing runtime behaviour changed.

artifacts.yaml + generated modules regenerated; artifacts-check passes.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…CHOO-2455)

The New agent dialog greys out "Add agent" whenever the form is not ready but
doesn't tell people why. This fixes that.
The previous commit keyed the tooltip on !runHostReady, which is true both
while the readiness probe is still in flight and when the host is known to
be missing setup. A blocked host got "Waiting for ... to be ready", telling
the user to wait for something that never resolves. Branch on
hostReadiness.checking and hostReadiness.blocked instead, and point the
blocked case at the HostReadinessNotice that names what is missing.

Also runs the file through oxfmt, which the previous commit skipped and
which is what failed CI.
…disabled-reason

Tell the user why "Add agent" is disabled, on hover over the button (CHOO-2455)
…ion-bump-rule

Stop hand-bumping versions per commit; leave it to the release agent
The name input now lowercases as the user types, so "MyAgent" becomes
"myagent" without a server-side validation error. Genuinely invalid
characters are still caught by the backend.
Copilot AI lite review requested due to automatic review settings August 31, 2026 09:59

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The PR bundles multiple unrelated functional areas (gateway UI, runtime process management, release/versioning, docs) under a narrow title/description, increasing review and regression risk.

Pull request overview

This PR combines a small gateway UX change (auto-lowercasing agent names during registration) with a broader set of console/runtime lifecycle fixes, connector pin/version updates, documentation sync output changes, and release metadata updates across the repo.

Changes:

  • Gateway: normalize Register Agent “Name” input to lowercase as the user types.
  • Console/runtime: add orphaned-runtime reaping + shutdown triggers so switch-agent-runtime doesn’t outlive its host; add connector catch-up at boot; bump related artifact versions/pins.
  • Docs/meta: rename docs index output to TOC.md, update README/docs pointers and various release/version tracking files.
File summaries
File Description
signatures/version1/cla.json Adds additional CLA signature entries.
scripts/sync_docs.py Writes docs table-of-contents to docs/official/TOC.md during sync.
README.md Updates top-level marketing copy, badges, images, and embeds demo recordings.
gateway/src/pages/agents/RegisterAgentDialog.tsx Lowercases agent name input on change.
docs/README.md Updates docs pointer from INDEX.md to TOC.md.
docs/official/TOC.md Adds generated documentation table-of-contents file.
core/tests/switch_core/bridges/collaboration/test_slack_adapter.py Adds test ensuring typed !command mentions are normalized.
core/switch_core/bridges/collaboration/slack/adapter.py Normalizes typed-command args via translate_inbound.
core/switch_core/artifacts.py Bumps tracked artifact versions (console/runtime/sidecar/connectors).
CONTRIBUTING.md Updates README anchor and clarifies docs/ directory meaning.
console/packages/switch-agent-runtime/src/reap.ts Adds orphaned runtime/session-dir reaper implementation.
console/packages/switch-agent-runtime/src/reap.test.ts Unit tests for runtime reaper predicates and directory sweeping.
console/packages/switch-agent-runtime/src/index.ts Exports reaper utilities from the runtime package.
console/packages/switch-agent-runtime/src/bin.ts Adds robust shutdown triggers and runs reaper after MCP handshake; unrefs hook listener server.
console/packages/switch-agent-runtime/src/bin.shutdown.test.ts Tests/shims asserting shutdown triggers remain present and effective.
console/packages/switch-agent-runtime/src/artifacts.ts Updates runtime-side artifact version constants.
console/packages/switch-agent-runtime/package.json Bumps runtime package version to 0.3.3.
console/packages/shared/src/artifacts.ts Updates shared artifact version constants.
console/packages/plugins/src/distribution.ts Updates runtime pin used for marketplace/plugin distribution.
console/apps/switch-console-desktop/src/renderer/tests/browser/onboarding-checklist-dismiss.test.tsx Adds renderer test ensuring checklist dismissal updates cached settings and persists.
console/apps/switch-console-desktop/src/renderer/features/onboarding/use-onboarding-checklist.ts Routes dismissal through settings mutation (react-query) instead of direct IPC call.
console/apps/switch-console-desktop/src/renderer/features/locations/components/add-agent-modal/add-agent-modal.tsx Adds tooltip explaining why “Add agent” is disabled.
console/apps/switch-console-desktop/src/main/index.ts Runs orphaned-runtime reap and connector catch-up at boot (best-effort, unawaited).
console/apps/switch-console-desktop/src/main/core/switch-setup/catch-up-connectors.ts Implements one-shot connector catch-up with generation+attempt latching.
console/apps/switch-console-desktop/src/main/core/switch-setup/catch-up-connectors.test.ts Tests catch-up behavior, latching, and retry limits.
console/apps/switch-console-desktop/src/main/core/agent-runtime/reap-orphaned-runtimes.ts Main-process wrapper calling runtime reaper and logging outcomes.
console/apps/switch-console-desktop/src/main/core/agent-runtime/reap-orphaned-runtimes.test.ts Tests main-process reap wrapper behavior and logging.
console/apps/switch-console-desktop/package.json Bumps desktop app version to 0.31.2.
console/AGENTS.md Fixes connector file paths to be relative to console/.
connectors/opencode-plugin/package.json Bumps OpenCode connector version to 0.1.6.
connectors/opencode-plugin/opencode.json Updates runtime pin to @sandboxaq/switch-agent-runtime@0.3.3.
connectors/codex-plugin/skills/configure/SKILL.md Fixes mcpServers naming and adjusts stated feature support text.
connectors/codex-plugin/README.md Updates wording around env var forwarding and feature list.
connectors/codex-plugin/.mcp.json Updates runtime pin to 0.3.3.
connectors/codex-plugin/.codex-plugin/plugin.json Bumps Codex connector version to 0.3.11.
connectors/claude-code-plugin/skills/configure/SKILL.md Adjusts stated feature support text.
connectors/claude-code-plugin/.mcp.json Updates runtime pin to 0.3.3.
connectors/claude-code-plugin/.claude-plugin/plugin.json Bumps Claude Code connector version to 0.9.10.
CLAUDE.md Updates repo guidance text and documentation section.
CHANGELOG.md Adds entries for 0.31.2, runtime 0.3.3, sidecar 1.9.5, connector bumps, etc.
artifacts.yaml Updates declared artifact versions to match bumped packages/connectors.
Review details
  • Files reviewed: 40/43 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines 339 to 343
<TextField
label="Name"
value={name}
onChange={(e) => setName(e.target.value)}
onChange={(e) => setName(e.target.value.toLowerCase())}
fullWidth
Comment thread scripts/sync_docs.py
Comment on lines 260 to +262
rel = page[len(SOURCE_PREFIX) :] or "index"
lines.append(f"- [{rel}]({rel}.md) — <{published_url(page)}>")
(dest / "INDEX.md").write_text("\n".join(lines).rstrip() + "\n", encoding="utf-8")
(dest / "TOC.md").write_text("\n".join(lines).rstrip() + "\n", encoding="utf-8")
@abeldantas abeldantas closed this Aug 31, 2026
@abeldantas
abeldantas deleted the feat/auto-lowercase-agent-name branch August 31, 2026 10:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants