Skip to content

AI provider credits + mobile empty-state stability & Cairn Stacker easter egg - #98

Merged
ddutchie merged 8 commits into
mainfrom
ddutchie/credits
Jul 26, 2026
Merged

ddutchie merged 8 commits into
mainfrom
ddutchie/credits

Conversation

@ddutchie

@ddutchie ddutchie commented Jul 26, 2026 •

Copy link
Copy Markdown
Owner

What does this PR do?

Bundles the ddutchie/credits line of work plus two follow-up fixes:

  • AI provider credits + searchable models (desktop + mobile): show a provider's remaining credit balance (e.g. OpenRouter) under the model picker, and make the mobile model list searchable/scrollable.
  • Mobile empty-state overlays are now keyboard-stable: Chat and Search empty states are rendered as a shared pinned overlay sibling of their scroll/list, so they no longer drift when the keyboard opens. One anchoring system replaces the two hand-tuned ones.
  • Easter egg restored & expanded: the 5-tap Cairn-icon trigger works again (the pinned overlay had swallowed the taps), and now opens a mini-games menu — the existing Breakout plus a new on-brand Cairn Stacker.
  • Desktop fixes: the "lines changed since you last viewed this note" banner no longer flashes and vanishes on open; Settings → AI/Coding Agent no longer hits a getSnapshot should be cached infinite render loop.
  • Earlier on the branch: mobile sync re-query storm + graph-blanking-after-backgrounding fix, and full-height calendar + light-mode contrast polish.

Type of change

  • Bug fix
  • New feature
  • Refactor / code quality
  • Docs / changelog
  • Tests

Screenshots / recording

Checklist

  • npm run type-check:all passes (mobile tsc --noEmit clean for the mobile changes)
  • npm run lint passes (eslint clean on changed mobile files)
  • npm test passes
  • npm run test:e2e passes (run before merging UI changes or cutting a release)
  • No major-feature "What's New" entry needed (fixes + incremental features; changelogs updated)
  • No hardcoded colours — CSS variables / theme tokens only
  • No text-[Npx] pixel font classes
  • New IPC handlers wrapped in handle() and return IpcResult<T> — n/a to the new mobile work; the credits IPC (electron/ipc/ai-handlers.ts) added earlier on the branch
  • No new DB migrations
  • No new SQL / Database construction outside the two bootstrap sites
  • No new dependencies
  • No new MCP tools
  • No --external: compile-flag changes

Notes for reviewer

  • The desktop verification boxes (npm test, test:e2e, full type-check:all across renderer + electron) I could not run in this environment — please run them before merge.
  • Two focused areas to eyeball on-device:
    1. Empty-state pass-through: with pointerEvents="box-none", confirm scroll / pull-to-refresh / tapping the native search bar still work over the empty state, and that the Chat "Set up AI" button + the 5-tap egg both fire.
    2. Cairn Stacker feel: slide speed ramp (SPEED_RAMP/MAX_SPEED) and the PERFECT_EPS alignment tolerance are tuned by eye — adjust if it feels too easy/hard.
  • The branch is named ddutchie/credits and includes several prior commits; the newest two commits are the empty-state/egg and the note-banner/Settings fixes.

Summary by CodeRabbit

  • New Features
    • Added provider credit/usage “credits left” badges with hover details.
    • Upgraded AI model pickers/search with selected model pinned.
    • Added a hidden Cairn mini-games menu featuring Stacker and Breakout, plus pinned overlay-style empty states.
  • Bug Fixes
    • Note “what’s new” highlights no longer disappear prematurely and remain until dismissed or edited.
    • Fixed an infinite render loop crash in Settings → AI and Coding Agent.
    • Improved iOS reliability for WebView recovery and refined chat/empty-state layout and sync result read/apply reporting.
  • Style
    • Updated iconography, spacing, and lighter border contrast.

ddutchie added 6 commits July 25, 2026 21:46
Mobile: replace the wrapping model chips in AI settings with a search box
and a bounded scrollable list so providers that return 50+ models (e.g.
OpenRouter) are easy to browse. Filters by name, shows a match count, and
pins the selected model in view.

