Commit Graph

3332 Commits

Author SHA1 Message Date
Lemon f6677d1e5d Simplify SpellContent: plain text name, unified outline badges, friendly tag filter labels 2026-04-14 11:27:07 -07:00
Lemon 3e01e7f53d Show friendly kind labels in spell badges (e.g. 'Posts (1)' instead of 'kind:1') 2026-04-14 11:27:07 -07:00
Lemon 3fa00abaa0 Clicking a spell card runs the spell; 'View post details' in More menu goes to post detail 2026-04-14 11:27:07 -07:00
Lemon 8c2d95f9db Rename Search to Discover with compass icon; make Feeds the default tab; route /search to /discover 2026-04-14 11:27:07 -07:00
Lemon d6dc3546eb Rename sidebar Search to Discover with compass icon 2026-04-14 11:27:07 -07:00
Lemon bcc72c9159 Move spells to Feeds tab on Search page; route kind:777 nevent through NIP19Page 2026-04-14 11:27:07 -07:00
Lemon a6b241aecc Replace sidebar star with home feed tab toggle on SpellRunPage 2026-04-14 11:27:07 -07:00
Lemon 15557ef523 Add spell sharing: 'Share' option in search save popover and share button on SpellRunPage 2026-04-14 11:27:07 -07:00
Lemon 576473f1c2 Let $contacts resolve to empty array instead of throwing when user has no follows 2026-04-14 11:27:07 -07:00
Lemon 05a4ce6d68 Extract buildUnsignedSpell helper to deduplicate inline spell construction 2026-04-14 11:27:07 -07:00
Lemon cb6614b42e Cleanup: remove dead code, fix stale comment, clarify Ditto relay routing 2026-04-14 11:27:07 -07:00
Lemon d395ca2079 Fix profile tab $me regression: use literal owner pubkey for 'Me' scope
The spell engine's $me resolves to the logged-in viewer, but profile tabs
need 'Me' scope to mean the profile owner. Fixed by emitting the owner's
literal hex pubkey instead of $me in ProfileTabEditModal.

Also noted the $contacts behavioral change: profile tab 'Contacts' scope
now shows the viewer's contacts (not the owner's). This is intentional --
the old behavior fetched the owner's kind 3 event, but the spell engine
resolves $contacts from the viewer's follow list.
2026-04-14 11:27:07 -07:00
Lemon 0fbf59b436 Cleanup: remove dead code from SavedFeedFiltersEditor and useProfileFeed
- SavedFeedFiltersEditor: removed the main SavedFeedFiltersEditor component
  (unused after modals were rewritten), parseSelectedKinds, kindsToKindFilter,
  getAuthorScope, and the local TabFilter type. Removed unused imports (Globe,
  UserSearch, Input, Separator, useUserLists, useFollowPacks). The file now
  only exports the reusable sub-components (buildKindOptions, KindPicker,
  MultiKindPicker, ScopeToggle, ListPackPicker, AuthorChip, AuthorFilterDropdown).
- useProfileFeed: removed useTabFeed (120 lines) and TabFeedPage type. Profile
  tabs now use useStreamPosts with spell events.
- Removed unused NostrFilter import from useProfileFeed.
2026-04-14 11:27:07 -07:00
Lemon 32539c0aee Migrate profile tabs to spell events; delete useResolveTabFilter
Profile tabs (kind 16769) now store spell events instead of TabFilter objects.
Each tab tag contains a JSON-encoded kind:777 spell with all filter parameters,
runtime variables ($me, $contacts), and client hints in its tags. The old var
tag system is eliminated entirely.

Key changes:
- profileTabsEvent.ts: ProfileTab now has { label, spell } instead of
  { label, filter }. ProfileTabsData no longer has vars. Deleted TabFilter,
  TabVarDef, resolvePointer, resolveFilter (~100 lines removed).
- ProfilePage.tsx: ProfileSavedFeedContent uses useStreamPosts with spell
  instead of useResolveTabFilter + useTabFeed. Core tab spells built via
  buildSpellTags. Removed profileVars, useResolveTabFilter, useTabFeed imports.
- ProfileTabEditModal.tsx: Produces spell events. Parses spell tags to seed form.
  Uses $me for 'me' scope, $contacts for 'contacts' scope.
- SearchPage.tsx: handleSaveProfileTab builds spell events instead of TabFilter.
- Deleted useResolveTabFilter.ts (93 lines) — no longer needed anywhere.
- NIP.md: Updated kind 16769 documentation for spell-based tab format.
2026-04-14 11:27:07 -07:00
Lemon a64575a13c Change SavedFeed to store spell events; update all producers and consumers
SavedFeed now stores a kind:777 spell event instead of TabFilter + TabVarDef.
Old saved feeds in encrypted settings silently drop (Zod schema rejects them).

Key changes:
- AppContext: SavedFeed type changed to { id, label, spell: NostrEvent, createdAt }
  Removed TabFilter and TabVarDef types (kept in profileTabsEvent.ts for profile tabs)
- schemas.ts: SavedFeedSchema validates a NostrEvent in the spell field
- useSavedFeeds: addSavedFeed takes (label, spell) instead of (label, filter, vars)
- Feed.tsx SavedFeedContent: passes feed.spell to useStreamPosts, removed
  useResolveTabFilter usage and all manual option extraction (~40 lines deleted)
- SearchPage handleSaveFeed: builds spell tags via buildSpellTags(), creates an
  unsigned spell event, stores it. Profile tab save path kept as compat shim.
- FeedEditModal: produces spell events from UI state instead of TabFilter objects.
  Parses spell tags to seed the form in edit mode.
- ContentSettings: adapted handlers to new (label, spell) signature
- SavedFeedFiltersEditor: TabFilter defined locally (no longer in AppContext)
2026-04-14 11:27:07 -07:00
Lemon 9d9425c0b9 Add spell support to useStreamPosts; migrate SpellRunPage to use it
useStreamPosts now accepts an optional 'spell' (kind:777 NostrEvent) in its
options. When provided, the spell is resolved internally — variables ($me,
$contacts), relative timestamps, client hints (media, language, sort, etc.)
— and drives the entire stream. All other option fields are ignored in spell
mode.

Key changes to useStreamPosts:
- Resolves spell via resolveSpell() using useCurrentUser + useFollowList
- Derives effectiveOptions/effectiveQuery from spell hints
- Routes initial query to Ditto relays when needsDittoRelay is true
- Merges spell extra filter fields (since, until, tag filters) into queries
- Existing callers unchanged (spell option is optional)

SpellRunPage now uses useStreamPosts with the spell option instead of manual
useQuery + nostr.query, gaining live streaming and the new-posts pill for free.
2026-04-14 11:27:07 -07:00
Lemon 133b9a7227 Extend spell engine with NIP-50 client-hint tags (media, language, platform, sort, include-replies)
- Add client-hint tags to spell format: media, language, platform, sort,
  include-replies. These instruct clients how to build NIP-50 search
  extensions and apply client-side filters.
- Add SpellClientHints interface and needsDittoRelay flag to ResolvedSpell
  for downstream consumers to know when Ditto relay routing is required.
- Move buildSpellTags() from useAIChatTools into spellEngine.ts as the
  single source of truth for spell tag construction.
- Update AI tool schema and system prompt with new parameters and examples.
- Update SpellContent badge display for new tags.
- Document kind 777 in NIP.md.
2026-04-14 11:27:07 -07:00
Lemon 9c5807f49d Fix saved feed 'follows' filter not working: omit #d filter for non-addressable kinds
The $follows variable resolver was querying kind 3 (contact list) with a
'#d' filter, but kind 3 is a replaceable event that has no d tag. This
caused the query to return zero results, so the follows list was never
resolved and the author filter was silently dropped.

Only include '#d' in the query filter for addressable events (30000-39999).
Also fix pre-existing lint error (unused useMemo import) and missing
aiModel field in TestApp.
2026-04-14 11:27:07 -07:00
Lemon e27d928e38 Fix follows filter not saved: add $follows placeholder to authors in TabFilter 2026-04-14 11:26:41 -07:00
Lemon 7dfad82a9b Persist NIP-50 filter extensions (media, language, sort, protocol) in saved feeds and fix sort bug 2026-04-14 11:26:41 -07:00
Lemon 472c8e943f Add opaque background to inline NoteCard in Dork chat 2026-04-14 11:26:41 -07:00
Lemon b615e9d395 Make Dork sheet background transparent to match search sheet overlay style 2026-04-14 11:26:41 -07:00
Lemon 9a5944fff8 Animate Dork toggle button during streaming instead of spinner 2026-04-14 11:26:41 -07:00
Lemon a8a9cbcaf1 Add opaque background to Dork messages area 2026-04-14 11:26:41 -07:00
Lemon d4e518bcbe Add slash commands: /new and /clear to reset chat history 2026-04-14 11:26:41 -07:00
Lemon b55c37f510 Raise bottom nav z-index to match Dork sheet 2026-04-14 11:26:41 -07:00
Lemon 94f034c1f0 Fix Dork sheet scroll: contain scroll events, add bottom padding to clear input bar 2026-04-14 11:26:41 -07:00
Lemon 1daa9a2715 Refine mobile Dork sheet: bidirectional toggle, keyboard-only send/stop, full-screen transparent layout 2026-04-14 11:26:41 -07:00
Lemon 95eb55133f Add Dork chat to mobile search sheet with toggle
- Extract MessageBubble, DorkThinking, ToolCallBadge to shared AIChat components
- Add MobileDorkSheet with chat messages, send/stop, and search toggle
- Add Dork toggle (<[o_o]>) to MobileSearchSheet input bar
- MobileBottomNav manages shared backdrop and both sheets via hidden prop
- Both sheets stay mounted to preserve state when toggling
2026-04-14 11:26:41 -07:00
Lemon 4d4381310c Match Dork settings section style to System/Wallet sections 2026-04-14 11:26:08 -07:00
Lemon 4d2ae05c4b Reduce empty state padding to avoid premature scrollbar 2026-04-14 11:26:08 -07:00
Lemon 4ff019e9cf Move AI model selector from Dork chat to Settings > Advanced 2026-04-14 11:26:08 -07:00
Lemon 7cb244e8a9 Tighten spacing in Dork empty state 2026-04-14 11:25:30 -07:00
Lemon 5152ead795 Sort and deduplicate spell results 2026-04-14 11:25:30 -07:00
Lemon 31c4dd3f78 Add suggestion buttons to empty Dork chat state 2026-04-14 11:25:29 -07:00
Lemon 7b214ea5b2 Hide empty assistant message bubble on tool-only turns 2026-04-14 11:25:29 -07:00
Lemon 47044752b9 Fix follow pack search: use broad fetch with multiple filters instead of relying on NIP-50 tag indexing 2026-04-14 11:25:29 -07:00
Lemon f35b4e7bd2 Add search_follow_packs tool to Dork AI for pack-based spell creation 2026-04-14 11:25:29 -07:00
Lemon 8bc0393b51 Remove 'Dork AI' heading from empty chat state 2026-04-14 11:25:29 -07:00
Lemon 8164ccafa5 Rename AI Chat to Dork in all user-facing labels 2026-04-14 11:25:29 -07:00
Lemon e54b9908fa Move AI Chat controls into PageHeader as children 2026-04-14 11:25:29 -07:00
Lemon 98560717d6 Make PageHeader transparent to match note card opacity 2026-04-14 11:25:29 -07:00
Lemon b8124d5069 Add stop button during AI streaming, fix prose link color with inline style 2026-04-14 11:25:29 -07:00
Lemon 52b3755727 Fix prose link color using CSS variable override for theme compatibility 2026-04-14 11:25:29 -07:00
Lemon 31baa83fa3 Add overflow-hidden to AI chat main element 2026-04-14 11:25:29 -07:00
Lemon 41016780c2 Extract AI Chat into focused modules, fix page scroll layout
- Extract tool definitions and message types to src/lib/aiChatTools.ts
- Extract system prompt to src/lib/aiChatSystemPrompt.ts
- Extract tool executor hook to src/hooks/useAIChatTools.ts
- Extract session logic to src/hooks/useAIChatSession.ts
- Page reduced from 1086 to 321 lines (render + sub-components only)
- Fix layout: remove overflow-hidden and nested scroll, align with main branch
2026-04-14 11:25:29 -07:00
Lemon 01209dbce4 Use proper OpenAI tool protocol instead of fake user messages for tool results 2026-04-14 11:24:17 -07:00
Lemon f734d682fc Restore ai-chat-height class for proper viewport containment
The main element was using h-full min-h-0 which doesn't work because
the parent wrapper div has no fixed height. Restore the original
ai-chat-height class which uses calc(100dvh - ...) for an absolute
height constraint. Keep overflow-hidden to prevent outer page scroll.
2026-04-14 11:23:48 -07:00
Lemon 1512630878 Tighten AI chat viewport layout 2026-04-14 11:23:48 -07:00
Lemon bffa8c58b4 Move credits badge to model selector row, fix page overflow
CreditsBadge now sits left of the model dropdown in the controls row
instead of in the PageHeader, so it stays on the same line on small
screens. Added overflow-hidden to the main container so only the
ScrollArea chat pane scrolls, eliminating the extra space below the
input that the user could scroll to reveal.
2026-04-14 11:23:48 -07:00