Skip to content

refactor: move skillhub from desktop IPC to controller HTTP#279

Merged
alchemistklk merged 6 commits intomainfrom
fix/skill-install-race-condition
Mar 19, 2026
Merged

refactor: move skillhub from desktop IPC to controller HTTP#279
alchemistklk merged 6 commits intomainfrom
fix/skill-install-race-condition

Conversation

@alchemistklk
Copy link
Copy Markdown
Contributor

@alchemistklk alchemistklk commented Mar 19, 2026

Summary

  • Move CatalogManager, SkillDb, and curated-skills from Electron main process (apps/desktop/main/skillhub/) into the controller (apps/controller/src/services/skillhub/)
  • Replace stub skillhub HTTP routes with real CatalogManager-backed implementations so the Skills page Community tab works via HTTP (no IPC needed)
  • Simplify web hooks to HTTP-only — remove all IPC branching (isElectron, NexuHostBridge, getHostBridge())
  • Remove all skillhub IPC from desktop (index.ts, ipc.ts, host.ts, webview-preload.ts, host-api.ts)
  • Remove better-sqlite3, clawhub, npm, @electron/rebuild from desktop deps (moved to controller, except npm which uses PATH-based fallback)
  • Pass SKILLHUB_STATIC_SKILLS_DIR and OPENCLAW_CURATED_SKILLS_DIR env vars to controller sidecar

Test plan

  • pnpm --filter @nexu/controller build passes
  • pnpm --filter @nexu/desktop build passes
  • pnpm --filter @nexu/web typecheck passes
  • pnpm desktop:start — Skills page Community tab shows 12,891 skills (not 0)
  • Install a skill → appears in Installed tab
  • Uninstall a skill → removed from Installed tab
  • Click refresh → catalog re-syncs
  • pnpm desktop:stop && pnpm desktop:start — skills persist across restarts

🤖 Generated with Claude Code

…ough IPC

Replace the fragile .curated-state.json ledger with a SQLite database
(better-sqlite3) in the Electron main process. This eliminates race
conditions and state loss when the bundled-skills directory is wiped.

- Add SkillDb module with schema, install/uninstall tracking, bulk ops,
  and automatic migration from legacy .curated-state.json
- Refactor CatalogManager and curated-skills to use SkillDb instead of
  JSON file state
- Add IPC wrappers (skillhub:*) and switch web hooks to IPC in Electron
  with HTTP fallback for cloud
- Remove duplicate curated state ledger code from API sidecar routes
- Add controller skillhub route documentation for desktop vs cloud split
- Exclude sharp/@img and sqlite build artifacts from electron-builder
  asar to reduce package size (~130MB saved)
- Skip catalog sync and curated skill install in CI to avoid ClawHub
  rate-limit failures
@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented Mar 19, 2026

Deploying nexu-docs with  Cloudflare Pages  Cloudflare Pages

Latest commit: da914a8
Status: ✅  Deploy successful!
Preview URL: https://03196a91.nexu-docs.pages.dev
Branch Preview URL: https://fix-skill-install-race-condi.nexu-docs.pages.dev

View logs

- Wrap SkillDb construction in try-catch so ABI mismatch between system
  Node.js and dev Electron doesn't crash app startup. CatalogManager
  falls back to no-db mode (skills still work, just no cross-restart
  uninstall persistence).
- Skip catalog sync and curated skill install when CI env var is set
  to avoid ClawHub rate-limit failures on shared runners.
- Add desktop vs cloud architecture documentation to controller
  skillhub routes.
Move CatalogManager, SkillDb, and curated-skills from the Electron main
process into the controller so the web app always uses HTTP for skill
catalog/install/uninstall operations. This eliminates the webview IPC
bridge for skills and makes the controller self-contained for both
desktop and cloud deployments.

- Move skillhub modules to apps/controller/src/services/skillhub/
- Add SkillhubService wrapper with lifecycle management
- Replace stub skillhub routes with real CatalogManager-backed handlers
- Simplify web hooks to HTTP-only (remove IPC branching)
- Remove all skillhub IPC from desktop (index.ts, ipc.ts, host.ts)
- Pass SKILLHUB_STATIC_SKILLS_DIR and OPENCLAW_CURATED_SKILLS_DIR
  to controller sidecar via manifests.ts
