feat(config): add-agent-type wizard at /config (#460) #476

Merged
code-lead merged 1 commit from boss/460 into main 2026-04-27 18:52:48 +00:00
Collaborator

Closes #460

Summary

  • GET /config/agent-types returns sanitised type metadata (no token contents) plus the available roles, with clonable=false flagged on host-mode types so the wizard hides them.
  • POST /config/agent-types clones an existing type into a new one: validates slug + role + template, hits Forgejo /users/{login} to confirm the new user actually exists (typo → 400, no disk write), splices a new block into agents.json with identity/path fields rewritten and routing labels reset, reloads the in-memory config, registers a worker for <name>-default, and reconciles its container. Failures roll the file back. Broadcasts agent_type_created + agent_created over SSE.
  • New /config route renders a list of agent types and an "+ Add agent type" wizard: 3 steps (template + role → name slug-validated + forgejo_user + display_name → confirm with JSON diff). The reconcile result ("created", "started", error) is shown inline on success.

Test plan

  • bun test apps/server/src/http/handlers/config-agent-types.test.ts — 22 specs including AC matrix (clone from dev, slug rejects spaces/uppercase/leading-digit/collision, invalid forgejo_user → 400)
  • bun x turbo run typecheck lint test (whole workspace, 2225 server tests pass)
  • Manual: visit /config, clone dev into a new type, confirm agents.json updated and container reconciled

🤖 Generated with Claude Code

Closes #460 ## Summary - `GET /config/agent-types` returns sanitised type metadata (no token contents) plus the available roles, with `clonable=false` flagged on host-mode types so the wizard hides them. - `POST /config/agent-types` clones an existing type into a new one: validates slug + role + template, hits Forgejo `/users/{login}` to confirm the new user actually exists (typo → 400, no disk write), splices a new block into `agents.json` with identity/path fields rewritten and routing labels reset, reloads the in-memory config, registers a worker for `<name>-default`, and reconciles its container. Failures roll the file back. Broadcasts `agent_type_created` + `agent_created` over SSE. - New `/config` route renders a list of agent types and an "+ Add agent type" wizard: 3 steps (template + role → name slug-validated + forgejo_user + display_name → confirm with JSON diff). The reconcile result ("created", "started", error) is shown inline on success. ## Test plan - [x] `bun test apps/server/src/http/handlers/config-agent-types.test.ts` — 22 specs including AC matrix (clone from `dev`, slug rejects spaces/uppercase/leading-digit/collision, invalid forgejo_user → 400) - [x] `bun x turbo run typecheck lint test` (whole workspace, 2225 server tests pass) - [ ] Manual: visit `/config`, clone `dev` into a new type, confirm `agents.json` updated and container reconciled 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(config): add-agent-type wizard at /config (#460)
All checks were successful
qa / qa (pull_request) Successful in 8m57s
qa / dockerfile (pull_request) Successful in 13s
a4ce19f410
GET /config/agent-types returns sanitised type metadata; POST clones an
existing type, verifies forgejo_user against Forgejo before touching disk,
splices the new block into agents.json, reloads the in-memory config, and
reconciles the new container. A 3-step wizard (template+role → name+user →
confirm+diff) drives it from the dashboard.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
reviewer approved these changes 2026-04-27 18:52:17 +00:00
reviewer left a comment

Pipeline is correct end-to-end: validation order (slug → role → template → host-mode guard → forgejo user → disk write → reload → reconcile), rollback on loader failure, and guardMutating on POST. Test matrix covers all AC items. CI green.

Nits (none blocking): buildPreviewBlock in config.tsx omits container/plugins/caveman fields the server copies from the template — labelling it "key fields shown" rather than a full diff would set clearer expectations. The fallback token path in buildClonedTypeBlock hardcodes /home/charles/… for the case where a template has no token_file; that branch shouldn't be reachable in practice but an explicit error would be safer. No rollback-path test (write succeeds, reload throws), though the rollback logic is well-commented as best-effort.

Pipeline is correct end-to-end: validation order (slug → role → template → host-mode guard → forgejo user → disk write → reload → reconcile), rollback on loader failure, and `guardMutating` on POST. Test matrix covers all AC items. CI green. Nits (none blocking): `buildPreviewBlock` in `config.tsx` omits container/plugins/caveman fields the server copies from the template — labelling it "key fields shown" rather than a full diff would set clearer expectations. The fallback token path in `buildClonedTypeBlock` hardcodes `/home/charles/…` for the case where a template has no `token_file`; that branch shouldn't be reachable in practice but an explicit error would be safer. No rollback-path test (write succeeds, reload throws), though the rollback logic is well-commented as best-effort.
code-lead deleted branch boss/460 2026-04-27 18:52:50 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
charles/claude-hooks!476
No description provided.