Both: show a provider's remaining credits when it exposes them. Adds an
ai:fetchKeyInfo IPC handler (GET {base}/v1/key, OpenRouter shape) resolved
in the main process, surfaced via a CreditsBadge in ProviderManager on
desktop and getKeyInfo() + a credits card in AiSettingsForm on mobile.
Returns null on any non-2xx/parse/network failure so it hides gracefully
for providers without a credits endpoint (OpenAI, Ollama, LM Studio).

Changelogs: add changelogs/v2.5.10.md; append to mobile v0.1.3.md.
… backgrounding

- sync: report peerOpsApplied as the ops that ACTUALLY changed the DB
  (applyRemote().applied.length), not the raw peer-oplog read count. The
  data-changed signal keys off this, so a quiet 25s/post-write sync cycle no
  longer fires every screen's re-query + embeddings catch-up. Adds a distinct
  peerOpsRead field (mirrors desktop-sync); Sync screen shows it when >applied.
- graph/webview: remount the WKWebView (key bump) on content-process
  termination instead of the unreliable reload() — iOS reclaims a backgrounded
  web view's process, and reload() on a dead process often no-ops/restores a
  blank doc (why swapping layout type 'fixed' it). AppState-aware: rebuild on
  the next foreground if killed while backgrounded. onLoadEnd re-pushes live
  force-mode toggles so a rebuild can't revert them. Same fix for the note
  math/diagram WebViewRenderer.
- tools/registry: memoise the parsed community manifest by raw string (skip
  repeated JSON.parse + schema re-validation); use prebuilt id Sets for
  install checks and useMemo maps for per-row tool defs so unrelated re-renders
  stop re-parsing SQLite per catalog entry.

Changelog: mobile v0.1.3.
- Calendar: full-height layout — month/week grid flexes to fill (week rows
  share height, no grid scroll); selected-day list + Unscheduled tray move to
  a fixed-height (~35%) bottom band that scrolls independently, padded above
  the tab bar. Tray chips render inline (dropped the capped inner scroll).
- Light theme: darker border token so bordered inputs/cards read as defined
  edges instead of flat fills; AI-settings helper text bumped to textSecondary
  for WCAG AA contrast.
- Chat AI-settings icon: brain -> gearshape cog (it opens a settings sheet).
- Board cards: padding 10 -> 12 for consistent rhythm.
Chat and Search empty states lived inside their scroll/list containers, so
they drifted when the keyboard opened (Search re-anchored on every keyboard
resize via useWindowDimensions). Add a shared 'pinned' overlay mode to
EmptyState that renders as a fixed-position sibling of the scroll view, using
one anchoring system for both tabs instead of two hand-tuned ones.

The pinned overlay initially used pointerEvents='none', which killed the
5-tap easter-egg trigger on the Cairn icon (and would have killed Chat's
'Set up AI' button). Switch to 'box-none' so blank overlay area passes touches
through while the icon + action buttons stay tappable.

Five quick taps now opens a hidden mini-games menu offering Breakout plus a new
on-brand Cairn Stacker: a namesake stacking game where a stone slides across
the top and you tap to drop it; overhang is sliced off so the tower narrows,
perfect drops chain a combo, and each stone is a real workspace entity coloured
like the knowledge graph.
…render loop

The 'lines changed since you last viewed this note' banner flashed and vanished
on open: clearing the one-shot change mark re-ran the highlight effect and
wiped the highlight it had just set. Track the last processed mark per note so
our own clear doesn't erase the highlight, drop the 6.5s auto-timeout, and
clear highlights on first edit (line numbers shift).

Settings -> AI / Coding Agent could throw 'getSnapshot should be cached'
(infinite render loop) because the saved-providers selector built a fresh
setModel closure every render, defeating useShallow snapshot caching. Select
the stable store actions instead and build the per-surface setModel wrapper
outside the selector.
@coderabbitai

coderabbitai Bot commented Jul 26, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0b0eda55-7a3d-4f80-898b-0ee5b139af45

📥 Commits

Reviewing files that changed from the base of the PR and between 8859fc2 and 2e87089.

📒 Files selected for processing (8)
  • mobile/app/(tabs)/chat/index.tsx
  • mobile/app/settings/tools.tsx
  • mobile/changelogs/v0.1.3.md
  • mobile/src/components/AiSettingsForm.tsx
  • mobile/src/components/StackerGame.tsx
  • mobile/src/components/ai-settings/styles.ts
  • src/components/notes/note-editor.tsx
  • src/components/settings/endpoint-components.tsx