- Remove better-sqlite3, clawhub, npm, @electron/rebuild from desktop
- Use PATH-based npm in controller instead of bundled npm dep
- Delete obsolete legacy skillhub-routes test
@alchemistklk alchemistklk changed the title fix(desktop): replace JSON skill ledger with SQLite and route ops through IPC refactor: move skillhub from desktop IPC to controller HTTP Mar 19, 2026
Fixes biome a11y/useSemanticElements lint error on the channel card
in home.tsx. The outer div with role="button" is now a native <button>,
which handles keyboard events and accessibility automatically.
@alchemistklk
Copy link
Copy Markdown
Contributor Author

/cr

@slack-code-review-channel
Copy link
Copy Markdown

✅ CR topic created in Feishu topic group Refly CR.

@alchemistklk alchemistklk merged commit 1091f95 into main Mar 19, 2026
7 checks passed
lefarcen pushed a commit that referenced this pull request Mar 19, 2026
* fix(desktop): replace JSON skill ledger with SQLite and route ops through IPC

Replace the fragile .curated-state.json ledger with a SQLite database
(better-sqlite3) in the Electron main process. This eliminates race
conditions and state loss when the bundled-skills directory is wiped.

- Add SkillDb module with schema, install/uninstall tracking, bulk ops,
  and automatic migration from legacy .curated-state.json
- Refactor CatalogManager and curated-skills to use SkillDb instead of
  JSON file state
- Add IPC wrappers (skillhub:*) and switch web hooks to IPC in Electron
  with HTTP fallback for cloud
- Remove duplicate curated state ledger code from API sidecar routes
- Add controller skillhub route documentation for desktop vs cloud split
- Exclude sharp/@img and sqlite build artifacts from electron-builder
  asar to reduce package size (~130MB saved)
- Skip catalog sync and curated skill install in CI to avoid ClawHub
  rate-limit failures

* fix(desktop): make SkillDb init resilient and skip skillhub in CI

- Wrap SkillDb construction in try-catch so ABI mismatch between system
  Node.js and dev Electron doesn't crash app startup. CatalogManager
  falls back to no-db mode (skills still work, just no cross-restart
  uninstall persistence).
- Skip catalog sync and curated skill install when CI env var is set
  to avoid ClawHub rate-limit failures on shared runners.
- Add desktop vs cloud architecture documentation to controller
  skillhub routes.

* refactor: move skillhub from desktop IPC to controller HTTP

Move CatalogManager, SkillDb, and curated-skills from the Electron main
process into the controller so the web app always uses HTTP for skill
catalog/install/uninstall operations. This eliminates the webview IPC
bridge for skills and makes the controller self-contained for both
desktop and cloud deployments.

- Move skillhub modules to apps/controller/src/services/skillhub/
- Add SkillhubService wrapper with lifecycle management
- Replace stub skillhub routes with real CatalogManager-backed handlers
- Simplify web hooks to HTTP-only (remove IPC branching)
- Remove all skillhub IPC from desktop (index.ts, ipc.ts, host.ts)
- Pass SKILLHUB_STATIC_SKILLS_DIR and OPENCLAW_CURATED_SKILLS_DIR
  to controller sidecar via manifests.ts
- Remove better-sqlite3, clawhub, npm, @electron/rebuild from desktop
- Use PATH-based npm in controller instead of bundled npm dep
- Delete obsolete legacy skillhub-routes test

* fix(web): replace role=button div with semantic button element

Fixes biome a11y/useSemanticElements lint error on the channel card
in home.tsx. The outer div with role="button" is now a native <button>,
which handles keyboard events and accessibility automatically.
Siri-Ray pushed a commit that referenced this pull request Mar 20, 2026
* feat(web): restore design-system visual specs

- Add macOS-style Switch component (3 sizes + loading state)
- Sync CSS design tokens from design-system 2.0
- Rewrite Home page with first-run (Idle) and operational states
- Add Enabled/Providers grouping to Settings provider panel
- Integrate xs Switch for Skills install/uninstall toggle
- Add breathe animation for recommended channel cards
- Add InlineModelSelector component for Hero status bar

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(web): refine sidebar nav and home channels panel

