Skip to content

CL-6568: tell people before they type, and don't lie when it fails - #280

Merged
TheGreatAxios merged 2 commits into
mainfrom
cl-no-model-honest
Aug 22, 2026
Merged

CL-6568: tell people before they type, and don't lie when it fails#280
TheGreatAxios merged 2 commits into
mainfrom
cl-no-model-honest

Conversation

@TheGreatAxios

Copy link
Copy Markdown
Contributor

Summary

CL-6568: https://linear.app/abklabs/issue/CL-6568

A tenant's model_provider row seeds with no credential attached, so
"a provider row exists" was standing in for "a model can run." Fixed on
three fronts, in the reported priority order:

  • Pre-send: hasUsableModel (@corbits/inference-settings) reads
    the same resolved catalog resolveModelSources acts on at launch —
    true only once some model actually resolves an offering, never mere
    row presence. The composer now shows NoUsableModelBanner above
    itself (never disabling it) leading into Settings → AI providers
    whenever this tenant has none, for any workbench with an agent
    participant.
  • Failure message: the server (postUndeliveredNotice) already
    writes cause-aware text distinguishing a missing credential from a
    generic dispatch failure, but the client's FailedTurnStrip discarded
    it for a fixed "may be unavailable" guess. It now renders the
    notice's own text.
  • Don't lose the message: onRetryFailedTurn was wired nowhere —
    clicking Retry did nothing. findRetryText recovers the original
    request text and Retry now hands it back into the composer.

Test plan

  • bun test green in @corbits/chat-ui (668 pass) and
    @corbits/inference-settings (39 pass)
  • tsc --noEmit clean in @corbits/chat-ui, @corbits/inference-settings,
    @workbench/web
  • bun run check:browser-safe-subpaths, check:licenses,
    check:tool-package-pins all pass
  • bunx prettier --write + eslint clean on every changed file
  • Manual click-through in a live app with a no-credential tenant
    (not run — no browser session in this environment)

Covers a tenant whose model_provider row has no credential, the
failed-turn strip surfacing the server's cause-aware notice text
instead of a generic guess, and Retry recovering the original request
text so it isn't lost.
A tenant's model_provider row seeds with no credential attached, so
"a provider row exists" was standing in for "a model can run" - the
gap this fixes on three fronts:

- hasUsableModel (@corbits/inference-settings) checks the same
  resolved catalog resolveModelSources acts on at launch, so it's
  false whenever no offering actually resolves, provider row or not.
- The chat composer now shows NoUsableModelBanner and leads into
  Settings -> AI providers before a person invests a message in a
  reply that was never coming - the composer stays live throughout.
- The failed-turn strip renders postUndeliveredNotice's own
  cause-aware text (already distinguishing a missing credential from
  a generic dispatch failure server-side) instead of a fixed "may be
  unavailable" guess, and Retry now hands the original request text
  back to the composer via findRetryText instead of doing nothing.
@TheGreatAxios
TheGreatAxios merged commit b6a56e8 into main Aug 22, 2026
5 checks passed
TheGreatAxios added a commit that referenced this pull request Aug 22, 2026
A hub-owned ANTHROPIC_API_KEY has never been the only valid seed
source in spirit — it was just the only one anything ever triggered
from. Connecting a provider through Settings (packages/connections)
persisted the credential and seeded its catalog, but nothing ever told
the durable pending-seed drain (bench-provisioning.ts) about it, so a
self-serve tenant whose only provider is one it connected itself never
got Myra or the default workflow set, and /api/onboarding/
provisioning-status polled 200 forever with no way to converge.

The connect route now asks the same resolved-catalog question launch
itself asks (hasUsableModel, @corbits/inference-settings, PR #280) once
a credential is durably stored, and — only when that tenant now has a
model with a real offering, never merely because a credential row
exists — hands the connecting provider's own key to the same
pendingSeedStore + benchProvisioner the onboarding credential step
already feeds. That drain is idempotent and restart-safe already, so
routing a Settings connect through it needed no new seeding logic, only
a new trigger.

Also threads a `baseURLOverride` through the pending-seed row end to
end (pending-seed.ts, bench-provisioning.ts) so a url-kind connector
(Ollama) deploys against the instance a person actually pointed at
rather than falling back to a curated default — fixing the same latent
gap in onboarding's own credential-step trigger along the way.
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