💤 Files with no reviewable changes (1)
  • src/components/notes/note-editor.tsx
🚧 Files skipped from review as they are similar to previous changes (6)
  • mobile/src/components/ai-settings/styles.ts
  • mobile/app/(tabs)/chat/index.tsx
  • mobile/src/components/AiSettingsForm.tsx
  • mobile/src/components/StackerGame.tsx
  • src/components/settings/endpoint-components.tsx
  • mobile/changelogs/v0.1.3.md

📝 Walkthrough

Walkthrough

This release adds provider credit lookup and display, searchable mobile model selection, pinned empty states, a Stacker mini-game, calendar scrolling changes, WebView recovery, sync metrics, cached tool computations, persistent note-change highlights, and stable provider settings selectors.

Changes

Provider credits and model browsing

Layer / File(s) Summary
Provider credit lookup and settings integration
electron/ipc/ai-handlers.ts, electron/preload.ts, mobile/src/chat/providers/openai.ts, src/components/settings/endpoint-components.tsx, src/components/settings/ProviderManager.tsx
Provider key balances are fetched through IPC or provider endpoints, normalized into key information, refreshed with model loading, and displayed in settings.
Searchable mobile model picker
mobile/src/components/AiSettingsForm.tsx, mobile/src/components/ai-settings/styles.ts
The mobile AI form adds credit information, model filtering, match counts, and a scrollable selected-model list.

Pinned empty states and Cairn games

Layer / File(s) Summary
Pinned chat and search empty states
mobile/app/(tabs)/chat/index.tsx, mobile/app/(tabs)/search/index.tsx, mobile/src/components/EmptyState.tsx
Empty-state content is rendered as pinned overlays with safe-area positioning and non-blocking pointer behavior.
Cairn mini-game menu
mobile/src/components/EmptyState.tsx, mobile/src/components/StackerGame.tsx
The Cairn easter egg opens a platform-specific game chooser and supports Breakout or the new animated Stacker game.

Calendar grid and scrolling layout

Layer / File(s) Summary
Fixed calendar grid and bottom band
mobile/src/components/CalendarView.tsx, mobile/src/components/calendar/styles.ts, mobile/src/components/calendar/DayCell.tsx
The calendar renders week rows in a fixed grid and places selected-day content in an independently scrolling, responsive bottom band.
Unscheduled task tray integration
mobile/src/components/calendar/UnscheduledTray.tsx
The unscheduled tray renders inline within the parent scroll view and accepts bottom inset spacing.

Mobile recovery, synchronization, and cached tools

Layer / File(s) Summary
WebView process recovery
mobile/src/components/KnowledgeGraphWebView.tsx, mobile/src/components/WebViewRenderer.tsx
Terminated WebViews are remounted on recovery, and force-mode state is reapplied after loading.
Sync result accounting
mobile/src/sync/sync.ts, mobile/app/sync.tsx
Sync results separately report peer operations read and applied, and the UI displays the additional read count.
Cached tools and release notes
mobile/src/chat/registry.ts, mobile/app/settings/tools.tsx, mobile/changelogs/v0.1.3.md
Cached manifests and installed tool definitions are reused during rendering, with corresponding release notes updated.

Note highlights and provider selector stability

Layer / File(s) Summary
Persistent note-change highlights
src/components/notes/note-editor.tsx
Note-change marks are processed idempotently, highlights remain until dismissal, editing, or navigation, and stale highlights clear on edits.
Stable provider settings selectors
src/components/settings/ProviderManager.tsx
The saved-provider selector uses stable store actions and constructs the model wrapper outside the selector.

Supporting visual updates

Layer / File(s) Summary
Theme, icon, and board styling
mobile/src/theme.ts, mobile/src/components/toolbar-icons.ts, mobile/src/components/DraggableBoard.tsx
Light-theme border tokens, AI toolbar glyphs, and board card padding are updated.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

  • ddutchie/cairn#83: Both changes modify the mobile search empty-state rendering and scrolling behavior.
  • ddutchie/cairn#85: Both changes modify note-editor “what’s new” change and highlight handling.
  • ddutchie/cairn#95: Both changes modify the saved-provider and model-picker settings flow, including ProviderManager.tsx and endpoint-components.tsx.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 73.91% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly captures the main changes: AI provider credits, mobile empty-state stability, and the Cairn Stacker easter egg.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ddutchie/credits

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