- Update sidebar nav to use nav-item/nav-item-active classes
- Add Conversations nav item to main navigation
- Simplify sidebar session items with proper styling
- Refactor home running state channels panel with Chat button
- Update settings page header with heading-page class

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(web): load Caveat font for nexu alpha script text

Replace Great Vibes with Caveat font to match design-system spec
for the "nexu alpha" heading on home page.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(web): correct sidebar layout to match design prototype

- Remove Conversations from main nav (keep as section label only)
- Remove skill count from Skills nav item
- Add fixed sidebar toggle button next to traffic lights (desktop)
- Use logo image instead of text brand for desktop client
- Adjust spacing for desktop client header area

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(web): match home page running state to prototype

- Update Channels panel: connected channels show horizontal rows with
  icon + name + green dot + "Connected" button + "Chat ↗" link
- Not-connected channels display as dashed-border small cards with Cable icon
- Remove bottom quick action cards (conversations, skills, github star)
- Clean up unused imports (navigate, MessageSquare, Sparkles, GITHUB_SVG)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(web): match home page running state hero to prototype

- Change Hero from vertical-centered to horizontal layout (flex items-center gap-4)
- Use var(--color-success) for Running badge color consistency
- Reduce video size from w-32 to w-28 (matching prototype)
- Place model selector and message stats side-by-side in Hero right area
- Remove standalone CTA button (Chat in Feishu) - channels panel has Chat link
- Clean up unused code (getChannelShortNames, FeishuIconChat, firstChannel vars)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(web): add disconnect channel on Connected button click

- Click Connected button to disconnect channel (calls deleteApiV1ChannelsByChannelId)
- Add hover:text-danger and hover:bg-surface-3 styles matching prototype
- Auto-refresh channels list after disconnect

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(web): match InlineModelSelector trigger to prototype style

