Skip to content

Configure the platform and manage profiles from the UI instead of hand-editing profile.yaml #69

@sourcehawk

Description

@sourcehawk

Configure the platform and manage profiles from the UI instead of hand-editing profile.yaml

Problem

Configuring a deployment today means hand-editing profile.yaml under ~/.config/triagent/<profile>/, and there is no UI for picking or creating profiles at all. The schema has grown past the point where hand-editing is comfortable: auth, defaults, paths, linked repos, extra MCPs, investigation inputs, namespace derivation, models, prompt-file overrides, and now cloud sources (landing with feature/cloud-context-mcp). A new operator must learn the YAML shape, the ${XDG_*} path-expansion rules, and the base: merge semantics before the launcher will boot cleanly, and a single typo only surfaces as a load error at startup. The launcher exposes no profile read/write API beyond GET /api/profile/inputs and GET /api/profile/prom-defaults, and nothing to enumerate, create, or switch profiles. We want the whole configuration surface — both editing a profile's fields and managing which profile is active — to be point-and-fill and validated, so first-run setup is not YAML archaeology.

In scope

  • A guided, tabbed settings page that creates and edits a profile's configuration fields.
  • A read/write profile API (GET/PUT /api/profile) with server-side validation reusing internal/profile and atomic on-disk writes.
  • Inline editing of the prompt-file overrides' prose (architecture.md, strategies.md, editor.md, wiki_editor.md).
  • Profile lifecycle from the UI: list available profiles, show and switch the active one, create a new profile from scratch, delete an existing one.

Out of scope

  • Editing the system prompt (system.md) prose; it stays non-editable from the UI.
  • Storing or managing cloud credentials/secrets; the cloud config references source_profile and scope, not secret material.
  • Remote/multi-user config sync; this is local launcher state under ~/.config/triagent/.

Risks & mitigations

  • Writing an invalid profile bricks the next boot. Mitigate by validating server-side (the existing internal/profile validation) before any write, and writing through the existing atomicWrite tmp-file-then-rename helper so a failed write never leaves a half-file.
  • base: merge semantics make "what you see" ambiguous (resolved vs. raw overrides). Mitigate by being explicit in the API/UI about whether a field is inherited from base or set on this profile, and round-trip testing that a UI-saved profile loads identically to a hand-authored one.
  • Switching the active profile mid-session touches the launcher boot/reload path. Mitigate by treating switch as an explicit action with a clear reload boundary, scoped into its own sub-issue so the editor can ship first.
  • Cloud config schema is still in flight on feature/cloud-context-mcp. Mitigate by landing the editor against the merged schema and gating the cloud tab on that merge.

Design overview

Two seams, each a sub-issue. The first adds a profile read/write API in internal/server (handlers_profile.go) over the existing internal/profile package: GET /api/profile returns the active profile as structured JSON; PUT /api/profile validates with internal/profile's validate.go and, on success, writes ~/.config/triagent/<profile>/profile.yaml via atomicWrite (round-tripping through gopkg.in/yaml.v3), then reloads. Prompt-file overrides other than system.md are read and written as their own files alongside the profile. The frontend grows a Settings route under frontend/app/(main)/settings/, added to TopNav and the sidebar view union, following the existing "use client" + AppShell conventions, with a section per config group (Profile, Auth, Defaults, Paths, Repos & MCPs, Cloud, Investigations, Prompts, Advanced). The exact layout is left to the implementer to keep coherent and manageable; validation is surfaced inline on save.

The second seam adds profile lifecycle on top: endpoints to enumerate profiles and to create / delete / switch the active one, and the Profile section gains a picker plus create/delete controls. Switch and create reuse the same form and validation path as the editor.

flowchart LR
  subgraph Frontend["frontend/app/(main)/settings/"]
    Editor["Config editor<br/>(per-section form)"]
    Picker["Profile picker<br/>(list / switch / create / delete)"]
  end
  Editor -->|GET/PUT /api/profile| H["internal/server<br/>handlers_profile.go"]
  Picker -->|list / switch / create / delete| H
  H -->|validate| V["internal/profile<br/>validate.go"]
  V -->|ok: atomicWrite| D["~/.config/triagent/&lt;profile&gt;/profile.yaml"]
  V -->|errors| H
  H -->|reload| L["internal/profile loader"]
Loading

Sub-issues

Sub-issues will be linked below as they're filed.

Metadata

Metadata

Assignees

Labels

epicParent issue grouping feature/task/bug sub-issues

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions