Skip to content

feat(desktop): persona & team improvements — channel indicators, async imports, team export/import#156

Open
wesbillman wants to merge 8 commits intomainfrom
feat/personas-improvements
Open

feat(desktop): persona & team improvements — channel indicators, async imports, team export/import#156
wesbillman wants to merge 8 commits intomainfrom
feat/personas-improvements

Conversation

@wesbillman
Copy link
Collaborator

Summary

Three improvements to the agents/personas experience in the desktop app:

Feature 1: "Already in channel" indicators

  • AddAgentToChannelDialog shows "✓ Already a member" badge when the agent is already in the selected channel, with "Re-add to channel" button text
  • AddChannelBotDialog shows "In channel" badges on persona chips and team cards
  • New useInChannelPersonaIds hook — properly gated, only fires when dialog is open
  • Bonus: consolidated 4 duplicate normalizePubkey functions into shared/lib/pubkey.ts

Feature 2: Async import flow with loaders

  • PersonaDialog — spinner overlay during file parsing, submit disabled while parsing
  • BatchImportDialog — per-item status indicators (⏳ spinner / ✓ done / ✗ error)
  • No more UI freezing during imports

Feature 3: Team import/export

  • Rust backend: export_team_to_json + parse_team_file Tauri commands with 10 unit tests
  • Rust refactor: extracted slugify() + save_json_with_dialog() shared utils with 5 unit tests
  • TS API: exportTeamToJson + parseTeamFile in tauriTeams.ts
  • UI: Export button in team dropdown, Import button with file picker in TeamsSection header
  • TeamImportDialog: full preview → import flow with per-persona progress indicators
  • Auto-retry team creation on failure, clear error messaging for orphan recovery

Code quality

  • Extracted shared promptPreview function (was duplicated in 3 files)
  • Extracted shared ImportStatusIcon component (was duplicated in 2 files)
  • All pre-commit hooks pass (biome, file size limits, cargo fmt, TypeScript)
  • 15 new Rust unit tests

Test Plan

  • Rust: cargo test -p sprout -- team and cargo test -p sprout -- slugify (15 new tests)
  • TypeScript: pnpm typecheck clean
  • Biome: pnpm check clean
  • Manual: tested team export → import round-trip, persona batch import with loaders, "already in channel" indicators in both dialogs

…rt backend

Feature 1: Add agent-already-in-channel indicators
- AddAgentToChannelDialog: fetch channel members, show 'Already a member' badge,
  contextual 'Re-add to channel' button text
- AddChannelBotDialog: use new useInChannelPersonaIds hook to compute in-channel
  persona IDs, pass to PersonasSection and TeamsSection
- AddChannelBotPersonasSection: show 'In channel' badge on persona chips
- AddChannelBotTeamsSection: show per-team in-channel count and per-persona
  check marks in tooltip
- New useInChannelPersonaIds hook extracts shared logic

Refactor: extract shared normalizePubkey utility
- New shared/lib/pubkey.ts with canonical normalizePubkey function
- Deduplicate from channelAgents.ts, ChannelMembersBar.tsx, presence/hooks.ts,
  profile/lib/identity.ts, shared/lib/authors.ts

Feature 3 (backend): team export/import Tauri commands
- managed_agents/teams.rs: add encode_team_json, parse_team_json, types
  (TeamPersonaPreview, ParsedTeamPreview) with 10 unit tests
- commands/teams.rs: add export_team_to_json (async, save dialog) and
  parse_team_file commands
- Register new commands in lib.rs
Feature 2: Async import flow with loaders
- PersonaDialog: parsing overlay with spinner, submit disabled during parse
- BatchImportDialog: per-item status indicators (spinner/✓/✗) during import

Feature 3 Frontend: Team export/import UI
- TeamsSection: Export menu item + Import button with file picker
- TeamImportDialog: full import dialog with per-persona progress tracking
- tauriTeams.ts: exportTeamToJson + parseTeamFile API functions
- useTeamActions: export/import/complete handlers extracted from AgentsView

Rust refactors:
- Extracted slugify() into shared util with 5 unit tests
- Extracted save_json_with_dialog() into commands/export_util.rs
- Deduplicated ~60 lines across persona and team export commands

Fixes from review:
- TeamImportDialog: disable Import button on error (prevents duplicate personas)
- TeamImportDialog: use stable index-based React keys
- Team creation auto-retries once on failure with clear error message
Deduplicate promptPreview() from PersonasSection, TeamImportDialog, and
AddChannelBotPersonasSection into shared/lib/promptPreview.ts.

Extract the Loader2/Check/X status icon pattern from BatchImportDialog
and TeamImportDialog into shared/ui/import-status-icon.tsx with a
reusable ImportStatusIcon component and ImportItemStatus type.
The dialog content could overflow its container when importing teams with
many personas, pushing the footer buttons (Cancel / Import) below the
visible area and making them unclickable.

Fixes:
- Add min-h-0 to flex container for proper CSS flex shrinking
- Add shrink-0 to header and footer to prevent compression
- Reduce max-h from 85vh to 80vh for more breathing room
- Add min-h-0 to scrollable content area for flex overflow
@wesbillman wesbillman force-pushed the feat/personas-improvements branch from f0871ed to c9d5ac9 Compare March 22, 2026 16:31
Mirror the TeamsSection import pattern on PersonasSection:
- Drag/drop overlay for .persona.json, .persona.png, or .zip files
- Upload button (file picker) next to the Create button
- Drop zone hint text in subtitle and empty state
- handlePersonaImportFile in AgentsView routes single files to
  PersonaDialog and multi-file archives to BatchImportDialog

Bump AgentsView.tsx file size limit from 740 to 790 to accommodate
the new import handler wiring.
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