mobile/app/(tabs)/chat/index.tsx

ESLint skipped: missing config or dependency (missing-dependency). The ESLint configuration references a package that is not available in the sandbox.

mobile/app/settings/tools.tsx

ESLint skipped: the ESLint configuration for this file references a package that is not available in the sandbox.

mobile/src/components/AiSettingsForm.tsx

ESLint skipped: the ESLint configuration for this file references a package that is not available in the sandbox.

  • 2 others

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

The set-state-in-effect disable is no longer needed — the setChangedLines([])
reset is now inside a conditional, so the rule doesn't flag it. The stray
directive tripped --max-warnings 0 in CI.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

🧹 Nitpick comments (3)
mobile/src/components/StackerGame.tsx (1)

440-440: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Hardcoded #fff for the stone label. Stone backgrounds come from theme tokens (t.accent, t.info, …), so the foreground should too — t.accentFg keeps contrast correct if the palette changes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@mobile/src/components/StackerGame.tsx` at line 440, Update the stoneLabel
style in StackerGame to use the theme’s t.accentFg token instead of the
hardcoded "`#fff`" color, preserving the existing typography styles.
mobile/src/components/EmptyState.tsx (1)

84-108: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Android Alert.alert is limited to three buttons — this already hits that limit.

The secret-game picker has two choices plus Cancel; if hidden mini-games are meant to grow, use a custom picker instead of adding more Alert.alert options.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@mobile/src/components/EmptyState.tsx` around lines 84 - 108, Replace the
Android Alert.alert picker in openEggMenu with a custom picker component or
modal that supports more than three options, while preserving the existing game
choices, Cancel behavior, and setGame callbacks. Keep the iOS ActionSheetIOS
flow unchanged.
mobile/src/components/AiSettingsForm.tsx (1)

598-620: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Model rows lack accessibilityRole/accessibilityLabel, unlike other interactive elements in this file.

The model list Pressable rows don't declare accessibility role/label/selected-state, while other interactive elements in this same component (e.g. the "Tools & Services" navRow Pressable) do. For a searchable list of selectable options, this is an easy, high-value a11y improvement consistent with the file's own convention.

♿ Suggested accessibility props
                                <Pressable
                                  key={id}
                                  style={[styles.modelRow, active && styles.modelRowActive]}
                                  onPress={() => setModel(id)}
+                                 accessibilityRole="button"
+                                 accessibilityState={{ selected: active }}
+                                 accessibilityLabel={id}
                                >
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@mobile/src/components/AiSettingsForm.tsx` around lines 598 - 620, Add
accessibility metadata to the model-row Pressable elements in the filteredModels
map: declare their button role, provide a descriptive label based on each model
id, and expose the active selection state via the appropriate accessibility
prop. Follow the existing accessibility conventions in AiSettingsForm without
changing the selection behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@mobile/app/`(tabs)/chat/index.tsx:
- Around line 297-316: Move the pinned EmptyState block from before
KeyboardGestureArea to immediately after its closing tag so it paints above the
absolute-fill scroll view and the “Set up AI” Pressable receives taps. Update
the accompanying comment to say pointerEvents="box-none", matching EmptyState’s
pinned behavior, while preserving the existing messages.length and configured
conditions.

In `@mobile/app/settings/tools.tsx`:
- Around line 355-358: Update the component containing mcpToolsById to track a
cache revision state, incrementing it after each refreshServerTools path at the
referenced refresh points (192, 237, and 269). Add that revision to the useMemo
dependency array so the map recomputes whenever refreshed MCP tool definitions
are cached.

In `@mobile/changelogs/v0.1.3.md`:
- Around line 79-81: Move the three bullets describing Apple Intelligence schema
normalization, Tools & Services caching/timeout, and Android API-key entry out
of the accessibility section in mobile/changelogs/v0.1.3.md and place them under
the changelog’s Fixes or Under the hood section. Keep only the
accessibility-related item under the current heading, preserving the existing
bullet text.
- Line 23: Insert a line break between the “Search & filter the community
catalog” bullet and the “Services can bundle several tools” bullet in the
changelog, preserving both bullet entries and their existing text.

In `@mobile/src/components/ai-settings/styles.ts`:
- Around line 176-178: Update creditsSub in the styles definition to use the
accessible textSecondary color instead of textTertiary, matching the treatment
of readable content such as keyNoteText and compatHint while leaving its
typography unchanged.

In `@mobile/src/components/CalendarView.tsx`:
- Around line 319-367: The bottom-band ScrollView must remain reachable and
support drag autoscroll when its content exceeds bottomBandHeight. Update the
ScrollView around UnscheduledTray to use the DragController
integration—ctrl.scrollRef, scrollHandler, onScrollLayout, and
onScrollContentSizeChange—and avoid disabling scrolling solely through
ctrl.scrollLocked during dragging; preserve normal selected-day and tray
rendering while allowing the active drag to scroll this area.

In `@mobile/src/components/StackerGame.tsx`:
- Around line 254-294: The game loop effect currently resets the game whenever W
or H changes because its local started flag is recreated. Update the effect
around step and reset to depend only on visible, and use the mutable gameState
dimensions already synchronized elsewhere rather than capturing W/H; preserve
initialization on visibility changes without wiping the tower or score during
dimension updates.
- Around line 308-311: Update the StackerGame positioning logic around stoneTop,
tower rendering, the moving stone, and particle y coordinates to introduce a
camera offset that keeps the tower top at a stable screen position as
tower.length grows. Add this offset to every rendered top/y calculation,
including the moving stone, and remove or correct firstVisible culling so
on-screen low-index stones remain visible; render all stones or cull based on
their adjusted screen position within fieldTop and fieldBottom.
- Around line 261-294: Update the animation loop in the step function so
publish() is called only when the game state changes, such as movement or
particle updates; avoid publishing while paused, stopped, or otherwise
unchanged, while preserving requestAnimationFrame scheduling and cleanup.

In `@src/components/settings/endpoint-components.tsx`:
- Around line 114-133: The credits lookup writes lack stale-response protection.
In src/components/settings/endpoint-components.tsx lines 114-133, update
fetchKeyInfo to capture and validate the current request generation (using
fetchGenRef/isCurrent or an equivalent identity check) before both setKeyInfo
calls. In mobile/src/components/AiSettingsForm.tsx lines 289-311, guard the
getKeyInfo promise callback with a request generation or active-provider
identity check before setKeyInfo, preventing previous requests from overwriting
current or cleared state.
- Around line 205-210: Update formatCredits in
src/components/settings/endpoint-components.tsx (lines 205-210) and the
duplicated helper in mobile/src/components/AiSettingsForm.tsx (lines 59-64) to
place the minus sign before the dollar symbol for negative amounts, while
preserving the existing positive formatting and precision rules.

---

Nitpick comments:
In `@mobile/src/components/AiSettingsForm.tsx`:
- Around line 598-620: Add accessibility metadata to the model-row Pressable
elements in the filteredModels map: declare their button role, provide a
descriptive label based on each model id, and expose the active selection state
via the appropriate accessibility prop. Follow the existing accessibility
conventions in AiSettingsForm without changing the selection behavior.

In `@mobile/src/components/EmptyState.tsx`:
- Around line 84-108: Replace the Android Alert.alert picker in openEggMenu with
a custom picker component or modal that supports more than three options, while
preserving the existing game choices, Cancel behavior, and setGame callbacks.
Keep the iOS ActionSheetIOS flow unchanged.

In `@mobile/src/components/StackerGame.tsx`:
- Line 440: Update the stoneLabel style in StackerGame to use the theme’s
t.accentFg token instead of the hardcoded "`#fff`" color, preserving the existing
typography styles.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 116cd86b-e117-4957-b217-2648f5314918

