fix: slack channel diagnostics, GW default persistence, model registry#57
Merged
Merged
Conversation
A grab-bag of fixes for issues that surfaced after #56 landed. Three themes: 1) Slack channels weren't usable after workspace reconnect - /api/slack/channels was reading the workspace's `secrets` column raw from SQL, but the integrations table encrypts at rest. Added a `decryptSecret()` step so the channel list loads again. - SlackPollingAdapter and SlackUserAdapter now emit a structured `account_inactive` diagnostic with the exact fix (reinstall the Slack app at api.slack.com/apps + Reconnect in Settings). The `onAuthError` callback grew an `{kind, reason}` info argument so gateway can broadcast `auth_error` events to the UI with proper context. - At adapter boot, probe the default channel via conversations.info on both bot AND user tokens. Surface different diagnostics for "wrong workspace token / stale default" vs "bot not in channel". - `sendAsAgent` retries with the user client when the bot post fails with channel_not_found (the common "forgot to /invite @nomos to this channel" case). Agent stops going dark. - Validate the user token's team_id matches the workspace's teamId at boot — catches OAuth callbacks that wrote the wrong token to a per-workspace row. 2) Google Workspace "Make default" wasn't persisting - The integrations table's `metadata` column was being double-encoded via `JSON.stringify({...})::jsonb`, producing JSONB STRINGS like `"{\"is_default\":true}"` instead of JSONB OBJECTS. Every `metadata->>'is_default'` lookup returned NULL, so the PATCH's `jsonb_set` was a no-op on existing rows. - Fixed all writers to use `sql.json({...})`, and switched the PATCH to overwrite metadata wholesale instead of jsonb_set — wholesale replace self-heals legacy bad rows on the next click. - /api/google/status now reads the manifest first (source of truth), so it agrees with /api/google/accounts and the make- default change shows up immediately. 3) Model registry made dynamic + corrected to match Anthropic docs - New `src/sdk/model-capabilities.ts` (and a settings-side mirror) with the full lineup: Opus 4.7/4.6/4.5, Sonnet 4.6/4.5, Haiku 4.5. Per-model `contextWindow`, `maxOutputTokens`, family. - Corrected to match docs.claude.com/en/docs/about-claude/models: Opus 4.7, Opus 4.6, and Sonnet 4.6 are 1M-context by default (no beta needed). Older Opus / Sonnet 4.5 / Haiku 4.5 stay at 200K. Also fixed maxOutputTokens (Opus 4.7/4.6: 128K, Haiku 4.5: 64K). - /admin/context Model Limits panel now renders from the registry with the current model highlighted, and reports the actual context window from the running config (NOMOS_MODEL + NOMOS_BETAS via /api/admin/context). - Settings page model picker and /model slash-command picker derive their model lists from the registry too — add a new model in one place, it shows up everywhere. Bonus: `NOMOS_BETAS` is now mapped to the `app.betas` config row (both settings/lib/env.ts and src/db/app-config.ts) so future betas can be exposed in UI without another schema change. The 1M-context beta toggle was scaffolded then removed in this same commit once we confirmed it's not needed for any current model. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Grab-bag of fixes for issues that surfaced after #56 merged. Three themes:
Slack channels and diagnostics
/api/slack/channelswas returning 500 because it readsecretsraw from SQL — but the integrations table encrypts at rest. AddeddecryptSecret()step. (settings/src/app/api/slack/channels/route.ts)account_inactivediagnostic upgraded to actionable in both slack-user.ts and slack-polling.ts — exact fix steps (reinstall at api.slack.com/apps + Reconnect) instead of a generic WARN. TheonAuthErrorcallback grew an{kind, reason}info argument so the gateway can broadcast a structured `auth_error` event to the UI.conversations.infoon both bot AND user tokens, surfaces distinct diagnostics for wrong workspace token / stale default vs bot not in channel.sendAsAgentretries with user client when the bot post fails with `channel_not_found` (the common "forgot to /invite @nomos to this channel" case). Agent stops going dark.auth.team_idmatches the workspace's expectedteamIdat boot. Catches OAuth callbacks that wrote the wrong token to a per-workspace row.Google Workspace "Make default" wasn't persisting
The integrations table's `metadata` column was being double-encoded via `JSON.stringify({...})::jsonb` — postgres.js wraps an already-stringified JSON object again, producing JSONB STRINGS like `"{\"is_default\":true}"` instead of JSONB OBJECTS. Every `metadata->>'is_default'` lookup returned NULL, so the PATCH's `jsonb_set` was a no-op.
Fixes:
Model registry made dynamic + corrected to Anthropic docs
Bonus: `NOMOS_BETAS` is now mapped to the `app.betas` config row so future betas can be exposed via UI without another schema change.
Test plan
🤖 Generated with Claude Code