Skip to content

Make the config editors consult the agent and a provider#31

Merged
jellologic merged 1 commit into
feat/web-brandingfrom
feat/ux-capability-gating
Jul 24, 2026
Merged

Make the config editors consult the agent and a provider#31
jellologic merged 1 commit into
feat/web-brandingfrom
feat/ux-capability-gating

Conversation

@jellologic

Copy link
Copy Markdown
Owner

Stacked on #30 (branding). Shows only this commit; retargets through the stack as the bases merge.

Triaged from a "why does New agent profile have opus/sonnet when the relevant models depend on the provider?" question. The answer: model pins stay on the agent profile (v3 is right — bare ids let one setup back OpenRouter and z.ai), but the editor didn't consult what it already holds — the selected agent's capabilities and a provider to browse.

The model picker's real bug: browsing needs a provider and the setup names none, so the editor borrowed one from a downstream profile — null on "New agent profile", where the Browse buttons then vanished. Replaced with an explicit "Browse models against" provider lens: used only for the Browse buttons and placeholders, never stored. No schema change.

Capability-aware editors (AgentCapabilities was modelled but unused by the UI):

  • Model slots follow capabilities.models — Kilo shows one slot, OpenCode primary+small, Claude Code the four. Four-tier storage unchanged; hidden slots keep their value.
  • Gateway-compat shows only for agents that consume it; the [1m] copy and the --dangerously-skip-permissions literal appear only for the agent they apply to.
  • Accounts offers session mode only for first-party Anthropic (a ~/.claude login the gateways cannot read); switching to a gateway clears a stale configDir so the token can't reach a foreign host.
  • Profiles no longer badges a session account "no key" (reuses core's credentialSource()).

The one mismatch with no net, closed: a compat flag on a Kilo/OpenCode profile was inert at edit, launch and doctor. compatIgnoredWarning now fires from both adapters so the doctor surfaces a hand-edited or agent-switched config — with a test pinning it.

Verified in a browser against a config with all three agents and a session account. 785 tests, 140.6 kB packed.

The agent-profile editor offered inputs the selected agent silently ignores,
and its model picker was non-functional exactly where it is named. Both come
from the same root: the editor did not consult what it already holds — the
selected agent's capabilities, and a provider to browse. This fixes that, and
the same class of mismatch on the neighbouring screens.

MODEL SELECTION STAYS ON THE AGENT PROFILE — the v3 split is correct. Model ids
are bare, provider-agnostic strings so one setup can back an OpenRouter account
AND a z.ai one without redefinition; moving the pins to Profiles would re-couple
model choice to the credential and still not resolve which catalog a multi-
account profile browses. What was actually wrong: browsing needs a provider and
the setup names none, so the editor BORROWED one from a downstream profile —
null on the "New agent profile" screen, where the Browse buttons then vanished.
Replaced with an explicit "Browse models against" provider lens: any provider,
defaulting to the borrowed/default one, used only for the Browse buttons and the
default-model placeholders, never stored. No schema change.

CAPABILITY-AWARE EDITORS (AgentCapabilities was modelled but unused by the UI):
  - Model slots follow capabilities.models: Kilo ('single') shows one slot
    labelled "model", OpenCode ('primary+small') shows primary + small, Claude
    Code ('tiers') shows the four. Mapped onto the tier keys the adapters read
    (opus; opus+haiku; all four), so the four-tier storage is unchanged and a
    hidden slot keeps its value. The listing counts only the slots the agent uses.
  - Gateway-compat section shows only for agents with capabilities.compatFlags
    (Claude Code). For Kilo/OpenCode it is hidden; flags a previous Claude Code
    setup left behind are kept and explained, not dropped.
  - The Models copy is agent-aware — the [1m] extended-context sentence appears
    only for the agent that sends it.
  - Skip-permissions no longer hardcodes --dangerously-skip-permissions; the
    concrete flag shows only for Claude Code (OpenCode lowers to --auto, Kilo to
    a config block).

PROVIDER-AWARE where the provider is known:
  - Accounts offers session mode only for the first-party Anthropic endpoint
    (baseUrl null, not the custom "ask" provider) — a ~/.claude login the other
    providers cannot read. Switching to a gateway clears a stale configDir so the
    subscription token can never be shipped to a foreign host.
  - Profiles no longer badges a session account "no key" — it reuses core's
    credentialSource(), so a login counts as a credential and only a truly
    empty account warns.

THE ONE MISMATCH WITH NO NET, closed: a compat flag on a Kilo/OpenCode profile
was inert at edit, launch AND doctor. `compatIgnoredWarning` (shared.ts) now
fires from both non-Claude adapters, so the doctor's agentWarnings pass surfaces
a hand-edited or agent-switched config the UI's hiding cannot catch — the
capability-gap-never-silently-dropped rule the tier and session warnings follow.

Verified in a browser against a config with all three agents and a session
account: each agent shows its own slot count, compat hides for the two that
ignore it, session mode is offered only for Anthropic, and the session account
is no longer mislabelled. 785 tests, 140.6 kB packed.

Signed-off-by: jellologic <[email protected]>
@jellologic
jellologic merged commit 9c70d3a into feat/web-branding Jul 24, 2026
4 checks passed
jellologic added a commit that referenced this pull request Jul 24, 2026
* feat(web): swisscode brand — a code-forward mark, logo, and wordmark

Brings the identity into the web UI and refreshes the shared marks, matched
across the config UI (sidebar logo, favicon, empty states) and the public
assets (README hero, npm social card).

THE MARK IS A TERMINAL PROMPT, NOT A SWISS CROSS. A white cross on red is the
Swiss flag and coat of arms — restricted for commercial use, and evocative of
the Victorinox "Swiss Army Knife" marks the product's name plays on. So the mark
keeps the red HANDLE (a colour is not protectable) and drops the cross for a
chevron-plus-cursor `❯█`. It reads three ways at once: a terminal prompt (this
is a coding tool), two blades opening from a pivot (the multi-tool homage the
name is actually about — many providers from one launcher), and none of the
protected emblems. It even rhymes with the `$ █` cursor in the hero's terminal
card.

Scoped by two findings: the trademarked phrase "Swiss Army Knife" appears
nowhere in the repo and "swiss" only ever inside "swisscode", so the name, the
two-tone swiss·code wordmark, and the brand red all stay — only the emblem
changes. And a modified cross does not help, since white-plus-on-red reads as
the flag regardless; the cross had to go entirely.

  - web/src/Brand.tsx — Logo (chevron + block cursor on the red tile), Wordmark
    (swiss in text, code in coral), BrandMark for the sidebar, and a branded
    EmptyState/EmptyGraphic (a faint prompt in a dashed card) for the four true
    empty states. The header comment records WHY the cross was retired so it is
    not "restored" later.
  - web/public/favicon.svg — the same mark, served same-origin so the CSP stays
    'self'. index.html gains the icon link and theme-color metas.
  - assets/hero.svg + social.svg — cross replaced by the same mark via a
    transform reusing the exact geometry; hero.png (2400×760) and social.png
    (1280×640) regenerated with rsvg-convert to match.
  - Two brand.* tokens carry it, RESERVED for identity and never the interactive
    accent (a brand-red button would read as danger, since the dark-mode danger
    and the coral are nearly the same red).

Verified in a browser, both themes: the mark and empty-state graphic render, the
wordmark measures 4.57:1 light / 6.14:1 dark (both clear AA for text), the
favicon reads at 16px, the regenerated PNGs show the new mark at full size, and
no cross geometry remains in any of the four surfaces. The one hardcoded colour
in the new code is the white of the prompt — intrinsic to the mark, not a theme
value, stated where strictTokens does not reach.

783 tests, 139.9 kB packed (ceiling 150).

Signed-off-by: jellologic <[email protected]>

* feat(web): make the config editors consult the agent and a provider (#31)

The agent-profile editor offered inputs the selected agent silently ignores,
and its model picker was non-functional exactly where it is named. Both come
from the same root: the editor did not consult what it already holds — the
selected agent's capabilities, and a provider to browse. This fixes that, and
the same class of mismatch on the neighbouring screens.

MODEL SELECTION STAYS ON THE AGENT PROFILE — the v3 split is correct. Model ids
are bare, provider-agnostic strings so one setup can back an OpenRouter account
AND a z.ai one without redefinition; moving the pins to Profiles would re-couple
model choice to the credential and still not resolve which catalog a multi-
account profile browses. What was actually wrong: browsing needs a provider and
the setup names none, so the editor BORROWED one from a downstream profile —
null on the "New agent profile" screen, where the Browse buttons then vanished.
Replaced with an explicit "Browse models against" provider lens: any provider,
defaulting to the borrowed/default one, used only for the Browse buttons and the
default-model placeholders, never stored. No schema change.

CAPABILITY-AWARE EDITORS (AgentCapabilities was modelled but unused by the UI):
  - Model slots follow capabilities.models: Kilo ('single') shows one slot
    labelled "model", OpenCode ('primary+small') shows primary + small, Claude
    Code ('tiers') shows the four. Mapped onto the tier keys the adapters read
    (opus; opus+haiku; all four), so the four-tier storage is unchanged and a
    hidden slot keeps its value. The listing counts only the slots the agent uses.
  - Gateway-compat section shows only for agents with capabilities.compatFlags
    (Claude Code). For Kilo/OpenCode it is hidden; flags a previous Claude Code
    setup left behind are kept and explained, not dropped.
  - The Models copy is agent-aware — the [1m] extended-context sentence appears
    only for the agent that sends it.
  - Skip-permissions no longer hardcodes --dangerously-skip-permissions; the
    concrete flag shows only for Claude Code (OpenCode lowers to --auto, Kilo to
    a config block).

PROVIDER-AWARE where the provider is known:
  - Accounts offers session mode only for the first-party Anthropic endpoint
    (baseUrl null, not the custom "ask" provider) — a ~/.claude login the other
    providers cannot read. Switching to a gateway clears a stale configDir so the
    subscription token can never be shipped to a foreign host.
  - Profiles no longer badges a session account "no key" — it reuses core's
    credentialSource(), so a login counts as a credential and only a truly
    empty account warns.

THE ONE MISMATCH WITH NO NET, closed: a compat flag on a Kilo/OpenCode profile
was inert at edit, launch AND doctor. `compatIgnoredWarning` (shared.ts) now
fires from both non-Claude adapters, so the doctor's agentWarnings pass surfaces
a hand-edited or agent-switched config the UI's hiding cannot catch — the
capability-gap-never-silently-dropped rule the tier and session warnings follow.

Verified in a browser against a config with all three agents and a session
account: each agent shows its own slot count, compat hides for the two that
ignore it, session mode is offered only for Anthropic, and the session account
is no longer mislabelled. 785 tests, 140.6 kB packed.

Signed-off-by: jellologic <[email protected]>

---------

Signed-off-by: jellologic <[email protected]>
@jellologic
jellologic deleted the feat/ux-capability-gating branch July 24, 2026 12:19
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.

1 participant