📥 Commits

Reviewing files that changed from the base of the PR and between 072f89f and 8859fc2.

📒 Files selected for processing (27)
  • changelogs/v2.5.10.md
  • electron/ipc/ai-handlers.ts
  • electron/preload.ts
  • mobile/app/(tabs)/chat/index.tsx
  • mobile/app/(tabs)/search/index.tsx
  • mobile/app/settings/tools.tsx
  • mobile/app/sync.tsx
  • mobile/changelogs/v0.1.3.md
  • mobile/src/chat/providers/openai.ts
  • mobile/src/chat/registry.ts
  • mobile/src/components/AiSettingsForm.tsx
  • mobile/src/components/CalendarView.tsx
  • mobile/src/components/DraggableBoard.tsx
  • mobile/src/components/EmptyState.tsx
  • mobile/src/components/KnowledgeGraphWebView.tsx
  • mobile/src/components/StackerGame.tsx
  • mobile/src/components/WebViewRenderer.tsx
  • mobile/src/components/ai-settings/styles.ts
  • mobile/src/components/calendar/DayCell.tsx
  • mobile/src/components/calendar/UnscheduledTray.tsx
  • mobile/src/components/calendar/styles.ts
  • mobile/src/components/toolbar-icons.ts
  • mobile/src/sync/sync.ts
  • mobile/src/theme.ts
  • src/components/notes/note-editor.tsx
  • src/components/settings/ProviderManager.tsx
  • src/components/settings/endpoint-components.tsx