- Add border, background, padding (px-2.5 py-1 rounded-lg)
- Change text color from text-muted to text-primary
- Increase font size from 11px to 12px, add font-medium
- Increase icon sizes (14/13/10) and gap (1.5)
- Wrap provider logo in 4x4 centered container

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: restore desktop-managed model catalog (#282)

* fix: restore desktop-managed model catalog

* fix: allow selecting desktop cloud models

* chore: remove API smoke workflows

* fix(web): add brand logo and sidebar icon row per prototype

- Copy logo-black-1.svg to public/brand/
- Add Icon row with Help menu and GitHub link at sidebar bottom
- Add help menu with Documentation, Contact, Changelog links
- Add i18n keys for help menu items

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(web): match Settings page to prototype layout

- Remove General tab, directly show Providers panel
- Remove Current Model Selector from Settings page
- Update page header layout to match prototype (flex justify-between, mb-10)
- Simplify page structure

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(web): move BYOK provider action buttons above model list

- Move Save/Remove buttons before model list for better visibility
- User doesn't need to scroll to find action buttons
- Change margin from mt-6 to mb-6 for proper spacing

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(web): fix sidebar toggle button drag issue and alignment

- Add WebkitAppRegion: no-drag to prevent button from being draggable
- Adjust position from top-[6px] to top-[8px] to align with traffic lights
- Adjust left from 80px to 76px for better positioning

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: move skillhub from desktop IPC to controller HTTP (#279)

* fix(desktop): replace JSON skill ledger with SQLite and route ops through IPC

Replace the fragile .curated-state.json ledger with a SQLite database
(better-sqlite3) in the Electron main process. This eliminates race
conditions and state loss when the bundled-skills directory is wiped.

- Add SkillDb module with schema, install/uninstall tracking, bulk ops,
  and automatic migration from legacy .curated-state.json
- Refactor CatalogManager and curated-skills to use SkillDb instead of
  JSON file state
- Add IPC wrappers (skillhub:*) and switch web hooks to IPC in Electron
  with HTTP fallback for cloud
- Remove duplicate curated state ledger code from API sidecar routes
- Add controller skillhub route documentation for desktop vs cloud split
- Exclude sharp/@img and sqlite build artifacts from electron-builder
  asar to reduce package size (~130MB saved)
- Skip catalog sync and curated skill install in CI to avoid ClawHub
  rate-limit failures

* fix(desktop): make SkillDb init resilient and skip skillhub in CI

- Wrap SkillDb construction in try-catch so ABI mismatch between system
  Node.js and dev Electron doesn't crash app startup. CatalogManager
  falls back to no-db mode (skills still work, just no cross-restart
  uninstall persistence).
- Skip catalog sync and curated skill install when CI env var is set
  to avoid ClawHub rate-limit failures on shared runners.
- Add desktop vs cloud architecture documentation to controller
  skillhub routes.

* refactor: move skillhub from desktop IPC to controller HTTP

Move CatalogManager, SkillDb, and curated-skills from the Electron main
process into the controller so the web app always uses HTTP for skill
catalog/install/uninstall operations. This eliminates the webview IPC
bridge for skills and makes the controller self-contained for both
desktop and cloud deployments.

- Move skillhub modules to apps/controller/src/services/skillhub/
- Add SkillhubService wrapper with lifecycle management
- Replace stub skillhub routes with real CatalogManager-backed handlers
- Simplify web hooks to HTTP-only (remove IPC branching)
- Remove all skillhub IPC from desktop (index.ts, ipc.ts, host.ts)
- Pass SKILLHUB_STATIC_SKILLS_DIR and OPENCLAW_CURATED_SKILLS_DIR
  to controller sidecar via manifests.ts
- Remove better-sqlite3, clawhub, npm, @electron/rebuild from desktop
- Use PATH-based npm in controller instead of bundled npm dep
- Delete obsolete legacy skillhub-routes test

* fix(web): replace role=button div with semantic button element

Fixes biome a11y/useSemanticElements lint error on the channel card
in home.tsx. The outer div with role="button" is now a native <button>,
which handles keyboard events and accessibility automatically.

* feat: localize skill catalog ui for chinese

* chore: remove skill translation generator script

* fix: lazy load skill translations for lint

---------

Co-authored-by: lefarcen <935902669@qq.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Marc Chan <mrc@powerformer.com>
alchemistklk added a commit that referenced this pull request Mar 20, 2026
* feat(web): restore design-system visual specs

- Add macOS-style Switch component (3 sizes + loading state)
- Sync CSS design tokens from design-system 2.0
- Rewrite Home page with first-run (Idle) and operational states
- Add Enabled/Providers grouping to Settings provider panel
- Integrate xs Switch for Skills install/uninstall toggle
- Add breathe animation for recommended channel cards
- Add InlineModelSelector component for Hero status bar

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(web): refine sidebar nav and home channels panel

- Update sidebar nav to use nav-item/nav-item-active classes
- Add Conversations nav item to main navigation
- Simplify sidebar session items with proper styling
- Refactor home running state channels panel with Chat button
- Update settings page header with heading-page class

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(web): load Caveat font for nexu alpha script text

Replace Great Vibes with Caveat font to match design-system spec
for the "nexu alpha" heading on home page.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(web): correct sidebar layout to match design prototype

- Remove Conversations from main nav (keep as section label only)
- Remove skill count from Skills nav item
- Add fixed sidebar toggle button next to traffic lights (desktop)
- Use logo image instead of text brand for desktop client
- Adjust spacing for desktop client header area

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(web): match home page running state to prototype

- Update Channels panel: connected channels show horizontal rows with
  icon + name + green dot + "Connected" button + "Chat ↗" link
- Not-connected channels display as dashed-border small cards with Cable icon
- Remove bottom quick action cards (conversations, skills, github star)
- Clean up unused imports (navigate, MessageSquare, Sparkles, GITHUB_SVG)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(web): match home page running state hero to prototype

- Change Hero from vertical-centered to horizontal layout (flex items-center gap-4)
- Use var(--color-success) for Running badge color consistency
- Reduce video size from w-32 to w-28 (matching prototype)
- Place model selector and message stats side-by-side in Hero right area
- Remove standalone CTA button (Chat in Feishu) - channels panel has Chat link
- Clean up unused code (getChannelShortNames, FeishuIconChat, firstChannel vars)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(web): add disconnect channel on Connected button click

- Click Connected button to disconnect channel (calls deleteApiV1ChannelsByChannelId)
- Add hover:text-danger and hover:bg-surface-3 styles matching prototype
- Auto-refresh channels list after disconnect

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(web): match InlineModelSelector trigger to prototype style

- Add border, background, padding (px-2.5 py-1 rounded-lg)
- Change text color from text-muted to text-primary
- Increase font size from 11px to 12px, add font-medium
- Increase icon sizes (14/13/10) and gap (1.5)
- Wrap provider logo in 4x4 centered container

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: restore desktop-managed model catalog (#282)

* fix: restore desktop-managed model catalog

* fix: allow selecting desktop cloud models

* chore: remove API smoke workflows

* fix(web): add brand logo and sidebar icon row per prototype

- Copy logo-black-1.svg to public/brand/
- Add Icon row with Help menu and GitHub link at sidebar bottom
- Add help menu with Documentation, Contact, Changelog links
- Add i18n keys for help menu items

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(web): match Settings page to prototype layout

- Remove General tab, directly show Providers panel
- Remove Current Model Selector from Settings page
- Update page header layout to match prototype (flex justify-between, mb-10)
- Simplify page structure

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(web): move BYOK provider action buttons above model list

- Move Save/Remove buttons before model list for better visibility
- User doesn't need to scroll to find action buttons
- Change margin from mt-6 to mb-6 for proper spacing

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(web): fix sidebar toggle button drag issue and alignment

- Add WebkitAppRegion: no-drag to prevent button from being draggable
- Adjust position from top-[6px] to top-[8px] to align with traffic lights
- Adjust left from 80px to 76px for better positioning

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: move skillhub from desktop IPC to controller HTTP (#279)

* fix(desktop): replace JSON skill ledger with SQLite and route ops through IPC

Replace the fragile .curated-state.json ledger with a SQLite database
(better-sqlite3) in the Electron main process. This eliminates race
conditions and state loss when the bundled-skills directory is wiped.

- Add SkillDb module with schema, install/uninstall tracking, bulk ops,
  and automatic migration from legacy .curated-state.json
- Refactor CatalogManager and curated-skills to use SkillDb instead of
  JSON file state
- Add IPC wrappers (skillhub:*) and switch web hooks to IPC in Electron
  with HTTP fallback for cloud
- Remove duplicate curated state ledger code from API sidecar routes
- Add controller skillhub route documentation for desktop vs cloud split
- Exclude sharp/@img and sqlite build artifacts from electron-builder
  asar to reduce package size (~130MB saved)
- Skip catalog sync and curated skill install in CI to avoid ClawHub
  rate-limit failures

* fix(desktop): make SkillDb init resilient and skip skillhub in CI

- Wrap SkillDb construction in try-catch so ABI mismatch between system
  Node.js and dev Electron doesn't crash app startup. CatalogManager
  falls back to no-db mode (skills still work, just no cross-restart
  uninstall persistence).
- Skip catalog sync and curated skill install when CI env var is set
  to avoid ClawHub rate-limit failures on shared runners.
- Add desktop vs cloud architecture documentation to controller
  skillhub routes.

* refactor: move skillhub from desktop IPC to controller HTTP

Move CatalogManager, SkillDb, and curated-skills from the Electron main
process into the controller so the web app always uses HTTP for skill
catalog/install/uninstall operations. This eliminates the webview IPC
bridge for skills and makes the controller self-contained for both
desktop and cloud deployments.

- Move skillhub modules to apps/controller/src/services/skillhub/
- Add SkillhubService wrapper with lifecycle management
- Replace stub skillhub routes with real CatalogManager-backed handlers
- Simplify web hooks to HTTP-only (remove IPC branching)
- Remove all skillhub IPC from desktop (index.ts, ipc.ts, host.ts)
- Pass SKILLHUB_STATIC_SKILLS_DIR and OPENCLAW_CURATED_SKILLS_DIR
  to controller sidecar via manifests.ts
- Remove better-sqlite3, clawhub, npm, @electron/rebuild from desktop
- Use PATH-based npm in controller instead of bundled npm dep
- Delete obsolete legacy skillhub-routes test

* fix(web): replace role=button div with semantic button element

Fixes biome a11y/useSemanticElements lint error on the channel card
in home.tsx. The outer div with role="button" is now a native <button>,
which handles keyboard events and accessibility automatically.

* feat: localize skill catalog ui for chinese

* chore: remove skill translation generator script

* fix: lazy load skill translations for lint

* fix: keep original skill content in web ui

* fix: translate skill filter all label

---------

Co-authored-by: lefarcen <935902669@qq.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Marc Chan <mrc@powerformer.com>
alchemistklk added a commit that referenced this pull request Mar 20, 2026
…ompatibility (#298)

* feat(web): restore design-system visual specs

- Add macOS-style Switch component (3 sizes + loading state)
- Sync CSS design tokens from design-system 2.0
- Rewrite Home page with first-run (Idle) and operational states
- Add Enabled/Providers grouping to Settings provider panel
- Integrate xs Switch for Skills install/uninstall toggle
- Add breathe animation for recommended channel cards
- Add InlineModelSelector component for Hero status bar

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(web): refine sidebar nav and home channels panel

- Update sidebar nav to use nav-item/nav-item-active classes
- Add Conversations nav item to main navigation
- Simplify sidebar session items with proper styling
- Refactor home running state channels panel with Chat button
- Update settings page header with heading-page class

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(web): load Caveat font for nexu alpha script text

Replace Great Vibes with Caveat font to match design-system spec
for the "nexu alpha" heading on home page.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(web): correct sidebar layout to match design prototype

- Remove Conversations from main nav (keep as section label only)
- Remove skill count from Skills nav item
- Add fixed sidebar toggle button next to traffic lights (desktop)
- Use logo image instead of text brand for desktop client
- Adjust spacing for desktop client header area

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(web): match home page running state to prototype

- Update Channels panel: connected channels show horizontal rows with
  icon + name + green dot + "Connected" button + "Chat ↗" link
- Not-connected channels display as dashed-border small cards with Cable icon
- Remove bottom quick action cards (conversations, skills, github star)
- Clean up unused imports (navigate, MessageSquare, Sparkles, GITHUB_SVG)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(web): match home page running state hero to prototype

- Change Hero from vertical-centered to horizontal layout (flex items-center gap-4)
- Use var(--color-success) for Running badge color consistency
- Reduce video size from w-32 to w-28 (matching prototype)
- Place model selector and message stats side-by-side in Hero right area
- Remove standalone CTA button (Chat in Feishu) - channels panel has Chat link
- Clean up unused code (getChannelShortNames, FeishuIconChat, firstChannel vars)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(web): add disconnect channel on Connected button click

- Click Connected button to disconnect channel (calls deleteApiV1ChannelsByChannelId)
- Add hover:text-danger and hover:bg-surface-3 styles matching prototype
- Auto-refresh channels list after disconnect

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(web): match InlineModelSelector trigger to prototype style

- Add border, background, padding (px-2.5 py-1 rounded-lg)
- Change text color from text-muted to text-primary
- Increase font size from 11px to 12px, add font-medium
- Increase icon sizes (14/13/10) and gap (1.5)
- Wrap provider logo in 4x4 centered container

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: restore desktop-managed model catalog (#282)

* fix: restore desktop-managed model catalog

* fix: allow selecting desktop cloud models

* chore: remove API smoke workflows

* fix(web): add brand logo and sidebar icon row per prototype

- Copy logo-black-1.svg to public/brand/
- Add Icon row with Help menu and GitHub link at sidebar bottom
- Add help menu with Documentation, Contact, Changelog links
- Add i18n keys for help menu items

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(web): match Settings page to prototype layout

- Remove General tab, directly show Providers panel
- Remove Current Model Selector from Settings page
- Update page header layout to match prototype (flex justify-between, mb-10)
- Simplify page structure

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(web): move BYOK provider action buttons above model list

- Move Save/Remove buttons before model list for better visibility
- User doesn't need to scroll to find action buttons
- Change margin from mt-6 to mb-6 for proper spacing

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(web): fix sidebar toggle button drag issue and alignment

- Add WebkitAppRegion: no-drag to prevent button from being draggable
- Adjust position from top-[6px] to top-[8px] to align with traffic lights
- Adjust left from 80px to 76px for better positioning

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: move skillhub from desktop IPC to controller HTTP (#279)

* fix(desktop): replace JSON skill ledger with SQLite and route ops through IPC

Replace the fragile .curated-state.json ledger with a SQLite database
(better-sqlite3) in the Electron main process. This eliminates race
conditions and state loss when the bundled-skills directory is wiped.

- Add SkillDb module with schema, install/uninstall tracking, bulk ops,
  and automatic migration from legacy .curated-state.json
- Refactor CatalogManager and curated-skills to use SkillDb instead of
  JSON file state
- Add IPC wrappers (skillhub:*) and switch web hooks to IPC in Electron
  with HTTP fallback for cloud
- Remove duplicate curated state ledger code from API sidecar routes
- Add controller skillhub route documentation for desktop vs cloud split
- Exclude sharp/@img and sqlite build artifacts from electron-builder
  asar to reduce package size (~130MB saved)
- Skip catalog sync and curated skill install in CI to avoid ClawHub
  rate-limit failures

* fix(desktop): make SkillDb init resilient and skip skillhub in CI

- Wrap SkillDb construction in try-catch so ABI mismatch between system
  Node.js and dev Electron doesn't crash app startup. CatalogManager
  falls back to no-db mode (skills still work, just no cross-restart
  uninstall persistence).
- Skip catalog sync and curated skill install when CI env var is set
  to avoid ClawHub rate-limit failures on shared runners.
- Add desktop vs cloud architecture documentation to controller
  skillhub routes.

* refactor: move skillhub from desktop IPC to controller HTTP

Move CatalogManager, SkillDb, and curated-skills from the Electron main
process into the controller so the web app always uses HTTP for skill
catalog/install/uninstall operations. This eliminates the webview IPC
bridge for skills and makes the controller self-contained for both
desktop and cloud deployments.

- Move skillhub modules to apps/controller/src/services/skillhub/
- Add SkillhubService wrapper with lifecycle management
- Replace stub skillhub routes with real CatalogManager-backed handlers
- Simplify web hooks to HTTP-only (remove IPC branching)
- Remove all skillhub IPC from desktop (index.ts, ipc.ts, host.ts)
- Pass SKILLHUB_STATIC_SKILLS_DIR and OPENCLAW_CURATED_SKILLS_DIR
  to controller sidecar via manifests.ts
- Remove better-sqlite3, clawhub, npm, @electron/rebuild from desktop
- Use PATH-based npm in controller instead of bundled npm dep
- Delete obsolete legacy skillhub-routes test

* fix(web): replace role=button div with semantic button element

Fixes biome a11y/useSemanticElements lint error on the channel card
in home.tsx. The outer div with role="button" is now a native <button>,
which handles keyboard events and accessibility automatically.

* docs: add controller sidecar packaging and native addon rules

- Add hard rules to AGENTS.md for controller dep size and native addon
  placement (controller, not Electron main process)
- Add controller sidecar packaging section to desktop-runtime-guide.md
  with size check workflow and native module guidance
- Update "Where to look" table: skill catalog path now points to
  apps/controller/src/services/skillhub/
- Add SkillHub HTTP architecture note to desktop local dev section

* fix(controller): replace better-sqlite3 with sql.js for desktop ABI compatibility

better-sqlite3 is a native addon that fails in the packaged desktop app
due to ABI mismatch (CI compiles for system Node ABI 127, but the
controller sidecar runs under Electron's Node ABI 136). This caused
SkillDb to silently become undefined, skipping curated skill installation
entirely.

Replace with sql.js (SQLite compiled to WASM) — no native code, no ABI
issues. Key changes:

- SkillDb: sync constructor → async factory (SkillDb.create())
- Manual persistence via db.export() + atomic file write
- SkillDb is now required (not optional) in CatalogManager
- getCatalog() driven by DB records instead of file scanning
- Boot-time reconciliation syncs DB ↔ disk state
- On-disk skills recorded eagerly during installCuratedSkills()
- Fix nano-banana-one-shop display name in SKILL.md frontmatter

* fix(controller): handle cold-start catalog requests and safe dispose

- getCatalog() returns cached JSON fallback when init is in-flight
- Mutating routes (install/uninstall/refresh) await init completion
- initVersion counter prevents stale init from running after dispose
- Routes call SkillhubService methods directly instead of .catalog

* fix(ci): ignore transient files in desktop log capture

The captureLogs step copies the electron logs directory recursively.
Temp files like desktop-diagnostics.json.tmp can vanish between the
directory existence check and the recursive cp, causing ENOENT. Catch
and ignore ENOENT during copy so transient files don't fail the CI run.

---------

Co-authored-by: lefarcen <935902669@qq.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Marc Chan <mrc@powerformer.com>
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.

2 participants