💤 Files with no reviewable changes (1)
  • mobile/src/components/calendar/DayCell.tsx

Comment thread mobile/app/(tabs)/chat/index.tsx Outdated
Comment thread mobile/app/settings/tools.tsx
Comment thread mobile/changelogs/v0.1.3.md Outdated
Comment thread mobile/changelogs/v0.1.3.md Outdated
Comment on lines 79 to 81
- **Apple Intelligence works with more tools**: Some installed services (and any tool with an optional/nullable field in its schema) made Apple's on-device / Private Cloud Compute models refuse the whole request with an "unsupported schema type: null" error. Cairn now normalises those schemas to the types Apple accepts before sending them, so those tools work on Apple Foundation Models too.
- **Faster Tools & Services screen**: When a community catalog is already cached, the screen now shows it instantly and refreshes in the background, instead of blocking on a full-screen spinner. The catalog fetch also has a 20-second timeout so a hung network falls back to the cache rather than spinning forever.
- **Android API-key entry**: Installing a key-based service on Android now opens an in-app key prompt (Android has no native text-input alert), so key-based connectors can be added there too — iOS keeps its native prompt.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

These three bullets aren't accessibility items.

Apple Intelligence schema normalisation, the Tools & Services caching/timeout, and the Android key prompt belong under "Fixes" (or "Under the hood"), not "Accessibility" — only line 78 fits that heading.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@mobile/changelogs/v0.1.3.md` around lines 79 - 81, Move the three bullets
describing Apple Intelligence schema normalization, Tools & Services
caching/timeout, and Android API-key entry out of the accessibility section in
mobile/changelogs/v0.1.3.md and place them under the changelog’s Fixes or Under
the hood section. Keep only the accessibility-related item under the current
heading, preserving the existing bullet text.

Comment thread mobile/src/components/ai-settings/styles.ts Outdated
Comment thread mobile/src/components/StackerGame.tsx Outdated
Comment thread mobile/src/components/StackerGame.tsx Outdated
Comment thread mobile/src/components/StackerGame.tsx Outdated
Comment thread src/components/settings/endpoint-components.tsx
Comment thread src/components/settings/endpoint-components.tsx Outdated
…11y polish

- chat: paint pinned empty state above the scroll view so "Set up AI" is tappable
- tools: recompute cached MCP tool-def map after each refreshServerTools
- credits: guard fetchKeyInfo/getKeyInfo with a generation so stale responses
  can't overwrite current/cleared state (desktop + mobile); minus sign before $
- stacker: stop resetting on dimension changes, add a camera offset so the
  growing tower stays on screen, publish only on real state changes, theme the
  stone label + game-over close text
- ai-settings: readable credits subtext; a11y on model rows
- changelog: fix bullet line break + move non-a11y items out of Accessibility
@ddutchie
ddutchie merged commit be05dab into main Jul 26, 2026
6 checks passed
@ddutchie
ddutchie deleted the ddutchie/credits branch July 26, 2026 19:03
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